-experiment tinyload failed, back to my libogc booter

(however, I'll keep using that awesome loading bar of it lol)
-fixed this strange click sound on game boot
This commit is contained in:
fix94.1 2012-10-14 17:18:13 +00:00
parent d61801fd3e
commit 8cc82998ac
68 changed files with 2518 additions and 2629 deletions

View File

@ -54,7 +54,7 @@ ios := 249
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -ggdb -O1 -Wall -Wno-multichar -Wno-unused-parameter -Wextra $(MACHDEP) $(INCLUDE) -DBUILD_IOS=$(IOS)
CFLAGS = -g -ggdb -O1 -Wall -Wextra $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g -ggdb $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80620000,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size
@ -150,7 +150,8 @@ all:
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol $(CURDIR)/source/svnrev.h $(CURDIR)/source/loader/alt_ios_gen.h
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol $(CURDIR)/source/svnrev.h $(CURDIR)/source/loader/alt_ios_gen.h \
$(CURDIR)/source/booter/booter.c $(CURDIR)/source/booter/booter.h
#---------------------------------------------------------------------------------
else

View File

@ -1,340 +0,0 @@
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.

View File

@ -1,66 +1,117 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
#PREFIX = powerpc-gekko-
PREFIX = $(DEVKITPPC)/bin/powerpc-eabi-
#PREFIX = /home/megazig/Wii/bootmii-utils/bin/powerpc-elf-
include $(DEVKITPPC)/wii_rules
AR = $(PREFIX)ar
AS = $(PREFIX)as
CC = $(PREFIX)gcc
CXX = $(PREFIX)g++
LD = $(PREFIX)ld
OBJCOPY = $(PREFIX)objcopy
RANLIB = $(PREFIX)ranlib
STRIP = $(PREFIX)strip
#---------------------------------------------------------------------------------
# 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 := booter
BUILD := build
SOURCES := source
DATA := data
INCLUDES := source
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -ggdb -O1 -Wall -Wextra $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g -ggdb $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00000
MACHDEP = -mcpu=750 -mno-eabi -mhard-float -DTINY -DDEBUG
#CFLAGS = $(MACHDEP) -Os -Wall -pipe -ffunction-sections -finline-functions-called-once -mno-sdata --combine -fwhole-program -ffreestanding
CFLAGS = $(MACHDEP) -O1 -Wall -pipe -ffunction-sections -finline-functions-called-once -mno-sdata
LDFLAGS = $(MACHDEP) -n -nostartfiles -nostdlib -Wl,-T,link.ld -L.
ASFLAGS = -D_LANGUAGE_ASSEMBLY -DHW_RVL -DTINY
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -logc
TARGET_LINKED = boot.elf
TARGET = booter.bin
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CURDIR)
#---------------------------------------------------------------------------------
# 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)
CFILES = apploader.c cios.c cache.c debug.c di.c disc.c ios.c patchcode.c usb.c utils.c video.c \
fst.c multidol.c wip.c main.c
#OBJS = crt0.o _all.o
OBJS = crt0.o apploader.o cios.o cache.o debug.o di.o disc.o ios.o patchcode.o patchhook.o usb.o utils.o video.o \
fst.o multidol.o wip.o main.o
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
DEPDIR = .deps
export DEPSDIR := $(CURDIR)/$(BUILD)
LIBS =
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
export CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
export CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
all: $(TARGET)
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
%.o: %.s
@echo " ASSEMBLE $<"
@$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES), -I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
%.o: %.S
@echo " ASSEMBLE $<"
@$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
%.o: %.c
@echo " COMPILE $<"
@$(CC) $(CFLAGS) $(DEFINES) -c $< -o $@
export OUTPUT := $(CURDIR)/$(TARGET)
%.o: %.cpp
@echo " COMPILE $<"
@$(CXX) $(CFLAGS) $(DEFINES) -c $< -o $@
#_all.o: $(CFILES)
# @echo " COMPILE ALL "
# @mkdir -p $(DEPDIR)
# @$(CC) $(CFLAGS) $(DEFINES) -Wp,-MMD,$(DEPDIR)/$(*F).d,-MQ,"$@",-MP -c $(CFILES) -o $@
$(TARGET_LINKED): $(OBJS)
@echo " LINK $@"
@$(CC) -g -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
$(TARGET): $(TARGET_LINKED)
@echo " OBJCOPY $@"
@$(OBJCOPY) -O binary $< $@
#---------------------------------------------------------------------------------
.PHONY: $(BUILD) all clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
rm -rf $(TARGET_LINKED) $(TARGET) $(OBJS) $(DEPDIR)
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).bin: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
%.bin: %.elf
@echo output ... $(notdir $(@))
@$(OBJCOPY) -O binary $< $(@)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

View File

@ -1,131 +0,0 @@
TinyLoad v0.2
A Wii disc game loader in 4096 bytes
====================================
What?
=====
TinyLoad is a simple original Wii game launcher. You run it, it launches
whatever's inserted into the drive. Simple. It ignores game regions, so it's
region-free. It won't install updates. It won't load burned copies. There are no
controls or settings.
The user interface shows two things: progress, and error status. A white bar
across the bottom of the screen shows the current (rough) progress. If an error
is detected, a portion of the top of the screen will turn red. It will then
attempt to launch The Homebrew Channel (only applies to recent versions with the
JODI Title ID). If this fails then it will simply hang.
If the launcher freezes with the progress bar visible and no red error box, then
you've probably hit a bug. Try the debug version if you have a USB Gecko.
If it freezes with a black screen after the progress bar has reached its
endpoint and disappeared, then the game itself is freezing.
I obviously have only tested this with a few games. Chances are it doesn't work
with every Wii game out there.
The debug version requires a USB Gecko and shows debug messages over it.
Notes:
- TinyLoad sets the PPC timebase correctly according to your Wii's RTC. This
fixes date/time issues in games.
- The video code makes lots of assumptions. It will only work if VI was left
configured in a "standard" mode, with a 640x480-640x574 framebuffer. VI should
be blanked; if it isn't, then TinyLoad will not blank it before launching
the game so your screen will blink green for a split second as the game
initializes VI. It has been tested to work correctly when launched by the
Homebrew Channel in at least NTSC 480p and PAL interlaced modes. If these
assumptions don't hold then the progress bar display will not work properly,
but the rest of the loader should work fine.
- TinyLoad does not perform _any_ patching of games. The lowmem video mode
setting follows whatever video mode was left set by the application used to
launch TinyLoad, except that PAL games are forced to PAL if NTSC is detected.
This does not patch the game, it's merely the informative value in low memory;
games are free to read SYSCONF/setting.txt and ignore it. I don't really care
because I use 480p mode anyway. If you need more advanced options, just use
Gecko OS.
- Normally, game audio will not work correctly if launched via a loader that
was initially launched via BootMii-boot2. This is a bug in libogc (it doesn't
know how to initialize the DSP for the first time and leaves it in a broken
state), and it affects anything running after the Wii was booted first into
a libogc application, including the System Menu's loader. In other words,
BootMii-boot2 -> HBC -> System Menu (or Gecko OS) -> Game may cause distorted
audio. TinyLoad _does_ work, by resetting the audio hardware to let the game
reinitialize it properly. So, BootMii-boot2 -> HBC -> TinyLoad -> Game will
work fine. This ought to be worked around in a future release of HBC, at
least. I'd suggest fixing libogc, but I know shagkur is just going to rip the
proper code from the SDK again. Anyway, launching using TinyLoad will work
fine as it contains the workaround.
- TinyLoad will load the correct IOS as specified in the partition TMD. It does
not support loading any other IOS.
- TinyLoad will not install updates. Not having the right IOS for the game will
probably result in a red error and reset about halfway through.
Broken stuff:
- I don't think online games work. Not sure why (I do copy the TitleID to the
proper spot, I think). If it works for you, let me know. Likewise, if you know
what the problem is or you can fix it, please let me know.
Who?
====
Program:
Copyright 2008-2009 Hector Martin (marcan) <marcan@marcansoft.com>
Supporting code:
Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
Copyright 2008-2009 Andre Heider (dhewg) <dhewg@wiibrew.org>
Copyright 2008 Nuke <wiinuke@gmail.com>
Awesome icon:
Copyright 2009 Freddy Leitner (drmr)
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
The icon is licensed under CC-BY-NC-SA 3.0:
http://creativecommons.org/licenses/by-nc-sa/3.0/
Why?
====
Because:
- System Menu 4.2 forever broke region free via modchips
- I have a USA Wii which I regularly use with EUR games
- Gecko OS is somewhat annoying and recent versions are unstable (for me anyway)
- I refuse to perform retarded firmware mods.
- I autoboot HBC via BootMii-boot2 and using the System Menu takes longer
anyway.
I also think that low-level apps that tightly hug the hardware are very
educational, so why not. And hey, the code is pretty short, so you ought to be
able to read it completely and learn how all this crazy Wii stuff *actually*
works :-)
How?
====
TinyLoad is not compressed. The 4 kilobytes are raw code and data, plus the ELF
header. The original loader was fit in 4 kilobytes by avoiding bloated libraries
like libogc and instead using a small codebase pieced together from bits of the
Twilight Hack and of HBC's reload stub. Extra features (SYSCONF reading, RTC
reading, proper lowmem settings, VI stuff, progress bar, etc) were added by
making space via a combination of increasingly complex compiler options, manual
tweaks, and micro-optimization.
Nonetheless, there is almost no assembly code and the C code, though compact and
odd at times, should be moderately readable. Just keep in mind that I
deliberately leave old values floating around and/or use odd initializations in
order to simplify the code. Also, I haven't commented most of it. If you're
really interested, give me a shout and I'll see what I can do to make it more
acceptable.
If you want some *real* fun, load the ELF in IDA. The function inlining and tail
call goodness ought to provide tons of entertainment.
Where?
======
http://wiibrew.org/TinyLoad
http://marcansoft.com/blog/

View File

@ -1,15 +0,0 @@
#ifndef _APPLOADER_H_
#define _APPLOADER_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "types.h"
/* Prototypes */
u32 Apploader_Run(u8 vidMode, u8 vipatch, u8 countryString, u8 patchVidModes, int aspectRatio, u32 returnTo);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -1,59 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from the Twilight Hack */
// Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#include "types.h"
#include "debug.h"
// this saves 12 bytes
static void syncret(void) __attribute__((noinline));
static void syncret(void)
{
asm("sync ; isync");
}
void sync_before_read(void *p, u32 len)
{
u32 a, b;
a = (u32)p & ~0x1f;
b = ((u32)p + len + 0x1f) & ~0x1f;
for ( ; a < b; a += 32)
asm("dcbi 0,%0" : : "b"(a) : "memory");
syncret();
}
void sync_after_write(const void *p, u32 len)
{
u32 a, b;
a = (u32)p & ~0x1f;
b = ((u32)p + len + 0x1f) & ~0x1f;
for ( ; a < b; a += 32)
asm("dcbf 0,%0" : : "b"(a));
syncret();
}
void sync_before_exec(const void *p, u32 len)
{
u32 a, b;
a = (u32)p & ~0x1f;
b = ((u32)p + len + 0x1f) & ~0x1f;
for ( ; a < b; a += 32)
asm("dcbst 0,%0 ; sync ; icbi 0,%0" : : "b"(a));
syncret();
}

View File

@ -1,21 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from the Twilight Hack */
// Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#ifndef __CACHE_H__
#define __CACHE_H__
#include "types.h"
void sync_before_read(void *p, u32 len);
void sync_after_write(const void *p, u32 len);
void sync_before_exec(const void *p, u32 len);
#endif

View File

@ -1,39 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from the Twilight Hack */
// Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
.globl _start
_start:
# Disable interrupts
mfmsr 3 ; rlwinm 3,3,0,17,15 ; mtmsr 3 ; isync
# Setup stack.
lis 1,_stack_top@ha ; addi 1,1,_stack_top@l ; li 0,0 ; stwu 0,-64(1)
#if !defined(TINY) || defined(DEBUG)
# Clear BSS.
lis 3,__bss_start@ha ; addi 3,3,__bss_start@l
#if defined(TINY)
lis 4,0xDEAD
ori 4,4,0xBEEF
#else
li 4,0
#endif
lis 5,__bss_end@ha ; addi 5,5,__bss_end@l ; sub 5,5,3
bl memset32
#endif
# Go!
bl _main
#ifndef TINY
# If it returns, hang. Shouldn't happen.
b .
#endif

View File

@ -1,38 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from HBC's stub which was based on dhewg's geckoloader stub */
// Copyright 2008-2009 Andre Heider <dhewg@wiibrew.org>
#include "debug.h"
#include "usb.h"
#ifdef DEBUG
static char int2hex[] = "0123456789abcdef";
void debug_uint (u32 i) {
int j;
usb_sendbuffersafe ("0x", 2);
for (j = 0; j < 8; ++j) {
usb_sendbuffersafe (&int2hex[(i >> 28) & 0xf], 1);
i <<= 4;
}
}
void debug_string (const char *s) {
u32 i = 0;
while (s[i])
i++;
usb_sendbuffersafe (s, i);
}
#endif

View File

@ -1,215 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#include "types.h"
#include "ios.h"
#include "utils.h"
#include "debug.h"
#include "di.h"
int di_fd=0;
u32 inbuf[16] ALIGNED(64);
u32 outbuf[16] ALIGNED(64);
extern u32 __bss_start[];
extern u32 __bss_end[];
int di_init(void)
{
debug_string("Opening /dev/di: ");
di_fd = ios_open("/dev/di",0);
debug_uint(di_fd);
debug_string("\n");
//memset(inbuf, 0, 0x20 );
return di_fd;
}
int di_shutdown(void)
{
return ios_close(di_fd);
}
static int _di_ioctl_std(int num) __attribute__((noinline));
static int _di_ioctl_std(int num)
{
inbuf[0x00] = num << 24;
return ios_ioctl( di_fd, num, inbuf, 0x20, outbuf, 0x20);
}
int di_getcoverstatus(void)
{
//memset(inbuf, 0, 0x20 );
//memset(outbuf, 0, 0x20 );
//inbuf[0x00] = 0x88000000;
int ret = _di_ioctl_std(0x88);
if( ret != 1 )
return -1;
return outbuf[0];
}
int di_identify(void)
{
//memset(inbuf, 0, 0x20 );
//memset(outbuf, 0, 0x20 );
//inbuf[0x00] = 0x12000000;
return _di_ioctl_std(0x12);
}
#ifndef TINY
int di_waitforcoverclose(void)
{
//memset(inbuf, 0, 0x20 );
//memset(outbuf, 0, 0x20 );
//inbuf[0x00] = 0x79000000;
int ret = _di_ioctl_std(0x79);
if( ret < 0 )
return ret;
return outbuf[0];
}
#endif
#ifndef TINY
int di_requesterror(void)
{
//memset(inbuf, 0, 0x20 );
//memset(outbuf, 0, 0x20 );
//inbuf[0x00] = 0xE0000000;
int ret = _di_ioctl_std(0xE0);
if( ret < 0 )
return ret;
return outbuf[0];
}
#endif
int di_read(void *dst, u32 size, u32 offset)
{
//memset(inbuf, 0, 0x20 );
inbuf[0x00] = 0x71000000;
inbuf[0x01] = size;
inbuf[0x02] = offset;
return ios_ioctl( di_fd, 0x71, inbuf, 0x20, dst, size);
}
int di_unencryptedread(void *dst, u32 size, u32 offset)
{
//memset(inbuf, 0, 0x20 );
inbuf[0x00] = 0x8D000000;
inbuf[0x01] = size;
inbuf[0x02] = offset;
return ios_ioctl( di_fd, 0x8D, inbuf, 0x20, dst, size);
}
int di_reset(void)
{
//memset(inbuf, 0, 0x20 );
//inbuf[0x00] = 0x8A000000;
inbuf[0x01] = 1;
return _di_ioctl_std(0x8A);
}
#ifndef TINY
int di_stopmotor(void)
{
//memset(inbuf, 0, 0x20 );
//inbuf[0x00] = 0xE3000000;
inbuf[0x01] = 0;
inbuf[0x02] = 0;
return _di_ioctl_std(0xE3);
}
#endif
int di_openpartition(u32 offset, u8 *tmd)
{
static struct ioctlv vectors[16] ALIGNED(64);
//memset(inbuf, 0, 0x20 );
inbuf[0x00] = 0x8B000000;
inbuf[0x01] = offset;
vectors[0].data = inbuf;
vectors[0].len = 0x20;
vectors[1].data = NULL;
vectors[1].len = 0x2a4;
vectors[2].data = NULL;
vectors[2].len = 0;
vectors[3].data = tmd;
vectors[3].len = 0x49e4;
vectors[4].data = outbuf;
vectors[4].len = 0x20;
return ios_ioctlv(di_fd, 0x8B, 3, 2, vectors);
}
#ifndef TINY
int di_closepartition(void)
{
//memset(inbuf, 0, 0x20 );
//inbuf[0x00] = 0x8C000000;
return _di_ioctl_std(0x8C);
}
#endif
int di_readdiscid(void *dst)
{
//memset(inbuf, 0, 0x20 );
//memset(dst, 0, 0x20 );
inbuf[0x00] = 0x70000000;
return ios_ioctl( di_fd, 0x70, inbuf, 0x20, dst, 0x20);
}
int WDVD_SetFragList(int device, void *fraglist, int size)
{
debug_string("WDVD_SetFragList\n");
memset(inbuf, 0, 0x20);
/* Set FRAG mode */
inbuf[0] = 0xF9000000;
inbuf[1] = device;
inbuf[2] = (u32)fraglist;
inbuf[3] = size;
return ios_ioctl(di_fd, 0xF9, inbuf, 0x20, outbuf, 0x20);
}
int WDVD_SetUSBMode(u32 mode, const u8 *id, s32 partition)
{
debug_string("WDVD_SetUSBMode\n");
memset(inbuf, 0, 0x20);
/* Set USB mode */
inbuf[0] = 0xF4000000;
inbuf[1] = mode;
/* Copy ID */
if(id)
{
memcpy(&inbuf[2], id, 6);
if(partition >= 0)
inbuf[5] = partition;
}
return ios_ioctl(di_fd, 0xF4, inbuf, 0x20, outbuf, 0x20);
}

View File

@ -1,29 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#ifndef __DI_H__
#define __DI_H__
int di_init(void);
int di_getcoverstatus(void);
int di_requesterror(void);
int di_read(void *dst, u32 size, u32 offset);
int di_unencryptedread(void *dst, u32 size, u32 offset);
int di_identify(void);
int di_reset(void);
int di_stopmotor(void);
int di_openpartition(u32 offset, u8 *tmd);
int di_closepartition(void);
int di_readdiscid(void *dst);
int di_shutdown(void);
int WDVD_SetFragList(int device, void *fraglist, int size);
int WDVD_SetUSBMode(u32 mode, const u8 *id, s32 partition);
#endif

View File

@ -1,59 +0,0 @@
#include "types.h"
#include "memory.h"
#include "utils.h"
#include "frag.h"
#include "cache.h"
#include "di.h"
#include "cios.h"
void Disc_SetLowMem()
{
/* Setup low memory */
*Sys_Magic = 0x0D15EA5E; // Standard Boot Code
*Sys_Version = 0x00000001; // Version
*Arena_L = 0x00000000; // Arena Low
*BI2 = 0x817E5480; // BI2
*Bus_Speed = 0x0E7BE2C0; // Console Bus Speed
*CPU_Speed = 0x2B73A840; // Console CPU Speed
*Assembler = 0x38A00040; // Assembler
*(vu32*)0x800000E4 = 0x80431A80;
*Dev_Debugger = 0x81800000; // Dev Debugger Monitor Address
*Simulated_Mem = 0x01800000; // Simulated Memory Size
*(vu32*)0xCD00643C = 0x00000000; // 32Mhz on Bus
/* Fix for Sam & Max (WiiPower) */
if(CurrentIOS.Type != IOS_TYPE_HERMES)
*GameID_Address = 0x80000000;
/* Copy disc ID */
memcpy((void *)Online_Check, (void *)Disc_ID, 4);
/* ERROR 002 fix (WiiPower) */
*(u32 *)0x80003140 = *(u32 *)0x80003188;
}
s32 wbfsDev = 0;
u32 wbfs_part_idx = 0;
FragList *frag_list = NULL;
static int set_frag_list()
{
// (+1 for header which is same size as fragment)
int size = sizeof(Fragment) * (frag_list->num + 1);
return WDVD_SetFragList(wbfsDev, frag_list, size);
}
s32 Disc_SetUSB(const u8 *id, u8 frag)
{
//ENABLE USB in cIOS
if(id)
{
if(frag)
return set_frag_list();
s32 part = -1;
if(CurrentIOS.Type == IOS_TYPE_HERMES)
part = wbfs_part_idx ? wbfs_part_idx - 1 : 0;
return WDVD_SetUSBMode(wbfsDev, (u8*)id, part);
}
//DISABLE USB in cIOS
return WDVD_SetUSBMode(0, NULL, -1);
}

View File

@ -1,353 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from HBC's stub which was based on the Twilight Hack code */
// Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
// Copyright 2008-2009 Andre Heider <dhewg@wiibrew.org>
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#include "debug.h"
#include "ios.h"
#include "cache.h"
#include "utils.h"
#include "di.h"
#define virt_to_phys(x) ((u32*)(((u32)(x))&0x3FFFFFFF))
#define phys_to_virt(x) ((u32*)(((u32)(x))|0x80000000))
// Low-level IPC access.
static inline u32 iread32(u32 addr)
{
u32 x;
asm volatile("lwz %0,0(%1) ; sync ; isync" : "=r"(x) : "b"(0xc0000000 | addr));
return x;
}
static inline void iwrite32(u32 addr, u32 x)
{
asm volatile("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr));
}
#ifdef TINY
static u32 _ipc_read(u32 reg) __attribute__((noinline));
static void _ipc_write(u32 reg, u32 value) __attribute__((noinline));
static void ipc_bell(u32 w) __attribute__((noinline));
// inline the 4*, don't inline the 0x0d0 stuff. yes, this saves a few bytes.
static u32 _ipc_read(u32 reg) {
return iread32(0x0d000000 + reg);
}
static void _ipc_write(u32 reg, u32 value) {
iwrite32(0x0d000000 + reg, value);
}
static inline u32 ipc_read(u32 reg) {
return _ipc_read(4*reg);
}
static inline void ipc_write(u32 reg, u32 value) {
_ipc_write(4*reg, value);
}
#else
static u32 ipc_read(u32 reg) {
return iread32(0x0d000000 + 4*reg);
}
static void ipc_write(u32 reg, u32 value) {
iwrite32(0x0d000000 + 4*reg, value);
}
#endif
static void ipc_bell(u32 w)
{
ipc_write(1, w);
}
static void ios_delay(void) __attribute__((noinline));
static void ios_delay(void)
{
udelay(500);
}
static void ipc_wait_ack(void)
{
while (!(ipc_read(1) & 0x2)) {
//debug_string("no ack\n");
//udelay(10000);
}
ios_delay();
}
static void ipc_wait_reply(void)
{
while (!(ipc_read(1) & 0x4)) {
//debug_string("no reply\n");
//udelay(10000);
}
ios_delay();
}
static u32 ipc_wait(void)
{
u32 ret;
while (!((ret = ipc_read(1)) & 0x6)) {
//debug_string("no nothing\n");
//udelay(10000);
}
ios_delay();
return ret;
}
// Mid-level IPC access.
struct ipc {
u32 cmd;
int result;
int fd;
u32 arg[5];
u32 user[8];
};
static struct ipc ipc ALIGNED(64);
void ipc_init(void)
{
ipc_write(1, 0x06);
}
static void ipc_send_request(void)
{
sync_after_write(&ipc, 0x40);
ipc_write(0, (u32)virt_to_phys(&ipc));
ipc_bell(1);
ipc_wait_ack();
//udelay(1000);
ipc_bell(2);
}
static int ipc_send_twoack(void)
{
sync_after_write(&ipc, 0x40);
ios_delay();
ipc_write(0, (u32)virt_to_phys(&ipc));
ipc_bell(1);
if(ipc_wait() & 4) {
debug_string("got reply instead, bad\n");
return 0;
}
ipc_bell(2);
if(ipc_wait() & 4) {
debug_string("got reply instead, bad\n");
return 0;
}
ipc_bell(2);
ipc_bell(8);
debug_string("\n");
return 1;
}
static void ipc_recv_reply(void)
{
for (;;) {
u32 reply;
ipc_wait_reply();
reply = ipc_read(2);
ipc_bell(4);
ipc_bell(8);
if (((u32*)reply) == virt_to_phys(&ipc))
break;
debug_string("Ignoring unexpected IPC reply @");
debug_uint((u32)reply);
debug_string("\n");
}
sync_before_read(&ipc, 0x40);
}
// High-level IPC access.
void ios_cleanup()
{
int loops = 0xA;
do
{
if((ipc_read(1) & 0x22) == 0x22)
ipc_write(1, (ipc_read(1)&~0x30) | 2);
if((ipc_read(1) & 0x14) == 0x14)
{
ipc_read(2);
ipc_write(1, (ipc_read(1)&~0x30) | 4);
ipc_write(12, 0x4000);
ipc_write(1, (ipc_read(1)&~0x30) | 8);
}
ipc_write(12, 0x4000);
udelay(1000);
loops--;
} while(loops != 0);
int fd;
for(fd = 0; fd != 31; fd++)
ios_close(fd);
}
int ios_open(const char *filename, u32 mode)
{
#ifdef TINY
sync_after_write((void*)filename, 0x20);
#else
sync_after_write((void*)filename, strlen(filename) + 1);
#endif
#ifndef TINY
memset(&ipc, 0, sizeof ipc);
#endif
ipc.cmd = 1;
ipc.fd = 0;
ipc.arg[0] = (u32)virt_to_phys(filename);
ipc.arg[1] = mode;
//debug_string("Sending openreq\n");
ipc_send_request();
//debug_string("AAA\n");
ipc_recv_reply();
//debug_string("BBB\n");
return ipc.result;
}
static void ios_std(int fd, int cmd)
{
ipc.cmd = cmd;
ipc.fd = fd;
ipc_send_request();
ipc_recv_reply();
}
int ios_close(int fd)
{
#ifndef TINY
memset(&ipc, 0, sizeof ipc);
#endif
ios_std(fd, 2);
return ipc.result;
}
int ios_read(int fd, void *buf, u32 size)
{
#ifndef TINY
memset(&ipc, 0, sizeof ipc);
#endif
ipc.arg[0] = (u32)virt_to_phys(buf);
ipc.arg[1] = size;
ios_std(fd, 3);
sync_before_read(buf, size);
return ipc.result;
}
int ios_ioctl(int fd, u32 n, void *in, u32 in_size, void *out, u32 out_size)
{
#ifndef TINY
memset(&ipc, 0, sizeof ipc);
#endif
if(in)
sync_after_write(in, in_size);
if(out)
sync_after_write(out, out_size);
ipc.arg[0] = n;
ipc.arg[1] = (u32)virt_to_phys(in);
ipc.arg[2] = in_size;
ipc.arg[3] = (u32)virt_to_phys(out);
ipc.arg[4] = out_size;
ios_std(fd, 6);
if(out)
sync_before_read(out, out_size);
return ipc.result;
}
int _ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec, int reboot)
{
u32 i;
#ifndef TINY
memset(&ipc, 0, sizeof ipc);
#endif
for (i = 0; i < in_count + out_count; i++) {
if (vec[i].data) {
sync_after_write(vec[i].data, vec[i].len);
vec[i].data = (void *)virt_to_phys(vec[i].data);
}
}
sync_after_write(vec, (in_count + out_count) * sizeof *vec);
ipc.cmd = 7;
ipc.fd = fd;
ipc.arg[0] = n;
ipc.arg[1] = in_count;
ipc.arg[2] = out_count;
ipc.arg[3] = (u32)virt_to_phys(vec);
if(reboot) {
//debug_string("Sending twoack\n");
if(ipc_send_twoack())
return 0;
debug_string("Reboot returned a reply instead of an ACK");
} else {
//debug_string("Sending request\n");
ipc_send_request();
//debug_string("K\n");
}
ipc_recv_reply();
//debug_string("Got reply\n");
for (i = in_count; i < in_count + out_count; i++) {
if (vec[i].data) {
vec[i].data = phys_to_virt((u32)vec[i].data);
sync_before_read(vec[i].data, vec[i].len);
}
}
if(reboot && (ipc.result >= 0))
return -100;
return ipc.result;
}
int ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec) {
return _ios_ioctlv(fd, n, in_count, out_count, vec, 0);
}
int ios_ioctlvreboot(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec) {
return _ios_ioctlv(fd, n, in_count, out_count, vec, 1);
}

View File

@ -1,27 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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 __IOS_H__
#define __IOS_H__
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
struct ioctlv {
void *data;
u32 len;
};
void ipc_init(void);
int ios_open(const char *filename, u32 mode);
int ios_close(int fd);
int ios_ioctl(int fd, u32 n, void *in, u32 in_size, void *out, u32 out_size);
int ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec);
int ios_ioctlvreboot(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec);
int ios_read(int fd, void *buf, u32 size);
void ios_cleanup(void);
#endif

View File

@ -1,36 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
OUTPUT_FORMAT("elf32-powerpc")
OUTPUT_ARCH(powerpc:common)
ENTRY(_start)
PHDRS {
app PT_LOAD FLAGS(7);
}
SECTIONS {
. = 0x80F00000;
.text : { *(.text) *(.text.*) } :app
.data : { *(.data) *(.data.*) }
.rodata : { *(.rodata) *(.rodata.*) }
//.sdata : { *(.sdata) *(.sdata.*) }
__bss_start = .;
//.sbss : { *(.sbss) *(.sbss.*) }
.bss : { *(.bss) *(.bss.*) }
__bss_end = .;
. = ALIGN(0x40);
.stack : {
. = . + 0x48000;
_stack_top = .;
}
}

View File

@ -1,369 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from HBC's stub which was based on dhewg's geckoloader stub */
// Copyright 2008-2009 Andre Heider <dhewg@wiibrew.org>
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#include "utils.h"
#include "debug.h"
#include "usb.h"
#include "ios.h"
#include "cache.h"
#include "di.h"
#include "disc.h"
#include "apploader.h"
#include "patchcode.h"
#include "Config.h"
#include "video.h"
#include "fst.h"
IOS_Info CurrentIOS;
static the_CFG *conf = (the_CFG*)0x93100000;
//static struct ioctlv vecs[16] ALIGNED(64);
static u32 disc_id[0x40] ALIGNED(32);
static u32 AppEntrypoint = 0;
static u8 tmd[0x5000] ALIGNED(64);
static struct {
u32 count;
u32 offset;
u32 pad[6];
} part_table_info ALIGNED(32);
static struct {
u32 offset;
u32 type;
} partition_table[32] ALIGNED(32);
//static int es_fd;
void fail(void);
static s32 ios_getversion()
{
u32 vercode;
u16 version;
sync_before_read((void*)0x80003140,8);
vercode = *((u32*)0x80003140);
version = vercode >> 16;
if(version == 0) return -1;
if(version > 0xff) return -1;
return version;
}
static void printversion(void)
{
debug_string("IOS version: ");
debug_uint(ios_getversion());
debug_string("\n");
}
static u8 conf_buffer[0x4000] ALIGNED(32);
static u32 get_counter_bias(void)
{
int fd;
u32 bias = 0;
fd = ios_open("/shared2/sys/SYSCONF", 1);
if(ios_read(fd, conf_buffer, 0x4000) != 0x4000) {
debug_string("Failed to get conf buffer\n");
fail();
//goto finish;
}
debug_string("Read SYSCONF\n");
u16 count = *((u16*)(&conf_buffer[4]));
u16 *offset = (u16*)&conf_buffer[6];
while(count--) {
if(/*(6 == ((conf_buffer[*offset]&0x0F)+1)) &&*/ !memcmp("IPL.CB", &conf_buffer[*offset+1], 6))
break;
offset++;
}
if(count == -1) {
debug_string("Failed to find IPL.CB setting\n");
fail();
//goto finish;
}
u8 *b = &conf_buffer[*offset];
//memcpy(&bias, &conf_buffer[*offset+7], 4);
bias = (b[7]<<24) | (b[8]<<16) | (b[9]<<8) | b[10];
debug_string("Counter bias: ");
debug_uint(bias);
debug_string("\n");
//finish:
ios_close(fd);
return bias;
}
static u32 read_rtc(void)
{
u32 rtc;
exi_chan0sr = 0x00000130;
exi_chan0data = 0x20000000;
exi_chan0cr = 0x39;
while((exi_chan0cr)&1);
exi_chan0cr = 0x39;
while((exi_chan0cr)&1);
rtc = exi_chan0data;
debug_string("RTC: ");
debug_uint(rtc);
debug_string("\n");
exi_chan0sr = 0x00000030;
//udelay(100);
return rtc;
}
static inline void write32(u32 w, u32 addr)
{
*((u32 *)(addr + 0x80000000)) = w;
}
static inline void write16(u16 w, u16 addr)
{
*((u16 *)(addr + 0x80000000)) = w;
}
void fail(void)
{
debug_string("\nFAILURE\n");
void (*entrypoint)(void) = (void(*)(void))0x80001800;
entrypoint();
while(1);
}
#ifdef DEBUG
#define FAILNOTONE(val,msg) do { int __v = (val); if(__v != 1) { debug_string(msg "Value: "); debug_uint(__v); debug_string("\n"); fail(); } } while(0)
#else
#define FAILNOTONE(val,msg) failnotone((val))
static void failnotone(int v) __attribute__((noinline));
static void failnotone(int v) {
if(v != 1)
fail();
}
#endif
u32 hooktype;
extern s32 wbfsDev;
extern u32 wbfs_part_idx;
extern FragList *frag_list;
void _main (void)
{
int ret;
int i;
//u64 disc_ios;
u32 bias;
u32 rtc = 0;
u32 rtc2 = 1;
u64 tbtime;
u32 tmp;
debug_string("WiiFlow External Booter by FIX94 - based on TinyLoad v0.2\n");
video_init();
ipc_init();
printversion();
bias = get_counter_bias();
while(rtc != rtc2) {
rtc2 = rtc;
rtc = read_rtc();
}
tbtime = ((u64)((u32)(rtc+bias)))*(243000000u/4);
asm volatile(
"li %0,0\n\
mttbl %0\n\
mttbu %1\n\
mttbl %2\n"
: "=&r" (tmp)
: "b" ((u32)(tbtime >> 32)), "b" ((u32)(tbtime & 0xFFFFFFFF))
);
debug_string("Initializing DI\n");
if(di_init() < 0) {
debug_string("di_init() failed\n");
fail();
}
prog10();
app_gameconfig_set(conf->gameconf, conf->gameconfsize);
ocarina_set_codes(conf->codelist, conf->codelistend, conf->cheats, conf->cheatSize);
debuggerselect = conf->debugger;
hooktype = conf->hooktype;
frag_list = conf->fragments;
wbfsDev = conf->wbfsDevice;
wbfs_part_idx = conf->wbfsPart;
configbytes[0] = conf->configbytes[0];
configbytes[1] = conf->configbytes[1];
if(conf->GameBootType == TYPE_WII_DISC)
{
Disc_SetUSB(NULL, 0);
if(CurrentIOS.Type == IOS_TYPE_HERMES)
Hermes_Disable_EHC();
}
else
{
Disc_SetUSB((u8*)conf->gameID, conf->GameBootType == TYPE_WII_WBFS_EXT);
if(CurrentIOS.Type == IOS_TYPE_HERMES)
Hermes_shadow_mload(conf->mload_rev);
}
prog10();
//di_closepartition();
if((ret = di_getcoverstatus()) != 2) {
debug_string("di_getcoverstatus() failed\n");
fail();
}
debug_string("Resetting drive\n");
FAILNOTONE(di_reset(), "di_reset() failed\n");
prog10();
debug_string("Identifying disc\n");
FAILNOTONE(di_identify(), "di_identify() failed\n");
prog(40);
debug_string("Reading Disc ID\n");
FAILNOTONE(di_readdiscid(disc_id), "di_readdiscid() failed\n");
prog10();
//*(vu32*)0xcd8000c0 |= 0x100;
debug_string("Gamecode: ");
debug_uint(disc_id[0]);
debug_string("\n");
if(disc_id[6] != 0x5d1c9ea3) {
debug_string("Not a valid Wii disc!\n");
fail();
}
debug_string("Reading partition table info\n");
FAILNOTONE(di_unencryptedread(&part_table_info, sizeof(part_table_info), 0x10000), "Read failed\n");
prog10();
debug_string("Reading partition table\n");
FAILNOTONE(di_unencryptedread(partition_table, sizeof(partition_table), part_table_info.offset), "Read failed\n");
prog10();
for(i=0; i<part_table_info.count; i++) {
if(partition_table[i].type == 0) {
break;
}
}
if(i >= part_table_info.count) {
debug_string("Could not find valid partition table\n");
fail();
}
debug_string("Opening partition at ");
debug_uint(partition_table[i].offset);
debug_string("\n");
FAILNOTONE(di_openpartition(partition_table[i].offset, tmd), "Failed to open partition");
prog10();
debug_string("Reading partition header\n");
FAILNOTONE(di_read((void*)0x80000000, 0x20, 0), "Failed to read partition header");
prog10();
CurrentIOS = conf->IOS;
AppEntrypoint = Apploader_Run(conf->vidMode, conf->vipatch, conf->countryString,
conf->patchVidMode, conf->aspectRatio, conf->returnTo);
debug_string("Apploader complete\n");
prog10();
extern u32 vimode;
if(((u8*)disc_id)[3] == 'P' && vimode == 0)
vimode = 1;
debug_string("VI mode: ");
debug_uint(vimode);
debug_string("\n");
Disc_SetLowMem();
*(vu32*)0x800000cc = vimode;
sync_after_write((void*)0x80000000, 0x3f00);
setprog(320);
udelay(60000);
debug_string("Game entry: ");
debug_uint(AppEntrypoint);
debug_string("\n");
debug_string("ok, taking the plunge\n");
video_setblack();
di_shutdown();
*(vu32*)0xCD006C00 = 0x00000000; // deinit audio due to libogc fail
/* Originally from tueidj - taken from NeoGamma (thx) */
*(vu32*)0xCC003024 = 1;
if(AppEntrypoint == 0x3400)
{
if(hooktype)
{
asm volatile (
"lis %r3, returnpoint@h\n"
"ori %r3, %r3, returnpoint@l\n"
"mtlr %r3\n"
"lis %r3, 0x8000\n"
"ori %r3, %r3, 0x18A8\n"
"nop\n"
"mtctr %r3\n"
"bctr\n"
"returnpoint:\n"
/*"bl DCDisable\n"
"bl ICDisable\n"*/
"li %r3, 0\n"
"mtsrr1 %r3\n"
"lis %r4, AppEntrypoint@h\n"
"ori %r4,%r4,AppEntrypoint@l\n"
"lwz %r4, 0(%r4)\n"
"mtsrr0 %r4\n"
"rfi\n"
);
}
else
{
asm volatile (
"isync\n"
"lis %r3, AppEntrypoint@h\n"
"ori %r3, %r3, AppEntrypoint@l\n"
"lwz %r3, 0(%r3)\n"
"mtsrr0 %r3\n"
"mfmsr %r3\n"
"li %r4, 0x30\n"
"andc %r3, %r3, %r4\n"
"mtsrr1 %r3\n"
"rfi\n"
);
}
}
else if(hooktype)
{
asm volatile (
"lis %r3, AppEntrypoint@h\n"
"ori %r3, %r3, AppEntrypoint@l\n"
"lwz %r3, 0(%r3)\n"
"mtlr %r3\n"
"lis %r3, 0x8000\n"
"ori %r3, %r3, 0x18A8\n"
"nop\n"
"mtctr %r3\n"
"bctr\n"
);
}
else
{
asm volatile (
"lis %r3, AppEntrypoint@h\n"
"ori %r3, %r3, AppEntrypoint@l\n"
"lwz %r3, 0(%r3)\n"
"mtlr %r3\n"
"blr\n"
);
}
fail();
}

View File

@ -0,0 +1,173 @@
/***************************************************************************
* Copyright (C) 2010
* by dude
*
* 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.
*
* Channel Launcher Class
*
* for WiiXplorer 2010
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogcsys.h>
#include <unistd.h>
#include <malloc.h>
#include "ChannelHandler.hpp"
#include "patchcode.h"
#include "cios.h"
#include "fs.h"
#include "fst.h"
#include "lz77.h"
#include "utils.h"
#include "videopatch.h"
#include "video_tinyload.h"
using namespace std;
void *dolchunkoffset[18];
u32 dolchunksize[18];
u32 dolchunkcount;
u32 bootcontent;
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
static u8 *GetDol(u32 bootcontent, u64 title)
{
memset(filepath, 0, ISFS_MAXPATH);
sprintf(filepath, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(title), TITLE_LOWER(title), bootcontent);
u32 contentSize = 0;
u8 *data = ISFS_GetFile((u8 *) &filepath, &contentSize, -1);
if(data != NULL && contentSize != 0)
{
if(isLZ77compressed(data))
{
u8 *decompressed;
u32 size = 0;
if(decompressLZ77content(data, contentSize, &decompressed, &size) < 0)
{
free(data);
return NULL;
}
free(data);
data = decompressed;
}
return data;
}
return NULL;
}
static bool GetAppNameFromTmd(bool dol, u32 *bootcontent, u64 title)
{
bool ret = false;
memset(filepath, 0, ISFS_MAXPATH);
sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title));
u32 size;
u8 *data = ISFS_GetFile((u8 *) &filepath, &size, -1);
if(data == NULL || size < 0x208)
return ret;
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
for(u16 i = 0; i < tmd_file->num_contents; ++i)
{
if(tmd_file->contents[i].index == (dol ? tmd_file->boot_index : 0))
{
*bootcontent = tmd_file->contents[i].cid;
ret = true;
break;
}
}
free(data);
return ret;
}
static u32 MoveDol(u8 *buffer)
{
dolchunkcount = 0;
dolheader *dolfile = (dolheader *)buffer;
if(dolfile->bss_start)
{
if(!(dolfile->bss_start & 0x80000000))
dolfile->bss_start |= 0x80000000;
memset((void *)dolfile->bss_start, 0, dolfile->bss_size);
DCFlushRange((void *)dolfile->bss_start, dolfile->bss_size);
ICInvalidateRange((void *)dolfile->bss_start, dolfile->bss_size);
}
for(u8 i = 0; i < 18; i++)
{
if(!dolfile->section_size[i])
continue;
if(dolfile->section_pos[i] < sizeof(dolheader))
continue;
if(!(dolfile->section_start[i] & 0x80000000))
dolfile->section_start[i] |= 0x80000000;
dolchunkoffset[dolchunkcount] = (void *)dolfile->section_start[i];
dolchunksize[dolchunkcount] = dolfile->section_size[i];
memmove(dolchunkoffset[dolchunkcount], buffer + dolfile->section_pos[i], dolchunksize[dolchunkcount]);
dolchunkcount++;
prog(5);
}
return dolfile->entry_point;
}
u32 LoadChannel(u64 title)
{
u32 entry = 0;
GetAppNameFromTmd(true, &bootcontent, title);
u8 *data = GetDol(bootcontent, title);
entry = MoveDol(data);
free(data);
return entry;
}
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio, u64 title)
{
bool hook = false;
for(u8 i = 0; i < dolchunkcount; i++)
{
patchVideoModes(dolchunkoffset[i], dolchunksize[i], vidMode, vmode, patchVidModes);
if(vipatch) vidolpatcher(dolchunkoffset[i], dolchunksize[i]);
if(configbytes[0] != 0xCD) langpatcher(dolchunkoffset[i], dolchunksize[i]);
if(countryString) PatchCountryStrings(dolchunkoffset[i], dolchunksize[i]);
if(aspectRatio != -1) PatchAspectRatio(dolchunkoffset[i], dolchunksize[i], aspectRatio);
if(hooktype != 0 && dogamehooks(dolchunkoffset[i], dolchunksize[i], true))
hook = true;
DCFlushRange(dolchunkoffset[i], dolchunksize[i]);
ICInvalidateRange(dolchunkoffset[i], dolchunksize[i]);
prog(5);
}
if(hook)
ocarina_do_code(title);
}

View File

@ -0,0 +1,20 @@
#ifndef __CHANHANDLE_HPP_
#define __CHANHANDLE_HPP_
typedef struct _dolheader
{
u32 section_pos[18];
u32 section_start[18];
u32 section_size[18];
u32 bss_start;
u32 bss_size;
u32 entry_point;
u32 padding[7];
} __attribute__((packed)) dolheader;
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString,
u8 patchVidModes, int aspectRatio, u64 title);
u32 LoadChannel(u64 title);
#endif /* __CHANHANDLE_HPP_ */

View File

@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _CFG_H_
#define _CFG_H_
#ifndef _CFG_HPP_
#define _CFG_HPP_
#include "cios.h"
#include "frag.h"
@ -37,8 +37,8 @@ typedef struct _the_CFG {
u8 patchVidMode;
u8 configbytes[2];
u8 debugger;
u8 vipatch;
u8 countryString;
bool vipatch;
bool countryString;
int aspectRatio;
void *codelist;
u8 *codelistend;

View File

@ -1,15 +1,17 @@
#include <stdio.h>
#include <ogcsys.h>
#include <string.h>
#include <malloc.h>
#include "apploader.h"
#include "wdvd.h"
#include "patchcode.h"
#include "videopatch.h"
#include "cios.h"
#include "fst.h"
#include "wip.h"
#include "debug.h"
#include "utils.h"
#include "di.h"
#include "cache.h"
#include "config.h"
#include "video.h"
#include "gecko.h"
#include "video_tinyload.h"
/* Apploader function pointers */
typedef int (*app_main)(void **dst, int *size, int *offset);
@ -20,50 +22,36 @@ typedef void (*app_entry)(void (**init)(void (*report)(const char *fmt, ...)),
/* Apploader pointers */
static u8 *appldr = (u8 *)0x81200000;
/* Variables */
static u32 buffer[0x20] __attribute__((aligned(32)));
/* Constants */
#define APPLDR_OFFSET 0x2440
void maindolpatches(void *dst, int len, u8 vidMode, u8 vipatch, u8 countryString, u8 patchVidModes, int aspectRatio, u32 returnTo);
/* Variables */
static u32 buffer[0x20] ATTRIBUTE_ALIGN(32);
void maindolpatches(void *dst, int len, u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio, u32 returnTo);
static void patch_NoDiscinDrive(void *buffer, u32 len);
static void Anti_002_fix(void *Address, int Size);
static u8 Remove_001_Protection(void *Address, int Size);
static u8 PrinceOfPersiaPatch();
static u8 NewSuperMarioBrosPatch();
u8 hookpatched = 0;
u8 wip_needed = 0;
static bool Remove_001_Protection(void *Address, int Size);
static bool PrinceOfPersiaPatch();
static bool NewSuperMarioBrosPatch();
bool hookpatched = false;
static void simple_report(const char *fmt, ...)
s32 Apploader_Run(entry_point *entry, u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio, u32 returnTo)
{
debug_string(fmt);
}
PrinceOfPersiaPatch();
NewSuperMarioBrosPatch();
u32 Apploader_Run(u8 vidMode, u8 vipatch, u8 countryString, u8 patchVidModes, int aspectRatio, u32 returnTo)
{
/* Check if WIP patches are needed */
if(PrinceOfPersiaPatch() == 1)
{
debug_string("PoP patch\n");
wip_needed = 1;
}
else if(NewSuperMarioBrosPatch() == 1)
{
debug_string("NSMBW patch\n");
wip_needed = 1;
}
else
{
debug_string("No WIP patch\n");
wip_needed = 0;
}
/* Variables */
s32 ret;
void *dst = NULL;
int len = 0;
int offset = 0;
u32 appldr_len;
s32 ret;
app_init appldr_init;
app_main appldr_main;
app_final appldr_final;
/* Read apploader header */
ret = di_read(buffer, 0x20, 0x910);
ret = WDVD_Read(buffer, 0x20, APPLDR_OFFSET);
if(ret < 0)
return ret;
@ -71,12 +59,13 @@ u32 Apploader_Run(u8 vidMode, u8 vipatch, u8 countryString, u8 patchVidModes, in
appldr_len = buffer[5] + buffer[6];
/* Read apploader code */
ret = di_read(appldr, appldr_len, 0x918);
ret = WDVD_Read(appldr, appldr_len, APPLDR_OFFSET + 0x20);
if(ret < 0)
return ret;
/* Flush into memory */
sync_after_write(appldr, appldr_len);
DCFlushRange(appldr, appldr_len);
ICInvalidateRange(appldr, appldr_len);
/* Set apploader entry function */
app_entry appldr_entry = (app_entry)buffer[4];
@ -85,28 +74,33 @@ u32 Apploader_Run(u8 vidMode, u8 vipatch, u8 countryString, u8 patchVidModes, in
appldr_entry(&appldr_init, &appldr_main, &appldr_final);
/* Initialize apploader */
appldr_init(simple_report);
appldr_init(gprintf);
void *dst = NULL;
int len = 0;
int offset = 0;
while(appldr_main(&dst, &len, &offset))
{
/* Read data from DVD */
di_read(dst, len, offset);
maindolpatches(dst, len, vidMode, vipatch, countryString, patchVidModes, aspectRatio, returnTo);
sync_after_write(dst, len);
WDVD_Read(dst, len, (u64)(offset << 2));
maindolpatches(dst, len, vidMode, vmode, vipatch, countryString, patchVidModes, aspectRatio, returnTo);
DCFlushRange(dst, len);
ICInvalidateRange(dst, len);
prog10();
}
if(wip_needed == 1)
free_wip();
if(hooktype != 0 && hookpatched == 1)
if(hooktype != 0 && hookpatched)
ocarina_do_code(0);
/* Set entry point from apploader */
return (u32)appldr_final();
*entry = appldr_final();
/* ERROR 002 fix (WiiPower) */
*(u32 *)0x80003140 = *(u32 *)0x80003188;
DCFlushRange((void*)0x80000000, 0x3f00);
return 0;
}
void maindolpatches(void *dst, int len, u8 vidMode, u8 vipatch, u8 countryString, u8 patchVidModes, int aspectRatio, u32 returnTo)
void maindolpatches(void *dst, int len, u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio, u32 returnTo)
{
// Patch NoDiscInDrive only for IOS 249 < rev13 or IOS 222/223/224
if((CurrentIOS.Type == IOS_TYPE_WANIN && CurrentIOS.Revision < 13) || CurrentIOS.Type == IOS_TYPE_HERMES)
@ -114,20 +108,20 @@ void maindolpatches(void *dst, int len, u8 vidMode, u8 vipatch, u8 countryString
if(CurrentIOS.Type == IOS_TYPE_WANIN && CurrentIOS.Revision < 13)
Anti_002_fix(dst, len);
Remove_001_Protection(dst, len);
//patchVideoModes(dst, len, vidMode, vmode, patchVidModes);
if(hooktype != 0 && dogamehooks(dst, len, 0))
hookpatched = 1;
if(vipatch == 1)
patchVideoModes(dst, len, vidMode, vmode, patchVidModes);
if(hooktype != 0 && dogamehooks(dst, len, false))
hookpatched = true;
if(vipatch)
vidolpatcher(dst, len);
if(configbytes[0] != 0xCD)
langpatcher(dst, len);
//if(conf->countryString)
// PatchCountryStrings(dst, len); // Country Patch by WiiPower
if(countryString)
PatchCountryStrings(dst, len); // Country Patch by WiiPower
if(aspectRatio != -1)
PatchAspectRatio(dst, len, aspectRatio);
if(returnTo > 0)
if(returnTo)
PatchReturnTo(dst, len, returnTo);
if(wip_needed == 1)
do_wip_code((u8 *)dst, len);
}
@ -160,12 +154,12 @@ static void Anti_002_fix(void *Address, int Size)
}
}
static u8 PrinceOfPersiaPatch()
static bool PrinceOfPersiaPatch()
{
if (memcmp("SPX", (char *) 0x80000000, 3) != 0 && memcmp("RPW", (char *) 0x80000000, 3) != 0)
return 0;
WIP_Code CodeList[5*sizeof(WIP_Code)];
return false;
WIP_Code * CodeList = malloc(5 * sizeof(WIP_Code));
CodeList[0].offset = 0x007AAC6A;
CodeList[0].srcaddress = 0x7A6B6F6A;
CodeList[0].dstaddress = 0x6F6A7A6B;
@ -181,16 +175,26 @@ static u8 PrinceOfPersiaPatch()
CodeList[4].offset = 0x007AAC9D;
CodeList[4].srcaddress = 0x82806F3F;
CodeList[4].dstaddress = 0x6F3F8280;
set_wip_list(CodeList, 5);
return 1;
if (set_wip_list(CodeList, 5) == false)
{
free(CodeList);
CodeList = NULL;
return false;
}
static u8 NewSuperMarioBrosPatch()
return true;
}
static bool NewSuperMarioBrosPatch()
{
WIP_Code CodeList[3 * sizeof(WIP_Code)];
WIP_Code * CodeList = NULL;
if (memcmp("SMNE01", (char *) 0x80000000, 6) == 0)
{
CodeList = malloc(3 * sizeof(WIP_Code));
if(!CodeList)
return false;
CodeList[0].offset = 0x001AB610;
CodeList[0].srcaddress = 0x9421FFD0;
CodeList[0].dstaddress = 0x4E800020;
@ -200,11 +204,12 @@ static u8 NewSuperMarioBrosPatch()
CodeList[2].offset = 0x001CED6B;
CodeList[2].srcaddress = 0xDA000000;
CodeList[2].dstaddress = 0x71000000;
set_wip_list(CodeList, 3);
return 1;
}
else if (memcmp("SMNP01", (char *) 0x80000000, 6) == 0)
{
CodeList = malloc(3 * sizeof(WIP_Code));
if(!CodeList)
return false;
CodeList[0].offset = 0x001AB750;
CodeList[0].srcaddress = 0x9421FFD0;
CodeList[0].dstaddress = 0x4E800020;
@ -214,11 +219,12 @@ static u8 NewSuperMarioBrosPatch()
CodeList[2].offset = 0x001CEEA8;
CodeList[2].srcaddress = 0x388000DA;
CodeList[2].dstaddress = 0x38800071;
set_wip_list(CodeList, 3);
return 1;
}
else if (memcmp("SMNJ01", (char *) 0x80000000, 6) == 0)
{
CodeList = malloc(3 * sizeof(WIP_Code));
if(!CodeList)
return false;
CodeList[0].offset = 0x001AB420;
CodeList[0].srcaddress = 0x9421FFD0;
CodeList[0].dstaddress = 0x4E800020;
@ -228,13 +234,17 @@ static u8 NewSuperMarioBrosPatch()
CodeList[2].offset = 0x001CEB7B;
CodeList[2].srcaddress = 0xDA000000;
CodeList[2].dstaddress = 0x71000000;
set_wip_list(CodeList, 3);
return 1;
}
return 0;
if (CodeList && set_wip_list(CodeList, 3) == false)
{
free(CodeList);
CodeList = NULL;
return false;
}
return CodeList != NULL;
}
static u8 Remove_001_Protection(void *Address, int Size)
static bool Remove_001_Protection(void *Address, int Size)
{
static const u8 SearchPattern[] = {0x40, 0x82, 0x00, 0x0C, 0x38, 0x60, 0x00, 0x01, 0x48, 0x00, 0x02, 0x44, 0x38, 0x61, 0x00, 0x18};
static const u8 PatchData[] = {0x40, 0x82, 0x00, 0x04, 0x38, 0x60, 0x00, 0x01, 0x48, 0x00, 0x02, 0x44, 0x38, 0x61, 0x00, 0x18};
@ -246,8 +256,8 @@ static u8 Remove_001_Protection(void *Address, int Size)
if (memcmp(Addr, SearchPattern, sizeof SearchPattern) == 0)
{
memcpy(Addr, PatchData, sizeof PatchData);
return 1;
return true;
}
}
return 0;
return false;
}

View File

@ -0,0 +1,18 @@
#ifndef _APPLOADER_H_
#define _APPLOADER_H_
/* Entry point */
typedef void (*entry_point)(void);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Prototypes */
s32 Apploader_Run(entry_point *entry,u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio, u32 returnTo);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -24,24 +24,27 @@
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include "cios.h"
#include "debug.h"
#include "ios.h"
#include <gctypes.h>
#include <string.h>
#include <stdio.h>
u8 Hermes_shadow_mload(int mload_rev)
#include "cios.h"
#include "gecko.h"
bool Hermes_shadow_mload(int mload_rev)
{
int v51 = (5 << 4) & 1;
if(mload_rev >= v51)
{
ios_open("/dev/mload/OFF",0); // shadow /dev/mload supported in hermes cios v5.1
debug_string("Shadow mload\n");
return 1;
IOS_Open("/dev/mload/OFF",0); // shadow /dev/mload supported in hermes cios v5.1
gprintf("Shadow mload\n");
return true;
}
return 0;
return false;
}
void Hermes_Disable_EHC()
{
ios_open("/dev/usb123/OFF", 0);// this disables ehc completely
debug_string("Hermes EHC Disabled\n");
IOS_Open("/dev/usb123/OFF", 0);// this disables ehc completely
gprintf("Hermes EHC Disabled\n");
}

View File

@ -2,6 +2,7 @@
#ifndef _CIOSINFO_H_
#define _CIOSINFO_H_
#include <gccore.h>
#include "types.h"
#ifdef __cplusplus
@ -23,8 +24,14 @@ typedef struct _IOS_Info {
u8 Type;
u8 Base;
} IOS_Info;
extern IOS_Info CurrentIOS;
u8 Hermes_shadow_mload(int mload_rev);
void IOS_GetCurrentIOSInfo();
bool IOS_D2X(u8 ios, u8 *base);
u8 IOS_GetType(u8 slot);
bool Hermes_shadow_mload(int mload_rev);
void Hermes_Disable_EHC();
#ifdef __cplusplus

View File

@ -0,0 +1,265 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogcsys.h>
#include <unistd.h>
#include <malloc.h>
#include <ogc/lwp_watchdog.h>
#include "frag.h"
#include "memory.h"
#include "cios.h"
#include "types.h"
#include "wdvd.h"
/* Constants */
#define PTABLE_OFFSET 0x40000
static u8 *diskid = (u8*)0x80000000;
s32 Disc_Open()
{
/* Reset drive */
s32 ret = WDVD_Reset();
if (ret < 0) return ret;
memset(diskid, 0, 32);
/* Read disc ID */
ret = WDVD_ReadDiskId(diskid);
return ret;
}
void Disc_SetLowMem()
{
/* Setup low memory */
*Sys_Magic = 0x0D15EA5E; // Standard Boot Code
*Sys_Version = 0x00000001; // Version
*Arena_L = 0x00000000; // Arena Low
*BI2 = 0x817E5480; // BI2
*Bus_Speed = 0x0E7BE2C0; // Console Bus Speed
*CPU_Speed = 0x2B73A840; // Console CPU Speed
*Assembler = 0x38A00040; // Assembler
*(vu32*)0x800000E4 = 0x80431A80;
*Dev_Debugger = 0x81800000; // Dev Debugger Monitor Address
*Simulated_Mem = 0x01800000; // Simulated Memory Size
*(vu32*)0xCD00643C = 0x00000000; // 32Mhz on Bus
/* Fix for Sam & Max (WiiPower) */
if(CurrentIOS.Type != IOS_TYPE_HERMES)
*GameID_Address = 0x80000000;
/* Copy disc ID */
memcpy((void *)Online_Check, (void *)Disc_ID, 4);
}
s32 Disc_FindPartition(u64 *outbuf)
{
u8 TMP_Buffer_size = 0x20;
u64 offset = 0;
u32 cnt;
u32 *TMP_Buffer = (u32*)memalign(32, TMP_Buffer_size);
if(!TMP_Buffer)
return -1;
/* Read partition info */
s32 ret = WDVD_UnencryptedRead(TMP_Buffer, TMP_Buffer_size, PTABLE_OFFSET);
if(ret < 0)
{
free(TMP_Buffer);
return ret;
}
/* Get data */
u32 nb_partitions = TMP_Buffer[0];
u64 table_offset = TMP_Buffer[1] << 2;
if(nb_partitions > 8)
{
free(TMP_Buffer);
return -1;
}
memset(TMP_Buffer, 0, TMP_Buffer_size);
/* Read partition table */
ret = WDVD_UnencryptedRead(TMP_Buffer, TMP_Buffer_size, table_offset);
if (ret < 0)
{
free(TMP_Buffer);
return ret;
}
/* Find game partition */
for(cnt = 0; cnt < nb_partitions; cnt++)
{
u32 type = TMP_Buffer[cnt * 2 + 1];
/* Game partition */
if(!type)
offset = TMP_Buffer[cnt * 2] << 2;
}
free(TMP_Buffer);
/* No game partition found */
if (!offset)
return -1;
/* Set output buffer */
*outbuf = offset;
WDVD_Seek(offset);
return 0;
}
void Disc_SetTime()
{
/* Set proper time */
settime(secs_to_ticks(time(NULL) - 946684800));
}
GXRModeObj *Disc_SelectVMode(u8 videoselected, u32 *rmode_reg)
{
GXRModeObj *rmode = VIDEO_GetPreferredMode(0);
/* Get video mode configuration */
bool progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable();
/* Select video mode register */
switch (CONF_GetVideo())
{
case CONF_VIDEO_PAL:
if (CONF_GetEuRGB60() > 0)
{
*rmode_reg = VI_EURGB60;
rmode = progressive ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf;
}
else
*rmode_reg = VI_PAL;
break;
case CONF_VIDEO_MPAL:
*rmode_reg = VI_MPAL;
break;
case CONF_VIDEO_NTSC:
*rmode_reg = VI_NTSC;
break;
}
char Region = diskid[3];
switch(videoselected)
{
case 0: // DEFAULT (DISC/GAME)
/* Select video mode */
switch(Region)
{
case 'W':
break; // Don't overwrite wiiware video modes.
// PAL
case 'D':
case 'F':
case 'P':
case 'X':
case 'Y':
if(CONF_GetVideo() != CONF_VIDEO_PAL)
{
*rmode_reg = VI_PAL;
rmode = progressive ? &TVNtsc480Prog : &TVNtsc480IntDf;
}
break;
// NTSC
case 'E':
case 'J':
default:
if(CONF_GetVideo() != CONF_VIDEO_NTSC)
{
*rmode_reg = VI_NTSC;
rmode = progressive ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf;
}
break;
}
break;
case 1: // SYSTEM
break;
case 2: // PAL50
rmode = &TVPal528IntDf;
*rmode_reg = rmode->viTVMode >> 2;
break;
case 3: // PAL60
rmode = progressive ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf;
*rmode_reg = progressive ? TVEurgb60Hz480Prog.viTVMode >> 2 : rmode->viTVMode >> 2;
break;
case 4: // NTSC
rmode = progressive ? &TVNtsc480Prog : &TVNtsc480IntDf;
*rmode_reg = rmode->viTVMode >> 2;
break;
case 5: // PROGRESSIVE 480P
rmode = &TVNtsc480Prog;
*rmode_reg = Region == 'P' ? TVEurgb60Hz480Prog.viTVMode >> 2 : rmode->viTVMode >> 2;
break;
default:
break;
}
return rmode;
}
void Disc_SetVMode(GXRModeObj *rmode, u32 rmode_reg)
{
/* Set video mode register */
*Video_Mode = rmode_reg;
DCFlushRange((void*)Video_Mode, 4);
/* Set video mode */
if(rmode != 0)
VIDEO_Configure(rmode);
/* Setup video */
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode & VI_NON_INTERLACE)
VIDEO_WaitVSync();
else while(VIDEO_GetNextField())
VIDEO_WaitVSync();
/* Set black and flush */
VIDEO_SetBlack(TRUE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode & VI_NON_INTERLACE)
VIDEO_WaitVSync();
else while(VIDEO_GetNextField())
VIDEO_WaitVSync();
}
s32 wbfsDev = 0;
u32 wbfs_part_idx = 0;
FragList *frag_list = NULL;
static int set_frag_list()
{
// (+1 for header which is same size as fragment)
int size = sizeof(Fragment) * (frag_list->num + 1);
DCFlushRange(frag_list, size);
return WDVD_SetFragList(wbfsDev, frag_list, size);
}
s32 Disc_SetUSB(const u8 *id, bool frag)
{
/* ENABLE USB in cIOS */
if(id)
{
if(frag)
return set_frag_list();
s32 part = -1;
if(CurrentIOS.Type == IOS_TYPE_HERMES)
part = wbfs_part_idx ? wbfs_part_idx - 1 : 0;
return WDVD_SetUSBMode(wbfsDev, (u8*)id, part);
}
/* DISABLE USB in cIOS */
return WDVD_SetUSBMode(0, NULL, -1);
}

View File

@ -6,14 +6,15 @@
extern "C" {
#endif /* __cplusplus */
/*s32 Disc_Open();
s32 Disc_FindPartition(u64 *outbuf);*/
s32 Disc_SetUSB(const u8 *id, u8 frag);
s32 Disc_Open();
s32 Disc_FindPartition(u64 *outbuf);
s32 Disc_SetUSB(const u8 *id, bool frag);
void Disc_SetLowMem();
/*
void Disc_SetTime();
GXRModeObj *Disc_SelectVMode(u8 videoselected, u32 *rmode_reg);
void Disc_SetVMode(GXRModeObj *rmode, u32 rmode_reg);
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -9,7 +9,7 @@
extern "C" {
#endif
#include "types.h"
#include "gctypes.h"
typedef struct
{

View File

@ -0,0 +1,48 @@
#include <ogcsys.h>
#include <locale.h>
#include <malloc.h>
#include <ogc/isfs.h>
#include <string.h>
#include "fs.h"
#include "utils.h"
static fstats stats ATTRIBUTE_ALIGN(32);
u8 *ISFS_GetFile(u8 *path, u32 *size, s32 length)
{
*size = 0;
s32 fd = ISFS_Open((const char *)path, ISFS_OPEN_READ);
u8 *buf = NULL;
if(fd >= 0)
{
memset(&stats, 0, sizeof(fstats));
if(ISFS_GetFileStats(fd, &stats) >= 0)
{
if(length <= 0)
length = stats.file_length;
if(length > 0)
buf = (u8 *)memalign(32, ALIGN32(length));
if(buf)
{
*size = stats.file_length;
if(ISFS_Read(fd, (char*)buf, length) != length)
{
*size = 0;
free(buf);
}
}
}
ISFS_Close(fd);
}
if(*size > 0)
{
DCFlushRange(buf, *size);
ICInvalidateRange(buf, *size);
}
return buf;
}

View File

@ -0,0 +1,15 @@
#ifndef _FS_H_
#define _FS_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
u8 *ISFS_GetFile(u8 *path, u32 *size, s32 length);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -18,10 +18,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "types.h"
#include "utils.h"
#include "cache.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gccore.h>
#include <sys/unistd.h>
#include <ogc/ipc.h>
#include "fst.h"
#include "gecko.h"
#include "memory.h"
#include "patchcode.h"
#include "codehandler.h"
#include "codehandleronly.h"
@ -68,21 +74,19 @@ void ocarina_set_codes(void *list, u8 *listend, u8 *cheats, u32 cheatSize)
code_size = cheatSize;
if(code_size <= 0)
{
//printf("Ocarina: No codes found\n");
gprintf("Ocarina: No codes found\n");
code_buf = NULL;
code_size = 0;
return;
}
if (code_size > (u32)codelistend - (u32)codelist)
{
//printf("Ocarina: Too many codes found\n");
gprintf("Ocarina: Too many codes found\n");
code_buf = NULL;
code_size = 0;
return;
}
//printf("Ocarina: Codes found.\n");
gprintf("Ocarina: Codes found.\n");
}
void app_pokevalues()
@ -99,7 +103,7 @@ void app_pokevalues()
*((u32 *) (*(gameconf + i + 1))) == *(gameconf + i + 2))
{
*((u32 *) (*(gameconf + i + 3))) = *(gameconf + i + 4);
sync_after_write((void *) *(gameconf + i + 3), 4);
DCFlushRange((void *) *(gameconf + i + 3), 4);
}
i += 4;
}
@ -149,7 +153,7 @@ void load_handler()
memcpy((void*)0x80001CE2, ((u8*) &codelist) + 2, 2);
memcpy((void*)0x80001F5A, &codelist, 2);
memcpy((void*)0x80001F5E, ((u8*) &codelist) + 2, 2);
sync_after_write((void*)0x80001800,codehandler_size);
DCFlushRange((void*)0x80001800,codehandler_size);
}
else
{
@ -158,13 +162,13 @@ void load_handler()
memcpy((void*)0x80001800,codehandleronly,codehandleronly_size);
memcpy((void*)0x80001906, &codelist, 2);
memcpy((void*)0x8000190A, ((u8*) &codelist) + 2, 2);
sync_after_write((void*)0x80001800,codehandleronly_size);
DCFlushRange((void*)0x80001800,codehandleronly_size);
}
// Load multidol handler
memset((void*)0x80001000,0,multidol_size);
memcpy((void*)0x80001000,multidol,multidol_size);
sync_after_write((void*)0x80001000,multidol_size);
DCFlushRange((void*)0x80001000,multidol_size);
switch(hooktype)
{
case 0x01:
@ -211,7 +215,7 @@ void load_handler()
//memcpy((void*)0x80001198,wpadbuttonsdown2hooks+3,4);
break;
}
sync_after_write((void*)0x80001198,16);
DCFlushRange((void*)0x80001198,16);
}
memcpy((void *)0x80001800, (void*)0x80000000, 6);
}
@ -223,21 +227,19 @@ int ocarina_do_code(u64 chantitle)
memset((void *)0x80001800, 0, 0x1800);
char gameidbuffer[8];
memset(gameidbuffer, 0, 8);
if(chantitle != 0)
{
memset(gameidbuffer, 0, 8);
gameidbuffer[0] = (chantitle & 0xff000000) >> 24;
gameidbuffer[1] = (chantitle & 0x00ff0000) >> 16;
gameidbuffer[2] = (chantitle & 0x0000ff00) >> 8;
gameidbuffer[3] = chantitle & 0x000000ff;
}
else
strncpy(gameidbuffer, (char*)Disc_ID, 6);
load_handler();
if(chantitle != 0)
{
memcpy((void *)0x80001800, gameidbuffer, 8);
sync_after_write((void *)0x80001800, 8);
}
DCFlushRange((void *)0x80001800, 8);
if(codelist)
memset(codelist, 0, (u32)codelistend - (u32)codelist);
@ -246,7 +248,7 @@ int ocarina_do_code(u64 chantitle)
if(code_size > 0 && code_buf)
{
memcpy(codelist, code_buf, code_size);
sync_after_write(codelist, (u32)codelistend - (u32)codelist);
DCFlushRange(codelist, (u32)codelistend - (u32)codelist);
}
// TODO What's this???

View File

@ -0,0 +1,45 @@
#include <gccore.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <sys/iosupport.h>
#include <stdarg.h>
#include "gecko.h"
/* init-globals */
bool geckoinit = false;
static ssize_t __out_write(struct _reent *r __attribute__((unused)), int fd __attribute__((unused)), const char *ptr, size_t len)
{
if(geckoinit && ptr)
{
u32 level;
level = IRQ_Disable();
usb_sendbuffer_safe(1, ptr, len);
IRQ_Restore(level);
}
return len;
}
char gprintfBuffer[256];
void gprintf(const char *format, ...)
{
va_list va;
va_start(va, format);
int len = vsnprintf(gprintfBuffer, 255, format, va);
__out_write(NULL, 0, gprintfBuffer, len);
va_end(va);
}
bool InitGecko()
{
if(geckoinit)
return geckoinit;
u32 geckoattached = usb_isgeckoalive(EXI_CHANNEL_1);
if(geckoattached)
{
geckoinit = true;
usb_flush(EXI_CHANNEL_1);
}
return geckoinit;
}

View File

@ -0,0 +1,23 @@
#ifndef _GECKO_H_
#define _GECKO_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <gccore.h>
extern bool bufferMessages;
extern bool WriteToSD;
//use this just like printf();
void gprintf(const char *format, ...);
void ghexdump(void *d, int len);
bool InitGecko();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,215 @@
/*******************************************************************************
* lz77.c
*
* Copyright (c) 2009 The Lemon Man
* Copyright (c) 2009 Nicksasa
* Copyright (c) 2009 WiiPower
*
* Distributed under the terms of the GNU General Public License (v2)
* See http://www.gnu.org/licenses/gpl-2.0.txt for more info.
*
* Description:
* -----------
*
******************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include "lz77.h"
#include "utils.h"
u32 packBytes(int a, int b, int c, int d)
{
return (d << 24) | (c << 16) | (b << 8) | (a);
}
s32 __decompressLZ77_11(u8 *in, u32 inputLen, u8 **output, u32 *outputLen)
{
int x, y;
u8 *out = NULL;
u32 compressedPos = 0x4;
u32 decompressedPos = 0x0;
u32 decompressedSize = 0;
decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8;
if (!decompressedSize)
{
decompressedSize = packBytes(in[4], in[5], in[6], in[7]);
compressedPos += 0x4;
}
//printf("Decompressed size : %i\n", decompressedSize);
out = malloc(ALIGN32(decompressedSize));
if (out == NULL)
{
printf("Out of memory\n");
return -1;
}
while (compressedPos < inputLen && decompressedPos < decompressedSize)
{
u8 byteFlag = in[compressedPos];
compressedPos++;
for (x = 7; x >= 0; x--)
{
if ((byteFlag & (1 << x)) > 0)
{
u8 first = in[compressedPos];
u8 second = in[compressedPos + 1];
u32 pos, copyLen;
if (first < 0x20)
{
u8 third = in[compressedPos + 2];
if (first >= 0x10)
{
u32 fourth = in[compressedPos + 3];
pos = (u32)(((third & 0xF) << 8) | fourth) + 1;
copyLen = (u32)((second << 4) | ((first & 0xF) << 12) | (third >> 4)) + 273;
compressedPos += 4;
} else
{
pos = (u32)(((second & 0xF) << 8) | third) + 1;
copyLen = (u32)(((first & 0xF) << 4) | (second >> 4)) + 17;
compressedPos += 3;
}
} else
{
pos = (u32)(((first & 0xF) << 8) | second) + 1;
copyLen = (u32)(first >> 4) + 1;
compressedPos += 2;
}
for (y = 0; y < (int)copyLen; y++)
{
out[decompressedPos + y] = out[decompressedPos - pos + y];
}
decompressedPos += copyLen;
} else
{
out[decompressedPos] = in[compressedPos];
decompressedPos++;
compressedPos++;
}
if (compressedPos >= inputLen || decompressedPos >= decompressedSize)
break;
}
}
*output = out;
*outputLen = decompressedSize;
return 0;
}
s32 __decompressLZ77_10(u8 *in, u8 **output, u32 *outputLen)
{
int x, y;
u8 *out = NULL;
u32 compressedPos = 0;
u32 decompressedSize = 0x4;
u32 decompressedPos = 0;
decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8;
//int compressionType = (packBytes(in[0], in[1], in[2], in[3]) >> 4) & 0xF;
//printf("Decompressed size : %i\n", decompressedSize);
out = malloc(ALIGN32(decompressedSize));
if (out == NULL)
{
printf("Out of memory\n");
return -1;
}
compressedPos += 0x4;
while (decompressedPos < decompressedSize)
{
u8 flag = *(u8*)(in + compressedPos);
compressedPos += 1;
for (x = 0; x < 8; x++)
{
if (flag & 0x80)
{
u8 first = in[compressedPos];
u8 second = in[compressedPos + 1];
u16 pos = (u16)((((first << 8) + second) & 0xFFF) + 1);
u8 copyLen = (u8)(3 + ((first >> 4) & 0xF));
for (y = 0; y < copyLen; y++)
{
out[decompressedPos + y] = out[decompressedPos - pos + (y % pos)];
}
compressedPos += 2;
decompressedPos += copyLen;
} else
{
out[decompressedPos] = in[compressedPos];
compressedPos += 1;
decompressedPos += 1;
}
flag <<= 1;
if (decompressedPos >= decompressedSize)
break;
}
}
*output = out;
*outputLen = decompressedSize;
return 0;
}
int isLZ77compressed(u8 *buffer)
{
if ((buffer[0] == LZ77_0x10_FLAG) || (buffer[0] == LZ77_0x11_FLAG))
{
return 1;
}
return 0;
}
int decompressLZ77content(u8 *buffer, u32 length, u8 **output, u32 *outputLen)
{
int ret;
switch (buffer[0])
{
case LZ77_0x10_FLAG:
//printf("LZ77 variant 0x10 compressed content...unpacking may take a while...\n");
ret = __decompressLZ77_10(buffer, output, outputLen);
break;
case LZ77_0x11_FLAG:
//printf("LZ77 variant 0x11 compressed content...unpacking may take a while...\n");
ret = __decompressLZ77_11(buffer, length, output, outputLen);
break;
default:
//printf("Not compressed ...\n");
ret = -1;
break;
}
return ret;
}

View File

@ -0,0 +1,34 @@
/*******************************************************************************
* lz77.h
*
* Copyright (c) 2009 The Lemon Man
* Copyright (c) 2009 Nicksasa
* Copyright (c) 2009 WiiPower
*
* Distributed under the terms of the GNU General Public License (v2)
* See http://www.gnu.org/licenses/gpl-2.0.txt for more info.
*
* Description:
* -----------
*
******************************************************************************/
#ifndef _LZ77_MODULE
#define _LZ77_MODULE
#define LZ77_0x10_FLAG 0x10
#define LZ77_0x11_FLAG 0x11
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int isLZ77compressed(u8 *buffer);
int decompressLZ77content(u8 *buffer, u32 length, u8 **output, u32 *outputLen);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -0,0 +1,198 @@
/****************************************************************************
* Copyright (C) 2012 FIX94
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogcsys.h>
#include <unistd.h>
#include <malloc.h>
#include "Config.hpp"
#include "ChannelHandler.hpp"
#include "video_tinyload.h"
#include "apploader.h"
#include "patchcode.h"
#include "disc.h"
#include "fst.h"
#include "wdvd.h"
#include "gecko.h"
using namespace std;
IOS_Info CurrentIOS;
/* Boot Variables */
u32 vmode_reg = 0;
entry_point p_entry;
GXRModeObj *vmode = NULL;
u32 AppEntrypoint;
extern "C" {
extern void __exception_closeall();
extern s32 wbfsDev;
extern u32 wbfs_part_idx;
extern FragList *frag_list;
}
the_CFG normalCFG;
int main()
{
InitGecko();
gprintf("WiiFlow External Booter by FIX94\n");
memcpy(&normalCFG, (void*)0x93100000, sizeof(the_CFG));
VIDEO_Init();
video_init();
prog10();
configbytes[0] = normalCFG.configbytes[0];
configbytes[1] = normalCFG.configbytes[1];
hooktype = normalCFG.hooktype;
debuggerselect = normalCFG.debugger;
CurrentIOS = normalCFG.IOS;
app_gameconfig_set(normalCFG.gameconf, normalCFG.gameconfsize);
ocarina_set_codes(normalCFG.codelist, normalCFG.codelistend, normalCFG.cheats, normalCFG.cheatSize);
frag_list = normalCFG.fragments;
wbfsDev = normalCFG.wbfsDevice;
wbfs_part_idx = normalCFG.wbfsPart;
if(normalCFG.BootType == TYPE_WII_GAME)
{
WDVD_Init();
if(normalCFG.GameBootType == TYPE_WII_DISC)
{
Disc_SetUSB(NULL, false);
if(CurrentIOS.Type == IOS_TYPE_HERMES)
Hermes_Disable_EHC();
}
else
{
Disc_SetUSB((u8*)normalCFG.gameID, normalCFG.GameBootType == TYPE_WII_WBFS_EXT);
if(CurrentIOS.Type == IOS_TYPE_HERMES)
Hermes_shadow_mload(normalCFG.mload_rev);
}
prog10();
Disc_Open();
Disc_SetLowMem();
prog10();
u64 offset = 0;
Disc_FindPartition(&offset);
WDVD_OpenPartition(offset);
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
prog10();
Apploader_Run(&p_entry, normalCFG.vidMode, vmode, normalCFG.vipatch, normalCFG.countryString, normalCFG.patchVidMode,
normalCFG.aspectRatio, normalCFG.returnTo);
AppEntrypoint = (u32)p_entry;
WDVD_Close();
}
else if(normalCFG.BootType == TYPE_CHANNEL)
{
ISFS_Initialize();
Disc_SetLowMem();
prog10();
AppEntrypoint = LoadChannel(normalCFG.title);
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
PatchChannel(normalCFG.vidMode, vmode, normalCFG.vipatch, normalCFG.countryString,
normalCFG.patchVidMode, normalCFG.aspectRatio, normalCFG.title);
ISFS_Deinitialize();
}
gprintf("Entrypoint: %08x\n", AppEntrypoint);
setprog(320);
/* Set time */
Disc_SetTime();
/* Set an appropriate video mode */
Disc_SetVMode(vmode, vmode_reg);
/* Shutdown IOS subsystems */
u32 level = IRQ_Disable();
__IOS_ShutdownSubsystems();
__exception_closeall();
/* Originally from tueidj - taken from NeoGamma (thx) */
*(vu32*)0xCC003024 = 1;
if(AppEntrypoint == 0x3400)
{
if(hooktype)
{
asm volatile (
"lis %r3, returnpoint@h\n"
"ori %r3, %r3, returnpoint@l\n"
"mtlr %r3\n"
"lis %r3, 0x8000\n"
"ori %r3, %r3, 0x18A8\n"
"nop\n"
"mtctr %r3\n"
"bctr\n"
"returnpoint:\n"
"bl DCDisable\n"
"bl ICDisable\n"
"li %r3, 0\n"
"mtsrr1 %r3\n"
"lis %r4, AppEntrypoint@h\n"
"ori %r4,%r4,AppEntrypoint@l\n"
"lwz %r4, 0(%r4)\n"
"mtsrr0 %r4\n"
"rfi\n"
);
}
else
{
asm volatile (
"isync\n"
"lis %r3, AppEntrypoint@h\n"
"ori %r3, %r3, AppEntrypoint@l\n"
"lwz %r3, 0(%r3)\n"
"mtsrr0 %r3\n"
"mfmsr %r3\n"
"li %r4, 0x30\n"
"andc %r3, %r3, %r4\n"
"mtsrr1 %r3\n"
"rfi\n"
);
}
}
else if (hooktype)
{
asm volatile (
"lis %r3, AppEntrypoint@h\n"
"ori %r3, %r3, AppEntrypoint@l\n"
"lwz %r3, 0(%r3)\n"
"mtlr %r3\n"
"lis %r3, 0x8000\n"
"ori %r3, %r3, 0x18A8\n"
"nop\n"
"mtctr %r3\n"
"bctr\n"
);
}
else
{
asm volatile (
"lis %r3, AppEntrypoint@h\n"
"ori %r3, %r3, AppEntrypoint@l\n"
"lwz %r3, 0(%r3)\n"
"mtlr %r3\n"
"blr\n"
);
}
IRQ_Restore(level);
return 0;
}

View File

@ -18,11 +18,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gccore.h>
#include <sys/unistd.h>
#include "apploader.h"
#include "patchcode.h"
#include "cache.h"
#include "debug.h"
u32 hooktype;
u8 configbytes[2];
@ -97,7 +100,7 @@ const u32 langpatch[3] = {0x7C600775, 0x40820010, 0x38000000};
static const u32 oldpatch002[3] = {0x2C000000, 0x40820214, 0x3C608000};
static const u32 newpatch002[3] = {0x2C000000, 0x48000214, 0x3C608000};
u8 dogamehooks(void *addr, u32 len, u8 channel)
bool dogamehooks(void *addr, u32 len, bool channel)
{
/*
0 No Hook
@ -112,21 +115,21 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
void *addr_start = addr;
void *addr_end = addr+len;
u8 hookpatched = 0;
bool hookpatched = false;
while(addr_start < addr_end)
{
switch(hooktype)
{
case 0x00:
hookpatched = 1;
hookpatched = true;
break;
case 0x01:
if(memcmp(addr_start, viwiihooks, sizeof(viwiihooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
break;
@ -134,13 +137,13 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
if(memcmp(addr_start, kpadhooks, sizeof(kpadhooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
if(memcmp(addr_start, kpadoldhooks, sizeof(kpadoldhooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
break;
@ -148,7 +151,7 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
if(memcmp(addr_start, joypadhooks, sizeof(joypadhooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
break;
@ -156,7 +159,7 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
if(memcmp(addr_start, gxdrawhooks, sizeof(gxdrawhooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
break;
@ -164,7 +167,7 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
if(memcmp(addr_start, gxflushhooks, sizeof(gxflushhooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
break;
@ -172,7 +175,7 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
if(memcmp(addr_start, ossleepthreadhooks, sizeof(ossleepthreadhooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
break;
@ -180,7 +183,7 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
if(memcmp(addr_start, axnextframehooks, sizeof(axnextframehooks))==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
}
break;
@ -188,7 +191,7 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
/* if(memcmp(addr_start, customhook, customhooksize)==0)
{
patchhook((u32)addr_start, len);
hookpatched = 1;
hookpatched = true;
} */
break;
}
@ -197,15 +200,15 @@ u8 dogamehooks(void *addr, u32 len, u8 channel)
if(channel && memcmp(addr_start, multidolchanhooks, sizeof(multidolchanhooks))==0)
{
*(((u32*)addr_start)+1) = 0x7FE802A6;
sync_after_write(((u32*)addr_start)+1, 4);
DCFlushRange(((u32*)addr_start)+1, 4);
multidolhook((u32)addr_start+sizeof(multidolchanhooks)-4);
hookpatched = 1;
hookpatched = true;
}
else if(!channel && memcmp(addr_start, multidolhooks, sizeof(multidolhooks))==0)
{
multidolhook((u32)addr_start+sizeof(multidolhooks)-4);
hookpatched = 1;
hookpatched = true;
}
}
addr_start += 4;
@ -251,12 +254,11 @@ static u32 ad[ 4 ] = { 0, 0, 0, 0 };//these variables are global on the off chan
static u8 found = 0; //to find in the dol are found in different sections of the dol
static u8 returnToPatched = 0;
u8 PatchReturnTo( void *Address, int Size, u32 id )
bool PatchReturnTo( void *Address, int Size, u32 id )
{
if(returnToPatched == 1)
if( !id || returnToPatched )
return 0;
//gprintf("PatchReturnTo( %p, %08x, %08x )\n", Address, Size, id );
//debug_string("PatchReturnTo ID:"); debug_uint(id); debug_string("\n");
//new __OSLoadMenu() (SM2.0 and higher)
u8 SearchPattern[ 12 ] = { 0x38, 0x80, 0x00, 0x02, 0x38, 0x60, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x00 }; //li r4,2
@ -356,7 +358,6 @@ u8 PatchReturnTo( void *Address, int Size, u32 id )
addr = (u32*)ad[ 0 ];
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
debug_uint((u32)addr); debug_string(" -> "); debug_uint(newval); debug_string("\n");
//gprintf("\t%08x -> %08x\n", addr, newval );
//ES_GetTicketViews() again
@ -366,7 +367,6 @@ u8 PatchReturnTo( void *Address, int Size, u32 id )
addr = (u32*)ad[ 1 ];
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
debug_uint((u32)addr); debug_string(" -> "); debug_uint(newval); debug_string("\n");
//gprintf("\t%08x -> %08x\n", addr, newval );
//ES_LaunchTitle()
@ -376,7 +376,6 @@ u8 PatchReturnTo( void *Address, int Size, u32 id )
addr = (u32*)ad[ 2 ];
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
debug_uint((u32)addr); debug_string(" -> "); debug_uint(newval); debug_string("\n");
//gprintf("\t%08x -> %08x\n", addr, newval );
returnToPatched = 1;
@ -414,7 +413,7 @@ void PatchAspectRatio(void *addr, u32 len, u8 aspect)
addr_start += 4;
}
}
#if 0
void PatchCountryStrings(void *Address, int Size)
{
u8 SearchPattern[4] = {0x00, 0x00, 0x00, 0x00};
@ -491,4 +490,3 @@ void PatchCountryStrings(void *Address, int Size)
}
}
}
#endif

View File

@ -30,12 +30,12 @@ extern u32 hooktype;
extern u8 configbytes[2];
// Function prototypes
u8 dogamehooks(void *addr, u32 len, u8 channel);
bool dogamehooks(void *addr, u32 len, bool channel);
void langpatcher(void *addr, u32 len);
void vidolpatcher(void *addr, u32 len);
void PatchCountryStrings(void *Address, int Size);
void PatchAspectRatio(void *addr, u32 len, u8 aspect);
u8 PatchReturnTo(void *Address, int Size, u32 id);
bool PatchReturnTo(void *Address, int Size, u32 id);
#ifdef __cplusplus
}

View File

@ -0,0 +1,43 @@
#ifndef _TYPES_H_
#define _TYPES_H_
#ifdef __cplusplus
extern "C" {
#endif
enum
{
TYPE_WII_DISC = 0,
TYPE_WII_WBFS,
TYPE_WII_WBFS_EXT,
};
enum
{
TYPE_WII_GAME = 0,
TYPE_GC_GAME,
TYPE_CHANNEL,
TYPE_PLUGIN,
TYPE_HOMEBREW,
TYPE_END
};
#define NoGameID(x) (x == TYPE_PLUGIN || x == TYPE_HOMEBREW)
enum
{
IOS_TYPE_D2X = 0,
IOS_TYPE_WANIN,
IOS_TYPE_HERMES,
IOS_TYPE_KWIIRK,
IOS_TYPE_NEEK2O,
IOS_TYPE_NORMAL_IOS,
IOS_TYPE_STUB,
};
#define CustomIOS(x) (x != IOS_TYPE_NORMAL_IOS && x != IOS_TYPE_STUB)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,26 @@
#ifndef _UTILS_H_
#define _UTILS_H_
#include <gctypes.h>
#define KB_SIZE 1024.0
#define MB_SIZE 1048576.0
#define GB_SIZE 1073741824.0
#define MAX_FAT_PATH 1024
#define round_up(x,n) (-(-(x) & -(n)))
#define ALIGN(n, x) (((x) + (n - 1)) & ~(n - 1))
#define ALIGN32(x) (((x) + 31) & ~31)
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
#define TITLE_UPPER(x) ((u32)((x) >> 32))
#define TITLE_LOWER(x) ((u32)(x) & 0xFFFFFFFF)
#define Write8(addr, val) *(u8 *)addr = val; DCFlushRange((void *)addr, sizeof(u8));
#define Write16(addr, val) *(u16 *)addr = val; DCFlushRange((void *)addr, sizeof(u16));
#define Write32(addr, val) *(u32 *)addr = val; DCFlushRange((void *)addr, sizeof(u32));
#endif

View File

@ -1,3 +1,15 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from HBC's stub which was based on dhewg's geckoloader stub */
// Copyright 2008-2009 Andre Heider <dhewg@wiibrew.org>
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#include <ogc/cache.h>
#include <string.h>
#include "utils.h"
#define COLOR_BLACK 0x00800080
@ -17,6 +29,15 @@ u32 vto,vte;
u64 oldvtovte;
int progress = 20;
void memset32(u32 *addr, u32 data, u32 count)
{
int sc = count;
void *sa = addr;
while(count--)
*addr++ = data;
DCFlushRange(sa, 4*sc);
}
static void drawbar(int pix)
{
int i = 16;
@ -79,10 +100,3 @@ void video_init(void)
prog(0);
}
void video_setblack(void)
{
/* this sets VI to black, but I can't fit it in yet... */
viw(0x0, oldvtrdcr);
*(vu64*)(0xCC00200c) = oldvtovte;
}

View File

@ -7,23 +7,21 @@
/* This code comes from HBC's stub which was based on dhewg's geckoloader stub */
// Copyright 2008-2009 Andre Heider <dhewg@wiibrew.org>
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#ifndef _VIDEO_TINYLOAD_H_
#define _VIDEO_TINYLOAD_H_
#ifndef _STUB_DEBUG_H_
#define _STUB_DEBUG_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "types.h"
void video_init(void);
void prog(int p);
void prog10(void);
void setprog(int p);
#ifdef DEBUG
void debug_uint (u32 i);
void debug_string (const char *s);
#else
#define debug_uint(x)
#define debug_string(x)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
#endif

View File

@ -0,0 +1,317 @@
// Inspired by WiiPower's "video toy", but simpler
#include "videopatch.h"
#include <string.h>
#define ARRAY_SIZE(a) (sizeof a / sizeof a[0])
extern GXRModeObj TVNtsc480Int;
GXRModeObj TVPal528Prog =
{
6, // viDisplayMode
640, // fbWidth
528, // efbHeight
528, // xfbHeight
(VI_MAX_WIDTH_PAL - 640)/2, // viXOrigin
(VI_MAX_HEIGHT_PAL - 528)/2, // viYOrigin
640, // viWidth
528, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering
GX_FALSE, // aa
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
{
0, // line n-1
0, // line n-1
21, // line n
22, // line n
21, // line n
0, // line n+1
0 // line n+1
}
};
GXRModeObj TVPal528ProgSoft =
{
6, // viDisplayMode
640, // fbWidth
528, // efbHeight
528, // xfbHeight
(VI_MAX_WIDTH_PAL - 640)/2, // viXOrigin
(VI_MAX_HEIGHT_PAL - 528)/2, // viYOrigin
640, // viWidth
528, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering
GX_FALSE, // aa
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
{
8, // line n-1
8, // line n-1
10, // line n
12, // line n
10, // line n
8, // line n+1
8 // line n+1
}
};
GXRModeObj TVPal528ProgUnknown =
{
6, // viDisplayMode
640, // fbWidth
264, // efbHeight
524, // xfbHeight
(VI_MAX_WIDTH_PAL - 640)/2, // viXOrigin
(VI_MAX_HEIGHT_PAL - 528)/2, // viYOrigin
640, // viWidth
524, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering
GX_TRUE, // aa
// sample points arranged in increasing Y order
{
{3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{3,2},{9,6},{3,10}, // pix 1
{9,2},{3,6},{9,10}, // pix 2
{9,2},{3,6},{9,10} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
{
4, // line n-1
8, // line n-1
12, // line n
16, // line n
12, // line n
8, // line n+1
4 // line n+1
}
};
GXRModeObj TVMpal480Prog =
{
10, // viDisplayMode
640, // fbWidth
480, // efbHeight
480, // xfbHeight
(VI_MAX_WIDTH_NTSC - 640)/2, // viXOrigin
(VI_MAX_HEIGHT_NTSC - 480)/2, // viYOrigin
640, // viWidth
480, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering
GX_FALSE, // aa
// sample points arranged in increasing Y order
{
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
{6,6},{6,6},{6,6}, // pix 1
{6,6},{6,6},{6,6}, // pix 2
{6,6},{6,6},{6,6} // pix 3
},
// vertical filter[7], 1/64 units, 6 bits each
{
0, // line n-1
0, // line n-1
21, // line n
22, // line n
21, // line n
0, // line n+1
0 // line n+1
}
};
static const GXRModeObj *g_vidmodes[] = {
&TVNtsc480Int,
&TVNtsc480IntDf,
&TVNtsc480Prog,
&TVPal528Int,
&TVPal528IntDf,
&TVPal528Prog,
&TVPal528ProgSoft,
&TVPal528ProgUnknown,
&TVMpal480IntDf,
&TVMpal480Prog,
&TVEurgb60Hz480Int,
&TVEurgb60Hz480IntDf,
&TVEurgb60Hz480Prog
};
// Level :
// 0 : If same number of lines and same mode type (interlaced, progressive)
// 1 : If same mode type
// 2 : Always
static void applyVideoPatch(void *dst, u32 len, GXRModeObj *rmode, int level)
{
u32 i;
u32 *bufEnd = (u32 *)((u8 *)dst + (len - sizeof *rmode));
u32 *p = (u32 *)dst;
while (p <= bufEnd)
{
for (i = 0; i < ARRAY_SIZE(g_vidmodes); ++i)
if (memcmp(p, g_vidmodes[i], sizeof *rmode) == 0)
{
// Video mode description found, replace it
GXRModeObj *m = (GXRModeObj *)p;
if (level == 2
|| (((m->viTVMode & 3) == VI_PROGRESSIVE) == ((rmode->viTVMode & 3) == VI_PROGRESSIVE)
&& (level == 1 || m->viHeight == rmode->viHeight)))
memcpy(p, rmode, sizeof *rmode);
p = (u32 *)(m + 1);
break;
}
if (i == ARRAY_SIZE(g_vidmodes))
p++;
}
}
static bool compare_videomodes(GXRModeObj* mode1, GXRModeObj* mode2)
{
return memcmp(mode1, mode2, sizeof *mode1) == 0; // padding seems to always be 0
}
static void patch_videomode(GXRModeObj* mode1, GXRModeObj* mode2)
{
memcpy(mode1, mode2, sizeof *mode1);
}
static GXRModeObj* PAL2NTSC[]={
&TVMpal480IntDf, &TVNtsc480IntDf,
&TVPal264Ds, &TVNtsc240Ds,
&TVPal264DsAa, &TVNtsc240DsAa,
&TVPal264Int, &TVNtsc240Int,
&TVPal264IntAa, &TVNtsc240IntAa,
&TVPal524IntAa, &TVNtsc480IntAa,
&TVPal528Int, &TVNtsc480IntAa,
&TVPal528IntDf, &TVNtsc480IntDf,
&TVPal574IntDfScale, &TVNtsc480IntDf,
&TVEurgb60Hz240Ds, &TVNtsc240Ds,
&TVEurgb60Hz240DsAa, &TVNtsc240DsAa,
&TVEurgb60Hz240Int, &TVNtsc240Int,
&TVEurgb60Hz240IntAa, &TVNtsc240IntAa,
&TVEurgb60Hz480Int, &TVNtsc480IntAa,
&TVEurgb60Hz480IntDf, &TVNtsc480IntDf,
&TVEurgb60Hz480IntAa, &TVNtsc480IntAa,
&TVEurgb60Hz480Prog, &TVNtsc480Prog,
&TVEurgb60Hz480ProgSoft,&TVNtsc480Prog,
&TVEurgb60Hz480ProgAa, &TVNtsc480Prog,
0,0
};
static GXRModeObj* NTSC2PAL[]={
&TVNtsc240Ds, &TVPal264Ds,
&TVNtsc240DsAa, &TVPal264DsAa,
&TVNtsc240Int, &TVPal264Int,
&TVNtsc240IntAa, &TVPal264IntAa,
&TVNtsc480IntDf, &TVPal528IntDf,
&TVNtsc480IntAa, &TVPal524IntAa,
&TVNtsc480Prog, &TVPal528IntDf,
0,0
};
static GXRModeObj* NTSC2PAL60[]={
&TVNtsc240Ds, &TVEurgb60Hz240Ds,
&TVNtsc240DsAa, &TVEurgb60Hz240DsAa,
&TVNtsc240Int, &TVEurgb60Hz240Int,
&TVNtsc240IntAa, &TVEurgb60Hz240IntAa,
&TVNtsc480IntDf, &TVEurgb60Hz480IntDf,
&TVNtsc480IntAa, &TVEurgb60Hz480IntAa,
&TVNtsc480Prog, &TVEurgb60Hz480Prog,
0,0
};
static bool Search_and_patch_Video_Modes(void *Address, u32 Size, GXRModeObj* Table[])
{
u8 *Addr = (u8 *)Address;
bool found = 0;
u32 i;
while(Size >= sizeof(GXRModeObj))
{
for(i = 0; Table[i]; i+=2)
{
if(compare_videomodes(Table[i], (GXRModeObj*)Addr))
{
found = 1;
patch_videomode((GXRModeObj*)Addr, Table[i+1]);
Addr += (sizeof(GXRModeObj)-4);
Size -= (sizeof(GXRModeObj)-4);
break;
}
}
Addr += 4;
Size -= 4;
}
return found;
}
void patchVideoModes(void *dst, u32 len, int vidMode, GXRModeObj *vmode, int patchVidModes)
{
GXRModeObj **table = 0;
if(patchVidModes && vmode != 0)
applyVideoPatch(dst, len, vmode, patchVidModes - 1);
else
{
switch(vidMode)
{
case 0: // default / disc / game
break;
case 1: // SYSTEM
switch(CONF_GetVideo())
{
case CONF_VIDEO_PAL:
table = CONF_GetEuRGB60() > 0 ? NTSC2PAL60 : NTSC2PAL;
break;
case CONF_VIDEO_MPAL:
table = NTSC2PAL;
break;
default:
table = PAL2NTSC;
break;
}
Search_and_patch_Video_Modes(dst, len, table);
break;
case 2: // PAL50
Search_and_patch_Video_Modes(dst, len, NTSC2PAL);
break;
case 3: // PAL60
Search_and_patch_Video_Modes(dst, len, NTSC2PAL60);
break;
case 4: // NTSC
Search_and_patch_Video_Modes(dst, len, PAL2NTSC);
break;
default:
break;
}
}
}

View File

@ -0,0 +1,16 @@
#ifndef _VIDEOPATCH_H_
#define _VIDEOPATCH_H_
#include <gccore.h>
#ifdef __cplusplus
extern "C" {
#endif
void patchVideoModes(void *dst, u32 len, int vidMode, GXRModeObj *vmode, int patchVidModes);
#ifdef __cplusplus
}
#endif
#endif // !defined(_VIDEOPATCH_H_)

View File

@ -0,0 +1,410 @@
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include "gecko.h"
/* Constants */
#define IOCTL_DI_READID 0x70
#define IOCTL_DI_READ 0x71
#define IOCTL_DI_WAITCVRCLOSE 0x79
#define IOCTL_DI_GETCOVER 0x88
#define IOCTL_DI_RESET 0x8A
#define IOCTL_DI_OPENPART 0x8B
#define IOCTL_DI_CLOSEPART 0x8C
#define IOCTL_DI_UNENCREAD 0x8D
#define IOCTL_DI_SEEK 0xAB
#define IOCTL_DI_STOPLASER 0xD2
#define IOCTL_DI_OFFSET 0xD9
#define IOCTL_DI_DISC_BCA 0xDA
#define IOCTL_DI_REQUESTERROR 0xE0
#define IOCTL_DI_STOPMOTOR 0xE3
#define IOCTL_DI_DVDAUDIOBUFFERCFG 0xE4
#define IOCTL_DI_SETWBFSMODE 0xF4
#define IOCTL_DI_SETFRAG 0xF9
#define IOCTL_DI_GETMODE 0xFA
#define IOCTL_DI_HELLO 0xFB
/* Variables */
static u32 inbuf[8] ATTRIBUTE_ALIGN(32);
static u32 outbuf[8] ATTRIBUTE_ALIGN(32);
static const char di_fs[] ATTRIBUTE_ALIGN(32) = "/dev/di";
static s32 di_fd = -1;
s32 WDVD_Init(void)
{
/* Open "/dev/di" */
if (di_fd < 0) {
di_fd = IOS_Open(di_fs, 0);
if (di_fd < 0)
return di_fd;
}
return 0;
}
s32 WDVD_Close(void)
{
/* Close "/dev/di" */
if (di_fd >= 0) {
IOS_Close(di_fd);
di_fd = -1;
}
return 0;
}
s32 WDVD_GetHandle(void)
{
/* Return di handle */
return di_fd;
}
s32 WDVD_Reset(void)
{
memset(inbuf, 0, sizeof(inbuf));
/* Reset drive */
inbuf[0] = IOCTL_DI_RESET << 24;
inbuf[1] = 1;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_RESET, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_ReadDiskId(void *id)
{
memset(inbuf, 0, sizeof(inbuf));
/* Read disc ID */
inbuf[0] = IOCTL_DI_READID << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_READID, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
if (ret == 1)
{
memcpy(id, outbuf, sizeof(dvddiskid));
return 0;
}
return -ret;
}
s32 WDVD_Seek(u64 offset)
{
memset(inbuf, 0, sizeof(inbuf));
/* Drive seek */
inbuf[0] = IOCTL_DI_SEEK << 24;
inbuf[1] = (u32)(offset >> 2);
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_SEEK, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_Offset(u64 offset)
{
//u32 *off = (u32 *)((void *)&offset);
union { u64 off64; u32 off32[2]; } off;
off.off64 = offset;
memset(inbuf, 0, sizeof(inbuf));
/* Set offset */
inbuf[0] = IOCTL_DI_OFFSET << 24;
inbuf[1] = (off.off32[0]) ? 1: 0;
inbuf[2] = (off.off32[1] >> 2);
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_OFFSET, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_StopLaser(void)
{
memset(inbuf, 0, sizeof(inbuf));
/* Stop laser */
inbuf[0] = IOCTL_DI_STOPLASER << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_STOPLASER, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_StopMotor(void)
{
memset(inbuf, 0, sizeof(inbuf));
/* Stop motor */
inbuf[0] = IOCTL_DI_STOPMOTOR << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_STOPMOTOR, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_Eject(void)
{
memset(inbuf, 0, sizeof(inbuf));
/* Stop motor */
inbuf[0] = IOCTL_DI_STOPMOTOR << 24;
/* Eject DVD */
inbuf[1] = 1;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_STOPMOTOR, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_OpenPartition(u64 offset)
{
if (di_fd < 0)
return di_fd;
static u8 Tmd_Buffer[0x4A00] ATTRIBUTE_ALIGN(32);
static ioctlv Vectors[5] ATTRIBUTE_ALIGN(32);
s32 ret;
memset(inbuf, 0, sizeof inbuf);
memset(outbuf, 0, sizeof outbuf);
inbuf[0] = IOCTL_DI_OPENPART << 24;
inbuf[1] = offset >> 2;
Vectors[0].data = inbuf;
Vectors[0].len = 0x20;
Vectors[1].data = 0;
Vectors[1].len = 0;
Vectors[2].data = 0;
Vectors[2].len = 0;
Vectors[3].data = Tmd_Buffer;
Vectors[3].len = 0x49e4;
Vectors[4].data = outbuf;
Vectors[4].len = 0x20;
ret = IOS_Ioctlv(di_fd, IOCTL_DI_OPENPART, 3, 2, (ioctlv *)Vectors);
if (ret < 0)
return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_ClosePartition(void)
{
memset(inbuf, 0, sizeof(inbuf));
/* Close partition */
inbuf[0] = IOCTL_DI_CLOSEPART << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_CLOSEPART, inbuf, sizeof(inbuf), NULL, 0);
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_UnencryptedRead(void *buf, u32 len, u64 offset)
{
memset(inbuf, 0, sizeof(inbuf));
/* Unencrypted read */
inbuf[0] = IOCTL_DI_UNENCREAD << 24;
inbuf[1] = len;
inbuf[2] = (u32)(offset >> 2);
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_UNENCREAD, inbuf, sizeof(inbuf), buf, len);
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_Read(void *buf, u32 len, u64 offset)
{
memset(inbuf, 0, sizeof(inbuf));
/* Disc read */
inbuf[0] = IOCTL_DI_READ << 24;
inbuf[1] = len;
inbuf[2] = (u32)(offset >> 2);
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_READ, inbuf, sizeof(inbuf), buf, len);
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_LowRequestError(u32 *error)
{
memset(inbuf, 0, sizeof(inbuf));
inbuf[0] = IOCTL_DI_REQUESTERROR << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_REQUESTERROR, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
if (ret == 1)
memcpy(error, outbuf, sizeof(u32));
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_WaitForDisc(void)
{
memset(inbuf, 0, sizeof(inbuf));
/* Wait for disc */
inbuf[0] = IOCTL_DI_WAITCVRCLOSE << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_WAITCVRCLOSE, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_GetCoverStatus(u32 *status)
{
memset(inbuf, 0, sizeof(inbuf));
/* Get cover status */
inbuf[0] = IOCTL_DI_GETCOVER << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_GETCOVER, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
if (ret == 1) {
/* Copy cover status */
memcpy(status, outbuf, sizeof(u32));
return 0;
}
return -ret;
}
s32 WDVD_SetUSBMode(u32 mode, const u8 *id, s32 partition)
{
gprintf("WDVD_SetUSBMode, Mode: %i, ID: %s, Partition: %i\n", mode, id, partition);
memset(inbuf, 0, sizeof(inbuf));
/* Set USB mode */
inbuf[0] = IOCTL_DI_SETWBFSMODE << 24;
inbuf[1] = mode;
/* Copy ID */
if(id)
{
memcpy(&inbuf[2], id, 6);
if(partition >= 0)
inbuf[5] = partition;
}
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_SETWBFSMODE, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if(ret < 0)
return ret;
return(ret == 1) ? 0 : -ret;
}
s32 WDVD_Read_Disc_BCA(void *buf)
{
memset(inbuf, 0, sizeof(inbuf));
/* Disc read */
inbuf[0] = IOCTL_DI_DISC_BCA << 24;
//inbuf[1] = 64;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_DISC_BCA, inbuf, sizeof(inbuf), buf, 64);
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
// frag
s32 WDVD_SetFragList(int device, void *fraglist, int size)
{
gprintf("WDVD_SetFragList, Device: %i, Size: %i\n", device, size);
memset(inbuf, 0, sizeof(inbuf));
memset(outbuf, 0, sizeof(outbuf));
/* Set FRAG mode */
inbuf[0] = IOCTL_DI_SETFRAG << 24;
inbuf[1] = device;
inbuf[2] = (u32)fraglist;
inbuf[3] = size;
DCFlushRange(fraglist, size);
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_SETFRAG, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_hello(u32 *status)
{
memset(inbuf, 0, sizeof(inbuf));
inbuf[0] = IOCTL_DI_HELLO << 24;
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_HELLO, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
if (ret == 1)
{
if (status) memcpy(status, outbuf, sizeof(u32));
return 0;
}
return -ret;
}
s32 WDVD_SetStreaming(void)
{
memset(inbuf, 0, sizeof(inbuf));
inbuf[0] = IOCTL_DI_DVDAUDIOBUFFERCFG << 24;
if ((*(u32*)0x80000008)>>24)
{
inbuf[1] = 1;
if(((*(u32*)0x80000008)>>16) & 0xFF)
inbuf[2] = 10;
else
inbuf[2] = 0;
}
else
{
inbuf[1] = 0;
inbuf[2] = 0;
}
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_DVDAUDIOBUFFERCFG, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
if (ret < 0) return ret;
return (ret == 1) ? 0 : -ret;
}
s32 WDVD_NEEK_LoadDisc(u32 id, u32 magic)
{
u32 *vec = (u32*)memalign(32, sizeof(u32) * 2);
vec[0] = id;
vec[1] = magic;
s32 ret = IOS_Ioctl(di_fd, 0x25, vec, sizeof(u32) * 2, NULL, 0);
free(vec);
return ret;
}

View File

@ -0,0 +1,37 @@
#ifndef _WDVD_H_
#define _WDVD_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Prototypes */
s32 WDVD_Init(void);
s32 WDVD_Close(void);
s32 WDVD_GetHandle(void);
s32 WDVD_Reset(void);
s32 WDVD_ReadDiskId(void *);
s32 WDVD_Seek(u64);
s32 WDVD_Offset(u64);
s32 WDVD_StopLaser(void);
s32 WDVD_StopMotor(void);
s32 WDVD_OpenPartition(u64 offset);
s32 WDVD_ClosePartition(void);
s32 WDVD_UnencryptedRead(void *, u32, u64);
s32 WDVD_Read(void *, u32, u64);
s32 WDVD_LowRequestError(u32 *error);
s32 WDVD_WaitForDisc(void);
s32 WDVD_GetCoverStatus(u32 *);
s32 WDVD_SetUSBMode(u32, const u8 *, s32);
s32 WDVD_Eject(void);
s32 WDVD_Read_Disc_BCA(void *);
s32 WDVD_SetFragList(int device, void *fraglist, int size);
s32 WDVD_SetStreaming(void);
s32 WDVD_NEEK_LoadDisc(u32 id, u32 magic);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -0,0 +1,141 @@
#include <gccore.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include "wip.h"
#include "gecko.h"
static WIP_Code * CodeList = NULL;
static u32 CodesCount = 0;
static u32 ProcessedLength = 0;
static u32 Counter = 0;
void do_wip_code(u8 * dst, u32 len)
{
if(!CodeList)
return;
if(Counter < 3)
{
Counter++;
return;
}
u32 i = 0;
s32 n = 0;
s32 offset = 0;
for(i = 0; i < CodesCount; i++)
{
for(n = 0; n < 4; n++)
{
offset = CodeList[i].offset+n-ProcessedLength;
if(offset < 0 || (u32)offset >= len)
continue;
if(dst[offset] == ((u8 *)&CodeList[i].srcaddress)[n])
{
dst[offset] = ((u8 *)&CodeList[i].dstaddress)[n];
gprintf("WIP: %08X Address Patched.\n", CodeList[i].offset + n);
}
else
{
gprintf("WIP: %08X Address does not match with WIP entry.\n", CodeList[i].offset+n);
gprintf("Destination: %02X | Should be: %02X.\n", dst[offset], ((u8 *)&CodeList[i].srcaddress)[n]);
}
}
}
ProcessedLength += len;
Counter++;
}
//! for internal patches only
//! .wip files override internal patches
//! the codelist has to be freed if the set fails
//! if set was successful the codelist will be freed when it's done
bool set_wip_list(WIP_Code * list, int size)
{
if(!CodeList && size > 0)
{
CodeList = list;
CodesCount = size;
return true;
}
return false;
}
void wip_reset_counter()
{
ProcessedLength = 0;
//alternative dols don't need a skip. only main.dol.
Counter = 3;
}
void free_wip()
{
if(CodeList)
free(CodeList);
CodesCount = 0;
ProcessedLength = 0;
}
int load_wip_patches(u8 *dir, u8 *gameid)
{
char filepath[150];
char GameID[8];
memset(GameID, 0, sizeof(GameID));
memcpy(GameID, gameid, 6);
snprintf(filepath, sizeof(filepath), "%s/%s.wip", dir, GameID);
FILE *fp = fopen(filepath, "rb");
if(!fp)
{
memset(GameID, 0, sizeof(GameID));
memcpy(GameID, gameid, 3);
snprintf(filepath, sizeof(filepath), "%s/%s.wip", dir, GameID);
fp = fopen(filepath, "rb");
}
if(!fp)
return -1;
char line[255];
//printf("\nLoading WIP code from %s.\n", filepath);
while(fgets(line, sizeof(line), fp))
{
if(line[0] == '#' || strlen(line) < 26)
continue;
u32 offset = (u32) strtoul(line, NULL, 16);
u32 srcaddress = (u32) strtoul(line+9, NULL, 16);
u32 dstaddress = (u32) strtoul(line+18, NULL, 16);
if(!CodeList)
CodeList = malloc(sizeof(WIP_Code));
WIP_Code *tmp = realloc(CodeList, (CodesCount+1)*sizeof(WIP_Code));
if(!tmp)
{
free(CodeList);
fclose(fp);
return -1;
}
CodeList = tmp;
CodeList[CodesCount].offset = offset;
CodeList[CodesCount].srcaddress = srcaddress;
CodeList[CodesCount].dstaddress = dstaddress;
CodesCount++;
}
fclose(fp);
//printf("\n");
return 0;
}

View File

@ -12,9 +12,11 @@ typedef struct
u32 dstaddress;
} WIP_Code;
u8 set_wip_list(WIP_Code *list, int size);
bool set_wip_list(WIP_Code *list, int size);
void wip_reset_counter();
void free_wip();
void do_wip_code(u8 *dst, u32 len);
int load_wip_patches(u8 *dir, u8 *gameid);
#ifdef __cplusplus
}

View File

@ -1,71 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#ifndef __TYPES_H__
#define __TYPES_H__
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef volatile unsigned char vu8;
typedef volatile unsigned short vu16;
typedef volatile unsigned int vu32;
typedef volatile unsigned long long vu64;
typedef volatile signed char vs8;
typedef volatile signed short vs16;
typedef volatile signed int vs32;
typedef volatile signed long long vs64;
typedef unsigned int size_t;
typedef signed int ssize_t;
#define NULL ((void *)0)
#define ALIGNED(n) __attribute__((aligned(n)))
enum
{
TYPE_WII_DISC = 0,
TYPE_WII_WBFS,
TYPE_WII_WBFS_EXT,
};
enum
{
TYPE_WII_GAME = 0,
TYPE_GC_GAME,
TYPE_CHANNEL,
TYPE_PLUGIN,
TYPE_HOMEBREW,
TYPE_END
};
#define NoGameID(x) (x == TYPE_PLUGIN || x == TYPE_HOMEBREW)
enum
{
IOS_TYPE_D2X = 0,
IOS_TYPE_WANIN,
IOS_TYPE_HERMES,
IOS_TYPE_KWIIRK,
IOS_TYPE_NEEK2O,
IOS_TYPE_NORMAL_IOS,
IOS_TYPE_STUB,
};
#define CustomIOS(x) (x != IOS_TYPE_NORMAL_IOS && x != IOS_TYPE_STUB)
#endif

View File

@ -1,221 +0,0 @@
/*---------------------------------------------------------------------------------------------
* USB Gecko Development Kit - http://www.usbgecko.com
* --------------------------------------------------------------------------------------------
*
*
* usb.c - V1.2 functions for the USB Gecko adapter (www.usbgecko.com).
* Now works for Wii Mode - use WIIMODE define in usb.h to set
* Copyright (c) 2008 - Nuke - <wiinuke@gmail.com>
*
*---------------------------------------------------------------------------------------------*/
#include "types.h"
#include "usb.h"
#ifdef DEBUG
/*---------------------------------------------------------------------------------------------*
Name: usb_sendbyte
Description: Send byte to Gamecube/Wii over EXI memory card port
*----------------------------------------------------------------------------------------------*/
static int __usb_sendbyte (char sendbyte)
{
s32 i;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xB0000000 | (sendbyte<<20);
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0;
if (i&0x04000000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_receivebyte
Description: Receive byte from Gamecube/Wii over EXI memory card port
*----------------------------------------------------------------------------------------------*/
static int __usb_receivebyte (char *receivebyte)
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xA0000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0;
if (i&0x08000000){
*receivebyte=(i>>16)&0xff;
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_checksendstatus
Description: Chesk the FIFO is ready to send
*----------------------------------------------------------------------------------------------*/
static int __usb_checksendstatus()
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xC0000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0x0;
if (i&0x04000000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_checkreceivestatus
Description: Check the FIFO is ready to receive
*----------------------------------------------------------------------------------------------*/
static int __usb_checkreceivestatus()
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xD0000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0x0;
if (i&0x04000000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_sendbuffer
Description: Simple buffer send routine
*----------------------------------------------------------------------------------------------*/
void usb_sendbuffer (const void *buffer, int size)
{
char *sendbyte = (char*) buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
returnvalue = __usb_sendbyte(*sendbyte);
if(returnvalue) {
sendbyte++;
bytesleft--;
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_receivebuffer
Description: Simple buffer receive routine
*----------------------------------------------------------------------------------------------*/
void usb_receivebuffer (void *buffer, int size)
{
char *receivebyte = (char*)buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
returnvalue = __usb_receivebyte(receivebyte);
if(returnvalue) {
receivebyte++;
bytesleft--;
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_sendbuffersafe
Description: Simple buffer send routine with fifo check (use for large transfers)
*----------------------------------------------------------------------------------------------*/
void usb_sendbuffersafe (const void *buffer, int size)
{
char *sendbyte = (char*) buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
if(__usb_checksendstatus()){
returnvalue = __usb_sendbyte(*sendbyte);
if(returnvalue) {
sendbyte++;
bytesleft--;
}
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_receivebuffersafe
Description: Simple buffer receive routine with fifo check (use for large transfers)
*----------------------------------------------------------------------------------------------*/
void usb_receivebuffersafe (void *buffer, int size)
{
char *receivebyte = (char*)buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
if(__usb_checkreceivestatus()){
returnvalue = __usb_receivebyte(receivebyte);
if(returnvalue) {
receivebyte++;
bytesleft--;
}
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_checkgecko
Description: Chesk the Gecko is connected
*----------------------------------------------------------------------------------------------*/
int usb_checkgecko()
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0x90000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0x0;
if (i==0x04700000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_flush
Description: Flushes the FIFO, Use at the start of your program to avoid trash
*----------------------------------------------------------------------------------------------*/
void usb_flush()
{
char tempbyte;
while (__usb_receivebyte(&tempbyte));
}
#endif

View File

@ -1,41 +0,0 @@
/*---------------------------------------------------------------------------------------------
* USB Gecko Development Kit - http://www.usbgecko.com
* --------------------------------------------------------------------------------------------
*
*
* usb.h - functions for the USB Gecko adapter (www.usbgecko.com).
*
* Copyright (c) 2008 - Nuke - <wiinuke@gmail.com>
*
*---------------------------------------------------------------------------------------------*/
#ifndef __USB_H__
#define __USB_H__
#define exi_chan0sr *(volatile unsigned int*) 0xCD006800 // Channel 0 Status Register
#define exi_chan1sr *(volatile unsigned int*) 0xCD006814 // Channel 1 Status Register
#define exi_chan2sr *(volatile unsigned int*) 0xCD006828 // Channel 2 Status Register
#define exi_chan0cr *(volatile unsigned int*) 0xCD00680c // Channel 0 Control Register
#define exi_chan1cr *(volatile unsigned int*) 0xCD006820 // Channel 1 Control Register
#define exi_chan2cr *(volatile unsigned int*) 0xCD006834 // Channel 2 Control Register
#define exi_chan0data *(volatile unsigned int*) 0xCD006810 // Channel 0 Immediate Data
#define exi_chan1data *(volatile unsigned int*) 0xCD006824 // Channel 1 Immediate Data
#define exi_chan2data *(volatile unsigned int*) 0xCD006838 // Channel 2 Immediate Data
#define exi_chan0dmasta *(volatile unsigned int*) 0xCD006804 // Channel 0 DMA Start address
#define exi_chan1dmasta *(volatile unsigned int*) 0xCD006818 // Channel 1 DMA Start address
#define exi_chan2dmasta *(volatile unsigned int*) 0xCD00682c // Channel 2 DMA Start address
#define exi_chan0dmalen *(volatile unsigned int*) 0xCD006808 // Channel 0 DMA Length
#define exi_chan1dmalen *(volatile unsigned int*) 0xCD00681c // Channel 1 DMA Length
#define exi_chan2dmalen *(volatile unsigned int*) 0xCD006830 // Channel 2 DMA Length
#ifdef DEBUG
// Function prototypes
void usb_flush();
int usb_checkgecko();
void usb_sendbuffer (const void *buffer, int size);
void usb_receivebuffer (void *buffer, int size);
void usb_sendbuffersafe (const void *buffer, int size);
void usb_receivebuffersafe (void *buffer, int size);
#endif
#endif // __USB_H__

View File

@ -1,92 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
/* This code comes from HBC's stub which was based on geckoloader and the Twilight Hack code */
/* Some of these routines are from public domain sources */
// Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
// Copyright 2008-2009 Andre Heider <dhewg@wiibrew.org>
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#include "types.h"
#include "utils.h"
#include "cache.h"
#ifdef __cplusplus
extern "C"
{
#endif
void *memset(void *ptr, int c, int size) {
char* ptr2 = ptr;
while(size--) *ptr2++ = (char)c;
return ptr;
}
void *memcpy(void *ptr, const void *src, int size) {
char* ptr2 = ptr;
const char* src2 = src;
while(size--) *ptr2++ = *src2++;
return ptr;
}
int strlen(const char *ptr) {
int i=0;
while(*ptr++) i++;
return i;
}
int memcmp(const void *s1, const void *s2, size_t n)
{
const unsigned char *us1 = (const unsigned char *) s1;
const unsigned char *us2 = (const unsigned char *) s2;
while (n-- != 0) {
if (*us1 != *us2)
return (*us1 < *us2) ? -1 : +1;
us1++;
us2++;
}
return 0;
}
void memset32(u32 *addr, u32 data, u32 count)
{
int sc = count;
void *sa = addr;
while(count--)
*addr++ = data;
sync_after_write(sa, 4*sc);
}
#ifdef __cplusplus
}
#endif
// Timebase frequency is core frequency / 8. Ignore roundoff, this
// doesn't have to be very accurate.
#define TICKS_PER_USEC (729/8)
static u32 mftb(void)
{
u32 x;
asm volatile("mftb %0" : "=r"(x));
return x;
}
static void __delay(u32 ticks)
{
u32 start = mftb();
while (mftb() - start < ticks)
;
}
void udelay(u32 us)
{
__delay(TICKS_PER_USEC * us);
}

View File

@ -1,31 +0,0 @@
/*
TinyLoad - a simple region free (original) game launcher in 4k
# 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
*/
// Copyright 2008-2009 Hector Martin <marcan@marcansoft.com>
#ifndef __UTILS_H__
#define __UTILS_H__
#include "types.h"
#ifdef __cplusplus
extern "C"
{
#endif
void *memset(void *,int,int);
void memset32(u32 *addr, u32 data, u32 count) __attribute__ ((externally_visible));
void *memcpy(void *ptr, const void *src, int size);
int memcmp(const void *s1, const void *s2, size_t n);
int strlen(const char *ptr);
void udelay(u32 us);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,12 +0,0 @@
#ifndef VIDEO_H_
#define VIDEO_H_
void video_init(void);
void video_setblack(void);
void prog(int p);
void prog10(void);
void setprog(int p);
#endif

View File

@ -1,66 +0,0 @@
#include "utils.h"
#include "debug.h"
#include "wip.h"
WIP_Code *CodeList;
u32 CodesCount;
u32 ProcessedLength;
u32 Counter;
void do_wip_code(u8 * dst, u32 len)
{
if(Counter < 3)
{
Counter++;
return;
}
u32 i = 0;
s32 n = 0;
s32 offset = 0;
for(i = 0; i < CodesCount; i++)
{
for(n = 0; n < 4; n++)
{
offset = CodeList[i].offset+n-ProcessedLength;
if(offset < 0 || (u32)offset >= len)
continue;
if(dst[offset] == ((u8 *)&CodeList[i].srcaddress)[n])
{
dst[offset] = ((u8 *)&CodeList[i].dstaddress)[n];
debug_string("Address patched:"); debug_uint(CodeList[i].offset+n); debug_string("\n");
//printf("WIP: %08X Address Patched.\n", CodeList[i].offset + n);
}
else
{
debug_string("Address NOT patched:"); debug_uint(CodeList[i].offset+n); debug_string("\n");
//printf("WIP: %08X Address does not match with WIP entry.\n", CodeList[i].offset+n);
//printf("Destination: %02X | Should be: %02X.\n", dst[offset], ((u8 *)&CodeList[i].srcaddress)[n]);
}
}
}
ProcessedLength += len;
Counter++;
}
//! for internal patches only
//! .wip files override internal patches
//! the codelist has to be freed if the set fails
//! if set was successful the codelist will be freed when it's done
u8 set_wip_list(WIP_Code *list, int size)
{
CodeList = list;
CodesCount = size;
ProcessedLength = 0;
Counter = 0;
return 1;
}
void free_wip()
{
CodesCount = 0;
ProcessedLength = 0;
}

View File

@ -36,7 +36,7 @@ typedef void (*entrypoint) (void);
extern "C" { void __exception_closeall(); }
/* External WiiFlow Game Booter */
#define BOOTER_ADDR ((u8 *)0x80F00000)
#define BOOTER_ADDR ((u8 *)0x80B00000)
static the_CFG *BooterConfig = (the_CFG*)0x93100000;
static entrypoint exeEntryPoint = (entrypoint)BOOTER_ADDR;
@ -76,7 +76,7 @@ void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 pat
normalCFG.gameconfsize = gameconfsize;
normalCFG.BootType = BootType;
ShutdownBeforeExit(true);
ShutdownBeforeExit();
/* Copy CFG into new memory region */
memcpy(BooterConfig, &normalCFG, sizeof(the_CFG));
DCFlushRange(BooterConfig, sizeof(the_CFG));
@ -84,8 +84,8 @@ void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 pat
memcpy(BOOTER_ADDR, booter, booter_size);
DCFlushRange(BOOTER_ADDR, booter_size);
/* Shutdown IOS subsystems */
u32 level = IRQ_Disable();
__IOS_ShutdownSubsystems();
u32 level = IRQ_Disable();
__lwp_thread_closeall();
__exception_closeall();
/* Boot it */
@ -114,9 +114,9 @@ void ExternalBooter_ChannelSetup(u64 title)
memcpy(&normalCFG.title, &title, sizeof(u64));
}
void ShutdownBeforeExit(bool KeepPatches)
void ShutdownBeforeExit()
{
DeviceHandle.UnMountAll();
Nand::Instance()->DeInit_ISFS(KeepPatches);
Nand::Instance()->DeInit_ISFS();
WDVD_Close();
}

View File

@ -32,6 +32,6 @@ void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 pat
int aspectRatio, u32 returnTo, u8 BootType);
void ExternalBooter_ChannelSetup(u64 title);
void ExternalBooter_WiiGameSetup(bool wbfs, bool dvd, const char *ID);
void ShutdownBeforeExit(bool BootGame = false);
void ShutdownBeforeExit();
#endif

View File

@ -40,6 +40,7 @@
#include "gecko/gecko.h"
#include "loader/alt_ios.h"
#include "loader/cios.h"
#include "loader/nk.h"
#include "loader/sys.h"
#include "loader/wbfs.h"
#include "memory/memory.h"
@ -1052,10 +1053,8 @@ s32 Nand::Do_Region_Change(string id)
extern "C" { extern s32 MagicPatches(s32); }
void Nand::Init_ISFS()
void Nand::Enable_ISFS_Patches(void)
{
//gprintf("Init ISFS\n");
ISFS_Initialize();
if(AHBRPOT_Patched())
{
// Disable memory protection
@ -1068,22 +1067,33 @@ void Nand::Init_ISFS()
}
}
void Nand::DeInit_ISFS(bool KeepPatches)
void Nand::Disable_ISFS_Patches(void)
{
//gprintf("Deinit ISFS\n");
if(AHBRPOT_Patched())
{
// Disable memory protection
write16(MEM_PROT, 0);
if(!KeepPatches)
{
// Do patches
MagicPatches(0);
// Enable memory protection
write16(MEM_PROT, 1);
}
}
void Nand::Init_ISFS()
{
//gprintf("Init ISFS\n");
if(IOS_GetVersion() == 58 && !neek2o())
Enable_ISFS_Patches();
ISFS_Initialize();
}
void Nand::DeInit_ISFS()
{
//gprintf("Deinit ISFS\n");
ISFS_Deinitialize();
if(IOS_GetVersion() == 58 && !neek2o())
Disable_ISFS_Patches();
}
/* Thanks to postloader for that patch */
@ -1112,6 +1122,18 @@ void Nand::PatchAHB()
}
}
void Nand::Patch_AHB()
{
if(AHBRPOT_Patched())
{
// Disable memory protection
write16(MEM_PROT, 0);
// Do patches
PatchAHB();
// Enable memory protection
write16(MEM_PROT, 1);
}
}
/*
part of miniunz.c

View File

@ -68,8 +68,9 @@ public:
void Set_RCMode(bool rcmode) { FullMode = rcmode ? 0x40 : 0; };
void Set_SSMode(bool ssmode) { FullMode = ssmode ? 0x60 : 0; };
void Patch_AHB();
void Init_ISFS();
void DeInit_ISFS(bool KeepPatches = false);
void DeInit_ISFS();
const char * Get_NandPath(void) { return NandPath; };
u32 Get_Partition(void) { return Partition; };
@ -96,7 +97,11 @@ private:
s32 Nand_Unmount(NandDevice *Device);
s32 Nand_Enable(NandDevice *Device);
s32 Nand_Disable(void);
void PatchAHB(void);
void Enable_ISFS_Patches(void);
void Disable_ISFS_Patches(void);
void __Dec_Enc_TB(void);
void __configshifttxt(char *str);
void __GetNameList(const char *source, namelist **entries, int *count);

View File

@ -83,6 +83,7 @@ bool loadIOS(int ios, bool MountDevices)
WDVD_Close();
Close_Inputs();
gprintf("Reloading into IOS %i from %i...\n", ios, CurIOS);
Nand::Instance()->Patch_AHB(); //No AHBPROT for the next IOS
ShutdownBeforeExit();
ret = IOS_ReloadIOS(ios) == 0;
Nand::Instance()->Init_ISFS();

View File

@ -55,28 +55,21 @@ extern const u32 axnextframehooks[4];
extern const u32 wpadbuttonsdownhooks[4];
extern const u32 wpadbuttonsdown2hooks[4];
int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
int app_gameconfig_load(const char *discid, u8 *tempgameconf, u32 tempgameconfsize)
{
gameconfsize = 0;
if (gameconf == NULL)
{
gameconf = malloc(65536);
gameconf = (u32*) MEM2_alloc(65536);
if (gameconf == NULL)
return -1;
}
if (gameconfig == NULL || tempgameconfsize == 0)
return -2;
u8 *tempgameconf = (u8 *)gameconfig;
u32 ret;
s32 gameidmatch, maxgameidmatch = -1, maxgameidmatch2 = -1;
u32 i, numnonascii, parsebufpos;
u32 codeaddr, codeval, codeaddr2, codeval2, codeoffset;
u32 temp, tempoffset = 0;
char parsebuffer[18];
// Remove non-ASCII characters
numnonascii = 0;
for (i = 0; i < tempgameconfsize; i++)
@ -99,9 +92,11 @@ int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
maxgameidmatch2 = -1;
while (maxgameidmatch != maxgameidmatch2)
{
while (i != tempgameconfsize && tempgameconf[i] != ':') i++;
while (i != tempgameconfsize && tempgameconf[i] != ':')
i++;
if (i == tempgameconfsize) break;
while ((tempgameconf[i] != 10 && tempgameconf[i] != 13) && (i != 0)) i--;
while ((tempgameconf[i] != 10 && tempgameconf[i] != 13) && (i != 0))
i--;
if (i != 0) i++;
parsebufpos = 0;
gameidmatch = 0;
@ -118,8 +113,7 @@ int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
parsebuffer[parsebufpos++] = tempgameconf[i++];
else if (tempgameconf[i] == ' ')
break;
else
i++;
else i++;
if (parsebufpos == 8) break;
}
parsebuffer[parsebufpos] = 0;
@ -128,30 +122,35 @@ int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
gameidmatch = 0;
goto idmatch;
}
if (strncmp((char *) discid, parsebuffer, strlen(parsebuffer)) == 0)
if (strncasecmp(discid, parsebuffer, strlen(parsebuffer)) == 0)
{
gameidmatch += strlen(parsebuffer);
idmatch:
if (gameidmatch > maxgameidmatch2)
idmatch: if (gameidmatch > maxgameidmatch2)
{
maxgameidmatch2 = gameidmatch;
}
while ((i != tempgameconfsize) && (tempgameconf[i] != 10 && tempgameconf[i] != 13)) i++;
}
while ((i != tempgameconfsize) && (tempgameconf[i] != 10 && tempgameconf[i] != 13))
i++;
}
while (i != tempgameconfsize && tempgameconf[i] != ':')
{
parsebufpos = 0;
while ((i != tempgameconfsize) && (tempgameconf[i] != 10 && tempgameconf[i] != 13))
{
if (tempgameconf[i] != 0 && tempgameconf[i] != ' ' && tempgameconf[i] != '(' && tempgameconf[i] != ':')
if (tempgameconf[i] != 0 && tempgameconf[i] != ' ' && tempgameconf[i] != '(' && tempgameconf[i]
!= ':')
parsebuffer[parsebufpos++] = tempgameconf[i++];
else if (tempgameconf[i] == ' ' || tempgameconf[i] == '(' || tempgameconf[i] == ':')
break;
else
i++;
else i++;
if (parsebufpos == 17) break;
}
parsebuffer[parsebufpos] = 0;
if (strncasecmp("codeliststart", parsebuffer, strlen(parsebuffer)) == 0 && strlen(parsebuffer) == 13)
//if (!autobootcheck)
{
if (strncasecmp("codeliststart", parsebuffer, strlen(parsebuffer)) == 0 && strlen(parsebuffer)
== 13)
{
sscanf((char *) (tempgameconf + i), " = %x", (unsigned int *) &codelist);
}
@ -177,7 +176,8 @@ int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
}
if (strncasecmp("pokeifequal", parsebuffer, strlen(parsebuffer)) == 0 && strlen(parsebuffer) == 11)
{
ret = sscanf((char *)(tempgameconf + i), "( %x , %x , %x , %x", &codeaddr, &codeval, &codeaddr2, &codeval2);
ret = sscanf((char *) (tempgameconf + i), "( %x , %x , %x , %x", &codeaddr, &codeval,
&codeaddr2, &codeval2);
if (ret == 4)
{
*(gameconf + (gameconfsize / 4)) = 0;
@ -193,7 +193,8 @@ int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
DCFlushRange((void *) (gameconf + (gameconfsize / 4) - 5), 20);
}
}
if (strncasecmp("searchandpoke", parsebuffer, strlen(parsebuffer)) == 0 && strlen(parsebuffer) == 13)
if (strncasecmp("searchandpoke", parsebuffer, strlen(parsebuffer)) == 0 && strlen(parsebuffer)
== 13)
{
ret = sscanf((char *) (tempgameconf + i), "( %x%n", &codeval, &tempoffset);
if (ret == 1)
@ -209,7 +210,8 @@ int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
ret = sscanf((char *) (tempgameconf + i), " %x%n", &codeval, &tempoffset);
}
*(gameconf + (gameconfsize / 4) - temp - 1) = temp;
ret = sscanf((char *)(tempgameconf + i), " , %x , %x , %x , %x", &codeaddr, &codeaddr2, &codeoffset, &codeval2);
ret = sscanf((char *) (tempgameconf + i), " , %x , %x , %x , %x", &codeaddr, &codeaddr2,
&codeoffset, &codeval2);
if (ret == 4)
{
*(gameconf + (gameconfsize / 4)) = codeaddr;
@ -222,20 +224,22 @@ int app_gameconfig_load(u8 *discid, const u8 *gameconfig, u32 tempgameconfsize)
gameconfsize += 4;
DCFlushRange((void *) (gameconf + (gameconfsize / 4) - temp - 5), temp * 4 + 20);
}
else
gameconfsize -= temp * 4 + 4;
else gameconfsize -= temp * 4 + 4;
}
}
}
if (tempgameconf[i] != ':')
{
while ((i != tempgameconfsize) && (tempgameconf[i] != 10 && tempgameconf[i] != 13)) i++;
while ((i != tempgameconfsize) && (tempgameconf[i] != 10 && tempgameconf[i] != 13))
i++;
if (i != tempgameconfsize) i++;
}
}
if (i != tempgameconfsize) while ((tempgameconf[i] != 10 && tempgameconf[i] != 13) && (i != 0)) i--;
if (i != tempgameconfsize) while ((tempgameconf[i] != 10 && tempgameconf[i] != 13) && (i != 0))
i--;
}
}
free(tempgameconf);
return 0;
}
@ -260,15 +264,6 @@ int ocarina_load_code(const u8 *cheat, u32 cheatSize)
code_size = 0;
return 0;
}
if (code_size > (u32)codelistend - (u32)codelist)
{
gprintf("Ocarina: Too many codes found\n");
code_buf = NULL;
code_size = 0;
return 0;
}
//gprintf("Ocarina: Codes found.\n");
DCFlushRange(code_buf, code_size);
return code_size;

View File

@ -30,7 +30,7 @@ extern u8 debuggerselect;
#define MAX_GCT_SIZE 2056
int app_gameconfig_load(u8 *id, const u8 *gameconfig, u32 gameconfigsize);
int app_gameconfig_load(const char *discid, u8 *tempgameconf, u32 tempgameconfsize);
int ocarina_load_code(const u8 *cheat, u32 cheatSize);
int ocarina_do_code();

View File

@ -1401,16 +1401,16 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
Sys_Exit();
WBFS_Close();
}
if(gameconfig.get() != NULL)
{
app_gameconfig_load((u8*)&id, gameconfig.get(), gameconfigSize);
gameconfig.release();
}
if(cheatFile.get() != NULL)
{
ocarina_load_code(cheatFile.get(), cheatSize);
cheatFile.release();
}
if(gameconfig.get() != NULL)
{
app_gameconfig_load(id.c_str(), gameconfig.get(), gameconfigSize);
gameconfig.release();
}
ExternalBooter_WiiGameSetup(wbfs_partition, dvd, id.c_str());
WiiFlow_ExternalBooter(videoMode, vipatch, countryPatch, patchVidMode, aspectRatio, returnTo, TYPE_WII_GAME);
}