mirror of
https://gitlab.com/Nanolx/qwad.git
synced 2024-11-22 02:29:18 +01:00
import rev14 of original Qwad
This commit is contained in:
commit
5e8cf2a477
26
CHANGELOG.txt
Normal file
26
CHANGELOG.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
CHANGELOG
|
||||||
|
--0.3--(in development)
|
||||||
|
*Updated some porject's files which still referenced wii signer
|
||||||
|
*Added application's name and organization
|
||||||
|
*Now NUS title combobox is displayed sorteed
|
||||||
|
*Fixed everyone votes channel not returning a correct titleid
|
||||||
|
*Added some IOS to the dictionary
|
||||||
|
*Now can display the data stored in a TMD file.
|
||||||
|
|
||||||
|
-- 0.2 --
|
||||||
|
Major rewrite and refactoring of code.
|
||||||
|
|
||||||
|
*Backend changed from Wii Signer to the awesome Wii.py
|
||||||
|
*Added support form downloading and packing wads from NUS
|
||||||
|
*Added statusbar
|
||||||
|
*Now the backend runs in a different thread
|
||||||
|
|
||||||
|
Known bugs:
|
||||||
|
*Title names amb some statusbar messages don't get translated
|
||||||
|
*Title dictionary is incomplete. Additionally, there may be titles in the combobox which aren't actually in the NUS.
|
||||||
|
|
||||||
|
-- 0.1.1 Now with a windows port! --
|
||||||
|
*Fixed open modes and paths in order to work in Windows
|
||||||
|
*Independization from Wii Signer, due to needed changes to the original code. Now Qwad isn't a frontend anymore.
|
||||||
|
|
||||||
|
-- 0.1 - First public version --
|
28
GUI/AboutQwad.py
Normal file
28
GUI/AboutQwad.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Module implementing AboutQwad.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from PyQt4.QtGui import QDialog
|
||||||
|
from PyQt4.QtCore import pyqtSignature
|
||||||
|
|
||||||
|
from Ui_AboutQwad import Ui_Dialog
|
||||||
|
|
||||||
|
def Version():
|
||||||
|
return "0.2+svn"
|
||||||
|
def Author():
|
||||||
|
return "ssorgatem <ssorgatem@esdebian.org>"
|
||||||
|
|
||||||
|
class AboutQwad(QDialog, Ui_Dialog):
|
||||||
|
"""
|
||||||
|
Class documentation goes here.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
"""
|
||||||
|
QDialog.__init__(self, parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
self.versionNumber.setText(Version())
|
||||||
|
self.AuthorName.setText(Author())
|
864
GUI/AboutQwad.ui
Normal file
864
GUI/AboutQwad.ui
Normal file
@ -0,0 +1,864 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Dialog</class>
|
||||||
|
<widget class="QDialog" name="Dialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>441</width>
|
||||||
|
<height>496</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="../Qwad.qrc">
|
||||||
|
<normaloff>:/icons/wad.png</normaloff>:/icons/wad.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedStates"/>
|
||||||
|
</property>
|
||||||
|
<widget class="QLabel" name="QwadIcon">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>150</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>131</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../Qwad.qrc">:/icons/wad.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="Qwad_name">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>170</x>
|
||||||
|
<y>110</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>51</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:24pt; font-weight:600;">Qwad</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="Version">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>180</x>
|
||||||
|
<y>150</y>
|
||||||
|
<width>51</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Version</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="byAuthor">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>70</x>
|
||||||
|
<y>170</y>
|
||||||
|
<width>51</width>
|
||||||
|
<height>20</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedKingdom"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Author: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="versionNumber">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>230</x>
|
||||||
|
<y>150</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="AuthorName">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>120</x>
|
||||||
|
<y>170</y>
|
||||||
|
<width>311</width>
|
||||||
|
<height>20</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QTabWidget" name="abuttabs">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>281</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="licensetab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>License</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QTextEdit" name="textEdit">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>411</width>
|
||||||
|
<height>231</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="undoRedoEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="html">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> GNU GENERAL PUBLIC LICENSE</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Version 3, 29 June 2007</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Everyone is permitted to copy and distribute verbatim copies</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> of this license document, but changing it is not allowed.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Preamble</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The GNU General Public License is a free, copyleft license for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">software and other kinds of works.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The licenses for most software and other practical works are designed</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to take away your freedom to share and change the works. By contrast,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the GNU General Public License is intended to guarantee your freedom to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">share and change all versions of a program--to make sure it remains free</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">software for all its users. We, the Free Software Foundation, use the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GNU General Public License for most of our software; it applies also to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">any other work released this way by its authors. You can apply it to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">your programs, too.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> When we speak of free software, we are referring to freedom, not</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">price. Our General Public Licenses are designed to make sure that you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">have the freedom to distribute copies of free software (and charge for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">them if you wish), that you receive source code or can get it if you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">want it, that you can change the software or use pieces of it in new</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">free programs, and that you know you can do these things.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> To protect your rights, we need to prevent others from denying you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">these rights or asking you to surrender the rights. Therefore, you have</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">certain responsibilities if you distribute copies of the software, or if</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">you modify it: responsibilities to respect the freedom of others.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> For example, if you distribute copies of such a program, whether</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">gratis or for a fee, you must pass on to the recipients the same</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">freedoms that you received. You must make sure that they, too, receive</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">or can get the source code. And you must show them these terms so they</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">know their rights.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Developers that use the GNU GPL protect your rights with two steps:</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) assert copyright on the software, and (2) offer you this License</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">giving you legal permission to copy, distribute and/or modify it.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> For the developers' and authors' protection, the GPL clearly explains</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">that there is no warranty for this free software. For both users' and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">authors' sake, the GPL requires that modified versions be marked as</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">changed, so that their problems will not be attributed erroneously to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">authors of previous versions.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Some devices are designed to deny users access to install or run</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">modified versions of the software inside them, although the manufacturer</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">can do so. This is fundamentally incompatible with the aim of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">protecting users' freedom to change the software. The systematic</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">pattern of such abuse occurs in the area of products for individuals to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">use, which is precisely where it is most unacceptable. Therefore, we</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">have designed this version of the GPL to prohibit the practice for those</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">products. If such problems arise substantially in other domains, we</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">stand ready to extend this provision to those domains in future versions</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of the GPL, as needed to protect the freedom of users.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Finally, every program is threatened constantly by software patents.</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">States should not allow patents to restrict development and use of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">software on general-purpose computers, but in those that do, we wish to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">avoid the special danger that patents applied to a free program could</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">make it effectively proprietary. To prevent this, the GPL assures that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">patents cannot be used to render the program non-free.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The precise terms and conditions for copying, distribution and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">modification follow.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> TERMS AND CONDITIONS</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 0. Definitions.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> "This License" refers to version 3 of the GNU General Public License.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> "Copyright" also means copyright-like laws that apply to other kinds of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">works, such as semiconductor masks.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> "The Program" refers to any copyrightable work licensed under this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License. Each licensee is addressed as "you". "Licensees" and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">"recipients" may be individuals or organizations.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> To "modify" a work means to copy from or adapt all or part of the work</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in a fashion requiring copyright permission, other than the making of an</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">exact copy. The resulting work is called a "modified version" of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">earlier work or a work "based on" the earlier work.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A "covered work" means either the unmodified Program or a work based</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">on the Program.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> To "propagate" a work means to do anything with it that, without</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">permission, would make you directly or secondarily liable for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">infringement under applicable copyright law, except executing it on a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">computer or modifying a private copy. Propagation includes copying,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">distribution (with or without modification), making available to the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">public, and in some countries other activities as well.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> To "convey" a work means any kind of propagation that enables other</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">parties to make or receive copies. Mere interaction with a user through</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">a computer network, with no transfer of a copy, is not conveying.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> An interactive user interface displays "Appropriate Legal Notices"</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to the extent that it includes a convenient and prominently visible</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">feature that (1) displays an appropriate copyright notice, and (2)</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tells the user that there is no warranty for the work (except to the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">extent that warranties are provided), that licensees may convey the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">work under this License, and how to view a copy of this License. If</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the interface presents a list of user commands or options, such as a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">menu, a prominent item in the list meets this criterion.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 1. Source Code.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "source code" for a work means the preferred form of the work</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for making modifications to it. "Object code" means any non-source</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">form of a work.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A "Standard Interface" means an interface that either is an official</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">standard defined by a recognized standards body, or, in the case of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">interfaces specified for a particular programming language, one that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">is widely used among developers working in that language.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "System Libraries" of an executable work include anything, other</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">than the work as a whole, that (a) is included in the normal form of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">packaging a Major Component, but which is not part of that Major</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Component, and (b) serves only to enable use of the work with that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Major Component, or to implement a Standard Interface for which an</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">implementation is available to the public in source code form. A</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">"Major Component", in this context, means a major essential component</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(kernel, window system, and so on) of the specific operating system</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(if any) on which the executable work runs, or a compiler used to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">produce the work, or an object code interpreter used to run it.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Corresponding Source" for a work in object code form means all</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the source code needed to generate, install, and (for an executable</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">work) run the object code and to modify the work, including scripts to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">control those activities. However, it does not include the work's</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">System Libraries, or general-purpose tools or generally available free</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">programs which are used unmodified in performing those activities but</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">which are not part of the work. For example, Corresponding Source</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">includes interface definition files associated with source files for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the work, and the source code for shared libraries and dynamically</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">linked subprograms that the work is specifically designed to require,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">such as by intimate data communication or control flow between those</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">subprograms and other parts of the work.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The Corresponding Source need not include anything that users</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">can regenerate automatically from other parts of the Corresponding</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Source.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The Corresponding Source for a work in source code form is that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">same work.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 2. Basic Permissions.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> All rights granted under this License are granted for the term of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">copyright on the Program, and are irrevocable provided the stated</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">conditions are met. This License explicitly affirms your unlimited</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">permission to run the unmodified Program. The output from running a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">covered work is covered by this License only if the output, given its</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">content, constitutes a covered work. This License acknowledges your</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">rights of fair use or other equivalent, as provided by copyright law.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may make, run and propagate covered works that you do not</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">convey, without conditions so long as your license otherwise remains</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in force. You may convey covered works to others for the sole purpose</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of having them make modifications exclusively for you, or provide you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">with facilities for running those works, provided that you comply with</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the terms of this License in conveying all material for which you do</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">not control copyright. Those thus making or running the covered works</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for you must do so exclusively on your behalf, under your direction</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and control, on terms that prohibit them from making any copies of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">your copyrighted material outside their relationship with you.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Conveying under any other circumstances is permitted solely under</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the conditions stated below. Sublicensing is not allowed; section 10</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">makes it unnecessary.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 3. Protecting Users' Legal Rights From Anti-Circumvention Law.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> No covered work shall be deemed part of an effective technological</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">measure under any applicable law fulfilling obligations under article</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">11 of the WIPO copyright treaty adopted on 20 December 1996, or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">similar laws prohibiting or restricting circumvention of such</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">measures.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> When you convey a covered work, you waive any legal power to forbid</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">circumvention of technological measures to the extent such circumvention</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">is effected by exercising rights under this License with respect to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the covered work, and you disclaim any intention to limit operation or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">modification of the work as a means of enforcing, against the work's</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">users, your or third parties' legal rights to forbid circumvention of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">technological measures.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 4. Conveying Verbatim Copies.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may convey verbatim copies of the Program's source code as you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">receive it, in any medium, provided that you conspicuously and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">appropriately publish on each copy an appropriate copyright notice;</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">keep intact all notices stating that this License and any</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">non-permissive terms added in accord with section 7 apply to the code;</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">keep intact all notices of the absence of any warranty; and give all</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">recipients a copy of this License along with the Program.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may charge any price or no price for each copy that you convey,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and you may offer support or warranty protection for a fee.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 5. Conveying Modified Source Versions.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may convey a work based on the Program, or the modifications to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">produce it from the Program, in the form of source code under the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">terms of section 4, provided that you also meet all of these conditions:</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) The work must carry prominent notices stating that you modified</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> it, and giving a relevant date.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) The work must carry prominent notices stating that it is</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> released under this License and any conditions added under section</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 7. This requirement modifies the requirement in section 4 to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> "keep intact all notices".</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> c) You must license the entire work, as a whole, under this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> License to anyone who comes into possession of a copy. This</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> License will therefore apply, along with any applicable section 7</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> additional terms, to the whole of the work, and all its parts,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> regardless of how they are packaged. This License gives no</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> permission to license the work in any other way, but it does not</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> invalidate such permission if you have separately received it.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> d) If the work has interactive user interfaces, each must display</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Appropriate Legal Notices; however, if the Program has interactive</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> interfaces that do not display Appropriate Legal Notices, your</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> work need not make them do so.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A compilation of a covered work with other separate and independent</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">works, which are not by their nature extensions of the covered work,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and which are not combined with it such as to form a larger program,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in or on a volume of a storage or distribution medium, is called an</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">"aggregate" if the compilation and its resulting copyright are not</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">used to limit the access or legal rights of the compilation's users</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">beyond what the individual works permit. Inclusion of a covered work</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in an aggregate does not cause this License to apply to the other</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">parts of the aggregate.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 6. Conveying Non-Source Forms.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may convey a covered work in object code form under the terms</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of sections 4 and 5, provided that you also convey the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">machine-readable Corresponding Source under the terms of this License,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in one of these ways:</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Convey the object code in, or embodied in, a physical product</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> (including a physical distribution medium), accompanied by the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source fixed on a durable physical medium</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> customarily used for software interchange.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Convey the object code in, or embodied in, a physical product</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> (including a physical distribution medium), accompanied by a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> written offer, valid for at least three years and valid for as</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> long as you offer spare parts or customer support for that product</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> model, to give anyone who possesses the object code either (1) a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> copy of the Corresponding Source for all the software in the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> product that is covered by this License, on a durable physical</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> medium customarily used for software interchange, for a price no</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> more than your reasonable cost of physically performing this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> conveying of source, or (2) access to copy the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source from a network server at no charge.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> c) Convey individual copies of the object code with a copy of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> written offer to provide the Corresponding Source. This</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> alternative is allowed only occasionally and noncommercially, and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> only if you received the object code with such an offer, in accord</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> with subsection 6b.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> d) Convey the object code by offering access from a designated</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> place (gratis or for a charge), and offer equivalent access to the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source in the same way through the same place at no</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> further charge. You need not require recipients to copy the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source along with the object code. If the place to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> copy the object code is a network server, the Corresponding Source</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> may be on a different server (operated by you or a third party)</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> that supports equivalent copying facilities, provided you maintain</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> clear directions next to the object code saying where to find the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source. Regardless of what server hosts the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source, you remain obligated to ensure that it is</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> available for as long as needed to satisfy these requirements.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> e) Convey the object code using peer-to-peer transmission, provided</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> you inform other peers where the object code and Corresponding</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Source of the work are being offered to the general public at no</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> charge under subsection 6d.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A separable portion of the object code, whose source code is excluded</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">from the Corresponding Source as a System Library, need not be</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">included in conveying the object code work.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A "User Product" is either (1) a "consumer product", which means any</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tangible personal property which is normally used for personal, family,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">or household purposes, or (2) anything designed or sold for incorporation</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">into a dwelling. In determining whether a product is a consumer product,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">doubtful cases shall be resolved in favor of coverage. For a particular</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">product received by a particular user, "normally used" refers to a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">typical or common use of that class of product, regardless of the status</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of the particular user or of the way in which the particular user</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">actually uses, or expects or is expected to use, the product. A product</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">is a consumer product regardless of whether the product has substantial</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">commercial, industrial or non-consumer uses, unless such uses represent</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the only significant mode of use of the product.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> "Installation Information" for a User Product means any methods,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">procedures, authorization keys, or other information required to install</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and execute modified versions of a covered work in that User Product from</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">a modified version of its Corresponding Source. The information must</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">suffice to ensure that the continued functioning of the modified object</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">code is in no case prevented or interfered with solely because</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">modification has been made.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If you convey an object code work under this section in, or with, or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">specifically for use in, a User Product, and the conveying occurs as</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">part of a transaction in which the right of possession and use of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">User Product is transferred to the recipient in perpetuity or for a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">fixed term (regardless of how the transaction is characterized), the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Corresponding Source conveyed under this section must be accompanied</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">by the Installation Information. But this requirement does not apply</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">if neither you nor any third party retains the ability to install</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">modified object code on the User Product (for example, the work has</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">been installed in ROM).</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The requirement to provide Installation Information does not include a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">requirement to continue to provide support service, warranty, or updates</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for a work that has been modified or installed by the recipient, or for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the User Product in which it has been modified or installed. Access to a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">network may be denied when the modification itself materially and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">adversely affects the operation of the network or violates the rules and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">protocols for communication across the network.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source conveyed, and Installation Information provided,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in accord with this section must be in a format that is publicly</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">documented (and with an implementation available to the public in</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">source code form), and must require no special password or key for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">unpacking, reading or copying.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 7. Additional Terms.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> "Additional permissions" are terms that supplement the terms of this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License by making exceptions from one or more of its conditions.</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Additional permissions that are applicable to the entire Program shall</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">be treated as though they were included in this License, to the extent</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">that they are valid under applicable law. If additional permissions</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">apply only to part of the Program, that part may be used separately</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">under those permissions, but the entire Program remains governed by</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">this License without regard to the additional permissions.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> When you convey a copy of a covered work, you may at your option</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove any additional permissions from that copy, or from any part of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">it. (Additional permissions may be written to require their own</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">removal in certain cases when you modify the work.) You may place</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">additional permissions on material, added by you to a covered work,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for which you have or can give appropriate copyright permission.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Notwithstanding any other provision of this License, for material you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">add to a covered work, you may (if authorized by the copyright holders of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">that material) supplement the terms of this License with terms:</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Disclaiming warranty or limiting liability differently from the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> terms of sections 15 and 16 of this License; or</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Requiring preservation of specified reasonable legal notices or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> author attributions in that material or in the Appropriate Legal</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Notices displayed by works containing it; or</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> c) Prohibiting misrepresentation of the origin of that material, or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> requiring that modified versions of such material be marked in</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> reasonable ways as different from the original version; or</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> d) Limiting the use for publicity purposes of names of licensors or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> authors of the material; or</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> e) Declining to grant rights under trademark law for use of some</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> trade names, trademarks, or service marks; or</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> f) Requiring indemnification of licensors and authors of that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> material by anyone who conveys the material (or modified versions of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> it) with contractual assumptions of liability to the recipient, for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> any liability that these contractual assumptions directly impose on</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> those licensors and authors.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> All other non-permissive additional terms are considered "further</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">restrictions" within the meaning of section 10. If the Program as you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">received it, or any part of it, contains a notice stating that it is</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">governed by this License along with a term that is a further</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">restriction, you may remove that term. If a license document contains</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">a further restriction but permits relicensing or conveying under this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License, you may add to a covered work material governed by the terms</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of that license document, provided that the further restriction does</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">not survive such relicensing or conveying.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If you add terms to a covered work in accord with this section, you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">must place, in the relevant source files, a statement of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">additional terms that apply to those files, or a notice indicating</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">where to find the applicable terms.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Additional terms, permissive or non-permissive, may be stated in the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">form of a separately written license, or stated as exceptions;</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the above requirements apply either way.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 8. Termination.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may not propagate or modify a covered work except as expressly</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">provided under this License. Any attempt otherwise to propagate or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">modify it is void, and will automatically terminate your rights under</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">this License (including any patent licenses granted under the third</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">paragraph of section 11).</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> However, if you cease all violation of this License, then your</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">license from a particular copyright holder is reinstated (a)</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">provisionally, unless and until the copyright holder explicitly and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">finally terminates your license, and (b) permanently, if the copyright</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">holder fails to notify you of the violation by some reasonable means</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">prior to 60 days after the cessation.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Moreover, your license from a particular copyright holder is</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reinstated permanently if the copyright holder notifies you of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">violation by some reasonable means, this is the first time you have</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">received notice of violation of this License (for any work) from that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">copyright holder, and you cure the violation prior to 30 days after</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">your receipt of the notice.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Termination of your rights under this section does not terminate the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">licenses of parties who have received copies or rights from you under</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">this License. If your rights have been terminated and not permanently</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reinstated, you do not qualify to receive new licenses for the same</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">material under section 10.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 9. Acceptance Not Required for Having Copies.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You are not required to accept this License in order to receive or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">run a copy of the Program. Ancillary propagation of a covered work</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">occurring solely as a consequence of using peer-to-peer transmission</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to receive a copy likewise does not require acceptance. However,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">nothing other than this License grants you permission to propagate or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">modify any covered work. These actions infringe copyright if you do</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">not accept this License. Therefore, by modifying or propagating a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">covered work, you indicate your acceptance of this License to do so.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 10. Automatic Licensing of Downstream Recipients.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Each time you convey a covered work, the recipient automatically</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">receives a license from the original licensors, to run, modify and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">propagate that work, subject to this License. You are not responsible</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for enforcing compliance by third parties with this License.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> An "entity transaction" is a transaction transferring control of an</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">organization, or substantially all assets of one, or subdividing an</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">organization, or merging organizations. If propagation of a covered</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">work results from an entity transaction, each party to that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">transaction who receives a copy of the work also receives whatever</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">licenses to the work the party's predecessor in interest had or could</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">give under the previous paragraph, plus a right to possession of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Corresponding Source of the work from the predecessor in interest, if</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the predecessor has it or can get it with reasonable efforts.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may not impose any further restrictions on the exercise of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">rights granted or affirmed under this License. For example, you may</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">not impose a license fee, royalty, or other charge for exercise of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">rights granted under this License, and you may not initiate litigation</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(including a cross-claim or counterclaim in a lawsuit) alleging that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">any patent claim is infringed by making, using, selling, offering for</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">sale, or importing the Program or any portion of it.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 11. Patents.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A "contributor" is a copyright holder who authorizes use under this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License of the Program or a work on which the Program is based. The</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">work thus licensed is called the contributor's "contributor version".</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A contributor's "essential patent claims" are all patent claims</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">owned or controlled by the contributor, whether already acquired or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hereafter acquired, that would be infringed by some manner, permitted</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">by this License, of making, using, or selling its contributor version,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">but do not include claims that would be infringed only as a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">consequence of further modification of the contributor version. For</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">purposes of this definition, "control" includes the right to grant</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">patent sublicenses in a manner consistent with the requirements of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">this License.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Each contributor grants you a non-exclusive, worldwide, royalty-free</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">patent license under the contributor's essential patent claims, to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">make, use, sell, offer for sale, import and otherwise run, modify and</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">propagate the contents of its contributor version.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> In the following three paragraphs, a "patent license" is any express</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">agreement or commitment, however denominated, not to enforce a patent</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(such as an express permission to practice a patent or covenant not to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">sue for patent infringement). To "grant" such a patent license to a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">party means to make such an agreement or commitment not to enforce a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">patent against the party.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If you convey a covered work, knowingly relying on a patent license,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and the Corresponding Source of the work is not available for anyone</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to copy, free of charge and under the terms of this License, through a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">publicly available network server or other readily accessible means,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">then you must either (1) cause the Corresponding Source to be so</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">available, or (2) arrange to deprive yourself of the benefit of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">patent license for this particular work, or (3) arrange, in a manner</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">consistent with the requirements of this License, to extend the patent</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">license to downstream recipients. "Knowingly relying" means you have</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">actual knowledge that, but for the patent license, your conveying the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">covered work in a country, or your recipient's use of the covered work</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in a country, would infringe one or more identifiable patents in that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">country that you have reason to believe are valid.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If, pursuant to or in connection with a single transaction or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">arrangement, you convey, or propagate by procuring conveyance of, a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">covered work, and grant a patent license to some of the parties</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">receiving the covered work authorizing them to use, propagate, modify</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">or convey a specific copy of the covered work, then the patent license</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">you grant is automatically extended to all recipients of the covered</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">work and works based on it.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A patent license is "discriminatory" if it does not include within</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the scope of its coverage, prohibits the exercise of, or is</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">conditioned on the non-exercise of one or more of the rights that are</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">specifically granted under this License. You may not convey a covered</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">work if you are a party to an arrangement with a third party that is</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">in the business of distributing software, under which you make payment</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to the third party based on the extent of your activity of conveying</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the work, and under which the third party grants, to any of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">parties who would receive the covered work from you, a discriminatory</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">patent license (a) in connection with copies of the covered work</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">conveyed by you (or copies made from those copies), or (b) primarily</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for and in connection with specific products or compilations that</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">contain the covered work, unless you entered into that arrangement,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">or that patent license was granted, prior to 28 March 2007.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Nothing in this License shall be construed as excluding or limiting</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">any implied license or other defenses to infringement that may</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">otherwise be available to you under applicable patent law.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 12. No Surrender of Others' Freedom.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If conditions are imposed on you (whether by court order, agreement or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">otherwise) that contradict the conditions of this License, they do not</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">excuse you from the conditions of this License. If you cannot convey a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">covered work so as to satisfy simultaneously your obligations under this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License and any other pertinent obligations, then as a consequence you may</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">not convey it at all. For example, if you agree to terms that obligate you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to collect a royalty for further conveying from those to whom you convey</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the Program, the only way you could satisfy both those terms and this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License would be to refrain entirely from conveying the Program.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 13. Use with the GNU Affero General Public License.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Notwithstanding any other provision of this License, you have</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">permission to link or combine any covered work with a work licensed</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">under version 3 of the GNU Affero General Public License into a single</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">combined work, and to convey the resulting work. The terms of this</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License will continue to apply to the part which is the covered work,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">but the special requirements of the GNU Affero General Public License,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">section 13, concerning interaction through a network will apply to the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">combination as such.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 14. Revised Versions of this License.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The Free Software Foundation may publish revised and/or new versions of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the GNU General Public License from time to time. Such new versions will</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">be similar in spirit to the present version, but may differ in detail to</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">address new problems or concerns.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Each version is given a distinguishing version number. If the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Program specifies that a certain numbered version of the GNU General</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Public License "or any later version" applies to it, you have the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">option of following the terms and conditions either of that numbered</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">version or of any later version published by the Free Software</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Foundation. If the Program does not specify a version number of the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GNU General Public License, you may choose any version ever published</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">by the Free Software Foundation.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If the Program specifies that a proxy can decide which future</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">versions of the GNU General Public License can be used, that proxy's</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">public statement of acceptance of a version permanently authorizes you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to choose that version for the Program.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Later license versions may give you additional or different</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">permissions. However, no additional obligations are imposed on any</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">author or copyright holder as a result of your choosing to follow a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">later version.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 15. Disclaimer of Warranty.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 16. Limitation of Liability.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">SUCH DAMAGES.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 17. Interpretation of Sections 15 and 16.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If the disclaimer of warranty and limitation of liability provided</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">above cannot be given local legal effect according to their terms,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reviewing courts shall apply local law that most closely approximates</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">an absolute waiver of all civil liability in connection with the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Program, unless a warranty or assumption of liability accompanies a</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">copy of the Program in return for a fee.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> END OF TERMS AND CONDITIONS</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> How to Apply These Terms to Your New Programs</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If you develop a new program, and you want it to be of the greatest</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">possible use to the public, the best way to achieve this is to make it</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">free software which everyone can redistribute and change under these terms.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> To do so, attach the following notices to the program. It is safest</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">to attach them to the start of each source file to most effectively</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">state the exclusion of warranty; and each file should have at least</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the "copyright" line and a pointer to where the full notice is found.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> &lt;one line to give the program's name and a brief idea of what it does.&gt;</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Copyright (C) &lt;year&gt; &lt;name of author&gt;</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> This program is free software: you can redistribute it and/or modify</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> it under the terms of the GNU General Public License as published by</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> the Free Software Foundation, either version 3 of the License, or</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> (at your option) any later version.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> This program is distributed in the hope that it will be useful,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> but WITHOUT ANY WARRANTY; without even the implied warranty of</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> GNU General Public License for more details.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You should have received a copy of the GNU General Public License</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Also add information on how to contact you by electronic and paper mail.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If the program does terminal interaction, make it output a short</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">notice like this when it starts in an interactive mode:</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> &lt;program&gt; Copyright (C) &lt;year&gt; &lt;name of author&gt;</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> This is free software, and you are welcome to redistribute it</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> under certain conditions; type `show c' for details.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The hypothetical commands `show w' and `show c' should show the appropriate</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">parts of the General Public License. Of course, your program's commands</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">might be different; for a GUI interface, you would use an "about box".</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You should also get your employer (if you work as a programmer) or school,</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">if any, to sign a "copyright disclaimer" for the program, if necessary.</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information on this, and how to apply and follow the GNU GPL, see</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;http://www.gnu.org/licenses/&gt;.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The GNU General Public License does not permit incorporating your program</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">into proprietary programs. If your program is a subroutine library, you</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">may consider it more useful to permit linking proprietary applications with</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the library. If this is what you want to do, use the GNU Lesser General</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Public License instead of this License. But first, please read</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;http://www.gnu.org/philosophy/why-not-lgpl.html&gt;.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="acceptRichText">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="thankstab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Thanks</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>391</width>
|
||||||
|
<height>121</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Thanks to Wii.py team: Xuzz, SquidMan, megazig, TheLemonMan, |Omega, and Matt_P. Qwad is only a frontend for their unbelievably awesome framework.</string>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../Qwad.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
767
GUI/Ui_AboutQwad.py
Normal file
767
GUI/Ui_AboutQwad.py
Normal file
@ -0,0 +1,767 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file '/home/ssorgatem/Documents/python/Qwad/GUI/AboutQwad.ui'
|
||||||
|
#
|
||||||
|
# Created: Sat Jul 25 02:02:44 2009
|
||||||
|
# by: PyQt4 UI code generator 4.4.4
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
class Ui_Dialog(object):
|
||||||
|
def setupUi(self, Dialog):
|
||||||
|
Dialog.setObjectName("Dialog")
|
||||||
|
Dialog.resize(441, 496)
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
icon.addPixmap(QtGui.QPixmap(":/icons/wad.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
Dialog.setWindowIcon(icon)
|
||||||
|
self.QwadIcon = QtGui.QLabel(Dialog)
|
||||||
|
self.QwadIcon.setGeometry(QtCore.QRect(150, 0, 131, 131))
|
||||||
|
self.QwadIcon.setPixmap(QtGui.QPixmap(":/icons/wad.png"))
|
||||||
|
self.QwadIcon.setScaledContents(False)
|
||||||
|
self.QwadIcon.setObjectName("QwadIcon")
|
||||||
|
self.Qwad_name = QtGui.QLabel(Dialog)
|
||||||
|
self.Qwad_name.setGeometry(QtCore.QRect(170, 110, 91, 51))
|
||||||
|
self.Qwad_name.setObjectName("Qwad_name")
|
||||||
|
self.Version = QtGui.QLabel(Dialog)
|
||||||
|
self.Version.setGeometry(QtCore.QRect(180, 150, 51, 21))
|
||||||
|
self.Version.setObjectName("Version")
|
||||||
|
self.byAuthor = QtGui.QLabel(Dialog)
|
||||||
|
self.byAuthor.setGeometry(QtCore.QRect(70, 170, 51, 20))
|
||||||
|
self.byAuthor.setObjectName("byAuthor")
|
||||||
|
self.versionNumber = QtGui.QLabel(Dialog)
|
||||||
|
self.versionNumber.setGeometry(QtCore.QRect(230, 150, 131, 21))
|
||||||
|
self.versionNumber.setObjectName("versionNumber")
|
||||||
|
self.AuthorName = QtGui.QLabel(Dialog)
|
||||||
|
self.AuthorName.setGeometry(QtCore.QRect(120, 170, 311, 20))
|
||||||
|
self.AuthorName.setObjectName("AuthorName")
|
||||||
|
self.abuttabs = QtGui.QTabWidget(Dialog)
|
||||||
|
self.abuttabs.setGeometry(QtCore.QRect(10, 200, 421, 281))
|
||||||
|
self.abuttabs.setObjectName("abuttabs")
|
||||||
|
self.licensetab = QtGui.QWidget()
|
||||||
|
self.licensetab.setObjectName("licensetab")
|
||||||
|
self.textEdit = QtGui.QTextEdit(self.licensetab)
|
||||||
|
self.textEdit.setGeometry(QtCore.QRect(0, 10, 411, 231))
|
||||||
|
self.textEdit.setUndoRedoEnabled(False)
|
||||||
|
self.textEdit.setReadOnly(True)
|
||||||
|
self.textEdit.setAcceptRichText(False)
|
||||||
|
self.textEdit.setObjectName("textEdit")
|
||||||
|
self.abuttabs.addTab(self.licensetab, "")
|
||||||
|
self.thankstab = QtGui.QWidget()
|
||||||
|
self.thankstab.setObjectName("thankstab")
|
||||||
|
self.label = QtGui.QLabel(self.thankstab)
|
||||||
|
self.label.setGeometry(QtCore.QRect(10, 10, 391, 121))
|
||||||
|
self.label.setScaledContents(True)
|
||||||
|
self.label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||||
|
self.label.setWordWrap(True)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.abuttabs.addTab(self.thankstab, "")
|
||||||
|
|
||||||
|
self.retranslateUi(Dialog)
|
||||||
|
self.abuttabs.setCurrentIndex(0)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||||
|
|
||||||
|
def retranslateUi(self, Dialog):
|
||||||
|
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.Qwad_name.setText(QtGui.QApplication.translate("Dialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||||
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||||
|
"p, li { white-space: pre-wrap; }\n"
|
||||||
|
"</style></head><body style=\" font-family:\'DejaVu Sans\'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:24pt; font-weight:600;\">Qwad</span></p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.Version.setText(QtGui.QApplication.translate("Dialog", "Version", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.byAuthor.setText(QtGui.QApplication.translate("Dialog", "Author: ", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.textEdit.setHtml(QtGui.QApplication.translate("Dialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||||
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||||
|
"p, li { white-space: pre-wrap; }\n"
|
||||||
|
"</style></head><body style=\" font-family:\'DejaVu Sans\'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> GNU GENERAL PUBLIC LICENSE</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Version 3, 29 June 2007</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Everyone is permitted to copy and distribute verbatim copies</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> of this license document, but changing it is not allowed.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Preamble</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The GNU General Public License is a free, copyleft license for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">software and other kinds of works.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The licenses for most software and other practical works are designed</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to take away your freedom to share and change the works. By contrast,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the GNU General Public License is intended to guarantee your freedom to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">share and change all versions of a program--to make sure it remains free</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">software for all its users. We, the Free Software Foundation, use the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">GNU General Public License for most of our software; it applies also to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">any other work released this way by its authors. You can apply it to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">your programs, too.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> When we speak of free software, we are referring to freedom, not</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">price. Our General Public Licenses are designed to make sure that you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">have the freedom to distribute copies of free software (and charge for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">them if you wish), that you receive source code or can get it if you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">want it, that you can change the software or use pieces of it in new</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">free programs, and that you know you can do these things.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> To protect your rights, we need to prevent others from denying you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">these rights or asking you to surrender the rights. Therefore, you have</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">certain responsibilities if you distribute copies of the software, or if</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">you modify it: responsibilities to respect the freedom of others.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> For example, if you distribute copies of such a program, whether</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">gratis or for a fee, you must pass on to the recipients the same</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">freedoms that you received. You must make sure that they, too, receive</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">or can get the source code. And you must show them these terms so they</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">know their rights.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Developers that use the GNU GPL protect your rights with two steps:</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">(1) assert copyright on the software, and (2) offer you this License</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">giving you legal permission to copy, distribute and/or modify it.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> For the developers\' and authors\' protection, the GPL clearly explains</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">that there is no warranty for this free software. For both users\' and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">authors\' sake, the GPL requires that modified versions be marked as</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">changed, so that their problems will not be attributed erroneously to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">authors of previous versions.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Some devices are designed to deny users access to install or run</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">modified versions of the software inside them, although the manufacturer</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">can do so. This is fundamentally incompatible with the aim of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">protecting users\' freedom to change the software. The systematic</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">pattern of such abuse occurs in the area of products for individuals to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">use, which is precisely where it is most unacceptable. Therefore, we</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">have designed this version of the GPL to prohibit the practice for those</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">products. If such problems arise substantially in other domains, we</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">stand ready to extend this provision to those domains in future versions</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">of the GPL, as needed to protect the freedom of users.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Finally, every program is threatened constantly by software patents.</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">States should not allow patents to restrict development and use of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">software on general-purpose computers, but in those that do, we wish to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">avoid the special danger that patents applied to a free program could</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">make it effectively proprietary. To prevent this, the GPL assures that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">patents cannot be used to render the program non-free.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The precise terms and conditions for copying, distribution and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">modification follow.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> TERMS AND CONDITIONS</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 0. Definitions.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \"This License\" refers to version 3 of the GNU General Public License.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \"Copyright\" also means copyright-like laws that apply to other kinds of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">works, such as semiconductor masks.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \"The Program\" refers to any copyrightable work licensed under this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">License. Each licensee is addressed as \"you\". \"Licensees\" and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">\"recipients\" may be individuals or organizations.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> To \"modify\" a work means to copy from or adapt all or part of the work</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in a fashion requiring copyright permission, other than the making of an</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">exact copy. The resulting work is called a \"modified version\" of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">earlier work or a work \"based on\" the earlier work.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A \"covered work\" means either the unmodified Program or a work based</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">on the Program.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> To \"propagate\" a work means to do anything with it that, without</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">permission, would make you directly or secondarily liable for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">infringement under applicable copyright law, except executing it on a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">computer or modifying a private copy. Propagation includes copying,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">distribution (with or without modification), making available to the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">public, and in some countries other activities as well.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> To \"convey\" a work means any kind of propagation that enables other</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">parties to make or receive copies. Mere interaction with a user through</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">a computer network, with no transfer of a copy, is not conveying.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> An interactive user interface displays \"Appropriate Legal Notices\"</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to the extent that it includes a convenient and prominently visible</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">feature that (1) displays an appropriate copyright notice, and (2)</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">tells the user that there is no warranty for the work (except to the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">extent that warranties are provided), that licensees may convey the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">work under this License, and how to view a copy of this License. If</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the interface presents a list of user commands or options, such as a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">menu, a prominent item in the list meets this criterion.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 1. Source Code.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The \"source code\" for a work means the preferred form of the work</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">for making modifications to it. \"Object code\" means any non-source</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">form of a work.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A \"Standard Interface\" means an interface that either is an official</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">standard defined by a recognized standards body, or, in the case of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">interfaces specified for a particular programming language, one that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">is widely used among developers working in that language.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The \"System Libraries\" of an executable work include anything, other</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">than the work as a whole, that (a) is included in the normal form of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">packaging a Major Component, but which is not part of that Major</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Component, and (b) serves only to enable use of the work with that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Major Component, or to implement a Standard Interface for which an</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">implementation is available to the public in source code form. A</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">\"Major Component\", in this context, means a major essential component</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">(kernel, window system, and so on) of the specific operating system</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">(if any) on which the executable work runs, or a compiler used to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">produce the work, or an object code interpreter used to run it.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The \"Corresponding Source\" for a work in object code form means all</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the source code needed to generate, install, and (for an executable</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">work) run the object code and to modify the work, including scripts to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">control those activities. However, it does not include the work\'s</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">System Libraries, or general-purpose tools or generally available free</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">programs which are used unmodified in performing those activities but</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">which are not part of the work. For example, Corresponding Source</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">includes interface definition files associated with source files for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the work, and the source code for shared libraries and dynamically</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">linked subprograms that the work is specifically designed to require,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">such as by intimate data communication or control flow between those</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">subprograms and other parts of the work.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The Corresponding Source need not include anything that users</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">can regenerate automatically from other parts of the Corresponding</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Source.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The Corresponding Source for a work in source code form is that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">same work.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 2. Basic Permissions.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> All rights granted under this License are granted for the term of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">copyright on the Program, and are irrevocable provided the stated</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">conditions are met. This License explicitly affirms your unlimited</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">permission to run the unmodified Program. The output from running a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">covered work is covered by this License only if the output, given its</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">content, constitutes a covered work. This License acknowledges your</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">rights of fair use or other equivalent, as provided by copyright law.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You may make, run and propagate covered works that you do not</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">convey, without conditions so long as your license otherwise remains</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in force. You may convey covered works to others for the sole purpose</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">of having them make modifications exclusively for you, or provide you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">with facilities for running those works, provided that you comply with</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the terms of this License in conveying all material for which you do</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">not control copyright. Those thus making or running the covered works</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">for you must do so exclusively on your behalf, under your direction</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">and control, on terms that prohibit them from making any copies of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">your copyrighted material outside their relationship with you.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Conveying under any other circumstances is permitted solely under</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the conditions stated below. Sublicensing is not allowed; section 10</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">makes it unnecessary.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 3. Protecting Users\' Legal Rights From Anti-Circumvention Law.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> No covered work shall be deemed part of an effective technological</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">measure under any applicable law fulfilling obligations under article</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">11 of the WIPO copyright treaty adopted on 20 December 1996, or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">similar laws prohibiting or restricting circumvention of such</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">measures.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> When you convey a covered work, you waive any legal power to forbid</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">circumvention of technological measures to the extent such circumvention</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">is effected by exercising rights under this License with respect to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the covered work, and you disclaim any intention to limit operation or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">modification of the work as a means of enforcing, against the work\'s</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">users, your or third parties\' legal rights to forbid circumvention of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">technological measures.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 4. Conveying Verbatim Copies.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You may convey verbatim copies of the Program\'s source code as you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">receive it, in any medium, provided that you conspicuously and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">appropriately publish on each copy an appropriate copyright notice;</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">keep intact all notices stating that this License and any</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">non-permissive terms added in accord with section 7 apply to the code;</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">keep intact all notices of the absence of any warranty; and give all</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">recipients a copy of this License along with the Program.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You may charge any price or no price for each copy that you convey,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">and you may offer support or warranty protection for a fee.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 5. Conveying Modified Source Versions.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You may convey a work based on the Program, or the modifications to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">produce it from the Program, in the form of source code under the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">terms of section 4, provided that you also meet all of these conditions:</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> a) The work must carry prominent notices stating that you modified</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> it, and giving a relevant date.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> b) The work must carry prominent notices stating that it is</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> released under this License and any conditions added under section</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 7. This requirement modifies the requirement in section 4 to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \"keep intact all notices\".</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> c) You must license the entire work, as a whole, under this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> License to anyone who comes into possession of a copy. This</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> License will therefore apply, along with any applicable section 7</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> additional terms, to the whole of the work, and all its parts,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> regardless of how they are packaged. This License gives no</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> permission to license the work in any other way, but it does not</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> invalidate such permission if you have separately received it.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> d) If the work has interactive user interfaces, each must display</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Appropriate Legal Notices; however, if the Program has interactive</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> interfaces that do not display Appropriate Legal Notices, your</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> work need not make them do so.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A compilation of a covered work with other separate and independent</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">works, which are not by their nature extensions of the covered work,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">and which are not combined with it such as to form a larger program,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in or on a volume of a storage or distribution medium, is called an</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">\"aggregate\" if the compilation and its resulting copyright are not</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">used to limit the access or legal rights of the compilation\'s users</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">beyond what the individual works permit. Inclusion of a covered work</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in an aggregate does not cause this License to apply to the other</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">parts of the aggregate.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 6. Conveying Non-Source Forms.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You may convey a covered work in object code form under the terms</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">of sections 4 and 5, provided that you also convey the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">machine-readable Corresponding Source under the terms of this License,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in one of these ways:</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> a) Convey the object code in, or embodied in, a physical product</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> (including a physical distribution medium), accompanied by the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Corresponding Source fixed on a durable physical medium</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> customarily used for software interchange.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> b) Convey the object code in, or embodied in, a physical product</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> (including a physical distribution medium), accompanied by a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> written offer, valid for at least three years and valid for as</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> long as you offer spare parts or customer support for that product</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> model, to give anyone who possesses the object code either (1) a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> copy of the Corresponding Source for all the software in the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> product that is covered by this License, on a durable physical</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> medium customarily used for software interchange, for a price no</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> more than your reasonable cost of physically performing this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> conveying of source, or (2) access to copy the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Corresponding Source from a network server at no charge.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> c) Convey individual copies of the object code with a copy of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> written offer to provide the Corresponding Source. This</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> alternative is allowed only occasionally and noncommercially, and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> only if you received the object code with such an offer, in accord</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> with subsection 6b.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> d) Convey the object code by offering access from a designated</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> place (gratis or for a charge), and offer equivalent access to the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Corresponding Source in the same way through the same place at no</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> further charge. You need not require recipients to copy the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Corresponding Source along with the object code. If the place to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> copy the object code is a network server, the Corresponding Source</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> may be on a different server (operated by you or a third party)</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> that supports equivalent copying facilities, provided you maintain</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> clear directions next to the object code saying where to find the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Corresponding Source. Regardless of what server hosts the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Corresponding Source, you remain obligated to ensure that it is</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> available for as long as needed to satisfy these requirements.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> e) Convey the object code using peer-to-peer transmission, provided</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> you inform other peers where the object code and Corresponding</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Source of the work are being offered to the general public at no</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> charge under subsection 6d.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A separable portion of the object code, whose source code is excluded</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">from the Corresponding Source as a System Library, need not be</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">included in conveying the object code work.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A \"User Product\" is either (1) a \"consumer product\", which means any</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">tangible personal property which is normally used for personal, family,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">or household purposes, or (2) anything designed or sold for incorporation</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">into a dwelling. In determining whether a product is a consumer product,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">doubtful cases shall be resolved in favor of coverage. For a particular</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">product received by a particular user, \"normally used\" refers to a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">typical or common use of that class of product, regardless of the status</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">of the particular user or of the way in which the particular user</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">actually uses, or expects or is expected to use, the product. A product</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">is a consumer product regardless of whether the product has substantial</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">commercial, industrial or non-consumer uses, unless such uses represent</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the only significant mode of use of the product.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \"Installation Information\" for a User Product means any methods,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">procedures, authorization keys, or other information required to install</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">and execute modified versions of a covered work in that User Product from</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">a modified version of its Corresponding Source. The information must</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">suffice to ensure that the continued functioning of the modified object</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">code is in no case prevented or interfered with solely because</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">modification has been made.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If you convey an object code work under this section in, or with, or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">specifically for use in, a User Product, and the conveying occurs as</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">part of a transaction in which the right of possession and use of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">User Product is transferred to the recipient in perpetuity or for a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">fixed term (regardless of how the transaction is characterized), the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Corresponding Source conveyed under this section must be accompanied</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">by the Installation Information. But this requirement does not apply</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">if neither you nor any third party retains the ability to install</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">modified object code on the User Product (for example, the work has</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">been installed in ROM).</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The requirement to provide Installation Information does not include a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">requirement to continue to provide support service, warranty, or updates</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">for a work that has been modified or installed by the recipient, or for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the User Product in which it has been modified or installed. Access to a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">network may be denied when the modification itself materially and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">adversely affects the operation of the network or violates the rules and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">protocols for communication across the network.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Corresponding Source conveyed, and Installation Information provided,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in accord with this section must be in a format that is publicly</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">documented (and with an implementation available to the public in</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">source code form), and must require no special password or key for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">unpacking, reading or copying.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 7. Additional Terms.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \"Additional permissions\" are terms that supplement the terms of this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">License by making exceptions from one or more of its conditions.</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Additional permissions that are applicable to the entire Program shall</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">be treated as though they were included in this License, to the extent</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">that they are valid under applicable law. If additional permissions</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">apply only to part of the Program, that part may be used separately</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">under those permissions, but the entire Program remains governed by</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">this License without regard to the additional permissions.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> When you convey a copy of a covered work, you may at your option</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">remove any additional permissions from that copy, or from any part of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">it. (Additional permissions may be written to require their own</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">removal in certain cases when you modify the work.) You may place</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">additional permissions on material, added by you to a covered work,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">for which you have or can give appropriate copyright permission.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Notwithstanding any other provision of this License, for material you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">add to a covered work, you may (if authorized by the copyright holders of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">that material) supplement the terms of this License with terms:</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> a) Disclaiming warranty or limiting liability differently from the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> terms of sections 15 and 16 of this License; or</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> b) Requiring preservation of specified reasonable legal notices or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> author attributions in that material or in the Appropriate Legal</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Notices displayed by works containing it; or</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> c) Prohibiting misrepresentation of the origin of that material, or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> requiring that modified versions of such material be marked in</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> reasonable ways as different from the original version; or</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> d) Limiting the use for publicity purposes of names of licensors or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> authors of the material; or</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> e) Declining to grant rights under trademark law for use of some</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> trade names, trademarks, or service marks; or</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> f) Requiring indemnification of licensors and authors of that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> material by anyone who conveys the material (or modified versions of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> it) with contractual assumptions of liability to the recipient, for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> any liability that these contractual assumptions directly impose on</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> those licensors and authors.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> All other non-permissive additional terms are considered \"further</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">restrictions\" within the meaning of section 10. If the Program as you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">received it, or any part of it, contains a notice stating that it is</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">governed by this License along with a term that is a further</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">restriction, you may remove that term. If a license document contains</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">a further restriction but permits relicensing or conveying under this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">License, you may add to a covered work material governed by the terms</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">of that license document, provided that the further restriction does</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">not survive such relicensing or conveying.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If you add terms to a covered work in accord with this section, you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">must place, in the relevant source files, a statement of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">additional terms that apply to those files, or a notice indicating</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">where to find the applicable terms.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Additional terms, permissive or non-permissive, may be stated in the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">form of a separately written license, or stated as exceptions;</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the above requirements apply either way.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 8. Termination.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You may not propagate or modify a covered work except as expressly</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">provided under this License. Any attempt otherwise to propagate or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">modify it is void, and will automatically terminate your rights under</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">this License (including any patent licenses granted under the third</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">paragraph of section 11).</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> However, if you cease all violation of this License, then your</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">license from a particular copyright holder is reinstated (a)</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">provisionally, unless and until the copyright holder explicitly and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">finally terminates your license, and (b) permanently, if the copyright</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">holder fails to notify you of the violation by some reasonable means</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">prior to 60 days after the cessation.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Moreover, your license from a particular copyright holder is</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">reinstated permanently if the copyright holder notifies you of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">violation by some reasonable means, this is the first time you have</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">received notice of violation of this License (for any work) from that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">copyright holder, and you cure the violation prior to 30 days after</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">your receipt of the notice.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Termination of your rights under this section does not terminate the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">licenses of parties who have received copies or rights from you under</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">this License. If your rights have been terminated and not permanently</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">reinstated, you do not qualify to receive new licenses for the same</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">material under section 10.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 9. Acceptance Not Required for Having Copies.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You are not required to accept this License in order to receive or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">run a copy of the Program. Ancillary propagation of a covered work</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">occurring solely as a consequence of using peer-to-peer transmission</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to receive a copy likewise does not require acceptance. However,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">nothing other than this License grants you permission to propagate or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">modify any covered work. These actions infringe copyright if you do</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">not accept this License. Therefore, by modifying or propagating a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">covered work, you indicate your acceptance of this License to do so.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 10. Automatic Licensing of Downstream Recipients.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Each time you convey a covered work, the recipient automatically</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">receives a license from the original licensors, to run, modify and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">propagate that work, subject to this License. You are not responsible</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">for enforcing compliance by third parties with this License.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> An \"entity transaction\" is a transaction transferring control of an</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">organization, or substantially all assets of one, or subdividing an</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">organization, or merging organizations. If propagation of a covered</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">work results from an entity transaction, each party to that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">transaction who receives a copy of the work also receives whatever</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">licenses to the work the party\'s predecessor in interest had or could</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">give under the previous paragraph, plus a right to possession of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Corresponding Source of the work from the predecessor in interest, if</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the predecessor has it or can get it with reasonable efforts.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You may not impose any further restrictions on the exercise of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">rights granted or affirmed under this License. For example, you may</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">not impose a license fee, royalty, or other charge for exercise of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">rights granted under this License, and you may not initiate litigation</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">(including a cross-claim or counterclaim in a lawsuit) alleging that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">any patent claim is infringed by making, using, selling, offering for</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">sale, or importing the Program or any portion of it.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 11. Patents.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A \"contributor\" is a copyright holder who authorizes use under this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">License of the Program or a work on which the Program is based. The</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">work thus licensed is called the contributor\'s \"contributor version\".</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A contributor\'s \"essential patent claims\" are all patent claims</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">owned or controlled by the contributor, whether already acquired or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">hereafter acquired, that would be infringed by some manner, permitted</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">by this License, of making, using, or selling its contributor version,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">but do not include claims that would be infringed only as a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">consequence of further modification of the contributor version. For</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">purposes of this definition, \"control\" includes the right to grant</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">patent sublicenses in a manner consistent with the requirements of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">this License.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Each contributor grants you a non-exclusive, worldwide, royalty-free</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">patent license under the contributor\'s essential patent claims, to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">make, use, sell, offer for sale, import and otherwise run, modify and</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">propagate the contents of its contributor version.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> In the following three paragraphs, a \"patent license\" is any express</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">agreement or commitment, however denominated, not to enforce a patent</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">(such as an express permission to practice a patent or covenant not to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">sue for patent infringement). To \"grant\" such a patent license to a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">party means to make such an agreement or commitment not to enforce a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">patent against the party.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If you convey a covered work, knowingly relying on a patent license,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">and the Corresponding Source of the work is not available for anyone</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to copy, free of charge and under the terms of this License, through a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">publicly available network server or other readily accessible means,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">then you must either (1) cause the Corresponding Source to be so</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">available, or (2) arrange to deprive yourself of the benefit of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">patent license for this particular work, or (3) arrange, in a manner</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">consistent with the requirements of this License, to extend the patent</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">license to downstream recipients. \"Knowingly relying\" means you have</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">actual knowledge that, but for the patent license, your conveying the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">covered work in a country, or your recipient\'s use of the covered work</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in a country, would infringe one or more identifiable patents in that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">country that you have reason to believe are valid.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If, pursuant to or in connection with a single transaction or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">arrangement, you convey, or propagate by procuring conveyance of, a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">covered work, and grant a patent license to some of the parties</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">receiving the covered work authorizing them to use, propagate, modify</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">or convey a specific copy of the covered work, then the patent license</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">you grant is automatically extended to all recipients of the covered</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">work and works based on it.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> A patent license is \"discriminatory\" if it does not include within</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the scope of its coverage, prohibits the exercise of, or is</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">conditioned on the non-exercise of one or more of the rights that are</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">specifically granted under this License. You may not convey a covered</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">work if you are a party to an arrangement with a third party that is</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">in the business of distributing software, under which you make payment</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to the third party based on the extent of your activity of conveying</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the work, and under which the third party grants, to any of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">parties who would receive the covered work from you, a discriminatory</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">patent license (a) in connection with copies of the covered work</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">conveyed by you (or copies made from those copies), or (b) primarily</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">for and in connection with specific products or compilations that</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">contain the covered work, unless you entered into that arrangement,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">or that patent license was granted, prior to 28 March 2007.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Nothing in this License shall be construed as excluding or limiting</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">any implied license or other defenses to infringement that may</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">otherwise be available to you under applicable patent law.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 12. No Surrender of Others\' Freedom.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If conditions are imposed on you (whether by court order, agreement or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">otherwise) that contradict the conditions of this License, they do not</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">excuse you from the conditions of this License. If you cannot convey a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">covered work so as to satisfy simultaneously your obligations under this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">License and any other pertinent obligations, then as a consequence you may</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">not convey it at all. For example, if you agree to terms that obligate you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to collect a royalty for further conveying from those to whom you convey</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the Program, the only way you could satisfy both those terms and this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">License would be to refrain entirely from conveying the Program.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 13. Use with the GNU Affero General Public License.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Notwithstanding any other provision of this License, you have</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">permission to link or combine any covered work with a work licensed</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">under version 3 of the GNU Affero General Public License into a single</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">combined work, and to convey the resulting work. The terms of this</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">License will continue to apply to the part which is the covered work,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">but the special requirements of the GNU Affero General Public License,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">section 13, concerning interaction through a network will apply to the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">combination as such.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 14. Revised Versions of this License.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The Free Software Foundation may publish revised and/or new versions of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the GNU General Public License from time to time. Such new versions will</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">be similar in spirit to the present version, but may differ in detail to</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">address new problems or concerns.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Each version is given a distinguishing version number. If the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Program specifies that a certain numbered version of the GNU General</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Public License \"or any later version\" applies to it, you have the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">option of following the terms and conditions either of that numbered</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">version or of any later version published by the Free Software</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Foundation. If the Program does not specify a version number of the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">GNU General Public License, you may choose any version ever published</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">by the Free Software Foundation.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If the Program specifies that a proxy can decide which future</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">versions of the GNU General Public License can be used, that proxy\'s</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">public statement of acceptance of a version permanently authorizes you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to choose that version for the Program.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Later license versions may give you additional or different</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">permissions. However, no additional obligations are imposed on any</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">author or copyright holder as a result of your choosing to follow a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">later version.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 15. Disclaimer of Warranty.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 16. Limitation of Liability.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">SUCH DAMAGES.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 17. Interpretation of Sections 15 and 16.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If the disclaimer of warranty and limitation of liability provided</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">above cannot be given local legal effect according to their terms,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">reviewing courts shall apply local law that most closely approximates</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">an absolute waiver of all civil liability in connection with the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Program, unless a warranty or assumption of liability accompanies a</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">copy of the Program in return for a fee.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> END OF TERMS AND CONDITIONS</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> How to Apply These Terms to Your New Programs</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If you develop a new program, and you want it to be of the greatest</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">possible use to the public, the best way to achieve this is to make it</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">free software which everyone can redistribute and change under these terms.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> To do so, attach the following notices to the program. It is safest</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">to attach them to the start of each source file to most effectively</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">state the exclusion of warranty; and each file should have at least</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the \"copyright\" line and a pointer to where the full notice is found.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> <one line to give the program\'s name and a brief idea of what it does.></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> Copyright (C) <year> <name of author></p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> This program is free software: you can redistribute it and/or modify</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> it under the terms of the GNU General Public License as published by</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> the Free Software Foundation, either version 3 of the License, or</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> (at your option) any later version.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> This program is distributed in the hope that it will be useful,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> but WITHOUT ANY WARRANTY; without even the implied warranty of</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> GNU General Public License for more details.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You should have received a copy of the GNU General Public License</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> along with this program. If not, see <http://www.gnu.org/licenses/>.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Also add information on how to contact you by electronic and paper mail.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> If the program does terminal interaction, make it output a short</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">notice like this when it starts in an interactive mode:</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> <program> Copyright (C) <year> <name of author></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> This program comes with ABSOLUTELY NO WARRANTY; for details type `show w\'.</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> This is free software, and you are welcome to redistribute it</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> under certain conditions; type `show c\' for details.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">The hypothetical commands `show w\' and `show c\' should show the appropriate</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">parts of the General Public License. Of course, your program\'s commands</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">might be different; for a GUI interface, you would use an \"about box\".</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> You should also get your employer (if you work as a programmer) or school,</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">if any, to sign a \"copyright disclaimer\" for the program, if necessary.</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">For more information on this, and how to apply and follow the GNU GPL, see</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><http://www.gnu.org/licenses/>.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> The GNU General Public License does not permit incorporating your program</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">into proprietary programs. If your program is a subroutine library, you</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">may consider it more useful to permit linking proprietary applications with</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">the library. If this is what you want to do, use the GNU Lesser General</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Public License instead of this License. But first, please read</p>\n"
|
||||||
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><http://www.gnu.org/philosophy/why-not-lgpl.html>.</p>\n"
|
||||||
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.abuttabs.setTabText(self.abuttabs.indexOf(self.licensetab), QtGui.QApplication.translate("Dialog", "License", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label.setText(QtGui.QApplication.translate("Dialog", "Thanks to Wii.py team: Xuzz, SquidMan, megazig, TheLemonMan, |Omega, and Matt_P. Qwad is only a frontend for their unbelievably awesome framework.", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.abuttabs.setTabText(self.abuttabs.indexOf(self.thankstab), QtGui.QApplication.translate("Dialog", "Thanks", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
|
import Qwad_rc
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtGui.QApplication(sys.argv)
|
||||||
|
Dialog = QtGui.QDialog()
|
||||||
|
ui = Ui_Dialog()
|
||||||
|
ui.setupUi(Dialog)
|
||||||
|
Dialog.show()
|
||||||
|
sys.exit(app.exec_())
|
||||||
|
|
279
GUI/Ui_VenPri.py
Normal file
279
GUI/Ui_VenPri.py
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file '/home/ssorgatem/Documents/python/qwad/GUI/VenPri.ui'
|
||||||
|
#
|
||||||
|
# Created: Mon Jul 27 19:07:42 2009
|
||||||
|
# by: PyQt4 UI code generator 4.4.4
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
class Ui_Qwad(object):
|
||||||
|
def setupUi(self, Qwad):
|
||||||
|
Qwad.setObjectName("Qwad")
|
||||||
|
Qwad.resize(481, 296)
|
||||||
|
Qwad.setMinimumSize(QtCore.QSize(481, 296))
|
||||||
|
Qwad.setMaximumSize(QtCore.QSize(481, 296))
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
icon.addPixmap(QtGui.QPixmap(":/icons/wad.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
Qwad.setWindowIcon(icon)
|
||||||
|
self.centralWidget = QtGui.QWidget(Qwad)
|
||||||
|
self.centralWidget.setObjectName("centralWidget")
|
||||||
|
self.tabWidget = QtGui.QTabWidget(self.centralWidget)
|
||||||
|
self.tabWidget.setGeometry(QtCore.QRect(0, 0, 481, 251))
|
||||||
|
self.tabWidget.setAcceptDrops(False)
|
||||||
|
self.tabWidget.setObjectName("tabWidget")
|
||||||
|
self.unpacktab = QtGui.QWidget()
|
||||||
|
self.unpacktab.setObjectName("unpacktab")
|
||||||
|
self.MuestraRutaWad = QtGui.QLineEdit(self.unpacktab)
|
||||||
|
self.MuestraRutaWad.setGeometry(QtCore.QRect(160, 40, 241, 26))
|
||||||
|
self.MuestraRutaWad.setObjectName("MuestraRutaWad")
|
||||||
|
self.BotonRutaWad = QtGui.QToolButton(self.unpacktab)
|
||||||
|
self.BotonRutaWad.setGeometry(QtCore.QRect(70, 40, 91, 25))
|
||||||
|
self.BotonRutaWad.setObjectName("BotonRutaWad")
|
||||||
|
self.MuestraRutaExtraer = QtGui.QLineEdit(self.unpacktab)
|
||||||
|
self.MuestraRutaExtraer.setGeometry(QtCore.QRect(160, 110, 241, 26))
|
||||||
|
self.MuestraRutaExtraer.setObjectName("MuestraRutaExtraer")
|
||||||
|
self.BotonRutaExtraer = QtGui.QToolButton(self.unpacktab)
|
||||||
|
self.BotonRutaExtraer.setGeometry(QtCore.QRect(70, 110, 91, 25))
|
||||||
|
self.BotonRutaExtraer.setAutoRaise(False)
|
||||||
|
self.BotonRutaExtraer.setArrowType(QtCore.Qt.NoArrow)
|
||||||
|
self.BotonRutaExtraer.setObjectName("BotonRutaExtraer")
|
||||||
|
self.Desempaqueta = QtGui.QPushButton(self.unpacktab)
|
||||||
|
self.Desempaqueta.setGeometry(QtCore.QRect(170, 180, 121, 25))
|
||||||
|
self.Desempaqueta.setObjectName("Desempaqueta")
|
||||||
|
self.tabWidget.addTab(self.unpacktab, "")
|
||||||
|
self.TMDviewer = QtGui.QWidget()
|
||||||
|
self.TMDviewer.setObjectName("TMDviewer")
|
||||||
|
self.TMDfilepath = QtGui.QLineEdit(self.TMDviewer)
|
||||||
|
self.TMDfilepath.setGeometry(QtCore.QRect(150, 10, 241, 26))
|
||||||
|
self.TMDfilepath.setObjectName("TMDfilepath")
|
||||||
|
self.TMDfilebutton = QtGui.QToolButton(self.TMDviewer)
|
||||||
|
self.TMDfilebutton.setGeometry(QtCore.QRect(60, 10, 91, 25))
|
||||||
|
self.TMDfilebutton.setObjectName("TMDfilebutton")
|
||||||
|
self.widget = QtGui.QWidget(self.TMDviewer)
|
||||||
|
self.widget.setGeometry(QtCore.QRect(10, 50, 451, 147))
|
||||||
|
self.widget.setObjectName("widget")
|
||||||
|
self.gridLayout = QtGui.QGridLayout(self.widget)
|
||||||
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
|
self.label = QtGui.QLabel(self.widget)
|
||||||
|
self.label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
|
||||||
|
self.TitleID = QtGui.QLineEdit(self.widget)
|
||||||
|
self.TitleID.setReadOnly(True)
|
||||||
|
self.TitleID.setObjectName("TitleID")
|
||||||
|
self.gridLayout.addWidget(self.TitleID, 0, 1, 1, 1)
|
||||||
|
self.label_9 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_9.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_9.setObjectName("label_9")
|
||||||
|
self.gridLayout.addWidget(self.label_9, 0, 2, 1, 2)
|
||||||
|
self.idASCII = QtGui.QLineEdit(self.widget)
|
||||||
|
self.idASCII.setReadOnly(True)
|
||||||
|
self.idASCII.setObjectName("idASCII")
|
||||||
|
self.gridLayout.addWidget(self.idASCII, 0, 4, 1, 1)
|
||||||
|
self.label_3 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_3.setObjectName("label_3")
|
||||||
|
self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1)
|
||||||
|
self.Version = QtGui.QLineEdit(self.widget)
|
||||||
|
self.Version.setReadOnly(True)
|
||||||
|
self.Version.setObjectName("Version")
|
||||||
|
self.gridLayout.addWidget(self.Version, 1, 1, 1, 1)
|
||||||
|
self.label_5 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_5.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_5.setObjectName("label_5")
|
||||||
|
self.gridLayout.addWidget(self.label_5, 1, 3, 1, 1)
|
||||||
|
self.TitleType = QtGui.QLineEdit(self.widget)
|
||||||
|
self.TitleType.setReadOnly(True)
|
||||||
|
self.TitleType.setObjectName("TitleType")
|
||||||
|
self.gridLayout.addWidget(self.TitleType, 1, 4, 1, 1)
|
||||||
|
self.label_2 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_2.setObjectName("label_2")
|
||||||
|
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
|
||||||
|
self.label_6 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_6.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_6.setObjectName("label_6")
|
||||||
|
self.gridLayout.addWidget(self.label_6, 2, 3, 1, 1)
|
||||||
|
self.GroupID = QtGui.QLineEdit(self.widget)
|
||||||
|
self.GroupID.setReadOnly(True)
|
||||||
|
self.GroupID.setObjectName("GroupID")
|
||||||
|
self.gridLayout.addWidget(self.GroupID, 2, 4, 1, 1)
|
||||||
|
self.label_4 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_4.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_4.setObjectName("label_4")
|
||||||
|
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
|
||||||
|
self.BootIndex = QtGui.QLineEdit(self.widget)
|
||||||
|
self.BootIndex.setReadOnly(True)
|
||||||
|
self.BootIndex.setObjectName("BootIndex")
|
||||||
|
self.gridLayout.addWidget(self.BootIndex, 3, 1, 1, 1)
|
||||||
|
self.label_7 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_7.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_7.setObjectName("label_7")
|
||||||
|
self.gridLayout.addWidget(self.label_7, 3, 3, 1, 1)
|
||||||
|
self.AccessRights = QtGui.QLineEdit(self.widget)
|
||||||
|
self.AccessRights.setReadOnly(True)
|
||||||
|
self.AccessRights.setObjectName("AccessRights")
|
||||||
|
self.gridLayout.addWidget(self.AccessRights, 3, 4, 1, 1)
|
||||||
|
self.label_8 = QtGui.QLabel(self.widget)
|
||||||
|
self.label_8.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.label_8.setObjectName("label_8")
|
||||||
|
self.gridLayout.addWidget(self.label_8, 4, 0, 1, 1)
|
||||||
|
self.Contents = QtGui.QLineEdit(self.widget)
|
||||||
|
self.Contents.setReadOnly(True)
|
||||||
|
self.Contents.setObjectName("Contents")
|
||||||
|
self.gridLayout.addWidget(self.Contents, 4, 1, 1, 1)
|
||||||
|
self.IOSversion = QtGui.QComboBox(self.widget)
|
||||||
|
self.IOSversion.setObjectName("IOSversion")
|
||||||
|
self.gridLayout.addWidget(self.IOSversion, 2, 1, 1, 1)
|
||||||
|
self.tabWidget.addTab(self.TMDviewer, "")
|
||||||
|
self.packtab = QtGui.QWidget()
|
||||||
|
self.packtab.setObjectName("packtab")
|
||||||
|
self.MuestraRutaEmpaquetado = QtGui.QLineEdit(self.packtab)
|
||||||
|
self.MuestraRutaEmpaquetado.setGeometry(QtCore.QRect(160, 110, 241, 26))
|
||||||
|
self.MuestraRutaEmpaquetado.setObjectName("MuestraRutaEmpaquetado")
|
||||||
|
self.MuestraRutaDesempaquetado = QtGui.QLineEdit(self.packtab)
|
||||||
|
self.MuestraRutaDesempaquetado.setGeometry(QtCore.QRect(160, 40, 241, 26))
|
||||||
|
self.MuestraRutaDesempaquetado.setObjectName("MuestraRutaDesempaquetado")
|
||||||
|
self.BotonRutaEmpaquetado = QtGui.QToolButton(self.packtab)
|
||||||
|
self.BotonRutaEmpaquetado.setGeometry(QtCore.QRect(70, 110, 91, 25))
|
||||||
|
self.BotonRutaEmpaquetado.setAutoRaise(False)
|
||||||
|
self.BotonRutaEmpaquetado.setArrowType(QtCore.Qt.NoArrow)
|
||||||
|
self.BotonRutaEmpaquetado.setObjectName("BotonRutaEmpaquetado")
|
||||||
|
self.BotonRutaDesempaquetado = QtGui.QToolButton(self.packtab)
|
||||||
|
self.BotonRutaDesempaquetado.setGeometry(QtCore.QRect(70, 40, 91, 25))
|
||||||
|
self.BotonRutaDesempaquetado.setObjectName("BotonRutaDesempaquetado")
|
||||||
|
self.Empaqueta = QtGui.QPushButton(self.packtab)
|
||||||
|
self.Empaqueta.setGeometry(QtCore.QRect(170, 180, 121, 25))
|
||||||
|
self.Empaqueta.setObjectName("Empaqueta")
|
||||||
|
self.tabWidget.addTab(self.packtab, "")
|
||||||
|
self.NUStab = QtGui.QWidget()
|
||||||
|
self.NUStab.setObjectName("NUStab")
|
||||||
|
self.NusOutputPath = QtGui.QLineEdit(self.NUStab)
|
||||||
|
self.NusOutputPath.setGeometry(QtCore.QRect(140, 150, 241, 26))
|
||||||
|
self.NusOutputPath.setObjectName("NusOutputPath")
|
||||||
|
self.Download_from_NUS = QtGui.QPushButton(self.NUStab)
|
||||||
|
self.Download_from_NUS.setGeometry(QtCore.QRect(170, 180, 121, 25))
|
||||||
|
self.Download_from_NUS.setObjectName("Download_from_NUS")
|
||||||
|
self.NusOutputButton = QtGui.QToolButton(self.NUStab)
|
||||||
|
self.NusOutputButton.setGeometry(QtCore.QRect(40, 150, 91, 25))
|
||||||
|
self.NusOutputButton.setAutoRaise(False)
|
||||||
|
self.NusOutputButton.setArrowType(QtCore.Qt.NoArrow)
|
||||||
|
self.NusOutputButton.setObjectName("NusOutputButton")
|
||||||
|
self.enteredTitleID = QtGui.QLineEdit(self.NUStab)
|
||||||
|
self.enteredTitleID.setGeometry(QtCore.QRect(125, 45, 161, 31))
|
||||||
|
self.enteredTitleID.setObjectName("enteredTitleID")
|
||||||
|
self.TitleIDlabel = QtGui.QLabel(self.NUStab)
|
||||||
|
self.TitleIDlabel.setGeometry(QtCore.QRect(15, 51, 101, 20))
|
||||||
|
self.TitleIDlabel.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTop|QtCore.Qt.AlignTrailing)
|
||||||
|
self.TitleIDlabel.setObjectName("TitleIDlabel")
|
||||||
|
self.Title = QtGui.QLabel(self.NUStab)
|
||||||
|
self.Title.setGeometry(QtCore.QRect(0, 10, 121, 21))
|
||||||
|
self.Title.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.Title.setObjectName("Title")
|
||||||
|
self.comboBox = QtGui.QComboBox(self.NUStab)
|
||||||
|
self.comboBox.setGeometry(QtCore.QRect(125, 10, 291, 25))
|
||||||
|
self.comboBox.setObjectName("comboBox")
|
||||||
|
self.comboBox.addItem(QtCore.QString())
|
||||||
|
self.decryptCheck = QtGui.QCheckBox(self.NUStab)
|
||||||
|
self.decryptCheck.setEnabled(False)
|
||||||
|
self.decryptCheck.setGeometry(QtCore.QRect(130, 80, 171, 23))
|
||||||
|
self.decryptCheck.setChecked(False)
|
||||||
|
self.decryptCheck.setObjectName("decryptCheck")
|
||||||
|
self.pack_in_WAD_checkbox = QtGui.QCheckBox(self.NUStab)
|
||||||
|
self.pack_in_WAD_checkbox.setGeometry(QtCore.QRect(130, 110, 181, 23))
|
||||||
|
self.pack_in_WAD_checkbox.setChecked(True)
|
||||||
|
self.pack_in_WAD_checkbox.setObjectName("pack_in_WAD_checkbox")
|
||||||
|
self.VersionlineEdit = QtGui.QLineEdit(self.NUStab)
|
||||||
|
self.VersionlineEdit.setGeometry(QtCore.QRect(340, 45, 71, 31))
|
||||||
|
self.VersionlineEdit.setObjectName("VersionlineEdit")
|
||||||
|
self.versionlabel = QtGui.QLabel(self.NUStab)
|
||||||
|
self.versionlabel.setGeometry(QtCore.QRect(290, 50, 51, 20))
|
||||||
|
self.versionlabel.setObjectName("versionlabel")
|
||||||
|
self.tabWidget.addTab(self.NUStab, "")
|
||||||
|
Qwad.setCentralWidget(self.centralWidget)
|
||||||
|
self.menuBar = QtGui.QMenuBar(Qwad)
|
||||||
|
self.menuBar.setGeometry(QtCore.QRect(0, 0, 481, 22))
|
||||||
|
self.menuBar.setObjectName("menuBar")
|
||||||
|
self.menuAyuda = QtGui.QMenu(self.menuBar)
|
||||||
|
self.menuAyuda.setObjectName("menuAyuda")
|
||||||
|
Qwad.setMenuBar(self.menuBar)
|
||||||
|
self.statusBar = QtGui.QStatusBar(Qwad)
|
||||||
|
self.statusBar.setObjectName("statusBar")
|
||||||
|
Qwad.setStatusBar(self.statusBar)
|
||||||
|
self.actionAcerca_de_Qwad = QtGui.QAction(Qwad)
|
||||||
|
self.actionAcerca_de_Qwad.setIcon(icon)
|
||||||
|
self.actionAcerca_de_Qwad.setObjectName("actionAcerca_de_Qwad")
|
||||||
|
self.actionAbout_Qt = QtGui.QAction(Qwad)
|
||||||
|
icon1 = QtGui.QIcon()
|
||||||
|
icon1.addPixmap(QtGui.QPixmap(":/icons/qt4.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.actionAbout_Qt.setIcon(icon1)
|
||||||
|
self.actionAbout_Qt.setObjectName("actionAbout_Qt")
|
||||||
|
self.actionAbout_Wii_Signer = QtGui.QAction(Qwad)
|
||||||
|
self.actionAbout_Wii_Signer.setObjectName("actionAbout_Wii_Signer")
|
||||||
|
self.menuAyuda.addAction(self.actionAcerca_de_Qwad)
|
||||||
|
self.menuAyuda.addAction(self.actionAbout_Qt)
|
||||||
|
self.menuBar.addAction(self.menuAyuda.menuAction())
|
||||||
|
|
||||||
|
self.retranslateUi(Qwad)
|
||||||
|
self.tabWidget.setCurrentIndex(1)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(Qwad)
|
||||||
|
|
||||||
|
def retranslateUi(self, Qwad):
|
||||||
|
Qwad.setWindowTitle(QtGui.QApplication.translate("Qwad", "Qwad - a WAD management tool", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaWad.setToolTip(QtGui.QApplication.translate("Qwad", "Ruta hacia el archivo WAD que quieres desempaquetar", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaWad.setText(QtGui.QApplication.translate("Qwad", "WAD file", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaExtraer.setToolTip(QtGui.QApplication.translate("Qwad", "Carpeta donde se almacenaran los contenidos del archivo WAD", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaExtraer.setText(QtGui.QApplication.translate("Qwad", "Output", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.Desempaqueta.setText(QtGui.QApplication.translate("Qwad", "Unpack", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.unpacktab), QtGui.QApplication.translate("Qwad", "Unpack WAD", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.TMDfilebutton.setToolTip(QtGui.QApplication.translate("Qwad", "Ruta hacia el archivo WAD que quieres desempaquetar", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.TMDfilebutton.setText(QtGui.QApplication.translate("Qwad", "TMD file", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label.setText(QtGui.QApplication.translate("Qwad", "Title ID", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.TitleID.setText(QtGui.QApplication.translate("Qwad", "0000000000000000", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_9.setText(QtGui.QApplication.translate("Qwad", "ID (ascii)", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_3.setText(QtGui.QApplication.translate("Qwad", "Version", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.Version.setText(QtGui.QApplication.translate("Qwad", "0", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_5.setText(QtGui.QApplication.translate("Qwad", "Title type", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_2.setText(QtGui.QApplication.translate("Qwad", "IOS needed", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_6.setText(QtGui.QApplication.translate("Qwad", "Group ID", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_4.setText(QtGui.QApplication.translate("Qwad", "Boot index", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_7.setText(QtGui.QApplication.translate("Qwad", "Access rights", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_8.setText(QtGui.QApplication.translate("Qwad", "Contents", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.TMDviewer), QtGui.QApplication.translate("Qwad", "TMD viewer", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaEmpaquetado.setToolTip(QtGui.QApplication.translate("Qwad", "Carpeta y nombre del nuevo WAD", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaEmpaquetado.setText(QtGui.QApplication.translate("Qwad", "Output", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaDesempaquetado.setToolTip(QtGui.QApplication.translate("Qwad", "Ruta hacia la carpeta que empaquetar en WAD", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.BotonRutaDesempaquetado.setText(QtGui.QApplication.translate("Qwad", "Folder", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.Empaqueta.setText(QtGui.QApplication.translate("Qwad", "Pack", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.packtab), QtGui.QApplication.translate("Qwad", "Pack WAD", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.Download_from_NUS.setText(QtGui.QApplication.translate("Qwad", "Download", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.NusOutputButton.setToolTip(QtGui.QApplication.translate("Qwad", "Carpeta y nombre del nuevo WAD", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.NusOutputButton.setText(QtGui.QApplication.translate("Qwad", "Output", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.enteredTitleID.setText(QtGui.QApplication.translate("Qwad", "000000000000000000", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.TitleIDlabel.setText(QtGui.QApplication.translate("Qwad", "Title ID", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.Title.setText(QtGui.QApplication.translate("Qwad", "Choose title:", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.comboBox.setItemText(0, QtGui.QApplication.translate("Qwad", "Custom title ID", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.decryptCheck.setText(QtGui.QApplication.translate("Qwad", "Decrypt", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.pack_in_WAD_checkbox.setText(QtGui.QApplication.translate("Qwad", "Pack into WAD", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.VersionlineEdit.setText(QtGui.QApplication.translate("Qwad", "unset", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.versionlabel.setText(QtGui.QApplication.translate("Qwad", "Version:", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.NUStab), QtGui.QApplication.translate("Qwad", "Download from NUS", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.menuAyuda.setTitle(QtGui.QApplication.translate("Qwad", "Help", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.actionAcerca_de_Qwad.setText(QtGui.QApplication.translate("Qwad", "About Qwad", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.actionAbout_Qt.setText(QtGui.QApplication.translate("Qwad", "About Qt", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.actionAbout_Wii_Signer.setText(QtGui.QApplication.translate("Qwad", "About Wii Signer", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
|
import Qwad_rc
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtGui.QApplication(sys.argv)
|
||||||
|
Qwad = QtGui.QMainWindow()
|
||||||
|
ui = Ui_Qwad()
|
||||||
|
ui.setupUi(Qwad)
|
||||||
|
Qwad.show()
|
||||||
|
sys.exit(app.exec_())
|
||||||
|
|
337
GUI/VenPri.py
Normal file
337
GUI/VenPri.py
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Module implementing Qwad's main window
|
||||||
|
"""
|
||||||
|
from PyQt4.QtGui import QMainWindow,QFileDialog,QMessageBox, QLabel
|
||||||
|
from PyQt4.QtCore import pyqtSignature,QString,QT_TR_NOOP,SIGNAL,QObject
|
||||||
|
from WiiPy.archive import WAD
|
||||||
|
from WiiPy.title import NUS, TMD
|
||||||
|
from Ui_VenPri import Ui_Qwad
|
||||||
|
from shutil import rmtree
|
||||||
|
from threading import Thread
|
||||||
|
import TitleIDs
|
||||||
|
import tempfile, os, time
|
||||||
|
|
||||||
|
CWD = os.getcwd()
|
||||||
|
|
||||||
|
class MWQwad(QMainWindow, Ui_Qwad):
|
||||||
|
"""
|
||||||
|
Class documentation goes here.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
"""
|
||||||
|
QMainWindow.__init__(self, parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
self.defaultversion = self.trUtf8("""(Latest)""")
|
||||||
|
self.VersionlineEdit.setText(self.defaultversion)
|
||||||
|
for key in sorted(TitleIDs.TitleDict):
|
||||||
|
self.comboBox.addItem(key)
|
||||||
|
for ios in sorted(TitleIDs.IOSdict):
|
||||||
|
self.IOSversion.addItem(ios)
|
||||||
|
self.getReady()
|
||||||
|
|
||||||
|
def Status(self,status):
|
||||||
|
print status
|
||||||
|
self.setEnabled(False)
|
||||||
|
self.statusBar.showMessage(status)
|
||||||
|
|
||||||
|
def getReady(self):
|
||||||
|
self.setEnabled(True)
|
||||||
|
self.statusBar.showMessage(self.trUtf8("Ready"))
|
||||||
|
os.chdir(CWD)
|
||||||
|
print "Done."
|
||||||
|
|
||||||
|
|
||||||
|
def ErrorDiag(self, error = QT_TR_NOOP("Unknown error")):
|
||||||
|
print error
|
||||||
|
QMessageBox.critical(None,
|
||||||
|
self.trUtf8("Error"),
|
||||||
|
self.trUtf8("""An error has ocurred:""") +" " + str(error),
|
||||||
|
QMessageBox.StandardButtons(\
|
||||||
|
QMessageBox.Ok),
|
||||||
|
QMessageBox.Ok)
|
||||||
|
|
||||||
|
def loadTMD(self,tmdpath):#TODO: TMD viewer
|
||||||
|
"""
|
||||||
|
Displays _TMD information in the UI
|
||||||
|
"""
|
||||||
|
tmd = TMD().loadFile(tmdpath)
|
||||||
|
self.TitleID.setText("%016x" % tmd.tmd.titleid)
|
||||||
|
# print tmd.tmd.version
|
||||||
|
#self.IOSversion.setText("%016x" % tmd.tmd.iosversion)
|
||||||
|
self.TitleType.setText(str(tmd.tmd.title_type))
|
||||||
|
self.GroupID.setText(str(tmd.tmd.group_id))
|
||||||
|
# print tmd.tmd.reserved
|
||||||
|
self.AccessRights.setText(str(tmd.tmd.access_rights))
|
||||||
|
self.Version.setText(str(tmd.tmd.title_version))
|
||||||
|
self.Contents.setText(str(tmd.tmd.numcontents))
|
||||||
|
self.BootIndex.setText(str(tmd.tmd.boot_index))
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_BotonRutaWad_clicked(self):
|
||||||
|
"""
|
||||||
|
Get path to WAD file
|
||||||
|
"""
|
||||||
|
WadPath = QFileDialog.getOpenFileName(\
|
||||||
|
None,
|
||||||
|
self.trUtf8("Select WAD file"),
|
||||||
|
QString(),
|
||||||
|
self.trUtf8("*.wad; *.WAD"),
|
||||||
|
None)
|
||||||
|
if WadPath != "" :
|
||||||
|
self.MuestraRutaWad.setText(WadPath)
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_BotonRutaExtraer_clicked(self):
|
||||||
|
"""
|
||||||
|
WAD contents output path
|
||||||
|
"""
|
||||||
|
OutputDir = QFileDialog.getExistingDirectory(\
|
||||||
|
None,
|
||||||
|
self.trUtf8("Select where to store WAD contents"),
|
||||||
|
QString(),
|
||||||
|
QFileDialog.Options(QFileDialog.ShowDirsOnly))
|
||||||
|
if OutputDir != "":
|
||||||
|
self.MuestraRutaExtraer.setText(OutputDir)
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_Desempaqueta_clicked(self):
|
||||||
|
"""
|
||||||
|
Unpack wad
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.unpack = Unpacking(str(self.MuestraRutaWad.text()), str(self.MuestraRutaExtraer.text()), self)
|
||||||
|
self.unpack.start()
|
||||||
|
except Exception, e:
|
||||||
|
self.ErrorDiag(e)
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_BotonRutaEmpaquetado_clicked(self):
|
||||||
|
"""
|
||||||
|
Select where to save the newly created WAD
|
||||||
|
"""
|
||||||
|
NewWadPath = QFileDialog.getSaveFileName(\
|
||||||
|
None,
|
||||||
|
self.trUtf8("Select where to save the newly created WAD"),
|
||||||
|
QString("output.wad"),
|
||||||
|
self.trUtf8("*.wad; *.WAD"),
|
||||||
|
None)
|
||||||
|
if NewWadPath != "":
|
||||||
|
self.MuestraRutaEmpaquetado.setText(NewWadPath)
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_BotonRutaDesempaquetado_clicked(self):
|
||||||
|
"""
|
||||||
|
Get path off folder to pack.
|
||||||
|
"""
|
||||||
|
Dir2Wad = QFileDialog.getExistingDirectory(\
|
||||||
|
None,
|
||||||
|
self.trUtf8("Select folder to pack into WAD"),
|
||||||
|
QString(),
|
||||||
|
QFileDialog.Options(QFileDialog.ShowDirsOnly))
|
||||||
|
if Dir2Wad != "":
|
||||||
|
self.MuestraRutaDesempaquetado.setText(Dir2Wad)
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_Empaqueta_clicked(self):
|
||||||
|
"""
|
||||||
|
Create WAD
|
||||||
|
"""
|
||||||
|
self.setEnabled(False)
|
||||||
|
try:
|
||||||
|
self.packing = Packing(str(self.MuestraRutaDesempaquetado.text()),str(self.MuestraRutaEmpaquetado.text()), self)
|
||||||
|
self.packing.start()
|
||||||
|
except Exception, e:
|
||||||
|
self.ErrorDiag(e)
|
||||||
|
self.setEnabled(True)
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_actionAcerca_de_Qwad_triggered(self):
|
||||||
|
"""
|
||||||
|
About Qwad
|
||||||
|
"""
|
||||||
|
from AboutQwad import AboutQwad
|
||||||
|
Pop = AboutQwad()
|
||||||
|
Pop.exec_()
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_actionAbout_Qt_triggered(self):
|
||||||
|
"""
|
||||||
|
About Qt
|
||||||
|
"""
|
||||||
|
QMessageBox.aboutQt(None,
|
||||||
|
self.trUtf8("About Qt"))
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_Download_from_NUS_clicked(self):
|
||||||
|
"""
|
||||||
|
Start doing the actual work... well, in fact, the actual work is done by Wii.py
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
version = self.VersionlineEdit.text()
|
||||||
|
if version == self.defaultversion:
|
||||||
|
print "downloading latest version"
|
||||||
|
version = None
|
||||||
|
else:
|
||||||
|
version = str(version)
|
||||||
|
print "downloading version " + version
|
||||||
|
outputdir = str(self.NusOutputPath.text())
|
||||||
|
self.nusdow = nusDownloading(int(str(self.enteredTitleID.text()).lower(),16), version, outputdir, self.decryptCheck.isChecked(), self)
|
||||||
|
self.nusdow.start()
|
||||||
|
except Exception, e:
|
||||||
|
self.ErrorDiag(e)
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_NusOutputButton_clicked(self):
|
||||||
|
"""
|
||||||
|
Selects the output path
|
||||||
|
"""
|
||||||
|
if self.pack_in_WAD_checkbox.isChecked():
|
||||||
|
outputdir = QFileDialog.getSaveFileName(\
|
||||||
|
None,
|
||||||
|
self.trUtf8("Select where to save the downloaded WAD"),
|
||||||
|
QString(),
|
||||||
|
self.trUtf8("*.wad; *.WAD"),
|
||||||
|
None)
|
||||||
|
else:
|
||||||
|
outputdir = QFileDialog.getExistingDirectory(\
|
||||||
|
None,
|
||||||
|
self.trUtf8("Select the directory where store the downloaded files"),
|
||||||
|
QString(),
|
||||||
|
QFileDialog.Options(QFileDialog.ShowDirsOnly))
|
||||||
|
if outputdir != "":
|
||||||
|
self.NusOutputPath.setText(outputdir)
|
||||||
|
|
||||||
|
@pyqtSignature("QString")
|
||||||
|
def on_comboBox_currentIndexChanged(self, selection):
|
||||||
|
"""
|
||||||
|
Show the title ID of the selected title
|
||||||
|
"""
|
||||||
|
if self.comboBox.findText(selection) != 0:
|
||||||
|
self.enteredTitleID.enabled = False
|
||||||
|
self.enteredTitleID.setText(TitleIDs.TitleDict[str(selection)])
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_enteredTitleID_returnPressed(self):
|
||||||
|
"""
|
||||||
|
Place combobox un custom titleid
|
||||||
|
"""
|
||||||
|
self.comboBox.setCurrentIndex(0)
|
||||||
|
|
||||||
|
@pyqtSignature("int")
|
||||||
|
def on_pack_in_WAD_checkbox_stateChanged(self, state):
|
||||||
|
"""
|
||||||
|
Clear output path, because we change output type
|
||||||
|
"""
|
||||||
|
self.NusOutputPath.clear()
|
||||||
|
if state == 2:
|
||||||
|
self.decryptCheck.setChecked(False)
|
||||||
|
self.decryptCheck.setEnabled(False)
|
||||||
|
elif state == 0:
|
||||||
|
self.decryptCheck.setChecked(True)
|
||||||
|
self.decryptCheck.setEnabled(True)
|
||||||
|
elif state == 1:
|
||||||
|
print "OMG, what are you doing?"
|
||||||
|
else:
|
||||||
|
print "This is the end of the world. For PyQt4, at least"
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_TMDfilepath_returnPressed(self):
|
||||||
|
"""
|
||||||
|
Trigger loadTMD
|
||||||
|
"""
|
||||||
|
self.loadTMD(str(self.TMDfilepath.text()))
|
||||||
|
|
||||||
|
@pyqtSignature("")
|
||||||
|
def on_TMDfilebutton_clicked(self):
|
||||||
|
"""
|
||||||
|
Trigger loadTMD
|
||||||
|
"""
|
||||||
|
tmdpath = QFileDialog.getOpenFileName(\
|
||||||
|
None,
|
||||||
|
self.trUtf8("Select a TMD file"),
|
||||||
|
QString(),
|
||||||
|
self.trUtf8("tmd; TMD"),
|
||||||
|
None,
|
||||||
|
QFileDialog.Options(QFileDialog.DontResolveSymlinks))
|
||||||
|
if tmdpath != "":
|
||||||
|
self.TMDfilepath.setText(tmdpath)
|
||||||
|
self.loadTMD(str(tmdpath))
|
||||||
|
|
||||||
|
#Here useful thread classes
|
||||||
|
class Unpacking(Thread):
|
||||||
|
def __init__(self, wadpath, dirpath, QMW):
|
||||||
|
Thread.__init__(self)
|
||||||
|
self.wadpath = wadpath
|
||||||
|
self.dirpath = dirpath
|
||||||
|
self.QMW = QMW
|
||||||
|
self.qobject = QObject()
|
||||||
|
self.qobject.connect(self.qobject, SIGNAL("working"),self.QMW.Status)
|
||||||
|
self.qobject.connect(self.qobject, SIGNAL("Exception"),self.QMW.ErrorDiag)
|
||||||
|
self.qobject.connect(self.qobject, SIGNAL("Done"),self.QMW.getReady)
|
||||||
|
def run(self):
|
||||||
|
self.qobject.emit(SIGNAL("working"),UNPACKING)
|
||||||
|
try:
|
||||||
|
WAD.loadFile(self.wadpath).dumpDir(self.dirpath)
|
||||||
|
except Exception, e:
|
||||||
|
print e
|
||||||
|
self.qobject.emit(SIGNAL("Exception"),e)
|
||||||
|
self.qobject.emit(SIGNAL("Done"))
|
||||||
|
|
||||||
|
class Packing(Unpacking):
|
||||||
|
def __init__(self, dirpath, wadpath, QMW, deletedir = False):
|
||||||
|
Unpacking.__init__(self, wadpath, dirpath, QMW)
|
||||||
|
self.deletedir = deletedir
|
||||||
|
def run(self):
|
||||||
|
self.qobject.emit(SIGNAL("working"),PACKING)
|
||||||
|
try:
|
||||||
|
print self.dirpath
|
||||||
|
print self.wadpath
|
||||||
|
WAD.loadDir(self.dirpath).dumpFile(self.wadpath)
|
||||||
|
if self.deletedir:
|
||||||
|
print "Cleaning temporary files"
|
||||||
|
self.qobject.emit(SIGNAL("working"),CLEANING)
|
||||||
|
rmtree(self.dirpath)
|
||||||
|
except Exception, e:
|
||||||
|
if self.deletedir:
|
||||||
|
print "Cleaning temporary files"
|
||||||
|
self.qobject.emit(SIGNAL("working"),CLEANING)
|
||||||
|
rmtree(self.dirpath)
|
||||||
|
print e
|
||||||
|
self.qobject.emit(SIGNAL("Exception"),e)
|
||||||
|
self.qobject.emit(SIGNAL("Done"))
|
||||||
|
|
||||||
|
class nusDownloading(Unpacking):
|
||||||
|
def __init__(self, titleid, version, outputdir, decrypt, QMW):
|
||||||
|
Unpacking.__init__(self, None, outputdir, QMW)
|
||||||
|
if version != None:
|
||||||
|
self.version = int(version)
|
||||||
|
else:
|
||||||
|
self.version = None
|
||||||
|
self.decrypt = decrypt
|
||||||
|
self.titleid = titleid
|
||||||
|
def run(self):
|
||||||
|
self.qobject.emit(SIGNAL("working"),DOWNLOADING)
|
||||||
|
try:
|
||||||
|
if self.QMW.pack_in_WAD_checkbox.isChecked():
|
||||||
|
self.dirpath = tempfile.gettempdir() + "/NUS_"+ str(time.time()).replace(".","") # A safe place for temporary files
|
||||||
|
NUS(self.titleid,self.version).download(self.dirpath, decrypt = self.decrypt)
|
||||||
|
self.packing = Packing(self.dirpath, str(self.QMW.NusOutputPath.text()), self.QMW, True)
|
||||||
|
self.packing.start()
|
||||||
|
else:
|
||||||
|
NUS(self.titleid,self.version).download(self.dirpath, decrypt = self.decrypt)
|
||||||
|
self.qobject.emit(SIGNAL("Done"))
|
||||||
|
except Exception, e:
|
||||||
|
print e
|
||||||
|
Errormsg = str(e) + ". " + QT_TR_NOOP(QString("Title %1 version %2 maybe isn't available for download on NUS.").arg(str(self.titleid)).arg(str(self.version)))
|
||||||
|
self.qobject.emit(SIGNAL("Exception"),Errormsg)
|
||||||
|
self.qobject.emit(SIGNAL("Done"))
|
||||||
|
|
||||||
|
#Statusbar messages
|
||||||
|
#FIXME: Why don't they get translated? It's frustrating
|
||||||
|
DOWNLOADING = QT_TR_NOOP("Downloading files from NUS... This may take a while, please, be patient.")
|
||||||
|
UNPACKING = QT_TR_NOOP("Unpacking WAD...")
|
||||||
|
PACKING = QT_TR_NOOP("Packing into WAD...")
|
||||||
|
CLEANING = QT_TR_NOOP("Cleaning temporary files...")
|
633
GUI/VenPri.ui
Normal file
633
GUI/VenPri.ui
Normal file
@ -0,0 +1,633 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Qwad</class>
|
||||||
|
<widget class="QMainWindow" name="Qwad">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>481</width>
|
||||||
|
<height>296</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>481</width>
|
||||||
|
<height>296</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>481</width>
|
||||||
|
<height>296</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Qwad - a WAD management tool</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="../Qwad.qrc">
|
||||||
|
<normaloff>:/icons/wad.png</normaloff>:/icons/wad.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="Spanish" country="Spain"/>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralWidget">
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>481</width>
|
||||||
|
<height>251</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="unpacktab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Unpack WAD</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLineEdit" name="MuestraRutaWad">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolButton" name="BotonRutaWad">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>70</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Ruta hacia el archivo WAD que quieres desempaquetar</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>WAD file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="MuestraRutaExtraer">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>110</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolButton" name="BotonRutaExtraer">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>70</x>
|
||||||
|
<y>110</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Carpeta donde se almacenaran los contenidos del archivo WAD</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Output</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="arrowType">
|
||||||
|
<enum>Qt::NoArrow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="Desempaqueta">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>170</x>
|
||||||
|
<y>180</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Unpack</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="TMDviewer">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>TMD viewer</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLineEdit" name="TMDfilepath">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>150</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolButton" name="TMDfilebutton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>60</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Ruta hacia el archivo WAD que quieres desempaquetar</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>TMD file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>451</width>
|
||||||
|
<height>147</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Title ID</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="TitleID">
|
||||||
|
<property name="text">
|
||||||
|
<string>0000000000000000</string>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>ID (ascii)</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QLineEdit" name="idASCII">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Version</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="Version">
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Title type</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QLineEdit" name="TitleType">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>IOS needed</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Group ID</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="4">
|
||||||
|
<widget class="QLineEdit" name="GroupID">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Boot index</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="BootIndex">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="3">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Access rights</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="4">
|
||||||
|
<widget class="QLineEdit" name="AccessRights">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Contents</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="Contents">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QComboBox" name="IOSversion"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="packtab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Pack WAD</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLineEdit" name="MuestraRutaEmpaquetado">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>110</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="MuestraRutaDesempaquetado">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolButton" name="BotonRutaEmpaquetado">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>70</x>
|
||||||
|
<y>110</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Carpeta y nombre del nuevo WAD</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Output</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="arrowType">
|
||||||
|
<enum>Qt::NoArrow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolButton" name="BotonRutaDesempaquetado">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>70</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Ruta hacia la carpeta que empaquetar en WAD</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Folder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="Empaqueta">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>170</x>
|
||||||
|
<y>180</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pack</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="NUStab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Download from NUS</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLineEdit" name="NusOutputPath">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>140</x>
|
||||||
|
<y>150</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="Download_from_NUS">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>170</x>
|
||||||
|
<y>180</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedStates"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Download</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolButton" name="NusOutputButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>40</x>
|
||||||
|
<y>150</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Carpeta y nombre del nuevo WAD</string>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedStates"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Output</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="arrowType">
|
||||||
|
<enum>Qt::NoArrow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="enteredTitleID">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>125</x>
|
||||||
|
<y>45</y>
|
||||||
|
<width>161</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedStates"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>000000000000000000</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="TitleIDlabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>15</x>
|
||||||
|
<y>51</y>
|
||||||
|
<width>101</width>
|
||||||
|
<height>20</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="UnitedStates"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Title ID</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="Title">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Choose title:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="comboBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>125</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>291</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Custom title ID</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="decryptCheck">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>130</x>
|
||||||
|
<y>80</y>
|
||||||
|
<width>171</width>
|
||||||
|
<height>23</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Decrypt</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="pack_in_WAD_checkbox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>130</x>
|
||||||
|
<y>110</y>
|
||||||
|
<width>181</width>
|
||||||
|
<height>23</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pack into WAD</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="VersionlineEdit">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>340</x>
|
||||||
|
<y>45</y>
|
||||||
|
<width>71</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>unset</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="versionlabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>290</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>51</width>
|
||||||
|
<height>20</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Version:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menuBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>481</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuAyuda">
|
||||||
|
<property name="title">
|
||||||
|
<string>Help</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionAcerca_de_Qwad"/>
|
||||||
|
<addaction name="actionAbout_Qt"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuAyuda"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusBar"/>
|
||||||
|
<action name="actionAcerca_de_Qwad">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../Qwad.qrc">
|
||||||
|
<normaloff>:/icons/wad.png</normaloff>:/icons/wad.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>About Qwad</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionAbout_Qt">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../Qwad.qrc">
|
||||||
|
<normaloff>:/icons/qt4.png</normaloff>:/icons/qt4.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>About Qt</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionAbout_Wii_Signer">
|
||||||
|
<property name="text">
|
||||||
|
<string>About Wii Signer</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../Qwad.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
0
GUI/__init__.py
Normal file
0
GUI/__init__.py
Normal file
3
Qwad.pro
Normal file
3
Qwad.pro
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
TRANSLATIONS = i18n/Qwad_es.ts \
|
||||||
|
i18n/Qwad_en.ts \
|
||||||
|
i18n/Qwad_ca.ts \
|
21
Qwad.pyw
Normal file
21
Qwad.pyw
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#-*- coding: utf-8 -*-
|
||||||
|
import sys
|
||||||
|
from PyQt4.QtGui import QApplication
|
||||||
|
from PyQt4.QtCore import QTranslator, QString, QLocale
|
||||||
|
from GUI.VenPri import MWQwad
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
translator = QTranslator()
|
||||||
|
translator.load(QString("i18n/Qwad_%1").arg(QLocale.system().name()))
|
||||||
|
qttranslator = QTranslator()
|
||||||
|
qttranslator.load(QString("qt_%1").arg(QLocale.system().name()))
|
||||||
|
Vapp = QApplication(sys.argv)
|
||||||
|
Vapp.setOrganizationName("ssorgatem productions")
|
||||||
|
Vapp.setApplicationName("Qwad")
|
||||||
|
Vapp.installTranslator(translator)
|
||||||
|
Vapp.installTranslator(qttranslator)
|
||||||
|
VentanaP = MWQwad()
|
||||||
|
VentanaP.show()
|
||||||
|
sys.exit(Vapp.exec_())
|
||||||
|
|
7
Qwad.qrc
Normal file
7
Qwad.qrc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE RCC>
|
||||||
|
<RCC version="1.0">
|
||||||
|
<qresource>
|
||||||
|
<file>icons/wad.png</file>
|
||||||
|
<file>icons/qt4.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
2154
Qwad_rc.py
Normal file
2154
Qwad_rc.py
Normal file
File diff suppressed because it is too large
Load Diff
90
TitleIDs.py
Normal file
90
TitleIDs.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#-*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
module storing a titleid dictionary
|
||||||
|
"""
|
||||||
|
import binascii, re
|
||||||
|
from PyQt4.QtCore import QT_TR_NOOP
|
||||||
|
|
||||||
|
TitleDict = {
|
||||||
|
#"BOOT2":"0000000100000001",
|
||||||
|
"System Menu":"0000000100000002",
|
||||||
|
#"BC":"0000000100000100",
|
||||||
|
"MIOS":"0000000100000101",
|
||||||
|
"IOS4":"0000000100000004",
|
||||||
|
"IOS9":"0000000100000009",
|
||||||
|
"IOS10":"000000010000000a",
|
||||||
|
"IOS11":"000000010000000b",
|
||||||
|
"IOS12":"000000010000000c",
|
||||||
|
"IOS13":"000000010000000d",
|
||||||
|
"IOS14":"000000010000000e",
|
||||||
|
"IOS15":"000000010000000f",
|
||||||
|
"IOS16":"0000000100000010",
|
||||||
|
"IOS17":"0000000100000011",
|
||||||
|
"IOS20":"0000000100000014",
|
||||||
|
"IOS21":"0000000100000015",
|
||||||
|
"IOS22":"0000000100000016",
|
||||||
|
"IOS28":"000000010000001c",
|
||||||
|
"IOS30":"000000010000001e",
|
||||||
|
"IOS31":"000000010000001f",
|
||||||
|
"IOS33":"0000000100000021",
|
||||||
|
"IOS34":"0000000100000022",
|
||||||
|
"IOS35":"0000000100000023",
|
||||||
|
"IOS36":"0000000100000024",
|
||||||
|
"IOS37":"0000000100000025",
|
||||||
|
"IOS38":"0000000100000026",
|
||||||
|
"IOS50":"0000000100000032",
|
||||||
|
"IOS51":"0000000100000033",
|
||||||
|
"IOS53":"0000000100000035",
|
||||||
|
"IOS55":"0000000100000037",
|
||||||
|
"IOS60":"000000010000003c",
|
||||||
|
"IOS61":"000000010000003d",
|
||||||
|
"IOS254":"00000001000000fe",
|
||||||
|
#TODO: Add remaining IOSes
|
||||||
|
#QT_TR_NOOP("Wii Speak Channel"):"00010001484346xx",
|
||||||
|
#QT_TR_NOOP("Photo Channel 1.1 [USA]"):"0001000148415a45",
|
||||||
|
QT_TR_NOOP("Photo Channel 1.1 [PAL]"):"0001000148415a50",
|
||||||
|
#QT_TR_NOOP("Photo Channel 1.1 [JAP]"):"0001000148415a4a",
|
||||||
|
#QT_TR_NOOP("Metroid Prime 3 Preview"):"00010001484157xx",
|
||||||
|
QT_TR_NOOP("Nintendo Channel"):"00010001484154xx",
|
||||||
|
QT_TR_NOOP("Check Mii Out / Mii Contest Channel[USA]"):"0001000148415045",
|
||||||
|
QT_TR_NOOP("Check Mii Out / Mii Contest Channel[PAL]"):"0001000148415050",
|
||||||
|
QT_TR_NOOP("Check Mii Out / Mii Contest Channel[JAP]"):"000100014841504A",
|
||||||
|
QT_TR_NOOP("Everyone Votes Channel[USA]"):"0001000148414a45",
|
||||||
|
QT_TR_NOOP("Everyone Votes Channel[PAL]"):"0001000148414a50",
|
||||||
|
QT_TR_NOOP("Everyone Votes Channel[JAP]"):"0001000148414a4A",
|
||||||
|
#QT_TR_NOOP("Opera / Internet Channel"):"00010001484144xx",
|
||||||
|
QT_TR_NOOP("Photo Channel"):"0001000248414141",
|
||||||
|
QT_TR_NOOP("Shopping Channel"):"0001000248414241",
|
||||||
|
QT_TR_NOOP("Mii Channel"):"001000248414341",
|
||||||
|
QT_TR_NOOP("Photo Channel 1.1"):"001000248415941",
|
||||||
|
#QT_TR_NOOP("Wii Message Board"):"001000148414541",
|
||||||
|
#QT_TR_NOOP("Weather Channel-HAFx"):"00010002484146xx",
|
||||||
|
#QT_TR_NOOP("Weather Channel-HAFA"):"0001000248414641",
|
||||||
|
#QT_TR_NOOP("News Channel-HAGx"):"00010002484147xx",
|
||||||
|
#QT_TR_NOOP("News Channel-HAGA"):"0001000248414741"
|
||||||
|
}
|
||||||
|
|
||||||
|
#idDict = {}
|
||||||
|
#for title in TitleDict:
|
||||||
|
# idDict[TitleDict[title]] = title
|
||||||
|
|
||||||
|
IOSdict = {}
|
||||||
|
for title in TitleDict:
|
||||||
|
if re.search("IOS", title):
|
||||||
|
IOSdict[title] = TitleDict[title]
|
||||||
|
IOSdict["IOS202"] = "00000001000000ca"
|
||||||
|
IOSdict["IOS222"] = "00000001000000de"
|
||||||
|
IOSdict["IOS249"] = "00000001000000f9"
|
||||||
|
|
||||||
|
IOSids = {}
|
||||||
|
for ios in IOSdict:
|
||||||
|
IOSids[IOSdict[ios]] = ios
|
||||||
|
|
||||||
|
def AsciiID(channelname):
|
||||||
|
return binascii.unhexlify(TitleDict[channelname][7:])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print TitleDict["System Menu"]
|
||||||
|
print TitleDict["Mii Channel"][7:]
|
||||||
|
print AsciiID("Mii Channel")
|
||||||
|
print idDict["0001000248414741"]
|
282
WiiPy/Struct.py
Normal file
282
WiiPy/Struct.py
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
import struct, sys
|
||||||
|
|
||||||
|
class StructType(tuple):
|
||||||
|
def __getitem__(self, value):
|
||||||
|
return [self] * value
|
||||||
|
def __call__(self, value, endian='<'):
|
||||||
|
if isinstance(value, str):
|
||||||
|
return struct.unpack(endian + tuple.__getitem__(self, 0), value[:tuple.__getitem__(self, 1)])[0]
|
||||||
|
else:
|
||||||
|
return struct.pack(endian + tuple.__getitem__(self, 0), value)
|
||||||
|
|
||||||
|
class StructException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Struct(object):
|
||||||
|
__slots__ = ('__attrs__', '__baked__', '__defs__', '__endian__', '__next__', '__sizes__', '__values__')
|
||||||
|
int8 = StructType(('b', 1))
|
||||||
|
uint8 = StructType(('B', 1))
|
||||||
|
|
||||||
|
int16 = StructType(('h', 2))
|
||||||
|
uint16 = StructType(('H', 2))
|
||||||
|
|
||||||
|
int32 = StructType(('l', 4))
|
||||||
|
uint32 = StructType(('L', 4))
|
||||||
|
|
||||||
|
int64 = StructType(('q', 8))
|
||||||
|
uint64 = StructType(('Q', 8))
|
||||||
|
|
||||||
|
float = StructType(('f', 4))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def string(cls, len, offset=0, encoding=None, stripNulls=False, value=''):
|
||||||
|
return StructType(('string', (len, offset, encoding, stripNulls, value)))
|
||||||
|
|
||||||
|
LE = '<'
|
||||||
|
BE = '>'
|
||||||
|
__endian__ = '<'
|
||||||
|
|
||||||
|
def __init__(self, func=None, unpack=None, **kwargs):
|
||||||
|
self.__defs__ = []
|
||||||
|
self.__sizes__ = []
|
||||||
|
self.__attrs__ = []
|
||||||
|
self.__values__ = {}
|
||||||
|
self.__next__ = True
|
||||||
|
self.__baked__ = False
|
||||||
|
|
||||||
|
if func == None:
|
||||||
|
self.__format__()
|
||||||
|
else:
|
||||||
|
sys.settrace(self.__trace__)
|
||||||
|
func()
|
||||||
|
for name in func.func_code.co_varnames:
|
||||||
|
value = self.__frame__.f_locals[name]
|
||||||
|
self.__setattr__(name, value)
|
||||||
|
|
||||||
|
self.__baked__ = True
|
||||||
|
|
||||||
|
if unpack != None:
|
||||||
|
if isinstance(unpack, tuple):
|
||||||
|
self.unpack(*unpack)
|
||||||
|
else:
|
||||||
|
self.unpack(unpack)
|
||||||
|
|
||||||
|
if len(kwargs):
|
||||||
|
for name in kwargs:
|
||||||
|
self.__values__[name] = kwargs[name]
|
||||||
|
|
||||||
|
def __trace__(self, frame, event, arg):
|
||||||
|
self.__frame__ = frame
|
||||||
|
sys.settrace(None)
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
if name in self.__slots__:
|
||||||
|
return object.__setattr__(self, name, value)
|
||||||
|
|
||||||
|
if self.__baked__ == False:
|
||||||
|
if not isinstance(value, list):
|
||||||
|
value = [value]
|
||||||
|
attrname = name
|
||||||
|
else:
|
||||||
|
attrname = '*' + name
|
||||||
|
|
||||||
|
self.__values__[name] = None
|
||||||
|
|
||||||
|
for sub in value:
|
||||||
|
if isinstance(sub, Struct):
|
||||||
|
sub = sub.__class__
|
||||||
|
try:
|
||||||
|
if issubclass(sub, Struct):
|
||||||
|
sub = ('struct', sub)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
type_, size = tuple(sub)
|
||||||
|
if type_ == 'string':
|
||||||
|
self.__defs__.append(Struct.string)
|
||||||
|
self.__sizes__.append(size)
|
||||||
|
self.__attrs__.append(attrname)
|
||||||
|
self.__next__ = True
|
||||||
|
|
||||||
|
if attrname[0] != '*':
|
||||||
|
self.__values__[name] = size[3]
|
||||||
|
elif self.__values__[name] == None:
|
||||||
|
self.__values__[name] = [size[3] for val in value]
|
||||||
|
elif type_ == 'struct':
|
||||||
|
self.__defs__.append(Struct)
|
||||||
|
self.__sizes__.append(size)
|
||||||
|
self.__attrs__.append(attrname)
|
||||||
|
self.__next__ = True
|
||||||
|
|
||||||
|
if attrname[0] != '*':
|
||||||
|
self.__values__[name] = size()
|
||||||
|
elif self.__values__[name] == None:
|
||||||
|
self.__values__[name] = [size() for val in value]
|
||||||
|
else:
|
||||||
|
if self.__next__:
|
||||||
|
self.__defs__.append('')
|
||||||
|
self.__sizes__.append(0)
|
||||||
|
self.__attrs__.append([])
|
||||||
|
self.__next__ = False
|
||||||
|
|
||||||
|
self.__defs__[-1] += type_
|
||||||
|
self.__sizes__[-1] += size
|
||||||
|
self.__attrs__[-1].append(attrname)
|
||||||
|
|
||||||
|
if attrname[0] != '*':
|
||||||
|
self.__values__[name] = 0
|
||||||
|
elif self.__values__[name] == None:
|
||||||
|
self.__values__[name] = [0 for val in value]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.__values__[name] = value
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(name)
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if self.__baked__ == False:
|
||||||
|
return name
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
return self.__values__[name]
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(name)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
ret = 0
|
||||||
|
arraypos, arrayname = None, None
|
||||||
|
|
||||||
|
for i in range(len(self.__defs__)):
|
||||||
|
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
|
||||||
|
|
||||||
|
if sdef == Struct.string:
|
||||||
|
size, offset, encoding, stripNulls, value = size
|
||||||
|
if isinstance(size, str):
|
||||||
|
size = self.__values__[size] + offset
|
||||||
|
elif sdef == Struct:
|
||||||
|
if attrs[0] == '*':
|
||||||
|
if arrayname != attrs:
|
||||||
|
arrayname = attrs
|
||||||
|
arraypos = 0
|
||||||
|
size = len(self.__values__[attrs[1:]][arraypos])
|
||||||
|
size = len(self.__values__[attrs])
|
||||||
|
|
||||||
|
ret += size
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def unpack(self, data, pos=0):
|
||||||
|
for name in self.__values__:
|
||||||
|
if not isinstance(self.__values__[name], Struct):
|
||||||
|
self.__values__[name] = None
|
||||||
|
elif self.__values__[name].__class__ == list and len(self.__values__[name]) != 0:
|
||||||
|
if not isinstance(self.__values__[name][0], Struct):
|
||||||
|
self.__values__[name] = None
|
||||||
|
|
||||||
|
arraypos, arrayname = None, None
|
||||||
|
|
||||||
|
for i in range(len(self.__defs__)):
|
||||||
|
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
|
||||||
|
|
||||||
|
if sdef == Struct.string:
|
||||||
|
size, offset, encoding, stripNulls, value = size
|
||||||
|
if isinstance(size, str):
|
||||||
|
size = self.__values__[size] + offset
|
||||||
|
|
||||||
|
temp = data[pos:pos+size]
|
||||||
|
if len(temp) != size:
|
||||||
|
raise StructException('Expected %i byte string, got %i' % (size, len(temp)))
|
||||||
|
|
||||||
|
if encoding != None:
|
||||||
|
temp = temp.decode(encoding)
|
||||||
|
|
||||||
|
if stripNulls:
|
||||||
|
temp = temp.rstrip('\0')
|
||||||
|
|
||||||
|
if attrs[0] == '*':
|
||||||
|
name = attrs[1:]
|
||||||
|
if self.__values__[name] == None:
|
||||||
|
self.__values__[name] = []
|
||||||
|
self.__values__[name].append(temp)
|
||||||
|
else:
|
||||||
|
self.__values__[attrs] = temp
|
||||||
|
pos += size
|
||||||
|
elif sdef == Struct:
|
||||||
|
if attrs[0] == '*':
|
||||||
|
if arrayname != attrs:
|
||||||
|
arrayname = attrs
|
||||||
|
arraypos = 0
|
||||||
|
name = attrs[1:]
|
||||||
|
self.__values__[attrs][arraypos].unpack(data, pos)
|
||||||
|
pos += len(self.__values__[attrs][arraypos])
|
||||||
|
arraypos += 1
|
||||||
|
else:
|
||||||
|
self.__values__[attrs].unpack(data, pos)
|
||||||
|
pos += len(self.__values__[attrs])
|
||||||
|
else:
|
||||||
|
values = struct.unpack(self.__endian__+sdef, data[pos:pos+size])
|
||||||
|
pos += size
|
||||||
|
j = 0
|
||||||
|
for name in attrs:
|
||||||
|
if name[0] == '*':
|
||||||
|
name = name[1:]
|
||||||
|
if self.__values__[name] == None:
|
||||||
|
self.__values__[name] = []
|
||||||
|
self.__values__[name].append(values[j])
|
||||||
|
else:
|
||||||
|
self.__values__[name] = values[j]
|
||||||
|
j += 1
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
arraypos, arrayname = None, None
|
||||||
|
|
||||||
|
ret = ''
|
||||||
|
for i in range(len(self.__defs__)):
|
||||||
|
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
|
||||||
|
|
||||||
|
if sdef == Struct.string:
|
||||||
|
size, offset, encoding, stripNulls, value = size
|
||||||
|
if isinstance(size, str):
|
||||||
|
size = self.__values__[size]+offset
|
||||||
|
|
||||||
|
if attrs[0] == '*':
|
||||||
|
if arrayname != attrs:
|
||||||
|
arraypos = 0
|
||||||
|
arrayname = attrs
|
||||||
|
temp = self.__values__[attrs[1:]][arraypos]
|
||||||
|
arraypos += 1
|
||||||
|
else:
|
||||||
|
temp = self.__values__[attrs]
|
||||||
|
|
||||||
|
if encoding != None:
|
||||||
|
temp = temp.encode(encoding)
|
||||||
|
|
||||||
|
temp = temp[:size]
|
||||||
|
ret += temp + ('\0' * (size - len(temp)))
|
||||||
|
elif sdef == Struct:
|
||||||
|
if attrs[0] == '*':
|
||||||
|
if arrayname != attrs:
|
||||||
|
arraypos = 0
|
||||||
|
arrayname = attrs
|
||||||
|
ret += self.__values__[attrs[1:]][arraypos].pack()
|
||||||
|
arraypos += 1
|
||||||
|
else:
|
||||||
|
ret += self.__values__[attrs].pack()
|
||||||
|
else:
|
||||||
|
values = []
|
||||||
|
for name in attrs:
|
||||||
|
if name[0] == '*':
|
||||||
|
if arrayname != name:
|
||||||
|
arraypos = 0
|
||||||
|
arrayname = name
|
||||||
|
values.append(self.__values__[name[1:]][arraypos])
|
||||||
|
arraypos += 1
|
||||||
|
else:
|
||||||
|
values.append(self.__values__[name])
|
||||||
|
|
||||||
|
ret += struct.pack(self.__endian__+sdef, *values)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __getitem__(self, value):
|
||||||
|
return [('struct', self.__class__)] * value
|
22
WiiPy/Wii.py
Normal file
22
WiiPy/Wii.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
__all__ = []
|
||||||
|
|
||||||
|
from common import *
|
||||||
|
from formats import *
|
||||||
|
from title import *
|
||||||
|
from disc import *
|
||||||
|
from image import *
|
||||||
|
from archive import *
|
||||||
|
from export import *
|
||||||
|
from compression import *
|
||||||
|
from nand import *
|
||||||
|
from headers import *
|
||||||
|
from bns import *
|
||||||
|
|
||||||
|
if (__name__ == "__main__"):
|
||||||
|
Crypto()
|
||||||
|
TMD()
|
||||||
|
Ticket()
|
||||||
|
|
||||||
|
#insert non-dependant check code here
|
||||||
|
|
||||||
|
print("\nAll Wii.py components loaded sucessfully!\n")
|
1
WiiPy/__init__.py
Normal file
1
WiiPy/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
454
WiiPy/archive.py
Normal file
454
WiiPy/archive.py
Normal file
@ -0,0 +1,454 @@
|
|||||||
|
from common import *
|
||||||
|
from title import *
|
||||||
|
import zlib
|
||||||
|
|
||||||
|
class U8(WiiArchive):
|
||||||
|
"""This class can unpack and pack U8 archives, which are used all over the Wii. They are often used in Banners and contents in Downloadable Titles. Please remove all headers and compression first, kthx.
|
||||||
|
|
||||||
|
The f parameter is either the source folder to pack, or the source file to unpack."""
|
||||||
|
class U8Header(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.tag = Struct.string(4)
|
||||||
|
self.rootnode_offset = Struct.uint32
|
||||||
|
self.header_size = Struct.uint32
|
||||||
|
self.data_offset = Struct.uint32
|
||||||
|
self.zeroes = Struct.string(16)
|
||||||
|
class U8Node(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.type = Struct.uint16
|
||||||
|
self.name_offset = Struct.uint16
|
||||||
|
self.data_offset = Struct.uint32
|
||||||
|
self.size = Struct.uint32
|
||||||
|
def __init__(self):
|
||||||
|
self.files = []
|
||||||
|
def _dump(self):
|
||||||
|
header = self.U8Header()
|
||||||
|
rootnode = self.U8Node()
|
||||||
|
|
||||||
|
# constants
|
||||||
|
header.tag = "U\xAA8-"
|
||||||
|
header.rootnode_offset = 0x20
|
||||||
|
header.zeroes = "\x00" * 16
|
||||||
|
rootnode.type = 0x0100
|
||||||
|
|
||||||
|
nodes = []
|
||||||
|
strings = "\x00"
|
||||||
|
data = ''
|
||||||
|
|
||||||
|
for item, value in self.files:
|
||||||
|
node = self.U8Node()
|
||||||
|
|
||||||
|
recursion = item.count('/')
|
||||||
|
if(recursion < 0):
|
||||||
|
recursion = 0
|
||||||
|
name = item[item.rfind('/') + 1:]
|
||||||
|
|
||||||
|
node.name_offset = len(strings)
|
||||||
|
strings += name + '\x00'
|
||||||
|
|
||||||
|
if(value == None):
|
||||||
|
node.type = 0x0100
|
||||||
|
node.data_offset = recursion
|
||||||
|
|
||||||
|
node.size = len(nodes)
|
||||||
|
for one, two in self.files:
|
||||||
|
if(one[:len(item)] == item): # find nodes in the folder
|
||||||
|
node.size += 1
|
||||||
|
node.size += 1
|
||||||
|
else:
|
||||||
|
sz = len(value)
|
||||||
|
node.data_offset = len(data)
|
||||||
|
data += value + "\x00" * (align(sz, 32) - sz) # 32 seems to work best for fuzzyness? I'm still really not sure
|
||||||
|
node.size = sz
|
||||||
|
node.type = 0x0000
|
||||||
|
nodes.append(node)
|
||||||
|
|
||||||
|
header.header_size = ((len(nodes) + 1) * len(rootnode)) + len(strings)
|
||||||
|
header.data_offset = align(header.header_size + header.rootnode_offset, 64)
|
||||||
|
rootnode.size = len(nodes) + 1
|
||||||
|
|
||||||
|
for i in range(len(nodes)):
|
||||||
|
if(nodes[i].type == 0x0000):
|
||||||
|
nodes[i].data_offset += header.data_offset
|
||||||
|
|
||||||
|
fd = ''
|
||||||
|
fd += header.pack()
|
||||||
|
fd += rootnode.pack()
|
||||||
|
for nodeobj in nodes:
|
||||||
|
fd += nodeobj.pack()
|
||||||
|
fd += strings
|
||||||
|
fd += "\x00" * (header.data_offset - header.rootnode_offset - header.header_size)
|
||||||
|
fd += data
|
||||||
|
|
||||||
|
return fd
|
||||||
|
def _dumpDir(self, dir):
|
||||||
|
if(not os.path.isdir(dir)):
|
||||||
|
os.mkdir(dir)
|
||||||
|
old = os.getcwd()
|
||||||
|
os.chdir(dir)
|
||||||
|
for item, data in self.files:
|
||||||
|
if(data == None):
|
||||||
|
if(not os.path.isdir(item)):
|
||||||
|
os.mkdir(item)
|
||||||
|
else:
|
||||||
|
open(item, "wb").write(data)
|
||||||
|
os.chdir(old)
|
||||||
|
def _loadDir(self, dir):
|
||||||
|
try:
|
||||||
|
self._tmpPath += ''
|
||||||
|
except:
|
||||||
|
self._tmpPath = ''
|
||||||
|
old = os.getcwd()
|
||||||
|
os.chdir(dir)
|
||||||
|
entries = os.listdir(".")
|
||||||
|
for entry in entries:
|
||||||
|
if(os.path.isdir(entry)):
|
||||||
|
self.files.append((self._tmpPath + entry, None))
|
||||||
|
self._tmpPath += entry + '/'
|
||||||
|
self._loadDir(entry)
|
||||||
|
elif(os.path.isfile(entry)):
|
||||||
|
data = open(entry, "rb").read()
|
||||||
|
self.files.append((self._tmpPath + entry, data))
|
||||||
|
os.chdir(old)
|
||||||
|
self._tmpPath = self._tmpPath[:self._tmpPath.find('/') + 1]
|
||||||
|
def _load(self, data):
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
header = self.U8Header()
|
||||||
|
header.unpack(data[offset:offset + len(header)])
|
||||||
|
offset += len(header)
|
||||||
|
|
||||||
|
assert header.tag == "U\xAA8-"
|
||||||
|
offset = header.rootnode_offset
|
||||||
|
|
||||||
|
rootnode = self.U8Node()
|
||||||
|
rootnode.unpack(data[offset:offset + len(rootnode)])
|
||||||
|
offset += len(rootnode)
|
||||||
|
|
||||||
|
nodes = []
|
||||||
|
for i in range(rootnode.size - 1):
|
||||||
|
node = self.U8Node()
|
||||||
|
node.unpack(data[offset:offset + len(node)])
|
||||||
|
offset += len(node)
|
||||||
|
nodes.append(node)
|
||||||
|
|
||||||
|
strings = data[offset:offset + header.data_offset - len(header) - (len(rootnode) * rootnode.size)]
|
||||||
|
offset += len(strings)
|
||||||
|
|
||||||
|
recursion = [rootnode.size]
|
||||||
|
recursiondir = []
|
||||||
|
counter = 0
|
||||||
|
for node in nodes:
|
||||||
|
counter += 1
|
||||||
|
name = strings[node.name_offset:].split('\0', 1)[0]
|
||||||
|
|
||||||
|
if(node.type == 0x0100): # folder
|
||||||
|
recursion.append(node.size)
|
||||||
|
recursiondir.append(name)
|
||||||
|
assert len(recursion) == node.data_offset + 2 # haxx
|
||||||
|
self.files.append(('/'.join(recursiondir), None))
|
||||||
|
elif(node.type == 0): # file
|
||||||
|
self.files.append(('/'.join(recursiondir) + '/' + name, data[node.data_offset:node.data_offset + node.size]))
|
||||||
|
offset += node.size
|
||||||
|
else: # unknown type -- wtf?
|
||||||
|
pass
|
||||||
|
|
||||||
|
sz = recursion.pop()
|
||||||
|
if(sz != counter + 1):
|
||||||
|
recursion.append(sz)
|
||||||
|
else:
|
||||||
|
recursiondir.pop()
|
||||||
|
def __str__(self):
|
||||||
|
ret = ''
|
||||||
|
for key, value in self.files:
|
||||||
|
name = key[key.rfind('/') + 1:]
|
||||||
|
recursion = key.count('/')
|
||||||
|
ret += ' ' * recursion
|
||||||
|
if(value == None):
|
||||||
|
ret += '[' + name + ']'
|
||||||
|
else:
|
||||||
|
ret += name
|
||||||
|
ret += '\n'
|
||||||
|
return ret
|
||||||
|
def __getitem__(self, key):
|
||||||
|
for item, val in self.files:
|
||||||
|
if(item == key):
|
||||||
|
if(val != None):
|
||||||
|
return val
|
||||||
|
else:
|
||||||
|
ret = []
|
||||||
|
for item2, val2 in self.files:
|
||||||
|
if(item2.find(item) == 0):
|
||||||
|
ret.append(item2[len(item) + 1:])
|
||||||
|
return ret[1:]
|
||||||
|
raise KeyError
|
||||||
|
def __setitem__(self, key, val):
|
||||||
|
for i in range(len(self.files)):
|
||||||
|
if(self.files[i][0] == key):
|
||||||
|
self.files[i] = (self.files[i][0], val)
|
||||||
|
return
|
||||||
|
self.files.append((key, val))
|
||||||
|
|
||||||
|
|
||||||
|
class WAD(WiiArchive):
|
||||||
|
def __init__(self, boot2 = False):
|
||||||
|
self.tmd = TMD()
|
||||||
|
self.tik = Ticket()
|
||||||
|
self.contents = []
|
||||||
|
self.boot2 = False
|
||||||
|
self.cert = ""
|
||||||
|
def _load(self, data):
|
||||||
|
if(self.boot2 != True):
|
||||||
|
headersize, wadtype, certsize, reserved, tiksize, tmdsize, datasize, footersize, padding = struct.unpack('>I4s6I32s', data[:64])
|
||||||
|
pos = 64
|
||||||
|
else:
|
||||||
|
headersize, data_offset, certsize, tiksize, tmdsize, padding = struct.unpack('>IIIII12s', data[:32])
|
||||||
|
pos = 32
|
||||||
|
|
||||||
|
rawcert = data[pos:pos + certsize]
|
||||||
|
pos += certsize
|
||||||
|
if(self.boot2 != True):
|
||||||
|
if(certsize % 64 != 0):
|
||||||
|
pos += 64 - (certsize % 64)
|
||||||
|
self.cert = rawcert
|
||||||
|
|
||||||
|
rawtik = data[pos:pos + tiksize]
|
||||||
|
pos += tiksize
|
||||||
|
if(self.boot2 != True):
|
||||||
|
if(tiksize % 64 != 0):
|
||||||
|
pos += 64 - (tiksize % 64)
|
||||||
|
self.tik = Ticket.load(rawtik)
|
||||||
|
|
||||||
|
rawtmd = data[pos:pos + tmdsize]
|
||||||
|
pos += tmdsize
|
||||||
|
if(self.boot2 == True):
|
||||||
|
pos = data_offset
|
||||||
|
else:
|
||||||
|
pos += 64 - (tmdsize % 64)
|
||||||
|
self.tmd = TMD.load(rawtmd)
|
||||||
|
|
||||||
|
titlekey = self.tik.getTitleKey()
|
||||||
|
contents = self.tmd.getContents()
|
||||||
|
for i in range(0, len(contents)):
|
||||||
|
tmpsize = contents[i].size
|
||||||
|
if(tmpsize % 16 != 0):
|
||||||
|
tmpsize += 16 - (tmpsize % 16)
|
||||||
|
encdata = data[pos:pos + tmpsize]
|
||||||
|
pos += tmpsize
|
||||||
|
decdata = Crypto().decryptContent(titlekey, contents[i].index, encdata)
|
||||||
|
self.contents.append(decdata)
|
||||||
|
if(tmpsize % 64 != 0):
|
||||||
|
pos += 64 - (tmpsize % 64)
|
||||||
|
def _loadDir(self, dir):
|
||||||
|
origdir = os.getcwd()
|
||||||
|
os.chdir(dir)
|
||||||
|
|
||||||
|
self.tmd = TMD.loadFile("tmd")
|
||||||
|
self.tik = Ticket.loadFile("tik")
|
||||||
|
self.cert = open("cert", "rb").read()
|
||||||
|
|
||||||
|
contents = self.tmd.getContents()
|
||||||
|
for i in range(len(contents)):
|
||||||
|
self.contents.append(open("%08x.app" % i, "rb").read())
|
||||||
|
os.chdir(origdir)
|
||||||
|
def _dumpDir(self, dir):
|
||||||
|
origdir = os.getcwd()
|
||||||
|
os.chdir(dir)
|
||||||
|
|
||||||
|
contents = self.tmd.getContents()
|
||||||
|
for i in range(len(contents)):
|
||||||
|
open("%08x.app" % i, "wb").write(self.contents[i])
|
||||||
|
self.tmd.dumpFile("tmd")
|
||||||
|
self.tik.dumpFile("tik")
|
||||||
|
open("cert", "wb").write(self.cert)
|
||||||
|
|
||||||
|
os.chdir(origdir)
|
||||||
|
def _dump(self, fakesign = True):
|
||||||
|
titlekey = self.tik.getTitleKey()
|
||||||
|
contents = self.tmd.getContents()
|
||||||
|
|
||||||
|
apppack = ""
|
||||||
|
for i, content in enumerate(contents):
|
||||||
|
if(fakesign):
|
||||||
|
content.hash = str(Crypto().createSHAHash(self.contents[content.index]))
|
||||||
|
content.size = len(self.contents[content.index])
|
||||||
|
|
||||||
|
encdata = Crypto().encryptContent(titlekey, content.index, self.contents[content.index])
|
||||||
|
|
||||||
|
apppack += encdata
|
||||||
|
if(len(encdata) % 64 != 0):
|
||||||
|
apppack += "\x00" * (64 - (len(encdata) % 64))
|
||||||
|
|
||||||
|
if(fakesign):
|
||||||
|
self.tmd.setContents(contents)
|
||||||
|
self.tmd.fakesign()
|
||||||
|
self.tik.fakesign()
|
||||||
|
|
||||||
|
rawtmd = self.tmd.dump()
|
||||||
|
rawcert = self.cert
|
||||||
|
rawtik = self.tik.dump()
|
||||||
|
|
||||||
|
sz = 0
|
||||||
|
for i in range(len(contents)):
|
||||||
|
sz += contents[i].size
|
||||||
|
if(sz % 64 != 0):
|
||||||
|
sz += 64 - (contents[i].size % 64)
|
||||||
|
|
||||||
|
if(self.boot2 != True):
|
||||||
|
pack = struct.pack('>I4s6I', 32, "Is\x00\x00", len(rawcert), 0, len(rawtik), len(rawtmd), sz, 0)
|
||||||
|
pack += "\x00" * 32
|
||||||
|
else:
|
||||||
|
pack = struct.pack('>IIIII12s', 32, align(len(rawcert) + len(rawtik) + len(rawtmd), 0x40), len(rawcert), len(rawtik), len(rawtmd), "\x00" * 12)
|
||||||
|
|
||||||
|
pack += rawcert
|
||||||
|
if(len(rawcert) % 64 != 0 and self.boot2 != True):
|
||||||
|
pack += "\x00" * (64 - (len(rawcert) % 64))
|
||||||
|
pack += rawtik
|
||||||
|
if(len(rawtik) % 64 != 0 and self.boot2 != True):
|
||||||
|
pack += "\x00" * (64 - (len(rawtik) % 64))
|
||||||
|
pack += rawtmd
|
||||||
|
if(len(rawtmd) % 64 != 0 and self.boot2 != True):
|
||||||
|
pack += "\x00" * (64 - (len(rawtmd) % 64))
|
||||||
|
|
||||||
|
if(self.boot2 == True):
|
||||||
|
pack += "\x00" * (align(len(rawcert) + len(rawtik) + len(rawtmd), 0x40) - (len(rawcert) + len(rawtik) + len(rawtmd)))
|
||||||
|
|
||||||
|
pack += apppack
|
||||||
|
return pack
|
||||||
|
def __getitem__(self, idx):
|
||||||
|
return self.contents[idx]
|
||||||
|
def __setitem__(self, idx, value):
|
||||||
|
self.contents[idx] = value
|
||||||
|
def __str__(self):
|
||||||
|
out = ""
|
||||||
|
out += "Wii WAD:\n"
|
||||||
|
out += str(self.tmd)
|
||||||
|
out += str(self.tik)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
class CCF():
|
||||||
|
class CCFHeader(Struct):
|
||||||
|
__endian__ = Struct.LE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.zeroes12 = Struct.string(12)
|
||||||
|
self.rootOffset = Struct.uint32
|
||||||
|
self.filesCount = Struct.uint32
|
||||||
|
self.zeroes8 = Struct.string(8)
|
||||||
|
|
||||||
|
class CCFFile(Struct):
|
||||||
|
__endian__ = Struct.LE
|
||||||
|
def __format__(self):
|
||||||
|
self.fileName = Struct.string(20)
|
||||||
|
self.fileOffset = Struct.uint32
|
||||||
|
self.fileSize = Struct.uint32
|
||||||
|
self.fileSizeDecompressed = Struct.uint32
|
||||||
|
|
||||||
|
def __init__(self, fileName):
|
||||||
|
self.fileName = fileName
|
||||||
|
self.fd = open(fileName, 'r+b')
|
||||||
|
|
||||||
|
def compress(self, folder):
|
||||||
|
fileList = []
|
||||||
|
|
||||||
|
fileHdr = self.CCFHeader()
|
||||||
|
|
||||||
|
files = os.listdir(folder)
|
||||||
|
|
||||||
|
fileHdr.magic = "\x43\x43\x46\x00"
|
||||||
|
fileHdr.zeroes12 = '\x00' * 12
|
||||||
|
fileHdr.rootOffset = 0x20
|
||||||
|
fileHdr.zeroes8 = '\x00' * 8
|
||||||
|
|
||||||
|
currentOffset = len(fileHdr)
|
||||||
|
packedFiles = 0
|
||||||
|
previousFileEndOffset = 0
|
||||||
|
|
||||||
|
for file in files:
|
||||||
|
if os.path.isdir(folder + '/' + file) or file == '.DS_Store':
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
fileList.append(file)
|
||||||
|
|
||||||
|
fileHdr.filesCount = len(fileList)
|
||||||
|
self.fd.write(fileHdr.pack())
|
||||||
|
self.fd.write('\x00' * (fileHdr.filesCount * len(self.CCFFile())))
|
||||||
|
|
||||||
|
for fileNumber in range(len(fileList)):
|
||||||
|
|
||||||
|
fileEntry = self.CCFFile()
|
||||||
|
|
||||||
|
compressedBuffer = zlib.compress(open(folder + '/' + fileList[fileNumber]).read())
|
||||||
|
|
||||||
|
fileEntry.fileName = fileList[fileNumber]
|
||||||
|
fileEntry.fileSize = len(compressedBuffer)
|
||||||
|
fileEntry.fileSizeDecompressed = os.stat(folder + '/' + fileList[fileNumber]).st_size
|
||||||
|
fileEntry.fileOffset = align(self.fd.tell(), 32) / 32
|
||||||
|
|
||||||
|
print 'File {0} ({1}Kb) placed at offset 0x{2:X}'.format(fileEntry.fileName, fileEntry.fileSize / 1024, fileEntry.fileOffset * 32)
|
||||||
|
|
||||||
|
self.fd.seek(len(fileHdr) + fileNumber * len(self.CCFFile()))
|
||||||
|
self.fd.write(fileEntry.pack())
|
||||||
|
self.fd.seek(fileEntry.fileOffset * 32)
|
||||||
|
self.fd.write(compressedBuffer)
|
||||||
|
|
||||||
|
self.fd.close()
|
||||||
|
|
||||||
|
def decompress(self):
|
||||||
|
fileHdr = self.CCFHeader()
|
||||||
|
hdrData = self.fd.read(len(fileHdr))
|
||||||
|
fileHdr.unpack(hdrData)
|
||||||
|
|
||||||
|
print 'Found {0} file/s and root node at 0x{1:X}'.format(fileHdr.filesCount, fileHdr.rootOffset)
|
||||||
|
|
||||||
|
if fileHdr.magic != "\x43\x43\x46\x00":
|
||||||
|
raise ValueError("Wrong magic, 0x{0}".format(fileHdr.magic))
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.mkdir(os.path.dirname(self.fileName) + '/' + self.fd.name.replace(".", "_") + "_out")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.chdir(os.path.dirname(self.fileName) + '/' + self.fd.name.replace(".", "_") + "_out")
|
||||||
|
|
||||||
|
currentOffset = len(fileHdr)
|
||||||
|
|
||||||
|
for x in range(fileHdr.filesCount):
|
||||||
|
self.fd.seek(currentOffset)
|
||||||
|
|
||||||
|
fileEntry = self.CCFFile()
|
||||||
|
fileData = self.fd.read(len(fileEntry))
|
||||||
|
fileEntry.unpack(fileData)
|
||||||
|
|
||||||
|
fileEntry.fileOffset = fileEntry.fileOffset * 32
|
||||||
|
|
||||||
|
print 'File {0} at offset 0x{1:X}'.format(fileEntry.fileName, fileEntry.fileOffset)
|
||||||
|
print 'File size {0}Kb ({1}Kb decompressed)'.format(fileEntry.fileSize / 1024, fileEntry.fileSizeDecompressed / 1024)
|
||||||
|
|
||||||
|
output = open(fileEntry.fileName.rstrip('\0'), 'w+b')
|
||||||
|
|
||||||
|
self.fd.seek(fileEntry.fileOffset)
|
||||||
|
if fileEntry.fileSize == fileEntry.fileSizeDecompressed:
|
||||||
|
print 'The file is stored uncompressed'
|
||||||
|
output.write(self.fd.read(fileEntry.fileSize))
|
||||||
|
else:
|
||||||
|
print 'The file is stored compressed..decompressing'
|
||||||
|
decompressedBuffer = zlib.decompress(self.fd.read(fileEntry.fileSize))
|
||||||
|
output.write(decompressedBuffer)
|
||||||
|
output.close()
|
||||||
|
|
||||||
|
currentOffset += len(fileEntry)
|
||||||
|
|
||||||
|
if(__name__ == '__main__'):
|
||||||
|
wad = WAD.loadFile("testing.wad")
|
||||||
|
print wad
|
||||||
|
wad.dumpDir("outdir")
|
||||||
|
wad.dumpFile("interesting.wad", fakesign = False) #keyword arguements work as expected when calling _dump(). awesome.
|
||||||
|
wad2 = WAD.loadDir("outdir")
|
||||||
|
print wad2
|
||||||
|
wad3 = WAD.loadFile("interesting.wad")
|
||||||
|
print wad3
|
||||||
|
wad3.dumpDir("outdir2")
|
618
WiiPy/bns.py
Normal file
618
WiiPy/bns.py
Normal file
@ -0,0 +1,618 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from common import *
|
||||||
|
|
||||||
|
class SoundFile:
|
||||||
|
def __init__(self, signal, filename, samplerate=32000):
|
||||||
|
self.actual_file = StringIO()
|
||||||
|
self.file = wave.open(filename, 'wb')
|
||||||
|
self.signal = signal
|
||||||
|
self.sr = samplerate
|
||||||
|
def write(self):
|
||||||
|
self.file.setparams((2, 2, self.sr, self.sr*4, 'NONE', 'noncompressed'))
|
||||||
|
self.file.writeframes(self.signal)
|
||||||
|
self.actual_file.seek(0)
|
||||||
|
self.file.close()
|
||||||
|
|
||||||
|
class BNS_data(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.magic = "DATA"
|
||||||
|
self.size = 0x0004d000
|
||||||
|
def eat(self, buffer, offset):
|
||||||
|
self.magic, self.size = struct.unpack('>4sI', buffer[offset:offset+8])
|
||||||
|
return offset + 8
|
||||||
|
def show(self):
|
||||||
|
print "Magic: %s" % self.magic
|
||||||
|
print "Length: %08x" % self.size
|
||||||
|
return
|
||||||
|
def write(self, file):
|
||||||
|
file.write(self.magic)
|
||||||
|
file.write(struct.pack('>I', self.size))
|
||||||
|
file.write(self.data)
|
||||||
|
return
|
||||||
|
|
||||||
|
class BNS_info(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.magic = "INFO"
|
||||||
|
self.size = 0x000000a0
|
||||||
|
self.codec = 0x00
|
||||||
|
self.has_loop = 0x00
|
||||||
|
self.chan_cnt = 0x02
|
||||||
|
self.zero = 0x00
|
||||||
|
self.samplerate = 0xac44
|
||||||
|
self.pad0 = 0x0000
|
||||||
|
self.loop_start = 0x00000000
|
||||||
|
self.loop_end = 0x00000000
|
||||||
|
self.offset_to_chan_starts = 0x00000018
|
||||||
|
self.pad2 = 0x00000000
|
||||||
|
self.channel1_start_offset = 0x00000020
|
||||||
|
self.channel2_start_offset = 0x0000002C
|
||||||
|
self.chan1_start = 0x00000000
|
||||||
|
self.coefficients1_offset = 0x0000038
|
||||||
|
self.pad1 = 0x00000000
|
||||||
|
self.chan2_start = 0x00000000
|
||||||
|
self.coefficients2_offset = 0x00000068
|
||||||
|
self.pad3 = 0x00000000
|
||||||
|
self.coefficients1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
self.chan1_gain = 0x0000
|
||||||
|
self.chan1_predictive_scale = 0x0000
|
||||||
|
self.chan1_previous_value = 0x0000
|
||||||
|
self.chan1_next_previous_value = 0x0000
|
||||||
|
self.chan1_loop_predictive_scale = 0x0000
|
||||||
|
self.chan1_loop_previous_value = 0x0000
|
||||||
|
self.chan1_loop_next_previous_value = 0x0000
|
||||||
|
self.chan1_loop_padding = 0x0000
|
||||||
|
self.coefficients2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
self.chan2_gain = 0x0000
|
||||||
|
self.chan2_predictive_scale = 0x0000
|
||||||
|
self.chan2_previous_value = 0x0000
|
||||||
|
self.chan2_next_previous_value = 0x0000
|
||||||
|
self.chan2_loop_predictive_scale = 0x0000
|
||||||
|
self.chan2_loop_previous_value = 0x0000
|
||||||
|
self.chan2_loop_next_previous_value = 0x0000
|
||||||
|
self.chan2_loop_padding = 0x0000
|
||||||
|
def eat(self, buffer, offset):
|
||||||
|
self.magic, self.size = struct.unpack('>4sI', buffer[offset+0:offset+8])
|
||||||
|
self.codec, self.has_loop = struct.unpack('>BB', buffer[offset+8:offset+10])
|
||||||
|
self.chan_cnt, self.zero = struct.unpack('>BB', buffer[offset+10:offset+12])
|
||||||
|
self.samplerate, self.pad0 = struct.unpack('>HH', buffer[offset+12:offset+16])
|
||||||
|
assert self.samplerate <= 48000
|
||||||
|
assert self.samplerate > 32000
|
||||||
|
self.loop_start, self.loop_end = struct.unpack('>II', buffer[offset+16:offset+24])
|
||||||
|
co = offset + 24
|
||||||
|
self.offset_to_chan_starts = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.pad2 = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.channel1_start_offset = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.channel2_start_offset = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.chan1_start = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.coefficients1_offset = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
if self.chan_cnt == 2:
|
||||||
|
self.pad1 = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.chan2_start = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.coefficients2_offset = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
self.pad3 = Struct.uint32(buffer[co:co+4], endian='>')
|
||||||
|
co += 4
|
||||||
|
for x in xrange(16):
|
||||||
|
self.coefficients1[x] = Struct.int16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_gain = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_predictive_scale = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_next_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_predictive_scale = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_next_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_padding = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
for x in xrange(16):
|
||||||
|
self.coefficients2[x] = Struct.int16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_gain = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_predictive_scale = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_next_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_loop_predictive_scale = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_loop_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_loop_next_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan2_loop_padding = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
elif self.chan_cnt == 1:
|
||||||
|
for x in xrange(16):
|
||||||
|
self.coefficients1[x] = Struct.int16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_gain = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_predictive_scale = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_next_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_predictive_scale = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_next_previous_value = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
self.chan1_loop_padding = Struct.uint16(buffer[co:co+2], endian='>')
|
||||||
|
co += 2
|
||||||
|
return co
|
||||||
|
def show(self):
|
||||||
|
print "Magic: %s" % self.magic
|
||||||
|
print "Length: %08x" % self.size
|
||||||
|
print "Codec: %02x " % self.codec,
|
||||||
|
if self.codec == 0: print "ADPCM"
|
||||||
|
else: print "Unknown (Maybe >_>, please contact megazig)"
|
||||||
|
print "Loop Flag: %02x " % self.has_loop,
|
||||||
|
if self.has_loop == 0: print "One shot"
|
||||||
|
else: print "Looping"
|
||||||
|
print "Channel Count: %02x" % self.chan_cnt
|
||||||
|
print "Zero: %02x" % self.zero
|
||||||
|
print "Samplerate: %04x %d" % ( self.samplerate , self.samplerate )
|
||||||
|
print "Padding: %04x" % self.pad0
|
||||||
|
print "Loop Start: %08x" % self.loop_start
|
||||||
|
print "Loop End: %08x" % self.loop_end
|
||||||
|
print "Channels Starts Offsets: %08x" % self.offset_to_chan_starts
|
||||||
|
print "Padding: %08x" % self.pad2
|
||||||
|
print "Channel 1 Start Offset: %08x" % self.channel1_start_offset
|
||||||
|
print "Channel 2 Start Offset: %08x" % self.channel2_start_offset
|
||||||
|
print "Channel 1 Start: %08x" % self.chan1_start
|
||||||
|
print "Coefficients 1 Offset: %08x" % self.coefficients1_offset
|
||||||
|
if self.chan_cnt == 2:
|
||||||
|
print "Padding: %08x" % self.pad1
|
||||||
|
print "Channel 2 Start: %08x" % self.chan2_start
|
||||||
|
print "Coefficients 2 Offset: %08x" % self.coefficients2_offset
|
||||||
|
print "Padding: %08x" % self.pad3
|
||||||
|
for x in xrange(16):
|
||||||
|
print "\t\tCoefficients 1: %2d - %04x - %d" % ( x , self.coefficients1[x], self.coefficients1[x] )
|
||||||
|
print "\tGain: %04x" % self.chan1_gain
|
||||||
|
print "\tPredictive Scale: %04x" % self.chan1_predictive_scale
|
||||||
|
print "\tPrevious Value: %04x" % self.chan1_previous_value
|
||||||
|
print "\tNext Previous Value: %04x" % self.chan1_next_previous_value
|
||||||
|
print "\tLoop Predictive Scale: %04x" % self.chan1_loop_predictive_scale
|
||||||
|
print "\tLoop Previous Value: %04x" % self.chan1_loop_previous_value
|
||||||
|
print "\tLoop Next Previous Value: %04x" % self.chan1_loop_next_previous_value
|
||||||
|
print "\tPadding: %04x" % self.chan1_loop_padding
|
||||||
|
for x in xrange(16):
|
||||||
|
print "\t\tCoefficients 2: %2d - %04x - %d" % ( x , self.coefficients2[x], self.coefficients2[x] )
|
||||||
|
print "\tGain: %04x" % self.chan2_gain
|
||||||
|
print "\tPredictive Scale: %04x" % self.chan2_predictive_scale
|
||||||
|
print "\tPrevious Value: %04x" % self.chan2_previous_value
|
||||||
|
print "\tNext Previous Value: %04x" % self.chan2_next_previous_value
|
||||||
|
print "\tLoop Predictive Scale: %04x" % self.chan2_loop_predictive_scale
|
||||||
|
print "\tLoop Previous Value: %04x" % self.chan2_loop_previous_value
|
||||||
|
print "\tLoop Next Previous Value: %04x" % self.chan2_loop_next_previous_value
|
||||||
|
print "\tPadding: %04x" % self.chan2_loop_padding
|
||||||
|
elif self.chan_cnt == 1:
|
||||||
|
for x in xrange(16):
|
||||||
|
print "\t\tCoefficients 1: %2d - %04x - %d" % ( x , self.coefficients1[x], self.coefficients1[x] )
|
||||||
|
print "\tGain: %04x" % self.chan1_gain
|
||||||
|
print "\tPredictive Scale: %04x" % self.chan1_predictive_scale
|
||||||
|
print "\tPrevious Value: %04x" % self.chan1_previous_value
|
||||||
|
print "\tNext Previous Value: %04x" % self.chan1_next_previous_value
|
||||||
|
print "\tLoop Predictive Scale: %04x" % self.chan1_loop_predictive_scale
|
||||||
|
print "\tLoop Previous Value: %04x" % self.chan1_loop_previous_value
|
||||||
|
print "\tLoop Next Previous Value: %04x" % self.chan1_loop_next_previous_value
|
||||||
|
print "\tPadding: %04x" % self.chan1_loop_padding
|
||||||
|
return
|
||||||
|
def write(self, file):
|
||||||
|
file.write(self.magic)
|
||||||
|
file.write(struct.pack('>I', self.size))
|
||||||
|
file.write(struct.pack('>B', self.codec))
|
||||||
|
file.write(struct.pack('>B', self.has_loop))
|
||||||
|
file.write(struct.pack('>B', self.chan_cnt))
|
||||||
|
file.write(struct.pack('>B', self.zero))
|
||||||
|
file.write(struct.pack('>H', self.samplerate))
|
||||||
|
file.write(struct.pack('>H', self.pad0))
|
||||||
|
file.write(struct.pack('>I', self.loop_start))
|
||||||
|
file.write(struct.pack('>I', self.loop_end))
|
||||||
|
file.write(struct.pack('>I', self.offset_to_chan_starts))
|
||||||
|
file.write(struct.pack('>I', self.pad2))
|
||||||
|
file.write(struct.pack('>I', self.channel1_start_offset))
|
||||||
|
file.write(struct.pack('>I', self.channel2_start_offset))
|
||||||
|
file.write(struct.pack('>I', self.chan1_start))
|
||||||
|
file.write(struct.pack('>I', self.coefficients1_offset))
|
||||||
|
if self.chan_cnt == 2:
|
||||||
|
file.write(struct.pack('>I', self.pad1))
|
||||||
|
file.write(struct.pack('>I', self.chan2_start))
|
||||||
|
file.write(struct.pack('>I', self.coefficients2_offset))
|
||||||
|
file.write(struct.pack('>I', self.pad3))
|
||||||
|
for x in xrange(16):
|
||||||
|
file.write(struct.pack('>h', self.coefficients1[x]))
|
||||||
|
file.write(struct.pack('>H', self.chan1_gain))
|
||||||
|
file.write(struct.pack('>H', self.chan1_predictive_scale))
|
||||||
|
file.write(struct.pack('>H', self.chan1_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_next_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_predictive_scale))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_next_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_padding))
|
||||||
|
for x in xrange(16):
|
||||||
|
file.write(struct.pack('>h', self.coefficients2[x]))
|
||||||
|
file.write(struct.pack('>H', self.chan2_gain))
|
||||||
|
file.write(struct.pack('>H', self.chan2_predictive_scale))
|
||||||
|
file.write(struct.pack('>H', self.chan2_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan2_next_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan2_loop_predictive_scale))
|
||||||
|
file.write(struct.pack('>H', self.chan2_loop_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan2_loop_next_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan2_loop_padding))
|
||||||
|
elif self.chan_cnt == 1:
|
||||||
|
for x in xrange(16):
|
||||||
|
file.write(struct.pack('>h', self.coefficients1[x]))
|
||||||
|
file.write(struct.pack('>H', self.chan1_gain))
|
||||||
|
file.write(struct.pack('>H', self.chan1_predictive_scale))
|
||||||
|
file.write(struct.pack('>H', self.chan1_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_next_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_predictive_scale))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_next_previous_value))
|
||||||
|
file.write(struct.pack('>H', self.chan1_loop_padding))
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class BNS_header(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.magic = "BNS "
|
||||||
|
self.flags = 0xfeff0100
|
||||||
|
self.filesize = 0x0004d0c0
|
||||||
|
self.size = 0x0020
|
||||||
|
self.chunk_cnt = 0x0002
|
||||||
|
self.info_off = 0x00000020
|
||||||
|
self.info_len = 0x000000a0
|
||||||
|
self.data_off = 0x000000c0
|
||||||
|
self.data_len = 0x0004d000
|
||||||
|
def eat(self, buffer, offset):
|
||||||
|
if struct.unpack('>4s', buffer[offset:offset+4])[0] != "BNS ":
|
||||||
|
offset += 0x20
|
||||||
|
self.magic, self.flags = struct.unpack('>4sI', buffer[offset+0:offset+8])
|
||||||
|
self.filesize, self.size, self.chunk_cnt = struct.unpack('>IHH', buffer[offset+8:offset+16])
|
||||||
|
self.info_off, self.info_len = struct.unpack('>II', buffer[offset+16:offset+24])
|
||||||
|
self.data_off, self.data_len = struct.unpack('>II', buffer[offset+24:offset+32])
|
||||||
|
assert self.magic == "BNS "
|
||||||
|
assert self.info_off < self.filesize
|
||||||
|
assert self.data_off < self.filesize
|
||||||
|
return offset + 32
|
||||||
|
def show(self):
|
||||||
|
print "Magic: %s" % self.magic
|
||||||
|
print "Flags: %08x" % self.flags
|
||||||
|
print "Length: %08x" % self.filesize
|
||||||
|
print "Header Size: %04x" % self.size
|
||||||
|
print "Chunk Count: %04x" % self.chunk_cnt
|
||||||
|
print "Info Offset: %08x" % self.info_off
|
||||||
|
print "Info Length: %08x" % self.info_len
|
||||||
|
print "Data Offset: %08x" % self.data_off
|
||||||
|
print "Data Length: %08x" % self.data_len
|
||||||
|
return
|
||||||
|
def write(self, file):
|
||||||
|
file.write(self.magic)
|
||||||
|
file.write(struct.pack('>I', self.flags))
|
||||||
|
file.write(struct.pack('>I', self.filesize))
|
||||||
|
file.write(struct.pack('>H', self.size))
|
||||||
|
file.write(struct.pack('>H', self.chunk_cnt))
|
||||||
|
file.write(struct.pack('>I', self.info_off))
|
||||||
|
file.write(struct.pack('>I', self.info_len))
|
||||||
|
file.write(struct.pack('>I', self.data_off))
|
||||||
|
file.write(struct.pack('>I', self.data_len))
|
||||||
|
return
|
||||||
|
|
||||||
|
class BNS(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.header = BNS_header()
|
||||||
|
self.info = BNS_info()
|
||||||
|
self.data = BNS_data()
|
||||||
|
self.buffered_data = ""
|
||||||
|
self.lsamps = [ [ 0 , 0 ] , [ 0 , 0 ] ]
|
||||||
|
self.rlsamps = [ [ 0 , 0 ] , [ 0 , 0 ] ]
|
||||||
|
self.tlsamps = [ 0 , 0 ]
|
||||||
|
self.hbc_deftbl = [ 674 , 1040,
|
||||||
|
3598, -1738,
|
||||||
|
2270, -583,
|
||||||
|
3967, -1969,
|
||||||
|
1516, 381,
|
||||||
|
3453, -1468,
|
||||||
|
2606, -617,
|
||||||
|
3795, -1759 ]
|
||||||
|
self.deftbl = [ 1820 , -856 ,
|
||||||
|
3238 , -1514 ,
|
||||||
|
2333 , -550 ,
|
||||||
|
3336 , -1376 ,
|
||||||
|
2444 , -949 ,
|
||||||
|
3666 , -1764 ,
|
||||||
|
2654 , -701 ,
|
||||||
|
3420 , -1398 ]
|
||||||
|
self.phist1 = [ 0 , 0 ]
|
||||||
|
self.phist2 = [ 0 , 0 ]
|
||||||
|
self.errors = 0
|
||||||
|
def find_exp(self, residual):
|
||||||
|
exp = 0
|
||||||
|
while residual>7.5 or residual<-8.5:
|
||||||
|
exp += 1
|
||||||
|
residual /= 2.0
|
||||||
|
return exp
|
||||||
|
def determine_std_exponent(self, idx, table, index, inbuf):
|
||||||
|
elsamps = [ 0 , 0 ]
|
||||||
|
max_res = 0
|
||||||
|
factor1 = table[2*index+0]
|
||||||
|
factor2 = table[2*index+1]
|
||||||
|
for x in xrange(2):
|
||||||
|
elsamps[x] = self.rlsamps[idx][x]
|
||||||
|
for i in xrange(14):
|
||||||
|
predictor = (elsamps[1]*factor1 + elsamps[0]*factor2) >> 11
|
||||||
|
residual = inbuf[i] - predictor
|
||||||
|
if residual>max_res:
|
||||||
|
max_res = residual
|
||||||
|
elsamps[0] = elsamps[1]
|
||||||
|
elsamps[1] = inbuf[i]
|
||||||
|
return self.find_exp(max_res)
|
||||||
|
def compress_adpcm(self, idx, table, tblidx, inbuf):
|
||||||
|
data = [0 for i in range(8)]
|
||||||
|
error = 0
|
||||||
|
factor1 = table[2*tblidx+0]
|
||||||
|
factor2 = table[2*tblidx+1]
|
||||||
|
exp = self.determine_std_exponent(idx, table, tblidx, inbuf)
|
||||||
|
while exp<=15:
|
||||||
|
error = 0
|
||||||
|
data[0] = exp | (tblidx << 4)
|
||||||
|
for x in xrange(2):
|
||||||
|
self.tlsamps[x] = self.rlsamps[idx][x]
|
||||||
|
j = 0
|
||||||
|
for i in xrange(14):
|
||||||
|
predictor = (self.tlsamps[1]*factor1 + self.tlsamps[0]*factor2) >> 11
|
||||||
|
residual = inbuf[i] - predictor
|
||||||
|
residual = residual >> exp
|
||||||
|
if residual>7 or residual<-8:
|
||||||
|
exp += 1
|
||||||
|
break
|
||||||
|
nibble = clamp(residual, -8, 7)
|
||||||
|
if i&1:
|
||||||
|
data[i/2+1] = data[i/2+1] | (nibble & 0xf)
|
||||||
|
else:
|
||||||
|
data[i/2+1] = nibble << 4
|
||||||
|
predictor = predictor + (nibble << exp)
|
||||||
|
self.tlsamps[0] = self.tlsamps[1]
|
||||||
|
self.tlsamps[1] = clamp(predictor, -32768, 32767)
|
||||||
|
error = error + ((self.tlsamps[1] - inbuf[i]) ** 2)
|
||||||
|
else:
|
||||||
|
j = 14
|
||||||
|
if j == 14:
|
||||||
|
break
|
||||||
|
return error, data
|
||||||
|
def repack_adpcm(self, idx, table, inbuf):
|
||||||
|
data = [0 for i in range(8)]
|
||||||
|
blsamps = [ 0 , 0 ]
|
||||||
|
bestidx = -1
|
||||||
|
besterror = 999999999.0
|
||||||
|
for tblidx in xrange(8):
|
||||||
|
error, testdata = self.compress_adpcm(idx, table, tblidx, inbuf)
|
||||||
|
if error < besterror:
|
||||||
|
besterror = error
|
||||||
|
for x in xrange(8):
|
||||||
|
data[x] = testdata[x]
|
||||||
|
for x in xrange(2):
|
||||||
|
blsamps[x] = self.tlsamps[x]
|
||||||
|
bestidx = tblidx
|
||||||
|
for x in xrange(2):
|
||||||
|
self.rlsamps[idx][x] = blsamps[x]
|
||||||
|
return data
|
||||||
|
def encode(self, buffer, offset=0):
|
||||||
|
sampsbuf = [0 for i in range(14)]
|
||||||
|
templen = len(buffer)
|
||||||
|
templen = templen / 4
|
||||||
|
modlen = templen % 14
|
||||||
|
for x in xrange(14-modlen):
|
||||||
|
buffer = buffer + '\x00'
|
||||||
|
buffer = buffer + '\x00'
|
||||||
|
buffer = buffer + '\x00'
|
||||||
|
buffer = buffer + '\x00'
|
||||||
|
num_samps = len(buffer) / 4
|
||||||
|
blocks = (num_samps + 13) / 14
|
||||||
|
snddatal = []
|
||||||
|
snddatar = []
|
||||||
|
co = offset
|
||||||
|
temp = 0
|
||||||
|
for x in xrange(num_samps):
|
||||||
|
snddatal.append(Struct.int16(buffer[co:co+2]))
|
||||||
|
co += 2
|
||||||
|
snddatar.append(Struct.int16(buffer[co:co+2]))
|
||||||
|
co += 2
|
||||||
|
data = [0 for i in range(blocks*16)]
|
||||||
|
data1_off = 0
|
||||||
|
data2_off = blocks * 8
|
||||||
|
self.info.chan2_start = data2_off
|
||||||
|
for i in xrange(blocks):
|
||||||
|
for j in xrange(14):
|
||||||
|
sampsbuf[j] = snddatal[i*14+j]
|
||||||
|
out_buf = self.repack_adpcm(0, self.deftbl, sampsbuf)
|
||||||
|
for k in xrange(8):
|
||||||
|
data[data1_off+k] = out_buf[k]
|
||||||
|
for j in xrange(14):
|
||||||
|
sampsbuf[j] = snddatar[i*14+j]
|
||||||
|
out_buf = self.repack_adpcm(1, self.deftbl, sampsbuf)
|
||||||
|
for k in xrange(8):
|
||||||
|
data[data2_off+k] = out_buf[k]
|
||||||
|
data1_off += 8
|
||||||
|
data2_off += 8
|
||||||
|
self.info.loop_end = blocks * 7
|
||||||
|
return data
|
||||||
|
def create_bns(self, inbuf, samplerate=44100, channels=2):
|
||||||
|
self.info.chan_cnt = channels
|
||||||
|
self.info.samplerate = samplerate
|
||||||
|
assert samplerate >=32000
|
||||||
|
self.data.data = ''.join(Struct.int8(p) for p in self.encode(inbuf))
|
||||||
|
self.data.size = len(self.data.data)
|
||||||
|
self.header.data_len = self.data.size
|
||||||
|
self.header.filesize = self.info.size + self.data.size + 8 + self.header.size
|
||||||
|
self.info.loop_end = self.data.size - (self.data.size / 7)
|
||||||
|
for x in xrange(16):
|
||||||
|
self.info.coefficients1[x] = self.deftbl[x]
|
||||||
|
if self.info.chan_cnt == 2:
|
||||||
|
for x in xrange(16): self.info.coefficients2[x] = self.deftbl[x]
|
||||||
|
return
|
||||||
|
def decode_adpcm(self, index, coefs, buffer):
|
||||||
|
outbuf = [0 for i in range(14)]
|
||||||
|
header = Struct.uint8(buffer[0:1], endian='>')
|
||||||
|
coef_index = (header >> 4) & 0x7
|
||||||
|
scale = 1 << (header & 0xf)
|
||||||
|
hist1 = self.phist1[index]
|
||||||
|
hist2 = self.phist2[index]
|
||||||
|
coef1 = coefs[coef_index * 2 + 0]
|
||||||
|
coef2 = coefs[coef_index * 2 + 1]
|
||||||
|
for x in xrange(14):
|
||||||
|
sample_byte = Struct.uint8(buffer[x/2+1:x/2+2], endian='>')
|
||||||
|
if x&1:
|
||||||
|
nibble = (sample_byte & 0xf0) >> 4
|
||||||
|
else:
|
||||||
|
nibble = (sample_byte & 0x0f) >> 0
|
||||||
|
if nibble >= 8:
|
||||||
|
nibble -= 16
|
||||||
|
sample_delta_11 = (scale * nibble) << 11
|
||||||
|
predicted_sample_11 = coef1*hist1 + coef2*hist2
|
||||||
|
sample_11 = predicted_sample_11 + sample_delta_11
|
||||||
|
sample_raw = (sample_11 + 1024) >> 11
|
||||||
|
sample_raw = clamp(sample_raw, -32768, 32767)
|
||||||
|
outbuf[x] = sample_raw
|
||||||
|
hist2 = hist1
|
||||||
|
hist1 = outbuf[x]
|
||||||
|
self.phist1[index] = hist1
|
||||||
|
self.phist2[index] = hist2
|
||||||
|
return outbuf
|
||||||
|
def decode(self, buffer, offset):
|
||||||
|
decoded_buffer = []
|
||||||
|
if self.info.chan_cnt == 2:
|
||||||
|
multi = 16
|
||||||
|
coeff0 = self.info.coefficients1
|
||||||
|
coeff1 = self.info.coefficients2
|
||||||
|
elif self.info.chan_cnt == 1:
|
||||||
|
multi = 8
|
||||||
|
coeff0 = self.info.coefficients1
|
||||||
|
coeff1 = self.info.coefficients1
|
||||||
|
blocks = self.data.size / multi
|
||||||
|
data1_offset = offset
|
||||||
|
data2_offset = offset + blocks * 8
|
||||||
|
decoded_buffer_l = [0 for i in range(blocks * 14)]
|
||||||
|
decoded_buffer_r = [0 for i in range(blocks * 14)]
|
||||||
|
for x in xrange(blocks):
|
||||||
|
out_buffer = self.decode_adpcm(0, coeff0, buffer[data1_offset:data1_offset+8])
|
||||||
|
for y in xrange(14):
|
||||||
|
decoded_buffer_l[x*14+y] = out_buffer[y]
|
||||||
|
out_buffer = self.decode_adpcm(1, coeff1, buffer[data2_offset:data2_offset+8])
|
||||||
|
for y in xrange(14):
|
||||||
|
decoded_buffer_r[x*14+y] = out_buffer[y]
|
||||||
|
data1_offset += 8
|
||||||
|
data2_offset += 8
|
||||||
|
for x in xrange(blocks * 14):
|
||||||
|
decoded_buffer.append(decoded_buffer_l[x])
|
||||||
|
decoded_buffer.append(decoded_buffer_r[x])
|
||||||
|
return decoded_buffer
|
||||||
|
def eat(self, buffer, offset, decode=False):
|
||||||
|
co = self.header.eat(buffer, offset)
|
||||||
|
co = self.info.eat(buffer, co)
|
||||||
|
co = self.data.eat(buffer, co)
|
||||||
|
self.data.data = buffer[co:]
|
||||||
|
if decode == True:
|
||||||
|
buffer_out = self.decode(buffer, co)
|
||||||
|
return buffer_out
|
||||||
|
return
|
||||||
|
def show(self):
|
||||||
|
self.header.show()
|
||||||
|
self.info.show()
|
||||||
|
self.data.show()
|
||||||
|
return
|
||||||
|
def write(self, filename):
|
||||||
|
file = open(filename, 'wb')
|
||||||
|
if file:
|
||||||
|
self.header.write(file)
|
||||||
|
self.info.write(file)
|
||||||
|
self.data.write(file)
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file for writing"
|
||||||
|
return
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if sys.argv[1] == "-d":
|
||||||
|
file = open(sys.argv[2], 'rb')
|
||||||
|
if file:
|
||||||
|
buffer = file.read()
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file"
|
||||||
|
sys.exit(2)
|
||||||
|
bns = BNS()
|
||||||
|
wavbuffer = bns.eat(buffer, 0x00, True)
|
||||||
|
wavstring = ''.join(Struct.int16(p) for p in wavbuffer)
|
||||||
|
f = SoundFile(wavstring, sys.argv[3], bns.info.samplerate)
|
||||||
|
f.write()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "-e":
|
||||||
|
f = wave.open(sys.argv[2], 'rb')
|
||||||
|
num_chans = f.getnchannels()
|
||||||
|
samplerate = f.getframerate()
|
||||||
|
assert samplerate >= 32000
|
||||||
|
assert samplerate <= 48000
|
||||||
|
buffer = f.readframes(f.getnframes())
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
bns = BNS()
|
||||||
|
bns.create_bns(buffer, samplerate, num_chans)
|
||||||
|
bns.write(sys.argv[3])
|
||||||
|
elif sys.argv[1] == "-s":
|
||||||
|
file = open(sys.argv[2], 'rb')
|
||||||
|
if file:
|
||||||
|
buffer = file.read()
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file"
|
||||||
|
sys.exit(2)
|
||||||
|
bns = BNS()
|
||||||
|
bns.eat(buffer, 0x00, False)
|
||||||
|
bns.show()
|
||||||
|
else:
|
||||||
|
print "Unknown second argument. possiblities are -d and -e"
|
||||||
|
print "Usage: python bns.py -d <sound.bin> <output.wav>"
|
||||||
|
print " == OR == "
|
||||||
|
print " python bns.py -e <input.wav> <sound.bin> "
|
||||||
|
print " == OR == "
|
||||||
|
print " python bns.py -s <sound.bin> "
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Import Psyco if available
|
||||||
|
try:
|
||||||
|
import psyco
|
||||||
|
psyco.full()
|
||||||
|
except ImportError:
|
||||||
|
print "no psycho import"
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
print "Usage: python bns.py -d <sound.bin> <output.wav>"
|
||||||
|
print " == OR == "
|
||||||
|
print " python bns.py -e <input.wav> <sound.bin> "
|
||||||
|
print " == OR == "
|
||||||
|
print " python bns.py -s <sound.bin> "
|
||||||
|
sys.exit(1)
|
||||||
|
main()
|
||||||
|
|
137
WiiPy/common.py
Normal file
137
WiiPy/common.py
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array, time, sys, tempfile, wave
|
||||||
|
from cStringIO import StringIO
|
||||||
|
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
from Struct import Struct
|
||||||
|
|
||||||
|
def align(x, boundary):
|
||||||
|
if(x % boundary):
|
||||||
|
x += (x + boundary) - (x % boundary)
|
||||||
|
return x
|
||||||
|
|
||||||
|
def clamp(var, min, max):
|
||||||
|
if var < min: var = min
|
||||||
|
if var > max: var = max
|
||||||
|
return var
|
||||||
|
|
||||||
|
def abs(var):
|
||||||
|
if var < 0:
|
||||||
|
var = var + (2 * var)
|
||||||
|
return var
|
||||||
|
|
||||||
|
def hexdump(s, sep=" "): # just dumps hex values
|
||||||
|
return sep.join(map(lambda x: "%02x" % ord(x), s))
|
||||||
|
|
||||||
|
def hexdump2(src, length = 16): # dumps to a "hex editor" style output
|
||||||
|
result = []
|
||||||
|
for i in xrange(0, len(src), length):
|
||||||
|
s = src[i:i + length]
|
||||||
|
if(len(s) % 4 == 0):
|
||||||
|
mod = 0
|
||||||
|
else:
|
||||||
|
mod = 1
|
||||||
|
hexa = ''
|
||||||
|
for j in range((len(s) / 4) + mod):
|
||||||
|
hexa += ' '.join(["%02X" % ord(x) for x in s[j * 4:j * 4 + 4]])
|
||||||
|
if(j != ((len(s) / 4) + mod) - 1):
|
||||||
|
hexa += ' '
|
||||||
|
printable = s.translate(''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)]))
|
||||||
|
result.append("0x%04X %-*s %s\n" % (i, (length * 3) + 2, hexa, printable))
|
||||||
|
return ''.join(result)
|
||||||
|
|
||||||
|
class Crypto(object):
|
||||||
|
"""This is a Cryptographic/hash class used to abstract away things (to make changes easier)"""
|
||||||
|
align = 64
|
||||||
|
@classmethod
|
||||||
|
def decryptData(self, key, iv, data, align = True):
|
||||||
|
"""Decrypts some data (aligns to 64 bytes, if needed)."""
|
||||||
|
if((len(data) % self.align) != 0 and align):
|
||||||
|
return AES.new(key, AES.MODE_CBC, iv).decrypt(data + ("\x00" * (self.align - (len(data) % self.align))))
|
||||||
|
else:
|
||||||
|
return AES.new(key, AES.MODE_CBC, iv).decrypt(data)
|
||||||
|
@classmethod
|
||||||
|
def encryptData(self, key, iv, data, align = True):
|
||||||
|
"""Encrypts some data (aligns to 64 bytes, if needed)."""
|
||||||
|
if((len(data) % self.align) != 0 and align):
|
||||||
|
return AES.new(key, AES.MODE_CBC, iv).encrypt(data + ("\x00" * (self.align - (len(data) % self.align))))
|
||||||
|
else:
|
||||||
|
return AES.new(key, AES.MODE_CBC, iv).encrypt(data)
|
||||||
|
@classmethod
|
||||||
|
def decryptContent(self, titlekey, idx, data):
|
||||||
|
"""Decrypts a Content."""
|
||||||
|
iv = struct.pack(">H", idx) + "\x00" * 14
|
||||||
|
return self.decryptData(titlekey, iv, data)
|
||||||
|
@classmethod
|
||||||
|
def decryptTitleKey(self, commonkey, tid, enckey):
|
||||||
|
"""Decrypts a Content."""
|
||||||
|
iv = struct.pack(">Q", tid) + "\x00" * 8
|
||||||
|
return self.decryptData(commonkey, iv, enckey, False)
|
||||||
|
@classmethod
|
||||||
|
def encryptContent(self, titlekey, idx, data):
|
||||||
|
"""Encrypts a Content."""
|
||||||
|
iv = struct.pack(">H", idx) + "\x00" * 14
|
||||||
|
return self.encryptData(titlekey, iv, data)
|
||||||
|
@classmethod
|
||||||
|
def createSHAHash(self, data): #tested WORKING (without padding)
|
||||||
|
return hashlib.sha1(data).digest()
|
||||||
|
@classmethod
|
||||||
|
def createSHAHashHex(self, data):
|
||||||
|
return hashlib.sha1(data).hexdigest()
|
||||||
|
@classmethod
|
||||||
|
def createMD5HashHex(self, data):
|
||||||
|
return hashlib.md5(data).hexdigest()
|
||||||
|
@classmethod
|
||||||
|
def createMD5Hash(self, data):
|
||||||
|
return hashlib.md5(data).digest()
|
||||||
|
@classmethod
|
||||||
|
def validateSHAHash(self, data, hash):
|
||||||
|
contentHash = hashlib.sha1(data).digest()
|
||||||
|
return 1
|
||||||
|
if (contentHash == hash):
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
#raise ValueError('Content hash : %s : len %i' % (hexdump(contentHash), len(contentHash)) + 'Expected : %s : len %i' % (hexdump(hash), len(hash)))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class WiiObject(object):
|
||||||
|
@classmethod
|
||||||
|
def load(cls, data, *args, **kwargs):
|
||||||
|
self = cls()
|
||||||
|
self._load(data, *args, **kwargs)
|
||||||
|
return self
|
||||||
|
@classmethod
|
||||||
|
def loadFile(cls, filename, *args, **kwargs):
|
||||||
|
return cls.load(open(filename, "rb").read(), *args, **kwargs)
|
||||||
|
|
||||||
|
def dump(self, *args, **kwargs):
|
||||||
|
return self._dump(*args, **kwargs)
|
||||||
|
def dumpFile(self, filename, *args, **kwargs):
|
||||||
|
open(filename, "wb").write(self.dump(*args, **kwargs))
|
||||||
|
return filename
|
||||||
|
|
||||||
|
class WiiArchive(WiiObject):
|
||||||
|
@classmethod
|
||||||
|
def loadDir(cls, dirname):
|
||||||
|
self = cls()
|
||||||
|
self._loadDir(dirname)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def dumpDir(self, dirname):
|
||||||
|
if(not os.path.isdir(dirname)):
|
||||||
|
os.mkdir(dirname)
|
||||||
|
self._dumpDir(dirname)
|
||||||
|
return dirname
|
||||||
|
|
||||||
|
class WiiHeader(object):
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
def addFile(self, filename):
|
||||||
|
open(filename, "wb").write(self.add())
|
||||||
|
def removeFile(self, filename):
|
||||||
|
open(filename, "wb").write(self.remove())
|
||||||
|
@classmethod
|
||||||
|
def loadFile(cls, filename, *args, **kwargs):
|
||||||
|
return cls(open(filename, "rb").read(), *args, **kwargs)
|
||||||
|
|
56
WiiPy/compression.py
Normal file
56
WiiPy/compression.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
class LZ77(WiiHeader):
|
||||||
|
class WiiLZ77: # class by marcan, used under scope of BSD license
|
||||||
|
TYPE_LZ77 = 1
|
||||||
|
def __init__(self, file, offset):
|
||||||
|
self.file = file
|
||||||
|
self.offset = offset
|
||||||
|
|
||||||
|
self.file.seek(self.offset)
|
||||||
|
|
||||||
|
hdr = struct.unpack("<I",self.file.read(4))[0]
|
||||||
|
self.uncompressed_length = hdr>>8
|
||||||
|
self.compression_type = hdr>>4 & 0xF
|
||||||
|
|
||||||
|
if self.compression_type != self.TYPE_LZ77:
|
||||||
|
raise ValueError("Unsupported compression method %d"%self.compression_type)
|
||||||
|
|
||||||
|
def uncompress(self):
|
||||||
|
dout = ""
|
||||||
|
|
||||||
|
self.file.seek(self.offset + 0x4)
|
||||||
|
|
||||||
|
while len(dout) < self.uncompressed_length:
|
||||||
|
flags = struct.unpack("<B",self.file.read(1))[0]
|
||||||
|
|
||||||
|
for i in range(8):
|
||||||
|
if flags & 0x80:
|
||||||
|
info = struct.unpack(">H",self.file.read(2))[0]
|
||||||
|
num = 3 + ((info>>12)&0xF)
|
||||||
|
disp = info & 0xFFF
|
||||||
|
ptr = len(dout) - (info & 0xFFF) - 1
|
||||||
|
for i in range(num):
|
||||||
|
dout += dout[ptr]
|
||||||
|
ptr+=1
|
||||||
|
if len(dout) >= self.uncompressed_length:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
dout += self.file.read(1)
|
||||||
|
flags <<= 1
|
||||||
|
if len(dout) >= self.uncompressed_length:
|
||||||
|
break
|
||||||
|
self.data = dout
|
||||||
|
return self.data
|
||||||
|
def remove(self):
|
||||||
|
hdr = self.data[:4]
|
||||||
|
if hdr != "LZ77":
|
||||||
|
return self.data
|
||||||
|
file = StringIO.StringIO(self.data)
|
||||||
|
file.seek(4)
|
||||||
|
unc = self.WiiLZ77(file, file.tell())
|
||||||
|
data = unc.uncompress()
|
||||||
|
|
||||||
|
return data
|
||||||
|
def compress(self, fn = ""):
|
||||||
|
raise NotImplementedError
|
357
WiiPy/disc.py
Normal file
357
WiiPy/disc.py
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
from common import *
|
||||||
|
from title import *
|
||||||
|
|
||||||
|
class WOD: #WiiOpticalDisc
|
||||||
|
class discHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.discId = Struct.string(1)
|
||||||
|
self.gameCode = Struct.string(2)
|
||||||
|
self.region = Struct.string(1)
|
||||||
|
self.makerCode = Struct.uint8[2]
|
||||||
|
self.h = Struct.uint8
|
||||||
|
self.version = Struct.uint8
|
||||||
|
self.audioStreaming = Struct.uint8
|
||||||
|
self.streamingBufSize = Struct.uint8
|
||||||
|
self.unused = Struct.uint8[14]
|
||||||
|
self.magic = Struct.uint32
|
||||||
|
self.title = Struct.string(64)
|
||||||
|
self.hashVerify = Struct.uint8
|
||||||
|
self.h3verify = Struct.uint8
|
||||||
|
def __str__(self):
|
||||||
|
ret = ''
|
||||||
|
ret += '%s [%s%s%s]\n' % (self.title, self.discId, self.gameCode, self.region)
|
||||||
|
if self.region == 'P':
|
||||||
|
ret += 'Region : PAL\n'
|
||||||
|
elif self.region == 'E':
|
||||||
|
ret += 'Region : NTSC\n'
|
||||||
|
elif self.region == 'J':
|
||||||
|
ret += 'Region : JPN\n'
|
||||||
|
ret += 'Version 0x%x Maker %i%i Audio streaming %x\n' % (self.version, self.makerCode[0], self.makerCode[1], self.audioStreaming)
|
||||||
|
ret += 'Hash verify flag 0x%x H3 verify flag : 0x%x\n' % (self.hashVerify, self.h3verify)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# Many many thanks to Wiipower
|
||||||
|
class Apploader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.buildDate = Struct.string(16)
|
||||||
|
self.entryPoint = Struct.uint32
|
||||||
|
self.size = Struct.uint32
|
||||||
|
self.trailingSize = Struct.uint32
|
||||||
|
self.padding = Struct.uint8[4]
|
||||||
|
def __str__(self):
|
||||||
|
ret = ''
|
||||||
|
ret += 'Apploader built on %s\n' % self.buildDate
|
||||||
|
ret += 'Entry point 0x%x\n' % self.entryPoint
|
||||||
|
ret += 'Size %i (%i of them are trailing)\n' % (self.size, self.trailingSize)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
ret = ''
|
||||||
|
ret += '%s\n' % self.discHdr
|
||||||
|
ret += 'Found %i partitions (table at 0x%x)\n' % (self.partitionCount, self.partsTableOffset)
|
||||||
|
ret += 'Found %i channels (table at 0x%x)\n' % (self.channelsCount, self.chansTableOffset)
|
||||||
|
ret += '\n'
|
||||||
|
ret += 'Partition %i opened (type 0x%x) at 0x%x\n' % (self.partitionOpen, self.partitionType, self.partitionOffset)
|
||||||
|
ret += 'Partition name : %s' % self.partitionHdr
|
||||||
|
ret += 'Partition key : %s\n' % hexdump(self.partitionKey)
|
||||||
|
ret += 'Partition IOS : IOS%i\n' % self.partitionIos
|
||||||
|
ret += 'Partition tmd : 0x%x (%x)\n' % (self.tmdOffset, self.tmdSize)
|
||||||
|
ret += 'Partition main.dol : 0x%x (%x)\n' % (self.dolOffset, self.dolSize)
|
||||||
|
ret += 'Partition FST : 0x%x (%x)\n' % (self.fstSize, self.fstOffset)
|
||||||
|
ret += '%s\n' % (self.appLdr)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __init__(self, f):
|
||||||
|
self.f = f
|
||||||
|
self.fp = open(f, 'rb')
|
||||||
|
|
||||||
|
self.discHdr = self.discHeader().unpack(self.fp.read(0x400))
|
||||||
|
if self.discHdr.magic != 0x5D1C9EA3:
|
||||||
|
raise Exception('Wrong disc magic')
|
||||||
|
|
||||||
|
self.fp.seek(0x40000)
|
||||||
|
|
||||||
|
self.partitionCount = 1 + struct.unpack(">I", self.fp.read(4))[0]
|
||||||
|
self.partsTableOffset = struct.unpack(">I", self.fp.read(4))[0] << 2
|
||||||
|
|
||||||
|
self.channelsCount = struct.unpack(">I", self.fp.read(4))[0]
|
||||||
|
self.chansTableOffset = struct.unpack(">I", self.fp.read(4))[0] << 2
|
||||||
|
|
||||||
|
self.markedBlocks = []
|
||||||
|
|
||||||
|
self.partitionOpen = -1
|
||||||
|
self.partitionOffset = -1
|
||||||
|
self.partitionType = -1
|
||||||
|
|
||||||
|
def markContent(self, offset, size):
|
||||||
|
blockStart = offset / 0x7C00
|
||||||
|
blockLen = (align(size, 0x7C00)) / 0x7C00
|
||||||
|
|
||||||
|
for x in range(blockStart, blockStart + blockLen):
|
||||||
|
try:
|
||||||
|
self.markedBlocks.index(blockStart + x)
|
||||||
|
except:
|
||||||
|
self.markedBlocks.append(blockStart + x)
|
||||||
|
|
||||||
|
def decryptBlock(self, block):
|
||||||
|
if len(block) != 0x8000:
|
||||||
|
raise Exception('Block size too big/small')
|
||||||
|
|
||||||
|
blockIV = block[0x3d0:0x3e0]
|
||||||
|
#print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV))
|
||||||
|
blockData = block[0x0400:0x8000]
|
||||||
|
|
||||||
|
return Crypto().decryptData(self.partitionKey, blockIV, blockData, True)
|
||||||
|
|
||||||
|
def readBlock(self, blockNumber):
|
||||||
|
self.fp.seek(self.partitionOffset + 0x20000 + (0x8000 * blockNumber))
|
||||||
|
return self.decryptBlock(self.fp.read(0x8000))
|
||||||
|
|
||||||
|
def readPartition(self, offset, size):
|
||||||
|
|
||||||
|
readStart = offset / 0x7C00
|
||||||
|
readLen = (align(size, 0x7C00)) / 0x7C00
|
||||||
|
blob = ''
|
||||||
|
|
||||||
|
#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))
|
||||||
|
|
||||||
|
for x in range(readLen + 1):
|
||||||
|
blob += self.decryptBlock(self.fp.read(0x8000))
|
||||||
|
|
||||||
|
self.markContent(offset, size)
|
||||||
|
|
||||||
|
#print 'Read from 0x%x to 0x%x' % (offset, offset + size)
|
||||||
|
offset -= readStart * 0x7C00
|
||||||
|
return blob[offset:offset + size]
|
||||||
|
|
||||||
|
def readUnencrypted(self, offset, size):
|
||||||
|
if offset + size > 0x20000:
|
||||||
|
raise Exception('This read is on encrypted data')
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
return self.fp.read(size)
|
||||||
|
class fstObject(object):
|
||||||
|
#TODO: add ability to extract file by path
|
||||||
|
def __init__(self, name, iso=None):
|
||||||
|
''' do init stuff here '''
|
||||||
|
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:
|
||||||
|
j = 1
|
||||||
|
while(j<size):
|
||||||
|
j = self.parseFst(fst, names, j, fstDir)
|
||||||
|
return size
|
||||||
|
if fst[12 * i] == '\x01':
|
||||||
|
newDir = self.fstObject(fileName)
|
||||||
|
j = i+1
|
||||||
|
while(j<size):
|
||||||
|
j = self.parseFst(fst, names, j, newDir)
|
||||||
|
fstDir.addChild(newDir)
|
||||||
|
return size
|
||||||
|
else:
|
||||||
|
fileOffset = 4 * struct.unpack(">I", fst[(12*i + 4):(12*i + 4) + 4])[0]
|
||||||
|
newFile = self.fstObject(fileName)
|
||||||
|
newFile.type = 0
|
||||||
|
newFile.fileOffset = fileOffset
|
||||||
|
newFile.size = size
|
||||||
|
newFile.nameOff = nameOff
|
||||||
|
fstDir.addChild(newFile)
|
||||||
|
self.markContent(fileOffset, size)
|
||||||
|
return i+1
|
||||||
|
|
||||||
|
def openPartition(self, index):
|
||||||
|
if index+1 > self.partitionCount:
|
||||||
|
raise ValueError('Partition index too big')
|
||||||
|
|
||||||
|
self.partitionOpen = index
|
||||||
|
|
||||||
|
self.partitionOffset = self.partsTableOffset + (8 * self.partitionOpen)
|
||||||
|
|
||||||
|
self.fp.seek(self.partsTableOffset + (8 * self.partitionOpen))
|
||||||
|
|
||||||
|
self.partitionOffset = struct.unpack(">I", self.fp.read(4))[0] << 2
|
||||||
|
self.partitionType = struct.unpack(">I", self.fp.read(4))[0]
|
||||||
|
|
||||||
|
self.fp.seek(self.partitionOffset)
|
||||||
|
|
||||||
|
self.tikData = self.fp.read(0x2A4)
|
||||||
|
self.partitionKey = Ticket(self.tikData).getTitleKey()
|
||||||
|
|
||||||
|
self.tmdSize = struct.unpack(">I", self.fp.read(4))[0]
|
||||||
|
self.tmdOffset = struct.unpack(">I", self.fp.read(4))[0] >> 2
|
||||||
|
|
||||||
|
self.certsSize = struct.unpack(">I", self.fp.read(4))[0]
|
||||||
|
self.certsOffset = struct.unpack(">I", self.fp.read(4))[0] >> 2
|
||||||
|
|
||||||
|
self.H3TableOffset = struct.unpack(">I", self.fp.read(4))[0] >> 2
|
||||||
|
|
||||||
|
self.dataOffset = struct.unpack(">I", self.fp.read(4))[0] >> 2
|
||||||
|
self.dataSize = struct.unpack(">I", self.fp.read(4))[0] >> 2
|
||||||
|
|
||||||
|
self.fstOffset = 4 * struct.unpack(">I", self.readPartition (0x424, 4))[0]
|
||||||
|
self.fstSize = 4 * struct.unpack(">I", self.readPartition (0x428, 4))[0]
|
||||||
|
|
||||||
|
self.dolOffset = 4 * struct.unpack(">I", self.readPartition (0x420, 4))[0]
|
||||||
|
self.dolSize = self.fstOffset - self.dolOffset
|
||||||
|
|
||||||
|
self.appLdr = self.Apploader().unpack(self.readPartition (0x2440, 32))
|
||||||
|
self.partitionHdr = self.discHeader().unpack(self.readPartition (0x0, 0x400))
|
||||||
|
|
||||||
|
self.partitionIos = TMD(self.getPartitionTmd()).getIOSVersion() & 0x0fffffff
|
||||||
|
|
||||||
|
def getFst(self):
|
||||||
|
fstBuf = self.readPartition(self.fstOffset, self.fstSize)
|
||||||
|
return fstBuf
|
||||||
|
|
||||||
|
def getIsoBootmode(self):
|
||||||
|
if self.discHdr.discId == 'R' or self.discHdr.discId == '_':
|
||||||
|
return 2
|
||||||
|
elif self.discHdr.discId == '0':
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def getOpenedPartition(self):
|
||||||
|
return self.partitionOpen
|
||||||
|
|
||||||
|
def getOpenedPartitionOffset(self):
|
||||||
|
return self.partitionOffset
|
||||||
|
|
||||||
|
def getOpenedPartitionType(self):
|
||||||
|
return self.partitionType
|
||||||
|
|
||||||
|
def getPartitionsCount(self):
|
||||||
|
return self.partitionCount
|
||||||
|
|
||||||
|
def getChannelsCount(self):
|
||||||
|
return self.channelsCount
|
||||||
|
|
||||||
|
def getPartitionCerts(self):
|
||||||
|
return self.readUnencrypted(self.certsOffset, self.certsSize)
|
||||||
|
|
||||||
|
def getPartitionH3Table(self):
|
||||||
|
return self.readUnencrypted(self.H3TableOffset, 0x18000)
|
||||||
|
|
||||||
|
def getPartitionTmd(self):
|
||||||
|
return self.readUnencrypted(self.tmdOffset, self.tmdSize)
|
||||||
|
|
||||||
|
def getPartitionTik(self):
|
||||||
|
self.fp.seek(self.partitionOffset)
|
||||||
|
return self.fp.read(0x2A4)
|
||||||
|
|
||||||
|
def getPartitionApploader(self):
|
||||||
|
return self.readPartition (0x2440, self.appLdr.size + self.appLdr.trailingSize + 32)
|
||||||
|
|
||||||
|
def getPartitionMainDol(self):
|
||||||
|
return self.readPartition (self.dolOffset, self.dolSize)
|
||||||
|
|
||||||
|
def dumpPartition(self, fn):
|
||||||
|
rawPartition = open(fn, 'w+b')
|
||||||
|
|
||||||
|
print 'Partition useful data %i Mb' % (align(len(self.markedBlocks) * 0x7C00, 1024) / 1024 / 1024)
|
||||||
|
|
||||||
|
self.fp.seek(self.partitionOffset)
|
||||||
|
rawPartition.write(self.fp.read(0x2A4)) # Write teh TIK
|
||||||
|
rawPartition.write(self.readUnencrypted(0, 0x20000 - 0x2A4)) # Write the TMD and other stuff
|
||||||
|
|
||||||
|
for x in range(len(self.markedBlocks)):
|
||||||
|
rawPartition.write(self.readBlock(self.markedBlocks[x])) # Write each decrypted block
|
||||||
|
|
||||||
|
class updateInf():
|
||||||
|
def __init__(self, f):
|
||||||
|
self.buffer = open(f, 'r+b').read()
|
||||||
|
def __str__(self):
|
||||||
|
out = ''
|
||||||
|
|
||||||
|
self.buildDate = self.buffer[:0x10]
|
||||||
|
self.fileCount = struct.unpack('>L', self.buffer[0x10:0x14])[0]
|
||||||
|
|
||||||
|
out += 'This update partition was built on %s and has %i files\n\n' % (self.buildDate, self.fileCount)
|
||||||
|
|
||||||
|
for x in range(self.fileCount):
|
||||||
|
updateEntry = self.buffer[0x20 + x * 0x200:0x20 + (x + 1) * 0x200]
|
||||||
|
titleType = struct.unpack('>L', updateEntry[:0x4])[0]
|
||||||
|
titleAttr = struct.unpack('>L', updateEntry[0x4:0x8])[0]
|
||||||
|
titleUnk1 = struct.unpack('>L', updateEntry[0x8:0xC])[0]
|
||||||
|
titleType2 = struct.unpack('>L', updateEntry[0xC:0x10])[0]
|
||||||
|
titleFile = updateEntry[0x10:0x50]
|
||||||
|
titleFile = titleFile[:titleFile.find('\x00')]
|
||||||
|
titleID = struct.unpack('>Q', updateEntry[0x50:0x58])[0]
|
||||||
|
titleMajor = struct.unpack('>B', updateEntry[0x58:0x59])[0]
|
||||||
|
titleMinor = struct.unpack('>B', updateEntry[0x59:0x5A])[0]
|
||||||
|
titleName = updateEntry[0x60:0xA0]
|
||||||
|
titleName = titleName[:titleName.find('\x00')]
|
||||||
|
titleInfo = updateEntry[0xA0:0xE0]
|
||||||
|
titleInfo = titleInfo[:titleInfo.find('\x00')]
|
||||||
|
out += 'Update type : 0x%x\n' % titleType
|
||||||
|
out += 'Update flag : %i (0 means critical, 1 means need reboot)\n' % titleAttr
|
||||||
|
out += 'Update file : %s\n' % titleFile
|
||||||
|
out += 'Update ID : %lu\n' % titleID
|
||||||
|
out += 'Update version : %i.%i\n' % (titleMajor, titleMinor)
|
||||||
|
out += 'Update name : %s\n' % titleName
|
||||||
|
out += 'Update info : %s\n' % titleInfo
|
||||||
|
out += '\n'
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
0
WiiPy/experimental/__init__.py
Normal file
0
WiiPy/experimental/__init__.py
Normal file
257
WiiPy/experimental/bmg.py
Executable file
257
WiiPy/experimental/bmg.py
Executable file
@ -0,0 +1,257 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import sys, re, struct
|
||||||
|
|
||||||
|
from Struct import Struct
|
||||||
|
|
||||||
|
def nullterm(str_plus):
|
||||||
|
z = str_plus.find('\x00\x00')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
def denullterm(str_plus):
|
||||||
|
z = str_plus.find('\r\n')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
class BMG(object):
|
||||||
|
class BMG_DAT1(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.length = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Magic: %s\n" % self.magic
|
||||||
|
return_string += "Length: %08x\n " % self.length
|
||||||
|
return return_string
|
||||||
|
def write(self, file):
|
||||||
|
file.write(self.magic)
|
||||||
|
file.write(struct.pack('>I', self.length))
|
||||||
|
return
|
||||||
|
|
||||||
|
class BMG_INF1(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.length = Struct.uint32
|
||||||
|
self.count = Struct.uint16
|
||||||
|
self.unknown01 = Struct.uint16
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Magic: %s\n" % self.magic
|
||||||
|
return_string += "Length: %08x\n " % self.length
|
||||||
|
return_string += "Count: %04x\n" % self.count
|
||||||
|
return_string += "Unknown: %04x\n" % self.unknown01
|
||||||
|
return return_string
|
||||||
|
def write(self, file):
|
||||||
|
file.write(self.magic)
|
||||||
|
file.write(struct.pack('>I', self.length))
|
||||||
|
file.write(struct.pack('>H', self.count))
|
||||||
|
file.write(struct.pack('>H', self.unknown01))
|
||||||
|
return
|
||||||
|
|
||||||
|
class BMG_Header(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.magic2 = Struct.string(4)
|
||||||
|
self.length = Struct.uint32
|
||||||
|
self.chunk_cnt = Struct.uint32
|
||||||
|
self.unknown01 = Struct.uint8
|
||||||
|
self.unknown02 = Struct.uint8
|
||||||
|
self.unknown03 = Struct.uint16
|
||||||
|
self.unknown04 = Struct.uint32
|
||||||
|
self.unknown05 = Struct.uint32
|
||||||
|
self.unknown06 = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Magic: %s\n" % self.magic
|
||||||
|
return_string += "Magic: %s\n" % self.magic2
|
||||||
|
return_string += "Length: %08x\n" % self.length
|
||||||
|
return_string += "Chunk Count: %08x\n" % self.chunk_cnt
|
||||||
|
return_string += "Unknown01: %02x\n" % self.unknown01
|
||||||
|
return_string += "Unknown02: %02x\n" % self.unknown02
|
||||||
|
return_string += "Unknown03: %04x\n" % self.unknown03
|
||||||
|
return_string += "Unknown04: %08x\n" % self.unknown04
|
||||||
|
return_string += "Unknown05: %08x\n" % self.unknown05
|
||||||
|
return_string += "Unknown06: %08x\n" % self.unknown06
|
||||||
|
return return_string
|
||||||
|
def write(self, file):
|
||||||
|
file.write(self.magic)
|
||||||
|
file.write(self.magic2)
|
||||||
|
file.write(struct.pack('>I', self.length))
|
||||||
|
file.write(struct.pack('>I', self.chunk_cnt))
|
||||||
|
file.write(struct.pack('>B', self.unknown01))
|
||||||
|
file.write(struct.pack('>B', self.unknown02))
|
||||||
|
file.write(struct.pack('>H', self.unknown03))
|
||||||
|
file.write(struct.pack('>I', self.unknown04))
|
||||||
|
file.write(struct.pack('>I', self.unknown05))
|
||||||
|
file.write(struct.pack('>I', self.unknown06))
|
||||||
|
return
|
||||||
|
|
||||||
|
def __init__(self, data=None, out_file=None, debug=False):
|
||||||
|
self.data = []
|
||||||
|
if data != None:
|
||||||
|
self.Unpack(data, out_file, debug)
|
||||||
|
|
||||||
|
def Unpack(self, data, out_file, debug):
|
||||||
|
file = open(out_file, 'wb')
|
||||||
|
if file:
|
||||||
|
pos = 0
|
||||||
|
header = self.BMG_Header()
|
||||||
|
header.unpack(data[pos:pos+len(header)])
|
||||||
|
pos += len(header)
|
||||||
|
if debug == True:
|
||||||
|
print header
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
info = self.BMG_INF1()
|
||||||
|
info.unpack(data[pos:pos+len(info)])
|
||||||
|
pos += len(info)
|
||||||
|
if debug == True:
|
||||||
|
print info
|
||||||
|
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
if debug == True:
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
offset_list = []
|
||||||
|
for x in xrange(info.count):
|
||||||
|
offset = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
if debug == True:
|
||||||
|
print "Offset: %08x" % offset
|
||||||
|
offset_list.append(offset)
|
||||||
|
|
||||||
|
while pos % 0x10:
|
||||||
|
padding = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
if debug == True:
|
||||||
|
print "Padding: %08x" % padding
|
||||||
|
|
||||||
|
if debug == True:
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
dat1 = self.BMG_DAT1()
|
||||||
|
dat1.unpack(data[pos:pos+len(dat1)])
|
||||||
|
pos += len(dat1)
|
||||||
|
if debug == True:
|
||||||
|
print dat1
|
||||||
|
|
||||||
|
if debug == True:
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
temp = pos
|
||||||
|
|
||||||
|
unknown = Struct.uint16(data[pos:pos+2], endian='>')
|
||||||
|
pos += 2
|
||||||
|
if debug == True:
|
||||||
|
print "Unknown: %04x" % unknown
|
||||||
|
|
||||||
|
for x in xrange(info.count):
|
||||||
|
pos = temp + offset_list[x]
|
||||||
|
string = nullterm(data[pos:])
|
||||||
|
string = unicode(string, 'utf_16_be')
|
||||||
|
file.write(string.encode('utf-8'))
|
||||||
|
file.write('\r')
|
||||||
|
file.write('\n')
|
||||||
|
if debug == True:
|
||||||
|
print "String: %s" % string.encode('utf-8')
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file for writing"
|
||||||
|
sys.exit(1)
|
||||||
|
def write(self, data, out_file):
|
||||||
|
file = open(out_file, 'wb')
|
||||||
|
if file:
|
||||||
|
pos = 0
|
||||||
|
count = 0
|
||||||
|
strings_list = []
|
||||||
|
while pos < len(data):
|
||||||
|
temp = denullterm(data[pos:])
|
||||||
|
pos += len(temp) + 2
|
||||||
|
string = unicode(temp, 'utf-8')
|
||||||
|
strings_list.append(string)
|
||||||
|
count += 1
|
||||||
|
offsets_list = []
|
||||||
|
offset = 2
|
||||||
|
for x in xrange(count):
|
||||||
|
offsets_list.append(offset)
|
||||||
|
offset += len(strings_list[x]) * 2 + 2
|
||||||
|
dat1 = self.BMG_DAT1()
|
||||||
|
dat1.length = offset + 8 + (0x10 - (offset % 0x10))
|
||||||
|
dat_pad_to_add = 0x10 - (offset % 0x10)
|
||||||
|
info = self.BMG_INF1()
|
||||||
|
info.length = 0x10 + 4 * count + (0x10 - ((4 * count) % 0x10))
|
||||||
|
info_pad_to_add = 0x10 - ((4*count) % 0x10)
|
||||||
|
header = self.BMG_Header()
|
||||||
|
header.magic = "MESG"
|
||||||
|
header.magic2 = "bmg1"
|
||||||
|
header.length = info.length + dat1.length + 0x20
|
||||||
|
header.chunk_cnt = 2
|
||||||
|
header.unknown01 = 2
|
||||||
|
header.unknown02 = 0
|
||||||
|
header.unknown03 = 0
|
||||||
|
header.unknown04 = 0
|
||||||
|
header.unknown05 = 0
|
||||||
|
header.unknown06 = 0
|
||||||
|
header.write(file)
|
||||||
|
info.magic = "INF1"
|
||||||
|
info.count = count
|
||||||
|
info.unknown01 = 4
|
||||||
|
info.write(file)
|
||||||
|
unknown = 0
|
||||||
|
file.write(struct.pack('>I', unknown))
|
||||||
|
offset_list = []
|
||||||
|
for x in offsets_list:
|
||||||
|
file.write(struct.pack('>I', x))
|
||||||
|
padding = 0
|
||||||
|
for x in xrange(info_pad_to_add):
|
||||||
|
file.write(struct.pack('>B', padding))
|
||||||
|
dat1.magic = "DAT1"
|
||||||
|
dat1.write(file)
|
||||||
|
unknown = 0
|
||||||
|
file.write(struct.pack('>H', unknown))
|
||||||
|
for x in strings_list:
|
||||||
|
file.write(x.encode('utf_16_be'))
|
||||||
|
file.write('\x00\x00')
|
||||||
|
file.write("\n")
|
||||||
|
padding = 0
|
||||||
|
for x in xrange(dat_pad_to_add):
|
||||||
|
file.write(struct.pack('>B', padding))
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file for writing"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
print 'Usage: python bmg.py -r <filename.bmg> <filename.hog>'
|
||||||
|
print ' == OR == '
|
||||||
|
print 'Usage: python bmg.py -w> <filename.hog> <filename.bmg'
|
||||||
|
sys.exit(1)
|
||||||
|
if sys.argv[1] == "-r":
|
||||||
|
f = open(sys.argv[2], 'rb')
|
||||||
|
if f:
|
||||||
|
bmg_buffer = f.read()
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
print 'Could not open file for reading'
|
||||||
|
sys.exit(1)
|
||||||
|
bmg = BMG(bmg_buffer, sys.argv[3], debug=False)
|
||||||
|
elif sys.argv[1] == "-w":
|
||||||
|
f = open(sys.argv[2], 'rb')
|
||||||
|
if f:
|
||||||
|
bmg_buffer = f.read()
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file for reading"
|
||||||
|
sys.exit(1)
|
||||||
|
bmg = BMG()
|
||||||
|
bmg.write(bmg_buffer, sys.argv[3])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
584
WiiPy/experimental/breff.py
Executable file
584
WiiPy/experimental/breff.py
Executable file
@ -0,0 +1,584 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import sys, struct
|
||||||
|
|
||||||
|
from Struct import Struct
|
||||||
|
|
||||||
|
def nullterm(str_plus):
|
||||||
|
z = str_plus.find('\0')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
class BREFF(object):
|
||||||
|
class BREFF_REFF_Section2(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.unknown00 = Struct.uint32
|
||||||
|
self.unknown01 = Struct.uint32
|
||||||
|
self.unknown02 = Struct.uint32
|
||||||
|
self.unk03p1 = Struct.uint16
|
||||||
|
self.unk03p2 = Struct.uint16
|
||||||
|
self.unk04p1 = Struct.int16
|
||||||
|
self.unk04p2 = Struct.uint16
|
||||||
|
self.unknown05 = Struct.uint32
|
||||||
|
self.unknown06 = Struct.float
|
||||||
|
self.unknown07 = Struct.float
|
||||||
|
self.unknown08 = Struct.uint32
|
||||||
|
self.unknown09 = Struct.uint32
|
||||||
|
self.unknown10 = Struct.float
|
||||||
|
self.unknown11 = Struct.float
|
||||||
|
self.unknown12 = Struct.uint32
|
||||||
|
self.unknown13 = Struct.float
|
||||||
|
self.unknown14 = Struct.uint32
|
||||||
|
self.unknown15 = Struct.uint32
|
||||||
|
self.unk16p1 = Struct.uint16
|
||||||
|
self.unk16p2 = Struct.uint16
|
||||||
|
self.unknown17 = Struct.float
|
||||||
|
self.unknown18 = Struct.float
|
||||||
|
self.unknown19 = Struct.uint32
|
||||||
|
self.unknown20 = Struct.float
|
||||||
|
self.unknown21 = Struct.float
|
||||||
|
self.unknown22 = Struct.float
|
||||||
|
self.unknown23 = Struct.float
|
||||||
|
self.unknown24 = Struct.float
|
||||||
|
self.unknown25 = Struct.float
|
||||||
|
self.unknown26 = Struct.uint32
|
||||||
|
self.unknown27 = Struct.uint32
|
||||||
|
self.unknown28 = Struct.uint32
|
||||||
|
self.unknown29 = Struct.uint32
|
||||||
|
self.unknown30 = Struct.uint32
|
||||||
|
self.unknown31 = Struct.float
|
||||||
|
self.unknown32 = Struct.uint32
|
||||||
|
self.unknown33 = Struct.uint32
|
||||||
|
self.unknown34 = Struct.uint32
|
||||||
|
self.unknown35 = Struct.uint32
|
||||||
|
self.unknown36 = Struct.uint32
|
||||||
|
self.unknown37 = Struct.float
|
||||||
|
self.unknown38 = Struct.float
|
||||||
|
self.unknown39 = Struct.float
|
||||||
|
self.unknown40 = Struct.float
|
||||||
|
self.unknown41 = Struct.float
|
||||||
|
self.unknown42 = Struct.uint32
|
||||||
|
self.unknown43 = Struct.uint32
|
||||||
|
self.unknown44 = Struct.float
|
||||||
|
self.unknown45 = Struct.uint32
|
||||||
|
self.unknown46 = Struct.uint32
|
||||||
|
self.unknown47 = Struct.uint32
|
||||||
|
self.unknown48 = Struct.uint32
|
||||||
|
self.unknown49 = Struct.uint32
|
||||||
|
self.unknown50 = Struct.uint32
|
||||||
|
self.unknown51 = Struct.uint32
|
||||||
|
self.unknown52 = Struct.uint32
|
||||||
|
self.unknown53 = Struct.uint32
|
||||||
|
self.unknown54 = Struct.uint32
|
||||||
|
self.unknown55 = Struct.uint32
|
||||||
|
self.unknown56 = Struct.uint32
|
||||||
|
self.unknown57 = Struct.uint32
|
||||||
|
self.unknown58 = Struct.uint32
|
||||||
|
self.unknown59 = Struct.uint32
|
||||||
|
self.unknown60 = Struct.uint32
|
||||||
|
self.unknown61 = Struct.uint32
|
||||||
|
self.unknown62 = Struct.uint32
|
||||||
|
self.unknown63 = Struct.uint32
|
||||||
|
self.unknown64 = Struct.uint32
|
||||||
|
self.unknown65 = Struct.uint32
|
||||||
|
self.unknown66 = Struct.uint32
|
||||||
|
self.unknown67 = Struct.uint32
|
||||||
|
self.unknown68 = Struct.uint32
|
||||||
|
self.unknown69 = Struct.uint32
|
||||||
|
self.unknown70 = Struct.uint32
|
||||||
|
self.unknown71 = Struct.uint32
|
||||||
|
self.unknown72 = Struct.uint32
|
||||||
|
self.unknown73 = Struct.uint32
|
||||||
|
self.unknown74 = Struct.uint32
|
||||||
|
self.unknown75 = Struct.uint32
|
||||||
|
self.unknown76 = Struct.uint32
|
||||||
|
self.unknown77 = Struct.uint32
|
||||||
|
self.unknown78 = Struct.uint32
|
||||||
|
self.unknown79 = Struct.uint32
|
||||||
|
self.unknown80 = Struct.uint32
|
||||||
|
self.unknown81 = Struct.float
|
||||||
|
self.unknown82 = Struct.float
|
||||||
|
self.unknown83 = Struct.float
|
||||||
|
self.unknown84 = Struct.float
|
||||||
|
self.unknown85 = Struct.uint32
|
||||||
|
self.unknown86 = Struct.uint32
|
||||||
|
self.unknown87 = Struct.uint32
|
||||||
|
self.unknown88 = Struct.float
|
||||||
|
self.unknown89 = Struct.float
|
||||||
|
self.unknown90 = Struct.float
|
||||||
|
self.unknown91 = Struct.float
|
||||||
|
self.unknown92 = Struct.float
|
||||||
|
self.unknown93 = Struct.float
|
||||||
|
self.unknown94 = Struct.uint32
|
||||||
|
self.unknown95 = Struct.uint32
|
||||||
|
self.unknown96 = Struct.uint32
|
||||||
|
self.unknown97 = Struct.uint32
|
||||||
|
self.unknown98 = Struct.uint32
|
||||||
|
self.unknown99 = Struct.uint32
|
||||||
|
self.unknownA0 = Struct.uint32
|
||||||
|
self.unknownA1 = Struct.uint32
|
||||||
|
self.unknownA2 = Struct.uint32
|
||||||
|
self.unknownA3 = Struct.uint32
|
||||||
|
self.unknownA4 = Struct.uint32
|
||||||
|
self.unknownA5 = Struct.uint32
|
||||||
|
self.unknownA6 = Struct.uint32
|
||||||
|
self.unknownA7 = Struct.uint32
|
||||||
|
self.unknownA8 = Struct.uint32
|
||||||
|
self.unknownA9 = Struct.uint32
|
||||||
|
self.unknownB0 = Struct.uint32
|
||||||
|
self.unknownB1 = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Unknown00: %08x\n" % self.unknown00
|
||||||
|
return_string += "Unknown01: %08x\talways 00000128 ?\n" % self.unknown01
|
||||||
|
return_string += "Unknown02: %08x\talways 80000xxx ?\n" % self.unknown02
|
||||||
|
return_string += "Unknown03: %04x\t%04x\n" % (self.unk03p1 , self.unk03p2)
|
||||||
|
return_string += "Unknown04: %.2d\t%04x\n" % (self.unk04p1 , self.unk04p2)
|
||||||
|
return_string += "Unknown05: %08x\n" % self.unknown05
|
||||||
|
return_string += "Unknown06: %.9f\n" % self.unknown06
|
||||||
|
return_string += "Unknown07: %f\n" % self.unknown07
|
||||||
|
return_string += "Unknown08: %08x\n" % self.unknown08
|
||||||
|
return_string += "Unknown09: %08x\n" % self.unknown09
|
||||||
|
return_string += "Size Outer Radius X: %.9f\n" % self.unknown10
|
||||||
|
return_string += "Size Outer Radius Y: %.9f\n" % self.unknown11
|
||||||
|
return_string += "Size Outer Radius Z: %.9f\n" % self.unknown12
|
||||||
|
return_string += "Inner Radius: %.9f\n" % self.unknown13
|
||||||
|
return_string += "Unknown14: %08x\n" % self.unknown14
|
||||||
|
return_string += "Unknown15: %08x\n" % self.unknown15
|
||||||
|
return_string += "Unknown16: %04x\t%04x\n" % (self.unk16p1, self.unk16p2)
|
||||||
|
return_string += "All Direction Speed: %.9f\n" % self.unknown17
|
||||||
|
return_string += "Y Axis Difuse Speed: %.9f\n" % self.unknown18
|
||||||
|
return_string += "Random Direction Speed: %.9f\n" % self.unknown19
|
||||||
|
return_string += "Normal Direction Speed: %.9f\n" % self.unknown20
|
||||||
|
return_string += "Unknown21: %.9f\n" % self.unknown21
|
||||||
|
return_string += "Move to Specific Direction: %.9f\n" % self.unknown22
|
||||||
|
return_string += "Unknown23: %08x\n" % self.unknown23
|
||||||
|
return_string += "Unknown24: %.20f\n" % self.unknown24
|
||||||
|
return_string += "Unknown25: %.9f\n" % self.unknown25
|
||||||
|
return_string += "Unknown26: %08x\n" % self.unknown26
|
||||||
|
return_string += "Unknown27: %.9f\n" % self.unknown27
|
||||||
|
return_string += "Unknown28: %.9f\n" % self.unknown28
|
||||||
|
return_string += "Unknown29: %.9f\n" % self.unknown29
|
||||||
|
return_string += "Unknown30: %08x\n" % self.unknown30
|
||||||
|
return_string += "Unknown31: %.9f\n" % self.unknown31
|
||||||
|
return_string += "Unknown32: %08x\n" % self.unknown32
|
||||||
|
return_string += "Four Bytes: %08x\n" % self.unknown33
|
||||||
|
return_string += "Unknown34: %08x\n" % self.unknown34
|
||||||
|
return_string += "Unknown35: %08x\n" % self.unknown35
|
||||||
|
return_string += "Unknown36: %08x\n" % self.unknown36
|
||||||
|
return_string += "Transform Scale X: %.9f\n" % self.unknown37
|
||||||
|
return_string += "Transform Scale Y: %.9f\n" % self.unknown38
|
||||||
|
return_string += "Transform Scale Z: %.9f\n" % self.unknown39
|
||||||
|
return_string += "Center of Particle SRT Horiz: %.9f\n" % self.unknown40
|
||||||
|
return_string += "Center of Particle SRT Vert: %.9f\n" % self.unknown41
|
||||||
|
return_string += "Unknown42: %08x\n" % self.unknown42
|
||||||
|
return_string += "Unknown43: %08x\n" % self.unknown43
|
||||||
|
return_string += "Unknown44: %.9f\n" % self.unknown44
|
||||||
|
return_string += "Unknown45: %08x\n" % self.unknown45
|
||||||
|
return_string += "Unknown46: %08x\n" % self.unknown46
|
||||||
|
return_string += "Unknown47: %08x\n" % self.unknown47
|
||||||
|
return_string += "Unknown48: %08x\n" % self.unknown48
|
||||||
|
return_string += "Unknown49: %08x\n" % self.unknown49
|
||||||
|
return_string += "Unknown50: %08x\n" % self.unknown50
|
||||||
|
return_string += "Unknown51: %08x\n" % self.unknown51
|
||||||
|
return_string += "Unknown52: %08x\n" % self.unknown52
|
||||||
|
return_string += "Unknown53: %08x\n" % self.unknown53
|
||||||
|
return_string += "Unknown54: %08x\n" % self.unknown54
|
||||||
|
return_string += "Unknown55: %08x\n" % self.unknown55
|
||||||
|
return_string += "Unknown56: %08x\n" % self.unknown56
|
||||||
|
return_string += "Unknown57: %08x\n" % self.unknown57
|
||||||
|
return_string += "Unknown58: %08x\n" % self.unknown58
|
||||||
|
return_string += "Unknown59: %08x\n" % self.unknown59
|
||||||
|
return_string += "Unknown60: %08x\n" % self.unknown60
|
||||||
|
return_string += "Unknown61: %08x\n" % self.unknown61
|
||||||
|
return_string += "Unknown62: %08x\n" % self.unknown62
|
||||||
|
return_string += "Unknown63: %08x\n" % self.unknown63
|
||||||
|
return_string += "Unknown64: %08x\n" % self.unknown64
|
||||||
|
return_string += "Unknown65: %08x\n" % self.unknown65
|
||||||
|
return_string += "Unknown66: %08x\n" % self.unknown66
|
||||||
|
return_string += "Unknown67: %08x\n" % self.unknown67
|
||||||
|
return_string += "Unknown68: %08x\n" % self.unknown68
|
||||||
|
return_string += "Unknown69: %08x\n" % self.unknown69
|
||||||
|
return_string += "Unknown70: %08x\n" % self.unknown70
|
||||||
|
return_string += "Unknown71: %08x\n" % self.unknown71
|
||||||
|
return_string += "Unknown72: %08x\n" % self.unknown72
|
||||||
|
return_string += "Unknown73: %08x\n" % self.unknown73
|
||||||
|
return_string += "Unknown74: %08x\n" % self.unknown74
|
||||||
|
return_string += "Unknown75: %08x\n" % self.unknown75
|
||||||
|
return_string += "Unknown76: %08x\n" % self.unknown76
|
||||||
|
return_string += "Unknown77: %08x\n" % self.unknown77
|
||||||
|
return_string += "Unknown78: %08x\n" % self.unknown78
|
||||||
|
return_string += "Unknown79: %08x\n" % self.unknown79
|
||||||
|
return_string += "Unknown80: %08x\n" % self.unknown80
|
||||||
|
return_string += "Unknown81: %.9f\n" % self.unknown81
|
||||||
|
return_string += "Unknown82: %.9f\n" % self.unknown82
|
||||||
|
return_string += "Unknown83: %.9f\n" % self.unknown83
|
||||||
|
return_string += "Unknown84: %.9f\n" % self.unknown84
|
||||||
|
return_string += "Unknown85: %08x\n" % self.unknown85
|
||||||
|
return_string += "Unknown86: %08x\n" % self.unknown86
|
||||||
|
return_string += "Unknown87: %08x\n" % self.unknown87
|
||||||
|
return_string += "Unknown88: %.9f\n" % self.unknown88
|
||||||
|
return_string += "Unknown89: %.9f\n" % self.unknown89
|
||||||
|
return_string += "Unknown90: %.9f\n" % self.unknown90
|
||||||
|
return_string += "Unknown91: %.9f\n" % self.unknown91
|
||||||
|
return_string += "Unknown92: %.9f\n" % self.unknown92
|
||||||
|
return_string += "Unknown93: %.9f\n" % self.unknown93
|
||||||
|
return_string += "Unknown94: %08x\n" % self.unknown94
|
||||||
|
return_string += "Unknown95: %08x\n" % self.unknown95
|
||||||
|
return_string += "Unknown96: %08x\n" % self.unknown96
|
||||||
|
return_string += "Unknown97: %08x\n" % self.unknown97
|
||||||
|
return_string += "Unknown98: %08x\n" % self.unknown98
|
||||||
|
return_string += "Unknown99: %08x\n" % self.unknown99
|
||||||
|
return_string += "UnknownA0: %08x\n" % self.unknownA0
|
||||||
|
return_string += "UnknownA1: %08x\n" % self.unknownA1
|
||||||
|
return_string += "UnknownA2: %08x\n" % self.unknownA2
|
||||||
|
return_string += "UnknownA3: %08x\n" % self.unknownA3
|
||||||
|
return_string += "UnknownA4: %08x\n" % self.unknownA4
|
||||||
|
return_string += "UnknownA5: %08x\n" % self.unknownA5
|
||||||
|
return_string += "UnknownA6: %08x\n" % self.unknownA6
|
||||||
|
return_string += "UnknownA7: %08x\n" % self.unknownA7
|
||||||
|
return_string += "UnknownA8: %08x\n" % self.unknownA8
|
||||||
|
return_string += "UnknownA9: %08x\n" % self.unknownA9
|
||||||
|
return_string += "UnknownB0: %08x\n" % self.unknownB0
|
||||||
|
return_string += "UnknownB1: %08x\n" % self.unknownB1
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFF_REFF_StringSection1(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.offset = Struct.uint32
|
||||||
|
self.length = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Offset: %08x\n" % self.offset
|
||||||
|
return_string += "Length: %08x\n" % self.length
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFF_REFF_StringHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.offset = Struct.uint16
|
||||||
|
self.length = Struct.uint16
|
||||||
|
self.string_cnt = Struct.uint16
|
||||||
|
self.unknown01 = Struct.uint16
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Offset: %04x\n" % self.offset
|
||||||
|
return_string += "Offset: %04x\n" % self.length
|
||||||
|
return_string += "String Count: %04x\n" % self.string_cnt
|
||||||
|
return_string += "Unknown01: %04x" % self.unknown01
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFF_REFF_Project(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.length = Struct.uint32
|
||||||
|
self.unknown01 = Struct.uint32
|
||||||
|
self.unknown02 = Struct.uint32
|
||||||
|
self.str_length = Struct.uint16
|
||||||
|
self.unknown03 = Struct.uint16
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Length: %08x\n" % self.length
|
||||||
|
return_string += "Unknown01: %08x\n" % self.unknown01
|
||||||
|
return_string += "Unknown02: %08x\n" % self.unknown02
|
||||||
|
return_string += "Number of Strings: %04x\n" % self.str_length
|
||||||
|
return_string += "Unknown: %04x" % self.unknown03
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFF_REFF(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.length = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Magic: %s\n" % self.magic
|
||||||
|
return_string += "Length: %08x\n" % self.length
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFF_Header(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.version = Struct.uint32
|
||||||
|
self.length = Struct.uint32
|
||||||
|
self.header_size = Struct.uint16
|
||||||
|
self.chunk_cnt = Struct.uint16
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Magic: %s\n" % self.magic
|
||||||
|
return_string += "Version: %08x\n" % self.version
|
||||||
|
return_string += "Length: %08x\n" % self.length
|
||||||
|
return_string += "Header Size: %04x\n" % self.header_size
|
||||||
|
return_string += "Chunk Count: %04x\n" % self.chunk_cnt
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = []
|
||||||
|
if data != None:
|
||||||
|
self.Unpack(data)
|
||||||
|
|
||||||
|
def Unpack(self, data):
|
||||||
|
pos = 0
|
||||||
|
header = self.BREFF_Header()
|
||||||
|
header.unpack(data[pos:pos+len(header)])
|
||||||
|
pos += len(header)
|
||||||
|
print header
|
||||||
|
assert header.magic == "REFF"
|
||||||
|
assert header.version == 0xfeff0004
|
||||||
|
reff = self.BREFF_REFF()
|
||||||
|
reff.unpack(data[pos:pos+len(reff)])
|
||||||
|
pos += len(reff)
|
||||||
|
print reff
|
||||||
|
assert reff.magic == "REFF"
|
||||||
|
|
||||||
|
reff_project = self.BREFF_REFF_Project()
|
||||||
|
reff_project.unpack(data[pos:pos+len(reff_project)])
|
||||||
|
pos += len(reft_project)
|
||||||
|
print reff_project
|
||||||
|
string = nullterm(data[pos:pos+reff_project.str_length])
|
||||||
|
pos += reff_project.str_length
|
||||||
|
print "String: %s\n" % string
|
||||||
|
|
||||||
|
while pos %2:
|
||||||
|
unknown = Struct.uint8(data[pos:pos+1])
|
||||||
|
pos += 1
|
||||||
|
print "Padding: %02x" % unknown
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
temp = pos
|
||||||
|
|
||||||
|
reff_string_header = self.BREFF_REFF_StringHeader()
|
||||||
|
reff_string_header.unpack(data[pos:pos+len(reff_string_header)])
|
||||||
|
pos += len(reff_string_header)
|
||||||
|
print reff_string_header
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
string_groups = []
|
||||||
|
for x in xrange(reff_string_header.string_cnt):
|
||||||
|
str_length = Struct.uint16(data[pos:pos+2], endian='>')
|
||||||
|
pos += 2
|
||||||
|
print "String Length with null added: %04x" % str_length
|
||||||
|
string = nullterm(data[pos:pos+str_length])
|
||||||
|
pos += str_length
|
||||||
|
print "String: %s" % string
|
||||||
|
string_section1 = self.BREFF_REFF_StringSection1()
|
||||||
|
string_section1.unpack(data[pos:pos+len(string_section1)])
|
||||||
|
pos += len(string_section1)
|
||||||
|
print string_section1
|
||||||
|
string_groups.append(string_section1)
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
while pos % 0x04:
|
||||||
|
padding = Struct.uint8(data[pos:pos+1])
|
||||||
|
pos += 1
|
||||||
|
print "Padding: %02x" % padding
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
assert pos == string_groups[0].offset + temp
|
||||||
|
for x in xrange(reff_string_header.string_cnt):
|
||||||
|
pos = temp + string_groups[x].offset
|
||||||
|
reff_section2 = self.BREFF_REFF_Section2()
|
||||||
|
reff_section2.unpack(data[pos:pos+len(reff_section2)])
|
||||||
|
pos += len(reff_section2)
|
||||||
|
print reff_section2
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
''' LARGE TEST DATA
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown01: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown02: %08x" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown03: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown04: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown05: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown06: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown07: %f" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown08: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown09: %08x" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Size Outer Radius X: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Size Outer Radius Y: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Size Outer Radius Z: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Inner Radius: %f" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown14: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown15: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown16: %08x" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "All Direction Speed: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Y Axis Difuse Speed: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Random Direction Speed: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Normal Direction Speed: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "PI DIVIDED BY 4 BITCHES: %.20f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Move to specific direction: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown23: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "PI BITCHES: %.20f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "PI DIVIDED BY 2 BITCHES: %.20f" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown26: %08x" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown27: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown28: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown29: %f" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown30: %08x" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown31: %f" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown32: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Bytes: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown34: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown35: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown36: %08x" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Transform Scale X: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Transform Scale Y: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Transform Scale Z: %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Center of Particle SRT Horizontal(x): %f" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Center of Particle SRT Verticle(y): %f" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown42: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown43: %08x" % unknown
|
||||||
|
unknown = Struct.float(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown44: %.20f" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown45: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown46: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown47: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown48: %08x" % unknown
|
||||||
|
LARGE TEST DATA '''
|
||||||
|
|
||||||
|
''' BEGIN TEST DATA
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
END TEST DATA '''
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print 'Usage: python breff.py <filename>'
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
f = open(sys.argv[1], 'rb')
|
||||||
|
if f:
|
||||||
|
reff = f.read()
|
||||||
|
f.close()
|
||||||
|
assert reff[0:8] == 'REFF\xfe\xff\x00\x04'
|
||||||
|
breff = BREFF(reff)
|
||||||
|
else:
|
||||||
|
print 'Could not open %s' % sys.argv[1]
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
467
WiiPy/experimental/breft.py
Executable file
467
WiiPy/experimental/breft.py
Executable file
@ -0,0 +1,467 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import sys, struct
|
||||||
|
|
||||||
|
from Struct import Struct
|
||||||
|
|
||||||
|
def nullterm(str_plus):
|
||||||
|
z = str_plus.find('\0')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
class BREFT(object):
|
||||||
|
class BREFT_REFT_Section2(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.unknown00 = Struct.uint32
|
||||||
|
self.unknown01 = Struct.uint32
|
||||||
|
self.unknown02 = Struct.uint32
|
||||||
|
self.unknown03 = Struct.uint32
|
||||||
|
self.unknown04 = Struct.uint32
|
||||||
|
self.unknown05 = Struct.uint32
|
||||||
|
self.unknown06 = Struct.uint32
|
||||||
|
self.unknown07 = Struct.uint32
|
||||||
|
self.unknown08 = Struct.uint32
|
||||||
|
self.unknown09 = Struct.uint32
|
||||||
|
self.unknown10 = Struct.uint32
|
||||||
|
self.unknown11 = Struct.uint32
|
||||||
|
self.unknown12 = Struct.uint32
|
||||||
|
self.unknown13 = Struct.uint32
|
||||||
|
self.unknown14 = Struct.uint32
|
||||||
|
self.unknown15 = Struct.uint32
|
||||||
|
self.unknown16 = Struct.uint32
|
||||||
|
self.unknown17 = Struct.uint32
|
||||||
|
self.unknown18 = Struct.uint32
|
||||||
|
self.unknown19 = Struct.uint32
|
||||||
|
self.unknown20 = Struct.uint32
|
||||||
|
self.unknown21 = Struct.uint32
|
||||||
|
self.unknown22 = Struct.uint32
|
||||||
|
self.unknown23 = Struct.uint32
|
||||||
|
self.unknown24 = Struct.uint32
|
||||||
|
self.unknown25 = Struct.uint32
|
||||||
|
self.unknown26 = Struct.uint32
|
||||||
|
self.unknown27 = Struct.uint32
|
||||||
|
self.unknown28 = Struct.uint32
|
||||||
|
self.unknown29 = Struct.uint32
|
||||||
|
self.unknown30 = Struct.uint32
|
||||||
|
self.unknown31 = Struct.uint32
|
||||||
|
self.unknown32 = Struct.uint32
|
||||||
|
self.unknown33 = Struct.uint32
|
||||||
|
self.unknown34 = Struct.uint32
|
||||||
|
self.unknown35 = Struct.uint32
|
||||||
|
self.unknown36 = Struct.uint32
|
||||||
|
self.unknown37 = Struct.uint32
|
||||||
|
self.unknown38 = Struct.uint32
|
||||||
|
self.unknown39 = Struct.uint32
|
||||||
|
self.unknown40 = Struct.uint32
|
||||||
|
self.unknown41 = Struct.uint32
|
||||||
|
self.unknown42 = Struct.uint32
|
||||||
|
self.unknown43 = Struct.uint32
|
||||||
|
self.unknown44 = Struct.uint32
|
||||||
|
self.unknown45 = Struct.uint32
|
||||||
|
self.unknown46 = Struct.uint32
|
||||||
|
self.unknown47 = Struct.uint32
|
||||||
|
self.unknown48 = Struct.uint32
|
||||||
|
self.unknown49 = Struct.uint32
|
||||||
|
self.unknown50 = Struct.uint32
|
||||||
|
self.unknown51 = Struct.uint32
|
||||||
|
self.unknown52 = Struct.uint32
|
||||||
|
self.unknown53 = Struct.uint32
|
||||||
|
self.unknown54 = Struct.uint32
|
||||||
|
self.unknown55 = Struct.uint32
|
||||||
|
self.unknown56 = Struct.uint32
|
||||||
|
self.unknown57 = Struct.uint32
|
||||||
|
self.unknown58 = Struct.uint32
|
||||||
|
self.unknown59 = Struct.uint32
|
||||||
|
self.unknown60 = Struct.uint32
|
||||||
|
self.unknown61 = Struct.uint32
|
||||||
|
self.unknown62 = Struct.uint32
|
||||||
|
self.unknown63 = Struct.uint32
|
||||||
|
self.unknown64 = Struct.uint32
|
||||||
|
self.unknown65 = Struct.uint32
|
||||||
|
self.unknown66 = Struct.uint32
|
||||||
|
self.unknown67 = Struct.uint32
|
||||||
|
self.unknown68 = Struct.uint32
|
||||||
|
self.unknown69 = Struct.uint32
|
||||||
|
self.unknown70 = Struct.uint32
|
||||||
|
self.unknown71 = Struct.uint32
|
||||||
|
self.unknown72 = Struct.uint32
|
||||||
|
self.unknown73 = Struct.uint32
|
||||||
|
self.unknown74 = Struct.uint32
|
||||||
|
self.unknown75 = Struct.uint32
|
||||||
|
self.unknown76 = Struct.uint32
|
||||||
|
self.unknown77 = Struct.uint32
|
||||||
|
self.unknown78 = Struct.uint32
|
||||||
|
self.unknown79 = Struct.uint32
|
||||||
|
self.unknown80 = Struct.uint32
|
||||||
|
self.unknown81 = Struct.uint32
|
||||||
|
self.unknown82 = Struct.uint32
|
||||||
|
self.unknown83 = Struct.uint32
|
||||||
|
self.unknown84 = Struct.uint32
|
||||||
|
self.unknown85 = Struct.uint32
|
||||||
|
self.unknown86 = Struct.uint32
|
||||||
|
self.unknown87 = Struct.uint32
|
||||||
|
self.unknown88 = Struct.uint32
|
||||||
|
self.unknown89 = Struct.uint32
|
||||||
|
self.unknown90 = Struct.uint32
|
||||||
|
self.unknown91 = Struct.uint32
|
||||||
|
self.unknown92 = Struct.uint32
|
||||||
|
self.unknown93 = Struct.uint32
|
||||||
|
self.unknown94 = Struct.uint32
|
||||||
|
self.unknown95 = Struct.uint32
|
||||||
|
self.unknown96 = Struct.uint32
|
||||||
|
self.unknown97 = Struct.uint32
|
||||||
|
self.unknown98 = Struct.uint32
|
||||||
|
self.unknown99 = Struct.uint32
|
||||||
|
self.unknownA0 = Struct.uint32
|
||||||
|
self.unknownA1 = Struct.uint32
|
||||||
|
self.unknownA2 = Struct.uint32
|
||||||
|
self.unknownA3 = Struct.uint32
|
||||||
|
self.unknownA4 = Struct.uint32
|
||||||
|
self.unknownA5 = Struct.uint32
|
||||||
|
self.unknownA6 = Struct.uint32
|
||||||
|
self.unknownA7 = Struct.uint32
|
||||||
|
self.unknownA8 = Struct.uint32
|
||||||
|
self.unknownA9 = Struct.uint32
|
||||||
|
self.unknownB0 = Struct.uint32
|
||||||
|
self.unknownB1 = Struct.uint32
|
||||||
|
self.unknownB2 = Struct.uint32
|
||||||
|
self.unknownB3 = Struct.uint32
|
||||||
|
self.unknownB4 = Struct.uint32
|
||||||
|
self.unknownB5 = Struct.uint32
|
||||||
|
self.unknownB6 = Struct.uint32
|
||||||
|
self.unknownB7 = Struct.uint32
|
||||||
|
self.unknownB8 = Struct.uint32
|
||||||
|
self.unknownB9 = Struct.uint32
|
||||||
|
self.unknownC0 = Struct.uint32
|
||||||
|
self.unknownC1 = Struct.uint32
|
||||||
|
self.unknownC2 = Struct.uint32
|
||||||
|
self.unknownC3 = Struct.uint32
|
||||||
|
self.unknownC4 = Struct.uint32
|
||||||
|
self.unknownC5 = Struct.uint32
|
||||||
|
self.unknownC6 = Struct.uint32
|
||||||
|
self.unknownC7 = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Unknown00: %08x\n" % self.unknown00
|
||||||
|
return_string += "Unknown01: %08x\n" % self.unknown01
|
||||||
|
return_string += "Unknown02: %08x\n" % self.unknown02
|
||||||
|
return_string += "Unknown03: %08x\n" % self.unknown03
|
||||||
|
return_string += "Unknown04: %08x\n" % self.unknown04
|
||||||
|
return_string += "Unknown05: %08x\n" % self.unknown05
|
||||||
|
return_string += "Unknown06: %08x\n" % self.unknown06
|
||||||
|
return_string += "Unknown07: %08x\n" % self.unknown07
|
||||||
|
return_string += "Unknown08: %08x\n" % self.unknown08
|
||||||
|
return_string += "Unknown09: %08x\n" % self.unknown09
|
||||||
|
return_string += "Unknown10: %08x\n" % self.unknown10
|
||||||
|
return_string += "Unknown11: %08x\n" % self.unknown11
|
||||||
|
return_string += "Unknown12: %08x\n" % self.unknown12
|
||||||
|
return_string += "Unknown13: %08x\n" % self.unknown13
|
||||||
|
return_string += "Unknown14: %08x\n" % self.unknown14
|
||||||
|
return_string += "Unknown15: %08x\n" % self.unknown15
|
||||||
|
return_string += "Unknown16: %08x\n" % self.unknown16
|
||||||
|
return_string += "Unknown17: %08x\n" % self.unknown17
|
||||||
|
return_string += "Unknown18: %08x\n" % self.unknown18
|
||||||
|
return_string += "Unknown19: %08x\n" % self.unknown19
|
||||||
|
return_string += "Unknown20: %08x\n" % self.unknown20
|
||||||
|
return_string += "Unknown21: %08x\n" % self.unknown21
|
||||||
|
return_string += "Unknown22: %08x\n" % self.unknown22
|
||||||
|
return_string += "Unknown23: %08x\n" % self.unknown23
|
||||||
|
return_string += "Unknown24: %08x\n" % self.unknown24
|
||||||
|
return_string += "Unknown25: %08x\n" % self.unknown25
|
||||||
|
return_string += "Unknown26: %08x\n" % self.unknown26
|
||||||
|
return_string += "Unknown27: %08x\n" % self.unknown27
|
||||||
|
return_string += "Unknown28: %08x\n" % self.unknown28
|
||||||
|
return_string += "Unknown29: %08x\n" % self.unknown29
|
||||||
|
return_string += "Unknown30: %08x\n" % self.unknown30
|
||||||
|
return_string += "Unknown31: %08x\n" % self.unknown31
|
||||||
|
return_string += "Unknown32: %08x\n" % self.unknown32
|
||||||
|
return_string += "Unknown33: %08x\n" % self.unknown33
|
||||||
|
return_string += "Unknown34: %08x\n" % self.unknown34
|
||||||
|
return_string += "Unknown35: %08x\n" % self.unknown35
|
||||||
|
return_string += "Unknown36: %08x\n" % self.unknown36
|
||||||
|
return_string += "Unknown37: %08x\n" % self.unknown37
|
||||||
|
return_string += "Unknown38: %08x\n" % self.unknown38
|
||||||
|
return_string += "Unknown39: %08x\n" % self.unknown39
|
||||||
|
return_string += "Unknown40: %08x\n" % self.unknown40
|
||||||
|
return_string += "Unknown41: %08x\n" % self.unknown41
|
||||||
|
return_string += "Unknown42: %08x\n" % self.unknown42
|
||||||
|
return_string += "Unknown43: %08x\n" % self.unknown43
|
||||||
|
return_string += "Unknown44: %08x\n" % self.unknown44
|
||||||
|
return_string += "Unknown45: %08x\n" % self.unknown45
|
||||||
|
return_string += "Unknown46: %08x\n" % self.unknown46
|
||||||
|
return_string += "Unknown47: %08x\n" % self.unknown47
|
||||||
|
return_string += "Unknown48: %08x\n" % self.unknown48
|
||||||
|
return_string += "Unknown49: %08x\n" % self.unknown49
|
||||||
|
return_string += "Unknown50: %08x\n" % self.unknown50
|
||||||
|
return_string += "Unknown51: %08x\n" % self.unknown51
|
||||||
|
return_string += "Unknown52: %08x\n" % self.unknown52
|
||||||
|
return_string += "Unknown53: %08x\n" % self.unknown53
|
||||||
|
return_string += "Unknown54: %08x\n" % self.unknown54
|
||||||
|
return_string += "Unknown55: %08x\n" % self.unknown55
|
||||||
|
return_string += "Unknown56: %08x\n" % self.unknown56
|
||||||
|
return_string += "Unknown57: %08x\n" % self.unknown57
|
||||||
|
return_string += "Unknown58: %08x\n" % self.unknown58
|
||||||
|
return_string += "Unknown59: %08x\n" % self.unknown59
|
||||||
|
return_string += "Unknown60: %08x\n" % self.unknown60
|
||||||
|
return_string += "Unknown61: %08x\n" % self.unknown61
|
||||||
|
return_string += "Unknown62: %08x\n" % self.unknown62
|
||||||
|
return_string += "Unknown63: %08x\n" % self.unknown63
|
||||||
|
return_string += "Unknown64: %08x\n" % self.unknown64
|
||||||
|
return_string += "Unknown65: %08x\n" % self.unknown65
|
||||||
|
return_string += "Unknown66: %08x\n" % self.unknown66
|
||||||
|
return_string += "Unknown67: %08x\n" % self.unknown67
|
||||||
|
return_string += "Unknown68: %08x\n" % self.unknown68
|
||||||
|
return_string += "Unknown69: %08x\n" % self.unknown69
|
||||||
|
return_string += "Unknown70: %08x\n" % self.unknown70
|
||||||
|
return_string += "Unknown71: %08x\n" % self.unknown71
|
||||||
|
return_string += "Unknown72: %08x\n" % self.unknown72
|
||||||
|
return_string += "Unknown73: %08x\n" % self.unknown73
|
||||||
|
return_string += "Unknown74: %08x\n" % self.unknown74
|
||||||
|
return_string += "Unknown75: %08x\n" % self.unknown75
|
||||||
|
return_string += "Unknown76: %08x\n" % self.unknown76
|
||||||
|
return_string += "Unknown77: %08x\n" % self.unknown77
|
||||||
|
return_string += "Unknown78: %08x\n" % self.unknown78
|
||||||
|
return_string += "Unknown79: %08x\n" % self.unknown79
|
||||||
|
return_string += "Unknown80: %08x\n" % self.unknown80
|
||||||
|
return_string += "Unknown81: %08x\n" % self.unknown81
|
||||||
|
return_string += "Unknown82: %08x\n" % self.unknown82
|
||||||
|
return_string += "Unknown83: %08x\n" % self.unknown83
|
||||||
|
return_string += "Unknown84: %08x\n" % self.unknown84
|
||||||
|
return_string += "Unknown85: %08x\n" % self.unknown85
|
||||||
|
return_string += "Unknown86: %08x\n" % self.unknown86
|
||||||
|
return_string += "Unknown87: %08x\n" % self.unknown87
|
||||||
|
return_string += "Unknown88: %08x\n" % self.unknown88
|
||||||
|
return_string += "Unknown89: %08x\n" % self.unknown89
|
||||||
|
return_string += "Unknown90: %08x\n" % self.unknown90
|
||||||
|
return_string += "Unknown91: %08x\n" % self.unknown91
|
||||||
|
return_string += "Unknown92: %08x\n" % self.unknown92
|
||||||
|
return_string += "Unknown93: %08x\n" % self.unknown93
|
||||||
|
return_string += "Unknown94: %08x\n" % self.unknown94
|
||||||
|
return_string += "Unknown95: %08x\n" % self.unknown95
|
||||||
|
return_string += "Unknown96: %08x\n" % self.unknown96
|
||||||
|
return_string += "Unknown97: %08x\n" % self.unknown97
|
||||||
|
return_string += "Unknown98: %08x\n" % self.unknown98
|
||||||
|
return_string += "Unknown99: %08x\n" % self.unknown99
|
||||||
|
return_string += "UnknownA0: %08x\n" % self.unknownA0
|
||||||
|
return_string += "UnknownA1: %08x\n" % self.unknownA1
|
||||||
|
return_string += "UnknownA2: %08x\n" % self.unknownA2
|
||||||
|
return_string += "UnknownA3: %08x\n" % self.unknownA3
|
||||||
|
return_string += "UnknownA4: %08x\n" % self.unknownA4
|
||||||
|
return_string += "UnknownA5: %08x\n" % self.unknownA5
|
||||||
|
return_string += "UnknownA6: %08x\n" % self.unknownA6
|
||||||
|
return_string += "UnknownA7: %08x\n" % self.unknownA7
|
||||||
|
return_string += "UnknownA8: %08x\n" % self.unknownA8
|
||||||
|
return_string += "UnknownA9: %08x\n" % self.unknownA9
|
||||||
|
return_string += "UnknownB0: %08x\n" % self.unknownB0
|
||||||
|
return_string += "UnknownB1: %08x\n" % self.unknownB1
|
||||||
|
return_string += "UnknownB2: %08x\n" % self.unknownB2
|
||||||
|
return_string += "UnknownB3: %08x\n" % self.unknownB3
|
||||||
|
return_string += "UnknownB4: %08x\n" % self.unknownB4
|
||||||
|
return_string += "UnknownB5: %08x\n" % self.unknownB5
|
||||||
|
return_string += "UnknownB6: %08x\n" % self.unknownB6
|
||||||
|
return_string += "UnknownB7: %08x\n" % self.unknownB7
|
||||||
|
return_string += "UnknownB8: %08x\n" % self.unknownB8
|
||||||
|
return_string += "UnknownB9: %08x\n" % self.unknownB9
|
||||||
|
return_string += "UnknownC0: %08x\n" % self.unknownC0
|
||||||
|
return_string += "UnknownC1: %08x\n" % self.unknownC1
|
||||||
|
return_string += "UnknownC2: %08x\n" % self.unknownC2
|
||||||
|
return_string += "UnknownC3: %08x\n" % self.unknownC3
|
||||||
|
return_string += "UnknownC4: %08x\n" % self.unknownC4
|
||||||
|
return_string += "UnknownC5: %08x\n" % self.unknownC5
|
||||||
|
return_string += "UnknownC6: %08x\n" % self.unknownC6
|
||||||
|
return_string += "UnknownC7: %08x\n" % self.unknownC7
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFT_REFT_StringSection1(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.offset = Struct.uint32
|
||||||
|
self.length = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Offset: %08x\n" % self.offset
|
||||||
|
return_string += "Length: %08x\n" % self.length
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFT_REFT_StringHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.offset = Struct.uint16
|
||||||
|
self.length = Struct.uint16
|
||||||
|
self.string_cnt = Struct.uint16
|
||||||
|
self.unknown01 = Struct.uint16
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Offset: %04x\n" % self.offset
|
||||||
|
return_string += "Offset: %04x\n" % self.length
|
||||||
|
return_string += "String Count: %04x\n" % self.string_cnt
|
||||||
|
return_string += "Unknown01: %04x" % self.unknown01
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFT_REFT_Project(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.length = Struct.uint32
|
||||||
|
self.unknown01 = Struct.uint32
|
||||||
|
self.unknown02 = Struct.uint32
|
||||||
|
self.str_length = Struct.uint16
|
||||||
|
self.unknown03 = Struct.uint16
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Length: %08x\n" % self.length
|
||||||
|
return_string += "Unknown01: %08x\n" % self.unknown01
|
||||||
|
return_string += "Unknown02: %08x\n" % self.unknown02
|
||||||
|
return_string += "Number of Strings: %04x\n" % self.str_length
|
||||||
|
return_string += "Unknown: %04x" % self.unknown03
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFT_REFT(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.length = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Magic: %s\n" % self.magic
|
||||||
|
return_string += "Length: %08x\n" % self.length
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
class BREFT_Header(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.version = Struct.uint32
|
||||||
|
self.length = Struct.uint32
|
||||||
|
self.header_size = Struct.uint16
|
||||||
|
self.chunk_cnt = Struct.uint16
|
||||||
|
def __str__(self):
|
||||||
|
return_string = "Magic: %s\n" % self.magic
|
||||||
|
return_string += "Version: %08x\n" % self.version
|
||||||
|
return_string += "Length: %08x\n" % self.length
|
||||||
|
return_string += "Header Size: %04x\n" % self.header_size
|
||||||
|
return_string += "Chunk Count: %04x\n" % self.chunk_cnt
|
||||||
|
return return_string
|
||||||
|
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = []
|
||||||
|
if data != None:
|
||||||
|
self.Unpack(data)
|
||||||
|
|
||||||
|
def Unpack(self, data):
|
||||||
|
pos = 0
|
||||||
|
header = self.BREFT_Header()
|
||||||
|
header.unpack(data[pos:pos+len(header)])
|
||||||
|
pos += len(header)
|
||||||
|
print header
|
||||||
|
assert header.magic == "REFT"
|
||||||
|
assert header.version == 0xfeff0004
|
||||||
|
reft = self.BREFT_REFT()
|
||||||
|
reft.unpack(data[pos:pos+len(reft)])
|
||||||
|
pos += len(reft)
|
||||||
|
print reft
|
||||||
|
assert reft.magic == "REFT"
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
reft_project = self.BREFT_REFT_Project()
|
||||||
|
reft_project.unpack(data[pos:pos+len(reft_project)])
|
||||||
|
pos += len(reft_project)
|
||||||
|
print reft_project
|
||||||
|
string = nullterm(data[pos:pos+reft_project.str_length])
|
||||||
|
pos += reft_project.str_length
|
||||||
|
print "String: %s\n" % string
|
||||||
|
|
||||||
|
while pos %2:
|
||||||
|
unknown = Struct.uint8(data[pos:pos+1])
|
||||||
|
pos += 1
|
||||||
|
print "Padding: %02x" % unknown
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
for x in xrange(0x30):
|
||||||
|
pad = Struct.uint8(data[pos:pos+1])
|
||||||
|
pos += 1
|
||||||
|
#print "Padding: %08x" % pad
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
temp = pos
|
||||||
|
|
||||||
|
reft_string_header = self.BREFT_REFT_StringHeader()
|
||||||
|
reft_string_header.unpack(data[pos:pos+len(reft_string_header)])
|
||||||
|
pos += len(reft_string_header)
|
||||||
|
print reft_string_header
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
string_groups = []
|
||||||
|
for x in xrange(reft_string_header.string_cnt):
|
||||||
|
str_length = Struct.uint16(data[pos:pos+2], endian='>')
|
||||||
|
pos += 2
|
||||||
|
print "String Length with null added: %04x" % str_length
|
||||||
|
string = nullterm(data[pos:pos+str_length])
|
||||||
|
pos += str_length
|
||||||
|
print "String: %s" % string
|
||||||
|
string_section1 = self.BREFT_REFT_StringSection1()
|
||||||
|
string_section1.unpack(data[pos:pos+len(string_section1)])
|
||||||
|
pos += len(string_section1)
|
||||||
|
print string_section1
|
||||||
|
string_groups.append(string_section1)
|
||||||
|
|
||||||
|
for x in xrange(reft_string_header.string_cnt):
|
||||||
|
pos = temp + string_groups[x].offset
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
reft_section2 = self.BREFT_REFT_Section2()
|
||||||
|
reft_section2.unpack(data[pos:pos+len(reft_section2)])
|
||||||
|
pos += len(reft_section2)
|
||||||
|
print reft_section2
|
||||||
|
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
#''' BEGIN TEST DATA
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
unknown = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
print "Unknown: %08x" % unknown
|
||||||
|
#END TEST DATA '''
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print 'Usage: python breft.py <filename>'
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
f = open(sys.argv[1], 'rb')
|
||||||
|
if f:
|
||||||
|
reft = f.read()
|
||||||
|
f.close()
|
||||||
|
assert reft[0:8] == 'REFT\xfe\xff\x00\x04'
|
||||||
|
breft = BREFT(reft)
|
||||||
|
else:
|
||||||
|
print 'Could not open %s' % sys.argv[1]
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
108
WiiPy/experimental/csv.py
Executable file
108
WiiPy/experimental/csv.py
Executable file
@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import sys, re, struct
|
||||||
|
|
||||||
|
from Struct import Struct
|
||||||
|
|
||||||
|
def nullterm(str_plus):
|
||||||
|
z = str_plus.find('\x00\x09')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
def denullterm(str_plus):
|
||||||
|
z = str_plus.find('\x0a\x0a')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
class CSV(object):
|
||||||
|
def __init__(self, data=None, outfile=None, debug=False):
|
||||||
|
self.data = []
|
||||||
|
if data != None:
|
||||||
|
self.Unpack(data, outfile, debug)
|
||||||
|
|
||||||
|
def Unpack(self, data, outfile=None, debug=False):
|
||||||
|
if outfile != None:
|
||||||
|
file = open(outfile, 'wb')
|
||||||
|
|
||||||
|
pos = 0
|
||||||
|
|
||||||
|
version = Struct.uint16(data[pos:pos+2], endian='>')
|
||||||
|
pos += 2
|
||||||
|
if debug == True:
|
||||||
|
print "Version: %04x" % version
|
||||||
|
print
|
||||||
|
|
||||||
|
self.string_list = []
|
||||||
|
while pos < len(data):
|
||||||
|
string = nullterm(data[pos:])
|
||||||
|
string = unicode(string, 'utf_16_be')
|
||||||
|
if debug == True:
|
||||||
|
print "String: %s" % string
|
||||||
|
pos += len(string) * 2 + 2
|
||||||
|
self.string_list.append(string)
|
||||||
|
file.write(string.encode('utf-8'))
|
||||||
|
file.write('\n')
|
||||||
|
if pos < len(data):
|
||||||
|
file.write('\n')
|
||||||
|
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
def write(self, data, output_file):
|
||||||
|
file = open(output_file, 'wb')
|
||||||
|
if file:
|
||||||
|
file.write('\xfe\xff')
|
||||||
|
|
||||||
|
pos = 0
|
||||||
|
while pos < len(data):
|
||||||
|
temp = denullterm(data[pos:])
|
||||||
|
pos += len(temp) + 2
|
||||||
|
string = unicode(temp, 'utf-8')
|
||||||
|
file.write(string.encode('utf_16_be'))
|
||||||
|
|
||||||
|
if pos < len(data):
|
||||||
|
file.write('\x00\x09')
|
||||||
|
else:
|
||||||
|
file.write('\x00\x0a')
|
||||||
|
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file for writing"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
print 'Usage: python -r csv.py <filename.csv> <filename.hog>'
|
||||||
|
print ' == OR == '
|
||||||
|
print 'Usage: python -w csv.py <filename.hog> <filename.csv>'
|
||||||
|
sys.exit(1)
|
||||||
|
if sys.argv[1] == "-r":
|
||||||
|
f = open(sys.argv[2], 'rb')
|
||||||
|
if f:
|
||||||
|
csv_buffer = f.read()
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
print 'Could not open file for reading'
|
||||||
|
sys.exit(1)
|
||||||
|
csv = CSV(csv_buffer, outfile=sys.argv[3], debug=False)
|
||||||
|
elif sys.argv[1] == "-w":
|
||||||
|
f = open(sys.argv[2], 'rb')
|
||||||
|
if f:
|
||||||
|
input_file = f.read()
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
print 'Could not open file for reading'
|
||||||
|
sys.exit(1)
|
||||||
|
csv = CSV()
|
||||||
|
csv.write(input_file, sys.argv[3])
|
||||||
|
else:
|
||||||
|
print 'Usage: python -r csv.py <filename.csv> <filename.hog>'
|
||||||
|
print ' == OR == '
|
||||||
|
print 'Usage: python -w csv.py <filename.hog> <filename.csv>'
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
182
WiiPy/experimental/thp.py
Normal file
182
WiiPy/experimental/thp.py
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
from Struct import *
|
||||||
|
from pyglet import clock, window, image
|
||||||
|
from pyglet.gl import *
|
||||||
|
import cStringIO
|
||||||
|
import math
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
|
||||||
|
class THP():
|
||||||
|
class THPHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.version = Struct.uint32
|
||||||
|
self.bufSize = Struct.uint32
|
||||||
|
self.audioMaxSamples = Struct.uint32
|
||||||
|
self.frameRate = Struct.float
|
||||||
|
self.numFrames = Struct.uint32
|
||||||
|
self.firstFrameSize = Struct.uint32
|
||||||
|
self.movieDataSize = Struct.uint32
|
||||||
|
self.compInfoDataOffsets = Struct.uint32
|
||||||
|
self.offsetDataOffsets = Struct.uint32 #Offset to a offset table, containing offsets to each frame, this allows for starting playback from any frame. If this is 0 then it does not exist.
|
||||||
|
self.movieDataOffsets = Struct.uint32
|
||||||
|
self.finalFrameDataOffsets = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
ret = "\n"
|
||||||
|
ret += "Magic: %s\n" % self.magic
|
||||||
|
ret += "Version: %d.%d.%d\n" % (((self.version & 0xFFFF0000) >> 16), ((self.version & 0xFF00) >> 8), ((self.version & 0xFF)))
|
||||||
|
ret += "bufSize: %s\n" % self.bufSize
|
||||||
|
ret += "audioMaxSamples: %d\n" % self.audioMaxSamples
|
||||||
|
ret += "frameRate: %f\n" % self.frameRate
|
||||||
|
ret += "numFrames: %d\n" % self.numFrames
|
||||||
|
ret += "firstFrameSize: %d\n" % self.firstFrameSize
|
||||||
|
ret += "movieDataSize: %d\n" % self.movieDataSize
|
||||||
|
ret += "compInfoDataOffsets: 0x%08X\n" % self.compInfoDataOffsets
|
||||||
|
ret += "offsetDataOffsets: 0x%08X\n" % self.offsetDataOffsets
|
||||||
|
ret += "movieDataOffsets: 0x%08X\n" % self.movieDataOffsets
|
||||||
|
ret += "finalFrameDataOffsets: 0x%08X\n" % self.finalFrameDataOffsets
|
||||||
|
return ret
|
||||||
|
class THPFrameCompInfo(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.numComponents = Struct.uint32
|
||||||
|
self.frameComp = Struct.uint8[16]
|
||||||
|
def __str__(self):
|
||||||
|
ret = ""
|
||||||
|
ret += "Number of Components: %d\n" % self.numComponents
|
||||||
|
return ret
|
||||||
|
class THPCompVideoInfo(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.width = Struct.uint32
|
||||||
|
self.height = Struct.uint32
|
||||||
|
self.videoType = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
tempType = ("Non-Interlaced", "Interlaced", "Odd Interlace", "3", "Even Interlace")
|
||||||
|
ret = ""
|
||||||
|
ret += "Width: %d\n" % self.width
|
||||||
|
ret += "Height: %d\n" % self.height
|
||||||
|
ret += "VideoType: %s\n" % tempType[self.videoType]
|
||||||
|
return ret
|
||||||
|
class THPCompAudioInfo(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.sndChannels = Struct.uint32
|
||||||
|
self.sndFrequency = Struct.uint32
|
||||||
|
self.sndNumberSamples = Struct.uint32
|
||||||
|
self.sndNumberTracks = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
ret = ""
|
||||||
|
ret += "Channels: %d\n" % self.sndChannels
|
||||||
|
ret += "Frequency: %d\n" % self.sndFrequency
|
||||||
|
ret += "Samples: %d\n" % self.sndNumberSamples
|
||||||
|
ret += "Tracks: %d\n" % self.sndNumberTracks
|
||||||
|
return ret
|
||||||
|
class THPFrameHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.frameSizeNext = Struct.uint32
|
||||||
|
self.frameSizePrev = Struct.uint32
|
||||||
|
self.vidFileSize = Struct.uint32
|
||||||
|
self.sndFileSize = Struct.uint32
|
||||||
|
def __str__(self):
|
||||||
|
ret = ""
|
||||||
|
ret += "next Frame Size: %d\n" % self.frameSizeNext
|
||||||
|
ret += "previous Frame Size: %d\n" % self.frameSizePrev
|
||||||
|
ret += "Video frame data size: %d\n" % self.vidFileSize
|
||||||
|
ret += "Track file size: %d\n" % self.sndFileSize
|
||||||
|
return ret
|
||||||
|
def readData(self, fp, i=0):
|
||||||
|
self.frameImage = fp.read(self.vidFileSize)
|
||||||
|
#fileName = "frame%06d.jpg" % i
|
||||||
|
#open("out/" + fileName, 'w+b').write(self.frameImage)
|
||||||
|
#print "Frame: %d" % i
|
||||||
|
startTime = time()
|
||||||
|
start = self.frameImage.find('\xff\xda')
|
||||||
|
end = self.frameImage.rfind('\xff\xd9')
|
||||||
|
#print "find(%d): This took "%i, time()-startTime,start,end
|
||||||
|
startTime = time()
|
||||||
|
startStr = self.frameImage[:start+2]
|
||||||
|
endStr = self.frameImage[end:]
|
||||||
|
#print "extr(%d): This took "%i, time()-startTime
|
||||||
|
self.frameImage = self.frameImage[start+2:end]
|
||||||
|
self.frameImage = startStr + self.frameImage.replace('\xff','\xff\x00') + endStr
|
||||||
|
#print self.frameImage
|
||||||
|
|
||||||
|
|
||||||
|
return cStringIO.StringIO(self.frameImage)
|
||||||
|
def __init__(self, movieFile=None):
|
||||||
|
if(movieFile==None):
|
||||||
|
print "Usage: python thp.py filename.thp"
|
||||||
|
exit(-1)
|
||||||
|
fp = file(movieFile, 'rb')
|
||||||
|
HEADER = self.THPHeader()
|
||||||
|
HEADER.unpack(fp.read(len(HEADER)))
|
||||||
|
print HEADER
|
||||||
|
fp.seek(HEADER.compInfoDataOffsets)
|
||||||
|
CompInfo = self.THPFrameCompInfo()
|
||||||
|
CompInfo.unpack(fp.read(len(CompInfo)))
|
||||||
|
print CompInfo
|
||||||
|
for i in range(0, CompInfo.numComponents):
|
||||||
|
if(CompInfo.frameComp[i] == 0):
|
||||||
|
VideoInfo = self.THPCompVideoInfo()
|
||||||
|
VideoInfo.unpack(fp.read(len(VideoInfo)))
|
||||||
|
print VideoInfo
|
||||||
|
if(CompInfo.frameComp[i] == 1):
|
||||||
|
AudioInfo = self.THPCompAudioInfo()
|
||||||
|
AudioInfo.unpack(fp.read(len(AudioInfo)))
|
||||||
|
print AudioInfo
|
||||||
|
|
||||||
|
clock.set_fps_limit(HEADER.frameRate)
|
||||||
|
currOff = HEADER.movieDataOffsets
|
||||||
|
currSize = HEADER.firstFrameSize
|
||||||
|
fp.seek(currOff)
|
||||||
|
|
||||||
|
win = window.Window(VideoInfo.width, VideoInfo.height)
|
||||||
|
fps_display = clock.ClockDisplay()
|
||||||
|
i = 1
|
||||||
|
j = 1
|
||||||
|
image_index = 0
|
||||||
|
image_period = 1.0 / HEADER.frameRate # Reciprocal of the frame rate
|
||||||
|
remained = 0
|
||||||
|
|
||||||
|
while not win.has_exit:
|
||||||
|
|
||||||
|
win.dispatch_events()
|
||||||
|
win.clear()
|
||||||
|
|
||||||
|
dt = clock.tick()
|
||||||
|
|
||||||
|
skip = math.floor((dt+remained)/image_period)
|
||||||
|
j += skip
|
||||||
|
print skip, ":break:", i, j, skip
|
||||||
|
remained = dt - skip * image_period
|
||||||
|
|
||||||
|
tempFrame = self.THPFrameHeader()
|
||||||
|
tempFrame.unpack(fp.read(len(tempFrame)))
|
||||||
|
|
||||||
|
for xx in range(1,skip):
|
||||||
|
currOff = currOff+currSize
|
||||||
|
currSize = tempFrame.frameSizeNext
|
||||||
|
fp.seek(currOff)
|
||||||
|
tempFrame = self.THPFrameHeader()
|
||||||
|
tempFrame.unpack(fp.read(len(tempFrame)))
|
||||||
|
|
||||||
|
imagedat = tempFrame.readData(fp, i)
|
||||||
|
|
||||||
|
pic = image.load("image.jpg",imagedat)
|
||||||
|
pic.blit(0,0)
|
||||||
|
|
||||||
|
currOff = currOff+currSize
|
||||||
|
currSize = tempFrame.frameSizeNext
|
||||||
|
fp.seek(currOff)
|
||||||
|
|
||||||
|
|
||||||
|
fps_display.draw()
|
||||||
|
win.flip()
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
THP(*sys.argv[1:])
|
123
WiiPy/experimental/znd.py
Executable file
123
WiiPy/experimental/znd.py
Executable file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import sys, re, struct
|
||||||
|
|
||||||
|
from Struct import Struct
|
||||||
|
|
||||||
|
def nullterm(str_plus):
|
||||||
|
z = str_plus.find('\x00\x00')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
def denullterm(str_plus):
|
||||||
|
z = str_plus.find('\x0a')
|
||||||
|
if z != -1:
|
||||||
|
return str_plus[:z]
|
||||||
|
else:
|
||||||
|
return str_plus
|
||||||
|
|
||||||
|
class ZND(object):
|
||||||
|
def __init__(self, data=None, out_file=None, debug=False):
|
||||||
|
self.data = []
|
||||||
|
if data != None:
|
||||||
|
self.Unpack(data, out_file, debug)
|
||||||
|
|
||||||
|
def Unpack(self, data, out_file, debug=False):
|
||||||
|
file = open(out_file, 'wb')
|
||||||
|
if file:
|
||||||
|
pos = 0
|
||||||
|
|
||||||
|
count = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
if debug == True:
|
||||||
|
print "Count: %08x" % count
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
offset_list = []
|
||||||
|
for x in xrange(count):
|
||||||
|
offset = Struct.uint32(data[pos:pos+4], endian='>')
|
||||||
|
pos += 4
|
||||||
|
if debug == True:
|
||||||
|
print "Offset: %08x" % offset
|
||||||
|
offset_list.append(offset)
|
||||||
|
|
||||||
|
if debug == True:
|
||||||
|
print "\n%08x\n" % pos
|
||||||
|
|
||||||
|
for x in xrange(count):
|
||||||
|
pos = offset_list[x]
|
||||||
|
string = nullterm(data[pos:])
|
||||||
|
string = unicode(string, 'utf_16_be')
|
||||||
|
if debug == True:
|
||||||
|
print "String: %s" % string.encode('utf-8')
|
||||||
|
pos += len(string)
|
||||||
|
file.write(string.encode('utf-8'))
|
||||||
|
file.write('\n')
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file for writing"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def write(self, data, out_file):
|
||||||
|
file = open(out_file, 'wb')
|
||||||
|
if file:
|
||||||
|
pos = 0
|
||||||
|
count = 0
|
||||||
|
string_list = []
|
||||||
|
while pos < len(data):
|
||||||
|
temp = denullterm(data[pos:])
|
||||||
|
pos += len(temp) + 1
|
||||||
|
string = unicode(temp, 'utf-8')
|
||||||
|
string_list.append(string)
|
||||||
|
count += 1
|
||||||
|
file.write(struct.pack('>I', count))
|
||||||
|
pos = count * 4 + 4
|
||||||
|
for x in xrange(count):
|
||||||
|
file.write(struct.pack('>I', pos))
|
||||||
|
pos += len(string_list[x]) * 2 + 2
|
||||||
|
for x in xrange(count):
|
||||||
|
file.write(string_list[x].encode('utf_16_be'))
|
||||||
|
file.write('\x00\x00')
|
||||||
|
while pos % 0x20:
|
||||||
|
pos += 2
|
||||||
|
file.write('\x00\x00')
|
||||||
|
file.close()
|
||||||
|
else:
|
||||||
|
print "Could not open file for writing"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
print 'Usage: python znd.py -r <filename.znd> <filename.hog>'
|
||||||
|
print ' == OR == '
|
||||||
|
print 'Usage: python znd.py -w <filename.hog> <filename.znd>'
|
||||||
|
sys.exit(1)
|
||||||
|
if sys.argv[1] == "-r":
|
||||||
|
f = open(sys.argv[2], 'rb')
|
||||||
|
if f:
|
||||||
|
znd_buffer = f.read()
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
print 'Could not open file for reading'
|
||||||
|
sys.exit(1)
|
||||||
|
znd = ZND(znd_buffer, sys.argv[3], debug=False)
|
||||||
|
elif sys.argv[1] == "-w":
|
||||||
|
f = open(sys.argv[2], 'rb')
|
||||||
|
if f:
|
||||||
|
buffer = f.read()
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
print 'Could not open file for reading'
|
||||||
|
sys.exit(1)
|
||||||
|
znd = ZND()
|
||||||
|
znd.write(buffer, sys.argv[3])
|
||||||
|
else:
|
||||||
|
print 'Usage: python znd.py -r <filename.znd> <filename.hog>'
|
||||||
|
print ' == OR == '
|
||||||
|
print 'Usage: python znd.py -w <filename.hog> <filename.znd>'
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
253
WiiPy/export.py
Normal file
253
WiiPy/export.py
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
from common import *
|
||||||
|
from title import *
|
||||||
|
from image import *
|
||||||
|
|
||||||
|
class Savegame():
|
||||||
|
class savegameHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.savegameId = Struct.uint32[2]
|
||||||
|
self.bannerSize = Struct.uint32
|
||||||
|
self.permissions = Struct.uint8
|
||||||
|
self.unknown1 = Struct.uint8
|
||||||
|
self.md5hash = Struct.string(16)
|
||||||
|
self.unknown2 = Struct.uint16
|
||||||
|
|
||||||
|
class savegameBanner(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.reserved = Struct.uint8[4]
|
||||||
|
self.flags = Struct.uint32
|
||||||
|
self.reserved = Struct.uint32[5]
|
||||||
|
self.gameTitle = Struct.string(64)
|
||||||
|
self.gameSubTitle = Struct.string(64)
|
||||||
|
self.banner = Struct.string(24576)
|
||||||
|
self.icon0 = Struct.string(4608)
|
||||||
|
self.icon1 = Struct.string(4608)
|
||||||
|
self.icon2 = Struct.string(4608)
|
||||||
|
self.icon3 = Struct.string(4608)
|
||||||
|
self.icon4 = Struct.string(4608)
|
||||||
|
self.icon5 = Struct.string(4608)
|
||||||
|
self.icon6 = Struct.string(4608)
|
||||||
|
self.icon7 = Struct.string(4608)
|
||||||
|
|
||||||
|
class backupHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.hdrSize = Struct.uint32
|
||||||
|
self.magic = Struct.string(2)
|
||||||
|
self.version = Struct.uint16
|
||||||
|
self.NGid = Struct.uint32
|
||||||
|
self.filesCount = Struct.uint32
|
||||||
|
self.filesSize = Struct.uint32
|
||||||
|
self.unknown1 = Struct.uint32
|
||||||
|
self.unknown2 = Struct.uint32
|
||||||
|
self.totalSize = Struct.uint32
|
||||||
|
self.unknown3 = Struct.uint8[64]
|
||||||
|
self.unknown4 = Struct.uint32
|
||||||
|
self.gameId = Struct.string(4)
|
||||||
|
self.wiiMacAddr = Struct.uint8[6]
|
||||||
|
self.unknown6 = Struct.uint16
|
||||||
|
self.padding = Struct.uint32[4]
|
||||||
|
|
||||||
|
class fileHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.uint32
|
||||||
|
self.size = Struct.uint32
|
||||||
|
self.permissions = Struct.uint8
|
||||||
|
self.attribute = Struct.uint8
|
||||||
|
self.type = Struct.uint8
|
||||||
|
self.nameIV = Struct.string(0x45)
|
||||||
|
|
||||||
|
def __init__(self, f):
|
||||||
|
self.f = f
|
||||||
|
try:
|
||||||
|
self.fd = open(f, 'r+b')
|
||||||
|
except:
|
||||||
|
raise Exception('Cannot open input')
|
||||||
|
|
||||||
|
self.sdKey = '\xab\x01\xb9\xd8\xe1\x62\x2b\x08\xaf\xba\xd8\x4d\xbf\xc2\xa5\x5d'
|
||||||
|
self.sdIv = '\x21\x67\x12\xe6\xaa\x1f\x68\x9f\x95\xc5\xa2\x23\x24\xdc\x6a\x98'
|
||||||
|
|
||||||
|
self.iconCount = 1
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
ret = ''
|
||||||
|
ret += '\nSavegame header \n'
|
||||||
|
|
||||||
|
ret += 'Savegame ID : 0x%x%x\n' % (self.hdr.savegameId[0], self.hdr.savegameId[1])
|
||||||
|
ret += 'Banner size : 0x%x\n' % self.hdr.bannerSize
|
||||||
|
ret += 'Permissions : 0x%x\n' % self.hdr.permissions
|
||||||
|
ret += 'Unknown : 0x%x\n' % self.hdr.unknown1
|
||||||
|
ret += 'MD5 hash : %s\n' % hexdump(self.hdr.md5hash)
|
||||||
|
ret += 'Unknown : 0x%x\n' % self.hdr.unknown2
|
||||||
|
|
||||||
|
ret += '\nBanner header \n'
|
||||||
|
|
||||||
|
ret += 'Flags : 0x%x\n' % self.bnr.flags
|
||||||
|
ret += 'Game title : %s\n' % self.bnr.gameTitle
|
||||||
|
ret += 'Game subtitle : %s\n' % self.bnr.gameSubTitle
|
||||||
|
ret += 'Icons found : %i\n' % self.iconCount
|
||||||
|
|
||||||
|
ret += '\nBackup header \n'
|
||||||
|
|
||||||
|
ret += 'Header size : 0x%x (+ 0x10 of padding) version 0x%x\n' % (self.bkHdr.hdrSize, self.bkHdr.version)
|
||||||
|
if self.bkHdr.gameId[3] == 'P':
|
||||||
|
ret += 'Region : PAL\n'
|
||||||
|
elif self.bkHdr.gameId[3] == 'E':
|
||||||
|
ret += 'Region : NTSC\n'
|
||||||
|
elif self.bkHdr.gameId[3] == 'J':
|
||||||
|
ret += 'Region : JAP\n'
|
||||||
|
ret += 'Game ID : %s\n' % self.bkHdr.gameId
|
||||||
|
ret += 'Wii unique ID : 0x%x\n' % self.bkHdr.NGid
|
||||||
|
ret += 'Wii MAC address %02x:%02x:%02x:%02x:%02x:%02x\n' % (self.bkHdr.wiiMacAddr[0], self.bkHdr.wiiMacAddr[1], self.bkHdr.wiiMacAddr[2], self.bkHdr.wiiMacAddr[3], self.bkHdr.wiiMacAddr[4], self.bkHdr.wiiMacAddr[5])
|
||||||
|
ret += 'Found %i files for %i bytes\n' % (self.bkHdr.filesCount, self.bkHdr.filesSize)
|
||||||
|
ret += 'Total size : %i bytes\n' % self.bkHdr.totalSize
|
||||||
|
ret += 'This save is %i blocks wise' % (self.bkHdr.totalSize / 0x20000)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def extractFiles(self):
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.mkdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.chdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
|
|
||||||
|
self.fd.seek(self.fileStartOffset)
|
||||||
|
|
||||||
|
for i in range(self.bkHdr.filesCount):
|
||||||
|
|
||||||
|
fileHdr = self.fd.read(0x80)
|
||||||
|
fileHdr = self.fileHeader().unpack(fileHdr)
|
||||||
|
|
||||||
|
if fileHdr.magic != 0x03adf17e:
|
||||||
|
raise Exception('Wrong file magic')
|
||||||
|
|
||||||
|
fileHdr.size = align(fileHdr.size, 64)
|
||||||
|
|
||||||
|
ivpos = 0
|
||||||
|
name = ""
|
||||||
|
i = 0
|
||||||
|
for char in list(fileHdr.nameIV):
|
||||||
|
if(char == "\x00"):
|
||||||
|
i -= 1
|
||||||
|
ivpos = i
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
name += char
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
|
||||||
|
fileIV = fileHdr.nameIV[ivpos:ivpos + 16]
|
||||||
|
|
||||||
|
if len(fileIV) != 16:
|
||||||
|
raise Exception('IV alignment issue')
|
||||||
|
|
||||||
|
if fileHdr.type == 1:
|
||||||
|
print 'Extracted %s (%ib)' % (name, fileHdr.size)
|
||||||
|
|
||||||
|
fileBuffer = self.fd.read(fileHdr.size)
|
||||||
|
fileBuffer = Crypto().decryptData(self.sdKey, fileIV, fileBuffer, True)
|
||||||
|
try:
|
||||||
|
open(name, 'w+b').write(fileBuffer)
|
||||||
|
except:
|
||||||
|
raise Exception('Cannot write the output')
|
||||||
|
elif fileHdr.type == 2:
|
||||||
|
print 'Extracted folder %s' % name
|
||||||
|
try:
|
||||||
|
os.mkdir(name)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print 'Attribute %i Permission %i' % (fileHdr.attribute, fileHdr.permissions)
|
||||||
|
print 'File IV : 0x%s' % hexdump(fileIV, '')
|
||||||
|
|
||||||
|
os.chdir('..')
|
||||||
|
|
||||||
|
def analyzeHeader(self):
|
||||||
|
headerBuffer = self.fd.read(0xF0C0)
|
||||||
|
headerBuffer = Crypto().decryptData(self.sdKey, self.sdIv, headerBuffer, True)
|
||||||
|
|
||||||
|
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')
|
||||||
|
#print 'Reashed md5 : %s' % hexdump(Crypto().createMD5Hash(headerBuffer))
|
||||||
|
|
||||||
|
self.bnr = self.savegameBanner().unpack(headerBuffer[0x20:])
|
||||||
|
|
||||||
|
if self.bnr.magic != 'WIBN':
|
||||||
|
raise Exception ('Wrong magic, should be WIBN')
|
||||||
|
|
||||||
|
if self.hdr.bannerSize != 0x72A0:
|
||||||
|
self.iconCount += 7
|
||||||
|
|
||||||
|
bkHdrBuffer = self.fd.read(0x80)
|
||||||
|
self.bkHdr = self.backupHeader().unpack(bkHdrBuffer)
|
||||||
|
|
||||||
|
if self.bkHdr.magic != 'Bk' or self.bkHdr.hdrSize != 0x70:
|
||||||
|
raise Exception ('Bk header error')
|
||||||
|
|
||||||
|
self.fileStartOffset = self.fd.tell()
|
||||||
|
|
||||||
|
def eraseWiiMac(self):
|
||||||
|
self.fd.seek(0xF128)
|
||||||
|
print self.fd.write('\x00' * 6)
|
||||||
|
|
||||||
|
def getBanner(self):
|
||||||
|
try:
|
||||||
|
os.mkdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.chdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
|
|
||||||
|
return Image.fromstring("RGBA", (192, 64), TPL('').RGB5A3((192, 64), self.bnr.banner)).save('banner', 'png')
|
||||||
|
|
||||||
|
def getIcon(self, index):
|
||||||
|
if index < 0 or index > 7 or index > self.iconCount:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.mkdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.chdir(os.path.dirname(self.f) + '/' + self.bkHdr.gameId)
|
||||||
|
|
||||||
|
if index == 0:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon0)).save('icon' + str(index), 'png')
|
||||||
|
if index == 1:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon1)).save('icon' + str(index), 'png')
|
||||||
|
if index == 2:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon2)).save('icon' + str(index), 'png')
|
||||||
|
if index == 3:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon3)).save('icon' + str(index), 'png')
|
||||||
|
if index == 4:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon4)).save('icon' + str(index), 'png')
|
||||||
|
if index == 5:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon5)).save('icon' + str(index), 'png')
|
||||||
|
if index == 6:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon6)).save('icon' + str(index), 'png')
|
||||||
|
if index == 7:
|
||||||
|
return Image.fromstring("RGBA", (48, 48), TPL('').RGB5A3((48, 48), self.bnr.icon7)).save('icon' + str(index), 'png')
|
||||||
|
|
||||||
|
def getIconsCount(self):
|
||||||
|
return self.iconCount
|
||||||
|
|
||||||
|
def getSaveString(self, string):
|
||||||
|
if string == 'id':
|
||||||
|
return self.bkHdr.gameId
|
||||||
|
elif string == 'title':
|
||||||
|
return self.bnr.gameTitle
|
||||||
|
elif string == 'subtitle':
|
||||||
|
return self.bnr.gameSubTitle
|
||||||
|
elif string == 'mac':
|
||||||
|
return self.bkHdr.wiiMacAddr[0] + ':' + self.bkHdr.wiiMacAddr[1] + ':' + self.bkHdr.wiiMacAddr[2] + ':' + self.bkHdr.wiiMacAddr[3] + ':' + self.bkHdr.wiiMacAddr[4] + ':' + self.bkHdr.wiiMacAddr[5]
|
||||||
|
|
||||||
|
def getFilesCount(self):
|
||||||
|
return self.bkHdr.filesCount
|
887
WiiPy/formats.py
Normal file
887
WiiPy/formats.py
Normal file
@ -0,0 +1,887 @@
|
|||||||
|
from binascii import *
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from common import *
|
||||||
|
from title import *
|
||||||
|
|
||||||
|
class locDat:
|
||||||
|
class locHeader(Struct):
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.md5 = Struct.string(16)
|
||||||
|
|
||||||
|
def __init__(self, f):
|
||||||
|
self.sdKey = '\xab\x01\xb9\xd8\xe1\x62\x2b\x08\xaf\xba\xd8\x4d\xbf\xc2\xa5\x5d'
|
||||||
|
self.sdIv = '\x21\x67\x12\xe6\xaa\x1f\x68\x9f\x95\xc5\xa2\x23\x24\xdc\x6a\x98'
|
||||||
|
|
||||||
|
self.titles = []
|
||||||
|
self.usedBlocks = 0
|
||||||
|
self.freeBlocks = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.fp = open(f, 'r+')
|
||||||
|
except:
|
||||||
|
raise Exception('File not found')
|
||||||
|
|
||||||
|
plainBuffer = Crypto().decryptData(self.sdKey, self.sdIv, self.fp.read(), False)
|
||||||
|
|
||||||
|
self.hdr = self.locHeader().unpack(plainBuffer[:0x14])
|
||||||
|
|
||||||
|
for x in range(240):
|
||||||
|
self.titles.append(plainBuffer[0x14 + x * 4:0x14 + (x + 1) * 4])
|
||||||
|
if self.titles[x] == '\x00\x00\x00\x00':
|
||||||
|
self.freeBlocks += 1
|
||||||
|
|
||||||
|
self.usedBlocks = 240 - self.freeBlocks
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
out = ''
|
||||||
|
out += 'Used %i blocks out of 240\n\n' % self.usedBlocks
|
||||||
|
for x in range(240):
|
||||||
|
if self.titles[x] == '\x00\x00\x00\x00':
|
||||||
|
out += 'Block %i on page %i is empty\n' % (x, x / 12)
|
||||||
|
else:
|
||||||
|
out += 'Block %i on page %i hold title %s\n' % (x, x / 12, self.titles[x])
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def getFreeBlocks(self):
|
||||||
|
return self.freeBlocks
|
||||||
|
|
||||||
|
def getUsedBlocks(self):
|
||||||
|
return self.usedBlocks
|
||||||
|
|
||||||
|
def isBlockFree(self, x, y, page):
|
||||||
|
if self.titles[((x + (y * 4) + (page * 12)))] == '\x00\x00\x00\x00':
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def isTitleInList(self, title):
|
||||||
|
try:
|
||||||
|
return self.titles.index(title.upper())
|
||||||
|
except:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def getPageTitles(self, page):
|
||||||
|
if page > 19:
|
||||||
|
raise Exception('Out of bounds')
|
||||||
|
|
||||||
|
return self.titles[12 * page:12 * (page + 1)]
|
||||||
|
|
||||||
|
def getTitle(self, x, y, page):
|
||||||
|
if x > 3 or y > 2 or page > 19:
|
||||||
|
raise Exception('Out of bounds')
|
||||||
|
|
||||||
|
return self.titles[((x + (y * 4) + (page * 12)))]
|
||||||
|
|
||||||
|
def setTitle(self, x, y, page, element):
|
||||||
|
if x > 3 or y > 2 or page > 19 or len(element) > 4:
|
||||||
|
raise Exception('Out of bounds')
|
||||||
|
|
||||||
|
self.titles[((x + (y * 4) + (page * 12)))] = element.upper()
|
||||||
|
|
||||||
|
titles = ''
|
||||||
|
|
||||||
|
titles += self.hdr.magic
|
||||||
|
titles += self.hdr.md5
|
||||||
|
|
||||||
|
for x in range(240):
|
||||||
|
titles += self.titles[x]
|
||||||
|
|
||||||
|
titles += '\x00' * 12
|
||||||
|
|
||||||
|
titles = titles[:0x4] + Crypto().createMD5Hash(titles) + titles[0x14:]
|
||||||
|
|
||||||
|
self.fp.seek(0)
|
||||||
|
self.fp.write(Crypto().encryptData(self.sdKey, self.sdIv, titles))
|
||||||
|
|
||||||
|
def delTitle(self, x, y, page):
|
||||||
|
self.setTitle(x, y, page, '\x00\x00\x00\x00')
|
||||||
|
|
||||||
|
class CONF:
|
||||||
|
"""This class deals with setting.txt which holds some important information like region and serial number """
|
||||||
|
def __init__(self, f):
|
||||||
|
self.conf = ''
|
||||||
|
self.keys = {}
|
||||||
|
self.lastKeyOffset = 0
|
||||||
|
self.totalKeys = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.fp = open(f, 'r+b')
|
||||||
|
except:
|
||||||
|
self.fp = open(f, 'w+b')
|
||||||
|
return
|
||||||
|
|
||||||
|
self.conf = self.fp.read(0x100)
|
||||||
|
self.conf = self.XORConf(self.conf)
|
||||||
|
self.fp.seek(0)
|
||||||
|
|
||||||
|
keys = self.conf.split('\r\n')
|
||||||
|
|
||||||
|
self.lastKeyOffset = self.conf.rfind('\r\n') + 2
|
||||||
|
self.totalKeys = len(keys) - 1
|
||||||
|
|
||||||
|
for x in range(self.totalKeys):
|
||||||
|
keyName = keys[x].split('=')[0]
|
||||||
|
keyVal = keys[x].split('=')[1]
|
||||||
|
|
||||||
|
self.keys[keyName] = keyVal
|
||||||
|
|
||||||
|
def getKeysCount(self):
|
||||||
|
"""Gets how many keys exist."""
|
||||||
|
return self.totalKeys
|
||||||
|
|
||||||
|
def getKeysName(self):
|
||||||
|
"""Returns the list of key names."""
|
||||||
|
return self.keys.keys()
|
||||||
|
|
||||||
|
def getKeyValue(self, key):
|
||||||
|
"""Returns the value of the key ``key''."""
|
||||||
|
try:
|
||||||
|
return self.keys[key.upper()]
|
||||||
|
except KeyError:
|
||||||
|
return 'Key not found'
|
||||||
|
|
||||||
|
def setKeyValue(self, key, value):
|
||||||
|
"""Sets the value of key ``key'' to ``value''."""
|
||||||
|
if(self.keyExist(key)):
|
||||||
|
self.keys[key.upper()] = value.upper()
|
||||||
|
|
||||||
|
self.conf = ''
|
||||||
|
|
||||||
|
for key in self.keys:
|
||||||
|
self.conf += key
|
||||||
|
self.conf += '='
|
||||||
|
self.conf += self.keys[key]
|
||||||
|
self.conf += '\r\n'
|
||||||
|
|
||||||
|
self.fp.seek(0)
|
||||||
|
self.fp.write(self.XORConf(self.conf))
|
||||||
|
self.fp.write('\x00' * (0x100 - len(self.conf)))
|
||||||
|
|
||||||
|
self.lastKeyOffset = self.conf.rfind('\r\n') + 2
|
||||||
|
|
||||||
|
def keyExist(self, key):
|
||||||
|
return self.keys.has_key(key.upper())
|
||||||
|
|
||||||
|
def addKey(self, key, value):
|
||||||
|
"""Adds key ``key'' with value ``value'' to the list."""
|
||||||
|
if self.lastKeyOffset + len(key) + 1 + len(value) + 2 > 0x100:
|
||||||
|
return -1
|
||||||
|
if not self.keyExist(key):
|
||||||
|
return -2
|
||||||
|
|
||||||
|
self.keys[key.upper()] = value.upper()
|
||||||
|
self.totalKeys +=1
|
||||||
|
|
||||||
|
self.conf = self.conf[:self.lastKeyOffset] + key.upper() + '=' + value.upper() + '\r\n'
|
||||||
|
|
||||||
|
self.lastKeyOffset += len(key) + 1 + len(value) + 2
|
||||||
|
|
||||||
|
self.fp.seek(0)
|
||||||
|
self.fp.write(self.XORConf(self.conf))
|
||||||
|
|
||||||
|
def XORConf(self, conf):
|
||||||
|
"""Encrypts/decrypts the setting.txt file."""
|
||||||
|
XORKey = 0x73B5DBFA
|
||||||
|
out = ''
|
||||||
|
for x in range(len(conf)):
|
||||||
|
out += chr(ord(conf[x]) ^ XORKey & 0xFF)
|
||||||
|
XORKey = (XORKey << 1) | (XORKey >> 31)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def deleteKey(self, key):
|
||||||
|
"""Deletes the key ``key''."""
|
||||||
|
try:
|
||||||
|
del self.keys[key.upper()]
|
||||||
|
self.totalKeys -=1
|
||||||
|
|
||||||
|
self.conf = ''
|
||||||
|
|
||||||
|
for key in self.keys:
|
||||||
|
self.conf += key
|
||||||
|
self.conf += '='
|
||||||
|
self.conf += self.keys[key]
|
||||||
|
self.conf += '\r\n'
|
||||||
|
|
||||||
|
self.fp.seek(0)
|
||||||
|
self.fp.write(self.XORConf(self.conf))
|
||||||
|
self.fp.write('\x00' * (0x100 - len(self.conf)))
|
||||||
|
|
||||||
|
self.lastKeyOffset = self.conf.rfind('\r\n') + 2
|
||||||
|
except KeyError:
|
||||||
|
return 'Key not found'
|
||||||
|
|
||||||
|
# This function is fucking dangerous. It deletes all keys with that value. Really not a good idea.
|
||||||
|
def deleteKeyByValue(self, value):
|
||||||
|
"""Deletes all keys with value ``value''. WATCH OUT, YOU MIGHT ACCIDENTALLY DELETE WRONG KEYS."""
|
||||||
|
try:
|
||||||
|
for key in self.keys.keys():
|
||||||
|
if self.keys.get(key) == value:
|
||||||
|
del self.keys[key]
|
||||||
|
self.totalKeys -=1
|
||||||
|
|
||||||
|
|
||||||
|
self.conf = ''
|
||||||
|
|
||||||
|
for key in self.keys:
|
||||||
|
self.conf += key
|
||||||
|
self.conf += '='
|
||||||
|
self.conf += self.keys[key]
|
||||||
|
self.conf += '\r\n'
|
||||||
|
|
||||||
|
self.fp.seek(0)
|
||||||
|
self.fp.write(self.XORConf(self.conf))
|
||||||
|
self.fp.write('\x00' * (0x100 - len(self.conf)))
|
||||||
|
|
||||||
|
self.lastKeyOffset = self.conf.rfind('\r\n') + 2
|
||||||
|
except KeyError:
|
||||||
|
return 'Key not found'
|
||||||
|
|
||||||
|
def getRegion(self):
|
||||||
|
"""gets the Region key. (Shortcut for getKeyValue("GAME"))"""
|
||||||
|
return self.getKeyValue("GAME")
|
||||||
|
|
||||||
|
def getArea(self):
|
||||||
|
"""gets the Area key. (Shortcut for getKeyValue("AREA"))"""
|
||||||
|
return self.getKeyValue("AREA")
|
||||||
|
|
||||||
|
def getVideoMode(self):
|
||||||
|
"""gets the Video Mode key. (Shortcut for getKeyValue("VIDEO"))"""
|
||||||
|
return self.getKeyValue("VIDEO")
|
||||||
|
|
||||||
|
def getSerialCode(self):
|
||||||
|
"""gets the Serial Code key. (Shortcut for getKeyValue("CODE"))"""
|
||||||
|
return self.getKeyValue("CODE")
|
||||||
|
|
||||||
|
def getDVDModel(self): # Might not be model =/
|
||||||
|
"""gets the DVD Model (?) key. (Shortcut for getKeyValue("DVD"))"""
|
||||||
|
return self.getKeyValue("DVD")
|
||||||
|
|
||||||
|
def getHardwareModel(self):
|
||||||
|
"""gets the Hardware Model key. (Shortcut for getKeyValue("MODEL"))"""
|
||||||
|
return self.getKeyValue("MODEL")
|
||||||
|
|
||||||
|
def getSerialNumber(self):
|
||||||
|
"""gets the Serial Number key. (Shortcut for getKeyValue("SERNO"))"""
|
||||||
|
return self.getKeyValue("SERNO")
|
||||||
|
|
||||||
|
|
||||||
|
def setRegion(self, value):
|
||||||
|
"""sets the Region key. (Shortcut for setKeyValue("GAME", value))"""
|
||||||
|
return self.setKeyValue("GAME", value)
|
||||||
|
|
||||||
|
def setArea(self, value):
|
||||||
|
"""sets the Area key. (Shortcut for setKeyValue("AREA", value))"""
|
||||||
|
return self.setKeyValue("AREA", value)
|
||||||
|
|
||||||
|
def setVideoMode(self, value):
|
||||||
|
"""sets the Video Mode key. (Shortcut for setKeyValue("VIDEO", value))"""
|
||||||
|
return self.setKeyValue("VIDEO", value)
|
||||||
|
|
||||||
|
def setSerialCode(self, value):
|
||||||
|
"""sets the Serial Code key. (Shortcut for setKeyValue("CODE", value))"""
|
||||||
|
return self.setKeyValue("CODE", value)
|
||||||
|
|
||||||
|
def setDVDModel(self, value): # Might not be model =/
|
||||||
|
"""sets the DVD Model (?) key. (Shortcut for setKeyValue("DVD", value))"""
|
||||||
|
return self.setKeyValue("DVD", value)
|
||||||
|
|
||||||
|
def setHardwareModel(self, value):
|
||||||
|
"""sets the Hardware Model key. (Shortcut for setKeyValue("MODEL", value))"""
|
||||||
|
return self.setKeyValue("MODEL", value)
|
||||||
|
|
||||||
|
def setSerialNumber(self, value):
|
||||||
|
"""sets the Serial Number key. (Shortcut for setKeyValue("SERNO", value))"""
|
||||||
|
return self.setKeyValue("SERNO", value)
|
||||||
|
|
||||||
|
class netConfig:
|
||||||
|
"""This class performs network configuration. The file is located on the NAND at /shared2/sys/net/02/config.dat."""
|
||||||
|
class configEntry(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.selected = Struct.uint8
|
||||||
|
self.padding_1 = Struct.string(1987)
|
||||||
|
self.ssid = Struct.string(32)
|
||||||
|
self.padding_2 = Struct.uint8
|
||||||
|
self.ssid_len = Struct.uint8
|
||||||
|
self.padding_3 = Struct.string(2)
|
||||||
|
self.padding_4 = Struct.uint8
|
||||||
|
self.encryption = Struct.uint8 # OPEN: 0x00, WEP: 0x01, WPA-PSK (TKIP): 0x04, WPA2-PSK (AES): 0x05, WPA-PSK (AES): 0x06
|
||||||
|
self.padding_5 = Struct.string(2)
|
||||||
|
self.padding_6 = Struct.uint8
|
||||||
|
self.key_len = Struct.uint8
|
||||||
|
self.padding_7 = Struct.string(2)
|
||||||
|
self.key = Struct.string(64)
|
||||||
|
self.padding_3 = Struct.string(236)
|
||||||
|
|
||||||
|
def __init__(self, conf):
|
||||||
|
self.f = conf
|
||||||
|
if(not os.path.isfile(self.f)):
|
||||||
|
fp = open(self.f, "wb")
|
||||||
|
fp.write("\x00\x00\x00\x00\x01\x07\x00\x00")
|
||||||
|
fp.write("\x00" * 0x91C * 3)
|
||||||
|
fp.close()
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
head = fp.read(8)
|
||||||
|
if(head != "\x00\x00\x00\x00\x01\x07\x00\x00"):
|
||||||
|
print("Config file is invalid!\n")
|
||||||
|
|
||||||
|
def getNotBlank(self, config):
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
fp.close()
|
||||||
|
if(sel & 0x20):
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def getIPType(self, config):
|
||||||
|
if(not self.getNotBlank(config)):
|
||||||
|
return None
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
if(sel & 0x04):
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
fp.close()
|
||||||
|
return sel
|
||||||
|
|
||||||
|
def getWireType(self, config):
|
||||||
|
if(not self.getNotBlank(config)):
|
||||||
|
return None
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
if(sel & 0x02):
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
def getSSID(self, config):
|
||||||
|
if(not self.getNotBlank(config)):
|
||||||
|
return None
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
fp.seek(8 + (0x91C * config) + 2021)
|
||||||
|
len = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
fp.seek(8 + (0x91C * config) + 1988)
|
||||||
|
ssid = fp.read(len)
|
||||||
|
fp.close()
|
||||||
|
return ssid
|
||||||
|
|
||||||
|
def getEncryptionType(self, config):
|
||||||
|
if(not self.getNotBlank(config)):
|
||||||
|
return None
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
fp.seek(8 + (0x91C * config) + 2025)
|
||||||
|
crypt = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
type = ""
|
||||||
|
if(crypt == 0):
|
||||||
|
type = "OPEN"
|
||||||
|
elif(crypt == 1):
|
||||||
|
type = "WEP"
|
||||||
|
elif(crypt == 4):
|
||||||
|
type = "WPA (TKIP)"
|
||||||
|
elif(crypt == 5):
|
||||||
|
type = "WPA2"
|
||||||
|
elif(crypt == 6):
|
||||||
|
type = "WPA (AES)"
|
||||||
|
else:
|
||||||
|
print("Invalid crypto type %02X. Valid types are: ``OPEN'', ``WEP'', ``WPA (TKIP)'', ``WPA2'', or ``WPA (AES)''\n" % crypt)
|
||||||
|
fp.close()
|
||||||
|
return None
|
||||||
|
fp.close()
|
||||||
|
return type
|
||||||
|
|
||||||
|
def getEncryptionKey(self, config):
|
||||||
|
if(not self.getNotBlank(config)):
|
||||||
|
return None
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
fp.seek(8 + (0x91C * config) + 2025)
|
||||||
|
crypt = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
type = ""
|
||||||
|
if(crypt == 0):
|
||||||
|
type = "OPEN"
|
||||||
|
elif(crypt == 1):
|
||||||
|
type = "WEP"
|
||||||
|
elif(crypt == 4):
|
||||||
|
type = "WPA (TKIP)"
|
||||||
|
elif(crypt == 5):
|
||||||
|
type = "WPA2"
|
||||||
|
elif(crypt == 6):
|
||||||
|
type = "WPA (AES)"
|
||||||
|
else:
|
||||||
|
print("Invalid crypto type %02X. Valid types are: ``OPEN'', ``WEP'', ``WPA (TKIP)'', ``WPA2'', or ``WPA (AES)''\n" % crypt)
|
||||||
|
fp.close()
|
||||||
|
return None
|
||||||
|
if(crypt != "\x00"):
|
||||||
|
fp.seek(8 + (0x91C * config) + 2029)
|
||||||
|
keylen = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
fp.seek(8 + (0x91C * config) + 2032)
|
||||||
|
key = fp.read(keylen)
|
||||||
|
fp.close()
|
||||||
|
return key
|
||||||
|
fp.close()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def clearConfig(self, config):
|
||||||
|
fp = open(self.f, "rb+")
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
sel &= 0xDF
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
fp.write(struct.pack(">B", sel))
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
def setNotBlank(self, config):
|
||||||
|
fp = open(self.f, "rb+")
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
sel |= 0x20
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
fp.write(struct.pack(">B", sel))
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
def setIPType(self, config, static):
|
||||||
|
fp = open(self.f, "rb+")
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
if(not static):
|
||||||
|
sel |= 0x04
|
||||||
|
else:
|
||||||
|
sel &= 0xFB
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
fp.write(struct.pack(">B", sel))
|
||||||
|
fp.close()
|
||||||
|
self.setNotBlank(config)
|
||||||
|
|
||||||
|
def setWireType(self, config, wired):
|
||||||
|
fp = open(self.f, "rb+")
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
if(not wired):
|
||||||
|
sel |= 0x02
|
||||||
|
else:
|
||||||
|
sel &= 0xFD
|
||||||
|
fp.seek(8 + (0x91C * config))
|
||||||
|
fp.write(struct.pack(">B", sel))
|
||||||
|
fp.close()
|
||||||
|
self.setNotBlank(config)
|
||||||
|
|
||||||
|
def setSSID(self, config, ssid):
|
||||||
|
fp = open(self.f, "rb+")
|
||||||
|
fp.seek(8 + (0x91C * config) + 1988)
|
||||||
|
fp.write(ssid)
|
||||||
|
fp.seek(8 + (0x91C * config) + 2021)
|
||||||
|
fp.write(a2b_hex("%02X" % len(ssid)))
|
||||||
|
fp.close()
|
||||||
|
self.setNotBlank(config)
|
||||||
|
|
||||||
|
def setEncryption(self, config, crypt, key):
|
||||||
|
fp = open(self.f, "rb+")
|
||||||
|
fp.seek(8 + (0x91C * config) + 2025)
|
||||||
|
if(crypt == "OPEN"):
|
||||||
|
fp.write("\x00")
|
||||||
|
elif(crypt == "WEP"):
|
||||||
|
fp.write("\x01")
|
||||||
|
elif(crypt == "WPA (TKIP)"):
|
||||||
|
fp.write("\x04")
|
||||||
|
elif(crypt == "WPA2"):
|
||||||
|
fp.write("\x05")
|
||||||
|
elif(crypt == "WPA (AES)"):
|
||||||
|
fp.write("\x06")
|
||||||
|
else:
|
||||||
|
print("Invalid crypto type. Valid types are: ``OPEN'', ``WEP'', ``WPA (TKIP)'', ``WPA2'', or ``WPA (AES)''\n")
|
||||||
|
fp.close()
|
||||||
|
return
|
||||||
|
if(crypt != "OPEN"):
|
||||||
|
fp.seek(8 + (0x91C * config) + 2029)
|
||||||
|
fp.write(a2b_hex("%02X" % len(key)))
|
||||||
|
fp.seek(8 + (0x91C * config) + 2032)
|
||||||
|
fp.write(key)
|
||||||
|
fp.close()
|
||||||
|
self.setNotBlank(config)
|
||||||
|
|
||||||
|
def selectConfig(self, config):
|
||||||
|
fp = open(self.f, "rb+")
|
||||||
|
fp.seek(8 + (0x91C * 0))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
if(config == 0):
|
||||||
|
sel |= 0x80
|
||||||
|
else:
|
||||||
|
sel &= 0x7F
|
||||||
|
fp.seek(8 + (0x91C * 0))
|
||||||
|
fp.write(struct.pack(">B", sel))
|
||||||
|
fp.seek(8 + (0x91C * 1))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
if(config == 1):
|
||||||
|
sel |= 0x80
|
||||||
|
else:
|
||||||
|
sel &= 0x7F
|
||||||
|
fp.seek(8 + (0x91C * 1))
|
||||||
|
fp.write(struct.pack(">B", sel))
|
||||||
|
fp.seek(8 + (0x91C * 2))
|
||||||
|
sel = struct.unpack(">B", fp.read(1))[0]
|
||||||
|
if(config == 2):
|
||||||
|
sel |= 0x80
|
||||||
|
else:
|
||||||
|
sel &= 0x7F
|
||||||
|
fp.seek(8 + (0x91C * 2))
|
||||||
|
fp.write(struct.pack(">B", sel))
|
||||||
|
self.setNotBlank(config)
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
|
||||||
|
class ContentMap:
|
||||||
|
"""This class performs all content.map related actions. Has functions to add contents, and find contents by hash.
|
||||||
|
The ``map'' parameter is the location of the content.map file."""
|
||||||
|
def __init__(self, map):
|
||||||
|
self.f = map
|
||||||
|
if(not os.path.isfile(map)):
|
||||||
|
open(map, "wb").close()
|
||||||
|
def contentByHash(self, hash):
|
||||||
|
"""When passed a sha1 hash (string of length 20), this will return the filename of the shared content (/shared1/%08x.app, no NAND prefix) specified by the hash in content.map. Note that if the content is not found, it will return False - not an empty string."""
|
||||||
|
cmfp = open(self.f, "rb")
|
||||||
|
cmdict = {}
|
||||||
|
num = len(cmfp.read()) / 28
|
||||||
|
cmfp.seek(0)
|
||||||
|
for z in range(num):
|
||||||
|
name = cmfp.read(8)
|
||||||
|
hash = cmfp.read(20)
|
||||||
|
cmdict[name] = hash
|
||||||
|
for key, value in cmdict.iteritems():
|
||||||
|
if(value == hash):
|
||||||
|
return "/shared1/%s.app" % key
|
||||||
|
return False #not found
|
||||||
|
|
||||||
|
def addContentToMap(self, contentid, hash):
|
||||||
|
"""Adds a content to the content.map file for the contentid and hash.
|
||||||
|
Returns the content id."""
|
||||||
|
cmfp = open(self.f, "rb")
|
||||||
|
cmdict = {}
|
||||||
|
num = len(cmfp.read()) / 28
|
||||||
|
cmfp.seek(0)
|
||||||
|
for z in range(num):
|
||||||
|
name = cmfp.read(8)
|
||||||
|
hash = cmfp.read(20)
|
||||||
|
cmdict[name] = hash
|
||||||
|
cmdict["%08x" % contentid] = hash
|
||||||
|
cmfp.close()
|
||||||
|
cmfp = open(self.f, "wb")
|
||||||
|
for key, value in cmdict.iteritems():
|
||||||
|
cmfp.write(key)
|
||||||
|
cmfp.write(value)
|
||||||
|
cmfp.close()
|
||||||
|
return contentid
|
||||||
|
|
||||||
|
def addHashToMap(self, hash):
|
||||||
|
"""Adds a content to the content.map file for the hash (uses next unavailable content id)
|
||||||
|
Returns the content id."""
|
||||||
|
cmfp = open(self.f, "rb")
|
||||||
|
cmdict = {}
|
||||||
|
cnt = 0
|
||||||
|
num = len(cmfp.read()) / 28
|
||||||
|
cmfp.seek(0)
|
||||||
|
for z in range(num):
|
||||||
|
name = cmfp.read(8)
|
||||||
|
hasho = cmfp.read(20)
|
||||||
|
cmdict[name] = hasho
|
||||||
|
cnt += 1
|
||||||
|
cmdict["%08x" % cnt] = hash
|
||||||
|
cmfp.close()
|
||||||
|
cmfp = open(self.f, "wb")
|
||||||
|
for key, value in cmdict.iteritems():
|
||||||
|
cmfp.write(key)
|
||||||
|
cmfp.write(value)
|
||||||
|
cmfp.close()
|
||||||
|
return cnt
|
||||||
|
|
||||||
|
def contentCount(self):
|
||||||
|
cmfp = open(self.f, "rb")
|
||||||
|
cmdict = {}
|
||||||
|
cnt = 0
|
||||||
|
num = len(cmfp.read()) / 28
|
||||||
|
cmfp.seek(0)
|
||||||
|
for z in range(num):
|
||||||
|
name = cmfp.read(8)
|
||||||
|
hash = cmfp.read(20)
|
||||||
|
cmdict[name] = hash
|
||||||
|
cnt += 1
|
||||||
|
cmfp.close()
|
||||||
|
return cnt
|
||||||
|
|
||||||
|
def contentHashes(self, count):
|
||||||
|
cmfp = open(self.f, "rb")
|
||||||
|
num = len(cmfp.read()) / 28
|
||||||
|
if(num > count):
|
||||||
|
num = count
|
||||||
|
cmfp.seek(0)
|
||||||
|
hashout = ""
|
||||||
|
for z in range(num):
|
||||||
|
name = cmfp.read(8)
|
||||||
|
hashout += cmfp.read(20)
|
||||||
|
cmfp.close()
|
||||||
|
return hashout
|
||||||
|
|
||||||
|
class uidsys:
|
||||||
|
"""This class performs all uid.sys related actions. It includes functions to add titles and find titles from the uid.sys file.
|
||||||
|
The ``uid'' parameter is the location of the uid.sys file."""
|
||||||
|
class UIDSYSStruct(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.titleid = Struct.uint64
|
||||||
|
self.padding = Struct.uint16
|
||||||
|
self.uid = Struct.uint16
|
||||||
|
|
||||||
|
def __init__(self, uid):
|
||||||
|
self.f = uid
|
||||||
|
if(not os.path.isfile(uid)):
|
||||||
|
uidfp = open(uid, "wb")
|
||||||
|
uiddat = self.UIDSYSStruct()
|
||||||
|
uiddat.titleid = 0x0000000100000002
|
||||||
|
uiddat.padding = 0
|
||||||
|
uiddat.uid = 0x1000
|
||||||
|
uidfp.write(uiddat.pack())
|
||||||
|
uidfp.close()
|
||||||
|
if((os.path.isfile(uid)) and (len(open(uid, "rb").read()) == 0)):
|
||||||
|
uidfp = open(uid, "wb")
|
||||||
|
uiddat = self.UIDSYSStruct()
|
||||||
|
uiddat.titleid = 0x0000000100000002
|
||||||
|
uiddat.padding = 0
|
||||||
|
uiddat.uid = 0x1000
|
||||||
|
uidfp.write(uiddat.pack())
|
||||||
|
uidfp.close()
|
||||||
|
|
||||||
|
def getUIDForTitle(self, title):
|
||||||
|
uidfp = open(self.f, "rb")
|
||||||
|
uiddat = uidfp.read()
|
||||||
|
cnt = len(uiddat) / 12
|
||||||
|
uidfp.seek(0)
|
||||||
|
uidstr = self.UIDSYSStruct()
|
||||||
|
uidict = {}
|
||||||
|
for i in range(cnt):
|
||||||
|
uidstr.titleid = uidfp.read(8)
|
||||||
|
uidstr.padding = uidfp.read(2)
|
||||||
|
uidstr.uid = uidfp.read(2)
|
||||||
|
uidict[uidstr.titleid] = uidstr.uid
|
||||||
|
for key, value in uidict.iteritems():
|
||||||
|
if(hexdump(key, "") == ("%016X" % title)):
|
||||||
|
return value
|
||||||
|
return self.addTitle(title)
|
||||||
|
|
||||||
|
def getTitle(self, uid):
|
||||||
|
uidfp = open(self.f, "rb")
|
||||||
|
uiddat = uidfp.read()
|
||||||
|
cnt = len(uiddat) / 12
|
||||||
|
uidfp.seek(0)
|
||||||
|
uidstr = self.UIDSYSStruct()
|
||||||
|
uidict = {}
|
||||||
|
for i in range(cnt):
|
||||||
|
uidstr.titleid = uidfp.read(8)
|
||||||
|
uidstr.padding = uidfp.read(2)
|
||||||
|
uidstr.uid = uidfp.read(2)
|
||||||
|
uidict[uidstr.titleid] = uidstr.uid
|
||||||
|
for key, value in uidict.iteritems():
|
||||||
|
if(hexdump(value, "") == ("%04X" % uid)):
|
||||||
|
return key
|
||||||
|
return None
|
||||||
|
|
||||||
|
def addTitle(self, title):
|
||||||
|
uidfp = open(self.f, "rb")
|
||||||
|
uiddat = uidfp.read()
|
||||||
|
cnt = len(uiddat) / 12
|
||||||
|
uidfp.seek(0)
|
||||||
|
uidstr = self.UIDSYSStruct()
|
||||||
|
uidict = {}
|
||||||
|
enduid = "\x10\x01"
|
||||||
|
for i in range(cnt):
|
||||||
|
uidstr.titleid = uidfp.read(8)
|
||||||
|
uidstr.padding = uidfp.read(2)
|
||||||
|
uidstr.uid = uidfp.read(2)
|
||||||
|
if(hexdump(uidstr.titleid, "") == ("%016X" % title)):
|
||||||
|
uidfp.close()
|
||||||
|
return uidstr.uid
|
||||||
|
if(struct.unpack(">H", uidstr.uid) >= struct.unpack(">H", enduid)):
|
||||||
|
enduid = a2b_hex("%04X" % (struct.unpack(">H", uidstr.uid)[0] + 1))
|
||||||
|
uidict[uidstr.titleid] = uidstr.uid
|
||||||
|
uidict[a2b_hex("%016X" % title)] = enduid
|
||||||
|
uidfp.close()
|
||||||
|
uidfp = open(self.f, "wb")
|
||||||
|
for key, value in uidict.iteritems():
|
||||||
|
uidfp.write(key)
|
||||||
|
uidfp.write("\0\0")
|
||||||
|
uidfp.write(value)
|
||||||
|
uidfp.close()
|
||||||
|
return enduid
|
||||||
|
|
||||||
|
class iplsave:
|
||||||
|
"""This class performs all iplsave.bin related things. It includes functions to add a title to the list, remove a title based upon position or title, and move a title from one position to another."""
|
||||||
|
class IPLSAVE_Entry(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.type1 = Struct.uint8
|
||||||
|
self.type2 = Struct.uint8
|
||||||
|
self.unk = Struct.uint32
|
||||||
|
self.flags = Struct.uint16
|
||||||
|
self.titleid = Struct.uint64
|
||||||
|
|
||||||
|
class IPLSAVE_Header(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.string(4)
|
||||||
|
self.filesize = Struct.uint32
|
||||||
|
self.unk = Struct.uint64
|
||||||
|
# 0x30 Entries go here.
|
||||||
|
self.unk2 = Struct.string(0x20)
|
||||||
|
self.md5 = Struct.string(0x10)
|
||||||
|
|
||||||
|
def __init__(self, f, nand = False):
|
||||||
|
self.f = f
|
||||||
|
if(not os.path.isfile(f)):
|
||||||
|
if(nand != False):
|
||||||
|
nand.newFile("/title/00000001/00000002/data/iplsave.bin", "rw----", 0x0001, 0x0000000100000002)
|
||||||
|
baseipl_h = self.IPLSAVE_Header
|
||||||
|
baseipl_ent = self.IPLSAVE_Entry
|
||||||
|
baseipl_ent.type1 = 0
|
||||||
|
baseipl_ent.type2 = 0
|
||||||
|
baseipl_ent.unk = 0
|
||||||
|
baseipl_ent.flags = 0
|
||||||
|
baseipl_ent.titleid = 0
|
||||||
|
baseipl_h.magic = "RIPL"
|
||||||
|
baseipl_h.filesize = 0x340
|
||||||
|
baseipl_h.unk = 0x0000000200000000
|
||||||
|
baseipl_h.unk2 = "\0" * 0x20
|
||||||
|
fp = open(f, "wb")
|
||||||
|
fp.write(baseipl_h.magic)
|
||||||
|
fp.write(a2b_hex("%08X" % baseipl_h.filesize))
|
||||||
|
fp.write(a2b_hex("%016X" % baseipl_h.unk))
|
||||||
|
i = 0
|
||||||
|
for i in range(0x30):
|
||||||
|
fp.write(a2b_hex("%02X" % baseipl_ent.type1))
|
||||||
|
fp.write(a2b_hex("%02X" % baseipl_ent.type2))
|
||||||
|
fp.write(a2b_hex("%08X" % baseipl_ent.unk))
|
||||||
|
fp.write(a2b_hex("%04X" % baseipl_ent.flags))
|
||||||
|
fp.write(a2b_hex("%016X" % baseipl_ent.titleid))
|
||||||
|
fp.write(baseipl_h.unk2)
|
||||||
|
fp.close()
|
||||||
|
self.updateMD5()
|
||||||
|
|
||||||
|
def updateMD5(self):
|
||||||
|
"""Updates the MD5 hash in the iplsave.bin file. Used by other functions here."""
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
data = fp.read()
|
||||||
|
fp.close()
|
||||||
|
md5 = Crypto().createMD5Hash(data)
|
||||||
|
fp = open(self.f, "wb")
|
||||||
|
fp.write(data)
|
||||||
|
fp.write(md5)
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
def slotUsed(self, x, y, page):
|
||||||
|
"""Returns whether or not the slot at (x,y) on page ``page'' is used."""
|
||||||
|
if((x + (y * 4) + (page * 12)) >= 0x30):
|
||||||
|
print "Too far!"
|
||||||
|
return None
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
data = fp.read()
|
||||||
|
fp.seek(16 + ((x + (y * 4) + (page * 12))) * 16)
|
||||||
|
baseipl_ent = self.IPLSAVE_Entry
|
||||||
|
baseipl_ent.type1 = fp.read(1)
|
||||||
|
baseipl_ent.type2 = fp.read(1)
|
||||||
|
baseipl_ent.unk = fp.read(4)
|
||||||
|
baseipl_ent.flags = fp.read(2)
|
||||||
|
baseipl_ent.titleid = fp.read(8)
|
||||||
|
fp.close()
|
||||||
|
if(baseipl_ent.type1 == "\0"):
|
||||||
|
return 0
|
||||||
|
return baseipl_ent.titleid
|
||||||
|
|
||||||
|
def addTitleBase(self, x, y, page, tid, movable, type, overwrite, clear, isdisc):
|
||||||
|
"""A base addTitle function that is used by others. Don't use this."""
|
||||||
|
if((x + (y * 4) + (page * 12)) >= 0x30):
|
||||||
|
print "Too far!"
|
||||||
|
return None
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
data = fp.read()
|
||||||
|
fp.seek(16 + ((x + (y * 4) + (page * 12))) * 16)
|
||||||
|
baseipl_ent = self.IPLSAVE_Entry
|
||||||
|
baseipl_ent.type1 = fp.read(1)
|
||||||
|
fp.close()
|
||||||
|
if((self.slotUsed(x, y, page)) and (not overwrite)):
|
||||||
|
return self.addTitleBase(x + 1, y, page, tid, movable, type, overwrite, clear, isdisc)
|
||||||
|
fp = open(self.f, "wb")
|
||||||
|
fp.write(data)
|
||||||
|
fp.seek(16 + ((x + (y * 4) + (page * 12))) * 16)
|
||||||
|
if((not clear) and (not isdisc)):
|
||||||
|
baseipl_ent.type1 = 3
|
||||||
|
baseipl_ent.type2 = type
|
||||||
|
baseipl_ent.unk = 0
|
||||||
|
baseipl_ent.flags = (movable ^ 1) + 0x0E
|
||||||
|
baseipl_ent.titleid = tid
|
||||||
|
if((clear) and (not isdisc)):
|
||||||
|
baseipl_ent.type1 = 0
|
||||||
|
baseipl_ent.type2 = 0
|
||||||
|
baseipl_ent.unk = 0
|
||||||
|
baseipl_ent.flags = 0
|
||||||
|
baseipl_ent.titleid = 0
|
||||||
|
if(isdisc):
|
||||||
|
baseipl_ent.type1 = 1
|
||||||
|
baseipl_ent.type2 = 1
|
||||||
|
baseipl_ent.unk = 0
|
||||||
|
baseipl_ent.flags = (movable ^ 1) + 0x0E
|
||||||
|
baseipl_ent.titleid = 0
|
||||||
|
fp.write(a2b_hex("%02X" % baseipl_ent.type1))
|
||||||
|
fp.write(a2b_hex("%02X" % baseipl_ent.type2))
|
||||||
|
fp.write(a2b_hex("%08X" % baseipl_ent.unk))
|
||||||
|
fp.write(a2b_hex("%04X" % baseipl_ent.flags))
|
||||||
|
fp.write(a2b_hex("%016X" % baseipl_ent.titleid))
|
||||||
|
fp.close()
|
||||||
|
self.updateMD5()
|
||||||
|
return (x + (y * 4) + (page * 12))
|
||||||
|
|
||||||
|
def addTitle(self, x, y, page, tid, movable, type):
|
||||||
|
"""Adds a title with title ID ``tid'' at location (x,y) on page ``page''. ``movable'' specifies whether the title is movable, and ``type'' specifies the type of title (00 for most titles.)"""
|
||||||
|
return self.addTitleBase(x, y, page, tid, movable, type, 0, 0, 0)
|
||||||
|
|
||||||
|
def addDisc(self, x, y, page, movable):
|
||||||
|
"""Adds the Disc Channel at location (x,y) on page ``page''. ``movable'' specifies whether it can be moved."""
|
||||||
|
return self.addTitleBase(x, y, page, 0, movable, 0, 0, 0, 1)
|
||||||
|
|
||||||
|
def deletePosition(self, x, y, page):
|
||||||
|
"""Deletes the title at (x,y) on page ``page''"""
|
||||||
|
return self.addTitleBase(x, y, page, 0, 0, 0, 1, 1, 0)
|
||||||
|
|
||||||
|
def deleteTitle(self, tid):
|
||||||
|
"""Deletes the title with title ID ``tid''"""
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
baseipl_ent = self.IPLSAVE_Entry
|
||||||
|
for i in range(0x30):
|
||||||
|
fp.seek(16 + (i * 16))
|
||||||
|
baseipl_ent.type1 = fp.read(1)
|
||||||
|
baseipl_ent.type2 = fp.read(1)
|
||||||
|
baseipl_ent.unk = fp.read(4)
|
||||||
|
baseipl_ent.flags = fp.read(2)
|
||||||
|
baseipl_ent.titleid = fp.read(8)
|
||||||
|
if(baseipl_ent.titleid == a2b_hex("%016X" % tid)):
|
||||||
|
self.deletePosition(i, 0, 0)
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
def moveTitle(self, x1, y1, page1, x2, y2, page2):
|
||||||
|
"""Moves a title from (x1,y1) on page ``page1'' to (x2,y2) on page ``page2''"""
|
||||||
|
fp = open(self.f, "rb")
|
||||||
|
baseipl_ent = self.IPLSAVE_Entry
|
||||||
|
fp.seek(16 + ((x1 + (y1 * 4) + (page1 * 12)) * 16))
|
||||||
|
baseipl_ent.type1 = fp.read(1)
|
||||||
|
baseipl_ent.type2 = fp.read(1)
|
||||||
|
baseipl_ent.unk = fp.read(4)
|
||||||
|
baseipl_ent.flags = fp.read(2)
|
||||||
|
baseipl_ent.titleid = fp.read(8)
|
||||||
|
fp.close()
|
||||||
|
self.deletePosition(x1, y1, page1)
|
||||||
|
return self.addTitle(x2, y2, page2, baseipl_ent.titleid, (baseipl_ent.flags - 0xE) ^ 1, baseipl_ent.type2)
|
112
WiiPy/headers.py
Normal file
112
WiiPy/headers.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
class IMD5(WiiHeader):
|
||||||
|
"""This class can add and remove IMD5 headers to files. The parameter f is the file to use for the addition or removal of the header. IMD5 headers are found in banner.bin, icon.bin, and sound.bin."""
|
||||||
|
class IMD5Header(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.tag = Struct.string(4)
|
||||||
|
self.size = Struct.uint32
|
||||||
|
self.zeroes = Struct.uint8[8]
|
||||||
|
self.crypto = Struct.string(16)
|
||||||
|
def add(self):
|
||||||
|
data = self.data
|
||||||
|
|
||||||
|
imd5 = self.IMD5Header()
|
||||||
|
imd5.tag = "IMD5"
|
||||||
|
imd5.size = len(data)
|
||||||
|
for i in range(8):
|
||||||
|
imd5.zeroes[i] = 0x00
|
||||||
|
imd5.crypto = str(Crypto().createMD5Hash(data))
|
||||||
|
data = imd5.pack() + data
|
||||||
|
|
||||||
|
return data
|
||||||
|
def remove(self):
|
||||||
|
"""This will remove an IMD5 header from the file specified in f, if one exists. If there is no IMD5 header, it will output the file as it is. It will output in the parameter fn if available, otherwise it will overwrite the source. Returns the output filename."""
|
||||||
|
data = self.data
|
||||||
|
imd5 = self.IMD5Header()
|
||||||
|
if(data[:4] != "IMD5"):
|
||||||
|
if(fn != ""):
|
||||||
|
open(fn, "wb").write(data)
|
||||||
|
return fn
|
||||||
|
else:
|
||||||
|
return self.f
|
||||||
|
data = data[len(imd5):]
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
class IMET(WiiHeader):
|
||||||
|
"""IMET headers are found in Opening.bnr and 0000000.app files. They contain the channel titles and more metadata about channels. They are in two different formats with different amounts of padding before the start of the IMET header. This class suports both.
|
||||||
|
|
||||||
|
The parameter f is used to specify the input file name."""
|
||||||
|
class IMETHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.zeroes = Struct.uint8[128]
|
||||||
|
self.tag = Struct.string(4)
|
||||||
|
self.unk = Struct.uint64
|
||||||
|
self.sizes = Struct.uint32[3] #icon, banner, sound
|
||||||
|
self.unk2 = Struct.uint32
|
||||||
|
self.names = Struct.string(84, encoding = "utf-16-be", stripNulls = True)[7]
|
||||||
|
self.zeroes2 = Struct.uint8[840]
|
||||||
|
self.hash = Struct.string(16)
|
||||||
|
def add(self, iconsz, bannersz, soundsz, name = "", langs = [], fn = ""):
|
||||||
|
"""This function adds an IMET header to the file specified with f in the initializer. The file will be output to fn if it is not empty, otherwise it will overwrite the input file. You must specify the size of banner.bin in bannersz, and respectivly for iconsz and soundsz. langs is an optional arguement that is a list of different langauge channel titles. name is the english name that is copied everywhere in langs that there is an empty string. Returns the output filename."""
|
||||||
|
data = self.data
|
||||||
|
imet = self.IMETHeader()
|
||||||
|
|
||||||
|
for i in imet.zeroes:
|
||||||
|
imet.zeroes[i] = 0x00
|
||||||
|
imet.tag = "IMET"
|
||||||
|
imet.unk = 0x0000060000000003
|
||||||
|
imet.sizes[0] = iconsz
|
||||||
|
imet.sizes[1] = bannersz
|
||||||
|
imet.sizes[2] = soundsz
|
||||||
|
imet.unk2 = 0
|
||||||
|
for i in range(len(imet.names)):
|
||||||
|
if(len(langs) > 0 and langs[i] != ""):
|
||||||
|
imet.names[i] = langs[i]
|
||||||
|
else:
|
||||||
|
imet.names[i] = name
|
||||||
|
for i in imet.zeroes2:
|
||||||
|
imet.zeroes2[i] = 0x00
|
||||||
|
imet.hash = "\x00" * 16
|
||||||
|
|
||||||
|
tmp = imet.pack()
|
||||||
|
imet.hash = Crypto().createMD5Hash(tmp[0x40:0x640]) #0x00 or 0x40?
|
||||||
|
|
||||||
|
data = imet.pack() + data
|
||||||
|
|
||||||
|
return data
|
||||||
|
def remove(self):
|
||||||
|
data = self.data
|
||||||
|
if(data[0x80:0x84] == "IMET"):
|
||||||
|
data = data[0x640:]
|
||||||
|
elif(data[0x40:0x44] == "IMET"):
|
||||||
|
data = data[0x640:]
|
||||||
|
return data
|
||||||
|
def getTitle(self):
|
||||||
|
imet = self.IMETHeader()
|
||||||
|
data = self.data
|
||||||
|
|
||||||
|
if(data[0x40:0x44] == "IMET"):
|
||||||
|
pass
|
||||||
|
elif(data[0x80:0x84] == "IMET"):
|
||||||
|
data = data[0x40:]
|
||||||
|
else:
|
||||||
|
raise ValueError("No IMET header found!")
|
||||||
|
|
||||||
|
imet.unpack(data[:len(imet)])
|
||||||
|
name = imet.names[1]
|
||||||
|
topop = []
|
||||||
|
for i in range(len(name)):
|
||||||
|
if(name[i] == "\x00"):
|
||||||
|
topop.append(i)
|
||||||
|
name = list(name)
|
||||||
|
popped = 0 #don't ask me why I did this
|
||||||
|
for pop in topop:
|
||||||
|
name.pop(pop - popped)
|
||||||
|
popped += 1
|
||||||
|
|
||||||
|
name = ''.join(name)
|
||||||
|
return name
|
802
WiiPy/image.py
Normal file
802
WiiPy/image.py
Normal file
@ -0,0 +1,802 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
from common import *
|
||||||
|
import wx
|
||||||
|
|
||||||
|
def flatten(myTuple):
|
||||||
|
if (len(myTuple) == 4):
|
||||||
|
return myTuple[0] << 0 | myTuple[1] << 8 | myTuple[2] << 16 | myTuple[3] << 24
|
||||||
|
else:
|
||||||
|
return myTuple[0] << 0 | myTuple[1] << 8 | myTuple[2] << 16 | 0xff << 24
|
||||||
|
|
||||||
|
def round_up(x, n):
|
||||||
|
left = x % n
|
||||||
|
return x + left
|
||||||
|
|
||||||
|
def avg(w0, w1, c0, c1):
|
||||||
|
a0 = c0 >> 11
|
||||||
|
a1 = c1 >> 11
|
||||||
|
a = (w0*a0 + w1*a1) / (w0 + w1)
|
||||||
|
c = (a << 11) & 0xffff
|
||||||
|
|
||||||
|
a0 = (c0 >> 5) & 63
|
||||||
|
a1 = (c1 >> 5) & 63
|
||||||
|
a = (w0*a0 + w1*a1) / (w0 + w1)
|
||||||
|
c = c | ((a << 5) & 0xffff)
|
||||||
|
|
||||||
|
a0 = c0 & 31
|
||||||
|
a1 = c1 & 31
|
||||||
|
a = (w0*a0 + w1*a1) / (w0 + w1)
|
||||||
|
c = c | a
|
||||||
|
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
class TPL():
|
||||||
|
"""This is the class to generate TPL texutres from PNG images, and to convert TPL textures to PNG images. The parameter file specifies the filename of the source, either a PNG image or a TPL image.
|
||||||
|
|
||||||
|
Currently supported are the following formats to convert from TPL (all formats): RGBA8, RGB565, RGB5A3, I4, IA4, I8, IA8, CI4, CI8, CMP, CI14X2.
|
||||||
|
|
||||||
|
Currently supported to convert to TPL: I4, I8, IA4, IA8, RBG565, RBGA8, RGB5A3. Currently not supported are CI4, CI8, CMP, CI14X2."""
|
||||||
|
|
||||||
|
|
||||||
|
class TPLHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.magic = Struct.uint32
|
||||||
|
self.ntextures = Struct.uint32
|
||||||
|
self.header_size = Struct.uint32
|
||||||
|
class TPLTexture(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.header_offset = Struct.uint32
|
||||||
|
self.palette_offset = Struct.uint32
|
||||||
|
class TPLTextureHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.height = Struct.uint16
|
||||||
|
self.width = Struct.uint16
|
||||||
|
self.format = Struct.uint32
|
||||||
|
self.data_off = Struct.uint32
|
||||||
|
self.wrap = Struct.uint32[2]
|
||||||
|
self.filter = Struct.uint32[2]
|
||||||
|
self.lod_bias = Struct.float
|
||||||
|
self.edge_lod = Struct.uint8
|
||||||
|
self.min_lod = Struct.uint8
|
||||||
|
self.max_lod = Struct.uint8
|
||||||
|
self.unpacked = Struct.uint8
|
||||||
|
class TPLPaletteHeader(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.nitems = Struct.uint16
|
||||||
|
self.unpacked = Struct.uint8
|
||||||
|
self.pad = Struct.uint8
|
||||||
|
self.format = Struct.uint32
|
||||||
|
self.offset = Struct.uint32
|
||||||
|
def __init__(self, file):
|
||||||
|
if(not ("\x00" in file) and os.path.isfile(file)):
|
||||||
|
self.file = file
|
||||||
|
self.data = None
|
||||||
|
else:
|
||||||
|
self.file = None
|
||||||
|
self.data = file
|
||||||
|
def toTPL(self, outfile, (width, height) = (None, None), format = "RGBA8"): #single texture only
|
||||||
|
"""This converts an image into a TPL. The image is specified as the file parameter to the class initializer, while the output filename is specified here as the parameter outfile. Width and height are optional parameters and specify the size to resize the image to, if needed. Returns the output filename.
|
||||||
|
|
||||||
|
This only can create TPL images with a single texture."""
|
||||||
|
head = self.TPLHeader()
|
||||||
|
head.magic = 0x0020AF30
|
||||||
|
head.ntextures = 1
|
||||||
|
head.header_size = 0x0C
|
||||||
|
|
||||||
|
tex = self.TPLTexture()
|
||||||
|
tex.header_offset = 0x14
|
||||||
|
tex.pallete_offset = 0
|
||||||
|
|
||||||
|
img = Image.open(self.file)
|
||||||
|
theWidth, theHeight = img.size
|
||||||
|
if(width != None and height != None and (width != theWidth or height != theHeight)):
|
||||||
|
img = img.resize((width, height), Image.ANTIALIAS)
|
||||||
|
w, h = img.size
|
||||||
|
|
||||||
|
texhead = self.TPLTextureHeader()
|
||||||
|
texhead.height = h
|
||||||
|
texhead.width = w
|
||||||
|
if format == "I4":
|
||||||
|
texhead.format = 0
|
||||||
|
tpldata = self.toI4((w, h), img)
|
||||||
|
elif format == "I8":
|
||||||
|
texhead.format = 1
|
||||||
|
tpldata = self.toI8((w, h), img)
|
||||||
|
elif format == "IA4":
|
||||||
|
texhead.format = 2
|
||||||
|
tpldata = self.toIA4((w, h), img)
|
||||||
|
elif format == "IA8":
|
||||||
|
texhead.format = 3
|
||||||
|
tpldata = self.toIA8((w, h), img)
|
||||||
|
elif format == "RGB565":
|
||||||
|
texhead.format = 4
|
||||||
|
tpldata = self.toRGB565((w, h), img)
|
||||||
|
elif format == "RGB5A3":
|
||||||
|
texhead.format = 5
|
||||||
|
tpldata = self.toRGB5A3((w, h), img)
|
||||||
|
elif format == "RGBA8":
|
||||||
|
texhead.format = 6
|
||||||
|
tpldata = self.toRGBA8((w, h), img)
|
||||||
|
elif format == "CI4":
|
||||||
|
texhead.format = 8
|
||||||
|
''' ADD toCI4 '''
|
||||||
|
raise Exception("toCI4 not done")
|
||||||
|
#tpldata = self.toCI4((w, h), img)
|
||||||
|
elif format == "CI8":
|
||||||
|
texhead.format = 9
|
||||||
|
''' ADD toCI8 '''
|
||||||
|
raise Exception("toCI8 not done")
|
||||||
|
#tpldata = self.toCI8((w, h), img)
|
||||||
|
elif format == "CI14X2":
|
||||||
|
texhead.format = 10
|
||||||
|
''' ADD toCI14X2 '''
|
||||||
|
raise Exception("toCI14X2 not done")
|
||||||
|
#tpldata = self.toCI14X2((w, h), img)
|
||||||
|
elif format == "CMP":
|
||||||
|
texhead.format = 14
|
||||||
|
''' ADD toCMP '''
|
||||||
|
raise Exception("toCMP not done")
|
||||||
|
#tpldata = self.toCMP((w, h), img)
|
||||||
|
|
||||||
|
texhead.data_off = 0x14 + len(texhead)
|
||||||
|
texhead.wrap = [0, 0]
|
||||||
|
texhead.filter = [1, 1]
|
||||||
|
texhead.lod_bias = 0
|
||||||
|
texhead.edge_lod = 0
|
||||||
|
texhead.min_lod = 0
|
||||||
|
texhead.max_lod = 0
|
||||||
|
texhead.unpacked = 0
|
||||||
|
|
||||||
|
f = open(outfile, "wb")
|
||||||
|
f.write(head.pack())
|
||||||
|
f.write(tex.pack())
|
||||||
|
f.write(texhead.pack())
|
||||||
|
if format == "I4":
|
||||||
|
f.write(struct.pack(">" + str(align(w,4) * align(h,4) / 2) + "B", *tpldata))
|
||||||
|
if format == "I8":
|
||||||
|
f.write(struct.pack(">" + str(align(w,4) * align(h,4) * 1) + "B", *tpldata))
|
||||||
|
if format == "IA4":
|
||||||
|
f.write(struct.pack(">" + str(align(w,4) * align(h,4) * 1) + "B", *tpldata))
|
||||||
|
if format == "IA8":
|
||||||
|
f.write(struct.pack(">" + str(align(w,4) * align(h,4) * 1) + "H", *tpldata))
|
||||||
|
if format == "RGB565":
|
||||||
|
f.write(struct.pack(">" + str(align(w,4) * align(h,4) * 1) + "H", *tpldata))
|
||||||
|
if format == "RGB5A3":
|
||||||
|
f.write(struct.pack(">" + str(align(w,4) * align(h,4) * 1) + "H", *tpldata))
|
||||||
|
if format == "RGBA8":
|
||||||
|
f.write(struct.pack(">" + str(align(w,4) * align(h,4) * 4) + "B", *tpldata))
|
||||||
|
if format == "CI4":
|
||||||
|
''' ADD toCI4 '''
|
||||||
|
#f.write(struct.pack(">"+ str(align(w,4) * align(h,4) * 4) + "B", *tpldata))
|
||||||
|
if format == "CI8":
|
||||||
|
''' ADD toCI8 '''
|
||||||
|
#f.write(struct.pack(">"+ str(align(w,4) * align(h,4) * 4) + "B", *tpldata))
|
||||||
|
if format == "CI14X2":
|
||||||
|
''' ADD toCI14X2 '''
|
||||||
|
#f.write(struct.pack(">"+ str(align(w,4) * align(h,4) * 4) + "B", *tpldata))
|
||||||
|
if format == "CMP":
|
||||||
|
''' ADD toCMP '''
|
||||||
|
#f.write(struct.pack(">"+ str(align(w,4) * align(h,4) * 4) + "B", *tpldata))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
return outfile
|
||||||
|
def toI4(self, (w, h), img):
|
||||||
|
out = [0 for i in range(align(w, 4) * align(h, 4) / 2)]
|
||||||
|
outp = 0
|
||||||
|
inp = list(img.getdata())
|
||||||
|
for y1 in range(0, h, 8):
|
||||||
|
for x1 in range(0, w, 8):
|
||||||
|
for y in range(y1, y1+8, 1):
|
||||||
|
for x in range(x1, x1+8, 2):
|
||||||
|
if x>=w or y>=h:
|
||||||
|
newpixel = 0
|
||||||
|
else:
|
||||||
|
rgba = flatten(inp[x+y*w])
|
||||||
|
r = (rgba >> 0) & 0xff
|
||||||
|
g = (rgba >> 8) & 0xff
|
||||||
|
b = (rgba >> 16) & 0xff
|
||||||
|
i1 = ((r + g + b) / 3) & 0xff
|
||||||
|
rgba = flatten(inp[x+1+y*w])
|
||||||
|
r = (rgba >> 0) & 0xff
|
||||||
|
g = (rgba >> 8) & 0xff
|
||||||
|
b = (rgba >> 16) & 0xff
|
||||||
|
i2 = ((r + g + b) / 3) & 0xff
|
||||||
|
|
||||||
|
newpixel = (((i1 * 15) / 255) << 4)
|
||||||
|
newpixel |= (((i2 * 15) / 255) & 0xf)
|
||||||
|
out[outp] = newpixel
|
||||||
|
outp += 1
|
||||||
|
return out
|
||||||
|
def toI8(self, (w, h), img):
|
||||||
|
out = [0 for i in range(align(w, 4) * align(h, 4))]
|
||||||
|
outp = 0
|
||||||
|
inp = list(img.getdata())
|
||||||
|
for y1 in range(0, h, 4):
|
||||||
|
for x1 in range(0, w, 8):
|
||||||
|
for y in range(y1, y1+4, 1):
|
||||||
|
for x in range(x1, x1+8, 1):
|
||||||
|
rgba = flatten(inp[x + (y * w)])
|
||||||
|
if x>= w or y>=h:
|
||||||
|
i1 = 0
|
||||||
|
else:
|
||||||
|
r = (rgba >> 0) & 0xff
|
||||||
|
g = (rgba >> 8) & 0xff
|
||||||
|
b = (rgba >> 16) & 0xff
|
||||||
|
i1 = ((r + g + b) / 3) & 0xff
|
||||||
|
out[outp] = i1
|
||||||
|
outp += 1
|
||||||
|
return out
|
||||||
|
def toIA4(self, (w, h), img):
|
||||||
|
out = [0 for i in range(align(w, 4) * align(h, 4))]
|
||||||
|
outp = 0
|
||||||
|
inp = list(img.getdata())
|
||||||
|
for y1 in range(0, h, 4):
|
||||||
|
for x1 in range(0, w, 8):
|
||||||
|
for y in range(y1, y1+4, 1):
|
||||||
|
for x in range(x1, x1+8, 1):
|
||||||
|
if x>=w or y>=h:
|
||||||
|
newpixel = 0
|
||||||
|
else:
|
||||||
|
rgba = flatten(inp[x + (y * w)])
|
||||||
|
r = (rgba >> 0) & 0xff
|
||||||
|
g = (rgba >> 8) & 0xff
|
||||||
|
b = (rgba >> 16) & 0xff
|
||||||
|
i1 = ((r + g + b) / 3) & 0xff
|
||||||
|
a1 = (rgba >> 24) & 0xff
|
||||||
|
|
||||||
|
newpixel = (((i1 * 15) / 255) & 0xf)
|
||||||
|
newpixel = newpixel | (((a1 * 15) / 255) << 4)
|
||||||
|
out[outp] = newpixel
|
||||||
|
outp += 1
|
||||||
|
return out
|
||||||
|
def toIA8(self, (w, h), img):
|
||||||
|
out = [0 for i in range(align(w, 4) * align(h, 4))]
|
||||||
|
outp = 0
|
||||||
|
inp = list(img.getdata())
|
||||||
|
for y1 in range(0, h, 4):
|
||||||
|
for x1 in range(0, w, 4):
|
||||||
|
for y in range(y1, y1+4, 1):
|
||||||
|
for x in range(x1, x1+4, 1):
|
||||||
|
if x>=w or y>=h:
|
||||||
|
newpixel = 0
|
||||||
|
else:
|
||||||
|
rgba = flatten(inp[x + (y * w)])
|
||||||
|
r = (rgba >> 0) & 0xff
|
||||||
|
g = (rgba >> 8) & 0xff
|
||||||
|
b = (rgba >> 16) & 0xff
|
||||||
|
i1 = ((r + g + b) / 3) & 0xff
|
||||||
|
a1 = (rgba >> 24) & 0xff
|
||||||
|
|
||||||
|
newpixel = i1 << 8
|
||||||
|
newpixel = newpixel | a1
|
||||||
|
out[outp] = newpixel
|
||||||
|
outp += 1
|
||||||
|
return out
|
||||||
|
def toRGB565(self, (w, h), img):
|
||||||
|
out = [0 for i in range(align(w, 4) * align(h, 4))]
|
||||||
|
outp = 0
|
||||||
|
inp = img.getdata()
|
||||||
|
for y1 in range(0, h, 4):
|
||||||
|
for x1 in range(0, w, 4):
|
||||||
|
for y in range(y1, y1+4, 1):
|
||||||
|
for x in range(x1, x1+4, 1):
|
||||||
|
newpixel = 0
|
||||||
|
if x>=w or y>=h:
|
||||||
|
newpixel = 0
|
||||||
|
else:
|
||||||
|
rgba = flatten(inp[x+y*w])
|
||||||
|
r = (rgba >> 0) & 0xff
|
||||||
|
g = (rgba >> 8) & 0xff
|
||||||
|
b = (rgba >> 16) & 0xff
|
||||||
|
newpixel = ((b >>3) << 11) | ((g >>2) << 5) | ((r >>3) << 0)
|
||||||
|
out[outp] = newpixel
|
||||||
|
outp += 1
|
||||||
|
return out
|
||||||
|
def toRGB5A3(self, (w, h), img):
|
||||||
|
out = [0 for i in range(align(w, 4) * align(h, 4))]
|
||||||
|
outp = 0
|
||||||
|
inp = list(img.getdata())
|
||||||
|
for y1 in range(0, h, 4):
|
||||||
|
for x1 in range(0, w, 4):
|
||||||
|
for y in range(y1, y1+4, 1):
|
||||||
|
for x in range(x1, x1+4, 1):
|
||||||
|
newpixel = 0
|
||||||
|
if x>=w or y>=h:
|
||||||
|
newpixel = 0
|
||||||
|
else:
|
||||||
|
rgba = flatten(inp[x + (y * h)])
|
||||||
|
r = (rgba >> 0) & 0xff
|
||||||
|
g = (rgba >> 8) & 0xff
|
||||||
|
b = (rgba >> 16) & 0xff
|
||||||
|
a = (rgba >> 24) & 0xff
|
||||||
|
if (a <= 0xda):
|
||||||
|
newpixel &= ~(1 << 15)
|
||||||
|
r = ((r * 15) / 255) & 0xf
|
||||||
|
g = ((g * 15) / 255) & 0xf
|
||||||
|
b = ((b * 15) / 255) & 0xf
|
||||||
|
a = ((a * 7) / 255) & 0x7
|
||||||
|
#newpixel |= r << 12
|
||||||
|
#newpixel |= g << 8
|
||||||
|
#newpixel |= b << 4
|
||||||
|
#newpixel |= a << 0
|
||||||
|
newpixel |= a << 12
|
||||||
|
newpixel |= b << 8
|
||||||
|
newpixel |= g << 4
|
||||||
|
newpixel |= r << 0
|
||||||
|
else:
|
||||||
|
newpixel |= (1 << 15)
|
||||||
|
r = ((r * 31) / 255) & 0x1f
|
||||||
|
g = ((g * 31) / 255) & 0x1f
|
||||||
|
b = ((b * 31) / 255) & 0x1f
|
||||||
|
newpixel |= b << 10
|
||||||
|
newpixel |= g << 5
|
||||||
|
newpixel |= r << 0
|
||||||
|
out[outp] = newpixel
|
||||||
|
outp += 1
|
||||||
|
return out
|
||||||
|
def toRGBA8(self, (w, h), img):
|
||||||
|
out = [0 for i in range(align(w, 4) * align(h, 4) * 4)]
|
||||||
|
inp = list(img.getdata())
|
||||||
|
iv = 0
|
||||||
|
z = 0
|
||||||
|
lr = [0 for i in range(32)]
|
||||||
|
lg = [0 for i in range(32)]
|
||||||
|
lb = [0 for i in range(32)]
|
||||||
|
la = [0 for i in range(32)]
|
||||||
|
for y1 in range(0, h, 4):
|
||||||
|
for x1 in range(0, w, 4):
|
||||||
|
for y in range(y1, y1 + 4, 1):
|
||||||
|
for x in range(x1, x1 + 4, 1):
|
||||||
|
if(y >= h or x >= w):
|
||||||
|
lr[z] = 0
|
||||||
|
lg[z] = 0
|
||||||
|
lb[z] = 0
|
||||||
|
la[z] = 0
|
||||||
|
else:
|
||||||
|
rgba = flatten(inp[x + (y * w)])
|
||||||
|
lr[z] = (rgba >> 0) & 0xff
|
||||||
|
lg[z] = (rgba >> 8) & 0xff
|
||||||
|
lb[z] = (rgba >> 16) & 0xff
|
||||||
|
la[z] = (rgba >> 24) & 0xff
|
||||||
|
z += 1
|
||||||
|
if(z == 16):
|
||||||
|
for i in range(16):
|
||||||
|
out[iv] = la[i] & 0xff
|
||||||
|
iv += 1
|
||||||
|
out[iv] = lr[i] & 0xff
|
||||||
|
iv += 1
|
||||||
|
for i in range(16):
|
||||||
|
out[iv] = lg[i] & 0xff
|
||||||
|
iv += 1
|
||||||
|
out[iv] = lb[i] & 0xff
|
||||||
|
iv += 1
|
||||||
|
z = 0
|
||||||
|
return out
|
||||||
|
def toImage(self, outfile):
|
||||||
|
"""This converts a TPL texture to a PNG image. You specify the input TPL filename in the initializer, and you specify the output filename in the outfile parameter to this method. Returns the output filename.
|
||||||
|
|
||||||
|
This only supports single textured TPL images."""
|
||||||
|
if(self.file):
|
||||||
|
data = open(self.file, "rb").read()
|
||||||
|
else:
|
||||||
|
data = self.data
|
||||||
|
|
||||||
|
header = self.TPLHeader()
|
||||||
|
textures = []
|
||||||
|
pos = 0
|
||||||
|
|
||||||
|
header.unpack(data[pos:pos + len(header)])
|
||||||
|
pos += len(header)
|
||||||
|
|
||||||
|
palette_offsets = []
|
||||||
|
|
||||||
|
for i in range(header.ntextures):
|
||||||
|
tmp = self.TPLTexture()
|
||||||
|
tmp.unpack(data[pos:pos + len(tmp)])
|
||||||
|
textures.append(tmp)
|
||||||
|
pos += len(tmp)
|
||||||
|
if(tmp.palette_offset > 0):
|
||||||
|
palette_offsets.append(tmp.palette_offset)
|
||||||
|
|
||||||
|
if(header.ntextures > 1):
|
||||||
|
raise ValueError("Only one texture supported. Don't touch me!")
|
||||||
|
|
||||||
|
for i in range(header.ntextures):
|
||||||
|
head = textures[i]
|
||||||
|
tex = self.TPLTextureHeader()
|
||||||
|
tex.unpack(data[head.header_offset:head.header_offset + len(tex)])
|
||||||
|
w = tex.width
|
||||||
|
h = tex.height
|
||||||
|
print tex.format
|
||||||
|
if(tex.format == 0): #I4, 4-bit
|
||||||
|
tpldata = struct.unpack(">" + str((w * h) / 2) + "B", data[tex.data_off:tex.data_off + ((w * h) / 2)])
|
||||||
|
rgbdata = self.I4((w, h), tpldata)
|
||||||
|
|
||||||
|
elif(tex.format == 1): #I8, 8-bit
|
||||||
|
tpldata = struct.unpack(">" + str(w * h) + "B", data[tex.data_off:tex.data_off + (w * h * 1)])
|
||||||
|
rgbdata = self.I8((w, h), tpldata)
|
||||||
|
elif(tex.format == 2): #IA4, 8-bit
|
||||||
|
tpldata = struct.unpack(">" + str(w * h) + "B", data[tex.data_off:tex.data_off + (w * h * 1)])
|
||||||
|
rgbdata = self.IA4((w, h), tpldata)
|
||||||
|
|
||||||
|
elif(tex.format == 4): #RGB565, 16-bit
|
||||||
|
tpldata = data[tex.data_off:]
|
||||||
|
rgbdata = self.RGB565((w, h), tpldata)
|
||||||
|
elif(tex.format == 5): #RGB5A3, 16-bit
|
||||||
|
tpldata = data[tex.data_off:]
|
||||||
|
rgbdata = self.RGB5A3((w, h), tpldata)
|
||||||
|
elif(tex.format == 3): #IA8, 16-bit
|
||||||
|
tpldata = data[tex.data_off:]
|
||||||
|
rgbdata = self.IA8((w, h), tpldata)
|
||||||
|
|
||||||
|
elif(tex.format == 6): #RGBA8, 32-bit, but for easyness's sake lets do it with 16-bit
|
||||||
|
tpldata = data[tex.data_off:]
|
||||||
|
rgbdata = self.RGBA8((w, h), tpldata)
|
||||||
|
|
||||||
|
elif(tex.format == 8 or tex.format == 9 or tex.format == 10):
|
||||||
|
palhead = self.TPLPaletteHeader()
|
||||||
|
offs = palette_offsets.pop(0)
|
||||||
|
palhead.unpack(data[offs:offs + len(palhead)])
|
||||||
|
|
||||||
|
tpldata = struct.unpack(">" + str(palhead.nitems) + "H", data[palhead.offset:palhead.offset + (palhead.nitems * 2)])
|
||||||
|
if(palhead.format == 0):
|
||||||
|
palette_data = self.IA8((palhead.nitems, 1), tpldata)[0]
|
||||||
|
elif(palhead.format == 1):
|
||||||
|
palette_data = self.RGB565((palhead.nitems, 1), tpldata)[0]
|
||||||
|
elif(palhead.format == 2):
|
||||||
|
palette_data = self.RGB5A3((palhead.nitems, 1), tpldata)[0]
|
||||||
|
|
||||||
|
paldata = []
|
||||||
|
for i in range(0, palhead.nitems * 4, 4):
|
||||||
|
tmp = 0
|
||||||
|
tmp |= palette_data[i + 0] << 24
|
||||||
|
tmp |= palette_data[i + 1] << 16
|
||||||
|
tmp |= palette_data[i + 2] << 8
|
||||||
|
tmp |= palette_data[i + 3] << 0
|
||||||
|
paldata.append(tmp)
|
||||||
|
|
||||||
|
if(tex.format == 8):
|
||||||
|
tpldata = struct.unpack(">" + str((w * h) / 2) + "B", data[tex.data_off:tex.data_off + ((w * h) / 2)])
|
||||||
|
rgbdata = self.CI4((w, h), tpldata, paldata)
|
||||||
|
if(tex.format == 9):
|
||||||
|
tpldata = struct.unpack(">" + str(w * h) + "B", data[tex.data_off:tex.data_off + (w * h * 1)])
|
||||||
|
rgbdata = self.CI8((w, h), tpldata, paldata)
|
||||||
|
if(tex.format == 10):
|
||||||
|
tpldata = struct.unpack(">" + str(w * h) + "H", data[tex.data_off:tex.data_off + (w * h * 2)])
|
||||||
|
rgbdata = self.CI14X2((w, h), tpldata, paldata)
|
||||||
|
elif(tex.format == 14):
|
||||||
|
tpldata = ''.join(data[tex.data_off:])
|
||||||
|
|
||||||
|
rgbdata = self.CMP((w, h), tpldata)
|
||||||
|
else:
|
||||||
|
raise TypeError("Unsupported TPL Format: " + str(tex.format))
|
||||||
|
|
||||||
|
output = Image.fromstring("RGBA", (w, h), rgbdata)
|
||||||
|
ext = outfile[outfile.rfind(".")+1:]
|
||||||
|
output.save(outfile, ext)
|
||||||
|
|
||||||
|
return outfile
|
||||||
|
def getSizes(self):
|
||||||
|
"""This returns a tuple containing the width and height of the TPL image filename in the class initializer. Will only return the size of single textured TPL images."""
|
||||||
|
data = open(self.file, "rb").read()
|
||||||
|
|
||||||
|
header = self.TPLHeader()
|
||||||
|
textures = []
|
||||||
|
pos = 0
|
||||||
|
|
||||||
|
header.unpack(data[pos:pos + len(header)])
|
||||||
|
pos += len(header)
|
||||||
|
|
||||||
|
for i in range(header.ntextures):
|
||||||
|
tmp = self.TPLTexture()
|
||||||
|
tmp.unpack(data[pos:pos + len(tmp)])
|
||||||
|
textures.append(tmp)
|
||||||
|
pos += len(tmp)
|
||||||
|
|
||||||
|
for i in range(header.ntextures):
|
||||||
|
head = textures[i]
|
||||||
|
tex = self.TPLTextureHeader()
|
||||||
|
tex.unpack(data[head.header_offset:head.header_offset + len(tex)])
|
||||||
|
w = tex.width
|
||||||
|
h = tex.height
|
||||||
|
return (w, h)
|
||||||
|
def toScreen(self): #single texture only
|
||||||
|
"""This will draw a simple window with the TPL image displayed on it. It uses WxPython for the window creation and management. The window has a minimum width and height of 300 x 200. Does not return a value.
|
||||||
|
|
||||||
|
Again, only a single texture is supported."""
|
||||||
|
import wx
|
||||||
|
class imp(wx.Dialog):
|
||||||
|
def __init__(self, title, im):
|
||||||
|
w = img.GetWidth()
|
||||||
|
h = img.GetHeight()
|
||||||
|
|
||||||
|
wx.Dialog.__init__(self, None, -1, title, size = (max(w, 300), max(h, 200)))
|
||||||
|
|
||||||
|
wx.StaticBitmap(self, -1, im, ( ((max(w, 300) - w) / 2), ((max(h, 200) - h) / 2) ), (w, h))
|
||||||
|
self.toImage("tmp.png")
|
||||||
|
img = wx.Image("tmp.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
|
||||||
|
w = img.GetWidth()
|
||||||
|
h = img.GetHeight()
|
||||||
|
dialog = imp("TPL (" + str(w) + ", " + str(h) + ")", img)
|
||||||
|
dialog.ShowModal()
|
||||||
|
dialog.Destroy()
|
||||||
|
os.unlink("tmp.png")
|
||||||
|
def RGBA8(self, (x, y), data):
|
||||||
|
out = [0 for i in range(x * y)]
|
||||||
|
inp = 0
|
||||||
|
for i in xrange(0, y, 4):
|
||||||
|
for j in xrange(0, x, 4):
|
||||||
|
for k in xrange(2):
|
||||||
|
for l in xrange(i, i + 4, 1):
|
||||||
|
for m in xrange(j, j + 4, 1):
|
||||||
|
texel = Struct.uint16(data[inp * 2:inp * 2 + 2], endian = '>')
|
||||||
|
inp += 1
|
||||||
|
if (m >= x) or (l >= y):
|
||||||
|
continue
|
||||||
|
if k == 0:
|
||||||
|
a = (texel >> 8) & 0xff
|
||||||
|
r = (texel >> 0) & 0xff
|
||||||
|
out[m + (l * x)] |= ((r << 0) | (a << 24))
|
||||||
|
else:
|
||||||
|
g = (texel >> 8) & 0xff
|
||||||
|
b = (texel >> 0) & 0xff
|
||||||
|
out[m + (l * x)] |= ((g << 8) | (b << 16))
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def RGB5A3(self, (w, h), jar):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 4):
|
||||||
|
for x in range(0, w, 4):
|
||||||
|
for y1 in range(y, y + 4):
|
||||||
|
for x1 in range(x, x + 4):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = Struct.uint16(jar[i * 2:i * 2 + 2], endian='>')
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if(pixel & (1 << 15)): #RGB555
|
||||||
|
b = (((pixel >> 10) & 0x1F) * 255) / 31
|
||||||
|
g = (((pixel >> 5) & 0x1F) * 255) / 31
|
||||||
|
r = (((pixel >> 0) & 0x1F) * 255) / 31
|
||||||
|
a = 255
|
||||||
|
else: #RGB4A3
|
||||||
|
a = (((pixel >> 12) & 0x07) * 255) / 7
|
||||||
|
b = (((pixel >> 8) & 0x0F) * 255) / 15
|
||||||
|
g = (((pixel >> 4) & 0x0F) * 255) / 15
|
||||||
|
r = (((pixel >> 0) & 0x0F) * 255)/ 15
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[(y1 * w) + x1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def RGB565(self, (w, h), jar):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 4):
|
||||||
|
for x in range(0, w, 4):
|
||||||
|
for y1 in range(y, y + 4):
|
||||||
|
for x1 in range(x, x + 4):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = Struct.uint16(jar[i * 2:i * 2 + 2], endian='>')
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
b = (((pixel >> 11) & 0x1F) << 3) & 0xff
|
||||||
|
g = (((pixel >> 5) & 0x3F) << 2) & 0xff
|
||||||
|
r = (((pixel >> 0) & 0x1F) << 3) & 0xff
|
||||||
|
a = 255
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def I4(self, (w, h), jar):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 8):
|
||||||
|
for x in range(0, w, 8):
|
||||||
|
for y1 in range(y, y + 8):
|
||||||
|
for x1 in range(x, x + 8, 2):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
|
||||||
|
r = (pixel >> 4) * 255 / 15
|
||||||
|
g = (pixel >> 4) * 255 / 15
|
||||||
|
b = (pixel >> 4) * 255 / 15
|
||||||
|
a = (pixel >> 4) * 255 / 15
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
r = (pixel & 0x0F) * 255 / 15
|
||||||
|
g = (pixel & 0x0F) * 255 / 15
|
||||||
|
b = (pixel & 0x0F) * 255 / 15
|
||||||
|
a = (pixel & 0x0F) * 255 / 15
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1 + 1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def IA4(self, (w, h), jar):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 4):
|
||||||
|
for x in range(0, w, 8):
|
||||||
|
for y1 in range(y, y + 4):
|
||||||
|
for x1 in range(x, x + 8):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
r = ((pixel & 0x0F) * 255 / 15) & 0xff
|
||||||
|
g = ((pixel & 0x0F) * 255 / 15) & 0xff
|
||||||
|
b = ((pixel & 0x0F) * 255 / 15) & 0xff
|
||||||
|
a = (((pixel >> 4) * 255) / 15) & 0xff
|
||||||
|
|
||||||
|
rgba = ( r<< 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def I8(self, (w, h), jar):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 4):
|
||||||
|
for x in range(0, w, 8):
|
||||||
|
for y1 in range(y, y + 4):
|
||||||
|
for x1 in range(x, x + 8):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
r = pixel
|
||||||
|
g = pixel
|
||||||
|
b = pixel
|
||||||
|
a = 255
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def IA8(self, (w, h), jar):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 4):
|
||||||
|
for x in range(0, w, 4):
|
||||||
|
for y1 in range(y, y + 4):
|
||||||
|
for x1 in range(x, x + 4):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = Struct.uint16(jar[i * 2:i * 2 + 2], endian='>')
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
r = (pixel >> 8) & 0xff
|
||||||
|
g = (pixel >> 8) & 0xff
|
||||||
|
b = (pixel >> 8) & 0xff
|
||||||
|
a = pixel & 0xff
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def CI4(self, (w, h), jar, pal):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 8):
|
||||||
|
for x in range(0, w, 8):
|
||||||
|
for y1 in range(y, y + 8):
|
||||||
|
for x1 in range(x, x + 8, 2):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
|
||||||
|
r = (pal[pixel] & 0xFF000000) >> 24
|
||||||
|
g = (pal[pixel] & 0x00FF0000) >> 16
|
||||||
|
b = (pal[pixel] & 0x0000FF00) >> 8
|
||||||
|
a = (pal[pixel] & 0x000000FF) >> 0
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
r = (pal[pixel] & 0xFF000000) >> 24
|
||||||
|
g = (pal[pixel] & 0x00FF0000) >> 16
|
||||||
|
b = (pal[pixel] & 0x0000FF00) >> 8
|
||||||
|
a = (pal[pixel] & 0x000000FF) >> 0
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1 + 1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def CI8(self, (w, h), jar, pal):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 4):
|
||||||
|
for x in range(0, w, 8):
|
||||||
|
for y1 in range(y, y + 4):
|
||||||
|
for x1 in range(x, x + 8):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
r = (pal[pixel] & 0xFF000000) >> 24
|
||||||
|
g = (pal[pixel] & 0x00FF0000) >> 16
|
||||||
|
b = (pal[pixel] & 0x0000FF00) >> 8
|
||||||
|
a = (pal[pixel] & 0x000000FF) >> 0
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
def CMP(self, (w, h), data):
|
||||||
|
temp = [0 for i in range(w * h)]
|
||||||
|
pix = [ 0 , 0 , 0 ]
|
||||||
|
c = [ 0 , 0 , 0 , 0 ]
|
||||||
|
outp = 0
|
||||||
|
for y in xrange(h):
|
||||||
|
for x in xrange(w):
|
||||||
|
ww = round_up(w, 8)
|
||||||
|
|
||||||
|
x0 = x & 0x03
|
||||||
|
x1 = (x >> 2) & 0x01
|
||||||
|
x2 = x >> 3
|
||||||
|
|
||||||
|
y0 = y & 0x03
|
||||||
|
y1 = (y >> 2) & 0x01
|
||||||
|
y2 = y >> 3
|
||||||
|
|
||||||
|
off = (8 * x1) + (16 * y1) + (32 * x2) + (4 * ww * y2)
|
||||||
|
|
||||||
|
c[0] = Struct.uint16(data[off + 0:off + 2], endian='>')
|
||||||
|
c[1] = Struct.uint16(data[off + 2:off + 4], endian='>')
|
||||||
|
if(c[0] > c[1]):
|
||||||
|
c[2] = avg(2, 1, c[0], c[1])
|
||||||
|
c[3] = avg(1, 2, c[0], c[1])
|
||||||
|
else:
|
||||||
|
c[2] = avg(1, 1, c[0], c[1])
|
||||||
|
c[3] = 0
|
||||||
|
|
||||||
|
px = Struct.uint32(data[off+4:off + 8], endian='>')
|
||||||
|
ix = x0 + ( 4 * y0 )
|
||||||
|
raw = c[(px >> (30 - (2 * ix))) & 0x03]
|
||||||
|
|
||||||
|
pix[0] = (raw >> 8) & 0xf8
|
||||||
|
pix[1] = (raw >> 3) & 0xf8
|
||||||
|
pix[2] = (raw << 3) & 0xf8
|
||||||
|
|
||||||
|
temp[outp] = (pix[0] <<0) | (pix[1] << 8) | (pix[2] << 16) | (255 << 24)
|
||||||
|
outp += 1
|
||||||
|
return ''.join(Struct.uint32(p) for p in temp)
|
||||||
|
def CI14X2(self, (w, h), jar):
|
||||||
|
out = [0 for i in range(w * h)]
|
||||||
|
i = 0
|
||||||
|
for y in range(0, h, 4):
|
||||||
|
for x in range(0, w, 4):
|
||||||
|
for y1 in range(y, y + 4):
|
||||||
|
for x1 in range(x, x + 4):
|
||||||
|
if(y1 >= h or x1 >= w):
|
||||||
|
continue
|
||||||
|
pixel = jar[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
r = (pal[pixel & 0x3FFF] & 0xFF000000) >> 24
|
||||||
|
g = (pal[pixel & 0x3FFF] & 0x00FF0000) >> 16
|
||||||
|
b = (pal[pixel & 0x3FFF] & 0x0000FF00) >> 8
|
||||||
|
a = (pal[pixel & 0x3FFF] & 0x000000FF) >> 0
|
||||||
|
|
||||||
|
rgba = (r << 0) | (g << 8) | (b << 16) | (a << 24)
|
||||||
|
out[y1 * w + x1] = rgba
|
||||||
|
return ''.join(Struct.uint32(p) for p in out)
|
||||||
|
if __name__=='__main__':
|
||||||
|
app = wx.PySimpleApp()
|
||||||
|
app.MainLoop()
|
||||||
|
TPL(*sys.argv[1:]).toScreen()
|
818
WiiPy/nand.py
Normal file
818
WiiPy/nand.py
Normal file
@ -0,0 +1,818 @@
|
|||||||
|
from binascii import *
|
||||||
|
from struct import *
|
||||||
|
|
||||||
|
from common import *
|
||||||
|
from title import *
|
||||||
|
from formats import *
|
||||||
|
|
||||||
|
class NAND:
|
||||||
|
"""This class performs all NAND related things. It includes functions to copy a title (given the TMD) into the correct structure as the Wii does, and has an entire ES-like system. Parameter f to the initializer is the folder that will be used as the NAND root."""
|
||||||
|
def __init__(self, f):
|
||||||
|
self.f = f
|
||||||
|
if(not os.path.isdir(f)):
|
||||||
|
os.mkdir(f)
|
||||||
|
|
||||||
|
self.perms = f + "/permission.txt"
|
||||||
|
if(not os.path.isfile(self.perms)):
|
||||||
|
open(self.perms, "wb").close()
|
||||||
|
self.newDirectory("/sys", "rwrw--", 0)
|
||||||
|
self.newFile("/sys/uid.sys", "rwrw--", 0)
|
||||||
|
self.UID = uidsys(self.f + "/sys/uid.sys")
|
||||||
|
self.newDirectory("/meta", "rwrwrw", 0x0001, 0x0000000100000002)
|
||||||
|
|
||||||
|
self.newDirectory("/import", "rwrw--", 0x0000)
|
||||||
|
self.newDirectory("/shared1", "rwrw--", 0x0000)
|
||||||
|
self.newDirectory("/shared2", "rwrwrw", 0x0000)
|
||||||
|
self.newFile("/sys/cc.sys", "rwrw--", 0x0000)
|
||||||
|
self.newFile("/sys/cert.sys", "rwrwr-", 0x0000)
|
||||||
|
self.newFile("/sys/space.sys", "rwrw--", 0x0000)
|
||||||
|
self.newDirectory("/ticket", "rwrw--", 0x0000)
|
||||||
|
self.newDirectory("/title", "rwrwr-", 0x0000)
|
||||||
|
self.newDirectory("/tmp", "rwrwrw", 0x0000)
|
||||||
|
self.ES = ESClass(self)
|
||||||
|
self.ISFS = ISFSClass(self)
|
||||||
|
self.ES._setisfs()
|
||||||
|
self.ISFS._setes()
|
||||||
|
self.contentmap = ContentMap(self.f + "/shared1/content.map")
|
||||||
|
|
||||||
|
def hasPermissionEntry(self, dir):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def removePermissionEntry(self, dir):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = -1
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read(newlineloc)
|
||||||
|
pfp.seek(endloc + 1)
|
||||||
|
data += pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
pfp = open(self.perms, "wb")
|
||||||
|
pfp.write(data)
|
||||||
|
pfp.close()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def _getFilePermissionBase(self, dir, loc):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = 0
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
if(loc > 0):
|
||||||
|
loc *= 2
|
||||||
|
pfp.seek(newlineloc + 1 + loc)
|
||||||
|
pdata = pfp.read(2)
|
||||||
|
pfp.close()
|
||||||
|
return pdata
|
||||||
|
|
||||||
|
def getFilePermissionOwner(self, dir):
|
||||||
|
pdata = self._getFilePermissionBase(dir, 0)
|
||||||
|
pval = 0
|
||||||
|
if(pdata[0] == "r"):
|
||||||
|
pval += 1
|
||||||
|
if(pdata[1] == "w"):
|
||||||
|
pval += 2
|
||||||
|
return pval
|
||||||
|
|
||||||
|
def getFilePermissionGroup(self, dir):
|
||||||
|
pdata = self._getFilePermissionBase(dir, 1)
|
||||||
|
pval = 0
|
||||||
|
if(pdata[0] == "r"):
|
||||||
|
pval += 1
|
||||||
|
if(pdata[1] == "w"):
|
||||||
|
pval += 2
|
||||||
|
return pval
|
||||||
|
|
||||||
|
def getFilePermissionOthers(self, dir):
|
||||||
|
pdata = self._getFilePermissionBase(dir, 2)
|
||||||
|
pval = 0
|
||||||
|
if(pdata[0] == "r"):
|
||||||
|
pval += 1
|
||||||
|
if(pdata[1] == "w"):
|
||||||
|
pval += 2
|
||||||
|
return pval
|
||||||
|
|
||||||
|
def getFilePermissionPerms(self, dir):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = 0
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
pfp.seek(newlineloc + 1)
|
||||||
|
pdata = pfp.read(6)
|
||||||
|
pfp.close()
|
||||||
|
return pdata
|
||||||
|
|
||||||
|
def _setFilePermissionBase(self, dir, loc, val):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = 0
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
if(loc > 0):
|
||||||
|
loc *= 2
|
||||||
|
pfp.seek(newlineloc + 1 + loc)
|
||||||
|
pfp.write(val)
|
||||||
|
pfp.close()
|
||||||
|
|
||||||
|
def setFilePermissionOwner(self, dir, val):
|
||||||
|
out = ""
|
||||||
|
if(val & 1):
|
||||||
|
out += "r"
|
||||||
|
if(val & 2):
|
||||||
|
out += "w"
|
||||||
|
self._setFilePermissionBase(dir, 0, out)
|
||||||
|
|
||||||
|
def setFilePermissionGroup(self, dir):
|
||||||
|
out = ""
|
||||||
|
if(val & 1):
|
||||||
|
out += "r"
|
||||||
|
if(val & 2):
|
||||||
|
out += "w"
|
||||||
|
self._setFilePermissionBase(dir, 1, out)
|
||||||
|
|
||||||
|
def setFilePermissionOthers(self, dir):
|
||||||
|
out = ""
|
||||||
|
if(val & 1):
|
||||||
|
out += "r"
|
||||||
|
if(val & 2):
|
||||||
|
out += "w"
|
||||||
|
self._setFilePermissionBase(dir, 2, out)
|
||||||
|
|
||||||
|
def isFileDirectory(self, dir):
|
||||||
|
pdata = self._getFilePermissionBase(dir, -1)
|
||||||
|
pval = 0
|
||||||
|
if(pdata[0] == "d"):
|
||||||
|
pval += 1
|
||||||
|
return pval
|
||||||
|
|
||||||
|
|
||||||
|
def getFilePermissionUID(self, dir):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = -1
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
pfp.seek(newlineloc + 8)
|
||||||
|
uidata = pfp.read(4)
|
||||||
|
pfp.close()
|
||||||
|
return int(uidata, 16)
|
||||||
|
|
||||||
|
def getFilePermissionGID(self, dir):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = -1
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
pfp.seek(newlineloc + 13)
|
||||||
|
gidata = pfp.read(4)
|
||||||
|
pfp.close()
|
||||||
|
return int(gidata, 16)
|
||||||
|
|
||||||
|
def setFilePermissionUID(self, dir, val):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = -1
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
pfp.seek(newlineloc + 8)
|
||||||
|
uidata = pfp.write("%04X" % val)
|
||||||
|
pfp.close()
|
||||||
|
return int(uidata, 16)
|
||||||
|
|
||||||
|
def setFilePermissionGID(self, dir, val):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
ret = data.find(dir)
|
||||||
|
if(ret == -1):
|
||||||
|
return 0
|
||||||
|
newlineloc = -1
|
||||||
|
for i in range(ret):
|
||||||
|
if(data.startswith("\n", i)):
|
||||||
|
newlineloc = i + 1
|
||||||
|
endloc = data.find("\n", newlineloc)
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
pfp.seek(newlineloc + 13)
|
||||||
|
gidata = pfp.write("%04X" % val)
|
||||||
|
pfp.close()
|
||||||
|
return int(gidata, 16)
|
||||||
|
|
||||||
|
def addPermissionEntry(self, uid, permissions, dir, groupid):
|
||||||
|
pfp = open(self.perms, "rb")
|
||||||
|
data = pfp.read()
|
||||||
|
pfp.close()
|
||||||
|
data += "%s " % permissions
|
||||||
|
if(uid == None):
|
||||||
|
print "UID is None!\n"
|
||||||
|
try:
|
||||||
|
data += hexdump(uid, "")
|
||||||
|
data += " "
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
data += "%04X " % uid
|
||||||
|
except:
|
||||||
|
print "UID type couldn't be confirmed..."
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
data += hexdump(groupid, "")
|
||||||
|
data += " "
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
data += "%04X " % groupid
|
||||||
|
except:
|
||||||
|
print "GID type couldn't be confirmed..."
|
||||||
|
return
|
||||||
|
data += "%s\n" % dir
|
||||||
|
pfp = open(self.perms, "wb")
|
||||||
|
pfp.write(data)
|
||||||
|
pfp.close()
|
||||||
|
|
||||||
|
def newDirectory(self, dir, perms, groupid, permtitle = 0):
|
||||||
|
"""Creates a new directory in the NAND filesystem and adds a permissions entry."""
|
||||||
|
if(not self.hasPermissionEntry(dir)):
|
||||||
|
if(permtitle == 0):
|
||||||
|
if(not os.path.isdir(self.f + dir)):
|
||||||
|
os.mkdir(self.f + dir)
|
||||||
|
self.addPermissionEntry(0, "d" + perms, dir, groupid)
|
||||||
|
else:
|
||||||
|
if(not os.path.isdir(self.f + dir)):
|
||||||
|
os.mkdir(self.f + dir)
|
||||||
|
self.addPermissionEntry(self.getUIDForTitleFromUIDSYS(permtitle), "d" + perms, dir, groupid)
|
||||||
|
|
||||||
|
def newFile(self, fil, perms, groupid, permtitle = 0):
|
||||||
|
"""Creates a new file in the NAND filesystem and adds a permissions entry."""
|
||||||
|
if(not self.hasPermissionEntry(fil)):
|
||||||
|
if(permtitle == 0):
|
||||||
|
if(not os.path.isfile(self.f + fil)):
|
||||||
|
open(self.f + fil, "wb").close()
|
||||||
|
self.addPermissionEntry(0, "-" + perms, fil, groupid)
|
||||||
|
else:
|
||||||
|
if(not os.path.isfile(self.f + fil)):
|
||||||
|
open(self.f + fil, "wb").close()
|
||||||
|
self.addPermissionEntry(self.getUIDForTitleFromUIDSYS(permtitle), "-" + perms, fil, groupid)
|
||||||
|
def removeFile(self, fil):
|
||||||
|
"""Deletes a file, and removes the permissions entry."""
|
||||||
|
os.remove(self.f + fil)
|
||||||
|
self.removePermissionEntry(fil)
|
||||||
|
|
||||||
|
def getContentByHashFromContentMap(self, hash):
|
||||||
|
"""Gets the filename of a shared content with SHA1 hash ``hash''. This includes the NAND prefix."""
|
||||||
|
return self.f + self.contentmap.contentByHash(hash)
|
||||||
|
|
||||||
|
def addContentToContentMap(self, contentid, hash):
|
||||||
|
"""Adds a content with content ID ``contentid'' and SHA1 hash ``hash'' to the content.map."""
|
||||||
|
return self.contentmap.addContentToMap(contentid, hash)
|
||||||
|
|
||||||
|
def addHashToContentMap(self, hash):
|
||||||
|
"""Adds a content with SHA1 hash ``hash'' to the content.map. It returns the content ID used."""
|
||||||
|
return self.contentmap.addHashToMap(hash)
|
||||||
|
|
||||||
|
def getContentCountFromContentMap(self):
|
||||||
|
"""Returns the number of contents in the content.map."""
|
||||||
|
return self.contentmap.contentCount()
|
||||||
|
|
||||||
|
def getContentHashesFromContentMap(self, count):
|
||||||
|
"""Returns the hashes of ``count'' contents in the content.map."""
|
||||||
|
return self.contentmap.contentHashes(count)
|
||||||
|
|
||||||
|
def addTitleToUIDSYS(self, title):
|
||||||
|
"""Adds the title with title ID ``title'' to the uid.sys file."""
|
||||||
|
return self.UID.addTitle(title)
|
||||||
|
|
||||||
|
def getTitleFromUIDSYS(self, uid):
|
||||||
|
"""Gets the title ID with UID ``uid'' from the uid.sys file."""
|
||||||
|
return self.UID.getTitle(uid)
|
||||||
|
|
||||||
|
def getUIDForTitleFromUIDSYS(self, title):
|
||||||
|
"""Gets the UID for title ID ``title'' from the uid.sys file."""
|
||||||
|
ret = self.UID.getUIDForTitle(title)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def addTitleToMenu(self, tid):
|
||||||
|
"""Adds a title to the System Menu."""
|
||||||
|
a = iplsave(self.f + "/title/00000001/00000002/data/iplsave.bin", self)
|
||||||
|
type = 0
|
||||||
|
if(((tid & 0xFFFFFFFFFFFFFF00) == 0x0001000248414300) or ((tid & 0xFFFFFFFFFFFFFF00) == 0x0001000248414200)):
|
||||||
|
type = 1
|
||||||
|
a.addTitle(0,0, 0, tid, 1, type)
|
||||||
|
|
||||||
|
def addDiscChannelToMenu(self, x, y, page, movable):
|
||||||
|
"""Adds the disc channel to the System Menu."""
|
||||||
|
a = iplsave(self.f + "/title/00000001/00000002/data/iplsave.bin", self)
|
||||||
|
a.addDisc(x, y, page, movable)
|
||||||
|
|
||||||
|
def deleteTitleFromMenu(self, tid):
|
||||||
|
"""Deletes a title from the System Menu."""
|
||||||
|
a = iplsave(self.f + "/title/00000001/00000002/data/iplsave.bin", self)
|
||||||
|
a.deleteTitle(tid)
|
||||||
|
|
||||||
|
def importTitle(self, prefix, tmd, tik, add_to_menu = True, is_decrypted = False, result_decrypted = False):
|
||||||
|
"""When passed a prefix (the directory to obtain the .app files from, sorted by content id), a TMD instance, and a Ticket instance, this will add that title to the NAND base folder specified in the constructor. If add_to_menu is True, the title (if neccessary) will be added to the menu. The default is True. Unless is_decrypted is set, the contents are assumed to be encrypted. If result_decrypted is True, then the contents will not end up decrypted."""
|
||||||
|
self.ES.AddTitleStart(tmd, None, None, is_decrypted, result_decrypted, use_version = True)
|
||||||
|
self.ES.AddTitleTMD(tmd)
|
||||||
|
self.ES.AddTicket(tik)
|
||||||
|
contents = tmd.getContents()
|
||||||
|
for i in range(tmd.tmd.numcontents):
|
||||||
|
self.ES.AddContentStart(tmd.tmd.titleid, contents[i].cid)
|
||||||
|
fp = open(prefix + "/%08x.app" % contents[i].cid, "rb")
|
||||||
|
data = fp.read()
|
||||||
|
fp.close()
|
||||||
|
self.ES.AddContentData(contents[i].cid, data)
|
||||||
|
self.ES.AddContentFinish(contents[i].cid)
|
||||||
|
self.ES.AddTitleFinish()
|
||||||
|
if(add_to_menu == True):
|
||||||
|
if(((tmd.tmd.titleid >> 32) != 0x00010008) and ((tmd.tmd.titleid >> 32) != 0x00000001)):
|
||||||
|
self.addTitleToMenu(tmd.tmd.titleid)
|
||||||
|
|
||||||
|
def createWADFromTitle(self, title, cert, output, version=0):
|
||||||
|
tmdpth = self.f + "/title/%08x/%08x/content/title.tmd" % (title >> 32, title & 0xFFFFFFFF)
|
||||||
|
if(version != 0):
|
||||||
|
tmdpth += ".%d" % version
|
||||||
|
tmd = TMD.loadFile(tmdpth)
|
||||||
|
if(not os.path.isdir("export")):
|
||||||
|
os.mkdir("export")
|
||||||
|
tmd.fakesign()
|
||||||
|
tmd.dumpFile("export/tmd")
|
||||||
|
tik = Ticket.loadFile(self.f + "/ticket/%08x/%08x.tik" % (title >> 32, title & 0xFFFFFFFF))
|
||||||
|
tik.fakesign()
|
||||||
|
tik.dumpFile("export/tik")
|
||||||
|
contents = tmd.getContents()
|
||||||
|
for i in range(tmd.tmd.numcontents):
|
||||||
|
path = ""
|
||||||
|
if(contents[i].type == 0x0001):
|
||||||
|
path = self.f + "/title/%08x/%08x/content/%08x.app" % (title >> 32, title & 0xFFFFFFFF, contents[i].cid)
|
||||||
|
elif(contents[i].type == 0x8001):
|
||||||
|
path = self.getContentByHashFromContentMap(contents[i].hash)
|
||||||
|
fp = open(path, "rb")
|
||||||
|
data = fp.read()
|
||||||
|
fp.close()
|
||||||
|
fp = open("export/%08x.app" % contents[i].index, "wb")
|
||||||
|
fp.write(data)
|
||||||
|
fp.close()
|
||||||
|
fp = open(cert, "rb")
|
||||||
|
data = fp.read()
|
||||||
|
fp.close()
|
||||||
|
fp = open("export/cert", "wb")
|
||||||
|
fp.write(data)
|
||||||
|
fp.close()
|
||||||
|
WAD("export").pack(output)
|
||||||
|
for i in range(tmd.tmd.numcontents):
|
||||||
|
os.remove("export/%08x.app" % contents[i].index)
|
||||||
|
os.remove("export/tmd")
|
||||||
|
os.remove("export/tik")
|
||||||
|
os.remove("export/cert")
|
||||||
|
os.rmdir("export")
|
||||||
|
|
||||||
|
|
||||||
|
class ISFSClass:
|
||||||
|
"""This class contains an interface to the NAND that simulates the permissions system and all other aspects of the ISFS.
|
||||||
|
The nand argument to the initializer is a NAND object."""
|
||||||
|
class ISFSFP:
|
||||||
|
def __init__(self, file, mode):
|
||||||
|
self.fp = open(file, mode)
|
||||||
|
self.loc = 0
|
||||||
|
self.size = len(self.fp.read())
|
||||||
|
self.fp.seek(0)
|
||||||
|
self.SEEK_SET = 0
|
||||||
|
self.SEEK_CUR = 1
|
||||||
|
self.SEEK_END = 2
|
||||||
|
def seek(self, where, whence = 0):
|
||||||
|
if(whence == self.SEEK_SET):
|
||||||
|
self.loc = where
|
||||||
|
if(whence == self.SEEK_CUR):
|
||||||
|
self.loc += where
|
||||||
|
if(whence == self.SEEK_END):
|
||||||
|
self.loc = self.size - where
|
||||||
|
self.fp.seek(self.loc)
|
||||||
|
return self.loc
|
||||||
|
def close(self):
|
||||||
|
self.fp.close()
|
||||||
|
self.loc = 0
|
||||||
|
self.size = 0
|
||||||
|
def write(self, data):
|
||||||
|
leng = self.fp.write(data)
|
||||||
|
self.loc += leng
|
||||||
|
return leng
|
||||||
|
def read(self, length=""):
|
||||||
|
if(length == ""):
|
||||||
|
self.loc = self.size
|
||||||
|
return self.fp.read()
|
||||||
|
self.loc += length
|
||||||
|
return self.fp.read(length)
|
||||||
|
|
||||||
|
def __init__(self, nand):
|
||||||
|
self.nand = nand
|
||||||
|
self.f = nand.f
|
||||||
|
self.ES = None
|
||||||
|
def _setes(self):
|
||||||
|
self.ES = self.nand.ES
|
||||||
|
|
||||||
|
def _checkPerms(self, mode, uid, gid, own, grp, oth):
|
||||||
|
if(uid == self.ES.title):
|
||||||
|
if(own & mode):
|
||||||
|
return 1
|
||||||
|
elif(gid == self.ES.group):
|
||||||
|
if(grp & mode):
|
||||||
|
return 1
|
||||||
|
elif(oth & mode):
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def Open(self, file, mode):
|
||||||
|
if(not os.path.isfile(self.f + file)):
|
||||||
|
return None
|
||||||
|
modev = 0
|
||||||
|
if(mode.find("r") != -1):
|
||||||
|
modev = 1
|
||||||
|
elif(mode.find("w") != -1):
|
||||||
|
modev = 2
|
||||||
|
if(mode.find("+") != -1):
|
||||||
|
modev = 3
|
||||||
|
uid = self.nand.getFilePermissionUID(file)
|
||||||
|
gid = self.nand.getFilePermissionGID(file)
|
||||||
|
own = self.nand.getFilePermissionOwner(file)
|
||||||
|
grp = self.nand.getFilePermissionGroup(file)
|
||||||
|
oth = self.nand.getFilePermissionOthers(file)
|
||||||
|
if(self._checkPerms(modev, uid, gid, own, grp, oth) == 0):
|
||||||
|
return -41
|
||||||
|
return self.ISFSFP(self.f + file, mode)
|
||||||
|
|
||||||
|
def Close(self, fp):
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
def Delete(self, file):
|
||||||
|
uid = self.nand.getFilePermissionUID(file)
|
||||||
|
gid = self.nand.getFilePermissionGID(file)
|
||||||
|
own = self.nand.getFilePermissionOwner(file)
|
||||||
|
grp = self.nand.getFilePermissionGroup(file)
|
||||||
|
oth = self.nand.getFilePermissionOthers(file)
|
||||||
|
if(self._checkPerms(2, uid, gid, own, grp, oth) == 0):
|
||||||
|
return -41
|
||||||
|
self.nand.removeFile(file)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def CreateFile(self, filename, perms):
|
||||||
|
dirabove = filename
|
||||||
|
uid = self.nand.getFilePermissionUID(dirabove)
|
||||||
|
gid = self.nand.getFilePermissionGID(dirabove)
|
||||||
|
own = self.nand.getFilePermissionOwner(dirabove)
|
||||||
|
grp = self.nand.getFilePermissionGroup(dirabove)
|
||||||
|
oth = self.nand.getFilePermissionOthers(dirabove)
|
||||||
|
if(self._checkPerms(2, uid, gid, own, grp, oth) == 0):
|
||||||
|
return -41
|
||||||
|
self.nand.newFile(filename, perms, self.ES.group, self.ES.title)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def Write(self, fp, data):
|
||||||
|
return fp.write(data)
|
||||||
|
|
||||||
|
def Read(self, fp, length=""):
|
||||||
|
return fp.read(length)
|
||||||
|
|
||||||
|
def Seek(self, fp, where, whence):
|
||||||
|
return fp.seek(where, whence)
|
||||||
|
|
||||||
|
def CreateDir(self, dirname, perms):
|
||||||
|
dirabove = dirname
|
||||||
|
uid = self.nand.getFilePermissionUID(dirabove)
|
||||||
|
gid = self.nand.getFilePermissionGID(dirabove)
|
||||||
|
own = self.nand.getFilePermissionOwner(dirabove)
|
||||||
|
grp = self.nand.getFilePermissionGroup(dirabove)
|
||||||
|
oth = self.nand.getFilePermissionOthers(dirabove)
|
||||||
|
if(self._checkPerms(2, uid, gid, own, grp, oth) == 0):
|
||||||
|
return -41
|
||||||
|
self.nand.newDirectory(dirname, perms, self.ES.group, self.ES.title)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def GetAttr(self, filename): # Wheeee, stupid haxx to put all the numbers into one return value!
|
||||||
|
ret = self.nand.getFilePermissionUID(filename)
|
||||||
|
ret += (self.nand.getFilePermissionGID(filename) << 16)
|
||||||
|
ret += (self.nand.getFilePermissionOwner(filename) << 32)
|
||||||
|
ret += (self.nand.getFilePermissionGroup(filename) << 34)
|
||||||
|
ret += (self.nand.getFilePermissionOthers(filename) << 36)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def splitAttrUID(self, attr):
|
||||||
|
return attr & 0xFFFF
|
||||||
|
def splitAttrGID(self, attr):
|
||||||
|
return (attr >> 16) & 0xFFFF
|
||||||
|
def splitAttrOwner(self, attr):
|
||||||
|
return (attr >> 32) & 0xFF
|
||||||
|
def splitAttrGroup(self, attr):
|
||||||
|
return (attr >> 34) & 0xFF
|
||||||
|
def splitAttrOthers(self, attr):
|
||||||
|
return (attr >> 36) & 0xFF
|
||||||
|
|
||||||
|
def Rename(self, fileold, filenew):
|
||||||
|
uid = self.nand.getFilePermissionUID(fileold)
|
||||||
|
gid = self.nand.getFilePermissionGID(fileold)
|
||||||
|
own = self.nand.getFilePermissionOwner(fileold)
|
||||||
|
grp = self.nand.getFilePermissionGroup(fileold)
|
||||||
|
oth = self.nand.getFilePermissionOthers(fileold)
|
||||||
|
if(self._checkPerms(2, uid, gid, own, grp, oth) == 0):
|
||||||
|
return -41
|
||||||
|
fld = self.nand.isFileDirectory(fileold)
|
||||||
|
if(fld):
|
||||||
|
print "Directory moving is busted ATM. Will fix laterz.\n"
|
||||||
|
return -40
|
||||||
|
fp = self.Open(fileold, "rb")
|
||||||
|
data = fp.Read()
|
||||||
|
fp.close()
|
||||||
|
perms = ""
|
||||||
|
if(own & 1):
|
||||||
|
perms += "r"
|
||||||
|
else:
|
||||||
|
perms += "-"
|
||||||
|
if(own & 2):
|
||||||
|
perms += "w"
|
||||||
|
else:
|
||||||
|
perms += "-"
|
||||||
|
if(grp & 1):
|
||||||
|
perms += "r"
|
||||||
|
else:
|
||||||
|
perms += "-"
|
||||||
|
if(grp & 2):
|
||||||
|
perms += "w"
|
||||||
|
else:
|
||||||
|
perms += "-"
|
||||||
|
if(oth & 1):
|
||||||
|
perms += "r"
|
||||||
|
else:
|
||||||
|
perms += "-"
|
||||||
|
if(oth & 2):
|
||||||
|
perms += "w"
|
||||||
|
else:
|
||||||
|
perms += "-"
|
||||||
|
self.CreateFile(filenew, perms)
|
||||||
|
fp = self.Open(filenew, "wb")
|
||||||
|
fp.write(data)
|
||||||
|
fp.close()
|
||||||
|
self.Delete(fileold)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def SetAttr(self, filename, uid, gid=0, owner=0, group=0, others=0):
|
||||||
|
uidx = self.nand.getFilePermissionUID(filename)
|
||||||
|
gidx = self.nand.getFilePermissionGID(filename)
|
||||||
|
own = self.nand.getFilePermissionOwner(filename)
|
||||||
|
grp = self.nand.getFilePermissionGroup(filename)
|
||||||
|
oth = self.nand.getFilePermissionOthers(filename)
|
||||||
|
if(self._checkPerms(2, uidx, gidx, own, grp, oth) == 0):
|
||||||
|
return -41
|
||||||
|
self.nand.setFilePermissionUID(filename, uid)
|
||||||
|
self.nand.setFilePermissionGID(filename, gid)
|
||||||
|
self.nand.setFilePermissionOwner(filename, owner)
|
||||||
|
self.nand.setFilePermissionGroup(filename, group)
|
||||||
|
self.nand.setFilePermissionOthers(filename, others)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class ESClass:
|
||||||
|
"""This class performs all services relating to titles installed on the Wii. It is a clone of the libogc ES interface.
|
||||||
|
The nand argument to the initializer is a NAND object."""
|
||||||
|
def __init__(self, nand):
|
||||||
|
self.title = 0x0000000100000002
|
||||||
|
self.group = 0x0001
|
||||||
|
self.ticketadded = 0
|
||||||
|
self.tmdadded = 0
|
||||||
|
self.workingcid = 0
|
||||||
|
self.workingcidcnt = 0
|
||||||
|
self.nand = nand
|
||||||
|
self.f = nand.f
|
||||||
|
self.ISFS = None
|
||||||
|
def _setisfs(self):
|
||||||
|
self.ISFS = self.nand.ISFS
|
||||||
|
def getContentIndexFromCID(self, tmd, cid):
|
||||||
|
"""Gets the content index from the content id cid referenced to in the TMD instance tmd."""
|
||||||
|
for i in range(tmd.tmd.numcontents):
|
||||||
|
if(cid == tmd.contents[i].cid):
|
||||||
|
return tmd.contents[i].index
|
||||||
|
return None
|
||||||
|
def Identify(self, id, version=0):
|
||||||
|
if(not os.path.isfile(self.f + "/ticket/%08x/%08x.tik" % (id >> 32, id & 0xFFFFFFFF))):
|
||||||
|
return None
|
||||||
|
tik = Ticket.loadFile(self.f + "/ticket/%08x/%08x.tik" % (id >> 32, id & 0xFFFFFFFF))
|
||||||
|
titleid = tik.titleid
|
||||||
|
path = "/title/%08x/%08x/content/title.tmd" % (titleid >> 32, titleid & 0xFFFFFFFF)
|
||||||
|
if(version):
|
||||||
|
path += ".%d" % version
|
||||||
|
if(not os.path.isfile(self.f + path)):
|
||||||
|
return None
|
||||||
|
tmd = TMD.loadFile(self.f + path)
|
||||||
|
self.title = titleid
|
||||||
|
self.group = tmd.tmd.group_id
|
||||||
|
return self.title
|
||||||
|
def GetTitleID(self):
|
||||||
|
return self.title
|
||||||
|
def GetDataDir(self, titleid):
|
||||||
|
"""When passed a titleid, it will get the Titles data directory. If there is no title associated with titleid, it will return None."""
|
||||||
|
if(not os.path.isdir(self.f + "/title/%08x/%08x/data" % (titleid >> 32, titleid & 0xFFFFFFFF))):
|
||||||
|
return None
|
||||||
|
return self.f + "/title/%08x/%08x/data" % (titleid >> 32, titleid & 0xFFFFFFFF)
|
||||||
|
def GetStoredTMD(self, titleid, version=0):
|
||||||
|
"""Gets the TMD for the specified titleid and version"""
|
||||||
|
path = "/title/%08x/%08x/content/title.tmd" % (titleid >> 32, titleid & 0xFFFFFFFF)
|
||||||
|
if(version):
|
||||||
|
path += ".%d" % version
|
||||||
|
if(not os.path.isfile(self.f + path)):
|
||||||
|
return None
|
||||||
|
return TMD.loadFile(self.f + path)
|
||||||
|
def GetTitleContentsCount(self, titleid, version=0):
|
||||||
|
"""Gets the number of contents the title with the specified titleid and version has."""
|
||||||
|
tmd = self.GetStoredTMD(titleid, version)
|
||||||
|
if(tmd == None):
|
||||||
|
return 0
|
||||||
|
return tmd.tmd.numcontents
|
||||||
|
def GetTitleContents(self, titleid, count, version=0):
|
||||||
|
"""Returns a list of content IDs for title id ``titleid'' and version ``version''. It will return, at maximum, ``count'' entries."""
|
||||||
|
tmd = self.GetStoredTMD(titleid, version)
|
||||||
|
if(tmd == None):
|
||||||
|
return 0
|
||||||
|
contents = tmd.getContents()
|
||||||
|
out = ""
|
||||||
|
for z in range(count):
|
||||||
|
out += a2b_hex("%08X" % contents[z].cid)
|
||||||
|
return out
|
||||||
|
def GetNumSharedContents(self):
|
||||||
|
"""Gets how many shared contents exist on the NAND"""
|
||||||
|
return self.nand.getContentCountFromContentMap()
|
||||||
|
def GetSharedContents(self, cnt):
|
||||||
|
"""Gets cnt amount of shared content hashes"""
|
||||||
|
return self.nand.getContentHashesFromContentMap(cnt)
|
||||||
|
def AddTitleStart(self, tmd, certs, crl, is_decrypted = False, result_decrypted = True, use_version = False):
|
||||||
|
self.nand.addTitleToUIDSYS(tmd.tmd.titleid)
|
||||||
|
self.nand.newDirectory("/title/%08x" % (tmd.tmd.titleid >> 32), "rwrwr-", 0x0000)
|
||||||
|
self.nand.newDirectory("/title/%08x/%08x" % (tmd.tmd.titleid >> 32, tmd.tmd.titleid & 0xFFFFFFFF), "rwrwr-", 0x0000)
|
||||||
|
self.nand.newDirectory("/title/%08x/%08x/content" % (tmd.tmd.titleid >> 32, tmd.tmd.titleid & 0xFFFFFFFF), "rwrw--", 0x0000)
|
||||||
|
self.nand.newDirectory("/title/%08x/%08x/data" % (tmd.tmd.titleid >> 32, tmd.tmd.titleid & 0xFFFFFFFF), "rw----", tmd.tmd.group_id, tmd.tmd.titleid)
|
||||||
|
self.nand.newDirectory("/ticket/%08x" % (tmd.tmd.titleid >> 32), "rwrw--", 0x0000)
|
||||||
|
self.workingcids = array.array('L')
|
||||||
|
self.wtitleid = tmd.tmd.titleid
|
||||||
|
self.is_decrypted = is_decrypted
|
||||||
|
self.result_decrypted = result_decrypted
|
||||||
|
self.use_version = use_version
|
||||||
|
return
|
||||||
|
def AddTicket(self, tik):
|
||||||
|
"""Adds ticket to the title being added."""
|
||||||
|
tik.dumpFile(self.f + "/tmp/title.tik")
|
||||||
|
self.ticketadded = 1
|
||||||
|
def DeleteTicket(self, tikview):
|
||||||
|
"""Deletes the ticket relating to tikview
|
||||||
|
(UNIMPLEMENTED!)"""
|
||||||
|
return
|
||||||
|
def AddTitleTMD(self, tmd):
|
||||||
|
"""Adds TMD to the title being added."""
|
||||||
|
tmd.dumpFile(self.f + "/tmp/title.tmd")
|
||||||
|
self.tmdadded = 1
|
||||||
|
def AddContentStart(self, titleid, cid):
|
||||||
|
"""Starts adding a content with content id cid to the title being added with ID titleid."""
|
||||||
|
if((self.workingcid != 0) and (self.workingcid != None)):
|
||||||
|
"Trying to start an already existing process"
|
||||||
|
return -41
|
||||||
|
if(self.tmdadded):
|
||||||
|
a = TMD.loadFile(self.f + "/tmp/title.tmd")
|
||||||
|
else:
|
||||||
|
a = TMD.loadFile(self.f + "/title/%08x/%08x/content/title.tmd.%d" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF, tmd.tmd.title_version))
|
||||||
|
x = self.getContentIndexFromCID(a, cid)
|
||||||
|
if(x == None):
|
||||||
|
"Not a valid Content ID"
|
||||||
|
return -43
|
||||||
|
self.workingcid = cid
|
||||||
|
self.workingfp = open(self.f + "/tmp/%08x.app" % cid, "wb")
|
||||||
|
return 0
|
||||||
|
def AddContentData(self, cid, data):
|
||||||
|
"""Adds data to the content cid being added."""
|
||||||
|
if(cid != self.workingcid):
|
||||||
|
"Working on the not current CID"
|
||||||
|
return -40
|
||||||
|
self.workingfp.write(data);
|
||||||
|
return 0
|
||||||
|
def AddContentFinish(self, cid):
|
||||||
|
"""Finishes the content cid being added."""
|
||||||
|
if(cid != self.workingcid):
|
||||||
|
"Working on the not current CID"
|
||||||
|
return -40
|
||||||
|
self.workingfp.close()
|
||||||
|
self.workingcids.append(cid)
|
||||||
|
self.workingcidcnt += 1
|
||||||
|
self.workingcid = None
|
||||||
|
return 0
|
||||||
|
def AddTitleCancel(self):
|
||||||
|
"""Cancels adding a title (deletes the tmp files and resets status)."""
|
||||||
|
if(self.ticketadded):
|
||||||
|
self.nand.removeFile("/tmp/title.tik")
|
||||||
|
self.ticketadded = 0
|
||||||
|
if(self.tmdadded):
|
||||||
|
self.nand.removeFile("/tmp/title.tmd")
|
||||||
|
self.tmdadded = 0
|
||||||
|
for i in range(self.workingcidcnt):
|
||||||
|
self.nand.removeFile("/tmp/%08x.app" % self.workingcids[i])
|
||||||
|
self.workingcidcnt = 0
|
||||||
|
self.workingcid = None
|
||||||
|
def AddTitleFinish(self):
|
||||||
|
"""Finishes the adding of a title."""
|
||||||
|
if(self.ticketadded):
|
||||||
|
tik = Ticket.loadFile(self.f + "/tmp/title.tik")
|
||||||
|
else:
|
||||||
|
tik = Ticket.loadFile(self.f + "/ticket/%08x/%08x.tik" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
||||||
|
if(self.tmdadded):
|
||||||
|
tmd = TMD.loadFile(self.f + "/tmp/title.tmd")
|
||||||
|
contents = tmd.getContents()
|
||||||
|
for i in range(self.workingcidcnt):
|
||||||
|
idx = self.getContentIndexFromCID(tmd, self.workingcids[i])
|
||||||
|
if(idx == None):
|
||||||
|
print "Content ID doesn't exist!"
|
||||||
|
return -42
|
||||||
|
fp = open(self.f + "/tmp/%08x.app" % self.workingcids[i], "rb")
|
||||||
|
if(contents[idx].type == 0x0001):
|
||||||
|
filestr = "/title/%08x/%08x/content/%08x.app" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF, self.workingcids[i])
|
||||||
|
elif(contents[idx].type == 0x8001):
|
||||||
|
num = self.nand.addHashToContentMap(contents[idx].hash)
|
||||||
|
filestr = "/shared1/%08x.app" % num
|
||||||
|
self.nand.newFile(filestr, "rwrw--", 0x0000)
|
||||||
|
outfp = open(self.f + filestr, "wb")
|
||||||
|
data = fp.read()
|
||||||
|
titlekey = tik.getTitleKey()
|
||||||
|
if(self.is_decrypted):
|
||||||
|
tmpdata = data
|
||||||
|
else:
|
||||||
|
tmpdata = Crypto().decryptContent(titlekey, contents[idx].index, data)
|
||||||
|
if(Crypto().validateSHAHash(tmpdata, contents[idx].hash) == 0):
|
||||||
|
"Decryption failed! SHA1 mismatch."
|
||||||
|
return -44
|
||||||
|
if(self.result_decrypted != True):
|
||||||
|
if(self.is_decrypted):
|
||||||
|
tmpdata = Crypto().encryptContent(titlekey, contents[idx].index, data)
|
||||||
|
else:
|
||||||
|
tmpdata = data
|
||||||
|
|
||||||
|
fp.close()
|
||||||
|
outfp.write(tmpdata)
|
||||||
|
outfp.close()
|
||||||
|
if(self.tmdadded and self.use_version):
|
||||||
|
self.nand.newFile("/title/%08x/%08x/content/title.tmd.%d" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF, tmd.tmd.title_version), "rwrw--", 0x0000)
|
||||||
|
tmd.dumpFile(self.f + "/title/%08x/%08x/content/title.tmd.%d" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF, tmd.tmd.title_version))
|
||||||
|
elif(self.tmdadded):
|
||||||
|
self.nand.newFile("/title/%08x/%08x/content/title.tmd" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF), "rwrw--", 0x0000)
|
||||||
|
tmd.dumpFile(self.f + "/title/%08x/%08x/content/title.tmd" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
||||||
|
if(self.ticketadded):
|
||||||
|
self.nand.newFile("/ticket/%08x/%08x.tik" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF), "rwrw--", 0x0000)
|
||||||
|
tik.dumpFile(self.f + "/ticket/%08x/%08x.tik" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
||||||
|
self.AddTitleCancel()
|
||||||
|
return 0
|
0
WiiPy/tests/__init__.py
Normal file
0
WiiPy/tests/__init__.py
Normal file
95
WiiPy/tests/bannerbin.py
Normal file
95
WiiPy/tests/bannerbin.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import Wii, os, sys, shutil
|
||||||
|
|
||||||
|
def packbanner()
|
||||||
|
bannerbin = U8()
|
||||||
|
bannerbin['arc'] = None #dir
|
||||||
|
bannerbin['arc/blyt'] = None
|
||||||
|
bannerbin['arc/anim'] = None
|
||||||
|
bannerbin['arc/timg'] = None
|
||||||
|
# then do
|
||||||
|
origdir = os.getcwd()
|
||||||
|
for files in os.walk(origdir + 'arc/timg/')
|
||||||
|
bannerbin['arc/timg/' + file] = open(file, "rb").read()
|
||||||
|
for files in os.walk(origdir + 'arc/anim/')
|
||||||
|
bannerbin['arc/anim/' + file] = open(file, "rb").read()
|
||||||
|
for files in os.walk(origdir + 'arc/blyt/')
|
||||||
|
bannerbin['arc/blyt/' + file] = open(file, "rb").read()
|
||||||
|
fn = open("banner.bin", "w+b")
|
||||||
|
fn.write(u8object.dumpFile())
|
||||||
|
fn.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def doPack():
|
||||||
|
exchange = [sys.argv[2], sys.argv[3], sys.argv[4]]
|
||||||
|
global banneru8, iconu8
|
||||||
|
|
||||||
|
print "Unpacking WAD..."
|
||||||
|
wad = wii.WAD.loadFile("squid.wad")
|
||||||
|
|
||||||
|
title = wii.IMET(wad[0]).getTitle()
|
||||||
|
print "Unpacking 00000000.app..."
|
||||||
|
wad[0] = wii.IMET(wad[0]).remove()
|
||||||
|
|
||||||
|
meta = wii.U8.load(wad[0])
|
||||||
|
|
||||||
|
prog = 20
|
||||||
|
for i, item in enumerate(exchange):
|
||||||
|
if(item == ""): #skip what doesn't get changed
|
||||||
|
continue
|
||||||
|
if(i == 0):
|
||||||
|
bin = "banner"
|
||||||
|
print "Replacing banner.bin..."
|
||||||
|
elif(i == 1):
|
||||||
|
bin = "icon"
|
||||||
|
print "Replacing icon.bin..."
|
||||||
|
else:
|
||||||
|
bin = "sound"
|
||||||
|
print "Replacing sound.bin..."
|
||||||
|
|
||||||
|
if(item[len(item) - 3:] == "app" or item[len(item) - 3:] == "bnr" or item[len(item - 3):] == "wad"):
|
||||||
|
if(item[len(item) - 3:] == "wad"):
|
||||||
|
wad2 = wii.WAD.loadFile(item)
|
||||||
|
wad2[0] = wii.IMET(wad2[0]).remove()
|
||||||
|
meta2 = wii.U8.load(wad2[0])
|
||||||
|
else:
|
||||||
|
meta2 = wii.IMET.loadFile(item).remove()
|
||||||
|
bin2 = meta2['meta/%s.bin' % bin]
|
||||||
|
elif(item[len(item) - 3:] == "bin"):
|
||||||
|
bin2 = wii.U8.loadFile(item)
|
||||||
|
else:
|
||||||
|
continue #only bin, wad, bnr and app are supported
|
||||||
|
meta['arc/%s.bin' % bin] = bin2.dump()
|
||||||
|
|
||||||
|
print "Unpacking banner.bin..."
|
||||||
|
meta['meta/banner.bin'] = wii.IMD5(meta['meta/banner.bin']).remove()
|
||||||
|
meta['meta/banner.bin'] = wii.LZ77(meta['meta/banner.bin']).remove()
|
||||||
|
banneru8 = wii.U8.load(meta['meta/banner.bin'])
|
||||||
|
|
||||||
|
print "Unpacking icon.bin..."
|
||||||
|
meta['meta/icon.bin'] = wii.IMD5(meta['meta/icon.bin']).remove()
|
||||||
|
meta['meta/icon.bin'] = wii.LZ77(meta['meta/icon.bin']).remove()
|
||||||
|
iconu8 = wii.U8.load(meta['meta/icon.bin'])
|
||||||
|
|
||||||
|
print "Packing banner.bin..."
|
||||||
|
meta['meta/banner.bin'] = banneru8.dump()
|
||||||
|
meta['meta/banner.bin'] = wii.IMD5(meta['meta/banner.bin']).add()
|
||||||
|
|
||||||
|
print "Packing icon.bin..."
|
||||||
|
meta['meta/icon.bin'] = iconu8.dump()
|
||||||
|
meta['meta/icon.bin'] = wii.IMD5(meta['meta/icon.bin']).add()
|
||||||
|
|
||||||
|
print "Packing 00000000.app..."
|
||||||
|
|
||||||
|
#meta['meta/sound.bin'] = open('wadunpack/00000000_app_out/meta/sound.bin', 'rb').read()
|
||||||
|
langs = []
|
||||||
|
wad[0] = meta.dump()
|
||||||
|
wad[0] = wii.IMET(wad[0]).add(len(meta['meta/icon.bin']), len(meta['meta/banner.bin']), len(meta['meta/sound.bin']), title, langs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print "Packing WAD..."
|
||||||
|
wad.dumpFile("squid.wad")
|
||||||
|
|
||||||
|
packbanner()
|
||||||
|
doPack()
|
30
WiiPy/tests/fakesign.py
Normal file
30
WiiPy/tests/fakesign.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from disc import *
|
||||||
|
from title import *
|
||||||
|
from Struct import Struct
|
||||||
|
import os
|
||||||
|
|
||||||
|
def fakesignPartition(self, iso, index)
|
||||||
|
iso = WOD(iso)
|
||||||
|
iso.openPartition(index)
|
||||||
|
fstBuf = iso.getFst() "
|
||||||
|
fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'appldr.bin', 'w+b')
|
||||||
|
fn.write(iso.getPartitionApploader()) #saved to cwd/GAMEID/PARTITION/file
|
||||||
|
fn.close()
|
||||||
|
fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'h3.bin', 'w+b')
|
||||||
|
fn.write(iso.getPartitionH3Table())
|
||||||
|
fn.close()
|
||||||
|
fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'main.dol', 'w+b')
|
||||||
|
fn.write(iso.getPartitionMainDol())
|
||||||
|
fn.close()
|
||||||
|
fn = open(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + 'fst.bin', 'w+b')
|
||||||
|
fn.write(fstBuf)
|
||||||
|
fn.close()
|
||||||
|
fileNumber = struct.unpack(">I", fstBuf[0x8:0xc])[0]
|
||||||
|
fileObject = iso.fstObject("", iso)
|
||||||
|
iso.parseFst(fstBuf, fstBuf[12 * fileNumber:], 0, fileObject)
|
||||||
|
fileObject.write(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/")
|
||||||
|
fileObject.close()
|
||||||
|
isoTik = Ticket(iso.getPartitionTik())
|
||||||
|
isoTik.dump(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + "tik")
|
||||||
|
isoTMD = TMD(iso.getPartitionTmd())
|
||||||
|
isoTMD.dump(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region + "/" + "PART" + index + "/" + "tmd")
|
5
WiiPy/tests/imd5sign.py
Normal file
5
WiiPy/tests/imd5sign.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import Wii
|
||||||
|
import sys
|
||||||
|
|
||||||
|
for elem in sys.argv:
|
||||||
|
Wii.IMD5(elem).add(elem)
|
26
WiiPy/tests/sysmenu.py
Normal file
26
WiiPy/tests/sysmenu.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import os, Wii
|
||||||
|
|
||||||
|
print 'Enter the sysmenu version you want then just wait...'
|
||||||
|
version = int(input()) #97
|
||||||
|
#Wii.NUS(0x0000000100000002, version).download('0000000100000002ver' + str(version))
|
||||||
|
os.chdir('0000000100000002ver' + str(version))
|
||||||
|
print 'Tmd dump :\n'
|
||||||
|
print '%s' % Wii.TMD().loadFile('tmd')
|
||||||
|
print 'Now unpacking all the archives in there :3\n'
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(os.getcwd()):
|
||||||
|
for name in files:
|
||||||
|
print '%s' % name
|
||||||
|
location = os.getcwd() + '/' + str(name)
|
||||||
|
if name == '00000000.app':
|
||||||
|
print 'IMET Title : %s' % Wii.IMET(name).getTitle()
|
||||||
|
if open(location).read(4) == '\x55\xaa\x38\x2d':
|
||||||
|
print 'Now unpacking the u8 archive %s' % location
|
||||||
|
try:
|
||||||
|
Wii.U8().loadFile(location)
|
||||||
|
except:
|
||||||
|
print "fix the U8 code!"
|
||||||
|
if open(location).read(4) == '\x43\x43\x46\x00':
|
||||||
|
print 'Now unpacking the CCF archive %s' % location
|
||||||
|
Wii.CCF(location).decompress()
|
||||||
|
|
10
WiiPy/tests/sysmenuUnpack.py
Normal file
10
WiiPy/tests/sysmenuUnpack.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import os
|
||||||
|
from U8 import *
|
||||||
|
from title import WAD
|
||||||
|
|
||||||
|
sysmenuWad = WAD('/home/giuseppe/Scrivania/RVL-WiiSystemmenu-v258.wad')
|
||||||
|
sysmenuWad.unpack('/home/giuseppe/Scrivania/sysdump')
|
||||||
|
|
||||||
|
for file in os.listdir('/home/giuseppe/Scrivania/sysdump'):
|
||||||
|
if open('/home/giuseppe/Scrivania/sysdump/' + file).read(4) == '\x55\xaa\x38\x2d':
|
||||||
|
U8('/home/giuseppe/Scrivania/sysdump/' + file).unpack('/home/giuseppe/Scrivania/sysdump/' + file + '_decompressed/')
|
25
WiiPy/tests/testDISC.py
Normal file
25
WiiPy/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
|
9
WiiPy/tests/testLOC.py
Normal file
9
WiiPy/tests/testLOC.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from formats import locDat
|
||||||
|
|
||||||
|
sdLoc = locDat('/home/giuseppe/Scrivania/sysmenu/loc.dat')
|
||||||
|
|
||||||
|
print '%s' % sdLoc
|
||||||
|
|
||||||
|
#concorsiMii = sdLoc.getTitle(0, 0, 0)
|
||||||
|
sdLoc.delTitle(0, 0, 0)
|
||||||
|
|
9
WiiPy/tests/testSAVE.py
Normal file
9
WiiPy/tests/testSAVE.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from savedata import *
|
||||||
|
|
||||||
|
save = Savegame('/home/giuseppe/Scrivania/data' + str(4) + '.bin')
|
||||||
|
save.analyzeHeader()
|
||||||
|
print '%s' % save
|
||||||
|
save.getBanner()
|
||||||
|
for i in range(save.getIconsCount()):
|
||||||
|
save.getIcon(i)
|
||||||
|
save.extractFiles()
|
314
WiiPy/title.py
Normal file
314
WiiPy/title.py
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
from common import *
|
||||||
|
|
||||||
|
class TicketView:
|
||||||
|
"""Creates a ticket view from the Ticket object ``tik''."""
|
||||||
|
class TikviewStruct(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.view = Struct.uint32
|
||||||
|
self.ticketid = Struct.uint64
|
||||||
|
self.devicetype = Struct.uint32
|
||||||
|
self.titleid = Struct.uint64
|
||||||
|
self.accessmask = Struct.uint16
|
||||||
|
self.reserved = Struct.string(0x3C)
|
||||||
|
self.cidxmask = Struct.string(0x40)
|
||||||
|
self.padding = Struct.uint16
|
||||||
|
self.limits = Struct.string(96)
|
||||||
|
|
||||||
|
def __init__(self, tik):
|
||||||
|
self.tikview = self.TikviewStruct()
|
||||||
|
self.tikview.view = 0
|
||||||
|
self.tikview.ticketid = tik.tik.tikid
|
||||||
|
self.tikview.devicetype = tik.tik.console
|
||||||
|
self.tikview.titleid = tik.getTitleID()
|
||||||
|
self.tikview.accessmask = 0xFFFF # This needs to be changed, I'm sure...
|
||||||
|
self.tikview.reserved = "\0" * 0x3C
|
||||||
|
self.tikview.cidxmask = "\xFF" * 0x40 # This needs to be changed, I'm sure...
|
||||||
|
self.tikview.padding = 0x0000
|
||||||
|
self.tikview.limits = "\0" * 96
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
out = ""
|
||||||
|
out += " Ticket View:\n"
|
||||||
|
out += " Title ID: %08X-%08X\n" % (self.tikview.titleid >> 32, self.tikview.titleid & 0xFFFFFFFF)
|
||||||
|
out += " Device type: %08X\n" % self.tikview.devicetype
|
||||||
|
out += " Ticket ID: %016X\n" % self.tikview.ticketid
|
||||||
|
out += " Access Mask: %04X\n" % self.tikview.accessmask
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
class Ticket(WiiObject):
|
||||||
|
"""Creates a ticket from the filename defined in f. This may take a longer amount of time than expected, as it also decrypts the title key. Now supports Korean tickets (but their title keys stay Korean on dump)."""
|
||||||
|
class TicketStruct(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.rsaexp = Struct.uint32
|
||||||
|
self.rsamod = Struct.string(256)
|
||||||
|
self.padding1 = Struct.string(60)
|
||||||
|
self.rsaid = Struct.string(64)
|
||||||
|
self.padding2 = Struct.string(63)
|
||||||
|
self.enctitlekey = Struct.string(16)
|
||||||
|
self.unk1 = Struct.uint8
|
||||||
|
self.tikid = Struct.uint64
|
||||||
|
self.console = Struct.uint32
|
||||||
|
self.titleid = Struct.uint64
|
||||||
|
self.unk2 = Struct.uint16
|
||||||
|
self.dlc = Struct.uint16
|
||||||
|
self.unk3 = Struct.uint64
|
||||||
|
self.commonkey_index = Struct.uint8
|
||||||
|
self.reserved = Struct.string(80)
|
||||||
|
self.unk3 = Struct.uint16
|
||||||
|
self.limits = Struct.string(96)
|
||||||
|
self.unk4 = Struct.uint8
|
||||||
|
def __init__(self):
|
||||||
|
self.tik = self.TicketStruct()
|
||||||
|
|
||||||
|
self.tik.rsaexp = 0x10001
|
||||||
|
self.tik.rsamod = "\x00" * 256
|
||||||
|
self.tik.padding1 = "\x00" * 60
|
||||||
|
self.tik.rsaid = "\x00" * 64
|
||||||
|
self.tik.padding2 = "\x00" * 63
|
||||||
|
self.tik.enctitlekey = "\x00" * 16
|
||||||
|
self.tik.titleid = 0x0000000100000000
|
||||||
|
self.tik.reserved = "\x00" * 80
|
||||||
|
self.tik.limits = "\x00" * 96
|
||||||
|
|
||||||
|
commonkey = "\xEB\xE4\x2A\x22\x5E\x85\x93\xE4\x48\xD9\xC5\x45\x73\x81\xAA\xF7"
|
||||||
|
koreankey = "\x63\xB8\x2B\xB4\xF4\x61\x4E\x2E\x13\xF2\xFE\xFB\xBA\x4C\x9B\x7E"
|
||||||
|
|
||||||
|
if(self.tik.commonkey_index == 1): #korean, kekekekek!
|
||||||
|
commonkey = koreankey
|
||||||
|
self.titlekey = Crypto().decryptTitleKey(commonkey, self.tik.titleid, self.tik.enctitlekey)
|
||||||
|
def _load(self, data):
|
||||||
|
self.tik.unpack(data[:len(self.tik)])
|
||||||
|
|
||||||
|
commonkey = "\xEB\xE4\x2A\x22\x5E\x85\x93\xE4\x48\xD9\xC5\x45\x73\x81\xAA\xF7"
|
||||||
|
koreankey = "\x63\xB8\x2B\xB4\xF4\x61\x4E\x2E\x13\xF2\xFE\xFB\xBA\x4C\x9B\x7E"
|
||||||
|
|
||||||
|
if(self.tik.commonkey_index == 1): #korean, kekekekek!
|
||||||
|
commonkey = koreankey
|
||||||
|
|
||||||
|
self.titlekey = Crypto().decryptTitleKey(commonkey, self.tik.titleid, self.tik.enctitlekey)
|
||||||
|
return self
|
||||||
|
def getTitleKey(self):
|
||||||
|
"""Returns a string containing the title key."""
|
||||||
|
return self.titlekey
|
||||||
|
def getTitleID(self):
|
||||||
|
"""Returns a long integer with the title id."""
|
||||||
|
return self.tik.titleid
|
||||||
|
def setTitleID(self, titleid):
|
||||||
|
"""Sets the title id of the ticket from the long integer passed in titleid."""
|
||||||
|
self.tik.titleid = titleid
|
||||||
|
commonkey = "\xEB\xE4\x2A\x22\x5E\x85\x93\xE4\x48\xD9\xC5\x45\x73\x81\xAA\xF7"
|
||||||
|
koreankey = "\x63\xB8\x2B\xB4\xF4\x61\x4E\x2E\x13\xF2\xFE\xFB\xBA\x4C\x9B\x7E"
|
||||||
|
|
||||||
|
if(self.tik.commonkey_index == 1): #korean, kekekekek!
|
||||||
|
commonkey = koreankey
|
||||||
|
self.titlekey = Crypto().decryptTitleKey(commonkey, self.tik.titleid, self.tik.enctitlekey) #This changes the decrypted title key!
|
||||||
|
def __str__(self):
|
||||||
|
out = ""
|
||||||
|
out += " Ticket:\n"
|
||||||
|
out += " Title ID: %08x-%08x\n" % (self.getTitleID() >> 32, self.getTitleID() & 0xFFFFFFFF)
|
||||||
|
|
||||||
|
out += " Title key IV: "
|
||||||
|
out += hexdump(struct.pack(">Q", self.getTitleID()) + "\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
out += "\n"
|
||||||
|
|
||||||
|
out += " Title key (encrypted): "
|
||||||
|
out += hexdump(self.tik.enctitlekey)
|
||||||
|
out += "\n"
|
||||||
|
|
||||||
|
out += " Title key (decrypted): "
|
||||||
|
out += hexdump(self.getTitleKey())
|
||||||
|
out += "\n"
|
||||||
|
|
||||||
|
return out
|
||||||
|
def fakesign(self):
|
||||||
|
"""Fakesigns (or Trucha signs) and dumps the ticket to either fn, if not empty, or overwriting the source if empty. Returns the output filename."""
|
||||||
|
self.rsamod = self.rsamod = "\x00" * 256
|
||||||
|
for i in range(65536):
|
||||||
|
self.tik.unk2 = i
|
||||||
|
if(Crypto().createSHAHashHex(self.tik.pack())[:2] == "00"):
|
||||||
|
break
|
||||||
|
if(i == 65535):
|
||||||
|
raise ValueError("Failed to fakesign. Aborting...")
|
||||||
|
def _dump(self):
|
||||||
|
"""Dumps the ticket to either fn, if not empty, or overwriting the source if empty. **Does not fakesign.** Returns the output filename."""
|
||||||
|
return self.tik.pack()
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.tik)
|
||||||
|
|
||||||
|
class TMD(WiiObject):
|
||||||
|
"""This class allows you to edit TMDs. TMD (Title Metadata) files are used in many places to hold information about titles. The parameter f to the initialization is the filename to open and create a TMD from."""
|
||||||
|
class TMDContent(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.cid = Struct.uint32
|
||||||
|
self.index = Struct.uint16
|
||||||
|
self.type = Struct.uint16
|
||||||
|
self.size = Struct.uint64
|
||||||
|
self.hash = Struct.string(20)
|
||||||
|
class TMDStruct(Struct):
|
||||||
|
__endian__ = Struct.BE
|
||||||
|
def __format__(self):
|
||||||
|
self.rsaexp = Struct.uint32
|
||||||
|
self.rsamod = Struct.string(256)
|
||||||
|
self.padding1 = Struct.string(60)
|
||||||
|
self.rsaid = Struct.string(64)
|
||||||
|
self.version = Struct.uint8[4]
|
||||||
|
self.iosversion = Struct.uint64
|
||||||
|
self.titleid = Struct.uint64
|
||||||
|
self.title_type = Struct.uint32
|
||||||
|
self.group_id = Struct.uint16
|
||||||
|
self.reserved = Struct.string(62)
|
||||||
|
self.access_rights = Struct.uint32
|
||||||
|
self.title_version = Struct.uint16
|
||||||
|
self.numcontents = Struct.uint16
|
||||||
|
self.boot_index = Struct.uint16
|
||||||
|
self.padding2 = Struct.uint16
|
||||||
|
#contents follow this
|
||||||
|
def _load(self, data):
|
||||||
|
self.tmd.unpack(data[:len(self.tmd)])
|
||||||
|
pos = len(self.tmd)
|
||||||
|
for i in range(self.tmd.numcontents):
|
||||||
|
cont = self.TMDContent()
|
||||||
|
cont.unpack(data[pos:pos + len(cont)])
|
||||||
|
pos += len(cont)
|
||||||
|
self.contents.append(cont)
|
||||||
|
def __init__(self):
|
||||||
|
self.tmd = self.TMDStruct()
|
||||||
|
self.tmd.titleid = 0x0000000100000000
|
||||||
|
self.contents = []
|
||||||
|
def getContents(self):
|
||||||
|
"""Returns a list of contents. Each content is an object with the members "size", the size of the content's decrypted data; "cid", the content id; "type", the type of the content (0x8001 for shared, 0x0001 for standard, more possible), and a 20 byte string called "hash"."""
|
||||||
|
return self.contents
|
||||||
|
def setContents(self, contents):
|
||||||
|
"""This sets the contents in the TMD to the contents you provide in the contents parameter. Also updates the TMD to the appropraite amount of contents."""
|
||||||
|
self.contents = contents
|
||||||
|
self.tmd.numcontents = len(contents)
|
||||||
|
def __str__(self):
|
||||||
|
out = ""
|
||||||
|
out += " TMD:\n"
|
||||||
|
out += " Versions: (todo) %u, CA CRL (todo) %u, Signer CRL (todo) %u, System %u-%u\n" % (0, 0, 0, self.getIOSVersion() >> 32, self.getIOSVersion() & 0xFFFFFFFF)
|
||||||
|
out += " Title ID: %08x-%08x\n" % (self.getTitleID() >> 32, self.getTitleID() & 0xFFFFFFFF)
|
||||||
|
out += " Title Type: %u\n" % self.tmd.title_type
|
||||||
|
out += " Group ID: '%02u'\n" % self.tmd.group_id
|
||||||
|
out += " Access Rights: 0x%08x\n" % self.tmd.access_rights
|
||||||
|
out += " Title Version: 0x%04x\n" % self.tmd.title_version
|
||||||
|
out += " Boot Index: %u\n" % self.getBootIndex()
|
||||||
|
out += " Contents: \n"
|
||||||
|
|
||||||
|
out += " ID Index Type Size Hash\n"
|
||||||
|
contents = self.getContents()
|
||||||
|
for i in range(len(contents)):
|
||||||
|
out += " %08X %-4u 0x%04x %#-12x " % (contents[i].cid, contents[i].index, contents[i].type, contents[i].size)
|
||||||
|
out += hexdump(contents[i].hash)
|
||||||
|
out += "\n"
|
||||||
|
|
||||||
|
return out
|
||||||
|
def __len__(self):
|
||||||
|
contents = self.getContents()
|
||||||
|
sz = len(self.tmd)
|
||||||
|
for i in range(len(contents)):
|
||||||
|
sz += len(contents[i])
|
||||||
|
return sz
|
||||||
|
def fakesign(self):
|
||||||
|
"""Dumps the TMD to the filename specified in fn, if not empty. If that is empty, it overwrites the original. This fakesigns the TMD, but does not update the hashes and the sizes, that is left as a job for you. Returns output filename."""
|
||||||
|
for i in range(65536):
|
||||||
|
self.tmd.padding2 = i
|
||||||
|
|
||||||
|
data = "" #gotta reset it every time
|
||||||
|
data += self.tmd.pack()
|
||||||
|
for i in range(self.tmd.numcontents):
|
||||||
|
data += self.contents[i].pack()
|
||||||
|
if(Crypto().createSHAHashHex(data)[:2] == "00"):
|
||||||
|
break
|
||||||
|
if(i == 65535):
|
||||||
|
raise ValueError("Failed to fakesign! Aborting...")
|
||||||
|
def _dump(self):
|
||||||
|
"""Same as the :dump: function, but does not fakesign the TMD. Also returns output filename."""
|
||||||
|
data = ""
|
||||||
|
data += self.tmd.pack()
|
||||||
|
for i in range(self.tmd.numcontents):
|
||||||
|
data += self.contents[i].pack()
|
||||||
|
|
||||||
|
return data
|
||||||
|
def getTitleID(self):
|
||||||
|
"""Returns the long integer title id."""
|
||||||
|
return self.tmd.titleid
|
||||||
|
def setTitleID(self, titleid):
|
||||||
|
"""Sets the title id to the long integer specified in the parameter titleid."""
|
||||||
|
self.tmd.titleid = titleid
|
||||||
|
def getIOSVersion(self):
|
||||||
|
"""Returns the IOS version the title will run off of."""
|
||||||
|
return self.tmd.iosversion
|
||||||
|
def setIOSVersion(self, version):
|
||||||
|
"""Sets the IOS version the title will run off of to the arguement version."""
|
||||||
|
self.tmd.iosverison = version
|
||||||
|
def getBootIndex(self):
|
||||||
|
"""Returns the boot index of the TMD."""
|
||||||
|
return self.tmd.boot_index
|
||||||
|
def setBootIndex(self, index):
|
||||||
|
"""Sets the boot index of the TMD to the value of index."""
|
||||||
|
self.tmd.boot_index = index
|
||||||
|
|
||||||
|
class NUS:
|
||||||
|
"""This class can download titles from NUS, or Nintendo Update Server. The titleid parameter is the long integer version of the title to download. The version parameter is optional and specifies the version to download. If version is not given, it is assumed to be the latest version on NUS."""
|
||||||
|
def __init__(self, titleid, version = None):
|
||||||
|
self.titleid = titleid
|
||||||
|
self.baseurl = "http://nus.cdn.shop.wii.com/ccs/download/%08x%08x/" % (titleid >> 32, titleid & 0xFFFFFFFF)
|
||||||
|
self.version = version
|
||||||
|
def download(self, fn = "", decrypt = True, useidx = True):
|
||||||
|
"""This will download a title from NUS into a directory either specified by fn (if it is not empty) or a directory created by the title id in hex form. If decrypt is true, it will decrypt the contents, otherwise it will not. A certs file is always created to enable easy WAD Packing. The parameter useidx specifies wheither to use the index or the content id for the file naming (default is index)."""
|
||||||
|
if(fn == ""):
|
||||||
|
fn = "%08x%08x" % (self.titleid >> 32, self.titleid & 0xFFFFFFFF)
|
||||||
|
try:
|
||||||
|
os.mkdir(fn)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
os.chdir(fn)
|
||||||
|
|
||||||
|
certs = ""
|
||||||
|
rawtmd = urllib.urlopen("http://nus.cdn.shop.wii.com/ccs/download/0000000100000002/tmd.289").read()
|
||||||
|
rawtik = urllib.urlopen("http://nus.cdn.shop.wii.com/ccs/download/0000000100000002/cetk").read()
|
||||||
|
|
||||||
|
certs += rawtik[0x2A4:0x2A4 + 0x300] #XS
|
||||||
|
certs += rawtik[0x2A4 + 0x300:] #CA (tik)
|
||||||
|
certs += rawtmd[0x328:0x328 + 0x300] #CP
|
||||||
|
|
||||||
|
if(Crypto().createMD5HashHex(certs) != "7ff50e2733f7a6be1677b6f6c9b625dd"):
|
||||||
|
raise ValueError("Failed to create certs! MD5 mistatch.")
|
||||||
|
|
||||||
|
open("cert", "wb").write(certs)
|
||||||
|
|
||||||
|
if(self.version == None):
|
||||||
|
versionstring = ""
|
||||||
|
else:
|
||||||
|
versionstring = ".%u" % self.version
|
||||||
|
|
||||||
|
urllib.urlretrieve(self.baseurl + "tmd" + versionstring, "tmd")
|
||||||
|
tmd = TMD.loadFile("tmd")
|
||||||
|
tmd.dumpFile("tmd") # strip certs
|
||||||
|
|
||||||
|
urllib.urlretrieve(self.baseurl + "cetk", "tik")
|
||||||
|
tik = Ticket.loadFile("tik")
|
||||||
|
tik.dumpFile("tik") # strip certs
|
||||||
|
if(decrypt):
|
||||||
|
titlekey = tik.getTitleKey()
|
||||||
|
|
||||||
|
contents = tmd.getContents()
|
||||||
|
for content in contents:
|
||||||
|
output = content.cid
|
||||||
|
if(useidx):
|
||||||
|
output = content.index
|
||||||
|
|
||||||
|
urllib.urlretrieve(self.baseurl + ("%08x" % content.cid), "%08x.app" % output)
|
||||||
|
|
||||||
|
if(decrypt):
|
||||||
|
data = open("%08x.app" % output, "rb").read(content.size)
|
||||||
|
tmpdata = Crypto().decryptContent(titlekey, content.index, data)
|
||||||
|
if(Crypto().validateSHAHash(tmpdata, content.hash) == 0):
|
||||||
|
raise ValueError("Decryption failed! SHA1 mismatch.")
|
||||||
|
open("%08x.app" % output, "wb").write(tmpdata)
|
||||||
|
|
||||||
|
os.chdir("..")
|
51
WiiPy/tools/NUStool.py
Normal file
51
WiiPy/tools/NUStool.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#----------------------------------------------------------------------
|
||||||
|
# NUS Tool - a simple command line tool for NUS downloading.
|
||||||
|
# (c) 2009 |Omega and #HACKERCHANNEL Productions.
|
||||||
|
#
|
||||||
|
# Wii.py (c) Xuzz, SquidMan, megazig, TheLemonMan, |Omega, and Matt_P.
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
import os, sys, Wii, shutil
|
||||||
|
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print "Usage: python %s -(d/p) titleid version [decrypt/fakesign](True/False) [download/pack](dirname/filename)" % sys.argv[0]
|
||||||
|
sys.exit()
|
||||||
|
print sys.argv
|
||||||
|
titleid = int(sys.argv[2], 16)
|
||||||
|
print titleid
|
||||||
|
ver = int(sys.argv[3])
|
||||||
|
print type(ver)
|
||||||
|
print ver
|
||||||
|
if not (sys.argv[4]) and sys.argv[1] == "-d" :
|
||||||
|
decrypt = False
|
||||||
|
else:
|
||||||
|
decrypt = True
|
||||||
|
|
||||||
|
if len(sys.argv) < 6:
|
||||||
|
tmp = "tmp"
|
||||||
|
else:
|
||||||
|
tmp = sys.argv[5]
|
||||||
|
|
||||||
|
#downloading
|
||||||
|
|
||||||
|
print "Downloading..."
|
||||||
|
if(ver != 0):
|
||||||
|
Wii.NUS(titleid, ver).download(tmp, decrypt = decrypt)
|
||||||
|
else:
|
||||||
|
Wii.NUS(titleid).download(tmp, decrypt = decrypt)
|
||||||
|
print "Done downloading!"
|
||||||
|
|
||||||
|
#wadpacking
|
||||||
|
|
||||||
|
if sys.argv[1] == "-p":
|
||||||
|
print "packing"
|
||||||
|
if len(sys.argv[5]) != 0:
|
||||||
|
wadfile = str(sys.argv[5]) + ".wad"
|
||||||
|
else:
|
||||||
|
wadfile = str(titleid) + "ver" + str(ver) + ".wad"
|
||||||
|
Wii.WAD.loadDir(tmp).dumpFile(wadfile, fakesign = sys.argv[4])
|
||||||
|
if(os.path.isdir(tmp)): #cleanup
|
||||||
|
shutil.rmtree(tmp)
|
||||||
|
print"Done packing the WAD!"
|
||||||
|
print "Everything is done!\nHave a nice day. :3"
|
||||||
|
sys.exit()
|
0
WiiPy/tools/__init__.py
Normal file
0
WiiPy/tools/__init__.py
Normal file
21
WiiPy/tools/wads.py
Normal file
21
WiiPy/tools/wads.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#----------------------------------------------------------------------
|
||||||
|
# WADd - a simple command line tool for packing and unpacking wads.
|
||||||
|
# (c) 2009 |Omega and #HACKERCHANNEL Productions.
|
||||||
|
#
|
||||||
|
# Wii.py (c) Xuzz, SquidMan, megazig, TheLemonMan, |Omega, and Matt_P.
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
import Wii, sys, os
|
||||||
|
|
||||||
|
if(len(sys.argv) < 2):
|
||||||
|
print "Usage: python wads.py <input> <output> ..."
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
for i in range(1, len(sys.argv), 2):
|
||||||
|
if(os.isdir(sys.argv[i]):
|
||||||
|
elem = sys.argv[i]
|
||||||
|
elem2 = sys.argv[i + 1]
|
||||||
|
Wii.WAD.loadDir(elem).dumpFile(elem2)
|
||||||
|
else:
|
||||||
|
elem = sys.argv[i]
|
||||||
|
elem2 = sys.argv[i + 1]
|
||||||
|
Wii.WAD.loadFile(elem).dumpDir(elem2)
|
27
WiiPy/tools/wadtool.py
Normal file
27
WiiPy/tools/wadtool.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Copyright (C) 2009 zc00gii
|
||||||
|
#
|
||||||
|
# Wii.py (c) Xuzz, SquidMan, megazig, TheLemonMan, |Omega, and Matt_P.
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
import os, sys, Wii
|
||||||
|
|
||||||
|
def wadpack(waddir, wadfile):
|
||||||
|
Wii.WAD.loadDir(waddir).dumpFile(wadfile)
|
||||||
|
print "WAD packed successfully"
|
||||||
|
|
||||||
|
def wadunpack(wadfile,waddir):
|
||||||
|
Wii.WAD.loadFile(wadfile).dumpDir(waddir)
|
||||||
|
print "WAD unpacked successfully"
|
||||||
|
|
||||||
|
if(len(sys.argv) < 4):
|
||||||
|
print "Usage: python wadtool.py [option] <input> <output>\nOptions:\n-u, --unpack Unpack your desired WAD file\n-p, --pack Pack your desired WAD file"
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
doPackOrUnpack = sys.argv[1]
|
||||||
|
inputWad = sys.argv[2]
|
||||||
|
outputWad = sys.argv[3]
|
||||||
|
|
||||||
|
if doPackOrUnpack in ('-u','--unpack'):
|
||||||
|
wadunpack(inputWad, outputWad)
|
||||||
|
if doPackOrUnpack in ('-p','--pack'):
|
||||||
|
wadpack(inputWad, outputWad)
|
7
dependencies.txt
Normal file
7
dependencies.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Dependencies:
|
||||||
|
Python 2.5 or higher
|
||||||
|
(Windows installer: )
|
||||||
|
PyQt4
|
||||||
|
(Windows installer: )
|
||||||
|
PyCrypto
|
||||||
|
(Windows installer: http://www.voidspace.org.uk/python/modules.shtml#pycrypto )
|
BIN
i18n/Qwad_ca.qm
Normal file
BIN
i18n/Qwad_ca.qm
Normal file
Binary file not shown.
1003
i18n/Qwad_ca.ts
Normal file
1003
i18n/Qwad_ca.ts
Normal file
File diff suppressed because it is too large
Load Diff
BIN
i18n/Qwad_de.qm
Normal file
BIN
i18n/Qwad_de.qm
Normal file
Binary file not shown.
1002
i18n/Qwad_de.ts
Normal file
1002
i18n/Qwad_de.ts
Normal file
File diff suppressed because it is too large
Load Diff
BIN
i18n/Qwad_en.qm
Normal file
BIN
i18n/Qwad_en.qm
Normal file
Binary file not shown.
1003
i18n/Qwad_en.ts
Normal file
1003
i18n/Qwad_en.ts
Normal file
File diff suppressed because it is too large
Load Diff
BIN
i18n/Qwad_es.qm
Normal file
BIN
i18n/Qwad_es.qm
Normal file
Binary file not shown.
1003
i18n/Qwad_es.ts
Normal file
1003
i18n/Qwad_es.ts
Normal file
File diff suppressed because it is too large
Load Diff
BIN
i18n/Qwad_fr.qm
Normal file
BIN
i18n/Qwad_fr.qm
Normal file
Binary file not shown.
1002
i18n/Qwad_fr.ts
Normal file
1002
i18n/Qwad_fr.ts
Normal file
File diff suppressed because it is too large
Load Diff
BIN
i18n/Qwad_it.qm
Normal file
BIN
i18n/Qwad_it.qm
Normal file
Binary file not shown.
1002
i18n/Qwad_it.ts
Normal file
1002
i18n/Qwad_it.ts
Normal file
File diff suppressed because it is too large
Load Diff
BIN
icons/gcqwadlogo.png
Normal file
BIN
icons/gcqwadlogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
icons/qt4.png
Normal file
BIN
icons/qt4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
icons/wad.ico
Normal file
BIN
icons/wad.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
BIN
icons/wad.png
Normal file
BIN
icons/wad.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
19
makeqwaddeb.sh
Executable file
19
makeqwaddeb.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#makeqwaddeb#
|
||||||
|
VERSION=$1
|
||||||
|
Sources=$(find | grep -v pyc$ | grep -v ui$ | grep -v ts$ | grep -v .pro$ | grep -v .qrc$ | grep -v bz2$ | grep -v dist | grep -v -w icons | grep -v ~$ | grep -v examinar | grep -v e4.$ | grep -v eric | grep -v makeqwaddeb)
|
||||||
|
|
||||||
|
cp -r GUI dist_debian/usr/share/Qwad/
|
||||||
|
cp -r wii_signer dist_debian/usr/share/Qwad/
|
||||||
|
cp -r i18n dist_debian/usr/share/Qwad/
|
||||||
|
cp Qwad.pyw dist_debian/usr/share/Qwad/
|
||||||
|
cp Qwad_rc.py dist_debian/usr/share/Qwad/
|
||||||
|
cp README.txt dist_debian/usr/share/Qwad/
|
||||||
|
cp CHANGELOG.txt dist_debian/usr/share/Qwad/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
kwrite dist_debian/DEBIAN/control
|
||||||
|
rm dist_debian/DEBIAN/control~
|
||||||
|
|
||||||
|
dpkg --build dist_debian/ qwad-"$VERSION"_all.deb
|
Loading…
Reference in New Issue
Block a user