initial import
This commit is contained in:
parent
7219ff58a8
commit
81897a0881
339
COPYING
Normal file
339
COPYING
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
151
Makefile
Normal file
151
Makefile
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
#DEVKITPRO = /opt/devkitPPC
|
||||||
|
#DEVKITPPC = /opt/devkitPPC
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPPC)/wii_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source source/libtinysmb source/libpng source/libpng/pngu
|
||||||
|
DATA := data
|
||||||
|
INCLUDES :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFLAGS = -Os -Wall -mrvl $(MACHDEP) $(INCLUDE)
|
||||||
|
CXXFLAGS = $(CFLAGS)
|
||||||
|
|
||||||
|
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map -T../rvl.ld
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# any extra libraries we wish to link with the project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBS := -ltinysmb -lpng -lfat -lwiiuse -lbte -logc -lm -lz -lwiilight -lruntimeiospatch
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# automatically build a list of object files for our project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
export LD := $(CC)
|
||||||
|
else
|
||||||
|
export LD := $(CXX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||||
|
$(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of include paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD) \
|
||||||
|
-I$(LIBOGC_INC)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of library paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||||
|
-L$(LIBOGC_LIB)
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
run:
|
||||||
|
wiiload $(TARGET).dol
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(OUTPUT).dol: $(OUTPUT).elf
|
||||||
|
$(OUTPUT).elf: $(OFILES)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# This rule links in binary data with the .jpg extension
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.jpg.o : %.jpg
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.elf.o : %.elf
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.dat.o : %.dat
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.png.o : %.png
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
52
README.md
52
README.md
@ -1,2 +1,50 @@
|
|||||||
yawmmde
|
+----------------------------+
|
||||||
=======
|
| WAD Manager v1.5 |
|
||||||
|
| developed by Waninkoko |
|
||||||
|
+----------------------------+
|
||||||
|
| www.teknoconsolas.es |
|
||||||
|
+----------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
[ DISCLAIMER ]:
|
||||||
|
|
||||||
|
- THIS APPLICATION COMES WITH NO WARRANTY AT ALL, NEITHER EXPRESS NOR IMPLIED.
|
||||||
|
I DO NOT TAKE ANY RESPONSIBILITY FOR ANY DAMAGE IN YOUR WII CONSOLE
|
||||||
|
BECAUSE OF A IMPROPER USAGE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
[ DESCRIPTION ]:
|
||||||
|
|
||||||
|
- WAD Manager is an application that allows you to (un)install
|
||||||
|
WAD packages.
|
||||||
|
|
||||||
|
It lists all the available WAD packages in a storage device
|
||||||
|
so you can select which one to (un)install.
|
||||||
|
|
||||||
|
|
||||||
|
[ SUPPORTED DEVICES ]:
|
||||||
|
|
||||||
|
- SDGecko.
|
||||||
|
- Internal SD slot (with SDHC support).
|
||||||
|
- USB device (1.1 and 2.0).
|
||||||
|
|
||||||
|
|
||||||
|
[ HOW TO USE ]:
|
||||||
|
|
||||||
|
1. Create a folder called "wad" in the root of the storage device.
|
||||||
|
2. Copy all the WAD packages in the folder created in the step 1.
|
||||||
|
3. Run the application with any method to load homebrew.
|
||||||
|
|
||||||
|
|
||||||
|
[ NOTES ]:
|
||||||
|
|
||||||
|
- To use the NAND emulation is necessary to have a COMPLETE copy
|
||||||
|
of the NAND filesystem in the root of the FAT device.
|
||||||
|
|
||||||
|
|
||||||
|
[ KUDOS ]:
|
||||||
|
|
||||||
|
- Team Twiizers/devkitPRO
|
||||||
|
- svpe
|
||||||
|
- kwiirk
|
||||||
|
- All my betatesters.
|
||||||
|
BIN
data/background
Normal file
BIN
data/background
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
data/background.png
Normal file
BIN
data/background.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
data/ehcmodule.elf
Normal file
BIN
data/ehcmodule.elf
Normal file
Binary file not shown.
295
rvl.ld
Normal file
295
rvl.ld
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* Linkscript for Wii
|
||||||
|
*/
|
||||||
|
|
||||||
|
OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc");
|
||||||
|
OUTPUT_ARCH(powerpc:common);
|
||||||
|
EXTERN(_start);
|
||||||
|
ENTRY(_start);
|
||||||
|
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
stub PT_LOAD FLAGS(5);
|
||||||
|
text PT_LOAD FLAGS(5);
|
||||||
|
data PT_LOAD FLAGS(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* stub is loaded at physical address 0x00003400 (though both 0x80003400 and 0x00003400 are equivalent for IOS) */
|
||||||
|
/* This can also be used to load an arbitrary standalone stub at an arbitrary address in memory, for any purpose */
|
||||||
|
/* Use -Wl,--section-start,.stub=0xADDRESS to change */
|
||||||
|
. = 0x00003400;
|
||||||
|
|
||||||
|
.stub :
|
||||||
|
{
|
||||||
|
KEEP(*(.stub))
|
||||||
|
} :stub = 0
|
||||||
|
|
||||||
|
/* default base address */
|
||||||
|
/* use -Wl,--section-start,.init=0xADDRESS to change */
|
||||||
|
. = 0x80004000;
|
||||||
|
|
||||||
|
/* Program */
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*crt0.o(*.init))
|
||||||
|
KEEP (*(.init))
|
||||||
|
} :text = 0
|
||||||
|
.plt : { *(.plt) }
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rel.init : { *(.rel.init) }
|
||||||
|
.rela.init : { *(.rela.init) }
|
||||||
|
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
|
||||||
|
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||||
|
.rel.fini : { *(.rel.fini) }
|
||||||
|
.rela.fini : { *(.rela.fini) }
|
||||||
|
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
|
||||||
|
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||||
|
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
|
||||||
|
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||||
|
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
|
||||||
|
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||||
|
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
|
||||||
|
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||||
|
.rel.ctors : { *(.rel.ctors) }
|
||||||
|
.rela.ctors : { *(.rela.ctors) }
|
||||||
|
.rel.dtors : { *(.rel.dtors) }
|
||||||
|
.rela.dtors : { *(.rela.dtors) }
|
||||||
|
.rel.got : { *(.rel.got) }
|
||||||
|
.rela.got : { *(.rela.got) }
|
||||||
|
.rela.got1 : { *(.rela.got1) }
|
||||||
|
.rela.got2 : { *(.rela.got2) }
|
||||||
|
.rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
|
||||||
|
.rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
|
||||||
|
.rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
|
||||||
|
.rela.sbss : { *(.rela.sbss .rela.sbss.* .rel.gnu.linkonce.sb.*) }
|
||||||
|
.rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
|
||||||
|
.rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
|
||||||
|
.rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
|
||||||
|
.rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
|
||||||
|
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
|
||||||
|
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||||
|
.rel.plt : { *(.rel.plt) }
|
||||||
|
.rela.plt : { *(.rela.plt) }
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
*(.text.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.gnu.linkonce.t.*)
|
||||||
|
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} = 0
|
||||||
|
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(.fini))
|
||||||
|
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} = 0
|
||||||
|
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
|
||||||
|
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) } :data
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
|
||||||
|
.sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
/* Ensure the __preinit_array_start label is properly aligned. We
|
||||||
|
could instead move the label definition inside the section, but
|
||||||
|
the linker would then create the section even if it turns out to
|
||||||
|
be empty, which isn't pretty. */
|
||||||
|
. = ALIGN(32 / 8);
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
.preinit_array : { *(.preinit_array) }
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
.init_array : { *(.init_array) }
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
.fini_array : { *(.fini_array) }
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
*(.gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||||
|
.eh_frame : { KEEP (*(.eh_frame)) }
|
||||||
|
.gcc_except_table : { *(.gcc_except_table) }
|
||||||
|
.fixup : { *(.fixup) }
|
||||||
|
.got1 : { *(.got1) }
|
||||||
|
.got2 : { *(.got2) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
from the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.got : { *(.got.plt) *(.got) }
|
||||||
|
|
||||||
|
|
||||||
|
/* We want the small data sections together, so single-instruction offsets
|
||||||
|
can access them all, and initialized data all before uninitialized, so
|
||||||
|
we can shorten the on-disk segment size. */
|
||||||
|
|
||||||
|
.sdata :
|
||||||
|
{
|
||||||
|
*(.sdata)
|
||||||
|
*(.sdata.*)
|
||||||
|
*(.gnu.linkonce.s.*)
|
||||||
|
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||||
|
}
|
||||||
|
|
||||||
|
_edata = .;
|
||||||
|
PROVIDE (edata = .);
|
||||||
|
|
||||||
|
.sbss :
|
||||||
|
{
|
||||||
|
__sbss_start = .;
|
||||||
|
PROVIDE (__sbss_start = .);
|
||||||
|
PROVIDE (___sbss_start = .);
|
||||||
|
*(.dynsbss)
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss.*)
|
||||||
|
*(.gnu.linkonce.sb.*)
|
||||||
|
*(.scommon)
|
||||||
|
PROVIDE (__sbss_end = .);
|
||||||
|
PROVIDE (___sbss_end = .);
|
||||||
|
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||||
|
__sbss_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
__bss_start = .;
|
||||||
|
PROVIDE (__bss_start = .);
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(.gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections. */
|
||||||
|
|
||||||
|
. = ALIGN(32);
|
||||||
|
|
||||||
|
PROVIDE (__bss_end = .);
|
||||||
|
__bss_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
_end = .;
|
||||||
|
PROVIDE(end = .);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* These must appear regardless of . */
|
||||||
|
}
|
||||||
|
|
||||||
|
__isIPL = 0;
|
||||||
|
__stack_addr = (__bss_start + SIZEOF(.bss) + 0x20000 + 7) & (-8);
|
||||||
|
__stack_end = (__bss_start + SIZEOF(.bss));
|
||||||
|
__intrstack_addr = (__stack_addr + 0x4000);
|
||||||
|
__intrstack_end = (__stack_addr);
|
||||||
|
__Arena1Lo = (__intrstack_addr + 31) & (-32);
|
||||||
|
__Arena1Hi = (0x817FEFF0);
|
||||||
|
__Arena2Lo = (0x90002000);
|
||||||
|
__Arena2Hi = (0x933E0000);
|
||||||
|
|
||||||
|
__gxregs = (__Arena1Hi + 31) & (-32);
|
||||||
|
__ipcbufferLo = (0x933e0000);
|
||||||
|
__ipcbufferHi = (0x93400000);
|
||||||
|
|
||||||
|
/* for backward compatibility with old crt0 */
|
||||||
|
PROVIDE (__stack = (0x817FEFF0));
|
||||||
|
|
||||||
|
PROVIDE(__isIPL = __isIPL);
|
||||||
|
PROVIDE(__stack_addr = __stack_addr);
|
||||||
|
PROVIDE(__stack_end = __stack_end);
|
||||||
|
PROVIDE(__intrstack_addr = __intrstack_addr);
|
||||||
|
PROVIDE(__intrstack_end = __intrstack_end);
|
||||||
|
PROVIDE(__Arena1Lo = __Arena1Lo);
|
||||||
|
PROVIDE(__Arena1Hi = __Arena1Hi);
|
||||||
|
PROVIDE(__Arena2Lo = __Arena2Lo);
|
||||||
|
PROVIDE(__Arena2Hi = __Arena2Hi);
|
||||||
|
PROVIDE(__ipcbufferLo = __ipcbufferLo);
|
||||||
|
PROVIDE(__ipcbufferHi = __ipcbufferHi);
|
||||||
|
PROVIDE(__gxregs = __gxregs);
|
58
source/fat.c
Normal file
58
source/fat.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
//#include <smb.h>
|
||||||
|
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
|
||||||
|
s32 Fat_Mount(fatDevice *dev)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Initialize interface */
|
||||||
|
ret = dev->interface->startup();
|
||||||
|
if (!ret)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Mount device */
|
||||||
|
ret = fatMountSimple(dev->mount, dev->interface);
|
||||||
|
if (!ret)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fat_Unmount(fatDevice *dev)
|
||||||
|
{
|
||||||
|
/* Unmount device */
|
||||||
|
fatUnmount(dev->mount);
|
||||||
|
|
||||||
|
/* Shutdown interface */
|
||||||
|
dev->interface->shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Fat_ToFilename(const char *filename)
|
||||||
|
{
|
||||||
|
static char buffer[128];
|
||||||
|
|
||||||
|
u32 cnt, idx, len;
|
||||||
|
|
||||||
|
/* Clear buffer */
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
|
||||||
|
/* Get filename length */
|
||||||
|
len = strlen(filename);
|
||||||
|
|
||||||
|
for (cnt = idx = 0; idx < len; idx++) {
|
||||||
|
char c = filename[idx];
|
||||||
|
|
||||||
|
/* Valid characters */
|
||||||
|
if ( (c >= '#' && c <= ')') || (c >= '-' && c <= '.') ||
|
||||||
|
(c >= '0' && c <= '9') || (c >= 'A' && c <= 'z') ||
|
||||||
|
(c >= 'a' && c <= 'z') || (c == '!') )
|
||||||
|
buffer[cnt++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
55
source/fat.h
Normal file
55
source/fat.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef _FAT_H_
|
||||||
|
#define _FAT_H_
|
||||||
|
|
||||||
|
/* libfat header */
|
||||||
|
#include <fat.h>
|
||||||
|
#include <sys/dir.h>
|
||||||
|
|
||||||
|
/* SD headers */
|
||||||
|
#include <sdcard/gcsd.h>
|
||||||
|
#include <sdcard/wiisd_io.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* 'FAT Device' structure */
|
||||||
|
typedef struct {
|
||||||
|
/* Device mount point */
|
||||||
|
char *mount;
|
||||||
|
|
||||||
|
/* Device name */
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* Device interface */
|
||||||
|
const DISC_INTERFACE *interface;
|
||||||
|
} fatDevice;
|
||||||
|
|
||||||
|
/* 'FAT File' structure */
|
||||||
|
typedef struct {
|
||||||
|
/* Filename */
|
||||||
|
char filename[128];
|
||||||
|
/* 1 = Batch Install, 2 = Batch Uninstall - Leathl */
|
||||||
|
int install;
|
||||||
|
|
||||||
|
int installstate;
|
||||||
|
|
||||||
|
int old_ios;
|
||||||
|
int new_ios;
|
||||||
|
bool old_ahbprot;
|
||||||
|
bool new_ahbprot;
|
||||||
|
bool old_pass;
|
||||||
|
bool new_pass;
|
||||||
|
|
||||||
|
u32 high_id;
|
||||||
|
u32 low_id;
|
||||||
|
|
||||||
|
/* Filestat */
|
||||||
|
struct dirent entry;
|
||||||
|
} fatFile;
|
||||||
|
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
s32 Fat_Mount(fatDevice *);
|
||||||
|
void Fat_Unmount(fatDevice *);
|
||||||
|
char *Fat_ToFilename(const char *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
57
source/globals.h
Normal file
57
source/globals.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef _GLOBALS_H_
|
||||||
|
#define _GLOBALS_H_
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
#define CIOS_VERSION 249
|
||||||
|
#define ENTRIES_PER_PAGE 12
|
||||||
|
#define MAX_FILE_PATH_LEN 1024
|
||||||
|
#define MAX_DIR_LEVELS 10
|
||||||
|
#define WAD_DIRECTORY "/"
|
||||||
|
|
||||||
|
#define MAX_PASSWORD_LENGTH 10
|
||||||
|
#define MAX_FAT_DEVICE_LENGTH 10
|
||||||
|
#define MAX_NAND_DEVICE_LENGTH 10
|
||||||
|
|
||||||
|
#define WM_CONFIG_FILE_PATH ":/wad/wm_config.txt"
|
||||||
|
#define WM_BACKGROUND_PATH ":/wad/background.png"
|
||||||
|
|
||||||
|
// These are indices into the fatDevice fdevList
|
||||||
|
#define FAT_DEVICE_INDEX_WII_SD 0
|
||||||
|
#define FAT_DEVICE_INDXE_USB 1
|
||||||
|
#define FAT_DEVICE_INDEX_USB2 2
|
||||||
|
#define FAT_DEVICE_INDEX_GC_SDA 3
|
||||||
|
#define FAT_DEVICE_INDEX_GC_SDB 4
|
||||||
|
#define FAT_DEVICE_INDEX_INVALID -1
|
||||||
|
|
||||||
|
// These are the indices into the nandDevice ndevList
|
||||||
|
#define NAND_DEVICE_INDEX_DISABLE 0
|
||||||
|
#define NAND_DEVICE_INDEX_SD 1
|
||||||
|
#define NAND_DEVICE_INDEX_USB 2
|
||||||
|
#define NAND_DEVICE_INDEX_INVALID -1
|
||||||
|
|
||||||
|
#define CIOS_VERSION_INVALID -1
|
||||||
|
|
||||||
|
// For the WiiLight
|
||||||
|
#define WII_LIGHT_OFF 0
|
||||||
|
#define WII_LIGHT_ON 1
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char password[MAX_PASSWORD_LENGTH];
|
||||||
|
char startupPath [256];
|
||||||
|
int cIOSVersion;
|
||||||
|
int fatDeviceIndex;
|
||||||
|
int nandDeviceIndex;
|
||||||
|
const char *smbuser;
|
||||||
|
const char *smbpassword;
|
||||||
|
const char *share;
|
||||||
|
const char *ip;
|
||||||
|
} CONFIG;
|
||||||
|
|
||||||
|
|
||||||
|
extern CONFIG gConfig;
|
||||||
|
extern nandDevice ndevList[];
|
||||||
|
extern fatDevice fdevList[];
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
58
source/gpio.h
Normal file
58
source/gpio.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||||
|
GPIO pin-out constants
|
||||||
|
|
||||||
|
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||||
|
|
||||||
|
# This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||||
|
# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GPIO_H__
|
||||||
|
#define __GPIO_H__
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GP_POWER = 0x000001,
|
||||||
|
GP_SHUTDOWN = 0x000002,
|
||||||
|
GP_FAN = 0x000004,
|
||||||
|
GP_DCDC = 0x000008,
|
||||||
|
GP_DISPIN = 0x000010,
|
||||||
|
GP_SLOTLED = 0x000020,
|
||||||
|
GP_EJECTBTN = 0x000040,
|
||||||
|
GP_SLOTIN = 0x000080,
|
||||||
|
GP_SENSORBAR = 0x000100,
|
||||||
|
GP_DOEJECT = 0x000200,
|
||||||
|
GP_EEP_CS = 0x000400,
|
||||||
|
GP_EEP_CLK = 0x000800,
|
||||||
|
GP_EEP_MOSI = 0x001000,
|
||||||
|
GP_EEP_MISO = 0x002000,
|
||||||
|
GP_AVE_SCL = 0x004000,
|
||||||
|
GP_AVE_SDA = 0x008000,
|
||||||
|
GP_DEBUG0 = 0x010000,
|
||||||
|
GP_DEBUG1 = 0x020000,
|
||||||
|
GP_DEBUG2 = 0x040000,
|
||||||
|
GP_DEBUG3 = 0x080000,
|
||||||
|
GP_DEBUG4 = 0x100000,
|
||||||
|
GP_DEBUG5 = 0x200000,
|
||||||
|
GP_DEBUG6 = 0x400000,
|
||||||
|
GP_DEBUG7 = 0x800000,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GP_DEBUG_SHIFT 16
|
||||||
|
#define GP_DEBUG_MASK 0xFF0000
|
||||||
|
|
||||||
|
#define GP_ALL 0xFFFFFF
|
||||||
|
#define GP_OWNER_PPC (GP_AVE_SDA | GP_AVE_SCL | GP_DOEJECT | GP_SENSORBAR | GP_SLOTIN | GP_SLOTLED)
|
||||||
|
#define GP_OWNER_ARM (GP_ALL ^ GP_OWNER_PPC)
|
||||||
|
#define GP_INPUTS (GP_POWER | GP_EJECTBTN | GP_SLOTIN | GP_EEP_MISO | GP_AVE_SDA)
|
||||||
|
#define GP_OUTPUTS (GP_ALL ^ GP_INPUTS)
|
||||||
|
#define GP_ARM_INPUTS (GP_INPUTS & GP_OWNER_ARM)
|
||||||
|
#define GP_PPC_INPUTS (GP_INPUTS & GP_OWNER_PPC)
|
||||||
|
#define GP_ARM_OUTPUTS (GP_OUTPUTS & GP_OWNER_ARM)
|
||||||
|
#define GP_PPC_OUTPUTS (GP_OUTPUTS & GP_OWNER_PPC)
|
||||||
|
#define GP_DEFAULT_ON (GP_AVE_SCL | GP_DCDC | GP_FAN)
|
||||||
|
#define GP_ARM_DEFAULT_ON (GP_DEFAULT_ON & GP_OWNER_ARM)
|
||||||
|
#define GP_PPC_DEFAULT_ON (GP_DEFAULT_ON & GP_OWNER_PPC)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
90
source/gui.c
Normal file
90
source/gui.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
|
||||||
|
#include "video.h"
|
||||||
|
#include "fat.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "nand.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
#define CONSOLE_XCOORD 50
|
||||||
|
#define CONSOLE_YCOORD 100
|
||||||
|
#define CONSOLE_WIDTH 540
|
||||||
|
#define CONSOLE_HEIGHT 320
|
||||||
|
|
||||||
|
bool file_exists(const char * filename)
|
||||||
|
{
|
||||||
|
FILE * file;
|
||||||
|
if (file = fopen(filename, "r"))
|
||||||
|
{
|
||||||
|
fclose(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 __Gui_DrawPng(void *img, u32 x, u32 y)
|
||||||
|
{
|
||||||
|
IMGCTX ctx = NULL;
|
||||||
|
PNGUPROP imgProp;
|
||||||
|
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
fatDevice *fdev = &fdevList[0];
|
||||||
|
ret = Fat_Mount(fdev);
|
||||||
|
if (file_exists("sd:/wad/background.png")) ctx = PNGU_SelectImageFromDevice ("sd:/wad/background.png");
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fdev = &fdevList[2];
|
||||||
|
Fat_Mount(fdev);
|
||||||
|
if (file_exists("usb2:/wad/background.png")) ctx = PNGU_SelectImageFromDevice ("usb2:/wad/background.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ctx)
|
||||||
|
{
|
||||||
|
/* Select PNG data */
|
||||||
|
ctx = PNGU_SelectImageFromBuffer(img);
|
||||||
|
if (!ctx) {
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Get image properties */
|
||||||
|
ret = PNGU_GetImageProperties(ctx, &imgProp);
|
||||||
|
if (ret != PNGU_OK) {
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw image */
|
||||||
|
Video_DrawPng(ctx, imgProp, x, y);
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Free memory */
|
||||||
|
if (ctx)
|
||||||
|
PNGU_ReleaseImageContext(ctx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Gui_InitConsole(void)
|
||||||
|
{
|
||||||
|
/* Initialize console */
|
||||||
|
Con_Init(CONSOLE_XCOORD, CONSOLE_YCOORD, CONSOLE_WIDTH, CONSOLE_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui_DrawBackground(void)
|
||||||
|
{
|
||||||
|
extern char bgData[];
|
||||||
|
|
||||||
|
/* Draw background */
|
||||||
|
__Gui_DrawPng(bgData, 0, 0);
|
||||||
|
}
|
8
source/gui.h
Normal file
8
source/gui.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _GUI_H_
|
||||||
|
#define _GUI_H_
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
void Gui_InitConsole(void);
|
||||||
|
void Gui_DrawBackground(void);
|
||||||
|
|
||||||
|
#endif
|
179
source/hollywood.h
Normal file
179
source/hollywood.h
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||||
|
Hollywood register definitions
|
||||||
|
|
||||||
|
Copyright (C) 2008, 2009 Haxx Enterprises <bushing@gmail.com>
|
||||||
|
Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
|
||||||
|
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||||
|
Copyright (C) 2008, 2009 John Kelley <wiidev@kelley.ca>
|
||||||
|
|
||||||
|
# This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||||
|
# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HOLLYWOOD_H__
|
||||||
|
#define __HOLLYWOOD_H__
|
||||||
|
|
||||||
|
/* Hollywood Registers */
|
||||||
|
|
||||||
|
#define HW_PPC_REG_BASE 0xd000000
|
||||||
|
#define HW_REG_BASE 0xd800000
|
||||||
|
|
||||||
|
// The PPC can only see the first three IPC registers
|
||||||
|
#define HW_IPC_PPCMSG (HW_REG_BASE + 0x000)
|
||||||
|
#define HW_IPC_PPCCTRL (HW_REG_BASE + 0x004)
|
||||||
|
#define HW_IPC_ARMMSG (HW_REG_BASE + 0x008)
|
||||||
|
#define HW_IPC_ARMCTRL (HW_REG_BASE + 0x00c)
|
||||||
|
|
||||||
|
#define HW_TIMER (HW_REG_BASE + 0x010)
|
||||||
|
#define HW_ALARM (HW_REG_BASE + 0x014)
|
||||||
|
|
||||||
|
#define HW_PPCIRQFLAG (HW_REG_BASE + 0x030)
|
||||||
|
#define HW_PPCIRQMASK (HW_REG_BASE + 0x034)
|
||||||
|
|
||||||
|
#define HW_ARMIRQFLAG (HW_REG_BASE + 0x038)
|
||||||
|
#define HW_ARMIRQMASK (HW_REG_BASE + 0x03c)
|
||||||
|
|
||||||
|
#define HW_MEMMIRR (HW_REG_BASE + 0x060)
|
||||||
|
#define HW_AHBPROT (HW_REG_BASE + 0x064)
|
||||||
|
|
||||||
|
// something to do with PPCBOOT
|
||||||
|
// and legacy DI it seems ?!?
|
||||||
|
#define HW_EXICTRL (HW_REG_BASE + 0x070)
|
||||||
|
#define EXICTRL_ENABLE_EXI 1
|
||||||
|
|
||||||
|
// PPC side of GPIO1 (Starlet can access this too)
|
||||||
|
// Output state
|
||||||
|
#define HW_GPIO1BOUT (HW_REG_BASE + 0x0c0)
|
||||||
|
// Direction (1=output)
|
||||||
|
#define HW_GPIO1BDIR (HW_REG_BASE + 0x0c4)
|
||||||
|
// Input state
|
||||||
|
#define HW_GPIO1BIN (HW_REG_BASE + 0x0c8)
|
||||||
|
// Interrupt level
|
||||||
|
#define HW_GPIO1BINTLVL (HW_REG_BASE + 0x0cc)
|
||||||
|
// Interrupt flags (write 1 to clear)
|
||||||
|
#define HW_GPIO1BINTFLAG (HW_REG_BASE + 0x0d0)
|
||||||
|
// Interrupt propagation enable
|
||||||
|
// Do these interrupts go anywhere???
|
||||||
|
#define HW_GPIO1BINTENABLE (HW_REG_BASE + 0x0d4)
|
||||||
|
//??? seems to be a mirror of inputs at some point... power-up state?
|
||||||
|
#define HW_GPIO1BINMIR (HW_REG_BASE + 0x0d8)
|
||||||
|
// 0xFFFFFF by default, if cleared disables respective outputs. Top bits non-settable.
|
||||||
|
#define HW_GPIO1ENABLE (HW_REG_BASE + 0x0dc)
|
||||||
|
|
||||||
|
#define HW_GPIO1_SLOT 0x000020
|
||||||
|
#define HW_GPIO1_DEBUG 0xFF0000
|
||||||
|
#define HW_GPIO1_DEBUG_SH 16
|
||||||
|
|
||||||
|
// Starlet side of GPIO1
|
||||||
|
// Output state
|
||||||
|
#define HW_GPIO1OUT (HW_REG_BASE + 0x0e0)
|
||||||
|
// Direction (1=output)
|
||||||
|
#define HW_GPIO1DIR (HW_REG_BASE + 0x0e4)
|
||||||
|
// Input state
|
||||||
|
#define HW_GPIO1IN (HW_REG_BASE + 0x0e8)
|
||||||
|
// Interrupt level
|
||||||
|
#define HW_GPIO1INTLVL (HW_REG_BASE + 0x0ec)
|
||||||
|
// Interrupt flags (write 1 to clear)
|
||||||
|
#define HW_GPIO1INTFLAG (HW_REG_BASE + 0x0f0)
|
||||||
|
// Interrupt propagation enable (interrupts go to main interrupt 0x800)
|
||||||
|
#define HW_GPIO1INTENABLE (HW_REG_BASE + 0x0f4)
|
||||||
|
//??? seems to be a mirror of inputs at some point... power-up state?
|
||||||
|
#define HW_GPIO1INMIR (HW_REG_BASE + 0x0f8)
|
||||||
|
// Owner of each GPIO bit. If 1, GPIO1B registers assume control. If 0, GPIO1 registers assume control.
|
||||||
|
#define HW_GPIO1OWNER (HW_REG_BASE + 0x0fc)
|
||||||
|
|
||||||
|
// ????
|
||||||
|
#define HW_DIFLAGS (HW_REG_BASE + 0x180)
|
||||||
|
#define DIFLAGS_BOOT_CODE 0x100000
|
||||||
|
|
||||||
|
// maybe a GPIO???
|
||||||
|
#define HW_RESETS (HW_REG_BASE + 0x194)
|
||||||
|
|
||||||
|
#define HW_CLOCKS (HW_REG_BASE + 0x1b4)
|
||||||
|
|
||||||
|
#define HW_GPIO2OUT (HW_REG_BASE + 0x1c8)
|
||||||
|
#define HW_GPIO2DIR (HW_REG_BASE + 0x1cc)
|
||||||
|
#define HW_GPIO2IN (HW_REG_BASE + 0x1d0)
|
||||||
|
|
||||||
|
#define HW_OTPCMD (HW_REG_BASE + 0x1ec)
|
||||||
|
#define HW_OTPDATA (HW_REG_BASE + 0x1f0)
|
||||||
|
#define HW_VERSION (HW_REG_BASE + 0x214)
|
||||||
|
|
||||||
|
/* NAND Registers */
|
||||||
|
|
||||||
|
#define NAND_REG_BASE 0xd010000
|
||||||
|
|
||||||
|
#define NAND_CMD (NAND_REG_BASE + 0x000)
|
||||||
|
#define NAND_STATUS NAND_CMD
|
||||||
|
#define NAND_CONF (NAND_REG_BASE + 0x004)
|
||||||
|
#define NAND_ADDR0 (NAND_REG_BASE + 0x008)
|
||||||
|
#define NAND_ADDR1 (NAND_REG_BASE + 0x00c)
|
||||||
|
#define NAND_DATA (NAND_REG_BASE + 0x010)
|
||||||
|
#define NAND_ECC (NAND_REG_BASE + 0x014)
|
||||||
|
#define NAND_UNK1 (NAND_REG_BASE + 0x018)
|
||||||
|
#define NAND_UNK2 (NAND_REG_BASE + 0x01c)
|
||||||
|
|
||||||
|
/* AES Registers */
|
||||||
|
|
||||||
|
#define AES_REG_BASE 0xd020000
|
||||||
|
|
||||||
|
#define AES_CMD (AES_REG_BASE + 0x000)
|
||||||
|
#define AES_SRC (AES_REG_BASE + 0x004)
|
||||||
|
#define AES_DEST (AES_REG_BASE + 0x008)
|
||||||
|
#define AES_KEY (AES_REG_BASE + 0x00c)
|
||||||
|
#define AES_IV (AES_REG_BASE + 0x010)
|
||||||
|
|
||||||
|
/* SHA-1 Registers */
|
||||||
|
|
||||||
|
#define SHA_REG_BASE 0xd030000
|
||||||
|
|
||||||
|
#define SHA_CMD (SHA_REG_BASE + 0x000)
|
||||||
|
#define SHA_SRC (SHA_REG_BASE + 0x004)
|
||||||
|
#define SHA_H0 (SHA_REG_BASE + 0x008)
|
||||||
|
#define SHA_H1 (SHA_REG_BASE + 0x00c)
|
||||||
|
#define SHA_H2 (SHA_REG_BASE + 0x010)
|
||||||
|
#define SHA_H3 (SHA_REG_BASE + 0x014)
|
||||||
|
#define SHA_H4 (SHA_REG_BASE + 0x018)
|
||||||
|
|
||||||
|
/* SD Host Controller Registers */
|
||||||
|
|
||||||
|
#define SDHC_REG_BASE 0xd070000
|
||||||
|
|
||||||
|
/* EXI Registers */
|
||||||
|
|
||||||
|
#define EXI_REG_BASE 0xd806800
|
||||||
|
#define EXI0_REG_BASE (EXI_REG_BASE+0x000)
|
||||||
|
#define EXI1_REG_BASE (EXI_REG_BASE+0x014)
|
||||||
|
#define EXI2_REG_BASE (EXI_REG_BASE+0x028)
|
||||||
|
|
||||||
|
#define EXI0_CSR (EXI0_REG_BASE+0x000)
|
||||||
|
#define EXI0_MAR (EXI0_REG_BASE+0x004)
|
||||||
|
#define EXI0_LENGTH (EXI0_REG_BASE+0x008)
|
||||||
|
#define EXI0_CR (EXI0_REG_BASE+0x00c)
|
||||||
|
#define EXI0_DATA (EXI0_REG_BASE+0x010)
|
||||||
|
|
||||||
|
#define EXI1_CSR (EXI1_REG_BASE+0x000)
|
||||||
|
#define EXI1_MAR (EXI1_REG_BASE+0x004)
|
||||||
|
#define EXI1_LENGTH (EXI1_REG_BASE+0x008)
|
||||||
|
#define EXI1_CR (EXI1_REG_BASE+0x00c)
|
||||||
|
#define EXI1_DATA (EXI1_REG_BASE+0x010)
|
||||||
|
|
||||||
|
#define EXI2_CSR (EXI2_REG_BASE+0x000)
|
||||||
|
#define EXI2_MAR (EXI2_REG_BASE+0x004)
|
||||||
|
#define EXI2_LENGTH (EXI2_REG_BASE+0x008)
|
||||||
|
#define EXI2_CR (EXI2_REG_BASE+0x00c)
|
||||||
|
#define EXI2_DATA (EXI2_REG_BASE+0x010)
|
||||||
|
|
||||||
|
#define EXI_BOOT_BASE (EXI_REG_BASE+0x040)
|
||||||
|
|
||||||
|
/* MEMORY CONTROLLER Registers */
|
||||||
|
|
||||||
|
#define MEM_REG_BASE 0xd8b4000
|
||||||
|
#define MEM_PROT (MEM_REG_BASE+0x20a)
|
||||||
|
#define MEM_PROT_START (MEM_REG_BASE+0x20c)
|
||||||
|
#define MEM_PROT_END (MEM_REG_BASE+0x20e)
|
||||||
|
#define MEM_FLUSHREQ (MEM_REG_BASE+0x228)
|
||||||
|
#define MEM_FLUSHACK (MEM_REG_BASE+0x22a)
|
||||||
|
|
||||||
|
#endif
|
1132
source/libpng/pngu/pngu.c
Normal file
1132
source/libpng/pngu/pngu.c
Normal file
File diff suppressed because it is too large
Load Diff
171
source/libpng/pngu/pngu.h
Normal file
171
source/libpng/pngu/pngu.h
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/********************************************************************************************
|
||||||
|
|
||||||
|
PNGU Version : 0.2a
|
||||||
|
|
||||||
|
Coder : frontier
|
||||||
|
|
||||||
|
More info : http://frontier-dev.net
|
||||||
|
|
||||||
|
********************************************************************************************/
|
||||||
|
#ifndef __PNGU__
|
||||||
|
#define __PNGU__
|
||||||
|
|
||||||
|
// Return codes
|
||||||
|
#define PNGU_OK 0
|
||||||
|
#define PNGU_ODD_WIDTH 1
|
||||||
|
#define PNGU_ODD_STRIDE 2
|
||||||
|
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
|
||||||
|
#define PNGU_FILE_IS_NOT_PNG 4
|
||||||
|
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
|
||||||
|
#define PNGU_NO_FILE_SELECTED 6
|
||||||
|
#define PNGU_CANT_OPEN_FILE 7
|
||||||
|
#define PNGU_CANT_READ_FILE 8
|
||||||
|
#define PNGU_LIB_ERROR 9
|
||||||
|
|
||||||
|
// Color types
|
||||||
|
#define PNGU_COLOR_TYPE_GRAY 1
|
||||||
|
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
|
||||||
|
#define PNGU_COLOR_TYPE_PALETTE 3
|
||||||
|
#define PNGU_COLOR_TYPE_RGB 4
|
||||||
|
#define PNGU_COLOR_TYPE_RGB_ALPHA 5
|
||||||
|
#define PNGU_COLOR_TYPE_UNKNOWN 6
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Types
|
||||||
|
typedef unsigned char PNGU_u8;
|
||||||
|
typedef unsigned short PNGU_u16;
|
||||||
|
typedef unsigned int PNGU_u32;
|
||||||
|
typedef unsigned long long PNGU_u64;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PNGU_u8 r;
|
||||||
|
PNGU_u8 g;
|
||||||
|
PNGU_u8 b;
|
||||||
|
} PNGUCOLOR;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PNGU_u32 imgWidth; // In pixels
|
||||||
|
PNGU_u32 imgHeight; // In pixels
|
||||||
|
PNGU_u32 imgBitDepth; // In bitx
|
||||||
|
PNGU_u32 imgColorType; // PNGU_COLOR_TYPE_*
|
||||||
|
PNGU_u32 validBckgrnd; // Non zero if there is a background color
|
||||||
|
PNGUCOLOR bckgrnd; // Backgroun color
|
||||||
|
PNGU_u32 numTrans; // Number of transparent colors
|
||||||
|
PNGUCOLOR *trans; // Transparent colors
|
||||||
|
} PNGUPROP;
|
||||||
|
|
||||||
|
// Image context, always initialize with SelectImageFrom* and free with ReleaseImageContext
|
||||||
|
struct _IMGCTX;
|
||||||
|
typedef struct _IMGCTX *IMGCTX;
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pixel conversion *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
// Macro to convert RGB8 values to RGB565
|
||||||
|
#define PNGU_RGB8_TO_RGB565(r,g,b) ( ((((PNGU_u16) r) & 0xF8U) << 8) | ((((PNGU_u16) g) & 0xFCU) << 3) | (((PNGU_u16) b) >> 3) )
|
||||||
|
|
||||||
|
// Macro to convert RGBA8 values to RGB5A3
|
||||||
|
#define PNGU_RGB8_TO_RGB5A3(r,g,b,a) (PNGU_u16) (((a & 0xE0U) == 0xE0U) ? \
|
||||||
|
(0x8000U | ((((PNGU_u16) r) & 0xF8U) << 7) | ((((PNGU_u16) g) & 0xF8U) << 2) | (((PNGU_u16) b) >> 3)) : \
|
||||||
|
(((((PNGU_u16) a) & 0xE0U) << 7) | ((((PNGU_u16) r) & 0xF0U) << 4) | (((PNGU_u16) g) & 0xF0U) | ((((PNGU_u16) b) & 0xF0U) >> 4)))
|
||||||
|
|
||||||
|
// Function to convert two RGB8 values to YCbYCr
|
||||||
|
PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2);
|
||||||
|
|
||||||
|
// Function to convert an YCbYCr to two RGB8 values.
|
||||||
|
void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Image context handling *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
// Selects a PNG file, previosly loaded into a buffer, and creates an image context for subsequent procesing.
|
||||||
|
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer);
|
||||||
|
|
||||||
|
// Selects a PNG file, from any devoptab device, and creates an image context for subsequent procesing.
|
||||||
|
IMGCTX PNGU_SelectImageFromDevice (const char *filename);
|
||||||
|
|
||||||
|
// Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX.
|
||||||
|
void PNGU_ReleaseImageContext (IMGCTX ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Miscelaneous *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
|
||||||
|
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Image conversion *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
// Expands selected image into an YCbYCr buffer. You need to specify context, image dimensions,
|
||||||
|
// destination address and stride in pixels (stride = buffer width - image width).
|
||||||
|
int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
||||||
|
|
||||||
|
// Macro for decoding an image inside a buffer at given coordinates.
|
||||||
|
#define PNGU_DECODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
|
||||||
|
\
|
||||||
|
PNGU_DecodeToYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
||||||
|
(coordX) * 2, (bufferWidth) - (imgWidth))
|
||||||
|
|
||||||
|
// Expands selected image into a linear RGB565 buffer. You need to specify context, image dimensions,
|
||||||
|
// destination address and stride in pixels (stride = buffer width - image width).
|
||||||
|
int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
||||||
|
|
||||||
|
// Macro for decoding an image inside a buffer at given coordinates.
|
||||||
|
#define PNGU_DECODE_TO_COORDS_RGB565(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
|
||||||
|
\
|
||||||
|
PNGU_DecodeToRGB565 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
||||||
|
(coordX) * 2, (bufferWidth) - (imgWidth))
|
||||||
|
|
||||||
|
// Expands selected image into a linear RGBA8 buffer. You need to specify context, image dimensions,
|
||||||
|
// destination address, stride in pixels and default alpha value, which is used if the source image
|
||||||
|
// doesn't have an alpha channel.
|
||||||
|
int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha);
|
||||||
|
|
||||||
|
// Macro for decoding an image inside a buffer at given coordinates.
|
||||||
|
#define PNGU_DECODE_TO_COORDS_RGBA8(ctx,coordX,coordY,imgWidth,imgHeight,default_alpha,bufferWidth,bufferHeight,buffer) \
|
||||||
|
\
|
||||||
|
PNGU_DecodeToRGBA8 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
||||||
|
(coordX) * 2, (bufferWidth) - (imgWidth), default_alpha)
|
||||||
|
|
||||||
|
// Expands selected image into a 4x4 tiled RGB565 buffer. You need to specify context, image dimensions
|
||||||
|
// and destination address.
|
||||||
|
int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer);
|
||||||
|
|
||||||
|
// Expands selected image into a 4x4 tiled RGB5A3 buffer. You need to specify context, image dimensions,
|
||||||
|
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
|
||||||
|
int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
|
||||||
|
|
||||||
|
// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
|
||||||
|
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
|
||||||
|
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
|
||||||
|
|
||||||
|
// Encodes an YCbYCr image in PNG format and stores it in the selected device or memory buffer. You need to
|
||||||
|
// specify context, image dimensions, destination address and stride in pixels (stride = buffer width - image width).
|
||||||
|
int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
||||||
|
|
||||||
|
// Macro for encoding an image stored into an YCbYCr buffer at given coordinates.
|
||||||
|
#define PNGU_ENCODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
|
||||||
|
\
|
||||||
|
PNGU_EncodeFromYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
||||||
|
(coordX) * 2, (bufferWidth) - (imgWidth))
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1478
source/menu.c
Normal file
1478
source/menu.c
Normal file
File diff suppressed because it is too large
Load Diff
8
source/menu.h
Normal file
8
source/menu.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _MENU_H_
|
||||||
|
#define _MENU_H_
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
void Menu_Loop(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
399
source/mload.c
Normal file
399
source/mload.c
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
/* mload.c (for PPC) (c) 2009, Hermes
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mload.h"
|
||||||
|
|
||||||
|
static const char mload_fs[] ATTRIBUTE_ALIGN(32) = "/dev/mload";
|
||||||
|
|
||||||
|
static s32 mload_fd = -1;
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// to init/test if the device is running
|
||||||
|
|
||||||
|
int mload_init()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if(mload_fd>=0) return 0;
|
||||||
|
|
||||||
|
for(n=0;n<10;n++) // try 2.5 seconds
|
||||||
|
{
|
||||||
|
mload_fd=IOS_Open(mload_fs, 0);
|
||||||
|
|
||||||
|
if(mload_fd>=0) break;
|
||||||
|
|
||||||
|
usleep(250*1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mload_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// to close the device (remember call it when rebooting the IOS!)
|
||||||
|
|
||||||
|
int mload_close()
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(mload_fd<0) return -1;
|
||||||
|
|
||||||
|
ret=IOS_Close(mload_fd);
|
||||||
|
|
||||||
|
mload_fd=-1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// to get the thread id of mload
|
||||||
|
|
||||||
|
int mload_get_thread_id()
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_MLOAD_THREAD_ID, ":");
|
||||||
|
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// get the base and the size of the memory readable/writable to load modules
|
||||||
|
|
||||||
|
int mload_get_load_base(u32 *starlet_base, int *size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_LOAD_BASE, ":ii",starlet_base, size);
|
||||||
|
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// load and run a module from starlet (it need to allocate MEM2 to send the elf file)
|
||||||
|
// the module must be a elf made with stripios
|
||||||
|
|
||||||
|
int mload_module(void *addr, int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
void *buf=NULL;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(len+0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
buf= iosAlloc(hid, len);
|
||||||
|
|
||||||
|
if(!buf) {ret= -1;goto out;}
|
||||||
|
|
||||||
|
|
||||||
|
memcpy(buf, addr,len);
|
||||||
|
|
||||||
|
ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_LOAD_MODULE, ":d", buf, len);
|
||||||
|
|
||||||
|
if(ret<0) goto out;
|
||||||
|
|
||||||
|
ret=IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_MODULE, ":");
|
||||||
|
|
||||||
|
if(ret<0) {ret= -666;goto out;}
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// load a module from the PPC
|
||||||
|
// the module must be a elf made with stripios
|
||||||
|
|
||||||
|
int mload_elf(void *my_elf, data_elf *data_elf)
|
||||||
|
{
|
||||||
|
int n,m;
|
||||||
|
int p;
|
||||||
|
u8 *adr;
|
||||||
|
u32 elf=(u32) my_elf;
|
||||||
|
|
||||||
|
if(elf & 3) return -1; // aligned to 4 please!
|
||||||
|
|
||||||
|
elfheader *head=(void *) elf;
|
||||||
|
elfphentry *entries;
|
||||||
|
|
||||||
|
if(head->ident0!=0x7F454C46) return -1;
|
||||||
|
if(head->ident1!=0x01020161) return -1;
|
||||||
|
if(head->ident2!=0x01000000) return -1;
|
||||||
|
|
||||||
|
p=head->phoff;
|
||||||
|
|
||||||
|
data_elf->start=(void *) head->entry;
|
||||||
|
|
||||||
|
for(n=0; n<head->phnum; n++)
|
||||||
|
{
|
||||||
|
entries=(void *) (elf+p);
|
||||||
|
p+=sizeof(elfphentry);
|
||||||
|
|
||||||
|
if(entries->type == 4)
|
||||||
|
{
|
||||||
|
adr=(void *) (elf + entries->offset);
|
||||||
|
|
||||||
|
if(getbe32(0)!=0) return -2; // bad info (sure)
|
||||||
|
|
||||||
|
for(m=4; m < entries->memsz; m+=8)
|
||||||
|
{
|
||||||
|
switch(getbe32(m))
|
||||||
|
{
|
||||||
|
case 0x9:
|
||||||
|
data_elf->start= (void *) getbe32(m+4);
|
||||||
|
break;
|
||||||
|
case 0x7D:
|
||||||
|
data_elf->prio= getbe32(m+4);
|
||||||
|
break;
|
||||||
|
case 0x7E:
|
||||||
|
data_elf->size_stack= getbe32(m+4);
|
||||||
|
break;
|
||||||
|
case 0x7F:
|
||||||
|
data_elf->stack= (void *) (getbe32(m+4));
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(entries->type == 1 && entries->memsz != 0 && entries->vaddr!=0)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(mload_memset((void *) entries->vaddr, 0, entries->memsz)<0) return -1;
|
||||||
|
if(mload_seek(entries->vaddr, SEEK_SET)<0) return -1;
|
||||||
|
if(mload_write((void *) (elf + entries->offset), entries->filesz)<0) return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// run one thread (you can use to load modules or binary files)
|
||||||
|
|
||||||
|
int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_THREAD, "iiii:", starlet_addr,starlet_top_stack, stack_size, priority);
|
||||||
|
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// stops one starlet thread
|
||||||
|
|
||||||
|
int mload_stop_thread(int id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_STOP_THREAD, "i:", id);
|
||||||
|
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// continue one stopped starlet thread
|
||||||
|
|
||||||
|
int mload_continue_thread(int id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_CONTINUE_THREAD, "i:", id);
|
||||||
|
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// fix starlet address to read/write (uses SEEK_SET, etc as mode)
|
||||||
|
|
||||||
|
int mload_seek(int offset, int mode)
|
||||||
|
{
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
return IOS_Seek(mload_fd, offset, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// read bytes from starlet (it update the offset)
|
||||||
|
|
||||||
|
int mload_read(void* buf, u32 size)
|
||||||
|
{
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
return IOS_Read(mload_fd, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// write bytes from starlet (it update the offset)
|
||||||
|
|
||||||
|
int mload_write(const void * buf, u32 size)
|
||||||
|
{
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
return IOS_Write(mload_fd, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// fill a block (similar to memset)
|
||||||
|
|
||||||
|
int mload_memset(void *starlet_addr, int set, int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_MEMSET, "iii:", starlet_addr, set, len);
|
||||||
|
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// get the ehci datas ( ehcmodule.elf uses this address)
|
||||||
|
|
||||||
|
void * mload_get_ehci_data()
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return NULL;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return NULL;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_EHCI_DATA, ":");
|
||||||
|
if(ret<0) return NULL;
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return (void *) ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// set the dev/es ioctlv in routine
|
||||||
|
|
||||||
|
int mload_set_ES_ioctlv_vector(void *starlet_addr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
s32 hid = -1;
|
||||||
|
|
||||||
|
|
||||||
|
if(mload_init()<0) return -1;
|
||||||
|
|
||||||
|
hid = iosCreateHeap(0x800);
|
||||||
|
|
||||||
|
if(hid<0) return hid;
|
||||||
|
|
||||||
|
ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_SET_ES_IOCTLV, "i:", starlet_addr);
|
||||||
|
|
||||||
|
|
||||||
|
//iosDestroyHeap(hid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
194
source/mload.h
Normal file
194
source/mload.h
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/* mload.c (for PPC) (c) 2009, Hermes
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MLOAD_H__
|
||||||
|
#define __MLOAD_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <gccore.h>
|
||||||
|
#include "unistd.h"
|
||||||
|
|
||||||
|
#define MLOAD_MLOAD_THREAD_ID 0x4D4C4400
|
||||||
|
#define MLOAD_LOAD_MODULE 0x4D4C4480
|
||||||
|
#define MLOAD_RUN_MODULE 0x4D4C4481
|
||||||
|
#define MLOAD_RUN_THREAD 0x4D4C4482
|
||||||
|
|
||||||
|
#define MLOAD_STOP_THREAD 0x4D4C4484
|
||||||
|
#define MLOAD_CONTINUE_THREAD 0x4D4C4485
|
||||||
|
|
||||||
|
#define MLOAD_GET_LOAD_BASE 0x4D4C4490
|
||||||
|
#define MLOAD_MEMSET 0x4D4C4491
|
||||||
|
|
||||||
|
#define MLOAD_GET_EHCI_DATA 0x4D4C44A0
|
||||||
|
|
||||||
|
#define MLOAD_SET_ES_IOCTLV 0x4D4C44B0
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// from IOS ELF stripper of neimod
|
||||||
|
|
||||||
|
#define getbe32(x) ((adr[x]<<24) | (adr[x+1]<<16) | (adr[x+2]<<8) | (adr[x+3]))
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 ident0;
|
||||||
|
u32 ident1;
|
||||||
|
u32 ident2;
|
||||||
|
u32 ident3;
|
||||||
|
u32 machinetype;
|
||||||
|
u32 version;
|
||||||
|
u32 entry;
|
||||||
|
u32 phoff;
|
||||||
|
u32 shoff;
|
||||||
|
u32 flags;
|
||||||
|
u16 ehsize;
|
||||||
|
u16 phentsize;
|
||||||
|
u16 phnum;
|
||||||
|
u16 shentsize;
|
||||||
|
u16 shnum;
|
||||||
|
u16 shtrndx;
|
||||||
|
} elfheader;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 type;
|
||||||
|
u32 offset;
|
||||||
|
u32 vaddr;
|
||||||
|
u32 paddr;
|
||||||
|
u32 filesz;
|
||||||
|
u32 memsz;
|
||||||
|
u32 flags;
|
||||||
|
u32 align;
|
||||||
|
} elfphentry;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void *start;
|
||||||
|
int prio;
|
||||||
|
void *stack;
|
||||||
|
int size_stack;
|
||||||
|
} data_elf;
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// to init/test if the device is running
|
||||||
|
|
||||||
|
int mload_init();
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// to close the device (remember call it when rebooting the IOS!)
|
||||||
|
|
||||||
|
int mload_close();
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// to get the thread id of mload
|
||||||
|
|
||||||
|
int mload_get_thread_id();
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// get the base and the size of the memory readable/writable to load modules
|
||||||
|
|
||||||
|
int mload_get_load_base(u32 *starlet_base, int *size);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// load and run a module from starlet (it need to allocate MEM2 to send the elf file)
|
||||||
|
// the module must be a elf made with stripios
|
||||||
|
|
||||||
|
int mload_module(void *addr, int len);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// load a module from the PPC
|
||||||
|
// the module must be a elf made with stripios
|
||||||
|
|
||||||
|
int mload_elf(void *my_elf, data_elf *data_elf);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// run one thread (you can use to load modules or binary files)
|
||||||
|
|
||||||
|
int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// stops one starlet thread
|
||||||
|
|
||||||
|
int mload_stop_thread(int id);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// continue one stopped starlet thread
|
||||||
|
|
||||||
|
int mload_continue_thread(int id);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// fix starlet address to read/write (uses SEEK_SET, etc as mode)
|
||||||
|
|
||||||
|
int mload_seek(int offset, int mode);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// read bytes from starlet (it update the offset)
|
||||||
|
|
||||||
|
int mload_read(void* buf, u32 size);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// write bytes from starlet (it update the offset)
|
||||||
|
|
||||||
|
int mload_write(const void * buf, u32 size);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// fill a block (similar to memset)
|
||||||
|
|
||||||
|
int mload_memset(void *starlet_addr, int set, int len);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// get the ehci datas ( ehcmodule.elf uses this address)
|
||||||
|
|
||||||
|
void * mload_get_ehci_data();
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// set the dev/es ioctlv in routine
|
||||||
|
|
||||||
|
int mload_set_ES_ioctlv_vector(void *starlet_addr);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
86
source/nand.c
Normal file
86
source/nand.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
|
||||||
|
#include "nand.h"
|
||||||
|
|
||||||
|
/* Buffer */
|
||||||
|
static u32 inbuf[8] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
|
||||||
|
s32 Nand_Mount(nandDevice *dev)
|
||||||
|
{
|
||||||
|
s32 fd, ret;
|
||||||
|
|
||||||
|
/* Open FAT module */
|
||||||
|
fd = IOS_Open("fat", 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Mount device */
|
||||||
|
ret = IOS_Ioctlv(fd, dev->mountCmd, 0, 0, NULL);
|
||||||
|
|
||||||
|
/* Close FAT module */
|
||||||
|
IOS_Close(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Nand_Unmount(nandDevice *dev)
|
||||||
|
{
|
||||||
|
s32 fd, ret;
|
||||||
|
|
||||||
|
/* Open FAT module */
|
||||||
|
fd = IOS_Open("fat", 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Unmount device */
|
||||||
|
ret = IOS_Ioctlv(fd, dev->umountCmd, 0, 0, NULL);
|
||||||
|
|
||||||
|
/* Close FAT module */
|
||||||
|
IOS_Close(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Nand_Enable(nandDevice *dev)
|
||||||
|
{
|
||||||
|
s32 fd, ret;
|
||||||
|
|
||||||
|
/* Open /dev/fs */
|
||||||
|
fd = IOS_Open("/dev/fs", 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Set input buffer */
|
||||||
|
inbuf[0] = dev->mode;
|
||||||
|
|
||||||
|
/* Enable NAND emulator */
|
||||||
|
ret = IOS_Ioctl(fd, 100, inbuf, sizeof(inbuf), NULL, 0);
|
||||||
|
|
||||||
|
/* Close /dev/fs */
|
||||||
|
IOS_Close(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Nand_Disable(void)
|
||||||
|
{
|
||||||
|
s32 fd, ret;
|
||||||
|
|
||||||
|
/* Open /dev/fs */
|
||||||
|
fd = IOS_Open("/dev/fs", 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Set input buffer */
|
||||||
|
inbuf[0] = 0;
|
||||||
|
|
||||||
|
/* Disable NAND emulator */
|
||||||
|
ret = IOS_Ioctl(fd, 100, inbuf, sizeof(inbuf), NULL, 0);
|
||||||
|
|
||||||
|
/* Close /dev/fs */
|
||||||
|
IOS_Close(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
24
source/nand.h
Normal file
24
source/nand.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _NAND_H_
|
||||||
|
#define _NAND_H_
|
||||||
|
|
||||||
|
/* 'NAND Device' structure */
|
||||||
|
typedef struct {
|
||||||
|
/* Device name */
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* Mode value */
|
||||||
|
u32 mode;
|
||||||
|
|
||||||
|
/* Un/mount command */
|
||||||
|
u32 mountCmd;
|
||||||
|
u32 umountCmd;
|
||||||
|
} nandDevice;
|
||||||
|
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
s32 Nand_Mount(nandDevice *);
|
||||||
|
s32 Nand_Unmount(nandDevice *);
|
||||||
|
s32 Nand_Enable(nandDevice *);
|
||||||
|
s32 Nand_Disable(void);
|
||||||
|
|
||||||
|
#endif
|
33
source/restart.c
Normal file
33
source/restart.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
|
||||||
|
#include "nand.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "wpad.h"
|
||||||
|
//#include "video.h"
|
||||||
|
|
||||||
|
|
||||||
|
void Restart(void)
|
||||||
|
{
|
||||||
|
printf("\n Beende den WAD-Manager...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Disable NAND emulator */
|
||||||
|
Nand_Disable();
|
||||||
|
|
||||||
|
/* Load system menu */
|
||||||
|
Sys_LoadMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Restart_Wait(void)
|
||||||
|
{
|
||||||
|
printf("\n Dr%ccke eine Taste f%cr den Neustart...",129,129);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Wait for button */
|
||||||
|
Wpad_WaitButtons();
|
||||||
|
|
||||||
|
/* Restart */
|
||||||
|
Restart();
|
||||||
|
}
|
||||||
|
|
8
source/restart.h
Normal file
8
source/restart.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _RESTART_H_
|
||||||
|
#define _RESTART_H_
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
void Restart(void);
|
||||||
|
void Restart_Wait(void);
|
||||||
|
|
||||||
|
#endif
|
177
source/sha1.c
Normal file
177
source/sha1.c
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
SHA-1 in C
|
||||||
|
By Steve Reid <steve@edmweb.com>
|
||||||
|
100% Public Domain
|
||||||
|
|
||||||
|
Test Vectors (from FIPS PUB 180-1)
|
||||||
|
"abc"
|
||||||
|
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||||
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||||
|
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||||
|
A million repetitions of "a"
|
||||||
|
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
|
||||||
|
#define SHA1HANDSOFF
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sha1.h"
|
||||||
|
|
||||||
|
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||||
|
|
||||||
|
/* blk0() and blk() perform the initial expand. */
|
||||||
|
/* I got the idea of expanding during the round function from SSLeay */
|
||||||
|
#ifdef LITTLE_ENDIAN
|
||||||
|
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
||||||
|
|(rol(block->l[i],8)&0x00FF00FF))
|
||||||
|
#else
|
||||||
|
#define blk0(i) block->l[i]
|
||||||
|
#endif
|
||||||
|
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||||
|
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||||
|
|
||||||
|
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||||
|
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||||
|
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||||
|
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||||
|
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||||
|
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long state[5];
|
||||||
|
unsigned long count[2];
|
||||||
|
unsigned char buffer[64];
|
||||||
|
} SHA1_CTX;
|
||||||
|
|
||||||
|
|
||||||
|
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||||
|
|
||||||
|
void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
|
||||||
|
{
|
||||||
|
unsigned long a, b, c, d, e;
|
||||||
|
typedef union {
|
||||||
|
unsigned char c[64];
|
||||||
|
unsigned long l[16];
|
||||||
|
} CHAR64LONG16;
|
||||||
|
CHAR64LONG16* block;
|
||||||
|
#ifdef SHA1HANDSOFF
|
||||||
|
static unsigned char workspace[64];
|
||||||
|
block = (CHAR64LONG16*)workspace;
|
||||||
|
memcpy(block, buffer, 64);
|
||||||
|
#else
|
||||||
|
block = (CHAR64LONG16*)buffer;
|
||||||
|
#endif
|
||||||
|
/* Copy context->state[] to working vars */
|
||||||
|
a = state[0];
|
||||||
|
b = state[1];
|
||||||
|
c = state[2];
|
||||||
|
d = state[3];
|
||||||
|
e = state[4];
|
||||||
|
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||||
|
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||||
|
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||||
|
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||||
|
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||||
|
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||||
|
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||||
|
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||||
|
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||||
|
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||||
|
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||||
|
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||||
|
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||||
|
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||||
|
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||||
|
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||||
|
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||||
|
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||||
|
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||||
|
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||||
|
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||||
|
/* Add the working vars back into context.state[] */
|
||||||
|
state[0] += a;
|
||||||
|
state[1] += b;
|
||||||
|
state[2] += c;
|
||||||
|
state[3] += d;
|
||||||
|
state[4] += e;
|
||||||
|
/* Wipe variables */
|
||||||
|
a = b = c = d = e = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SHA1Init - Initialize new context */
|
||||||
|
|
||||||
|
void SHA1Init(SHA1_CTX* context)
|
||||||
|
{
|
||||||
|
/* SHA1 initialization constants */
|
||||||
|
context->state[0] = 0x67452301;
|
||||||
|
context->state[1] = 0xEFCDAB89;
|
||||||
|
context->state[2] = 0x98BADCFE;
|
||||||
|
context->state[3] = 0x10325476;
|
||||||
|
context->state[4] = 0xC3D2E1F0;
|
||||||
|
context->count[0] = context->count[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Run your data through this. */
|
||||||
|
|
||||||
|
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
j = (context->count[0] >> 3) & 63;
|
||||||
|
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
||||||
|
context->count[1] += (len >> 29);
|
||||||
|
if ((j + len) > 63) {
|
||||||
|
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||||
|
SHA1Transform(context->state, context->buffer);
|
||||||
|
for ( ; i + 63 < len; i += 64) {
|
||||||
|
SHA1Transform(context->state, &data[i]);
|
||||||
|
}
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
else i = 0;
|
||||||
|
memcpy(&context->buffer[j], &data[i], len - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Add padding and return the message digest. */
|
||||||
|
|
||||||
|
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
||||||
|
{
|
||||||
|
unsigned long i, j;
|
||||||
|
unsigned char finalcount[8];
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||||
|
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||||
|
}
|
||||||
|
SHA1Update(context, (unsigned char *)"\200", 1);
|
||||||
|
while ((context->count[0] & 504) != 448) {
|
||||||
|
SHA1Update(context, (unsigned char *)"\0", 1);
|
||||||
|
}
|
||||||
|
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||||
|
for (i = 0; i < 20; i++) {
|
||||||
|
digest[i] = (unsigned char)
|
||||||
|
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||||
|
}
|
||||||
|
/* Wipe variables */
|
||||||
|
i = j = 0;
|
||||||
|
memset(context->buffer, 0, 64);
|
||||||
|
memset(context->state, 0, 20);
|
||||||
|
memset(context->count, 0, 8);
|
||||||
|
memset(&finalcount, 0, 8);
|
||||||
|
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
|
||||||
|
SHA1Transform(context->state, context->buffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
|
||||||
|
SHA1_CTX ctx;
|
||||||
|
|
||||||
|
SHA1Init(&ctx);
|
||||||
|
SHA1Update(&ctx, ptr, size);
|
||||||
|
SHA1Final(outbuf, &ctx);
|
||||||
|
}
|
6
source/sha1.h
Normal file
6
source/sha1.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _SHA1_H_
|
||||||
|
#define _SHA1_H_
|
||||||
|
|
||||||
|
void SHA1(unsigned char *, unsigned int, unsigned char *);
|
||||||
|
|
||||||
|
#endif
|
6
source/stub.S
Normal file
6
source/stub.S
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.rodata
|
||||||
|
|
||||||
|
.globl bgData
|
||||||
|
.balign 32
|
||||||
|
bgData:
|
||||||
|
.incbin "../data/background"
|
188
source/sys.c
Normal file
188
source/sys.c
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
#include "mload.h"
|
||||||
|
#include "ehcmodule_elf.h"
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
#define CERTS_LEN 0x280
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys";
|
||||||
|
|
||||||
|
void __Sys_ResetCallback(void)
|
||||||
|
{
|
||||||
|
/* Reboot console */
|
||||||
|
Sys_Reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __Sys_PowerCallback(void)
|
||||||
|
{
|
||||||
|
/* Poweroff console */
|
||||||
|
Sys_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIOSstub(u8 ios_number)
|
||||||
|
{
|
||||||
|
u32 tmd_size;
|
||||||
|
tmd_view *ios_tmd;
|
||||||
|
|
||||||
|
|
||||||
|
if((boot2version >= 5) && ( ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224)) return true;
|
||||||
|
|
||||||
|
ES_GetTMDViewSize(0x0000000100000000ULL | ios_number, &tmd_size);
|
||||||
|
if (!tmd_size)
|
||||||
|
{
|
||||||
|
//getting size failed. invalid or fake tmd for sure!
|
||||||
|
//gprintf("failed to get tmd for ios %d\n",ios_number);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ios_tmd = (tmd_view *)memalign( 32, (tmd_size+31)&(~31) );
|
||||||
|
if(!ios_tmd)
|
||||||
|
{
|
||||||
|
//gprintf("failed to mem align the TMD struct!\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
memset(ios_tmd , 0, tmd_size);
|
||||||
|
ES_GetTMDView(0x0000000100000000ULL | ios_number, (u8*)ios_tmd , tmd_size);
|
||||||
|
//gprintf("IOS %d is rev %d(0x%x) with tmd size of %u and %u contents\n",ios_number,ios_tmd->title_version,ios_tmd->title_version,tmd_size,ios_tmd->num_contents);
|
||||||
|
/*Stubs have a few things in common:
|
||||||
|
- title version : it is mostly 65280 , or even better : in hex the last 2 digits are 0.
|
||||||
|
example : IOS 60 rev 6400 = 0x1900 = 00 = stub
|
||||||
|
- exception for IOS21 which is active, the tmd size is 592 bytes (or 140 with the views)
|
||||||
|
- the stub ios' have 1 app of their own (type 0x1) and 2 shared apps (type 0x8001).
|
||||||
|
eventho the 00 check seems to work fine , we'll only use other knowledge as well cause some
|
||||||
|
people/applications install an ios with a stub rev >_> ...*/
|
||||||
|
u8 Version = ios_tmd->title_version;
|
||||||
|
|
||||||
|
if((boot2version >= 5) && (ios_number == 249 || ios_number == 250) && (Version < 18)) return true;
|
||||||
|
if(( ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224) && (Version < 4)) return true;
|
||||||
|
//version now contains the last 2 bytes. as said above, if this is 00, its a stub
|
||||||
|
if ( Version == 0 )
|
||||||
|
{
|
||||||
|
if ( ( ios_tmd->num_contents == 3) && (ios_tmd->contents[0].type == 1 && ios_tmd->contents[1].type == 0x8001 && ios_tmd->contents[2].type == 0x8001) )
|
||||||
|
{
|
||||||
|
//gprintf("IOS %d is a stub\n",ios_number);
|
||||||
|
free(ios_tmd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//gprintf("IOS %d is active\n",ios_number);
|
||||||
|
free(ios_tmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//gprintf("IOS %d is active\n",ios_number);
|
||||||
|
free(ios_tmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool loadIOS(int ios)
|
||||||
|
{
|
||||||
|
if(isIOSstub(ios)) return false;
|
||||||
|
mload_close();
|
||||||
|
if(IOS_ReloadIOS(ios)>=0)
|
||||||
|
{
|
||||||
|
if (IOS_GetVersion() != 249 && IOS_GetVersion() != 250)
|
||||||
|
{
|
||||||
|
if (mload_init() >= 0)
|
||||||
|
{
|
||||||
|
data_elf my_data_elf;
|
||||||
|
mload_elf((void *) ehcmodule_elf, &my_data_elf);
|
||||||
|
mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, 0x47);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_Init(void)
|
||||||
|
{
|
||||||
|
/* Initialize video subsytem */
|
||||||
|
VIDEO_Init();
|
||||||
|
|
||||||
|
/* Set RESET/POWER button callback */
|
||||||
|
SYS_SetResetCallback(__Sys_ResetCallback);
|
||||||
|
SYS_SetPowerCallback(__Sys_PowerCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_Reboot(void)
|
||||||
|
{
|
||||||
|
/* Restart console */
|
||||||
|
STM_RebootSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_Shutdown(void)
|
||||||
|
{
|
||||||
|
/* Poweroff console */
|
||||||
|
if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) {
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Set LED mode */
|
||||||
|
ret = CONF_GetIdleLedMode();
|
||||||
|
if(ret >= 0 && ret <= 2)
|
||||||
|
STM_SetLedMode(ret);
|
||||||
|
|
||||||
|
/* Shutdown to idle */
|
||||||
|
STM_ShutdownToIdle();
|
||||||
|
} else {
|
||||||
|
/* Shutdown to standby */
|
||||||
|
STM_ShutdownToStandby();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_LoadMenu(void)
|
||||||
|
{
|
||||||
|
int HBC = 0;
|
||||||
|
char * sig = (char *)0x80001804;
|
||||||
|
if(
|
||||||
|
sig[0] == 'S' &&
|
||||||
|
sig[1] == 'T' &&
|
||||||
|
sig[2] == 'U' &&
|
||||||
|
sig[3] == 'B' &&
|
||||||
|
sig[4] == 'H' &&
|
||||||
|
sig[5] == 'A' &&
|
||||||
|
sig[6] == 'X' &&
|
||||||
|
sig[7] == 'X')
|
||||||
|
HBC=1; // Exit to HBC
|
||||||
|
|
||||||
|
|
||||||
|
/* Homebrew Channel stub */
|
||||||
|
if (HBC == 1)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
/* Return to the Wii system menu */
|
||||||
|
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Sys_GetCerts(signed_blob **certs, u32 *len)
|
||||||
|
{
|
||||||
|
static signed_blob certificates[CERTS_LEN] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
s32 fd, ret;
|
||||||
|
|
||||||
|
/* Open certificates file */
|
||||||
|
fd = IOS_Open(certs_fs, 1);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Read certificates */
|
||||||
|
ret = IOS_Read(fd, certificates, sizeof(certificates));
|
||||||
|
|
||||||
|
/* Close file */
|
||||||
|
IOS_Close(fd);
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
if (ret > 0) {
|
||||||
|
*certs = certificates;
|
||||||
|
*len = sizeof(certificates);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
14
source/sys.h
Normal file
14
source/sys.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _SYS_H_
|
||||||
|
#define _SYS_H_
|
||||||
|
|
||||||
|
u32 boot2version;
|
||||||
|
/* Prototypes */
|
||||||
|
bool isIOSstub(u8 ios_number);
|
||||||
|
bool loadIOS(int ios);
|
||||||
|
void Sys_Init(void);
|
||||||
|
void Sys_Reboot(void);
|
||||||
|
void Sys_Shutdown(void);
|
||||||
|
void Sys_LoadMenu(void);
|
||||||
|
s32 Sys_GetCerts(signed_blob **, u32 *);
|
||||||
|
|
||||||
|
#endif
|
324
source/title.c
Normal file
324
source/title.c
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
|
||||||
|
#include "sha1.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
s32 Title_ZeroSignature(signed_blob *p_sig)
|
||||||
|
{
|
||||||
|
u8 *ptr = (u8 *)p_sig;
|
||||||
|
|
||||||
|
/* Fill signature with zeroes */
|
||||||
|
memset(ptr + 4, 0, SIGNATURE_SIZE(p_sig) - 4);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_FakesignTik(signed_blob *p_tik)
|
||||||
|
{
|
||||||
|
tik *tik_data = NULL;
|
||||||
|
u16 fill;
|
||||||
|
|
||||||
|
/* Zero signature */
|
||||||
|
Title_ZeroSignature(p_tik);
|
||||||
|
|
||||||
|
/* Ticket data */
|
||||||
|
tik_data = (tik *)SIGNATURE_PAYLOAD(p_tik);
|
||||||
|
|
||||||
|
for (fill = 0; fill < USHRT_MAX; fill++) {
|
||||||
|
sha1 hash;
|
||||||
|
|
||||||
|
/* Modify ticket padding field */
|
||||||
|
tik_data->padding = fill;
|
||||||
|
|
||||||
|
/* Calculate hash */
|
||||||
|
SHA1((u8 *)tik_data, sizeof(tik), hash);
|
||||||
|
|
||||||
|
/* Found valid hash */
|
||||||
|
if (!hash[0])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_FakesignTMD(signed_blob *p_tmd)
|
||||||
|
{
|
||||||
|
tmd *tmd_data = NULL;
|
||||||
|
u16 fill;
|
||||||
|
|
||||||
|
/* Zero signature */
|
||||||
|
Title_ZeroSignature(p_tmd);
|
||||||
|
|
||||||
|
/* TMD data */
|
||||||
|
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||||
|
|
||||||
|
for (fill = 0; fill < USHRT_MAX; fill++) {
|
||||||
|
sha1 hash;
|
||||||
|
|
||||||
|
/* Modify TMD fill field */
|
||||||
|
tmd_data->fill3 = fill;
|
||||||
|
|
||||||
|
/* Calculate hash */
|
||||||
|
SHA1((u8 *)tmd_data, TMD_SIZE(tmd_data), hash);
|
||||||
|
|
||||||
|
/* Found valid hash */
|
||||||
|
if (!hash[0])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_GetList(u64 **outbuf, u32 *outlen)
|
||||||
|
{
|
||||||
|
u64 *titles = NULL;
|
||||||
|
|
||||||
|
u32 len, nb_titles;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Get number of titles */
|
||||||
|
ret = ES_GetNumTitles(&nb_titles);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Calculate buffer lenght */
|
||||||
|
len = round_up(sizeof(u64) * nb_titles, 32);
|
||||||
|
|
||||||
|
/* Allocate memory */
|
||||||
|
titles = memalign(32, len);
|
||||||
|
if (!titles)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Get titles */
|
||||||
|
ret = ES_GetTitles(titles, nb_titles);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
*outbuf = titles;
|
||||||
|
*outlen = nb_titles;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* Free memory */
|
||||||
|
if (titles)
|
||||||
|
free(titles);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_GetTicketViews(u64 tid, tikview **outbuf, u32 *outlen)
|
||||||
|
{
|
||||||
|
tikview *views = NULL;
|
||||||
|
|
||||||
|
u32 nb_views;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Get number of ticket views */
|
||||||
|
ret = ES_GetNumTicketViews(tid, &nb_views);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Allocate memory */
|
||||||
|
views = (tikview *)memalign(32, sizeof(tikview) * nb_views);
|
||||||
|
if (!views)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Get ticket views */
|
||||||
|
ret = ES_GetTicketViews(tid, views, nb_views);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
*outbuf = views;
|
||||||
|
*outlen = nb_views;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* Free memory */
|
||||||
|
if (views)
|
||||||
|
free(views);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_GetTMD(u64 tid, signed_blob **outbuf, u32 *outlen)
|
||||||
|
{
|
||||||
|
void *p_tmd = NULL;
|
||||||
|
|
||||||
|
u32 len;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Get TMD size */
|
||||||
|
ret = ES_GetStoredTMDSize(tid, &len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Allocate memory */
|
||||||
|
p_tmd = memalign(32, round_up(len, 32));
|
||||||
|
if (!p_tmd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Read TMD */
|
||||||
|
ret = ES_GetStoredTMD(tid, p_tmd, len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
*outbuf = p_tmd;
|
||||||
|
*outlen = len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* Free memory */
|
||||||
|
if (p_tmd)
|
||||||
|
free(p_tmd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_GetVersion(u64 tid, u16 *outbuf)
|
||||||
|
{
|
||||||
|
signed_blob *p_tmd = NULL;
|
||||||
|
tmd *tmd_data = NULL;
|
||||||
|
|
||||||
|
u32 len;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Get title TMD */
|
||||||
|
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Retrieve TMD info */
|
||||||
|
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
*outbuf = tmd_data->title_version;
|
||||||
|
|
||||||
|
/* Free memory */
|
||||||
|
free(p_tmd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_GetSysVersion(u64 tid, u64 *outbuf)
|
||||||
|
{
|
||||||
|
signed_blob *p_tmd = NULL;
|
||||||
|
tmd *tmd_data = NULL;
|
||||||
|
|
||||||
|
u32 len;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Get title TMD */
|
||||||
|
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Retrieve TMD info */
|
||||||
|
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
*outbuf = tmd_data->sys_version;
|
||||||
|
|
||||||
|
/* Free memory */
|
||||||
|
free(p_tmd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_GetSize(u64 tid, u32 *outbuf)
|
||||||
|
{
|
||||||
|
signed_blob *p_tmd = NULL;
|
||||||
|
tmd *tmd_data = NULL;
|
||||||
|
|
||||||
|
u32 cnt, len, size = 0;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Get title TMD */
|
||||||
|
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Retrieve TMD info */
|
||||||
|
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||||
|
|
||||||
|
/* Calculate title size */
|
||||||
|
for (cnt = 0; cnt < tmd_data->num_contents; cnt++) {
|
||||||
|
tmd_content *content = &tmd_data->contents[cnt];
|
||||||
|
|
||||||
|
/* Add content size */
|
||||||
|
size += content->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
*outbuf = size;
|
||||||
|
|
||||||
|
/* Free memory */
|
||||||
|
free(p_tmd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen)
|
||||||
|
{
|
||||||
|
u8 *buffer = NULL;
|
||||||
|
u64 *list = NULL;
|
||||||
|
|
||||||
|
u32 count, cnt, idx;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Get title list */
|
||||||
|
ret = Title_GetList(&list, &count);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Count IOS */
|
||||||
|
for (cnt = idx = 0; idx < count; idx++) {
|
||||||
|
u32 tidh = (list[idx] >> 32);
|
||||||
|
u32 tidl = (list[idx] & 0xFFFFFFFF);
|
||||||
|
|
||||||
|
/* Title is IOS */
|
||||||
|
if ((tidh == 0x1) && (tidl >= 3) && (tidl <= 255))
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate memory */
|
||||||
|
buffer = (u8 *)memalign(32, cnt);
|
||||||
|
if (!buffer) {
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy IOS */
|
||||||
|
for (cnt = idx = 0; idx < count; idx++) {
|
||||||
|
u32 tidh = (list[idx] >> 32);
|
||||||
|
u32 tidl = (list[idx] & 0xFFFFFFFF);
|
||||||
|
|
||||||
|
/* Title is IOS */
|
||||||
|
if ((tidh == 0x1) && (tidl >= 3) && (tidl <= 255))
|
||||||
|
buffer[cnt++] = (u8)(tidl & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
*outbuf = buffer;
|
||||||
|
*outlen = cnt;
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Free memory */
|
||||||
|
if (list)
|
||||||
|
free(list);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
19
source/title.h
Normal file
19
source/title.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _TITLE_H_
|
||||||
|
#define _TITLE_H_
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
#define BLOCK_SIZE 1024
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
s32 Title_ZeroSignature(signed_blob *);
|
||||||
|
s32 Title_FakesignTik(signed_blob *);
|
||||||
|
s32 Title_FakesignTMD(signed_blob *);
|
||||||
|
s32 Title_GetList(u64 **, u32 *);
|
||||||
|
s32 Title_GetTicketViews(u64, tikview **, u32 *);
|
||||||
|
s32 Title_GetTMD(u64, signed_blob **, u32 *);
|
||||||
|
s32 Title_GetVersion(u64, u16 *);
|
||||||
|
s32 Title_GetSysVersion(u64, u64 *);
|
||||||
|
s32 Title_GetSize(u64, u32 *);
|
||||||
|
s32 Title_GetIOSVersions(u8 **, u32 *);
|
||||||
|
|
||||||
|
#endif
|
400
source/usbstorage.c
Normal file
400
source/usbstorage.c
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
/*-------------------------------------------------------------
|
||||||
|
|
||||||
|
usbstorage_starlet.c -- USB mass storage support, inside starlet
|
||||||
|
Copyright (C) 2009 Kwiirk
|
||||||
|
|
||||||
|
If this driver is linked before libogc, this will replace the original
|
||||||
|
usbstorage driver by svpe from libogc
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any
|
||||||
|
damages arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any
|
||||||
|
purpose, including commercial applications, and to alter it and
|
||||||
|
redistribute it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you
|
||||||
|
must not claim that you wrote the original software. If you use
|
||||||
|
this software in a product, an acknowledgment in the product
|
||||||
|
documentation would be appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and
|
||||||
|
must not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* IOCTL commands */
|
||||||
|
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
|
||||||
|
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
|
||||||
|
#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
|
||||||
|
#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
|
||||||
|
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
|
||||||
|
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
|
||||||
|
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
|
||||||
|
#define USB_IOCTL_UMS_UNMOUNT (UMS_BASE+0x10)
|
||||||
|
#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
|
||||||
|
|
||||||
|
#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
|
||||||
|
#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
|
||||||
|
#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
|
||||||
|
#define USB_IOCTL_WBFS_READ_DEBUG (WBFS_BASE+0x3)
|
||||||
|
#define USB_IOCTL_WBFS_SET_DEVICE (WBFS_BASE+0x4)
|
||||||
|
#define USB_IOCTL_WBFS_SET_FRAGLIST (WBFS_BASE+0x5)
|
||||||
|
|
||||||
|
#define UMS_HEAPSIZE 0x1000
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2";
|
||||||
|
static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc";
|
||||||
|
static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/usb123";
|
||||||
|
|
||||||
|
static s32 hid = -1, fd = -1;
|
||||||
|
static u32 sector_size;
|
||||||
|
|
||||||
|
s32 USBStorage_GetCapacity(u32 *_sector_size) {
|
||||||
|
if (fd > 0) {
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size);
|
||||||
|
|
||||||
|
if (ret && _sector_size)
|
||||||
|
*_sector_size = sector_size;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage_Init(void) {
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Already open */
|
||||||
|
if (fd > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Create heap */
|
||||||
|
if (hid < 0) {
|
||||||
|
hid = iosCreateHeap(UMS_HEAPSIZE);
|
||||||
|
if (hid < 0)
|
||||||
|
return IPC_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open USB device */
|
||||||
|
fd = IOS_Open(fs, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
fd = IOS_Open(fs2, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
fd = IOS_Open(fs3, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Initialize USB storage */
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":");
|
||||||
|
if (ret<0) goto err;
|
||||||
|
|
||||||
|
/* Get device capacity */
|
||||||
|
ret = USBStorage_GetCapacity(NULL);
|
||||||
|
if (!ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* Close USB device */
|
||||||
|
if (fd > 0) {
|
||||||
|
IOS_Close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Hermes **/
|
||||||
|
s32 USBStorage_Watchdog(u32 on_off) {
|
||||||
|
if (fd >= 0) {
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WATCHDOG, "i:", on_off);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage_Umount(void) {
|
||||||
|
if (fd >= 0) {
|
||||||
|
s32 ret;
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_UNMOUNT, ":");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBStorage_Deinit(void) {
|
||||||
|
/* Close USB device */
|
||||||
|
if (fd > 0) {
|
||||||
|
IOS_Close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) {
|
||||||
|
|
||||||
|
// void *buf = (void *)buffer;
|
||||||
|
u32 len = (sector_size * numSectors);
|
||||||
|
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Device not opened */
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buffer, len);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) {
|
||||||
|
u32 len = (sector_size * numSectors);
|
||||||
|
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Device not opened */
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Write data */
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buffer, len);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __io_usb_Startup(void)
|
||||||
|
{
|
||||||
|
return USBStorage_Init() >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __io_usb_IsInserted(void)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
if (fd < 0) return false;
|
||||||
|
ret = USBStorage_GetCapacity(NULL);
|
||||||
|
if (ret == 0) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __io_usb_ReadSectors(u32 sector, u32 count, void *buffer)
|
||||||
|
{
|
||||||
|
s32 ret = USBStorage_ReadSectors(sector, count, buffer);
|
||||||
|
return ret > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __io_usb_WriteSectors(u32 sector, u32 count, void *buffer)
|
||||||
|
{
|
||||||
|
s32 ret = USBStorage_WriteSectors(sector, count, buffer);
|
||||||
|
return ret > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __io_usb_ClearStatus(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __io_usb_Shutdown(void)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __io_usb_NOP(void)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DISC_INTERFACE __io_usbstorage_ro = {
|
||||||
|
DEVICE_TYPE_WII_USB,
|
||||||
|
FEATURE_MEDIUM_CANREAD | FEATURE_WII_USB,
|
||||||
|
(FN_MEDIUM_STARTUP) &__io_usb_Startup,
|
||||||
|
(FN_MEDIUM_ISINSERTED) &__io_usb_IsInserted,
|
||||||
|
(FN_MEDIUM_READSECTORS) &__io_usb_ReadSectors,
|
||||||
|
(FN_MEDIUM_WRITESECTORS) &__io_usb_NOP, //&__io_usb_WriteSectors,
|
||||||
|
(FN_MEDIUM_CLEARSTATUS) &__io_usb_ClearStatus,
|
||||||
|
(FN_MEDIUM_SHUTDOWN) &__io_usb_Shutdown
|
||||||
|
};
|
||||||
|
|
||||||
|
s32 USBStorage_WBFS_Open(char *buffer)
|
||||||
|
{
|
||||||
|
u32 len = 8;
|
||||||
|
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Device not opened */
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
extern u32 wbfs_part_lba;
|
||||||
|
u32 part = wbfs_part_lba;
|
||||||
|
|
||||||
|
/* Read data */
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_OPEN_DISC, "dd:", buffer, len, &part, 4);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// woffset is in 32bit words, len is in bytes
|
||||||
|
s32 USBStorage_WBFS_Read(u32 woffset, u32 len, void *buffer)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
USBStorage_Init();
|
||||||
|
/* Device not opened */
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Read data */
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_READ_DISC, "ii:d", woffset, len, buffer, len);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 USBStorage_WBFS_ReadDebug(u32 off, u32 size, void *buffer)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
USBStorage_Init();
|
||||||
|
/* Device not opened */
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Read data */
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_READ_DEBUG, "ii:d", off, size, buffer, size);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 USBStorage_WBFS_SetDevice(int dev)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
static s32 retval = 0;
|
||||||
|
retval = 0;
|
||||||
|
USBStorage_Init();
|
||||||
|
// Device not opened
|
||||||
|
if (fd < 0) return fd;
|
||||||
|
// ioctl
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_SET_DEVICE, "i:i", dev, &retval);
|
||||||
|
if (retval) return retval;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage_WBFS_SetFragList(void *p, int size)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
USBStorage_Init();
|
||||||
|
// Device not opened
|
||||||
|
if (fd < 0) return fd;
|
||||||
|
// ioctl
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_WBFS_SET_FRAGLIST, "d:", p, size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEVICE_TYPE_WII_UMS (('W'<<24)|('U'<<16)|('M'<<8)|'S')
|
||||||
|
|
||||||
|
bool umsio_Startup() {
|
||||||
|
return USBStorage_Init() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool umsio_IsInserted() {
|
||||||
|
return true; // allways true
|
||||||
|
}
|
||||||
|
|
||||||
|
bool umsio_ReadSectors(sec_t sector, sec_t numSectors, u8 *buffer) {
|
||||||
|
u32 cnt = 0;
|
||||||
|
s32 ret;
|
||||||
|
/* Do reads */
|
||||||
|
while (cnt < numSectors) {
|
||||||
|
u32 sectors = (numSectors - cnt);
|
||||||
|
|
||||||
|
/* Read sectors is too big */
|
||||||
|
if (sectors > 32)
|
||||||
|
sectors = 32;
|
||||||
|
|
||||||
|
/* USB read */
|
||||||
|
ret = USBStorage_ReadSectors(sector + cnt, sectors, &buffer[cnt*512]);
|
||||||
|
if (ret < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Increment counter */
|
||||||
|
cnt += sectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool umsio_WriteSectors(sec_t sector, sec_t numSectors, const u8* buffer) {
|
||||||
|
u32 cnt = 0;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Do writes */
|
||||||
|
while (cnt < numSectors) {
|
||||||
|
u32 sectors = (numSectors - cnt);
|
||||||
|
|
||||||
|
/* Write sectors is too big */
|
||||||
|
if (sectors > 32)
|
||||||
|
sectors = 32;
|
||||||
|
|
||||||
|
/* USB write */
|
||||||
|
ret = USBStorage_WriteSectors(sector + cnt, sectors, &buffer[cnt * 512]);
|
||||||
|
if (ret < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Increment counter */
|
||||||
|
cnt += sectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool umsio_ClearStatus(void) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool umsio_Shutdown() {
|
||||||
|
USBStorage_Deinit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DISC_INTERFACE __io_wiiums = {
|
||||||
|
DEVICE_TYPE_WII_UMS,
|
||||||
|
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
|
||||||
|
(FN_MEDIUM_STARTUP) &umsio_Startup,
|
||||||
|
(FN_MEDIUM_ISINSERTED) &umsio_IsInserted,
|
||||||
|
(FN_MEDIUM_READSECTORS) &umsio_ReadSectors,
|
||||||
|
(FN_MEDIUM_WRITESECTORS) &umsio_WriteSectors,
|
||||||
|
(FN_MEDIUM_CLEARSTATUS) &umsio_ClearStatus,
|
||||||
|
(FN_MEDIUM_SHUTDOWN) &umsio_Shutdown
|
||||||
|
};
|
||||||
|
|
||||||
|
const DISC_INTERFACE __io_wiiums_ro = {
|
||||||
|
DEVICE_TYPE_WII_UMS,
|
||||||
|
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
|
||||||
|
(FN_MEDIUM_STARTUP) &umsio_Startup,
|
||||||
|
(FN_MEDIUM_ISINSERTED) &umsio_IsInserted,
|
||||||
|
(FN_MEDIUM_READSECTORS) &umsio_ReadSectors,
|
||||||
|
(FN_MEDIUM_WRITESECTORS) &__io_usb_NOP,
|
||||||
|
(FN_MEDIUM_CLEARSTATUS) &umsio_ClearStatus,
|
||||||
|
(FN_MEDIUM_SHUTDOWN) &umsio_Shutdown
|
||||||
|
};
|
27
source/usbstorage.h
Normal file
27
source/usbstorage.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _USBSTORAGE_H_
|
||||||
|
#define _USBSTORAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* Prototypes */
|
||||||
|
s32 USBStorage_GetCapacity(u32 *);
|
||||||
|
s32 USBStorage_Init(void);
|
||||||
|
void USBStorage_Deinit(void);
|
||||||
|
s32 USBStorage_Watchdog(u32 on_off);
|
||||||
|
s32 USBStorage_ReadSectors(u32, u32, void *);
|
||||||
|
s32 USBStorage_WriteSectors(u32, u32, const void *);
|
||||||
|
|
||||||
|
s32 USBStorage_WBFS_Open(char *buf_id);
|
||||||
|
s32 USBStorage_WBFS_Read(u32 woffset, u32 len, void *buffer);
|
||||||
|
s32 USBStorage_WBFS_ReadDebug(u32 off, u32 size, void *buffer);
|
||||||
|
s32 USBStorage_WBFS_SetDevice(int dev);
|
||||||
|
s32 USBStorage_WBFS_SetFragList(void *p, int size);
|
||||||
|
|
||||||
|
extern const DISC_INTERFACE __io_wiiums;
|
||||||
|
extern const DISC_INTERFACE __io_wiiums_ro;
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
15
source/utils.h
Normal file
15
source/utils.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _UTILS_H_
|
||||||
|
#define _UTILS_H_
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
#define KB_SIZE 1024.0
|
||||||
|
#define MB_SIZE 1048576.0
|
||||||
|
#define GB_SIZE 1073741824.0
|
||||||
|
|
||||||
|
/* Macros */
|
||||||
|
#define round_up(x,n) (-(-(x) & -(n)))
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
u32 swap32(u32);
|
||||||
|
|
||||||
|
#endif
|
141
source/video.c
Normal file
141
source/video.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
#include "video.h"
|
||||||
|
|
||||||
|
/* Video variables */
|
||||||
|
static void *framebuffer = NULL;
|
||||||
|
static GXRModeObj *vmode = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void Con_Init(u32 x, u32 y, u32 w, u32 h)
|
||||||
|
{
|
||||||
|
/* Create console in the framebuffer */
|
||||||
|
CON_InitEx(vmode, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Con_Clear(void)
|
||||||
|
{
|
||||||
|
/* Clear console */
|
||||||
|
printf("\x1b[2J");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Con_ClearLine(void)
|
||||||
|
{
|
||||||
|
s32 cols, rows;
|
||||||
|
u32 cnt;
|
||||||
|
|
||||||
|
printf("\r");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Get console metrics */
|
||||||
|
CON_GetMetrics(&cols, &rows);
|
||||||
|
|
||||||
|
/* Erase line */
|
||||||
|
for (cnt = 1; cnt < cols; cnt++) {
|
||||||
|
printf(" ");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\r");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Con_FgColor(u32 color, u8 bold)
|
||||||
|
{
|
||||||
|
/* Set foreground color */
|
||||||
|
printf("\x1b[%u;%um", color + 30, bold);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Con_BgColor(u32 color, u8 bold)
|
||||||
|
{
|
||||||
|
/* Set background color */
|
||||||
|
printf("\x1b[%u;%um", color + 40, bold);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Con_FillRow(u32 row, u32 color, u8 bold)
|
||||||
|
{
|
||||||
|
s32 cols, rows;
|
||||||
|
u32 cnt;
|
||||||
|
|
||||||
|
/* Set color */
|
||||||
|
printf("\x1b[%u;%um", color + 40, bold);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Get console metrics */
|
||||||
|
CON_GetMetrics(&cols, &rows);
|
||||||
|
|
||||||
|
/* Save current row and col */
|
||||||
|
printf("\x1b[s");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Move to specified row */
|
||||||
|
printf("\x1b[%u;0H", row);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Fill row */
|
||||||
|
for (cnt = 0; cnt < cols; cnt++) {
|
||||||
|
printf(" ");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load saved row and col */
|
||||||
|
printf("\x1b[u");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Set default color */
|
||||||
|
Con_BgColor(0, 0);
|
||||||
|
Con_FgColor(7, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video_Configure(GXRModeObj *rmode)
|
||||||
|
{
|
||||||
|
/* Configure the video subsystem */
|
||||||
|
VIDEO_Configure(rmode);
|
||||||
|
|
||||||
|
/* Setup video */
|
||||||
|
VIDEO_SetBlack(FALSE);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
if (rmode->viTVMode & VI_NON_INTERLACE)
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video_SetMode(void)
|
||||||
|
{
|
||||||
|
/* Select preferred video mode */
|
||||||
|
vmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
|
||||||
|
/* Allocate memory for the framebuffer */
|
||||||
|
framebuffer = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
|
||||||
|
|
||||||
|
/* Configure the video subsystem */
|
||||||
|
VIDEO_Configure(vmode);
|
||||||
|
|
||||||
|
/* Setup video */
|
||||||
|
VIDEO_SetNextFramebuffer(framebuffer);
|
||||||
|
VIDEO_SetBlack(FALSE);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
if (vmode->viTVMode & VI_NON_INTERLACE)
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
/* Clear the screen */
|
||||||
|
Video_Clear(COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video_Clear(s32 color)
|
||||||
|
{
|
||||||
|
VIDEO_ClearFrameBuffer(vmode, framebuffer, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video_DrawPng(IMGCTX ctx, PNGUPROP imgProp, u16 x, u16 y)
|
||||||
|
{
|
||||||
|
PNGU_DECODE_TO_COORDS_YCbYCr(ctx, x, y, imgProp.imgWidth, imgProp.imgHeight, vmode->fbWidth, vmode->xfbHeight, framebuffer);
|
||||||
|
}
|
19
source/video.h
Normal file
19
source/video.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _VIDEO_H_
|
||||||
|
#define _VIDEO_H_
|
||||||
|
|
||||||
|
#include "libpng/pngu/pngu.h"
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
void Con_Init(u32, u32, u32, u32);
|
||||||
|
void Con_Clear(void);
|
||||||
|
void Con_ClearLine(void);
|
||||||
|
void Con_FgColor(u32, u8);
|
||||||
|
void Con_BgColor(u32, u8);
|
||||||
|
void Con_FillRow(u32, u32, u8);
|
||||||
|
|
||||||
|
void Video_Configure(GXRModeObj *);
|
||||||
|
void Video_SetMode(void);
|
||||||
|
void Video_Clear(s32);
|
||||||
|
void Video_DrawPng(IMGCTX, PNGUPROP, u16, u16);
|
||||||
|
|
||||||
|
#endif
|
494
source/wad-manager.c
Normal file
494
source/wad-manager.c
Normal file
@ -0,0 +1,494 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <wiilight.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <runtimeiospatch.h>
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "restart.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "wpad.h"
|
||||||
|
#include "fat.h"
|
||||||
|
#include "nand.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "xyzzy.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
CONFIG gConfig;
|
||||||
|
|
||||||
|
// Prototypes
|
||||||
|
extern u32 WaitButtons (void);
|
||||||
|
void CheckPassword (void);
|
||||||
|
void SetDefaultConfig (void);
|
||||||
|
int ReadConfigFile (char *configFilePath);
|
||||||
|
int GetIntParam (char *inputStr);
|
||||||
|
int GetStartupPath (char *startupPath, char *inputStr);
|
||||||
|
int GetStringParam (char *outParam, char *inputStr, int maxChars);
|
||||||
|
|
||||||
|
// Default password Up-Down-Left-Right-Up-Down
|
||||||
|
//#define PASSWORD "UDLRUD"
|
||||||
|
void CheckPassword (void)
|
||||||
|
{
|
||||||
|
char curPassword [11]; // Max 10 characters password, NULL terminated
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (strlen (gConfig.password) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ask user for a password. Press "B" to restart Wii
|
||||||
|
printf("[+] [Kennwort eingeben, um fortzufahren]:\n\n");
|
||||||
|
|
||||||
|
printf(">> Dr%ccke (A) zum Fortfahren.\n",129);
|
||||||
|
printf(">> Dr%ccke [B] zum Beenden.\n", 129);
|
||||||
|
|
||||||
|
/* Wait for user answer */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
if (buttons & WPAD_BUTTON_A)
|
||||||
|
{
|
||||||
|
// A button, validate the pw
|
||||||
|
curPassword [count] = 0;
|
||||||
|
//if (strcmp (curPassword, PASSWORD) == 0)
|
||||||
|
if (strcmp (curPassword, gConfig.password) == 0)
|
||||||
|
{
|
||||||
|
printf(">> Kennwort akzeptiert...\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("\n");
|
||||||
|
printf(">> Falsches Kennwort. Versuchen Sie es erneut...\n");
|
||||||
|
printf("[+] [Kennwort eingeben, um fortzufahren]:\n\n");
|
||||||
|
printf(">> Dr%ccke (A) zum Fortfahren.\n",129);
|
||||||
|
printf(">> Dr%ccke [B] zum Beenden.\n", 129);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_B)
|
||||||
|
// B button, restart
|
||||||
|
Restart();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (count < 10)
|
||||||
|
{
|
||||||
|
// Other buttons, build the password
|
||||||
|
if (buttons & WPAD_BUTTON_LEFT)
|
||||||
|
{
|
||||||
|
curPassword [count++] = 'L';
|
||||||
|
printf ("*");
|
||||||
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_RIGHT)
|
||||||
|
{
|
||||||
|
curPassword [count++] = 'R';
|
||||||
|
printf ("*");
|
||||||
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_UP)
|
||||||
|
{
|
||||||
|
curPassword [count++] = 'U';
|
||||||
|
printf ("*");
|
||||||
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_DOWN)
|
||||||
|
{
|
||||||
|
curPassword [count++] = 'D';
|
||||||
|
printf ("*");
|
||||||
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_1)
|
||||||
|
{
|
||||||
|
curPassword [count++] = '1';
|
||||||
|
printf ("*");
|
||||||
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_2)
|
||||||
|
{
|
||||||
|
curPassword [count++] = '2';
|
||||||
|
printf ("*");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disclaimer(void)
|
||||||
|
{
|
||||||
|
/* Print disclaimer */
|
||||||
|
printf("[+] [DISCLAIMER]:\n\n");
|
||||||
|
|
||||||
|
printf(" THIS APPLICATION COMES WITH NO WARRANTY AT ALL,\n");
|
||||||
|
printf(" NEITHER EXPRESS NOR IMPLIED.\n");
|
||||||
|
printf(" I DO NOT TAKE ANY RESPONSIBILITY FOR ANY DAMAGE IN YOUR\n");
|
||||||
|
printf(" WII CONSOLE BECAUSE OF A IMPROPER USAGE OF THIS SOFTWARE.\n\n");
|
||||||
|
printf(" Die Autoren dieses Programms %cbernehmen keine Haftung\n",129);
|
||||||
|
printf(" f%cr Sch%cden, die durch die Benutzung hervorgerufen werden.\n",129,132);
|
||||||
|
printf(" Wenn deine Konsole brickt, tr%cgst du alleine die Verantwortung\n",132);
|
||||||
|
printf(" daf%cr.\n\n",129);
|
||||||
|
|
||||||
|
printf(">> Dr%ccke (A) zum Fortfahren .\n", 129);
|
||||||
|
printf(">> Andernfalls, dr%ccke [B] f%cr einen Neustart.\n",129,129);
|
||||||
|
|
||||||
|
/* Wait for user answer */
|
||||||
|
for (;;) {
|
||||||
|
// u32 buttons = Wpad_WaitButtons();
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
/* A button */
|
||||||
|
if (buttons & WPAD_BUTTON_A)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* B button */
|
||||||
|
if (buttons & WPAD_BUTTON_B)
|
||||||
|
Restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void farbe(void)
|
||||||
|
{
|
||||||
|
/* Print disclaimer */
|
||||||
|
Con_BgColor(0, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(0, 0);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(1, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(1, 0);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(2, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(2, 0);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(3, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(3, 0);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(4, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(4, 0);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(5, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(5, 0);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(6, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(6, 0);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(7, 1);
|
||||||
|
printf(" \n");
|
||||||
|
Con_BgColor(7, 0);
|
||||||
|
printf(" \n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Wait for user answer */
|
||||||
|
for (;;) {
|
||||||
|
// u32 buttons = Wpad_WaitButtons();
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
/* A button */
|
||||||
|
if (buttons & WPAD_BUTTON_HOME)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
ES_GetBoot2Version(&boot2version);
|
||||||
|
/*
|
||||||
|
if(boot2version < 5)
|
||||||
|
{
|
||||||
|
if(!loadIOS(202)) if(!loadIOS(222)) if(!loadIOS(223)) if(!loadIOS(224)) if(!loadIOS(249)) loadIOS(36);
|
||||||
|
}else{
|
||||||
|
if(!loadIOS(249)) loadIOS(36);
|
||||||
|
}
|
||||||
|
*/ /* Initialize subsystems */
|
||||||
|
Sys_Init();
|
||||||
|
|
||||||
|
/* Set video mode */
|
||||||
|
Video_SetMode();
|
||||||
|
|
||||||
|
/* Initialize console */
|
||||||
|
Gui_InitConsole();
|
||||||
|
|
||||||
|
/* Draw background */
|
||||||
|
Gui_DrawBackground();
|
||||||
|
|
||||||
|
if (have_ahbprot()) {
|
||||||
|
fatDevice *fdev = &fdevList[0];
|
||||||
|
Fat_Unmount(fdev);
|
||||||
|
|
||||||
|
IosPatch_RUNTIME(true, true, true, true);
|
||||||
|
|
||||||
|
Fat_Mount(fdev);
|
||||||
|
keydump();
|
||||||
|
Fat_Unmount(fdev);
|
||||||
|
|
||||||
|
sleep(2);
|
||||||
|
Con_Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize Wiimote and GC Controller */
|
||||||
|
Wpad_Init();
|
||||||
|
PAD_Init ();
|
||||||
|
WIILIGHT_Init();
|
||||||
|
|
||||||
|
/* Print disclaimer */
|
||||||
|
// farbe();
|
||||||
|
Disclaimer();
|
||||||
|
|
||||||
|
// Set the defaults
|
||||||
|
SetDefaultConfig ();
|
||||||
|
|
||||||
|
// Read the config file
|
||||||
|
ReadConfigFile (WM_CONFIG_FILE_PATH);
|
||||||
|
|
||||||
|
// Check password
|
||||||
|
CheckPassword ();
|
||||||
|
|
||||||
|
/* Menu loop */
|
||||||
|
Menu_Loop();
|
||||||
|
|
||||||
|
/* Restart Wii */
|
||||||
|
Restart_Wait();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ReadConfigFile (char *configFilePath)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
FILE *fptr;
|
||||||
|
char *tmpStr = malloc (MAX_FILE_PATH_LEN);
|
||||||
|
char tmpOutStr [40], path[128];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (tmpStr == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
fatDevice *fdev = &fdevList[0];
|
||||||
|
s32 ret = Fat_Mount(fdev);
|
||||||
|
snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fdev = &fdevList[2];
|
||||||
|
ret = Fat_Mount(fdev);
|
||||||
|
snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
||||||
|
snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
printf(" FEHLER! (ret = %d)\n", ret);
|
||||||
|
// goto err;
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Read the file
|
||||||
|
fptr = fopen (path, "rb");
|
||||||
|
if (fptr != NULL)
|
||||||
|
{
|
||||||
|
// Read the options
|
||||||
|
char done = 0;
|
||||||
|
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
if (fgets (tmpStr, MAX_FILE_PATH_LEN, fptr) == NULL)
|
||||||
|
done = 1;
|
||||||
|
else if (isalpha(tmpStr[0]))
|
||||||
|
{
|
||||||
|
// Get the password
|
||||||
|
if (strncmp (tmpStr, "Password", 8) == 0)
|
||||||
|
{
|
||||||
|
// Get password
|
||||||
|
// GetPassword (gConfig.password, tmpStr);
|
||||||
|
GetStringParam (gConfig.password, tmpStr, MAX_PASSWORD_LENGTH);
|
||||||
|
|
||||||
|
// If password is too long, ignore it
|
||||||
|
if (strlen (gConfig.password) > 10)
|
||||||
|
{
|
||||||
|
gConfig.password [0] = 0;
|
||||||
|
printf ("Kennwort länger als 10 Zeichen werden ignoriert. Drücken Sie eine Taste...\n");
|
||||||
|
WaitButtons ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get startup path
|
||||||
|
else if (strncmp (tmpStr, "StartupPath", 11) == 0)
|
||||||
|
{
|
||||||
|
// Get startup Path
|
||||||
|
GetStartupPath (gConfig.startupPath, tmpStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cIOS
|
||||||
|
else if (strncmp (tmpStr, "cIOSVersion", 11) == 0)
|
||||||
|
{
|
||||||
|
// Get cIOSVersion
|
||||||
|
gConfig.cIOSVersion = (u8)GetIntParam (tmpStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FatDevice
|
||||||
|
else if (strncmp (tmpStr, "FatDevice", 9) == 0)
|
||||||
|
{
|
||||||
|
// Get fatDevice
|
||||||
|
GetStringParam (tmpOutStr, tmpStr, MAX_FAT_DEVICE_LENGTH);
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
if (strncmp (fdevList[i].mount, tmpOutStr, 4) == 0)
|
||||||
|
{
|
||||||
|
gConfig.fatDeviceIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NandDevice
|
||||||
|
else if (strncmp (tmpStr, "NANDDevice", 10) == 0)
|
||||||
|
{
|
||||||
|
// Get fatDevice
|
||||||
|
GetStringParam (tmpOutStr, tmpStr, MAX_NAND_DEVICE_LENGTH);
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (strncmp (ndevList[i].name, tmpOutStr, 2) == 0)
|
||||||
|
{
|
||||||
|
gConfig.nandDeviceIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // EndWhile
|
||||||
|
|
||||||
|
// Close the config file
|
||||||
|
fclose (fptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the wm_config.txt file is not found, just take the default config params
|
||||||
|
//printf ("Config file is not found\n"); // This is for testing only
|
||||||
|
//WaitButtons();
|
||||||
|
}
|
||||||
|
Fat_Unmount(fdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free memory
|
||||||
|
free (tmpStr);
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
} // ReadConfig
|
||||||
|
|
||||||
|
|
||||||
|
void SetDefaultConfig (void)
|
||||||
|
{
|
||||||
|
// Default password is NULL or no password
|
||||||
|
gConfig.password [0] = 0;
|
||||||
|
|
||||||
|
// Default startup folder
|
||||||
|
strcpy (gConfig.startupPath, WAD_DIRECTORY);
|
||||||
|
|
||||||
|
gConfig.cIOSVersion = CIOS_VERSION_INVALID; // Means that user has to select later
|
||||||
|
gConfig.fatDeviceIndex = FAT_DEVICE_INDEX_INVALID; // Means that user has to select
|
||||||
|
gConfig.nandDeviceIndex = NAND_DEVICE_INDEX_INVALID; // Means that user has to select
|
||||||
|
|
||||||
|
} // SetDefaultConfig
|
||||||
|
|
||||||
|
|
||||||
|
int GetStartupPath (char *startupPath, char *inputStr)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int len = strlen (inputStr);
|
||||||
|
|
||||||
|
// Find the "="
|
||||||
|
while ((inputStr [i] != '=') && (i < len))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Get to the "/"
|
||||||
|
while ((inputStr [i] != '/') && (i < len))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the startup Path
|
||||||
|
int count = 0;
|
||||||
|
while (isascii(inputStr [i]) && (i < len) && (inputStr [i] != '\n') &&
|
||||||
|
(inputStr [i] != '\r') && (inputStr [i] != ' '))
|
||||||
|
{
|
||||||
|
startupPath [count++] = inputStr [i++];
|
||||||
|
}
|
||||||
|
startupPath [count] = 0; // NULL terminate
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
} // GetStartupPath
|
||||||
|
|
||||||
|
int GetIntParam (char *inputStr)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
int i = 0;
|
||||||
|
int len = strlen (inputStr);
|
||||||
|
char outParam [40];
|
||||||
|
|
||||||
|
// Find the "="
|
||||||
|
while ((inputStr [i] != '=') && (i < len))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Get to the first alpha numeric character
|
||||||
|
while ((isdigit(inputStr [i]) == 0) && (i < len))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the string param
|
||||||
|
int outCount = 0;
|
||||||
|
while ((isdigit(inputStr [i])) && (i < len) && (outCount < 40))
|
||||||
|
{
|
||||||
|
outParam [outCount++] = inputStr [i++];
|
||||||
|
}
|
||||||
|
outParam [outCount] = 0; // NULL terminate
|
||||||
|
retval = atoi (outParam);
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
} // GetIntParam
|
||||||
|
|
||||||
|
|
||||||
|
int GetStringParam (char *outParam, char *inputStr, int maxChars)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int len = strlen (inputStr);
|
||||||
|
|
||||||
|
// Find the "="
|
||||||
|
while ((inputStr [i] != '=') && (i < len))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Get to the first alpha character
|
||||||
|
while ((isalpha(inputStr [i]) == 0) && (i < len))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the string param
|
||||||
|
int outCount = 0;
|
||||||
|
while ((isalnum(inputStr [i])) && (i < len) && (outCount < maxChars))
|
||||||
|
{
|
||||||
|
outParam [outCount++] = inputStr [i++];
|
||||||
|
}
|
||||||
|
outParam [outCount] = 0; // NULL terminate
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
} // GetStringParam
|
797
source/wad.c
Normal file
797
source/wad.c
Normal file
@ -0,0 +1,797 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <ogc/pad.h>
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
#include "title.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "wad.h"
|
||||||
|
#include "wpad.h"
|
||||||
|
|
||||||
|
// Turn upper and lower into a full title ID
|
||||||
|
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
|
||||||
|
// Get upper or lower half of a title ID
|
||||||
|
#define TITLE_UPPER(x) ((u32)((x) >> 32))
|
||||||
|
#define TITLE_LOWER(x) ((u32)(x))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int version;
|
||||||
|
int region;
|
||||||
|
|
||||||
|
} SMRegion;
|
||||||
|
|
||||||
|
SMRegion regionlist[] = {
|
||||||
|
{33, 'X'},
|
||||||
|
{128, 'J'}, {97, 'E'}, {130, 'P'},
|
||||||
|
{162, 'P'},
|
||||||
|
{192, 'J'}, {193, 'E'}, {194, 'P'},
|
||||||
|
{224, 'J'}, {225, 'E'}, {226, 'P'},
|
||||||
|
{256, 'J'}, {257, 'E'}, {258, 'P'},
|
||||||
|
{288, 'J'}, {289, 'E'}, {290, 'P'},
|
||||||
|
{352, 'J'}, {353, 'E'}, {354, 'P'}, {326, 'K'},
|
||||||
|
{384, 'J'}, {385, 'E'}, {386, 'P'},
|
||||||
|
{390, 'K'},
|
||||||
|
{416, 'J'}, {417, 'E'}, {418, 'P'},
|
||||||
|
{448, 'J'}, {449, 'E'}, {450, 'P'}, {454, 'K'},
|
||||||
|
{480, 'J'}, {481, 'E'}, {482, 'P'}, {486, 'K'},
|
||||||
|
{512, 'E'}, {513, 'E'}, {514, 'P'}, {518, 'K'},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NB_SM (sizeof(regionlist) / sizeof(SMRegion))
|
||||||
|
|
||||||
|
static u8 wadBuffer[BLOCK_SIZE] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
u32 WaitButtons(void);
|
||||||
|
|
||||||
|
u32 be32(const u8 *p)
|
||||||
|
{
|
||||||
|
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 be64(const u8 *p)
|
||||||
|
{
|
||||||
|
return ((u64)be32(p) << 32) | be32(p + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 get_title_ios(u64 title) {
|
||||||
|
s32 ret, fd;
|
||||||
|
static char filepath[256] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
// Check to see if title exists
|
||||||
|
if (ES_GetDataDir(title, filepath) >= 0 ) {
|
||||||
|
u32 tmd_size;
|
||||||
|
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
ret = ES_GetStoredTMDSize(title, &tmd_size);
|
||||||
|
if (ret < 0){
|
||||||
|
// If we fail to use the ES function, try reading manually
|
||||||
|
// This is a workaround added since some IOS (like 21) don't like our
|
||||||
|
// call to ES_GetStoredTMDSize
|
||||||
|
|
||||||
|
//printf("Error! ES_GetStoredTMDSize: %d\n", ret);
|
||||||
|
|
||||||
|
sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title));
|
||||||
|
|
||||||
|
ret = ISFS_Open(filepath, ISFS_OPEN_READ);
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
//printf("Error! ISFS_Open (ret = %d)\n", ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = ret;
|
||||||
|
|
||||||
|
ret = ISFS_Seek(fd, 0x184, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
//printf("Error! ISFS_Seek (ret = %d)\n", ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ISFS_Read(fd,tmd_buf,8);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
//printf("Error! ISFS_Read (ret = %d)\n", ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ISFS_Close(fd);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
//printf("Error! ISFS_Close (ret = %d)\n", ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return be64(tmd_buf);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Normal versions of IOS won't have a problem, so we do things the "right" way.
|
||||||
|
|
||||||
|
// Some of this code adapted from bushing's title_lister.c
|
||||||
|
signed_blob *s_tmd = (signed_blob *)tmd_buf;
|
||||||
|
ret = ES_GetStoredTMD(title, s_tmd, tmd_size);
|
||||||
|
if (ret < 0){
|
||||||
|
//printf("Error! ES_GetStoredTMD: %d\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmd *t = SIGNATURE_PAYLOAD(s_tmd);
|
||||||
|
return t->sys_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_sm_region_basic()
|
||||||
|
{
|
||||||
|
u32 tmd_size;
|
||||||
|
|
||||||
|
u64 title = TITLE_ID(1, 2);
|
||||||
|
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
int ret = ES_GetStoredTMDSize(title, &tmd_size);
|
||||||
|
|
||||||
|
// Some of this code adapted from bushing's title_lister.c
|
||||||
|
signed_blob *s_tmd = (signed_blob *)tmd_buf;
|
||||||
|
ret = ES_GetStoredTMD(title, s_tmd, tmd_size);
|
||||||
|
if (ret < 0){
|
||||||
|
//printf("Error! ES_GetStoredTMD: %d\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmd *t = SIGNATURE_PAYLOAD(s_tmd);
|
||||||
|
ret = t->title_version;
|
||||||
|
int i = 0;
|
||||||
|
while( i <= NB_SM)
|
||||||
|
{
|
||||||
|
if( regionlist[i].version == ret) return regionlist[i].region;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'WAD Header' structure */
|
||||||
|
typedef struct {
|
||||||
|
/* Header length */
|
||||||
|
u32 header_len;
|
||||||
|
|
||||||
|
/* WAD type */
|
||||||
|
u16 type;
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
u16 padding;
|
||||||
|
|
||||||
|
/* Data length */
|
||||||
|
u32 certs_len;
|
||||||
|
u32 crl_len;
|
||||||
|
u32 tik_len;
|
||||||
|
u32 tmd_len;
|
||||||
|
u32 data_len;
|
||||||
|
u32 footer_len;
|
||||||
|
} ATTRIBUTE_PACKED wadHeader;
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
static u8 wadBuffer[BLOCK_SIZE] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
|
||||||
|
s32 __Wad_ReadFile(FILE *fp, void *outbuf, u32 offset, u32 len)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Seek to offset */
|
||||||
|
fseek(fp, offset, SEEK_SET);
|
||||||
|
|
||||||
|
/* Read data */
|
||||||
|
ret = fread(outbuf, len, 1, fp);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 __Wad_ReadAlloc(FILE *fp, void **outbuf, u32 offset, u32 len)
|
||||||
|
{
|
||||||
|
void *buffer = NULL;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Allocate memory */
|
||||||
|
buffer = memalign(32, len);
|
||||||
|
if (!buffer)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Read file */
|
||||||
|
ret = __Wad_ReadFile(fp, buffer, offset, len);
|
||||||
|
if (ret < 0) {
|
||||||
|
free(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set pointer */
|
||||||
|
*outbuf = buffer;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 __Wad_GetTitleID(FILE *fp, wadHeader *header, u64 *tid)
|
||||||
|
{
|
||||||
|
signed_blob *p_tik = NULL;
|
||||||
|
tik *tik_data = NULL;
|
||||||
|
|
||||||
|
u32 offset = 0;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Ticket offset */
|
||||||
|
offset += round_up(header->header_len, 64);
|
||||||
|
offset += round_up(header->certs_len, 64);
|
||||||
|
offset += round_up(header->crl_len, 64);
|
||||||
|
|
||||||
|
/* Read ticket */
|
||||||
|
ret = __Wad_ReadAlloc(fp, (void *)&p_tik, offset, header->tik_len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Ticket data */
|
||||||
|
tik_data = (tik *)SIGNATURE_PAYLOAD(p_tik);
|
||||||
|
|
||||||
|
/* Copy title ID */
|
||||||
|
*tid = tik_data->titleid;
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Free memory */
|
||||||
|
if (p_tik)
|
||||||
|
free(p_tik);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __Wad_FixTicket(signed_blob *p_tik)
|
||||||
|
{
|
||||||
|
u8 *data = (u8 *)p_tik;
|
||||||
|
u8 *ckey = data + 0x1F1;
|
||||||
|
|
||||||
|
/* Check common key */
|
||||||
|
if (*ckey > 1)
|
||||||
|
*ckey = 0;
|
||||||
|
|
||||||
|
/* Fakesign ticket */
|
||||||
|
Title_FakesignTik(p_tik);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Wad_Install(FILE *fp, fatFile *file)
|
||||||
|
{
|
||||||
|
wadHeader *header = NULL;
|
||||||
|
signed_blob *p_certs = NULL, *p_crl = NULL, *p_tik = NULL, *p_tmd = NULL;
|
||||||
|
|
||||||
|
tmd *tmd_data = NULL;
|
||||||
|
|
||||||
|
u32 cnt, offset = 0;
|
||||||
|
s32 ret;
|
||||||
|
u64 tid;
|
||||||
|
|
||||||
|
printf("\t\t>> Lese WAD-Daten...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
ret = __Wad_ReadAlloc(fp, (void *)&header, offset, sizeof(wadHeader));
|
||||||
|
if (ret >= 0)
|
||||||
|
offset += round_up(header->header_len, 64);
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
//Don't try to install boot2
|
||||||
|
__Wad_GetTitleID(fp, header, &tid);
|
||||||
|
|
||||||
|
if (tid == TITLE_ID(1, 1))
|
||||||
|
{
|
||||||
|
printf("\n Das kann ich nicht zulassen\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WAD certificates */
|
||||||
|
ret = __Wad_ReadAlloc(fp, (void *)&p_certs, offset, header->certs_len);
|
||||||
|
if (ret >= 0)
|
||||||
|
offset += round_up(header->certs_len, 64);
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* WAD crl */
|
||||||
|
if (header->crl_len) {
|
||||||
|
ret = __Wad_ReadAlloc(fp, (void *)&p_crl, offset, header->crl_len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
else
|
||||||
|
offset += round_up(header->crl_len, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WAD ticket */
|
||||||
|
ret = __Wad_ReadAlloc(fp, (void *)&p_tik, offset, header->tik_len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
else
|
||||||
|
offset += round_up(header->tik_len, 64);
|
||||||
|
|
||||||
|
/* WAD TMD */
|
||||||
|
ret = __Wad_ReadAlloc(fp, (void *)&p_tmd, offset, header->tmd_len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
else
|
||||||
|
offset += round_up(header->tmd_len, 64);
|
||||||
|
|
||||||
|
Con_ClearLine();
|
||||||
|
|
||||||
|
/* Get TMD info */
|
||||||
|
|
||||||
|
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||||
|
|
||||||
|
if(TITLE_LOWER(tmd_data->sys_version) != NULL && isIOSstub(TITLE_LOWER(tmd_data->sys_version)))
|
||||||
|
{
|
||||||
|
printf("\n Diese Wad braucht IOS%i aber die installierte version\n ist ein stub.\n", TITLE_LOWER(tmd_data->sys_version));
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(get_title_ios(TITLE_ID(1, 2)) == tid)
|
||||||
|
{
|
||||||
|
if ( ( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001) )
|
||||||
|
{
|
||||||
|
printf("\n Ich installiere kein Stub f%cr das Systemmen%c\n", 129, 129);
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'K')))
|
||||||
|
{
|
||||||
|
if ( ( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001) )
|
||||||
|
{
|
||||||
|
printf("\n Ich installiere kein Stub f%cr die EULA\n", 129);
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'K')))
|
||||||
|
{
|
||||||
|
if ( ( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001) )
|
||||||
|
{
|
||||||
|
printf("\n Ich installiere kein Stub f%cr rgsel IOS\n", 129);
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tid == get_title_ios(TITLE_ID(0x10001, 0x48415858)) || tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449)))
|
||||||
|
{
|
||||||
|
if ( ( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001) )
|
||||||
|
{
|
||||||
|
printf("\n Sind Sie sicher, ein Stub vom HBC zu installieren?\n");
|
||||||
|
printf("\n Dr%ccke (A) zum Fortfahren.\n",129);
|
||||||
|
printf(" Dr%ccke [B] zum %cberspringen.", 129, 154);
|
||||||
|
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
if (!(buttons & WPAD_BUTTON_A))
|
||||||
|
{
|
||||||
|
ret = -998;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tid == TITLE_ID(1, 2))
|
||||||
|
{
|
||||||
|
if(get_sm_region_basic() == 0)
|
||||||
|
{
|
||||||
|
printf("\n Kann die Region vom Systemmen%c nicht ermitteln\n", 129);
|
||||||
|
printf("\n Dr%ccke (A) zum Fortfahren.\n",129);
|
||||||
|
printf(" Dr%ccke [B] zum %cberspringen.", 129, 154);
|
||||||
|
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
if (!(buttons & WPAD_BUTTON_A))
|
||||||
|
{
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int i, ret = -1;
|
||||||
|
for(i = 0; i <= NB_SM; i++)
|
||||||
|
{
|
||||||
|
if( regionlist[i].version == tmd_data->title_version)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ret -1)
|
||||||
|
{
|
||||||
|
printf("\n Kann die Region vom Systemmen%c nicht ermitteln\n", 129);
|
||||||
|
printf("\n Dr%ccke (A) zum Fortfahren.\n",129);
|
||||||
|
printf(" Dr%ccke [B] zum %cberspringen.", 129, 154);
|
||||||
|
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
if (!(buttons & WPAD_BUTTON_A))
|
||||||
|
{
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( get_sm_region_basic() != regionlist[i].region)
|
||||||
|
{
|
||||||
|
printf("\n Falsche Regionen f%crs Systemmen%c\n", 129, 129);
|
||||||
|
printf("\n Dr%ccke (A) zum Fortfahren.\n",129);
|
||||||
|
printf(" Dr%ccke [B] zum %cberspringen.", 129, 154);
|
||||||
|
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
if (!(buttons & WPAD_BUTTON_A))
|
||||||
|
{
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(tmd_data->title_version < 416)
|
||||||
|
{
|
||||||
|
if(boot2version == 4)
|
||||||
|
{
|
||||||
|
printf("\n Diese Version des Systemmen%cs\n ist nicht kompatibel mit Ihrer Wii\n", 129);
|
||||||
|
ret = -999;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix ticket */
|
||||||
|
__Wad_FixTicket(p_tik);
|
||||||
|
|
||||||
|
printf("\t\t>> Installiere Ticket...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Install ticket */
|
||||||
|
ret = ES_AddTicket(p_tik, header->tik_len, p_certs, header->certs_len, p_crl, header->crl_len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
Con_ClearLine();
|
||||||
|
|
||||||
|
printf("\r\t\t>> Installiere Title...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Install title */
|
||||||
|
ret = ES_AddTitleStart(p_tmd, header->tmd_len, p_certs, header->certs_len, p_crl, header->crl_len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Install contents */
|
||||||
|
for (cnt = 0; cnt < tmd_data->num_contents; cnt++) {
|
||||||
|
tmd_content *content = &tmd_data->contents[cnt];
|
||||||
|
|
||||||
|
u32 idx = 0, len;
|
||||||
|
s32 cfd;
|
||||||
|
|
||||||
|
Con_ClearLine();
|
||||||
|
|
||||||
|
printf("\r\t\t>> Installiere Inhalt #%02d...", content->cid);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Encrypted content size */
|
||||||
|
len = round_up(content->size, 64);
|
||||||
|
|
||||||
|
/* Install content */
|
||||||
|
cfd = ES_AddContentStart(tmd_data->title_id, content->cid);
|
||||||
|
if (cfd < 0) {
|
||||||
|
ret = cfd;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Install content data */
|
||||||
|
while (idx < len) {
|
||||||
|
u32 size;
|
||||||
|
|
||||||
|
/* Data length */
|
||||||
|
size = (len - idx);
|
||||||
|
if (size > BLOCK_SIZE)
|
||||||
|
size = BLOCK_SIZE;
|
||||||
|
|
||||||
|
/* Read data */
|
||||||
|
ret = __Wad_ReadFile(fp, &wadBuffer, offset, size);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Install data */
|
||||||
|
ret = ES_AddContentData(cfd, wadBuffer, size);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Increase variables */
|
||||||
|
idx += size;
|
||||||
|
offset += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finish content installation */
|
||||||
|
ret = ES_AddContentFinish(cfd);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
Con_ClearLine();
|
||||||
|
|
||||||
|
printf("\r\t\t>> Beende Installation...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Finish title install */
|
||||||
|
ret = ES_AddTitleFinish();
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
if(file->old_ios != file->new_ios || file->old_ahbprot != file->new_ahbprot || file->old_pass != file->new_pass)
|
||||||
|
{
|
||||||
|
Con_ClearLine();
|
||||||
|
|
||||||
|
printf("\r\t\t>> Patche TMD");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
ISFS_Initialize();
|
||||||
|
|
||||||
|
s32 fd;
|
||||||
|
|
||||||
|
char filepath[ISFS_MAXPATH];
|
||||||
|
sprintf(filepath, "/title/%08x/%08x/content/title.tmd", file->high_id, file->low_id);
|
||||||
|
|
||||||
|
static fstats filestats ATTRIBUTE_ALIGN(32);
|
||||||
|
static u8 filearray[1024] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
fd = ISFS_Open(filepath, ISFS_OPEN_READ);
|
||||||
|
if (fd <= 0)
|
||||||
|
ISFS_Close(fd);
|
||||||
|
|
||||||
|
ISFS_GetFileStats(fd, &filestats);
|
||||||
|
ISFS_Read(fd, filearray, filestats.file_length);
|
||||||
|
ISFS_Close(fd);
|
||||||
|
|
||||||
|
if(filestats.file_length >= 0)
|
||||||
|
{
|
||||||
|
fd = ISFS_Open(filepath, ISFS_OPEN_RW);
|
||||||
|
|
||||||
|
filearray[395] = file->new_ios;
|
||||||
|
if(file->new_ahbprot)
|
||||||
|
{
|
||||||
|
filearray[472] = 0;
|
||||||
|
filearray[473] = 0;
|
||||||
|
filearray[474] = 0;
|
||||||
|
filearray[475] = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filearray[472] = 0;
|
||||||
|
filearray[473] = 0;
|
||||||
|
filearray[474] = 0;
|
||||||
|
filearray[475] = 0;
|
||||||
|
}
|
||||||
|
if(!file->new_pass)
|
||||||
|
filearray[417] = 0;
|
||||||
|
else
|
||||||
|
filearray[417] = 16;
|
||||||
|
|
||||||
|
ISFS_Write(fd, filearray, sizeof( filearray ));
|
||||||
|
ISFS_Close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISFS_Deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" OK!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
printf(" FEHLER! (ret = %d)\n", ret);
|
||||||
|
|
||||||
|
/* Cancel install */
|
||||||
|
ES_AddTitleCancel();
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Free memory */
|
||||||
|
if (header)
|
||||||
|
free(header);
|
||||||
|
if (p_certs)
|
||||||
|
free(p_certs);
|
||||||
|
if (p_crl)
|
||||||
|
free(p_crl);
|
||||||
|
if (p_tik)
|
||||||
|
free(p_tik);
|
||||||
|
if (p_tmd)
|
||||||
|
free(p_tmd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Wad_Uninstall(FILE *fp)
|
||||||
|
{
|
||||||
|
wadHeader *header = NULL;
|
||||||
|
tikview *viewData = NULL;
|
||||||
|
|
||||||
|
u64 tid;
|
||||||
|
u32 viewCnt;
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
printf("\t\t>> Reading WAD data...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* WAD header */
|
||||||
|
ret = __Wad_ReadAlloc(fp, (void *)&header, 0, sizeof(wadHeader));
|
||||||
|
if (ret < 0) {
|
||||||
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get title ID */
|
||||||
|
ret = __Wad_GetTitleID(fp, header, &tid);
|
||||||
|
if (ret < 0) {
|
||||||
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
//Assorted Checks
|
||||||
|
if (TITLE_UPPER(tid) == 1 && get_title_ios(TITLE_ID(1, 2)) == 0)
|
||||||
|
{
|
||||||
|
printf("\n I can't determine the System Menus IOS\nDeleting system titles is disabled\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (tid == TITLE_ID(1, 1))
|
||||||
|
{
|
||||||
|
printf("\n I won't try to uninstall boot2\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (tid == TITLE_ID(1, 2))
|
||||||
|
{
|
||||||
|
printf("\n I won't uninstall the System Menu\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(get_title_ios(TITLE_ID(1, 2)) == tid)
|
||||||
|
{
|
||||||
|
printf("\n I won't uninstall the System Menus IOS\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (tid == get_title_ios(TITLE_ID(0x10001, 0x48415858)) || tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449)))
|
||||||
|
{
|
||||||
|
printf("\n This is the HBCs IOS, uninstalling will break the HBC!\n");
|
||||||
|
printf("\n Press A to continue.\n");
|
||||||
|
printf(" Press B skip.");
|
||||||
|
|
||||||
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
|
if (!(buttons & WPAD_BUTTON_A))
|
||||||
|
{
|
||||||
|
ret = -998;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if((tid == TITLE_ID(0x10008, 0x48414B00 | 'E') || tid == TITLE_ID(0x10008, 0x48414B00 | 'P') || tid == TITLE_ID(0x10008, 0x48414B00 | 'J') || tid == TITLE_ID(0x10008, 0x48414B00 | 'K')
|
||||||
|
|| (tid == TITLE_ID(0x10008, 0x48414C00 | 'E') || tid == TITLE_ID(0x10008, 0x48414C00 | 'P') || tid == TITLE_ID(0x10008, 0x48414C00 | 'J') || tid == TITLE_ID(0x10008, 0x48414C00 | 'K'))) && get_sm_region_basic() == 0)
|
||||||
|
{
|
||||||
|
printf("\n Can't get the SM region\n Please check the site for updates\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(tid == TITLE_ID(0x10008, 0x48414B00 | get_sm_region_basic()))
|
||||||
|
{
|
||||||
|
printf("\n I won't uninstall the EULA\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(tid == TITLE_ID(0x10008, 0x48414C00 | get_sm_region_basic()))
|
||||||
|
{
|
||||||
|
printf("\n I won't uninstall rgsel\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | get_sm_region_basic())))
|
||||||
|
{
|
||||||
|
printf("\n I won't uninstall the EULAs IOS\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | get_sm_region_basic())))
|
||||||
|
{
|
||||||
|
printf("\n I won't uninstall the rgsel IOS\n");
|
||||||
|
ret = -999;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
Con_ClearLine();
|
||||||
|
|
||||||
|
printf("\t\t>> Deleting tickets...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Get ticket views */
|
||||||
|
ret = Title_GetTicketViews(tid, &viewData, &viewCnt);
|
||||||
|
if (ret < 0)
|
||||||
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
|
|
||||||
|
/* Delete tickets */
|
||||||
|
if (ret >= 0) {
|
||||||
|
u32 cnt;
|
||||||
|
|
||||||
|
/* Delete all tickets */
|
||||||
|
for (cnt = 0; cnt < viewCnt; cnt++) {
|
||||||
|
ret = ES_DeleteTicket(&viewData[cnt]);
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
printf(" ERROR! (ret = %d\n", ret);
|
||||||
|
else
|
||||||
|
printf(" OK!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\t\t>> Deleting title contents...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Delete title contents */
|
||||||
|
ret = ES_DeleteTitleContent(tid);
|
||||||
|
if (ret < 0)
|
||||||
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
|
else
|
||||||
|
printf(" OK!\n");
|
||||||
|
|
||||||
|
|
||||||
|
printf("\t\t>> Deleting title...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Delete title */
|
||||||
|
ret = ES_DeleteTitle(tid);
|
||||||
|
if (ret < 0)
|
||||||
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
|
else
|
||||||
|
printf(" OK!\n");
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Free memory */
|
||||||
|
if (header)
|
||||||
|
free(header);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wad_Read(FILE *fp, int *ios, bool *ahbprot, bool *pass, u32 *high_id, u32 *low_id)
|
||||||
|
{
|
||||||
|
wadHeader *header = NULL;
|
||||||
|
|
||||||
|
/* WAD header */
|
||||||
|
__Wad_ReadAlloc(fp, (void *)&header, 0, sizeof(wadHeader));
|
||||||
|
__Wad_ReadFile(fp, &wadBuffer, 3328, header->tmd_len);
|
||||||
|
|
||||||
|
|
||||||
|
*ios = wadBuffer[395];
|
||||||
|
if(ios > 0)
|
||||||
|
{
|
||||||
|
if(wadBuffer[472] == 0 && wadBuffer[473] == 0 && wadBuffer[474] == 0 && wadBuffer[475] == 3)
|
||||||
|
*ahbprot = true;
|
||||||
|
else
|
||||||
|
*ahbprot = false;
|
||||||
|
|
||||||
|
if(wadBuffer[417] < 16)
|
||||||
|
*pass = false;
|
||||||
|
else
|
||||||
|
*pass = true;
|
||||||
|
|
||||||
|
signed_blob *p_tmd = NULL;
|
||||||
|
|
||||||
|
__Wad_ReadAlloc(fp, (void *)&p_tmd, 3328, header->tmd_len);
|
||||||
|
tmd *tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||||
|
|
||||||
|
*high_id = TITLE_UPPER(tmd_data->title_id);
|
||||||
|
*low_id = TITLE_LOWER(tmd_data->title_id);
|
||||||
|
|
||||||
|
if (p_tmd)
|
||||||
|
free(p_tmd);
|
||||||
|
}
|
||||||
|
if (header)
|
||||||
|
free(header);
|
||||||
|
}
|
9
source/wad.h
Normal file
9
source/wad.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _WAD_H_
|
||||||
|
#define _WAD_H_
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
s32 Wad_Install(FILE *, fatFile *file);
|
||||||
|
s32 Wad_Uninstall(FILE *);
|
||||||
|
void Wad_Read(FILE *, int *ios, bool *ahbprot, bool *pass, u32 *high_id, u32 *low_id);
|
||||||
|
#endif
|
47
source/wkb.c
Normal file
47
source/wkb.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "wkb.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
s32 USBKeyboard_Open(const eventcallback cb);
|
||||||
|
void USBKeyboard_Close(void);
|
||||||
|
|
||||||
|
bool USBKeyboard_IsConnected(void);
|
||||||
|
s32 USBKeyboard_Scan(void);
|
||||||
|
|
||||||
|
s32 USBKeyboard_SetLed(const USBKeyboard_led led, bool on);
|
||||||
|
s32 USBKeyboard_ToggleLed(const USBKeyboard_led led);
|
||||||
|
*/
|
||||||
|
|
||||||
|
s32 WkbInit(void)
|
||||||
|
{
|
||||||
|
s32 retval = 0;
|
||||||
|
|
||||||
|
retval = USBKeyboard_Initialize();
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
|
||||||
|
} // WkbInit
|
||||||
|
|
||||||
|
s32 WkbDeInit(void)
|
||||||
|
{
|
||||||
|
s32 retval = 0;
|
||||||
|
|
||||||
|
retval = USBKeyboard_Deinitialize();
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
|
||||||
|
} // WkbDeInit
|
||||||
|
|
||||||
|
u32 WkbWaitKey (void)
|
||||||
|
{
|
||||||
|
u32 retval = 0;
|
||||||
|
|
||||||
|
// Stub
|
||||||
|
return (retval);
|
||||||
|
|
||||||
|
} // WkbWaitKey
|
||||||
|
|
||||||
|
//void Wpad_Disconnect(void);
|
||||||
|
//u32 Wpad_GetButtons(void);
|
||||||
|
|
||||||
|
|
19
source/wkb.h
Normal file
19
source/wkb.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _WKB_H_
|
||||||
|
#define _WKB_H_
|
||||||
|
|
||||||
|
//#include <stdio.h>
|
||||||
|
//#include <stdlib.h>
|
||||||
|
//#include <string.h>
|
||||||
|
//#include <malloc.h>
|
||||||
|
#include <ogcsys.h> // u8, u16, etc...
|
||||||
|
|
||||||
|
#include <wiikeyboard/keyboard.h>
|
||||||
|
#include <wiikeyboard/usbkeyboard.h>
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
s32 WkbInit(void);
|
||||||
|
u32 WkbWaitKey (void);
|
||||||
|
//void Wpad_Disconnect(void);
|
||||||
|
//u32 Wpad_GetButtons(void);
|
||||||
|
|
||||||
|
#endif
|
105
source/wpad.c
Normal file
105
source/wpad.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
#include "wpad.h"
|
||||||
|
//#include "wkb.h"
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
#define MAX_WIIMOTES 4
|
||||||
|
|
||||||
|
int start;
|
||||||
|
|
||||||
|
void __Wpad_PowerCallback(s32 chan)
|
||||||
|
{
|
||||||
|
/* Poweroff console */
|
||||||
|
Sys_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32 Wpad_Init(void)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
/* Initialize Wiimote subsystem */
|
||||||
|
ret = WPAD_Init();
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Set POWER button callback */
|
||||||
|
WPAD_SetPowerButtonCallback(__Wpad_PowerCallback);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wpad_Disconnect(void)
|
||||||
|
{
|
||||||
|
u32 cnt;
|
||||||
|
|
||||||
|
/* Disconnect Wiimotes */
|
||||||
|
for (cnt = 0; cnt < MAX_WIIMOTES; cnt++)
|
||||||
|
WPAD_Disconnect(cnt);
|
||||||
|
|
||||||
|
/* Shutdown Wiimote subsystem */
|
||||||
|
WPAD_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Wpad_GetButtons(void)
|
||||||
|
{
|
||||||
|
u32 buttons = 0, cnt;
|
||||||
|
|
||||||
|
/* Scan pads */
|
||||||
|
WPAD_ScanPads();
|
||||||
|
|
||||||
|
/* Get pressed buttons */
|
||||||
|
for (cnt = 0; cnt < MAX_WIIMOTES; cnt++)
|
||||||
|
buttons |= WPAD_ButtonsDown(cnt);
|
||||||
|
|
||||||
|
return buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Wpad_WaitButtons(void)
|
||||||
|
{
|
||||||
|
u32 buttons = 0;
|
||||||
|
/* Wait for button pressing */
|
||||||
|
while (!buttons) {
|
||||||
|
buttons = Wpad_GetButtons();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Wpad_HeldButtons(void)
|
||||||
|
{
|
||||||
|
u32 buttons = 0, cnt;
|
||||||
|
|
||||||
|
/* Scan pads */
|
||||||
|
WPAD_ScanPads();
|
||||||
|
|
||||||
|
/* Get pressed buttons */
|
||||||
|
for (cnt = 0; cnt < MAX_WIIMOTES; cnt++)
|
||||||
|
buttons |= WPAD_ButtonsHeld(cnt);
|
||||||
|
|
||||||
|
return buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Wpad_TimeButton(void)
|
||||||
|
{
|
||||||
|
u32 buttons = 1;
|
||||||
|
|
||||||
|
time_t start,end;
|
||||||
|
time (&start);
|
||||||
|
int dif;
|
||||||
|
/* Wait for button pressing */
|
||||||
|
while (buttons) {
|
||||||
|
buttons = Wpad_HeldButtons();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
time (&end);
|
||||||
|
dif = difftime (end,start);
|
||||||
|
if(dif>=2) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
13
source/wpad.h
Normal file
13
source/wpad.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _WPAD_H_
|
||||||
|
#define _WPAD_H_
|
||||||
|
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
s32 Wpad_Init(void);
|
||||||
|
void Wpad_Disconnect(void);
|
||||||
|
u32 Wpad_GetButtons(void);
|
||||||
|
u32 Wpad_WaitButtons(void);
|
||||||
|
bool Wpad_TimeButton(void);
|
||||||
|
|
||||||
|
#endif
|
173
source/xyzzy.c
Normal file
173
source/xyzzy.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/* xyzzy -- keydumper for Wii
|
||||||
|
|
||||||
|
Copyright (C) 2008 bushing
|
||||||
|
Copyright (C) 2011 R2-D2199
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 2.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fat.h>
|
||||||
|
#include <ogc/machine/processor.h>
|
||||||
|
|
||||||
|
#include "hollywood.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "xyzzy.h"
|
||||||
|
|
||||||
|
#define eeprom_delay() udelay(5)
|
||||||
|
#define HAVE_AHBPROT ((*(vu32*)0xcd800064 == 0xFFFFFFFF) ? 1 : 0)
|
||||||
|
|
||||||
|
keys *keys_bin;
|
||||||
|
void udelay(int us);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline void set32(u32 addr, u32 set)
|
||||||
|
{
|
||||||
|
write32(addr, read32(addr) | set);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear32(u32 addr, u32 clear)
|
||||||
|
{
|
||||||
|
write32(addr, read32(addr)&(~clear));
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_bits(int b, int bits)
|
||||||
|
{
|
||||||
|
while(bits--)
|
||||||
|
{
|
||||||
|
if(b & (1 << bits))
|
||||||
|
set32(HW_GPIO1OUT, GP_EEP_MOSI);
|
||||||
|
else
|
||||||
|
clear32(HW_GPIO1OUT, GP_EEP_MOSI);
|
||||||
|
eeprom_delay();
|
||||||
|
set32(HW_GPIO1OUT, GP_EEP_CLK);
|
||||||
|
eeprom_delay();
|
||||||
|
clear32(HW_GPIO1OUT, GP_EEP_CLK);
|
||||||
|
eeprom_delay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int recv_bits(int bits)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
while(bits--)
|
||||||
|
{
|
||||||
|
res <<= 1;
|
||||||
|
set32(HW_GPIO1OUT, GP_EEP_CLK);
|
||||||
|
eeprom_delay();
|
||||||
|
clear32(HW_GPIO1OUT, GP_EEP_CLK);
|
||||||
|
eeprom_delay();
|
||||||
|
res |= !!(read32(HW_GPIO1IN) & GP_EEP_MISO);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int seeprom_read(void *dst, int offset, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u16 *ptr = (u16 *)dst;
|
||||||
|
u16 recv;
|
||||||
|
|
||||||
|
if(size & 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
clear32(HW_GPIO1OUT, GP_EEP_CLK);
|
||||||
|
clear32(HW_GPIO1OUT, GP_EEP_CS);
|
||||||
|
eeprom_delay();
|
||||||
|
|
||||||
|
for(i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
set32(HW_GPIO1OUT, GP_EEP_CS);
|
||||||
|
send_bits((0x600 | (offset + i)), 11);
|
||||||
|
recv = recv_bits(16);
|
||||||
|
*ptr++ = recv;
|
||||||
|
clear32(HW_GPIO1OUT, GP_EEP_CS);
|
||||||
|
eeprom_delay();
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_read_otp(void)
|
||||||
|
{
|
||||||
|
otp_t *otpd = memalign(32, sizeof(otp_t));
|
||||||
|
u32 buffer[0x20];
|
||||||
|
int i;
|
||||||
|
for (i=0; i< 0x20; i++) {
|
||||||
|
write32(HW_OTPCMD,0x80000000|i);
|
||||||
|
buffer[i] = read32(HW_OTPDATA);
|
||||||
|
}
|
||||||
|
memcpy(otpd, buffer, sizeof(otp_t));
|
||||||
|
memcpy(keys_bin->boot1Hash, otpd->boot1_hash, sizeof(otpd->boot1_hash));
|
||||||
|
memcpy(keys_bin->commonKey, otpd->common_key, sizeof(otpd->common_key));
|
||||||
|
keys_bin->consoleID = otpd->ng_id;
|
||||||
|
snprintf(keys_bin->text, sizeof(keys_bin->text), "YAWMM_DE, ConsoleID: %08x", otpd->ng_id);
|
||||||
|
memset(keys_bin->text+29, 0, sizeof(keys_bin->text)-30);
|
||||||
|
memcpy(keys_bin->privateKey, otpd->ng_priv, sizeof(otpd->ng_priv));
|
||||||
|
memcpy(keys_bin->nandHmac, otpd->nand_hmac, sizeof(otpd->nand_hmac));
|
||||||
|
memcpy(keys_bin->nandKey, otpd->nand_key, sizeof(otpd->nand_key));
|
||||||
|
memcpy(keys_bin->rngKey, otpd->rng_key, sizeof(otpd->rng_key));
|
||||||
|
memcpy(keys_bin->nandKey, otpd->nand_key, sizeof(otpd->nand_key));
|
||||||
|
keys_bin->unk1 = otpd->unk1;
|
||||||
|
keys_bin->unk2 = otpd->unk2;
|
||||||
|
free(otpd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void seeprom_read_seeprom(void) {
|
||||||
|
u32 buffer[sizeof(seeprom_t) / 4];
|
||||||
|
seeprom_t *seeprom = memalign(32, sizeof(seeprom_t));
|
||||||
|
seeprom_read(&buffer, 0, sizeof(seeprom_t) / 2);
|
||||||
|
memcpy(seeprom, buffer, sizeof(seeprom_t));
|
||||||
|
|
||||||
|
memset(keys_bin->blank, 0, 136);
|
||||||
|
keys_bin->ngKeyID = seeprom->ng_key_id;
|
||||||
|
memcpy(keys_bin->ngSig, seeprom->ng_sig, sizeof(seeprom->ng_sig));
|
||||||
|
memset(keys_bin->blank2, 0, 440);
|
||||||
|
free(seeprom);
|
||||||
|
}
|
||||||
|
|
||||||
|
int keydump() {
|
||||||
|
static char buf[128];
|
||||||
|
snprintf(buf, 128, "sd:/keys.bin");
|
||||||
|
FILE *fp = NULL;
|
||||||
|
fp = fopen(buf, "r");
|
||||||
|
if (fp) {
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf(" Dumpe keys.bin");
|
||||||
|
keys_bin = memalign(32, sizeof(keys));
|
||||||
|
printf(".");
|
||||||
|
crypto_read_otp();
|
||||||
|
printf(".");
|
||||||
|
seeprom_read_seeprom();
|
||||||
|
printf(".");
|
||||||
|
|
||||||
|
fp = fopen(buf, "wb");
|
||||||
|
printf(".");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fwrite((u8 *)keys_bin, 1, sizeof(keys), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
free(keys_bin);
|
||||||
|
printf("OK\n");
|
||||||
|
return 0;
|
||||||
|
}
|
74
source/xyzzy.h
Normal file
74
source/xyzzy.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 boot1_hash[20];
|
||||||
|
u8 common_key[16];
|
||||||
|
u32 ng_id;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u8 ng_priv[30];
|
||||||
|
u8 _wtf1[18];
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
u8 _wtf2[28];
|
||||||
|
u8 nand_hmac[20];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
u8 nand_key[16];
|
||||||
|
u8 rng_key[16];
|
||||||
|
u32 unk1;
|
||||||
|
u32 unk2; // 0x00000007
|
||||||
|
} __attribute__((packed)) otp_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 boot2version;
|
||||||
|
u8 unknown1;
|
||||||
|
u8 unknown2;
|
||||||
|
u8 pad;
|
||||||
|
u32 update_tag;
|
||||||
|
u16 checksum;
|
||||||
|
} __attribute__((packed)) eep_ctr_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u32 ms_id;
|
||||||
|
u32 ca_id;
|
||||||
|
u32 ng_key_id;
|
||||||
|
u8 ng_sig[60];
|
||||||
|
eep_ctr_t counters[2];
|
||||||
|
u8 fill[0x18];
|
||||||
|
u8 korean_key[16];
|
||||||
|
};
|
||||||
|
u8 data[256];
|
||||||
|
};
|
||||||
|
} __attribute__((packed)) seeprom_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char text[0x100];
|
||||||
|
u8 boot1Hash[20];
|
||||||
|
u8 commonKey[16];
|
||||||
|
u32 consoleID;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u8 privateKey[30];
|
||||||
|
u8 _wtf1[18];
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
u8 _wtf2[28];
|
||||||
|
u8 nandHmac[20];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
u8 nandKey[16];
|
||||||
|
u8 rngKey[16];
|
||||||
|
u32 unk1;
|
||||||
|
u32 unk2; // 0x00000007
|
||||||
|
char blank[136];
|
||||||
|
u32 ngKeyID;
|
||||||
|
u8 ngSig[60];
|
||||||
|
char blank2[440];
|
||||||
|
|
||||||
|
} keys;
|
||||||
|
|
||||||
|
int keydump();
|
25
wm_config.txt
Normal file
25
wm_config.txt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
;Config file format
|
||||||
|
;
|
||||||
|
;No spaces precedes the keyword on a line
|
||||||
|
;
|
||||||
|
Password=
|
||||||
|
|
||||||
|
; StartupPath:
|
||||||
|
StartupPath=/wad
|
||||||
|
|
||||||
|
; cIOS: 249, 222, whatever
|
||||||
|
:cIOSVersion=249
|
||||||
|
|
||||||
|
; FatDevice: sd usb usb2 gcsda gcsdb
|
||||||
|
:FatDevice=sd
|
||||||
|
|
||||||
|
; NANDDevice: Disable SD USB
|
||||||
|
; Note that WM will prompt for NAND device only if you selected cIOS=249
|
||||||
|
:NANDDevice=Disable
|
||||||
|
|
||||||
|
: Settings for SMB shares
|
||||||
|
|
||||||
|
:SMBUser=
|
||||||
|
:SMBPassword=
|
||||||
|
:SMBShare=
|
||||||
|
:SMBhostIP=
|
Loading…
Reference in New Issue
Block a user