Compare commits

6 Commits

Author SHA1 Message Date
Archie Halliwell
a31c3bbcc6 fix order so it is the same as in master 2025-04-14 21:35:09 +09:00
Archie Halliwell
9a46141a82 fix TypeError 2025-04-14 21:35:09 +09:00
Archie Halliwell
561041a71c fix freetype dependencies 2025-04-14 21:35:09 +09:00
Archie Halliwell
43de8436d6 fix issue #19 2025-04-14 21:35:09 +09:00
Hector Martin
1536182957 Alameda fixes 2021-03-22 11:49:55 +09:00
Hector Martin
cad274a7fb WIP: Quick and dirty python3 port 2021-03-22 11:14:07 +09:00
41 changed files with 2424 additions and 2468 deletions

View File

@@ -1,85 +1,3 @@
# ARCHIVED
This repository is archived and will not accept any further contributions.
Like most Wii homebrew software, this software depends on [libogc](https://github.com/devkitPro/libogc).
After development of The Homebrew Channel had already started, we discovered that large portions of libogc
were stolen directly from the Nintendo SDK or games using the Nintendo SDK (decompiled and cleaned up).
We thought that at least significant parts of libogc, such as its threading implementation, were original,
and reluctantly continued to use the project while distancing ourselves from it.
It has recently been revealed that the threading/OS implementation in libogc is, in fact,
[stolen from RTEMS](https://github.com/derek57/libogc). The authors of libogc didn't just steal proprietary
Nintendo code, but also saw it fit to steal an *open source* RTOS and remove all attribution and copyright
information. This goes far beyond ignorance about the copyright implications of reverse engineering Nintendo
binaries, and goes straight into outright deliberate, malicious code theft and copyright infringement.
The current developers of libogc are [not interested](https://github.com/devkitPro/libogc/issues/201) in
tracking this issue, finding a solution, nor informing the community of the problematic copyright status of
the project. When we filed an issue about it, they immediately closed it, replied with verbal abuse, and then
completely deleted it from public view.
For this reason, we consider it impossible to legally and legitimately compile this software at this point,
and cannot encourage any further development.
The Wii homebrew community was all built on top of a pile of lies and copyright infringement, and it's all
thanks to shagkur (who did the stealing) and the rest of the team (who enabled it and did nothing when it was
discovered). Together, the developers deceived everyone into believing their work was original.
Please demand that the leaders and major contributors to console or other proprietary device SDKs and
toolkits that you use and work with do things legally, and do not tolerate this kind of behavior.
If you wish to check for yourself, for example, you can compare
[this](https://github.com/devkitPro/libogc/blob/52c525a13fd1762c10395c78875e3260f94368b5/libogc/lwp_threads.c#L580)
function in libogc to
[this](https://github.com/atgreen/RTEMS/blob/2f200c7e642c214accb7cc6bd7f0f1784deec833/c/src/exec/score/src/thread.c#L385)
function in a really old version of RTEMS. While the code has been simplified and many identifiers renamed, it
is clear that the libogc version is a direct descendant of the RTEMS version. It is not possible for two code
implementations to end up this similar purely by chance.
**Update**: The libogc developers have restored the issue and are now claiming that the code
[was not stolen](https://mardy.it/blog/2025/04/no-libogc-did-not-steal-rtems-code.html). What they are in fact
arguing is that the code was not copied verbatim and then changed to obfuscate its origin, but rather that it was
developed by "referencing" RTEMS. Indeed, the original commits of the code to libogc are a less complete copy
of RTEMS than the current version. What that means is that, instead of literally duplicating RTEMS and then
reducing it, they instead *piecewise* incorporated RTEMS code by re-typing or copyediting it line by line,
over time. This is equivalent to opening up a copy of The Lord of the Rings, pulling up a blank document, and
meticulously re-typing the whole story in different words, with different names for the characters, while
preserving the entirety of the plot. Unfortunately for shagkur and the other libogc authors, this is still
plagiarism and copyright infringement. It doesn't matter that they didn't literally Ctrl-C and Ctrl-V the
entirety of RTEMS. The end result is, very clearly, still plagiarized.
Feel free to check out another example:
[this RTEMS function](https://github.com/atgreen/RTEMS/blob/2f200c7e642c214accb7cc6bd7f0f1784deec833/c/src/exec/score/src/thread.c#L1141)
is 1:1 identical to
[this libogc function](https://github.com/devkitPro/libogc/blob/52c525a13fd1762c10395c78875e3260f94368b5/libogc/lwp_threads.c#L388),
other than slightly renamed identifiers, different code formatting, and the `prependit` parameter in the
libogc version and `if` branch (which does seem to be a novel addition). It would be clear in any court of
law that this constitutes copyright infringement, regardless of whether it was achieved in one shot or
incrementally over time. It is simply not possible for this kind of non-trivial code to wind up completely
identical like this, purely on accident. This kind of conduct is, in fact, the same conduct that led libogc
to contain large parts of decompiled Nintendo SDK code verbatim. We just thought that that was a result of a
lack of understanding (or caring) of how copyright works when it related to reverse engineering proprietary
binary code, but it seems shagkur believes that he is entitled to manually copy and re-type *any* code, even
open source code, and the mere action of doing so erases its original copyright.
WinterMute is also is not innocent, and not just by virtue of being complicit with shagkur and enabling his
plagiarism behavior. He, himself, was previously
[caught](https://github.com/devkitPro/libnds/commit/426a369220dcb43320e203f9087de74e43452d84#diff-f376c160388ca187fe35e962eb047fe606338869b515128a6257d3a7a6694ff0R17-R25)
referencing the official Nintendo DS ("nitro") SDK while writing code for libnds\*. WinterMute has a huge
siege mentality issue when it comes to DevkitPro, which is why nobody has been able to get through to him,
as any criticism of his work or the way he manages his project has always been met with extreme hostility.
This is why nothing has ever been done about these issues with the project, even after all these years.
\* Edited to note: This should not be taken to imply that any or all of libnds itself is tainted with SDK
code. The commit in question itself only adds fairly standard cache maintenance functions, and is not itself
evidence that there was substantial copying. It just reflects poorly on WinterMute that he was referencing
the leaked SDK, especially for something as trivial as this. For a more thorough take on the general
mismanagement of the devkitPro project as a whole, please read
[this](https://heyquark.com/brew/2020/07/13/leaving-devkitpro/) blog post. The stories told there track
very closely with our experience with that team way back in the Wii days, and it seems nothing has changed
nor improved after all these years.
# The Homebrew Channel
This repository contains the public release of the source code for

View File

@@ -14,14 +14,14 @@ export ALAMEDA := $(CURDIR)/../../pywii/Alameda
export PNG2TPL := $(CURDIR)/tools/png2tpl$(EXE)
export MKBNS := $(CURDIR)/tools/mkbns$(EXE)
export LZ77 := $(CURDIR)/tools/lz77$(EXE)
export ADDIMD5 := python2 $(CURDIR)/tools/addimd5.py
export ARCPACK := python2 $(PYWII)/arcpack.py
export ADDIMD5 := python3 $(CURDIR)/tools/addimd5.py
export ARCPACK := python3 $(PYWII)/arcpack.py
export SOX := sox
all: channel.imet
channel.imet: build/data.arc names.txt tools/join-imet.py
python2 tools/join-imet.py $@ build/data.arc build/icon.arc build/banner.arc build/sound.bns names.txt
python3 tools/join-imet.py $@ build/data.arc build/icon.arc build/banner.arc build/sound.bns names.txt
build/data.arc : build/data/meta/icon.bin build/data/meta/banner.bin build/data/meta/sound.bin
$(ARCPACK) $@ build/data
@@ -45,9 +45,9 @@ build/%.raw : sound/%.wav
$(SOX) $< -r 32000 -c 2 -e signed-integer -b 16 -t raw $@
testi : channel.imet
python2 $(ALAMEDA)/Alameda.py channel.imet icon
python3 $(ALAMEDA)/Alameda.py channel.imet icon
testb : channel.imet
python2 $(ALAMEDA)/Alameda.py channel.imet banner
python3 $(ALAMEDA)/Alameda.py channel.imet banner
$(PNG2TPL): tools/*.c
$(MAKE) -C tools png2tpl$(EXE)

View File

@@ -19,7 +19,7 @@ endif
../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS) : mk$(TYPE).py
@[ ! -d ../build/$(TYPE)/arc/anim ] && mkdir -p ../build/$(TYPE)/arc/anim || true
@[ ! -d ../build/$(TYPE)/arc/blyt ] && mkdir -p ../build/$(TYPE)/arc/blyt || true
python2 mk$(TYPE).py ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS)
python3 mk$(TYPE).py ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS)
../build/$(TYPE).arc : $(TPLS) ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS)
$(ARCPACK) ../build/$(TYPE).arc ../build/$(TYPE)

View File

@@ -244,7 +244,7 @@ class BubbleInstance:
for i in tps:
if len(i.Triplets) > 0:
if i.Triplets[-1][0] >= self.Start:
print "WTF at %s: %f >= %f"%(self.Picture.Name,i.Triplets[-1][0],self.Start)
print("WTF at %s: %f >= %f"%(self.Picture.Name,i.Triplets[-1][0],self.Start))
raise RuntimeError("We Have A Problem")
brlan.Anim[self.Picture.Name][Brlan.A_COORD][Brlan.C_X].Triplets.append((self.Start, self.X, 0))
@@ -293,15 +293,15 @@ class BubbleCollection:
#print "Freeing instance: [%f-%f]"%(user.Start,user.End)
tis[i] = pic, None
def printinstances(self):
print "Type Instances:"
print("Type Instances:")
for tid, tis in enumerate(self.TypeInstances):
print " Type Instances for type %d (%s):"%(tid, self.BubbleTypes[tid][0].Name)
print(" Type Instances for type %d (%s):"%(tid, self.BubbleTypes[tid][0].Name))
for i, ti in enumerate(tis):
pic, user = ti
if user is None:
print " %d: Picture %s, free"%(i,pic.Name)
print(" %d: Picture %s, free"%(i,pic.Name))
else:
print " %d: Picture %s, user: %s [%f-%f]"%(i,pic.Name,repr(user),user.Start,user.End)
print(" %d: Picture %s, user: %s [%f-%f]"%(i,pic.Name,repr(user),user.Start,user.End))
def render(self):
for t,c in self.BubbleTypes:
t.makemat(self.Brlyt)
@@ -330,9 +330,9 @@ class BubbleCollection:
i.render(self.Brlan)
#self.printinstances()
print "Fake Start",fakeStart
print "Loop Start",loopStart
print "Loop End",loopEnd
print("Fake Start",fakeStart)
print("Loop Start",loopStart)
print("Loop End",loopEnd)
col = BubbleCollection(brlyt, brlan, bubblepane)
col.addtype(BubbleType("abubble1", 48, 48),1)
@@ -374,10 +374,10 @@ for i in col.Instances:
col.render()
brldata = brlyt.Pack()
open(sys.argv[1],"w").write(brldata)
open(sys.argv[1],"wb").write(brldata)
bradata = brlan.Pack(loopStart)
open(sys.argv[2],"w").write(bradata)
open(sys.argv[2],"wb").write(bradata)
bradata = brlan.Pack(loopStart, loopEnd)
open(sys.argv[3],"w").write(bradata)
open(sys.argv[3],"wb").write(bradata)

View File

@@ -111,7 +111,7 @@ brlyt.RootPane.Add(tit)
brldata = brlyt.Pack()
open(sys.argv[1],"w").write(brldata)
open(sys.argv[1],"wb").write(brldata)
brlan = Brlan()
@@ -177,6 +177,6 @@ brlan.Anim['shadow'][Brlan.A_COORD][Brlan.C_X].repsimple(0, 960, 2, -45, -0.1, 4
bradata = brlan.Pack(60*16)
for a,b,c in brlan.Anim['waveb'][Brlan.A_COORD][Brlan.C_X].Triplets:
print a,b,c
print(a,b,c)
open(sys.argv[2],"w").write(bradata)
open(sys.argv[2],"wb").write(bradata)

View File

@@ -1,12 +1,12 @@
import md5, sys, struct
import hashlib, sys, struct
data= open(sys.argv[1]).read()
data= open(sys.argv[1], "rb").read()
digest = md5.new(data).digest()
digest = hashlib.md5(data).digest()
hdr = struct.pack(">4sI8x","IMD5",len(data))
hdr = struct.pack(">4sI8x",b"IMD5",len(data))
f2 = open(sys.argv[2],"w")
f2 = open(sys.argv[2],"wb")
f2.write(hdr)
f2.write(digest)
f2.write(data)

View File

@@ -1,8 +1,8 @@
import os, sys, struct, md5
import os, sys, struct, hashlib
output, datafile, iconarc, bannerarc, soundbns, namesfile = sys.argv[1:]
data = open(datafile,"r").read()
data = open(datafile,"rb").read()
names={}
@@ -11,7 +11,7 @@ for i in open(namesfile,"r"):
while b[-1] == "\n":
b = b[:-1]
b = b.replace("\\n","\n")
names[a] = b.decode("utf-8")
names[a] = b
def getsize(x):
return os.stat(x).st_size
@@ -20,29 +20,29 @@ def pad(x,l):
if len(x) > l:
raise ValueError("%d > %d",len(x),l)
n = l-len(x)
return x + "\x00"*n
return x + b"\x00"*n
imet = "\x00"*0x40
imet += struct.pack(">4sIIIIII","IMET",0x600,3,getsize(iconarc),getsize(bannerarc),getsize(soundbns),1)
imet = b"\x00"*0x40
imet += struct.pack(">4sIIIIII",b"IMET",0x600,3,getsize(iconarc),getsize(bannerarc),getsize(soundbns),1)
for i in ["jp", "en", "de", "fr", "sp", "it", "nl", "cn", None, "ko"]:
try:
imet += pad(names[i].encode("UTF-16BE"),0x54)
except KeyError:
imet += "\x00"*0x54
imet += "\x00"*(0x600 - len(imet))
imet += b"\x00"*0x54
imet += b"\x00"*(0x600 - len(imet))
imet = imet[:-16] + md5.new(imet).digest()
imet = imet[:-16] + hashlib.md5(imet).digest()
open(output,"w").write(imet)
open(output,"wb").write(imet)
f = open(sys.argv[1],"w")
f = open(sys.argv[1],"wb")
f.write(imet)
f.write(data)
fsize = f.tell()
if (fsize % 20) != 0:
f.write("\x00"*(20-(fsize%20)))
f.write(b"\x00"*(20-(fsize%20)))
f.close()

View File

@@ -17,20 +17,20 @@ import pywii as wii
def LZ77Decompress(data):
inp = 0
dlen = len(data)
data += '\0' * 16
data += b'\0' * 16
ret = []
while inp < dlen:
bitmask = ord(data[inp])
bitmask = data[inp]
inp += 1
for i in xrange(8):
for i in range(8):
if bitmask & 0x80:
rep = ord(data[inp])
rep = data[inp]
repLength = (rep >> 4) + 3
inp += 1
repOff = ord(data[inp]) | ((rep & 0x0F) << 8)
repOff = data[inp] | ((rep & 0x0F) << 8)
inp += 1
assert repOff <= len(ret)
@@ -44,13 +44,13 @@ def LZ77Decompress(data):
bitmask <<= 1
return ''.join(ret)
return bytes(ret)
class U8(object):
class U8Header(Struct):
__endian__ = Struct.BE
def __format__(self):
self.Tag = Struct.string(4)
self.Tag = Struct.uint32
self.RootNode = Struct.uint32
self.HeaderSize = Struct.uint32
self.DataOffset = Struct.uint32
@@ -76,7 +76,8 @@ class U8(object):
u8.unpack(data[pos:pos+len(u8)])
pos += len(u8)
assert u8.Tag == 'U\xAA8-'
print(hex(u8.Tag))
assert u8.Tag == 0x55aa382d
pos += u8.RootNode - 0x20
root = self.U8Node()
@@ -84,7 +85,7 @@ class U8(object):
pos += len(root)
children = []
for i in xrange(root.Size - 1):
for i in range(root.Size - 1):
child = self.U8Node()
child.unpack(data[pos:pos+len(child)])
pos += len(child)
@@ -98,7 +99,7 @@ class U8(object):
path = ['.']
pathDepth = [root.Size - 1]
for offset,child in enumerate(children):
name = stringTable[child.NameOffset:].split('\0', 1)[0]
name = stringTable[child.NameOffset:].split(b'\0', 1)[0].decode("ascii")
if child.Type == 0x0100:
path.append(name)
pathDepth.append(child.Size-offset-1)
@@ -136,7 +137,7 @@ def IMD5(data):
assert imd5.Tag == 'IMD5'
pos = len(imd5)
if data[pos:pos+4] == 'LZ77':
if data[pos:pos+4] == b'LZ77':
return LZ77Decompress(data[pos+8:])
else:
return data[pos:]
@@ -145,7 +146,7 @@ class TPL(object):
class TPLHeader(Struct):
__endian__ = Struct.BE
def __format__(self):
self.Magic = Struct.string(4)
self.Magic = Struct.uint32
self.Count = Struct.uint32
self.Size = Struct.uint32
@@ -188,10 +189,10 @@ class TPL(object):
header.unpack(data[:len(header)])
pos = len(header)
assert header.Magic == '\x00\x20\xAF\x30'
assert header.Magic == 0x0020AF30
assert header.Size == 0xc
for i in xrange(header.Count):
for i in range(header.Count):
offs = self.TexOffsets()
offs.unpack(data[pos:pos+len(offs)])
pos += len(offs)
@@ -221,26 +222,27 @@ class TPL(object):
elif format == 14:
rgba = self.S3TC(data[texHeader.DataOff:], texHeader.Size)
else:
print 'Unknown texture format', format
print('Unknown texture format', format)
if rgba == None:
rgba = '\0\0\0\0' * texHeader.Size[0] * texHeader.Size[1]
rgba = b'\0\0\0\0' * texHeader.Size[0] * texHeader.Size[1]
image = ImageData(texHeader.Size[1], texHeader.Size[0], 'RGBA', rgba)
print format
print(format)
return image
def I4(self, data, (y, x)):
out = [0 for i in xrange(x * y)]
def I4(self, data, xxx_todo_changeme):
(y, x) = xxx_todo_changeme
out = [0 for i in range(x * y)]
outp = 0
inp = 0
for i in xrange(0, y, 8):
for j in xrange(0, x, 8):
for i in range(0, y, 8):
for j in range(0, x, 8):
ofs = 0
for k in xrange(8):
for k in range(8):
off = min(x - j, 8)
for sub in xrange(0, off, 2):
texel = ord(data[inp])
for sub in range(0, off, 2):
texel = data[inp]
high, low = texel >> 4, texel & 0xF
if (outp + ofs + sub) < (x*y):
out[outp + ofs + sub] = (high << 4) | (high << 20) | (high << 12) | 0xFF<<24
@@ -252,23 +254,24 @@ class TPL(object):
inp += 1
ofs += x
inp += (8 - off) / 2
inp += (8 - off) // 2
outp += off
outp += x * 7
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
def I8(self, data, (y, x)):
out = [0 for i in xrange(x * y*2)]
def I8(self, data, xxx_todo_changeme1):
(y, x) = xxx_todo_changeme1
out = [0 for i in range(x * y*2)]
outp = 0
inp = 0
for i in xrange(0, y, 4):
for j in xrange(0, x, 4):
for i in range(0, y, 4):
for j in range(0, x, 4):
ofs = 0
for k in xrange(4):
for k in range(4):
off = min(x - j, 4)
for sub in xrange(off):
texel = ord(data[inp])
for sub in range(off):
texel = data[inp]
out[outp + ofs + sub] = (texel << 24) | (texel << 16) | (texel << 8) | 0xFF
inp += 1
@@ -277,19 +280,20 @@ class TPL(object):
outp += off
outp += x * 3
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
def IA4(self, data, (y, x)):
out = [0 for i in xrange(x * y)]
def IA4(self, data, xxx_todo_changeme2):
(y, x) = xxx_todo_changeme2
out = [0 for i in range(x * y)]
outp = 0
inp = 0
for i in xrange(0, y, 4):
for j in xrange(0, x, 8):
for i in range(0, y, 4):
for j in range(0, x, 8):
ofs = 0
for k in xrange(4):
for k in range(4):
off = min(x - j, 8)
for sub in xrange(off):
texel = ord(data[inp])
for sub in range(off):
texel = data[inp]
alpha, inte = texel >> 4, texel & 0xF
if (outp + ofs + sub) < (x*y):
out[outp + ofs + sub] = (inte << 4) | (inte << 12) | (inte << 20) | (alpha << 28)
@@ -300,18 +304,19 @@ class TPL(object):
outp += off
outp += x * 3
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
def IA8(self, data, (y, x)):
out = [0 for i in xrange(x * y)]
def IA8(self, data, xxx_todo_changeme3):
(y, x) = xxx_todo_changeme3
out = [0 for i in range(x * y)]
outp = 0
inp = 0
for i in xrange(0, y, 4):
for j in xrange(0, x, 4):
for i in range(0, y, 4):
for j in range(0, x, 4):
ofs = 0
for k in xrange(4):
for k in range(4):
off = min(x - j, 4)
for sub in xrange(off):
for sub in range(off):
if (outp + ofs + sub) < (x*y):
texel = Struct.uint16(data[inp:inp + 2], endian='>')
p = (texel & 0xFF)
@@ -326,18 +331,19 @@ class TPL(object):
outp += off
outp += x * 3
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
def RGB565(self, data, (y, x)):
out = [0 for i in xrange(x * y)]
def RGB565(self, data, xxx_todo_changeme4):
(y, x) = xxx_todo_changeme4
out = [0 for i in range(x * y)]
outp = 0
inp = 0
for i in xrange(0, y, 4):
for j in xrange(0, x, 4):
for i in range(0, y, 4):
for j in range(0, x, 4):
ofs = 0
for k in xrange(4):
for k in range(4):
off = min(x - j, 4)
for sub in xrange(off):
for sub in range(off):
if (outp + ofs + sub) < (x*y):
texel = Struct.uint16(data[inp:inp + 2], endian='>')
p = ((texel >> 11) & 0x1F) << 3
@@ -352,18 +358,19 @@ class TPL(object):
outp += off
outp += x * 3
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
def RGB5A3(self, data, (y, x)):
out = [0 for i in xrange(x * y)]
def RGB5A3(self, data, xxx_todo_changeme5):
(y, x) = xxx_todo_changeme5
out = [0 for i in range(x * y)]
outp = 0
inp = 0
for i in xrange(0, y, 4):
for j in xrange(0, x, 4):
for i in range(0, y, 4):
for j in range(0, x, 4):
ofs = 0
for k in xrange(4):
for k in range(4):
off = min(x - j, 4)
for sub in xrange(off):
for sub in range(off):
texel = Struct.uint16(data[inp:inp + 2], endian='>')
if texel & 0x8000:
p = ((texel >> 10) & 0x1F) << 3
@@ -384,18 +391,19 @@ class TPL(object):
outp += off
outp += x * 3
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
def RGBA8(self, data, (y, x)):
out = [0 for i in xrange(x * y)]
def RGBA8(self, data, xxx_todo_changeme6):
(y, x) = xxx_todo_changeme6
out = [0 for i in range(x * y)]
outp = 0
inp = 0
for i in xrange(0, y, 4):
for j in xrange(0, x, 4):
for i in range(0, y, 4):
for j in range(0, x, 4):
ofs = 0
for k in xrange(4):
for k in range(4):
off = min(x - j, 4)
for sub in xrange(off):
for sub in range(off):
texel = Struct.uint16(data[inp:inp + 2], endian='>')<<16
texel |= Struct.uint16(data[inp+32:inp + 34], endian='>')
if (outp + ofs + sub) < (x*y):
@@ -408,7 +416,7 @@ class TPL(object):
inp += 32
outp += x * 3
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
def unpack_rgb565(self,texel):
b = (texel&0x1f)<<3
@@ -420,24 +428,25 @@ class TPL(object):
return (0xff<<24) | (b<<16) | (g<<8) | r
def icolor(self,a,b,fa,fb,fc):
c = 0
for i in xrange(0,32,8):
for i in range(0,32,8):
xa = (a>>i)&0xff
xb = (b>>i)&0xff
xc = min(255,max(0,int((xa*fa + xb*fb)/fc)))
c |= xc<<i
return c
def S3TC(self, data, (y, x)):
out = [0 for i in xrange(x * y)]
def S3TC(self, data, xxx_todo_changeme7):
(y, x) = xxx_todo_changeme7
out = [0 for i in range(x * y)]
TILE_WIDTH = 8
TILE_HEIGHT = 8
inp = 0
outp = 0
for i in xrange(0, y, TILE_HEIGHT):
for j in xrange(0, x, TILE_WIDTH):
for i in range(0, y, TILE_HEIGHT):
for j in range(0, x, TILE_WIDTH):
maxw = min(x - j,TILE_WIDTH)
for k in xrange(2):
for l in xrange(2):
for k in range(2):
for l in range(2):
rgb = [0,0,0,0]
texel1 = Struct.uint16(data[inp:inp + 2], endian='>')
texel2 = Struct.uint16(data[inp + 2:inp + 4], endian='>')
@@ -452,7 +461,7 @@ class TPL(object):
rgb[3] = 0
# color selection (00, 01, 10, 11)
cm = map(ord,data[inp+4:inp+8])
cm = list(data[inp+4:inp+8])
ofs = l*4
for n in range(4):
if (ofs + outp)<(x*y):
@@ -471,7 +480,7 @@ class TPL(object):
outp += maxw - x * 8
outp += x * (TILE_HEIGHT - 1)
return ''.join(Struct.uint32(p) for p in out)
return b''.join(Struct.uint32(p) for p in out)
class Object(object):
def __init__(self, name):
@@ -554,7 +563,7 @@ class ItemList(object):
pos = 8
count = self.__unpkcnt__(data[pos:])
pos = self.__getlistoff__(data[pos:])
for i in xrange(count):
for i in range(count):
off = Struct.uint32(data[pos:pos+4], endian='>') + self.OFFSET
if i == (count-1):
next = len(data)
@@ -568,11 +577,11 @@ class ItemList(object):
def pack(self,extra=None):
extradata = ""
extradata = b""
if extra is not None:
extradata = extra.pack()
data = ""
data = b""
offsets = []
@@ -583,9 +592,9 @@ class ItemList(object):
listlen = len(self.Items) * self.LSIZE
head = self.__mkheader__()
outdata = ""
outdata = b""
if self.IS_ATOM:
outdata += self.FOURCC + Struct.uint32((len(extradata) + listlen + len(data) + 8 + len(head) + 3) &(~3), endian='>')
outdata += self.FOURCC.encode("ascii") + Struct.uint32((len(extradata) + listlen + len(data) + 8 + len(head) + 3) &(~3), endian='>')
outdata += head
dataoff = len(outdata) + listlen - self.OFFSET
@@ -594,18 +603,18 @@ class ItemList(object):
for n in offsets:
outdata += Struct.uint32(n + dataoff, endian='>')
if self.LSIZE > 4:
outdata += (self.LSIZE-4)*"\x00"
outdata += (self.LSIZE-4)*b"\x00"
outdata += data
outdata += extradata
if len(outdata)%4 != 0:
outdata += (4-len(outdata)%4)*"\x00"
outdata += (4-len(outdata)%4)*b"\x00"
return outdata
def __mkheader__(self):
return Struct.uint16(len(self.Items), endian='>') + "\x00\x00"
return Struct.uint16(len(self.Items), endian='>') + b"\x00\x00"
def __unpkcnt__(self, data):
return Struct.uint16(data[0:2], endian='>')
@@ -668,12 +677,12 @@ class Brlyt(object):
ItemList.__init__(self, data)
def unpack_item(self, i, data):
fn = data.split('\0', 1)[0]
print fn
fn = data.split(b'\0', 1)[0].decode("ascii")
print(fn)
tex = TPL(self.Archive.Files['./arc/timg/' + fn.lower()]).Textures[0]
self.Items.append(Brlyt.BrlytTexture(fn, tex))
def pack_item(self, i, item):
return item.Name + "\0"
return item.Name.encode("ascii") + b"\0"
class BrlytMAT1(ItemList):
LSIZE = 4
@@ -709,20 +718,20 @@ class Brlyt(object):
self.m_8 = bool((value>>27) & 1)
def show(self):
print "Flags: %08x"%self.value
print "ReserveGXMem("
print " r4 =",self.NumTextures
print " r5 =",self.NumCoords
print " r6 =",self.m_2
print " r7 =",self.m_3
print " r8 =",self.m_4
print " r9 =",self.m_5
print " r10 =",self.m_6
print " 0x8(%sp) =",self.m_7
print " 0xC(%sp) =",self.m_8
print " 0x10(%sp) =",self.m_9
print " 0x14(%sp) =",self.m_10
print ")"
print("Flags: %08x"%self.value)
print("ReserveGXMem(")
print(" r4 =",self.NumTextures)
print(" r5 =",self.NumCoords)
print(" r6 =",self.m_2)
print(" r7 =",self.m_3)
print(" r8 =",self.m_4)
print(" r9 =",self.m_5)
print(" r10 =",self.m_6)
print(" 0x8(%sp) =",self.m_7)
print(" 0xC(%sp) =",self.m_8)
print(" 0x10(%sp) =",self.m_9)
print(" 0x14(%sp) =",self.m_10)
print(")")
def pack(self):
val = 0
@@ -743,7 +752,7 @@ class Brlyt(object):
__endian__ = Struct.BE
def __format__(self):
self.Name = Struct.string(0x14)
self.Name = Struct.string(0x14, stripNulls=True)
self.Color1 = Struct.uint16[4]
self.Color2 = Struct.uint16[4]
self.Color3 = Struct.uint16[4]
@@ -822,63 +831,63 @@ class Brlyt(object):
for i in range(self.FlagData.NumTextures):
texid = Struct.uint16(data[ptr:ptr+2], endian='>')
texcs = Struct.uint8(data[ptr+2], endian='>')
texct = Struct.uint8(data[ptr+3], endian='>')
print " * Texture: %04x %d %d"%(texid,texcs,texct)
texcs = data[ptr+2]
texct = data[ptr+3]
print(" * Texture: %04x %d %d"%(texid,texcs,texct))
self.Textures.append((texid,texcs,texct))
ptr += 4
for i in range(self.FlagData.NumCoords):
dat = []
for j in range(5):
dat.append(Struct.float(data[ptr+j*4:ptr+j*4+4], endian='>'))
print " * Coords: [",', '.join(["%f"%x for x in dat]),"]"
print(" * Coords: [",', '.join(["%f"%x for x in dat]),"]")
ptr += 0x14
self.TextureCoords.append(dat)
for i in range(self.FlagData.m_2):
dat = Struct.uint32(data[ptr:ptr+4], endian='>')
self.SthB.append(dat)
print " * SthB: %08x"%dat
print(" * SthB: %08x"%dat)
ptr += 0x04
if self.FlagData.m_7:
self.SthI = Struct.uint32(data[ptr:ptr+4], endian='>')
print " SthI: %08x"%self.SthI
print(" SthI: %08x"%self.SthI)
ptr += 0x04
if self.FlagData.m_8:
self.SthJ = Struct.uint32(data[ptr:ptr+4], endian='>')
print " SthJ: %08x"%self.SthJ
print(" SthJ: %08x"%self.SthJ)
ptr += 0x04
if self.FlagData.m_4:
self.SthC = Struct.uint32(data[ptr:ptr+4], endian='>')
print " SthC: %08x"%self.SthC
print(" SthC: %08x"%self.SthC)
ptr += 0x04
for i in range(self.FlagData.m_6):
dat = []
for j in range(5):
dat.append(Struct.float(data[ptr+j*4:ptr+j*4+4], endian='>'))
self.SthD.append(dat)
print " * SthD: [",', '.join(["%f"%x for x in dat]),"]"
print(" * SthD: [",', '.join(["%f"%x for x in dat]),"]")
ptr += 0x14
for i in range(self.FlagData.m_5):
dat = Struct.uint32(data[ptr:ptr+4], endian='>')
self.SthE.append(dat)
print " * SthE: %08x"%dat
print(" * SthE: %08x"%dat)
ptr += 0x04
for i in range(self.FlagData.m_3):
dat = []
for j in range(4):
dat.append(Struct.uint32(data[ptr+j*4:ptr+j*4+4], endian='>'))
self.SthF.append(dat)
print " * SthF: [",', '.join(["%08x"%x for x in dat]),"]"
print(" * SthF: [",', '.join(["%08x"%x for x in dat]),"]")
ptr += 0x10
if self.FlagData.m_9:
dat = Struct.uint32(data[ptr:ptr+4], endian='>')
self.SthG = dat
print " SthG: %08x"%dat
print(" SthG: %08x"%dat)
ptr += 0x04
if self.FlagData.m_10:
dat = Struct.uint32(data[ptr:ptr+4], endian='>')
self.SthH = dat
print " SthH: %08x"%dat
print(" SthH: %08x"%dat)
ptr += 0x04
#assert ptr == len(data)
@@ -903,7 +912,7 @@ class Brlyt(object):
hdr = Brlyt.BrlytMatHeader()
hdr.Name = self.Name + "\x00"*(0x14-len(self.Name))
hdr.Name = self.Name.encode("ascii") + b"\x00"*(0x14-len(self.Name))
hdr.Color1 = self.Color1
hdr.Color2 = self.Color2
hdr.Color3 = self.Color3
@@ -947,16 +956,21 @@ class Brlyt(object):
StdAtom.__format__(self)
self.Flags = Struct.uint16
self.Alpha = Struct.uint16
self.Name = Struct.string(0x18)
self.Name = Struct.string(0x18, stripNulls=True)
self.Coords = Struct.float[10]
class BrlytPIC1(BrlytPAN1):
class BrlytPIC1v1(BrlytPAN1):
FOURCC = "pic1"
def __format__(self):
Brlyt.BrlytPAN1.__format__(self)
self.unk = Struct.uint8[16]
self.Material = Struct.uint16
self.Flags2 = Struct.uint16
class BrlytPIC1v2(BrlytPIC1v1):
FOURCC = "pic1"
def __format__(self):
Brlyt.BrlytPIC1v1.__format__(self)
self.MaterialCoords = Struct.float[8]
def __init__(self, archive, data, renderer):
@@ -969,7 +983,7 @@ class Brlyt(object):
self.Objects = {}
self.PanePath = []
self.PaneId = 0
self.Language = "ENG"
self.Language = b"ENG"
self.Renderer = renderer
if data != None:
@@ -979,17 +993,17 @@ class Brlyt(object):
pos = 0
header = self.BrlytHeader()
header.unpack(data[:len(header)])
print "BRLYT header:"
print("BRLYT header:")
wii.chexdump(data[:len(header)])
print " unk1: %08x"%header.Unk
print " unkc: %08x"%header.UnkCount
print(" unk1: %08x"%header.Unk)
print(" unkc: %08x"%header.UnkCount)
pos += len(header)
print " %d atoms"%header.AtomCount
print(" %d atoms"%header.AtomCount)
assert header.Magic == 'RLYT'
for i in xrange(header.AtomCount):
for i in range(header.AtomCount):
atom = StdAtom()
atom.unpack(data[pos:pos+len(atom)])
@@ -1011,7 +1025,7 @@ class Brlyt(object):
elif atom.FourCC == "grp1":
self.GRP1(atomdata)
else:
print "Unknown FOURCC:",atom.FourCC
print("Unknown FOURCC:",atom.FourCC)
wii.chexdump(atomdata)
pos += atom.Size
@@ -1021,10 +1035,10 @@ class Brlyt(object):
if isinstance(object,Pane):
atoms += 1
if isinstance(object,Picture):
atom = Brlyt.BrlytPIC1()
atom = Brlyt.BrlytPIC1v2()
else:
atom = Brlyt.BrlytPAN1()
atom.Name = object.Name + "\x00"*(0x18-len(object.Name))
atom.Name = object.Name.encode("ascii") + b"\x00"*(0x18-len(object.Name))
atom.Alpha = int(object.Alpha * 256)
atom.Flags = object.Flags
atom.Coords = object.Coords
@@ -1032,17 +1046,17 @@ class Brlyt(object):
atom.Flags2 = object.Flags2
atom.Material = object.Material
atom.unk = object.Unk
atom.MaterialCoords = sum(map(list,object.MaterialCoords),[])
atom.MaterialCoords = sum(object.MaterialCoords,())
data = atom.pack()
if len(object.Children) > 0:
atoms += 2
data += "pas1\x00\x00\x00\x08"
data += b"pas1\x00\x00\x00\x08"
for child in object.Children:
ac, dc = self._PackObject(child)
data += dc
atoms += ac
data += "pae1\x00\x00\x00\x08"
data += b"pae1\x00\x00\x00\x08"
return atoms, data
else:
raise ValueError("Unknown object: "+repr(object))
@@ -1055,7 +1069,7 @@ class Brlyt(object):
header.Magic = "RLYT"
header.AtomCount = 0
data = ""
data = b""
data += self.mkLYT1()
header.AtomCount+=1
@@ -1070,7 +1084,7 @@ class Brlyt(object):
header.AtomCount += atoms
#uuugly. TODO: fix this crap.
data += "grp1\x00\x00\x00\x1cRootGroup\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
data += b"grp1\x00\x00\x00\x1cRootGroup\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
header.AtomCount += 1
header.Size = len(data) + len(header)
@@ -1098,7 +1112,7 @@ class Brlyt(object):
lyt1.unpack(data)
self.Width = lyt1.Width
self.Height = lyt1.Height
print "LYT1: %f x %f, flag %d"%(self.Width, self.Height, lyt1.Flag)
print("LYT1: %f x %f, flag %d"%(self.Width, self.Height, lyt1.Flag))
self.Renderer.Create(int(self.Width), int(self.Height))
def TXL1(self, data):
@@ -1107,13 +1121,13 @@ class Brlyt(object):
i.create_texture()
def ApplyMask(self, image, mask):
print "Making mask:",image,mask
print image.width,image.height,mask.width,mask.height
print("Making mask:",image,mask)
print(image.width,image.height,mask.width,mask.height)
if image.height != mask.height or image.width != mask.width:
raise ValueError("Mask dimensions must be equal to mask dimensions")
newdata = [0 for x in xrange(image.height * image.width * 4)]
newdata = [0 for x in range(image.height * image.width * 4)]
for pix in xrange(image.height * image.width):
for pix in range(image.height * image.width):
newdata[pix*4 + 0] = image.data[pix*4 + 0]
newdata[pix*4 + 1] = image.data[pix*4 + 1]
newdata[pix*4 + 2] = image.data[pix*4 + 2]
@@ -1136,8 +1150,8 @@ class Brlyt(object):
wii.chexdump(data)
pane = Brlyt.BrlytPAN1()
pane.unpack(data)
p = Pane(pane.Name.split('\0',1)[0], pane.Flags, pane.Alpha/256.0, pane.Coords)
print 'Pane %s (flags %04x, alpha %f): ' % (p.Name, pane.Flags, pane.Alpha),pane.Coords
p = Pane(pane.Name, pane.Flags, pane.Alpha/256.0, pane.Coords)
print('Pane %s (flags %04x, alpha %f): ' % (p.Name, pane.Flags, pane.Alpha),pane.Coords)
self._addpane(p)
def PAS1(self, data):
@@ -1145,48 +1159,55 @@ class Brlyt(object):
if self.CurPane is None:
raise ValueError("No current pane!")
self.PanePath.append(self.CurPane)
print "Pane start:",'.'.join(map(str,self.PanePath))
print("Pane start:",'.'.join(map(str,self.PanePath)))
self.CurPane = None
def PAE1(self, data):
print "Pane end:",'.'.join(map(str,self.PanePath))
print("Pane end:",'.'.join(map(str,self.PanePath)))
self.PanePath = self.PanePath[:-1]
def PIC1(self, data):
wii.chexdump(data)
pic = Brlyt.BrlytPIC1()
if len(data) == len(Brlyt.BrlytPIC1v1()):
pic = Brlyt.BrlytPIC1v1()
else:
pic = Brlyt.BrlytPIC1v2()
pic.unpack(data)
mc = []
for i in range(4):
mc.append(pic.MaterialCoords[i*2:i*2+2])
print mc
p = Picture(pic.Name.split("\0",1)[0], pic.Flags, pic.Alpha/256.0, pic.Coords, pic.unk, pic.Material, pic.Flags2, mc)
print repr(p.Name)
kw = {}
if not isinstance(pic, Brlyt.BrlytPIC1v1):
mc = []
for i in range(4):
mc.append(pic.MaterialCoords[i*2:i*2+2])
kw["matcoord"] = mc
p = Picture(pic.Name, pic.Flags, pic.Alpha/256.0, pic.Coords, pic.unk, pic.Material, pic.Flags2, *kw)
print(repr(p.Name))
mat = self.Materials[pic.Material]
if mat is not None:
self._addpane(p)
else:
print 'Picture %s with null material!'
print('Picture %s with null material!')
def GRP1(self, data):
wii.chexdump(data)
if len(data) < 0x1c:
pass
lang = data[0x8:0x18].split('\0', 1)[0]
lang = data[0x8:0x18].split(b'\0', 1)[0]
nitems = Struct.uint16(data[0x18:0x1a], endian='>')
p = 0x1c
items = []
for i in xrange(nitems):
items.append(data[p:].split('\0', 1)[0])
for i in range(nitems):
items.append(data[p:p+0x10].split(b'\0', 1)[0].decode("ascii"))
p += 0x10
for i in items:
try:
if lang != self.Language:
self.Objects[i].Enabled = False
else:
self.Objects[i].Enabled = True
except:
pass
if i not in self.Objects:
print("Missing object:", i)
continue
if lang != self.Language:
self.Objects[i].Enabled = False
else:
self.Objects[i].Enabled = True
class Brlan(object):
A_COORD = "RLPA"
@@ -1222,7 +1243,7 @@ class Brlan(object):
assert header.Magic == 'RLAN'
for i in xrange(header.AtomCount):
for i in range(header.AtomCount):
atom = StdAtom()
atom.unpack(data[pos:pos+len(atom)])
atomdata = data[pos:pos+atom.Size]
@@ -1231,7 +1252,7 @@ class Brlan(object):
if atom.FourCC == 'pai1':
self.PAI1(atomdata)
else:
print "Unknown animation atom: %s"%atom.FourCC
print("Unknown animation atom: %s"%atom.FourCC)
class BrlanPAI1(ItemList):
LSIZE=4
@@ -1240,7 +1261,7 @@ class Brlan(object):
HDRLEN=12
def unpack(self, data):
self.FrameCount = Struct.uint16(data[8:10], endian='>')
print self.FrameCount
print(self.FrameCount)
ItemList.unpack(self, data)
def __mkheader__(self):
hdr = Struct.uint16(self.FrameCount, endian='>')
@@ -1292,13 +1313,13 @@ class Brlan(object):
else:
ItemList.__init__(self, data)
def unpack(self, data):
self.Name = data[:0x14].split("\0",1)[0]
print self.Name
self.Name = data[:0x14].split(b"\0",1)[0].decode("ascii")
print(self.Name)
ItemList.unpack(self, data)
def __mkheader__(self):
hdr = self.Name + "\x00" * (0x14-len(self.Name))
hdr = self.Name.encode("ascii") + b"\x00" * (0x14-len(self.Name))
hdr += Struct.uint8(len(self.Items), endian='>')
hdr += "\x00\x00\x00"
hdr += b"\x00\x00\x00"
return hdr
def __unpkcnt__(self, data):
return Struct.uint8(data[0x14:0x15], endian='>')
@@ -1330,7 +1351,7 @@ class Brlan(object):
self.item = 0
def __iter__(self):
return self
def next(self):
def __next__(self):
if self.item == len(self.cl.Items):
raise StopIteration()
else:
@@ -1344,13 +1365,13 @@ class Brlan(object):
else:
ItemList.__init__(self, data)
def unpack(self, data):
self.Type = data[0:4]
print " ",self.Type
self.Type = data[0:4].decode("ascii")
print(" ",self.Type)
ItemList.unpack(self, data)
def __mkheader__(self):
hdr = self.Type
hdr = self.Type.encode("ascii")
hdr += Struct.uint8(len(self.Items), endian='>')
hdr += "\x00\x00\x00"
hdr += b"\x00\x00\x00"
return hdr
def __unpkcnt__(self, data):
return Struct.uint8(data[4:5], endian='>')
@@ -1383,18 +1404,18 @@ class Brlan(object):
self.Unk = Struct.uint16(data[2:4], endian='>')
count = Struct.uint16(data[4:6], endian='>')
pos = Struct.uint32(data[8:12], endian='>')
print " ",self.Type
print(" ",self.Type)
if self.Unk == 0x200:
print " Triplets:"
print(" Triplets:")
for i in range(count):
F = Struct.float(data[pos+0:pos+4], endian='>')
P = Struct.float(data[pos+4:pos+8], endian='>')
D = Struct.float(data[pos+8:pos+12], endian='>')
print " %11f %11f %11f"%(F,P,D)
print(" %11f %11f %11f"%(F,P,D))
self.Triplets.append((F,P,D))
pos += 12
else:
print " Unknown format: %04x"%self.Unk
print(" Unknown format: %04x"%self.Unk)
def pack(self, offset):
self.Triplets.sort(key=lambda x: x[0])
t = self.Triplets
@@ -1411,7 +1432,7 @@ class Brlan(object):
out = Struct.uint16(self.Type, endian='>')
out += Struct.uint16(self.Unk, endian='>')
out += Struct.uint16(len(self.Triplets), endian='>')
out += "\x00\x00"
out += b"\x00\x00"
out += Struct.uint32(0xc, endian='>')
for F,P,D in self.Triplets:
out += Struct.float(F-offset, endian='>')
@@ -1511,7 +1532,7 @@ class Renderer(object):
def Create(self, width, height):
self.Width = width
self.Height = height
print "Render: %f x %f"%(self.Width,self.Height)
print("Render: %f x %f"%(self.Width,self.Height))
self.Window = BannerWindow(self.Width, self.Height)
self.Window.set_exclusive_mouse(False)
@@ -1523,7 +1544,7 @@ class Renderer(object):
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_BLEND)
glEnable(GL_TEXTURE_2D)
clock.set_fps_limit(60)
#clock.set_fps_limit(60)
def Render(self, item, wireframe=False):
@@ -1532,6 +1553,9 @@ class Renderer(object):
if isinstance(item, Picture):
mat = self.Brlyt.Materials[item.Material]
if not mat.Textures:
return
texture = self.Brlyt.Textures[mat.Textures[0][0]].GLTexture
mtc = mat.TextureCoords[0]
x, y, a, b, c, rot, xsc, ysc, xs, ys = item.Coords[:10]
@@ -1638,7 +1662,10 @@ class Renderer(object):
for set in self.Brlan.Anim:
for clss in set:
for anim in clss:
#print set.Name, clss.Type, anim.Type, anim.calc(frame), frame
if set.Name not in self.Brlyt.Objects:
print("Missing object for animation: %s (%s)" % (set.Name, clss.Type))
continue
#print(set.Name, clss.Type, anim.Type, anim.calc(frame), frame)
if clss.Type == Brlan.A_COORD:
self.Brlyt.Objects[set.Name].Coords[anim.Type] = anim.calc(frame)
elif clss.Type == Brlan.A_PARM:
@@ -1647,8 +1674,9 @@ class Renderer(object):
def MainLoop(self, loop):
frame = 0
print "Starting mainloop: loop =",loop
print "Length in frames:",self.Brlan.Anim.FrameCount
print("Starting mainloop: loop =",loop)
if self.Brlan:
print("Length in frames:",self.Brlan.Anim.FrameCount)
while not self.Window.has_exit:
self.Window.dispatch_events()
self.Window.clear()
@@ -1660,17 +1688,17 @@ class Renderer(object):
self.Render(self.Brlyt.RootPane,False)
#self.Render(self.Brlyt.RootPane,True)
#clock.tick()
clock.tick()
self.Window.flip()
if self.Brlan is not None:
self.Animate(frame)
if frame >= self.Brlan.Anim.FrameCount:
if not loop:
print "Animation done!"
print("Animation done!")
return True
else:
print "Looping..."
print("Looping...")
frame = -1
frame += 1
@@ -1690,7 +1718,7 @@ class Alameda(object):
def __init__(self, fn, type='icon'):
renderer = Renderer()
fp = file(fn, 'rb')
fp = open(fn, 'rb')
imet = self.IMETHeader()
try:
@@ -1703,7 +1731,7 @@ class Alameda(object):
imet.unpack(fp.read(len(imet)))
assert imet.IMET == 'IMET'
print 'English title: %s' % imet.Names[1]
print('English title: %s' % imet.Names[1])
root = U8(fp.read())
@@ -1722,14 +1750,22 @@ class Alameda(object):
else:
banner = U8(IMD5(root.Files['./meta/banner.bin']))
renderer.Brlyt = Brlyt(banner, banner.Files['./arc/blyt/banner.brlyt'], renderer)
loop = not banner.Files.has_key('./arc/anim/banner_start.brlan')
loop = './arc/anim/banner_start.brlan' not in banner.Files
loop_anim = None
if not loop:
renderer.Brlan = Brlan(banner.Files['./arc/anim/banner_start.brlan'])
if './arc/anim/banner_loop.brlan' in banner.Files:
loop_anim = Brlan(banner.Files['./arc/anim/banner_loop.brlan'])
else:
renderer.Brlan = Brlan(banner.Files['./arc/anim/banner.brlan'])
if './arc/anim/banner.brlan' in banner.Files:
renderer.Brlan = Brlan(banner.Files['./arc/anim/banner.brlan'])
else:
renderer.Brlan = None
if renderer.MainLoop(loop) and type == 'banner' and not loop:
renderer.Brlan = Brlan(banner.Files['./arc/anim/banner_loop.brlan'])
renderer.Brlan = loop_anim
renderer.MainLoop(True)
if __name__=='__main__':

View File

@@ -4,7 +4,7 @@ class StructType(tuple):
def __getitem__(self, value):
return [self] * value
def __call__(self, value, endian='<'):
if isinstance(value, str):
if isinstance(value, bytes):
return struct.unpack(endian + tuple.__getitem__(self, 0), value[:tuple.__getitem__(self, 1)])[0]
else:
return struct.pack(endian + tuple.__getitem__(self, 0), value)
@@ -12,8 +12,8 @@ class StructType(tuple):
class StructException(Exception):
pass
class Struct(object):
__slots__ = ('__attrs__', '__baked__', '__defs__', '__endian__', '__next__', '__sizes__', '__values__')
class Struct:
__slots__ = ('__attrs__', '__baked__', '__defs__', '__next__', '__sizes__', '__values__')
int8 = StructType(('b', 1))
uint8 = StructType(('B', 1))
@@ -49,7 +49,7 @@ class Struct(object):
else:
sys.settrace(self.__trace__)
func()
for name in func.func_code.co_varnames:
for name in func.__code__.co_varnames:
value = self.__frame__.f_locals[name]
self.__setattr__(name, value)
@@ -186,11 +186,13 @@ class Struct(object):
if len(temp) != size:
raise StructException('Expected %i byte string, got %i' % (size, len(temp)))
if stripNulls:
temp = temp.rstrip(b'\0')
if encoding != None:
temp = temp.decode(encoding)
if stripNulls:
temp = temp.rstrip('\0')
else:
temp = temp.decode("ascii")
if attrs[0] == '*':
name = attrs[1:]
@@ -231,7 +233,7 @@ class Struct(object):
def pack(self):
arraypos, arrayname = None, None
ret = ''
ret = b''
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
@@ -251,9 +253,11 @@ class Struct(object):
if encoding != None:
temp = temp.encode(encoding)
elif isinstance(temp, str):
temp = temp.encode("ascii")
temp = temp[:size]
ret += temp + ('\0' * (size - len(temp)))
ret += temp + (b'\0' * (size - len(temp)))
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
@@ -299,16 +303,16 @@ if __name__=='__main__':
self.hax = HaxStruct
test = TestStruct()
test.unpack('\xEF\xBE\xAD\xDE\x00\x00\x80\x3Fdeadbeef\x04\x00\x00\x00test\xCA\xFE\xBA\xBE\xBE\xBA\xFE\xCA')
test.unpack(b'\xEF\xBE\xAD\xDE\x00\x00\x80\x3Fdeadbeef\x04\x00\x00\x00test\xCA\xFE\xBA\xBE\xBE\xBA\xFE\xCA')
assert test.foo == 0xDEADBEEF
assert test.bar == 1.0
assert test.baz == 'deadbeef'
assert test.baz == b'deadbeef'
assert test.omg == 4
assert test.wtf == 'test'
assert test.wtf == b'test'
assert test.hax.thing1 == 0xBEBAFECA
assert test.hax.thing2 == 0xCAFEBABE
print 'Tests successful'
print('Tests successful')
"""
@Struct.LE

View File

@@ -1,3 +1,3 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
from wii import *
from .wii import *

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
# Copyright 2008 Hector Martin <marcan@marcansoft.com>
# Licensed under the terms of the GNU GPL, version 2
@@ -12,11 +12,11 @@ except ImportError:
from Crypto.Util.number import bytes_to_long, long_to_bytes
# y**2 + x*y = x**3 + x + b
ec_b = "\x00\x66\x64\x7e\xde\x6c\x33\x2c\x7f\x8c\x09\x23\xbb\x58\x21"+\
"\x3b\x33\x3b\x20\xe9\xce\x42\x81\xfe\x11\x5f\x7d\x8f\x90\xad"
ec_b = (b"\x00\x66\x64\x7e\xde\x6c\x33\x2c\x7f\x8c\x09\x23\xbb\x58\x21"+
b"\x3b\x33\x3b\x20\xe9\xce\x42\x81\xfe\x11\x5f\x7d\x8f\x90\xad")
def hexdump(s,sep=""):
return sep.join(map(lambda x: "%02x"%ord(x),s))
return sep.join(["%02x"%ord(x) for x in s])
def bhex(s,sep=""):
return hexdump(long_to_bytes(s,30),sep)
@@ -41,20 +41,20 @@ class ByteArray(array):
else:
array.__setitem__(self, item, value & 0xFF)
def __long__(self):
return bytes_to_long(self.tostring())
return bytes_to_long(self.tobytes())
def __str__(self):
return ''.join(["%02x"%ord(x) for x in self.tostring()])
return ''.join(["%02x"%x for x in self.tobytes()])
def __repr__(self):
return "ByteArray('%s')"%''.join(["\\x%02x"%ord(x) for x in self.tostring()])
return "ByteArray('%s')"%''.join(["\\x%02x"%x for x in self.tobytes()])
class ELT_PY:
SIZEBITS=233
SIZE=(SIZEBITS+7)/8
square = ByteArray("\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55")
square = ByteArray(b"\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55")
def __init__(self, initializer=None):
if isinstance(initializer, long) or isinstance(initializer, int):
if isinstance(initializer, int) or isinstance(initializer, int):
self.d = ByteArray(long_to_bytes(initializer,self.SIZE))
elif isinstance(initializer, str):
elif isinstance(initializer, bytes):
self.d = ByteArray(initializer)
elif isinstance(initializer, ByteArray):
self.d = ByteArray(initializer)
@@ -80,12 +80,12 @@ class ELT_PY:
return cmp(self.d,other.d)
def __long__(self):
return long(self.d)
return int(self.d)
def __repr__(self):
return repr(self.d).replace("ByteArray","ELT")
def __str__(self):
return str(self.d)
def __nonzero__(self):
def __bytes__(self):
return bytes(self.d)
def __bool__(self):
for x in self.d:
if x != 0:
return True
@@ -184,21 +184,21 @@ class ELT_PY:
def __setitem__(self,item,value):
self.d[item] = value
def tobignum(self):
return bytes_to_long(self.d.tostring())
return bytes_to_long(self.d.tobytes())
def tobytes(self):
return self.d.tostring()
return self.d.tobytes()
class ELT_C(ELT_PY):
def __mul__(self,other):
if not isinstance(other,ELT):
return NotImplemented
return ELT(_ec.elt_mul(self.d.tostring(),other.d.tostring()))
return ELT(_ec.elt_mul(self.d.tobytes(),other.d.tobytes()))
def __rdiv__(self,other):
if other != 1:
return ELT_PY.__rdiv__(self,other)
return ELT(_ec.elt_inv(self.d.tostring()))
return ELT(_ec.elt_inv(self.d.tobytes()))
def _square(self):
return ELT(_ec.elt_square(self.d.tostring()))
return ELT(_ec.elt_square(self.d.tobytes()))
if fastelt:
ELT = ELT_C
@@ -207,7 +207,7 @@ else:
class Point:
def __init__(self,x,y=None):
if isinstance(x,str) and (y is None) and (len(x) == 60):
if isinstance(x,bytes) and (y is None) and (len(x) == 60):
self.x = ELT(x[:30])
self.y = ELT(x[30:])
elif isinstance(x,Point):
@@ -292,7 +292,7 @@ class Point:
return "(%s,%s)"%(str(self.x),str(self.y))
def __repr__(self):
return "Point"+str(self)
def __nonzero__(self):
def __bool__(self):
return self.x or self.y
def tobytes(self):
return self.x.tobytes() + self.y.tobytes()
@@ -305,15 +305,15 @@ def bn_inv(a,N):
# order of the addition group of points
ec_N = bytes_to_long(
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+\
"\x13\xe9\x74\xe7\x2f\x8a\x69\x22\x03\x1d\x26\x03\xcf\xe0\xd7")
b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+
b"\x13\xe9\x74\xe7\x2f\x8a\x69\x22\x03\x1d\x26\x03\xcf\xe0\xd7")
# base point
ec_G = Point(
"\x00\xfa\xc9\xdf\xcb\xac\x83\x13\xbb\x21\x39\xf1\xbb\x75\x5f"+
"\xef\x65\xbc\x39\x1f\x8b\x36\xf8\xf8\xeb\x73\x71\xfd\x55\x8b"+
"\x01\x00\x6a\x08\xa4\x19\x03\x35\x06\x78\xe5\x85\x28\xbe\xbf"+
"\x8a\x0b\xef\xf8\x67\xa7\xca\x36\x71\x6f\x7e\x01\xf8\x10\x52")
b"\x00\xfa\xc9\xdf\xcb\xac\x83\x13\xbb\x21\x39\xf1\xbb\x75\x5f"+
b"\xef\x65\xbc\x39\x1f\x8b\x36\xf8\xf8\xeb\x73\x71\xfd\x55\x8b"+
b"\x01\x00\x6a\x08\xa4\x19\x03\x35\x06\x78\xe5\x85\x28\xbe\xbf"+
b"\x8a\x0b\xef\xf8\x67\xa7\xca\x36\x71\x6f\x7e\x01\xf8\x10\x52")
def generate_ecdsa(k, sha):
k = bytes_to_long(k)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
# Copyright 2008 Hector Martin <marcan@marcansoft.com>
# Licensed under the terms of the GNU GPL, version 2
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
@@ -21,7 +21,7 @@ except ImportError:
from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.Signature import pkcs1_15
import ec
from . import ec
WII_RSA4096 = 0
WII_RSA2048 = 1
@@ -30,13 +30,13 @@ WII_ECDSA = 2
sigtypes = [ "RSA-4096", "RSA-2048", "EC-DSA" ]
def load_rsa_key(issuer):
print "Loading private key for %s" % issuer
print("Loading private key for %s" % issuer)
path = os.path.join(os.environ["HOME"], ".wii", "dpki", issuer + ".pem")
return RSA.importKey(open(path, "r").read())
signkeyfuncs = [ load_rsa_key, load_rsa_key, None ]
NULL_IV = "\x00"*16
NULL_IV = b"\x00"*16
keylist = [
"common-key",
@@ -86,13 +86,13 @@ known_titles_noregion = {
}
def hexdump(s,sep=" "):
return sep.join(map(lambda x: "%02x"%ord(x),s))
return sep.join(["%02x"%x for x in s])
def strcmp(s1,s2):
clen = min(len(s1),len(s2))
for i in range(clen):
if s1[i] == "\0" and s2[i] == "\0":
if s1[i] == 0 and s2[i] == 0:
return True
if s1[i] != s2[i]:
return False
@@ -101,10 +101,10 @@ def strcmp(s1,s2):
def ascii(s):
s2 = ""
for c in s:
if ord(c)<0x20 or ord(c)>0x7e:
if c<0x20 or c>0x7e:
s2 += "."
else:
s2 += c
s2 += chr(c)
return s2
def pad(s,c,l):
@@ -114,15 +114,10 @@ def pad(s,c,l):
def chexdump(s):
for i in range(0,len(s),16):
print "%08x %s %s |%s|"%(i,pad(hexdump(s[i:i+8],' ')," ",23),pad(hexdump(s[i+8:i+16],' ')," ",23),pad(ascii(s[i:i+16])," ",16))
print("%08x %s %s |%s|"%(i,pad(hexdump(s[i:i+8],' ')," ",23),pad(hexdump(s[i+8:i+16],' ')," ",23),pad(ascii(s[i:i+16])," ",16)))
def getcstring(s):
s2 = ""
for c in s:
if c == "\x00":
break
s2 += c
return s2
return s.split(b"\x00")[0].decode("ascii")
def align(n,a):
if a == 0:
@@ -132,10 +127,10 @@ def align(n,a):
return n
def rangel(n,s):
return range(n,n+s)
return list(range(n,n+s))
def xrangel(n,s):
return xrange(n,n+s)
return range(n,n+s)
def falign(f,a):
f.seek(align(f.tell(),a))
@@ -200,7 +195,7 @@ def loadkeys(path = None):
try:
keys[key] = open(path + os.sep + key, "rb").read()
except:
print "Warning: failed to load key %s"%key
print("Warning: failed to load key %s"%key)
def loadkeys_dpki(path = None):
if path is None:
@@ -210,7 +205,7 @@ def loadkeys_dpki(path = None):
def parse_certs(blob):
certs = {}
certlist = []
while blob != "":
while blob != b"":
cert = WiiCert(blob)
certs[cert.name] = cert
certlist.append(cert)
@@ -250,7 +245,7 @@ class WiiPKAlgo:
code = ">"+codes[bytes]
matchlen = len(match)
for pad in xrange(0, 256**bytes):
for pad in range(0, 256**bytes):
pad += 0x4612512415125316
pad %= 256**bytes
padsig = signature + pack(code, pad)
@@ -270,11 +265,11 @@ class WiiRSA(WiiPKAlgo):
def get_digest(self, signature):
lsig = bytes_to_long(signature)
if lsig >= self.n:
print "Warning: signature larger than modulus, using sig%modulus as signature"
print("Warning: signature larger than modulus, using sig%modulus as signature")
ldec = pow(lsig, self.e, self.n)
dec = long_to_bytes(ldec)
pad = len(signature) - len(dec)
dec = "\x00"*pad+dec
dec = b"\x00"*pad+dec
return dec[-20:]
def sign(self, data, key):
@@ -340,11 +335,11 @@ class WiiDisc:
return self.partitions
def showinfo(self):
print "Game %s, maker %s, magic %08x: %s"%(self.gamecode, self.makercode, self.magic, self.gamename)
print("Game %s, maker %s, magic %08x: %s"%(self.gamecode, self.makercode, self.magic, self.gamename))
self.read_partitions()
print "%d partitions in ISO:"%len(self.partitions)
print("%d partitions in ISO:"%len(self.partitions))
for p_num,p_dat in enumerate(self.partitions):
print " [%2d] 0x%010x (%08x)"%(p_num,p_dat[0],p_dat[1])
print(" [%2d] 0x%010x (%08x)"%(p_num,p_dat[0],p_dat[1]))
class WiiSigned:
sigsizes = [512, 256, 60]
@@ -370,7 +365,7 @@ class WiiSigned:
def update(self):
self.data = pack(">I",self.sigtype+0x10000) + self.signature
self.data += "\x00" * (self.body_offset - len(self.data))
self.data += b"\x00" * (self.body_offset - len(self.data))
self.data += self.body
def parse(self):
@@ -388,7 +383,7 @@ class WiiSigned:
raise ValueError("Signature type %s does not match certificate type %s!"%(sigtypes[self.sigtype],sigtypes[cert.key_type]))
return cert.pkalgo.get_digest(self.sigtype, self.signature)
def brute_sha(self, match = "\x00", fillshort = None):
def brute_sha(self, match = b"\x00", fillshort = None):
l = len(match)
if fillshort is None:
@@ -408,7 +403,7 @@ class WiiSigned:
if len(issuer) > 39:
raise ValueError("issuer name too long!")
self.issuer = issuer.split("-")
self.body = issuer + "\x00" * (0x40 - len(issuer)) + self.body[0x40:]
self.body = issuer + b"\x00" * (0x40 - len(issuer)) + self.body[0x40:]
self.update()
def update_signature(self, sig):
@@ -416,7 +411,7 @@ class WiiSigned:
self.data = pack(">I",self.sigtype+0x10000) + self.signature + self.data[len(sig) + 4:]
def null_signature(self):
self.signature = "\x00"*len(self.signature)
self.signature = b"\x00"*len(self.signature)
self.data = pack(">I",self.sigtype+0x10000) + self.signature + self.data[len(self.signature) + 4:]
def sign(self,certs):
@@ -453,22 +448,22 @@ class WiiSigned:
if cert.pkalgo.can_get_digest:
signhash = cert.pkalgo.get_digest(self.signature)
if myhash == signhash:
print it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash))
print(it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
elif strcmp(myhash, signhash):
print it+"%s signed by %s using %s: %s [BUG]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash))
print it+" Signature hash: %s"%hexdump(signhash)
print(it+"%s signed by %s using %s: %s [BUG]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
print(it+" Signature hash: %s"%hexdump(signhash))
else:
print it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash))
print it+" Signature hash: %s"%hexdump(signhash)
print(it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
print(it+" Signature hash: %s"%hexdump(signhash))
else:
sigok = cert.pkalgo.check_digest(self.signature,myhash)
if sigok:
print it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash))
print(it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
else:
print it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash))
print(it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
except KeyError:
print it+"%s signed by %s using %s: %s [ISSUER NOT FOUND]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash))
print(it+"%s signed by %s using %s: %s [ISSUER NOT FOUND]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
class WiiTik(WiiSigned):
def __init__(self, data):
@@ -480,7 +475,7 @@ class WiiTik(WiiSigned):
def parse(self):
self.title_key_enc = self.body[0x7f:0x8f]
self.title_id = self.body[0x9c:0xa4]
self.title_key_iv = self.title_id + "\x00"*8
self.title_key_iv = self.title_id + b"\x00"*8
self.common_key_index = ord(self.body[0xb1:0xb2])
try:
@@ -489,7 +484,7 @@ class WiiTik(WiiSigned):
elif self.common_key_index == 1:
key = keys["korean-key"]
else:
print "WARNING: OLD FAKESIGNED TICKET WITH BAD KEY OFFSET, ASSUMING NORMAL COMMON KEY"
print("WARNING: OLD FAKESIGNED TICKET WITH BAD KEY OFFSET, ASSUMING NORMAL COMMON KEY")
key = keys["common-key"]
aes = AES.new(key, AES.MODE_CBC, self.title_key_iv)
self.title_key = aes.decrypt(self.title_key_enc)
@@ -505,13 +500,13 @@ class WiiTik(WiiSigned):
return 0x164
def showinfo(self, it=""):
print it+"ETicket: "
print it+" Title ID: "+repr(self.title_id)
print it+" Title key IV: "+hexdump(self.title_key_iv)
print it+" Title key (encrypted): "+hexdump(self.title_key_enc)
print it+" Common key index: %d" % self.common_key_index
print(it+"ETicket: ")
print(it+" Title ID: "+repr(self.title_id))
print(it+" Title key IV: "+hexdump(self.title_key_iv))
print(it+" Title key (encrypted): "+hexdump(self.title_key_enc))
print(it+" Common key index: %d" % self.common_key_index)
if self.title_key is not None:
print it+" Title key (decrypted): "+hexdump(self.title_key)
print(it+" Title key (decrypted): "+hexdump(self.title_key))
class WiiPartitionOffsets:
def __init__(self, data):
@@ -528,9 +523,9 @@ class WiiPartitionOffsets:
self.data_size = unpack(">I",self.data[0x18:0x1c])[0]<<2
def showinfo(self, it=""):
print it+"TMD @ 0x%x [0x%x], Certs @ 0x%x [0x%x], H3 @ 0x%x, Data @ 0x%x [0x%x]"%(
print(it+"TMD @ 0x%x [0x%x], Certs @ 0x%x [0x%x], H3 @ 0x%x, Data @ 0x%x [0x%x]"%(
self.tmd_offset, self.tmd_size, self.cert_offset, self.cert_size,
self.h3_offset, self.data_offset, self.data_size)
self.h3_offset, self.data_offset, self.data_size))
def update(self):
self.data = pack(">II",self.tmd_size, self.tmd_offset>>2)
@@ -600,20 +595,20 @@ class WiiTmd(WiiSigned):
self.update()
def showinfo(self,it=""):
print it+"TMD: "
print it+" Versions: %d, CA CRL %d, Signer CRL %d, System %d-%d"%(
self.version,self.ca_crl_version,self.signer_crl_version,self.sys_version>>32,self.sys_version&0xffffffff)
print it+" Title ID: %s-%s (%s-%s)"%(hexdump(self.title_id[:4],''),hexdump(self.title_id[4:],''),repr(self.title_id[:4]),repr(self.title_id[4:]))
print it+" Title Type: %d"%self.title_type
print it+" Group ID: %s"%repr(self.group_id)
print it+" Access Rights: 0x%08x"%self.access_rights
print it+" Title Version: 0x%x"%self.title_version
print it+" Boot Index: %d"%self.boot_index
print it+" Contents:"
print it+" ID Index Type Size Hash"
print(it+"TMD: ")
print(it+" Versions: %d, CA CRL %d, Signer CRL %d, System %d-%d"%(
self.version,self.ca_crl_version,self.signer_crl_version,self.sys_version>>32,self.sys_version&0xffffffff))
print(it+" Title ID: %s-%s (%s-%s)"%(hexdump(self.title_id[:4],''),hexdump(self.title_id[4:],''),repr(self.title_id[:4]),repr(self.title_id[4:])))
print(it+" Title Type: %d"%self.title_type)
print(it+" Group ID: %s"%repr(self.group_id))
print(it+" Access Rights: 0x%08x"%self.access_rights)
print(it+" Title Version: 0x%x"%self.title_version)
print(it+" Boot Index: %d"%self.boot_index)
print(it+" Contents:")
print(it+" ID Index Type Size Hash")
for ct in self.get_content_records():
print it+" %08X %-5d 0x%-5x %-12s %s"%(ct.cid, ct.index, ct.ftype, "0x%x"%ct.size,hexdump(ct.sha))
print(it+" %08X %-5d 0x%-5x %-12s %s"%(ct.cid, ct.index, ct.ftype, "0x%x"%ct.size,hexdump(ct.sha)))
class WiiCert(WiiSigned):
key_sizes = [516, 260, 60]
@@ -638,7 +633,7 @@ class WiiCert(WiiSigned):
self.pkalgo = self.pk_types[self.key_type](self.key)
def showinfo(self,it=""):
print it+"%s (%s)"%(self.name,sigtypes[self.key_type])
print(it+"%s (%s)"%(self.name,sigtypes[self.key_type]))
class WiiRootCert:
def __init__(self, data):
@@ -650,7 +645,7 @@ class WiiRootCert:
self.key_type = 0
def showinfo(self,it=""):
print it+"%s (%s)"%(self.name,sigtypes[self.key_type])
print(it+"%s (%s)"%(self.name,sigtypes[self.key_type]))
class WiiPartition:
BLOCKS_PER_SUBGROUP = 8
@@ -732,37 +727,37 @@ class WiiPartition:
self.f.write(self.offsets.data)
def showinfo(self,it=""):
print it+"Wii Partition at 0x%010x:"%(self.offset)
print(it+"Wii Partition at 0x%010x:"%(self.offset))
self.offsets.showinfo(" ")
self.tik.showinfo(it+" ")
self.tik.showsig(self.certs,it+" ")
self.tmd.showinfo(it+" ")
self.tmd.showsig(self.certs,it+" ")
if self.checkh4hash():
print it+" H4 hash check passed"
print(it+" H4 hash check passed")
else:
print it+" H4 check failed: SHA1(H3) = "+hexdump(self.geth4hash())
print it+" Data:"
print it+" Blocks: %d"%self.data_blocks
print it+" Subgroups: %d (plus %d blocks)"%(self.data_subgroups,self.extra_subgroup_blocks)
print it+" Groups: %d (plus %d blocks)"%(self.data_groups,self.extra_group_blocks)
print(it+" H4 check failed: SHA1(H3) = "+hexdump(self.geth4hash()))
print(it+" Data:")
print(it+" Blocks: %d"%self.data_blocks)
print(it+" Subgroups: %d (plus %d blocks)"%(self.data_subgroups,self.extra_subgroup_blocks))
print(it+" Groups: %d (plus %d blocks)"%(self.data_groups,self.extra_group_blocks))
self.showcerts(it+" ")
def showcerts(self,it=""):
print it+"Certificates: "
print(it+"Certificates: ")
for cert in self.certlist:
cert.showinfo(it+" - ")
cert.showsig(self.certs,it+" ")
def geth4hash(self):
return SHA.new(''.join(self.h3) + "\x00"*self.TAIL_H3).digest()
return SHA.new(b''.join(self.h3) + b"\x00"*self.TAIL_H3).digest()
def checkh4hash(self):
return self.geth4hash() == self.tmd.get_content_records()[0].sha
def updateh3(self):
self._seek(self.offsets.h3_offset)
self.f.write(''.join(self.h3))
self.f.write(b''.join(self.h3))
def updateh4(self):
cr = self.tmd.get_content_records()[0]
@@ -903,7 +898,7 @@ class WiiPartition:
else:
raise ValueError("Attempted to read group past the end of the partition data")
data = ""
data = b""
for i in range(nblocks):
data += self.readblock(blockoff+i)
return data
@@ -919,7 +914,7 @@ class WiiPartition:
if groupnum == self.data_groups and self.extra_group_blocks > 0 and len(data) == (self.extra_group_blocks * self.PLAIN_BLOCK_SIZE):
blocks = self.extra_group_blocks
writesize = blocks * self.CIPHER_BLOCK_SIZE
data += "\x00" * (self.PLAIN_BLOCK_SIZE * self.BLOCKS_PER_GROUP - blocks)
data += b"\x00" * (self.PLAIN_BLOCK_SIZE * self.BLOCKS_PER_GROUP - blocks)
else:
raise ValueError("Attempted to write group past the end of the partition data")
else:
@@ -930,12 +925,12 @@ class WiiPartition:
h0 = []
h1 = []
h2 = ""
h2 = b""
for subgroup in range(self.SUBGROUPS_PER_GROUP):
bh1 = ""
bh1 = b""
sh0 = []
for block in range(self.BLOCKS_PER_SUBGROUP):
bh0 = ""
bh0 = b""
for chunk in range(self.DATA_CHUNKS_PER_BLOCK):
offset = subgroup * self.PLAIN_SUBGROUP_SIZE + block * self.PLAIN_BLOCK_SIZE + chunk * self.DATA_CHUNK_SIZE
bh0 += SHA.new(data[offset:offset+self.DATA_CHUNK_SIZE]).digest()
@@ -946,16 +941,16 @@ class WiiPartition:
h2 += SHA.new(bh1).digest()
h3 = SHA.new(h2).digest()
data_out = ""
data_out = b""
for subgroup in range(self.SUBGROUPS_PER_GROUP):
for block in range(self.BLOCKS_PER_SUBGROUP):
shablock = ""
shablock += h0[subgroup][block]
shablock += "\x00"*20
shablock += b"\x00"*20
shablock += h1[subgroup]
shablock += "\x00"*32
shablock += b"\x00"*32
shablock += h2
shablock += "\x00"*32
shablock += b"\x00"*32
assert len(shablock) == self.SHA_SIZE, "sha block size messed up"
aes = AES.new(self.tik.title_key, AES.MODE_CBC, NULL_IV)
shablock = aes.encrypt(shablock)
@@ -1019,7 +1014,7 @@ class WiiCachedPartition(WiiPartition):
def _dprint(self, s, *args):
if self.debug:
print s%tuple(args)
print(s%tuple(args))
def _readblock(self, blocknum):
self._dprint("_readblock(0x%x)",blocknum)
@@ -1174,7 +1169,7 @@ class WiiCachedPartition(WiiPartition):
hb = self.readblock(bstart - 1)
hb = hb[:hdroff] + data[:header] + hb[hdroff+header:]
self.writeblock(bstart - 1, hb)
for block in xrange(bnum):
for block in range(bnum):
self.writeblock(block+bstart, data[header+block*self.PLAIN_BLOCK_SIZE:header+(block+1)*self.PLAIN_BLOCK_SIZE])
if footer:
fb = self.readblock(bstart+bnum)
@@ -1246,11 +1241,11 @@ class WiiApploader:
self.extrafooter = data[0x20+self.textsize+self.trailersize:]
def showinfo(self, it=""):
print it+"Apploader:"
print it+" Date: %s"%self.date
print it+" Entrypoint: 0x%08x"%self.entry
print it+" Text size: 0x%x"%self.textsize
print it+" Trailer size: 0x%x"%self.trailersize
print(it+"Apploader:")
print(it+" Date: %s"%self.date)
print(it+" Entrypoint: 0x%08x"%self.entry)
print(it+" Text size: 0x%x"%self.textsize)
print(it+" Trailer size: 0x%x"%self.trailersize)
class WiiPartitionData:
def __init__(self, partition):
@@ -1291,11 +1286,11 @@ class WiiPartitionData:
self.dol = dol
self.part.write(self.doloff, dol)
def showinfo(self,it=""):
print it+"Partition data:"
print it+" Game Name: %s"%self.gamename
print it+" Offsets: DOL @ 0x%x [0x%x], Apploader @ 0x%x [0x%x], FST @ 0x%x [0x%x]"%(self.doloff, self.dolsize, 0x2440, self.apploadersize, self.fstoff, self.fstsize)
print(it+"Partition data:")
print(it+" Game Name: %s"%self.gamename)
print(it+" Offsets: DOL @ 0x%x [0x%x], Apploader @ 0x%x [0x%x], FST @ 0x%x [0x%x]"%(self.doloff, self.dolsize, 0x2440, self.apploadersize, self.fstoff, self.fstsize))
self.apploader.showinfo(it+" ")
print it+"FST:"
print(it+"FST:")
self.fst.show(it+" ")
class FakeFile:
@@ -1381,7 +1376,7 @@ class WiiWad:
self.f.seek(4)
wt = self.f.read(2)
if wt == "\x00\x00":
if wt == b"\x00\x00":
self.read_boot2hdr()
else:
self.read_hdr()
@@ -1389,7 +1384,7 @@ class WiiWad:
certdata = self.f.read(self.cert_len)
self.certlist = []
self.certs = {}
while certdata != "":
while certdata != b"":
cert = WiiCert(certdata)
self.certs[cert.name] = cert
self.certlist.append(cert)
@@ -1415,8 +1410,8 @@ class WiiWad:
self.f.write(self.tik.data)
def showinfo(self,it=""):
print it+"Wii Wad:"
print it+" Header 0x%x Type %s Certs 0x%x Tik 0x%x TMD 0x%x Data 0x%x @ 0x%x Footer 0x%x"%(self.hdr_len, repr(self.wadtype), self.cert_len, self.tik_len, self.tmd_len, self.data_len, self.data_off, self.footer_len)
print(it+"Wii Wad:")
print(it+" Header 0x%x Type %s Certs 0x%x Tik 0x%x TMD 0x%x Data 0x%x @ 0x%x Footer 0x%x"%(self.hdr_len, repr(self.wadtype), self.cert_len, self.tik_len, self.tmd_len, self.data_len, self.data_off, self.footer_len))
self.tik.showinfo(it+" ")
self.tik.showsig(self.certs,it+" ")
self.tmd.showinfo(it+" ")
@@ -1426,15 +1421,15 @@ class WiiWad:
d = self.getcontent(ct.index)
sha = SHA.new(d).digest()
if sha != ct.sha:
print it+" SHA-1 for content %08x is invalid:"%ct.cid, hexdump(sha)
print it+" Expected:",hexdump(ct.sha)
print(it+" SHA-1 for content %08x is invalid:"%ct.cid, hexdump(sha))
print(it+" Expected:",hexdump(ct.sha))
allok=False
if allok:
print it+" All content SHA-1 hashes are valid"
print(it+" All content SHA-1 hashes are valid")
self.showcerts(it+" ")
def showcerts(self,it=""):
print it+"Certificates: "
print(it+"Certificates: ")
for cert in self.certlist:
cert.showinfo(it+" - ")
cert.showsig(self.certs,it+" ")
@@ -1447,7 +1442,7 @@ class WiiWad:
if encrypted:
return data
iv = pack(">H",index)+"\x00"*14
iv = pack(">H",index)+b"\x00"*14
aes = AES.new(self.tik.title_key, AES.MODE_CBC, iv)
return aes.decrypt(data)[:ct.size]
@@ -1470,14 +1465,14 @@ class WiiWadMaker(WiiWad):
self.tik_len = len(self.tik.data)
# if boot2, set type to "ib"
if self.tmd.title_id == "\x00\x00\x00\x01\x00\x00\x00\x01":
if self.tmd.title_id == b"\x00\x00\x00\x01\x00\x00\x00\x01":
if nandwad:
self.wadtype = 0
self.ALIGNMENT = 0
else:
self.wadtype = "ib"
self.wadtype = b"ib"
else:
self.wadtype = "Is"
self.wadtype = b"Is"
self.data_len = 0
self.footer = footer
@@ -1509,16 +1504,16 @@ class WiiWadMaker(WiiWad):
cr.size = len(data)
self.tmd.update_content_record(i,cr)
if len(data)%16 != 0:
data += "\x00"*(16-len(data)%16)
data += b"\x00"*(16-len(data)%16)
falign(self.f,0x40)
iv = pack(">H",cr.index)+"\x00"*14
iv = pack(">H",cr.index)+b"\x00"*14
aes = AES.new(self.tik.title_key, AES.MODE_CBC, iv)
self.f.write(aes.encrypt(data))
falign(self.f,0x40)
def adddata_encrypted(self, data):
if len(data)%16 != 0:
data += "\x00"*(16-len(data)%16)
data += b"\x00"*(16-len(data)%16)
falign(self.f,0x40)
self.f.write(data)
falign(self.f,0x40)
@@ -1531,7 +1526,7 @@ class WiiWadMaker(WiiWad):
falign(self.f,self.ALIGNMENT)
self.f.truncate()
if pad:
self.f.write("\x00"*0x40)
self.f.write(b"\x00"*0x40)
self.updatetmd()
self.f.seek(0)
if self.wadtype == 0:
@@ -1641,9 +1636,9 @@ class WiiFSTFile:
self.off = off
self.size = size
def show(self, it=""):
print "%s%s @ 0x%x [0x%x]"%(it,self.name,self.off,self.size)
print("%s%s @ 0x%x [0x%x]"%(it,self.name,self.off,self.size))
def generate(self, offset, stringoff, parent, dataoff, wiigcm=False):
stringdata = self.name + "\x00"
stringdata = self.name.encode("ascii") + b"\x00"
off = self.off+dataoff
if wiigcm:
off >>= 2
@@ -1688,9 +1683,9 @@ class WiiFSTDir:
raise ValueError("WTF")
def show(self, it=""):
if self.name == "":
print it+"/"
print(it+"/")
else:
print it+self.name+"/"
print(it+self.name+"/")
for i in self.entries:
i.show(it+self.name+"/")
def dump(self):
@@ -1698,15 +1693,15 @@ class WiiFSTDir:
def add(self,x):
self.entries.append(x)
def generate(self, offset, stringoff, parent, dataoff, wiigcm=False):
stringdata = self.name + "\x00"
stringdata = self.name.encode("ascii") + b"\x00"
myoff = offset
mysoff = stringoff
stringoff+=len(stringdata)
offset += 1
subdata=""
subdata=b""
for e in self.entries:
d, s = e.generate(offset, stringoff, myoff, dataoff, wiigcm)
offset += len(d)/12
offset += len(d)//12
stringoff += len(s)
stringdata += s
subdata += d

View File

@@ -1,11 +1,11 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys
import re
import pywii as wii
hash = wii.SHA.new(open(sys.argv[2]).read()).digest().encode("hex")
f = open(sys.argv[1], "r")
f = open(sys.argv[1], "rb")
data = f.read()
f.close()
data = re.sub('@SHA1SUM@', hash, data)
open(sys.argv[3], "w").write(data)
open(sys.argv[3], "wb").write(data)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path, struct
import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path, struct
import pywii as wii
@@ -7,20 +7,24 @@ fstb = wii.WiiFSTBuilder(0x20)
fstb.addfrom(sys.argv[2])
arc = open(sys.argv[1],"wb")
# dummy generate to get length
fstlen = len(fstb.fst.generate())
dataoff = wii.align(0x20+fstlen,0x20)
fst = fstb.fst.generate(dataoff)
try:
arc = open(sys.argv[1],"wb")
# dummy generate to get length
fstlen = len(fstb.fst.generate())
dataoff = wii.align(0x20+fstlen,0x20)
fst = fstb.fst.generate(dataoff)
hdr = struct.pack(">IIII16x",0x55AA382d,0x20,fstlen,dataoff)
arc.write(hdr)
hdr = struct.pack(">IIII16x",0x55AA382d,0x20,fstlen,dataoff)
arc.write(hdr)
arc.write(fst)
wii.falign(arc,0x20)
for f in fstb.files:
data = open(f, "rb").read()
arc.write(data)
arc.write(fst)
wii.falign(arc,0x20)
for f in fstb.files:
data = open(f, "rb").read()
arc.write(data)
wii.falign(arc,0x20)
arc.close()
arc.close()
except:
os.remove(sys.argv[1])
raise

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -15,12 +15,12 @@ certfile = args.pop(0)
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "Certification file %s: " % certfile
print("Certification file %s: " % certfile)
cert = wii.WiiCert(open(certfile, "rb").read())
cert.showinfo(" ")
cert.showsig(certs," ")
print "Certificates:"
print("Certificates:")
for cert in certlist:
cert.showinfo(" - ")
cert.showsig(certs," ")

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -11,7 +11,7 @@ disc.showinfo()
partitions = disc.read_partitions()
parts = range(len(partitions))
parts = list(range(len(partitions)))
try:
pnum = int(sys.argv[2])

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii
@@ -17,7 +17,7 @@ if sys.argv[1] == "-cetk":
elif sys.argv[1] == "-tmd":
signed = pywii.WiiTmd(open(infile, "rb").read())
else:
print "EYOUFAILIT"
print("EYOUFAILIT")
sys.exit(1)
certs, certlist = pywii.parse_certs(open(certfile).read())
@@ -25,11 +25,11 @@ certs, certlist = pywii.parse_certs(open(certfile).read())
signed.update_issuer(issuer)
if not signed.sign(certs):
print "dpki signing failed"
print("dpki signing failed")
sys.exit(1)
open(outfile, "wb").write(signed.data)
print "successfully signed %s" % outfile
print("successfully signed %s" % outfile)
sys.exit(0)

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys
import pywii as wii
if len(sys.argv) != 3:
print "Usage: %s keyfile.[priv|pub] infile"%sys.argv[0]
print("Usage: %s keyfile.[priv|pub] infile"%sys.argv[0])
sys.exit(1)
if sys.argv[1] == "-":
@@ -12,46 +12,46 @@ if sys.argv[1] == "-":
else:
k = open(sys.argv[1],"rb").read()
if len(k) not in (30,60):
print "Failed to read key"
print("Failed to read key")
sys.exit(2)
if len(k) == 30:
print "Key is a private key, generating public key..."
print("Key is a private key, generating public key...")
q = wii.ec.priv_to_pub(k)
else:
q = k
print "Public key:"
print("Public key:")
pq = q.encode('hex')
print "X =",pq[:30]
print " ",pq[30:60]
print "Y =",pq[60:90]
print " ",pq[90:]
print
print("X =",pq[:30])
print(" ",pq[30:60])
print("Y =",pq[60:90])
print(" ",pq[90:])
print()
indata = open(sys.argv[2],"rb").read()
if len(indata) < 64 or indata[:4] != "SIG0":
print "Invalid header"
print("Invalid header")
sys.exit(3)
r = indata[4:34]
s = indata[34:64]
sha = wii.SHA.new(indata[64:]).digest()
print "SHA1: %s"%sha.encode('hex')
print("SHA1: %s"%sha.encode('hex'))
print
print "Signature:"
print "R =",r[:15].encode('hex')
print " ",r[15:].encode('hex')
print "S =",s[:15].encode('hex')
print " ",s[15:].encode('hex')
print
print()
print("Signature:")
print("R =",r[:15].encode('hex'))
print(" ",r[15:].encode('hex'))
print("S =",s[:15].encode('hex'))
print(" ",s[15:].encode('hex'))
print()
if wii.ec.check_ecdsa(q,r,s,sha):
print "Signature is VALID"
print("Signature is VALID")
else:
print "Signature is INVALID"
print("Signature is INVALID")
sys.exit(4)

View File

@@ -1,33 +1,33 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os
import pywii as wii
if len(sys.argv) != 2:
print "Usage: %s keyfile.priv"%sys.argv[0]
print("Usage: %s keyfile.priv"%sys.argv[0])
sys.exit(1)
print "Generating private key..."
print("Generating private key...")
k = wii.ec.gen_priv_key()
print "Private key:"
print("Private key:")
pk = k.encode('hex')
print "K =",pk[:30]
print " ",pk[30:]
print("K =",pk[:30])
print(" ",pk[30:])
print
print "Corresponding public key:"
print()
print("Corresponding public key:")
q = wii.ec.priv_to_pub(k)
pq = q.encode('hex')
print "X =",pq[:30]
print " ",pq[30:60]
print "Y =",pq[60:90]
print " ",pq[90:]
print("X =",pq[:30])
print(" ",pq[30:60])
print("Y =",pq[60:90])
print(" ",pq[90:])
fd = open(sys.argv[1],"wb")
os.fchmod(fd.fileno(), 0o600)
fd.write(k)
fd.close()
print "Saved private key to %s"%sys.argv[1]
print("Saved private key to %s"%sys.argv[1])

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys
import pywii as wii
if len(sys.argv) not in (2,3):
print "Usage: %s keyfile.priv [keyfile.pub]"%sys.argv[0]
print("Usage: %s keyfile.priv [keyfile.pub]"%sys.argv[0])
sys.exit(1)
if sys.argv[1] == "-":
@@ -12,19 +12,19 @@ if sys.argv[1] == "-":
else:
k = open(sys.argv[1],"rb").read()
if len(k) != 30:
print "Failed to read private key"
print("Failed to read private key")
sys.exit(2)
print "Public key:"
print("Public key:")
q = wii.ec.priv_to_pub(k)
pq = q.encode('hex')
print "X =",pq[:30]
print " ",pq[30:60]
print "Y =",pq[60:90]
print " ",pq[90:]
print("X =",pq[:30])
print(" ",pq[30:60])
print("Y =",pq[60:90])
print(" ",pq[90:])
if len(sys.argv) == 3:
fd = open(sys.argv[2],"wb")
fd.write(q)
fd.close()
print "Saved public key to %s"%sys.argv[2]
print("Saved public key to %s"%sys.argv[2])

View File

@@ -1,10 +1,9 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys
import pywii as wii
if len(sys.argv) != 4:
print "Usage: %s keyfile.priv infile outfile"%sys.argv[0]
print("Usage: %s keyfile.priv infile outfile"%sys.argv[0])
sys.exit(1)
if sys.argv[1] == "-":
@@ -13,20 +12,20 @@ else:
k = open(sys.argv[1],"rb").read()
if len(k) != 30:
print "Failed to read private key"
print("Failed to read private key")
sys.exit(2)
indata = open(sys.argv[2],"rb").read()
sha = wii.SHA.new(indata).digest()
print "SHA1: %s"%sha.encode('hex')
print
print "Signature:"
print("SHA1: %s"%sha.encode('hex'))
print()
print("Signature:")
r,s = wii.ec.generate_ecdsa(k,sha)
print "R =",r[:15].encode('hex')
print " ",r[15:].encode('hex')
print "S =",s[:15].encode('hex')
print " ",s[15:].encode('hex')
print("R =",r[:15].encode('hex'))
print(" ",r[15:].encode('hex'))
print("S =",s[:15].encode('hex'))
print(" ",s[15:].encode('hex'))
outdata = "SIG0" + r + s + indata

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -11,8 +11,8 @@ def parseint(d):
return int(d)
if len(sys.argv) < 4 or len(sys.argv) > 7:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <file to extract to> [Partition offset] [length]"%sys.argv[0]
print("Usage:")
print(" python %s <encrypted ISO> <partition number> <file to extract to> [Partition offset] [length]"%sys.argv[0])
sys.exit(1)
iso_name, partno, data_name = sys.argv[1:4]
@@ -27,19 +27,19 @@ if len(sys.argv) == 6:
copy_length = parseint(sys.argv[5])
if copy_length is not None and copy_length < 0:
print "Error: negative copy length"
print("Error: negative copy length")
sys.exit(1)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False, checkhash=False)
if part_offset >= part.data_bytes:
print "Error: Offset past end of partition"
print("Error: Offset past end of partition")
sys.exit(1)
if copy_length is None:
copy_length = part.data_bytes - part_offset
if copy_length > (part.data_bytes - part_offset):
print "Error: Length too large"
print("Error: Length too large")
sys.exit(1)
dataf = open(data_name, "wb")
@@ -49,7 +49,7 @@ while left > 0:
blocklen = min(left, 4*1024*1024)
d = part.read(offset, blocklen)
if len(d) != blocklen:
print "Part EOF reached!"
print("Part EOF reached!")
sys.exit(1)
dataf.write(d)
offset += blocklen

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
import sys, os, os.path
sys.path.append(os.path.realpath(os.path.dirname(sys.argv[0]))+"/../Common")
@@ -7,8 +7,8 @@ import pywii as wii
wii.loadkeys(os.environ["HOME"]+os.sep+".wii")
if len(sys.argv) != 4:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <dol output>"%sys.argv[0]
print("Usage:")
print(" python %s <encrypted ISO> <partition number> <dol output>"%sys.argv[0])
sys.exit(1)
iso_name, partno, dol_name = sys.argv[1:4]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -11,8 +11,8 @@ def parseint(d):
return int(d)
if len(sys.argv) < 4 or len(sys.argv) > 7:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <root path to extract to> "%sys.argv[0]
print("Usage:")
print(" python %s <encrypted ISO> <partition number> <root path to extract to> "%sys.argv[0])
sys.exit(1)
iso_name, partno, data_name = sys.argv[1:4]
@@ -27,19 +27,19 @@ if len(sys.argv) == 6:
copy_length = parseint(sys.argv[5])
if copy_length is not None and copy_length < 0:
print "Error: negative copy length"
print("Error: negative copy length")
sys.exit(1)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False, checkhash=False)
if part_offset >= part.data_bytes:
print "Error: Offset past end of partition"
print("Error: Offset past end of partition")
sys.exit(1)
if copy_length is None:
copy_length = part.data_bytes - part_offset
if copy_length > (part.data_bytes - part_offset):
print "Error: Length too large"
print("Error: Length too large")
sys.exit(1)
dataf = open(data_name, "wb")
@@ -49,7 +49,7 @@ while left > 0:
blocklen = min(left, 4*1024*1024)
d = part.read(offset, blocklen)
if len(d) != blocklen:
print "Part EOF reached!"
print("Part EOF reached!")
sys.exit(1)
dataf.write(d)
offset += blocklen

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -6,8 +6,8 @@ import pywii as wii
wii.loadkeys()
if len(sys.argv) != 5:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <apploader text> <apploader trailer>"%sys.argv[0]
print("Usage:")
print(" python %s <encrypted ISO> <partition number> <apploader text> <apploader trailer>"%sys.argv[0])
sys.exit(1)
iso_name, partno, app_name, trail_name = sys.argv[1:5]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -11,8 +11,8 @@ def parseint(d):
return int(d)
if len(sys.argv) < 4 or len(sys.argv) > 7:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <file to inject> [Partition offset] [data offset] [length]"%sys.argv[0]
print("Usage:")
print(" python %s <encrypted ISO> <partition number> <file to inject> [Partition offset] [data offset] [length]"%sys.argv[0])
sys.exit(1)
iso_name, partno, data_name = sys.argv[1:4]
@@ -34,10 +34,10 @@ if copy_length == None:
copy_length = data_len - data_offset
copy_end = data_offset + copy_length
if copy_length < 0:
print "Error: negative copy length"
print("Error: negative copy length")
sys.exit(1)
if copy_end > data_len:
print "Error: data file is too small"
print("Error: data file is too small")
sys.exit(1)
disc = wii.WiiDisc(iso_name)
@@ -52,7 +52,7 @@ while left > 0:
blocklen = min(left, 4*1024*1024)
d = dataf.read(blocklen)
if len(d) != blocklen:
print "File EOF reached!"
print("File EOF reached!")
sys.exit(1)
part.write(offset, d)
offset += blocklen

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -6,8 +6,8 @@ import pywii as wii
wii.loadkeys()
if len(sys.argv) != 4:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <dol to inject>"%sys.argv[0]
print("Usage:")
print(" python %s <encrypted ISO> <partition number> <dol to inject>"%sys.argv[0])
sys.exit(1)
iso_name, partno, dol_name = sys.argv[1:4]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -6,9 +6,9 @@ import pywii as wii
wii.loadkeys()
if len(sys.argv) != 4:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <IOS version>"%sys.argv[0]
print " IOS version should be just the minor number (16, 33, etc) in decimal"
print("Usage:")
print(" python %s <encrypted ISO> <partition number> <IOS version>"%sys.argv[0])
print(" IOS version should be just the minor number (16, 33, etc) in decimal")
sys.exit(1)
iso_name, partno, ios = sys.argv[1:4]

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
def hexdump(s):
return ' '.join(map(lambda x: "%02x"%x,map(ord,s)))
return ' '.join(["%02x"%x for x in list(map(ord,s))])
isofile = sys.argv[1]
disc = WiiDisc(isofile)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -6,7 +6,7 @@ import pywii as wii
wii.loadkeys()
tikfile = sys.argv[1]
print "fixing Tik file %s " % tikfile
print("fixing Tik file %s " % tikfile)
tik = wii.WiiTik(open(tikfile, "rb").read())
tik.null_signature()
tik.brute_sha()

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -17,12 +17,12 @@ certs = None
if len(args) > 0:
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "ETicket file %s:"%tikfile
print("ETicket file %s:"%tikfile)
tik = wii.WiiTik(open(tikfile, "rb").read())
tik.showinfo(" ")
if certs is not None:
tik.showsig(certs," ")
print "Certificates:"
print("Certificates:")
for cert in certlist:
cert.showinfo(" - ")
cert.showsig(certs," ")

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -6,7 +6,7 @@ import pywii as wii
wii.loadkeys()
tmdfile = sys.argv[1]
print "TMD file %s:"%tmdfile
print("TMD file %s:"%tmdfile)
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.null_signature()
tmd.brute_sha()

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -17,12 +17,12 @@ certs = None
if len(args) > 0:
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "TMD file %s:"%tmdfile
print("TMD file %s:"%tmdfile)
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.showinfo(" ")
if certs is not None:
tmd.showsig(certs," ")
print "Certificates:"
print("Certificates:")
for cert in certlist:
cert.showinfo(" - ")
cert.showsig(certs," ")

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -14,7 +14,7 @@ args = sys.argv[1:]
tmdfile = args.pop(0)
indir = args.pop(0)
print "updating content records of TMD file %s" % tmdfile
print("updating content records of TMD file %s" % tmdfile)
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
for i, cr in enumerate(tmd.get_content_records()):

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii
@@ -14,7 +14,7 @@ if len(args) == 2:
else:
newvers = int(args.pop(0), 16)
print "setting version of TMD file %s to 0x%04x" % (tmdfile, newvers)
print("setting version of TMD file %s to 0x%04x" % (tmdfile, newvers))
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.title_version = newvers
tmd.update()

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
import sys, os, os.path
import pywii as wii