From c152f5c3d4433c7fef40b8bebb4d183d81502a20 Mon Sep 17 00:00:00 2001 From: dimok321 <15055714+dimok789@users.noreply.github.com> Date: Sun, 3 May 2009 18:53:31 +0000 Subject: [PATCH] *Added Standard IOS option to global settings. This decides with what IOS the Loader is gonna boot next. --- Makefile | 150 + gui.pnproj | 1 + gui.pnps | 1 + source/FreeTypeGX.cpp | 718 +++ source/FreeTypeGX.h | 286 ++ source/apploader.c | 327 ++ source/apploader.h | 10 + source/audio.cpp | 35 + source/audio.h | 15 + source/cfg.c | 1065 +++++ source/cfg.h | 261 ++ source/disc.c | 310 ++ source/disc.h | 58 + source/dns.c | 122 + source/dns.h | 23 + source/dvd_broadway.c | 612 +++ source/dvd_broadway.h | 53 + source/filelist.h | 212 + source/fonts/font.ttf | Bin 0 -> 48364 bytes source/fst.c | 115 + source/fst.h | 27 + source/fwrite_patch.h | 15 + source/geckomenu.h | 60 + source/http.c | 234 + source/http.h | 38 + source/images/background.png | Bin 0 -> 51389 bytes source/images/battery.png | Bin 0 -> 118 bytes source/images/battery_bar.png | Bin 0 -> 225 bytes source/images/battery_red.png | Bin 0 -> 225 bytes source/images/bg_options.png | Bin 0 -> 1765 bytes source/images/bg_options_entry.png | Bin 0 -> 1146 bytes source/images/bg_options_settings.png | Bin 0 -> 9572 bytes source/images/button_dialogue_box.png | Bin 0 -> 2255 bytes source/images/button_install.png | Bin 0 -> 2173 bytes source/images/button_install_over.png | Bin 0 -> 2971 bytes source/images/credits_bg.png | Bin 0 -> 60848 bytes source/images/credits_button.png | Bin 0 -> 2897 bytes source/images/credits_button_over.png | Bin 0 -> 5039 bytes source/images/dialogue_box.png | Bin 0 -> 3834 bytes source/images/dialogue_box_install.png | Bin 0 -> 3397 bytes source/images/dialogue_box_startgame.png | Bin 0 -> 19284 bytes source/images/keyboard_key.png | Bin 0 -> 653 bytes source/images/keyboard_key_over.png | Bin 0 -> 907 bytes source/images/keyboard_largekey.png | Bin 0 -> 1017 bytes source/images/keyboard_largekey_over.png | Bin 0 -> 1005 bytes source/images/keyboard_mediumkey.png | Bin 0 -> 961 bytes source/images/keyboard_mediumkey_over.png | Bin 0 -> 952 bytes source/images/keyboard_textbox.png | Bin 0 -> 3597 bytes source/images/little_star.png | Bin 0 -> 11046 bytes source/images/menu_button.png | Bin 0 -> 4231 bytes source/images/menu_button_over.png | Bin 0 -> 7080 bytes source/images/nocover.png | Bin 0 -> 33220 bytes source/images/nodisc.png | Bin 0 -> 24745 bytes source/images/player1_grab.png | Bin 0 -> 1995 bytes source/images/player1_point.png | Bin 0 -> 2044 bytes source/images/player2_grab.png | Bin 0 -> 2077 bytes source/images/player2_point.png | Bin 0 -> 2128 bytes source/images/player3_grab.png | Bin 0 -> 2102 bytes source/images/player3_point.png | Bin 0 -> 2154 bytes source/images/player4_grab.png | Bin 0 -> 2045 bytes source/images/player4_point.png | Bin 0 -> 2079 bytes source/images/progressbar.png | Bin 0 -> 241 bytes source/images/progressbar_empty.png | Bin 0 -> 224 bytes source/images/progressbar_outline.png | Bin 0 -> 1286 bytes source/images/scrollbar.png | Bin 0 -> 441 bytes source/images/scrollbar_arrowdown.png | Bin 0 -> 1091 bytes source/images/scrollbar_arrowup.png | Bin 0 -> 1025 bytes source/images/scrollbar_box.png | Bin 0 -> 945 bytes source/images/sdcard.png | Bin 0 -> 1686 bytes source/images/settings_background.png | Bin 0 -> 12068 bytes source/images/settings_button.png | Bin 0 -> 4435 bytes source/images/settings_button_over.png | Bin 0 -> 7553 bytes source/images/settings_menu_button.png | Bin 0 -> 1919 bytes source/images/startgame_arrow_left.png | Bin 0 -> 1385 bytes source/images/startgame_arrow_right.png | Bin 0 -> 1381 bytes source/images/tooltip.png | Bin 0 -> 1289 bytes source/images/tooltip_large.png | Bin 0 -> 1608 bytes source/images/tooltip_medium.png | Bin 0 -> 1441 bytes source/images/wbackground.png | Bin 0 -> 43881 bytes source/images/wdialogue_box_startgame.png | Bin 0 -> 19167 bytes source/images/wiimote_poweroff.png | Bin 0 -> 2013 bytes source/images/wiimote_poweroff_over.png | Bin 0 -> 2927 bytes source/input.cpp | 115 + source/input.h | 23 + source/kenobiwii.h | 264 ++ source/libwbfs/libwbfs.c | 618 +++ source/libwbfs/libwbfs.h | 223 + source/libwbfs/libwbfs_os.h | 33 + source/libwbfs/rijndael.c | 398 ++ source/libwbfs/wiidisc.c | 337 ++ source/libwbfs/wiidisc.h | 67 + source/libwiigui/gui.h | 839 ++++ source/libwiigui/gui_button.cpp | 355 ++ source/libwiigui/gui_customoptionbrowser.cpp | 531 +++ source/libwiigui/gui_customoptionbrowser.h | 85 + source/libwiigui/gui_element.cpp | 577 +++ source/libwiigui/gui_gamebrowser.cpp | 615 +++ source/libwiigui/gui_gamebrowser.h | 88 + source/libwiigui/gui_image.cpp | 239 + source/libwiigui/gui_imagedata.cpp | 171 + source/libwiigui/gui_keyboard.cpp | 330 ++ source/libwiigui/gui_optionbrowser.cpp | 653 +++ source/libwiigui/gui_sound.cpp | 153 + source/libwiigui/gui_text.cpp | 234 + source/libwiigui/gui_trigger.cpp | 255 ++ source/libwiigui/gui_window.cpp | 405 ++ source/main.cpp | 149 + source/main.h | 21 + source/menu.cpp | 4080 ++++++++++++++++++ source/menu.h | 30 + source/oggplayer.c | 350 ++ source/oggplayer.h | 170 + source/partition.c | 51 + source/partition.h | 42 + source/patchcode.c | 359 ++ source/patchcode.h | 46 + source/patchhook.S | 508 +++ source/ppc.h | 83 + source/sdhc.c | 159 + source/sdhc.h | 22 + source/sounds/bg_music.ogg | Bin 0 -> 223108 bytes source/sounds/button_click.pcm | Bin 0 -> 7204 bytes source/sounds/button_click2.pcm | Bin 0 -> 152064 bytes source/sounds/button_over.pcm | Bin 0 -> 32256 bytes source/sounds/credits_music.ogg | Bin 0 -> 96468 bytes source/sys.c | 91 + source/sys.h | 20 + source/usbstorage.c | 186 + source/usbstorage.h | 21 + source/utils.c | 8 + source/utils.h | 15 + source/video.cpp | 327 ++ source/video.h | 24 + source/video2.c | 136 + source/video2.h | 27 + source/wbfs.c | 531 +++ source/wbfs.h | 43 + source/wdvd.c | 338 ++ source/wdvd.h | 35 + source/wpad.c | 71 + source/wpad.h | 23 + 141 files changed, 20322 insertions(+) create mode 100644 Makefile create mode 100644 gui.pnproj create mode 100644 gui.pnps create mode 100644 source/FreeTypeGX.cpp create mode 100644 source/FreeTypeGX.h create mode 100644 source/apploader.c create mode 100644 source/apploader.h create mode 100644 source/audio.cpp create mode 100644 source/audio.h create mode 100644 source/cfg.c create mode 100644 source/cfg.h create mode 100644 source/disc.c create mode 100644 source/disc.h create mode 100644 source/dns.c create mode 100644 source/dns.h create mode 100644 source/dvd_broadway.c create mode 100644 source/dvd_broadway.h create mode 100644 source/filelist.h create mode 100644 source/fonts/font.ttf create mode 100644 source/fst.c create mode 100644 source/fst.h create mode 100644 source/fwrite_patch.h create mode 100644 source/geckomenu.h create mode 100644 source/http.c create mode 100644 source/http.h create mode 100644 source/images/background.png create mode 100644 source/images/battery.png create mode 100644 source/images/battery_bar.png create mode 100644 source/images/battery_red.png create mode 100644 source/images/bg_options.png create mode 100644 source/images/bg_options_entry.png create mode 100644 source/images/bg_options_settings.png create mode 100644 source/images/button_dialogue_box.png create mode 100644 source/images/button_install.png create mode 100644 source/images/button_install_over.png create mode 100644 source/images/credits_bg.png create mode 100644 source/images/credits_button.png create mode 100644 source/images/credits_button_over.png create mode 100644 source/images/dialogue_box.png create mode 100644 source/images/dialogue_box_install.png create mode 100644 source/images/dialogue_box_startgame.png create mode 100644 source/images/keyboard_key.png create mode 100644 source/images/keyboard_key_over.png create mode 100644 source/images/keyboard_largekey.png create mode 100644 source/images/keyboard_largekey_over.png create mode 100644 source/images/keyboard_mediumkey.png create mode 100644 source/images/keyboard_mediumkey_over.png create mode 100644 source/images/keyboard_textbox.png create mode 100644 source/images/little_star.png create mode 100644 source/images/menu_button.png create mode 100644 source/images/menu_button_over.png create mode 100644 source/images/nocover.png create mode 100644 source/images/nodisc.png create mode 100644 source/images/player1_grab.png create mode 100644 source/images/player1_point.png create mode 100644 source/images/player2_grab.png create mode 100644 source/images/player2_point.png create mode 100644 source/images/player3_grab.png create mode 100644 source/images/player3_point.png create mode 100644 source/images/player4_grab.png create mode 100644 source/images/player4_point.png create mode 100644 source/images/progressbar.png create mode 100644 source/images/progressbar_empty.png create mode 100644 source/images/progressbar_outline.png create mode 100644 source/images/scrollbar.png create mode 100644 source/images/scrollbar_arrowdown.png create mode 100644 source/images/scrollbar_arrowup.png create mode 100644 source/images/scrollbar_box.png create mode 100644 source/images/sdcard.png create mode 100644 source/images/settings_background.png create mode 100644 source/images/settings_button.png create mode 100644 source/images/settings_button_over.png create mode 100644 source/images/settings_menu_button.png create mode 100644 source/images/startgame_arrow_left.png create mode 100644 source/images/startgame_arrow_right.png create mode 100644 source/images/tooltip.png create mode 100644 source/images/tooltip_large.png create mode 100644 source/images/tooltip_medium.png create mode 100644 source/images/wbackground.png create mode 100644 source/images/wdialogue_box_startgame.png create mode 100644 source/images/wiimote_poweroff.png create mode 100644 source/images/wiimote_poweroff_over.png create mode 100644 source/input.cpp create mode 100644 source/input.h create mode 100644 source/kenobiwii.h create mode 100644 source/libwbfs/libwbfs.c create mode 100644 source/libwbfs/libwbfs.h create mode 100644 source/libwbfs/libwbfs_os.h create mode 100644 source/libwbfs/rijndael.c create mode 100644 source/libwbfs/wiidisc.c create mode 100644 source/libwbfs/wiidisc.h create mode 100644 source/libwiigui/gui.h create mode 100644 source/libwiigui/gui_button.cpp create mode 100644 source/libwiigui/gui_customoptionbrowser.cpp create mode 100644 source/libwiigui/gui_customoptionbrowser.h create mode 100644 source/libwiigui/gui_element.cpp create mode 100644 source/libwiigui/gui_gamebrowser.cpp create mode 100644 source/libwiigui/gui_gamebrowser.h create mode 100644 source/libwiigui/gui_image.cpp create mode 100644 source/libwiigui/gui_imagedata.cpp create mode 100644 source/libwiigui/gui_keyboard.cpp create mode 100644 source/libwiigui/gui_optionbrowser.cpp create mode 100644 source/libwiigui/gui_sound.cpp create mode 100644 source/libwiigui/gui_text.cpp create mode 100644 source/libwiigui/gui_trigger.cpp create mode 100644 source/libwiigui/gui_window.cpp create mode 100644 source/main.cpp create mode 100644 source/main.h create mode 100644 source/menu.cpp create mode 100644 source/menu.h create mode 100644 source/oggplayer.c create mode 100644 source/oggplayer.h create mode 100644 source/partition.c create mode 100644 source/partition.h create mode 100644 source/patchcode.c create mode 100644 source/patchcode.h create mode 100644 source/patchhook.S create mode 100644 source/ppc.h create mode 100644 source/sdhc.c create mode 100644 source/sdhc.h create mode 100644 source/sounds/bg_music.ogg create mode 100644 source/sounds/button_click.pcm create mode 100644 source/sounds/button_click2.pcm create mode 100644 source/sounds/button_over.pcm create mode 100644 source/sounds/credits_music.ogg create mode 100644 source/sys.c create mode 100644 source/sys.h create mode 100644 source/usbstorage.c create mode 100644 source/usbstorage.h create mode 100644 source/utils.c create mode 100644 source/utils.h create mode 100644 source/video.cpp create mode 100644 source/video.h create mode 100644 source/video2.c create mode 100644 source/video2.h create mode 100644 source/wbfs.c create mode 100644 source/wbfs.h create mode 100644 source/wdvd.c create mode 100644 source/wdvd.h create mode 100644 source/wpad.c create mode 100644 source/wpad.h diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..f73df6a3 --- /dev/null +++ b/Makefile @@ -0,0 +1,150 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := boot +BUILD := build +SOURCES := source source/libwiigui source/images source/fonts source/sounds source/libwbfs +INCLUDES := source + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) +CXXFLAGS = -save-temps -Xassembler -aln=$@.lst $(CFLAGS) +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80a00100 + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lfat -lpngu -lpng -lmetaphrasis -lm -lz -lwiiuse -lbte -lasnd -logc -ltremor -lfreetype +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(DEVKITPPC)/lib $(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)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) +OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg))) +PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \ + $(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.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) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +run: + wiiload $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +reload: + wiiload -r $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with .ttf, .png, and .mp3 extensions +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + $(bin2o) + +%.png.o : %.png + @echo $(notdir $<) + $(bin2o) + +%.ogg.o : %.ogg + @echo $(notdir $<) + $(bin2o) + +%.pcm.o : %.pcm + @echo $(notdir $<) + $(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/gui.pnproj b/gui.pnproj new file mode 100644 index 00000000..97e8c185 --- /dev/null +++ b/gui.pnproj @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gui.pnps b/gui.pnps new file mode 100644 index 00000000..4d76a3fe --- /dev/null +++ b/gui.pnps @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/source/FreeTypeGX.cpp b/source/FreeTypeGX.cpp new file mode 100644 index 00000000..0cbab38e --- /dev/null +++ b/source/FreeTypeGX.cpp @@ -0,0 +1,718 @@ +/* + * FreeTypeGX is a wrapper class for libFreeType which renders a compiled + * FreeType parsable font into a GX texture for Wii homebrew development. + * Copyright (C) 2008 Armin Tamzarian + * Modified by Tantric, 2009 + * + * This file is part of FreeTypeGX. + * + * FreeTypeGX is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FreeTypeGX 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FreeTypeGX. If not, see . + */ + +#include "FreeTypeGX.h" + +/** + * Default constructor for the FreeTypeGX class. + * + * @param textureFormat Optional format (GX_TF_*) of the texture as defined by the libogc gx.h header file. If not specified default value is GX_TF_RGBA8. + * @param vertexIndex Optional vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. If not specified default value is GX_VTXFMT1. + */ +FreeTypeGX::FreeTypeGX(uint8_t textureFormat, uint8_t vertexIndex) { + FT_Init_FreeType(&this->ftLibrary); + + this->textureFormat = textureFormat; + this->setVertexFormat(vertexIndex); + this->setCompatibilityMode(FTGX_COMPATIBILITY_NONE); +} + +/** + * Default destructor for the FreeTypeGX class. + */ +FreeTypeGX::~FreeTypeGX() { + this->unloadFont(); +} + +/** + * Convert a short char sctring to a wide char string. + * + * This routine converts a supplied shot character string into a wide character string. + * Note that it is the user's responsibility to clear the returned buffer once it is no longer needed. + * + * @param strChar Character string to be converted. + * @return Wide character representation of supplied character string. + */ +wchar_t* FreeTypeGX::charToWideChar(char* strChar) { + wchar_t *strWChar; + strWChar = new wchar_t[strlen(strChar) + 1]; + + char *tempSrc = strChar; + wchar_t *tempDest = strWChar; + while((*tempDest++ = *tempSrc++)); + + return strWChar; +} + +/** + * + * \overload + */ +wchar_t* FreeTypeGX::charToWideChar(const char* strChar) { + return FreeTypeGX::charToWideChar((char*) strChar); +} + +/** + * Setup the vertex attribute formats for the glyph textures. + * + * This function sets up the vertex format for the glyph texture on the specified vertex format index. + * Note that this function should not need to be called except if the vertex formats are cleared or the specified + * vertex format index is modified. + * + * @param vertexIndex Vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. +*/ +void FreeTypeGX::setVertexFormat(uint8_t vertexIndex) { + this->vertexIndex = vertexIndex; + + GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_POS, GX_POS_XY, GX_S16, 0); + GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); +} + +/** + * Sets the TEV and VTX rendering compatibility requirements for the class. + * + * This sets up the default TEV opertion and VTX descriptions rendering values for the class. This ensures that FreeTypeGX + * can remain compatible with external liraries or project code. Certain external libraries or code by design or lack of + * foresight assume that the TEV opertion and VTX descriptions values will remain constant or are always returned to a + * certain value. This will enable compatibility with those libraries and any other code which cannot or will not be changed. + * + * @param compatibilityMode Compatibility descritor (FTGX_COMPATIBILITY_*) as defined in FreeTypeGX.h +*/ +void FreeTypeGX::setCompatibilityMode(uint32_t compatibilityMode) { + this->compatibilityMode = compatibilityMode; +} + +/** + * Sets the TEV operation and VTX descriptor values after texture rendering it complete. + * + * This function calls the GX_SetTevOp and GX_SetVtxDesc functions with the compatibility parameters specified + * in setCompatibilityMode. + */ +void FreeTypeGX::setDefaultMode() { + if(this->compatibilityMode) { + switch(this->compatibilityMode & 0x00FF) { + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE: + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL: + GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_BLEND: + GX_SetTevOp(GX_TEVSTAGE0, GX_BLEND); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_REPLACE: + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR: + GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + break; + default: + break; + } + + switch(this->compatibilityMode & 0xFF00) { + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE: + GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); + break; + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT: + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + break; + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX8: + GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX8); + break; + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX16: + GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16); + break; + default: + break; + } + } +} + +/** + * Loads and processes a specified true type font buffer to a specific point size. + * + * This routine takes a precompiled true type font buffer and loads the necessary processed data into memory. This routine should be called before drawText will succeed. + * + * @param fontBuffer A pointer in memory to a precompiled true type font buffer. + * @param bufferSize Size of the true type font buffer in bytes. + * @param pointSize The desired point size this wrapper's configured font face. + * @param cacheAll Optional flag to specify if all font characters should be cached when the class object is created. If specified as false the characters only become cached the first time they are used. If not specified default value is false. + */ +uint16_t FreeTypeGX::loadFont(uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll) { + this->unloadFont(); + this->ftPointSize = pointSize; + + FT_New_Memory_Face(this->ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &this->ftFace); + + if(this->ftPointSize > 0) + FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize); + + this->ftSlot = this->ftFace->glyph; + this->ftKerningEnabled = FT_HAS_KERNING(this->ftFace); + + if (cacheAll) { + return this->cacheGlyphDataComplete(); + } + + return 0; +} + +/** + * + * \overload + */ +uint16_t FreeTypeGX::loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll) { + return this->loadFont((uint8_t *)fontBuffer, bufferSize, pointSize, cacheAll); +} + +/** + * Clears all loaded font glyph data. + * + * This routine clears all members of the font map structure and frees all allocated memory back to the system. + */ +void FreeTypeGX::unloadFont() { + if(this->fontData.size() == 0) + return; + + GX_DrawDone(); + GX_Flush(); + + for( std::map::iterator i = this->fontData.begin(); i != this->fontData.end(); i++) { + free(i->second.glyphDataTexture); + } + + this->fontData.clear(); +} + +void FreeTypeGX::changeSize(FT_UInt pointSize) { + this->unloadFont(); + this->ftPointSize = pointSize; + FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize); +} + +/** + * Adjusts the texture data buffer to necessary width for a given texture format. + * + * This routine determines adjusts the given texture width into the required width to hold the necessary texture data for proper alignment. + * + * @param textureWidth The initial guess for the texture width. + * @param textureFormat The texture format to which the data is to be converted. + * @return The correctly adjusted texture width. + */ +uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat) { + uint16_t alignment; + + switch(textureFormat) { + case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */ + case GX_TF_I8: /* 8x4 Tiles - 8-bit Intensity */ + case GX_TF_IA4: /* 8x4 Tiles - 4-bit Intensity, , 4-bit Alpha */ + alignment = 8; + break; + + case GX_TF_IA8: /* 4x4 Tiles - 8-bit Intensity, 8-bit Alpha */ + case GX_TF_RGB565: /* 4x4 Tiles - RGB565 Format */ + case GX_TF_RGB5A3: /* 4x4 Tiles - RGB5A3 Format */ + case GX_TF_RGBA8: /* 4x4 Tiles - RGBA8 Dual Cache Line Format */ + default: + alignment = 4; + break; + } + return textureWidth % alignment == 0 ? textureWidth : alignment + textureWidth - (textureWidth % alignment); + +} + +/** + * Adjusts the texture data buffer to necessary height for a given texture format. + * + * This routine determines adjusts the given texture height into the required height to hold the necessary texture data for proper alignment. + * + * @param textureHeight The initial guess for the texture height. + * @param textureFormat The texture format to which the data is to be converted. + * @return The correctly adjusted texture height. + */ +uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat) { + uint16_t alignment; + + switch(textureFormat) { + case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */ + alignment = 8; + break; + + case GX_TF_I8: /* 8x4 Tiles - 8-bit Intensity */ + case GX_TF_IA4: /* 8x4 Tiles - 4-bit Intensity, , 4-bit Alpha */ + case GX_TF_IA8: /* 4x4 Tiles - 8-bit Intensity, 8-bit Alpha */ + case GX_TF_RGB565: /* 4x4 Tiles - RGB565 Format */ + case GX_TF_RGB5A3: /* 4x4 Tiles - RGB5A3 Format */ + case GX_TF_RGBA8: /* 4x4 Tiles - RGBA8 Dual Cache Line Format */ + default: + alignment = 4; + break; + } + return textureHeight % alignment == 0 ? textureHeight : alignment + textureHeight - (textureHeight % alignment); + +} + +/** + * Caches the given font glyph in the instance font texture buffer. + * + * This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible + * structure within an instance-specific map. + * + * @param charCode The requested glyph's character code. + * @return A pointer to the allocated font structure. + */ +ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) { + FT_UInt gIndex; + uint16_t textureWidth = 0, textureHeight = 0; + + gIndex = FT_Get_Char_Index( this->ftFace, charCode ); + if (!FT_Load_Glyph(this->ftFace, gIndex, FT_LOAD_DEFAULT )) { + FT_Render_Glyph( this->ftSlot, FT_RENDER_MODE_NORMAL ); + + if(this->ftSlot->format == FT_GLYPH_FORMAT_BITMAP) { + FT_Bitmap *glyphBitmap = &this->ftSlot->bitmap; + + textureWidth = adjustTextureWidth(glyphBitmap->width, this->textureFormat); + textureHeight = adjustTextureHeight(glyphBitmap->rows, this->textureFormat); + + this->fontData[charCode] = (ftgxCharData){ + this->ftSlot->advance.x >> 6, + gIndex, + textureWidth, + textureHeight, + this->ftSlot->bitmap_top, + this->ftSlot->bitmap_top, + textureHeight - this->ftSlot->bitmap_top, + NULL + }; + this->loadGlyphData(glyphBitmap, &this->fontData[charCode]); + + return &this->fontData[charCode]; + } + } + + return NULL; +} + +/** + * Locates each character in this wrapper's configured font face and proccess them. + * + * This routine locates each character in the configured font face and renders the glyph's bitmap. + * Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map. + */ +uint16_t FreeTypeGX::cacheGlyphDataComplete() { + uint16_t i = 0; + FT_UInt gIndex; + FT_ULong charCode = FT_Get_First_Char( this->ftFace, &gIndex ); + while ( gIndex != 0 ) { + + if(this->cacheGlyphData(charCode) != NULL) { + i++; + } + + charCode = FT_Get_Next_Char( this->ftFace, charCode, &gIndex ); + } + + return i; +} + +/** + * Loads the rendered bitmap into the relevant structure's data buffer. + * + * This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer. + * Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value. + * + * @param bmp A pointer to the most recently rendered glyph's bitmap. + * @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph. + */ +void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) { + + uint32_t *glyphData = (uint32_t *)memalign(32, charData->textureWidth * charData->textureHeight * 4); + memset(glyphData, 0x00, charData->textureWidth * charData->textureHeight * 4); + + for (uint16_t imagePosY = 0; imagePosY < bmp->rows; imagePosY++) { + for (uint16_t imagePosX = 0; imagePosX < bmp->width; imagePosX++) { + uint32_t pixel = (uint32_t) bmp->buffer[imagePosY * bmp->width + imagePosX]; + glyphData[imagePosY * charData->textureWidth + imagePosX] = 0x00000000 | (pixel << 24) | (pixel << 16) | (pixel << 8) | pixel; + } + } + + switch(this->textureFormat) { + case GX_TF_I4: + charData->glyphDataTexture = Metaphrasis::convertBufferToI4(glyphData, charData->textureWidth, charData->textureHeight); + break; + case GX_TF_I8: + charData->glyphDataTexture = Metaphrasis::convertBufferToI8(glyphData, charData->textureWidth, charData->textureHeight); + break; + case GX_TF_IA4: + charData->glyphDataTexture = Metaphrasis::convertBufferToIA4(glyphData, charData->textureWidth, charData->textureHeight); + break; + case GX_TF_IA8: + charData->glyphDataTexture = Metaphrasis::convertBufferToIA8(glyphData, charData->textureWidth, charData->textureHeight); + break; + case GX_TF_RGB565: + charData->glyphDataTexture = Metaphrasis::convertBufferToRGB565(glyphData, charData->textureWidth, charData->textureHeight); + break; + case GX_TF_RGB5A3: + charData->glyphDataTexture = Metaphrasis::convertBufferToRGB5A3(glyphData, charData->textureWidth, charData->textureHeight); + break; + case GX_TF_RGBA8: + default: + charData->glyphDataTexture = Metaphrasis::convertBufferToRGBA8(glyphData, charData->textureWidth, charData->textureHeight); + break; + } + + free(glyphData); +} + +/** + * Determines the x offset of the rendered string. + * + * This routine calculates the x offset of the rendered string based off of a supplied positional format parameter. + * + * @param width Current pixel width of the string. + * @param format Positional format of the string. + */ +uint16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) { + + if (format & FTGX_JUSTIFY_LEFT ) { + return 0; + } + else if (format & FTGX_JUSTIFY_CENTER ) { + return width >> 1; + } + else if (format & FTGX_JUSTIFY_RIGHT ) { + return width; + } + + return 0; +} + +/** + * Determines the y offset of the rendered string. + * + * This routine calculates the y offset of the rendered string based off of a supplied positional format parameter. + * + * @param offset Current pixel offset data of the string. + * @param format Positional format of the string. + */ +uint16_t FreeTypeGX::getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format) { + if (format & FTGX_ALIGN_TOP ) { + return -offset.max; + } + else if (format & FTGX_ALIGN_MIDDLE ) { + return -offset.max; + } + else if (format & FTGX_ALIGN_BOTTOM ) { + return offset.min; + } + + return 0; +} + +/** + * Processes the supplied text string and prints the results at the specified coordinates. + * + * This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer, + * a texture from said buffer, and loads the resultant texture into the EFB. + * + * @param x Screen X coordinate at which to output the text. + * @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs. + * @param text NULL terminated string to output. + * @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff} + * @param textStyle Flags which specify any styling which should be applied to the rendered string. + * @return The number of characters printed. + */ +uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color, uint16_t textStyle) { + uint16_t strLength = wcslen(text); + uint16_t x_pos = x, printed = 0; + uint16_t x_offset = 0, y_offset = 0; + GXTexObj glyphTexture; + FT_Vector pairDelta; + + if(textStyle & 0x000F) { + x_offset = this->getStyleOffsetWidth(this->getWidth(text), textStyle); + } + if(textStyle & 0x00F0) { + y_offset = this->getStyleOffsetHeight(this->getOffset(text), textStyle); + } + + for (uint16_t i = 0; i < strLength; i++) { + + ftgxCharData* glyphData = NULL; + if( this->fontData.find(text[i]) != this->fontData.end() ) { + glyphData = &this->fontData[text[i]]; + } + else { + glyphData = this->cacheGlyphData(text[i]); + } + + if(glyphData != NULL) { + + if(this->ftKerningEnabled && i) { + FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta ); + x_pos += pairDelta.x >> 6; + } + + GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, this->textureFormat, GX_CLAMP, GX_CLAMP, GX_FALSE); + this->copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos - x_offset, y - glyphData->renderOffsetY - y_offset, color); + + x_pos += glyphData->glyphAdvanceX; + printed++; + } + } + + if(textStyle & 0x0F00) { + this->drawTextFeature(x - x_offset, y, this->getWidth(text), this->getOffset(text), textStyle, color); + } + + return printed; +} + +/** + * \overload + */ +uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color, uint16_t textStyle) { + return this->drawText(x, y, (wchar_t *)text, color, textStyle); +} + +void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset offsetData, uint16_t format, GXColor color) { + uint16_t featureHeight = this->ftPointSize >> 4 > 0 ? this->ftPointSize >> 4 : 1; + + if (format & FTGX_STYLE_UNDERLINE ) { + switch(format & 0x00F0) { + case FTGX_ALIGN_TOP: + this->copyFeatureToFramebuffer(width, featureHeight, x, y + offsetData.max + 1, color); + break; + case FTGX_ALIGN_MIDDLE: + this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData.max - offsetData.min) >> 1) + 1, color); + break; + case FTGX_ALIGN_BOTTOM: + this->copyFeatureToFramebuffer(width, featureHeight, x, y - offsetData.min, color); + break; + default: + this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color); + break; + } + } + + if (format & FTGX_STYLE_STRIKE ) { + switch(format & 0x00F0) { + case FTGX_ALIGN_TOP: + this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData.max + offsetData.min) >> 1), color); + break; + case FTGX_ALIGN_MIDDLE: + this->copyFeatureToFramebuffer(width, featureHeight, x, y, color); + break; + case FTGX_ALIGN_BOTTOM: + this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max + offsetData.min) >> 1), color); + break; + default: + this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max - offsetData.min) >> 1), color); + break; + } + } +} + +/** + * Processes the supplied string and return the width of the string in pixels. + * + * This routine processes each character of the supplied text string and calculates the width of the entire string. + * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. + * + * @param text NULL terminated string to calculate. + * @return The width of the text string in pixels. + */ +uint16_t FreeTypeGX::getWidth(wchar_t *text) { + uint16_t strLength = wcslen(text); + uint16_t strWidth = 0; + FT_Vector pairDelta; + + for (uint16_t i = 0; i < strLength; i++) { + + ftgxCharData* glyphData = NULL; + if( this->fontData.find(text[i]) != this->fontData.end() ) { + glyphData = &this->fontData[text[i]]; + } + else { + glyphData = this->cacheGlyphData(text[i]); + } + + if(glyphData != NULL) { + if(this->ftKerningEnabled && (i > 0)) { + FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta ); + strWidth += pairDelta.x >> 6; + } + + strWidth += glyphData->glyphAdvanceX; + } + } + + return strWidth; +} + +/** + * + * \overload + */ +uint16_t FreeTypeGX::getWidth(wchar_t const *text) { + return this->getWidth((wchar_t *)text); +} + +/** + * Processes the supplied string and return the height of the string in pixels. + * + * This routine processes each character of the supplied text string and calculates the height of the entire string. + * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. + * + * @param text NULL terminated string to calculate. + * @return The height of the text string in pixels. + */ +uint16_t FreeTypeGX::getHeight(wchar_t *text) { + ftgxDataOffset offset = this->getOffset(text); + + return offset.max + offset.min; +} + +/** + * + * \overload + */ +uint16_t FreeTypeGX::getHeight(wchar_t const *text) { + return this->getHeight((wchar_t *)text); +} + +/** + * Get the maximum offset above and minimum offset below the font origin line. + * + * This function calculates the maximum pixel height above the font origin line and the minimum + * pixel height below the font origin line and returns the values in an addressible structure. + * + * @param text NULL terminated string to calculate. + * @return The max and min values above and below the font origin line. + */ +ftgxDataOffset FreeTypeGX::getOffset(wchar_t *text) { + uint16_t strLength = wcslen(text); + uint16_t strMax = 0, strMin = 0; + + for (uint16_t i = 0; i < strLength; i++) { + + ftgxCharData* glyphData = NULL; + if( this->fontData.find(text[i]) != this->fontData.end() ) { + glyphData = &this->fontData[text[i]]; + } + else { + glyphData = this->cacheGlyphData(text[i]); + } + + if(glyphData != NULL) { + strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax; + strMin = glyphData->renderOffsetMin > strMin ? glyphData->renderOffsetMin : strMin; + } + } + + return (ftgxDataOffset){strMax, strMin}; +} + +/** + * + * \overload + */ +ftgxDataOffset FreeTypeGX::getOffset(wchar_t const *text) { + return this->getOffset(text); +} + +/** + * Copies the supplied texture quad to the EFB. + * + * This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target. + * + * @param texObj A pointer to the glyph's initialized texture object. + * @param texWidth The pixel width of the texture object. + * @param texHeight The pixel height of the texture object. + * @param screenX The screen X coordinate at which to output the rendered texture. + * @param screenY The screen Y coordinate at which to output the rendered texture. + * @param color Color to apply to the texture. + */ +void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color) { + + GX_LoadTexObj(texObj, GX_TEXMAP0); + GX_InvalidateTexAll(); + + GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); + GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); + + GX_Begin(GX_QUADS, this->vertexIndex, 4); + GX_Position2s16(screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(0.0f, 0.0f); + + GX_Position2s16(texWidth + screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(1.0f, 0.0f); + + GX_Position2s16(texWidth + screenX, texHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(1.0f, 1.0f); + + GX_Position2s16(screenX, texHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(0.0f, 1.0f); + GX_End(); + + this->setDefaultMode(); +} + +/** + * Creates a feature quad to the EFB. + * + * This function creates a simple quad for displaying underline or strikeout text styling. + * + * @param featureWidth The pixel width of the quad. + * @param featureHeight The pixel height of the quad. + * @param screenX The screen X coordinate at which to output the quad. + * @param screenY The screen Y coordinate at which to output the quad. + * @param color Color to apply to the texture. + */ +void FreeTypeGX::copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color) { + + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); + + GX_Begin(GX_QUADS, this->vertexIndex, 4); + GX_Position2s16(screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + + GX_Position2s16(featureWidth + screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + + GX_Position2s16(featureWidth + screenX, featureHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + + GX_Position2s16(screenX, featureHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_End(); + + this->setDefaultMode(); +} diff --git a/source/FreeTypeGX.h b/source/FreeTypeGX.h new file mode 100644 index 00000000..935cd7d0 --- /dev/null +++ b/source/FreeTypeGX.h @@ -0,0 +1,286 @@ +/* + * FreeTypeGX is a wrapper class for libFreeType which renders a compiled + * FreeType parsable font into a GX texture for Wii homebrew development. + * Copyright (C) 2008 Armin Tamzarian + * Modified by Tantric, 2009 + * + * This file is part of FreeTypeGX. + * + * FreeTypeGX is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FreeTypeGX 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FreeTypeGX. If not, see . + */ + +/** \mainpage FreeTypeGX + * + * \section sec_intro Introduction + * + * FreeTypeGX is a wrapper class for libFreeType which renders a compiled FreeType parsable font into a GX texture for Wii homebrew development. + *
+ * FreeTypeGX is written in C++ and makes use of a selectable pre-buffered or buffer-on-demand methodology to allow fast and efficient printing of text to the EFB. + *

+ * This library was developed in-full by Armin Tamzarian with the support of developers in \#wiibrew on EFnet. + * + * \section sec_installation_source Installation (Source Code) + * + * -# Ensure that you have the libFreeType Wii library installed in your development environment with the library added to your Makefile where appropriate. + * -# Ensure that you have the Metaphrasis library installed in your development environment with the library added to your Makefile where appropriate. + * -# Extract the FreeTypeGX archive. + * -# Copy the contents of the src directory into your project's development path. + * -# Include the FreeTypeGX header file in your code using syntax such as the following: + * \code + * #include "FreeTypeGX.h" + * \endcode + * + * \section sec_installation_library Installation (Library) + * + * -# Ensure that you have the libFreeType Wii library installed in your development environment with the library added to your Makefile where appropriate. + * -# Ensure that you have the Metaphrasis library installed in your development environment with the library added to your Makefile where appropriate. + * -# Extract the FreeTypeGX archive. + * -# Copy the contents of the lib directory into your devKitPro/libogc directory. + * -# Include the FreeTypeGX header file in your code using syntax such as the following: + * \code + * #include "FreeTypeGX.h" + * \endcode + * + * \section sec_freetypegx_prerequisites FreeTypeGX Prerequisites + * + * Before you begin using FreeTypeGX in your project you must ensure that the desired font in compiled into your project. For this example I will assume you are building your project with a Makefile using devKitPro evironment and are attempting to include a font whose filename is rursus_compact_mono.ttf. + * + * -# Copy the font into a directory which will be processed by the project's Makefile. If you are unsure about where you should place your font just copy the it into your project's source directory. + * \n\n + * -# Modify the Makefile to convert the font into an object file: + * \code + * %.ttf.o : %.ttf + * @echo $(notdir $<) + * $(bin2o) + * \endcode + * \n + * -# Include the font object's generated header file in your source code: + * \code + * #include "rursus_compact_mono_ttf.h" + * \endcode + * This header file defines the two variables that you will need for use within your project: + * \code + * extern const u8 rursus_compact_mono_ttf[]; A pointer to the font buffer within the compiled project. + * extern const u32 rursus_compact_mono_ttf_size; The size of the font's buffer in bytes. + * \endcode + * + * \section sec_freetypegx_usage FreeTypeGX Usage + * + * -# Within the file you included the FreeTypeGX.h header create an instance object of the FreeTypeGX class: + * \code + * FreeTypeGX *freeTypeGX = new FreeTypeGX(); + * \endcode + * Alternately you can specify a texture format to which you would like to render the font characters. Note that the default value for this parameter is GX_TF_RGBA8. + * \code + * FreeTypeGX *freeTypeGX = new FreeTypeGX(GX_TF_RGB565); + * \endcode + * Furthermore, you can also specify a vertex format index to avoid conflicts with concurrent libraries or other systems. Note that the default value for this parameter is GX_VTXFMT1. + * \code + * FreeTypeGX *freeTypeGX = new FreeTypeGX(GX_TF_RGB565, GX_VTXFMT1); + * \endcode + * \n + * Currently supported textures are: + * \li GX_TF_I4 + * \li GX_TF_I8 + * \li GX_TF_IA4 + * \li GX_TF_IA8 + * \li GX_TF_RGB565 + * \li GX_TF_RGB5A3 + * \li GX_TF_RGBA8 + * + * \n + * -# Using the allocated FreeTypeGX instance object call the loadFont function to load the font from the compiled buffer and specify the desired point size. Note that this function can be called multiple times to load a new: + * \code + * freeTypeGX->loadFont(rursus_compact_mono_ttf, rursus_compact_mono_ttf_size, 64); + * \endcode + * Alternately you can specify a flag which will load and cache all available font glyphs immidiately. Note that on large font sets enabling this feature could take a significant amount of time. + * \code + * freeTypeGX->loadFont(rursus_compact_mono_ttf, rursus_compact_mono_ttf_size, 64, true); + * \endcode + * \n + * -# If necessary you can enable compatibility modes with concurrent libraries or systems. For more information on this feature see the documentation for setCompatibilityMode: + * \code + * freeTypeGX->setCompatibilityMode(FTGX_COMPATIBILITY_GRRLIB); + * \endcode + * -# Using the allocated FreeTypeGX instance object call the drawText function to print a string at the specified screen X and Y coordinates to the current EFB: + * \code + * freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!")); + * \endcode + * Alternately you can specify a GXColor object you would like to apply to the printed characters: + * \code + * freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!"), + * (GXColor){0xff, 0xee, 0xaa, 0xff}); + * \endcode + * Furthermore you can also specify a group of styling parameters which will modify the positioning or style of the text: + * \code + * freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!"), + * (GXColor){0xff, 0xee, 0xaa, 0xff}, + * FTGX_JUSTIFY_CENTER | FTGX_ALIGN_BOTTOM | FTGX_STYLE_UNDERLINE); + * \endcode + * \n + * Currently style parameters are: + * \li FTGX_JUSTIFY_LEFT + * \li FTGX_JUSTIFY_CENTER + * \li FTGX_JUSTIFY_RIGHT + * \li FTGX_ALIGN_TOP + * \li FTGX_ALIGN_MIDDLE + * \li FTGX_ALIGN_BOTTOM + * \li FTGX_STYLE_UNDERLINE + * \li FTGX_STYLE_STRIKE + * + * \section sec_license License + * + * FreeTypeGX is distributed under the GNU Lesser General Public License. + * + * \section sec_contact Contact + * + * If you have any suggestions, questions, or comments regarding this library feel free to e-mail me at tamzarian1989 [at] gmail [dawt] com. + */ + +#ifndef FREETYPEGX_H_ +#define FREETYPEGX_H_ + +#include +#include +#include FT_FREETYPE_H +#include FT_BITMAP_H +#include + +#include +#include +#include + +/*! \struct ftgxCharData_ + * + * Font face character glyph relevant data structure. + */ +typedef struct ftgxCharData_ { + uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ + uint16_t glyphIndex; /**< Charachter glyph index in the font face. */ + + uint16_t textureWidth; /**< Texture width in pixels/bytes. */ + uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */ + + uint16_t renderOffsetY; /**< Texture Y axis bearing offset. */ + uint16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ + uint16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ + + uint32_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */ +} ftgxCharData; + +/*! \struct ftgxDataOffset_ + * + * Offset structure which hold both a maximum and minimum value. + */ +typedef struct ftgxDataOffset_ { + int16_t max; /**< Maximum data offset. */ + int16_t min; /**< Minimum data offset. */ +} ftgxDataOffset; + +#define _TEXT(t) L ## t /**< Unicode helper macro. */ + +#define FTGX_NULL 0x0000 +#define FTGX_JUSTIFY_LEFT 0x0001 +#define FTGX_JUSTIFY_CENTER 0x0002 +#define FTGX_JUSTIFY_RIGHT 0x0004 + +#define FTGX_ALIGN_TOP 0x0010 +#define FTGX_ALIGN_MIDDLE 0x0020 +#define FTGX_ALIGN_BOTTOM 0x0040 + +#define FTGX_STYLE_UNDERLINE 0x0100 +#define FTGX_STYLE_STRIKE 0x0200 + +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE 0X0001 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL 0X0002 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_BLEND 0X0004 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_REPLACE 0X0008 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR 0X0010 + +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE 0X0100 +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT 0X0200 +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX8 0X0400 +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX16 0X0800 + +#define FTGX_COMPATIBILITY_NONE 0x0000 +#define FTGX_COMPATIBILITY_GRRLIB FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE +#define FTGX_COMPATIBILITY_LIBWIISPRITE FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT + +const GXColor ftgxWhite = (GXColor){0xff, 0xff, 0xff, 0xff}; /**< Constant color value used only to sanitize Doxygen documentation. */ + +/*! \class FreeTypeGX + * \brief Wrapper class for the libFreeType library with GX rendering. + * \author Armin Tamzarian + * \version 0.2.4 + * + * FreeTypeGX acts as a wrapper class for the libFreeType library. It supports precaching of transformed glyph data into + * a specified texture format. Rendering of the data to the EFB is accomplished through the application of high performance + * GX texture functions resulting in high throughput of string rendering. + */ +class FreeTypeGX { + + private: + FT_Library ftLibrary; /**< FreeType FT_Library instance. */ + FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */ + FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */ + FT_UInt ftPointSize; /**< Requested size of the rendered font. */ + bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */ + + uint8_t textureFormat; /**< Defined texture format of the target EFB. */ + uint8_t vertexIndex; /**< Vertex format descriptor index. */ + uint32_t compatibilityMode; /**< Compatibility mode for default tev operations and vertex descriptors. */ + std::map fontData; /**< Map which holds the glyph data structures for the corresponding characters. */ + + static uint16_t adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat); + static uint16_t adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat); + + static uint16_t getStyleOffsetWidth(uint16_t width, uint16_t format); + static uint16_t getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format); + + void unloadFont(); + ftgxCharData *cacheGlyphData(wchar_t charCode); + uint16_t cacheGlyphDataComplete(); + void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData); + + void setDefaultMode(); + + void drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset offsetData, uint16_t format, GXColor color); + void copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color); + void copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color); + + public: + FreeTypeGX(uint8_t textureFormat = GX_TF_RGBA8, uint8_t vertexIndex = GX_VTXFMT1); + ~FreeTypeGX(); + + static wchar_t* charToWideChar(char* p); + static wchar_t* charToWideChar(const char* p); + void setVertexFormat(uint8_t vertexIndex); + void setCompatibilityMode(uint32_t compatibilityMode); + + uint16_t loadFont(uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll = false); + uint16_t loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll = false); + void changeSize(FT_UInt pointSize); + + uint16_t drawText(int16_t x, int16_t y, wchar_t *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL); + uint16_t drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL); + + uint16_t getWidth(wchar_t *text); + uint16_t getWidth(wchar_t const *text); + uint16_t getHeight(wchar_t *text); + uint16_t getHeight(wchar_t const *text); + ftgxDataOffset getOffset(wchar_t *text); + ftgxDataOffset getOffset(wchar_t const *text); +}; + +#endif /* FREETYPEGX_H_ */ diff --git a/source/apploader.c b/source/apploader.c new file mode 100644 index 00000000..3ee503cf --- /dev/null +++ b/source/apploader.c @@ -0,0 +1,327 @@ +#include +#include +#include + +#include "apploader.h" +#include "wdvd.h" +#include "wpad.h" +#include "patchcode.h" +#include "kenobiwii.h" /*FISHEARS*/ + +/*KENOBI! - FISHEARS*/ +extern const unsigned char kenobiwii[]; +extern const int kenobiwii_size; +/*KENOBI! - FISHEARS*/ + +/* Apploader function pointers */ +typedef int (*app_main)(void **dst, int *size, int *offset); +typedef void (*app_init)(void (*report)(const char *fmt, ...)); +typedef void *(*app_final)(); +typedef void (*app_entry)(void (**init)(void (*report)(const char *fmt, ...)), int (**main)(), void *(**final)()); + +/* Apploader pointers */ +static u8 *appldr = (u8 *)0x81200000; + + +/* Constants */ +#define APPLDR_OFFSET 0x2440 + +/* Variables */ +static u32 buffer[0x20] ATTRIBUTE_ALIGN(32); + + +static void __noprint(const char *fmt, ...) +{ +} + + + +bool compare_videomodes(GXRModeObj* mode1, GXRModeObj* mode2) +{ + if (mode1->viTVMode != mode2->viTVMode || mode1->fbWidth != mode2->fbWidth || mode1->efbHeight != mode2->efbHeight || mode1->xfbHeight != mode2->xfbHeight || + mode1->viXOrigin != mode2->viXOrigin || mode1->viYOrigin != mode2->viYOrigin || mode1->viWidth != mode2->viWidth || mode1->viHeight != mode2->viHeight || + mode1->xfbMode != mode2->xfbMode || mode1->field_rendering != mode2->field_rendering || mode1->aa != mode2->aa || mode1->sample_pattern[0][0] != mode2->sample_pattern[0][0] || + mode1->sample_pattern[1][0] != mode2->sample_pattern[1][0] || mode1->sample_pattern[2][0] != mode2->sample_pattern[2][0] || + mode1->sample_pattern[3][0] != mode2->sample_pattern[3][0] || mode1->sample_pattern[4][0] != mode2->sample_pattern[4][0] || + mode1->sample_pattern[5][0] != mode2->sample_pattern[5][0] || mode1->sample_pattern[6][0] != mode2->sample_pattern[6][0] || + mode1->sample_pattern[7][0] != mode2->sample_pattern[7][0] || mode1->sample_pattern[8][0] != mode2->sample_pattern[8][0] || + mode1->sample_pattern[9][0] != mode2->sample_pattern[9][0] || mode1->sample_pattern[10][0] != mode2->sample_pattern[10][0] || + mode1->sample_pattern[11][0] != mode2->sample_pattern[11][0] || mode1->sample_pattern[0][1] != mode2->sample_pattern[0][1] || + mode1->sample_pattern[1][1] != mode2->sample_pattern[1][1] || mode1->sample_pattern[2][1] != mode2->sample_pattern[2][1] || + mode1->sample_pattern[3][1] != mode2->sample_pattern[3][1] || mode1->sample_pattern[4][1] != mode2->sample_pattern[4][1] || + mode1->sample_pattern[5][1] != mode2->sample_pattern[5][1] || mode1->sample_pattern[6][1] != mode2->sample_pattern[6][1] || + mode1->sample_pattern[7][1] != mode2->sample_pattern[7][1] || mode1->sample_pattern[8][1] != mode2->sample_pattern[8][1] || + mode1->sample_pattern[9][1] != mode2->sample_pattern[9][1] || mode1->sample_pattern[10][1] != mode2->sample_pattern[10][1] || + mode1->sample_pattern[11][1] != mode2->sample_pattern[11][1] || mode1->vfilter[0] != mode2->vfilter[0] || + mode1->vfilter[1] != mode2->vfilter[1] || mode1->vfilter[2] != mode2->vfilter[2] || mode1->vfilter[3] != mode2->vfilter[3] || mode1->vfilter[4] != mode2->vfilter[4] || + mode1->vfilter[5] != mode2->vfilter[5] || mode1->vfilter[6] != mode2->vfilter[6] ) + { + return false; + } else + { + return true; + } +} + + +void patch_videomode(GXRModeObj* mode1, GXRModeObj* mode2) +{ + mode1->viTVMode = mode2->viTVMode; + mode1->fbWidth = mode2->fbWidth; + mode1->efbHeight = mode2->efbHeight; + mode1->xfbHeight = mode2->xfbHeight; + mode1->viXOrigin = mode2->viXOrigin; + mode1->viYOrigin = mode2->viYOrigin; + mode1->viWidth = mode2->viWidth; + mode1->viHeight = mode2->viHeight; + mode1->xfbMode = mode2->xfbMode; + mode1->field_rendering = mode2->field_rendering; + mode1->aa = mode2->aa; + mode1->sample_pattern[0][0] = mode2->sample_pattern[0][0]; + mode1->sample_pattern[1][0] = mode2->sample_pattern[1][0]; + mode1->sample_pattern[2][0] = mode2->sample_pattern[2][0]; + mode1->sample_pattern[3][0] = mode2->sample_pattern[3][0]; + mode1->sample_pattern[4][0] = mode2->sample_pattern[4][0]; + mode1->sample_pattern[5][0] = mode2->sample_pattern[5][0]; + mode1->sample_pattern[6][0] = mode2->sample_pattern[6][0]; + mode1->sample_pattern[7][0] = mode2->sample_pattern[7][0]; + mode1->sample_pattern[8][0] = mode2->sample_pattern[8][0]; + mode1->sample_pattern[9][0] = mode2->sample_pattern[9][0]; + mode1->sample_pattern[10][0] = mode2->sample_pattern[10][0]; + mode1->sample_pattern[11][0] = mode2->sample_pattern[11][0]; + mode1->sample_pattern[0][1] = mode2->sample_pattern[0][1]; + mode1->sample_pattern[1][1] = mode2->sample_pattern[1][1]; + mode1->sample_pattern[2][1] = mode2->sample_pattern[2][1]; + mode1->sample_pattern[3][1] = mode2->sample_pattern[3][1]; + mode1->sample_pattern[4][1] = mode2->sample_pattern[4][1]; + mode1->sample_pattern[5][1] = mode2->sample_pattern[5][1]; + mode1->sample_pattern[6][1] = mode2->sample_pattern[6][1]; + mode1->sample_pattern[7][1] = mode2->sample_pattern[7][1]; + mode1->sample_pattern[8][1] = mode2->sample_pattern[8][1]; + mode1->sample_pattern[9][1] = mode2->sample_pattern[9][1]; + mode1->sample_pattern[10][1] = mode2->sample_pattern[10][1]; + mode1->sample_pattern[11][1] = mode2->sample_pattern[11][1]; + mode1->vfilter[0] = mode2->vfilter[0]; + mode1->vfilter[1] = mode2->vfilter[1]; + mode1->vfilter[2] = mode2->vfilter[2]; + mode1->vfilter[3] = mode2->vfilter[3]; + mode1->vfilter[4] = mode2->vfilter[4]; + mode1->vfilter[5] = mode2->vfilter[5]; + mode1->vfilter[6] = mode2->vfilter[6]; +} + +GXRModeObj* vmodes[] = { + &TVNtsc240Ds, + &TVNtsc240DsAa, + &TVNtsc240Int, + &TVNtsc240IntAa, + &TVNtsc480IntDf, + &TVNtsc480IntAa, + &TVNtsc480Prog, + &TVMpal480IntDf, + &TVPal264Ds, + &TVPal264DsAa, + &TVPal264Int, + &TVPal264IntAa, + &TVPal524IntAa, + &TVPal528Int, + &TVPal528IntDf, + &TVPal574IntDfScale, + &TVEurgb60Hz240Ds, + &TVEurgb60Hz240DsAa, + &TVEurgb60Hz240Int, + &TVEurgb60Hz240IntAa, + &TVEurgb60Hz480Int, + &TVEurgb60Hz480IntDf, + &TVEurgb60Hz480IntAa, + &TVEurgb60Hz480Prog, + &TVEurgb60Hz480ProgSoft, + &TVEurgb60Hz480ProgAa +}; + +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 +}; + +GXRModeObj* NTSC2PAL[]={ + &TVNtsc240Ds, &TVPal264Ds, + &TVNtsc240DsAa, &TVPal264DsAa, + &TVNtsc240Int, &TVPal264Int, + &TVNtsc240IntAa, &TVPal264IntAa, + &TVNtsc480IntDf, &TVPal528IntDf, + &TVNtsc480IntAa, &TVPal524IntAa, + &TVNtsc480Prog, &TVPal528IntDf, + 0,0 +}; + +GXRModeObj* NTSC2PAL60[]={ + &TVNtsc240Ds, &TVEurgb60Hz240Ds, + &TVNtsc240DsAa, &TVEurgb60Hz240DsAa, + &TVNtsc240Int, &TVEurgb60Hz240Int, + &TVNtsc240IntAa, &TVEurgb60Hz240IntAa, + &TVNtsc480IntDf, &TVEurgb60Hz480IntDf, + &TVNtsc480IntAa, &TVEurgb60Hz480IntAa, + &TVNtsc480Prog, &TVEurgb60Hz480Prog, + 0,0 +}; +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; +} + +s32 Apploader_Run(entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch) +{ + app_entry appldr_entry; + app_init appldr_init; + app_main appldr_main; + app_final appldr_final; + + u32 appldr_len; + s32 ret; + + /* Read apploader header */ + ret = WDVD_Read(buffer, 0x20, APPLDR_OFFSET); + if (ret < 0) + return ret; + + /* Calculate apploader length */ + appldr_len = buffer[5] + buffer[6]; + + /* Read apploader code */ + ret = WDVD_Read(appldr, appldr_len, APPLDR_OFFSET + 0x20); + if (ret < 0) + return ret; + + /* Set apploader entry function */ + appldr_entry = (app_entry)buffer[4]; + + /* Call apploader entry */ + appldr_entry(&appldr_init, &appldr_main, &appldr_final); + + /* Initialize apploader */ + appldr_init(__noprint); + + if (cheat) + { + /*HOOKS STUFF - FISHEARS*/ + memset((void*)0x80001800,0,kenobiwii_size); + memcpy((void*)0x80001800,kenobiwii,kenobiwii_size); + DCFlushRange((void*)0x80001800,kenobiwii_size); + hooktype = 1; + memcpy((void*)0x80001800, (char*)0x80000000, 6); // For WiiRD + /*HOOKS STUFF - FISHEARS*/ + } + + for (;;) { + void *dst = NULL; + int len = 0, offset = 0; + GXRModeObj** table = NULL; + + /* Run apploader main function */ + ret = appldr_main(&dst, &len, &offset); + if (!ret) + break; + + /* Read data from DVD */ + WDVD_Read(dst, len, (u64)(offset << 2)); + + + if (videoSelected == 5) // patch + + { + switch(CONF_GetVideo()) + { + case CONF_VIDEO_PAL: + if(CONF_GetEuRGB60() > 0) + { + table = NTSC2PAL60; + } + else + { + table = NTSC2PAL; + } + break; + + case CONF_VIDEO_MPAL: + + + + table = NTSC2PAL; + break; + + + default: + table = PAL2NTSC; + break; + } + Search_and_patch_Video_Modes(dst, len, table); + } + + /*GAME HOOK - FISHEARS*/ + dogamehooks(dst,len); + + if (vipatch) + vidolpatcher(dst,len); + + + /*LANGUAGE PATCH - FISHEARS*/ + langpatcher(dst,len); + + DCFlushRange(dst, len); + } + /* Set entry point from apploader */ + *entry = appldr_final(); + + return 0; +} +#ifdef __cplusplus +} +#endif diff --git a/source/apploader.h b/source/apploader.h new file mode 100644 index 00000000..5481bbb9 --- /dev/null +++ b/source/apploader.h @@ -0,0 +1,10 @@ +#ifndef _APPLOADER_H_ +#define _APPLOADER_H_ + +/* Entry point */ +typedef void (*entry_point)(void); + +/* Prototypes */ +s32 Apploader_Run(entry_point *, u8, u8, u8); + +#endif diff --git a/source/audio.cpp b/source/audio.cpp new file mode 100644 index 00000000..8d0b8854 --- /dev/null +++ b/source/audio.cpp @@ -0,0 +1,35 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * audio.cpp + * Audio support + ***************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * InitAudio + * + * Initializes the Wii's audio subsystem + ***************************************************************************/ +void InitAudio() +{ + AUDIO_Init(NULL); + ASND_Init(); + ASND_Pause(0); +} + +/**************************************************************************** + * ShutdownAudio + * + * Shuts down audio subsystem. Useful to avoid unpleasant sounds if a + * crash occurs during shutdown. + ***************************************************************************/ +void ShutdownAudio() +{ + ASND_Pause(1); + ASND_End(); +} diff --git a/source/audio.h b/source/audio.h new file mode 100644 index 00000000..6efdf6d5 --- /dev/null +++ b/source/audio.h @@ -0,0 +1,15 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * audio.h + * Audio support + ***************************************************************************/ + +#ifndef _AUDIO_H_ +#define _AUDIO_H_ + +void InitAudio(); +void ShutdownAudio(); + +#endif diff --git a/source/cfg.c b/source/cfg.c new file mode 100644 index 00000000..fb72d6b1 --- /dev/null +++ b/source/cfg.c @@ -0,0 +1,1065 @@ +#include +#include +#include +#include +#include +#include +#include +#include "cfg.h" + +struct SSettings Settings; +//struct SSettings2 Settings2; + + +char *cfg_path = "SD:/apps/usbloader/"; +//char *setting_path = "SD:/apps/usbloader/settings.cfg"; +char current_path[100]; + +/* configurable fields */ + +/* default */ +//int ENTRIES_PER_PAGE = 12; +//int MAX_CHARACTERS = 37; +//int CONSOLE_XCOORD = 260; +//int CONSOLE_YCOORD = 30; +//int CONSOLE_WIDTH = 340; +//int CONSOLE_HEIGHT = 290; +//int CONSOLE_FG_COLOR = 15; +//int CONSOLE_BG_COLOR = 0; +//int COVER_XCOORD = 28; +//int COVER_YCOORD = 105; + +struct CFG CFG; +struct THEME THEME; +u8 ocarinaChoice = 0; +u8 videoChoice = 0; +u8 languageChoice = 0; +u8 viChoice = 0; +u8 iosChoice = 0; +u8 parentalcontrolChoice = 0; + +#define TITLE_MAX 65 + +struct ID_Title +{ + u8 id[5]; + char title[TITLE_MAX]; + u8 block; +}; + +// renamed titles +int num_title = 0; //number of titles +struct ID_Title *cfg_title = NULL; + +#define MAX_SAVED_GAMES 1000 +int num_saved_games = 0; +struct Game_CFG cfg_game[MAX_SAVED_GAMES]; + + +/* For Mapping */ + +static char *cfg_name, *cfg_val; + +struct TextMap +{ + char *name; + int id; +}; + +struct TextMap map_video[] = +{ + { "system", CFG_VIDEO_SYS }, + { "game", CFG_VIDEO_GAME }, + { "patch", CFG_VIDEO_PATCH }, + { "pal50", CFG_VIDEO_PAL50 }, + { "pal60", CFG_VIDEO_PAL60 }, + { "ntsc", CFG_VIDEO_NTSC }, + { NULL, -1 } +}; + +struct TextMap map_language[] = +{ + { "console", CFG_LANG_CONSOLE }, + { "japanese", CFG_LANG_JAPANESE }, + { "english", CFG_LANG_ENGLISH }, + { "german", CFG_LANG_GERMAN }, + { "french", CFG_LANG_FRENCH }, + { "spanish", CFG_LANG_SPANISH }, + { "italian", CFG_LANG_ITALIAN }, + { "dutch", CFG_LANG_DUTCH }, + { "s.chinese", CFG_LANG_S_CHINESE }, + { "t.chinese", CFG_LANG_T_CHINESE }, + { "korean", CFG_LANG_KOREAN }, + { NULL, -1 } +}; + + +struct TextMap map_alignment[] = +{ + { "left", CFG_ALIGN_LEFT }, + { "right", CFG_ALIGN_RIGHT }, + { "center", CFG_ALIGN_CENTRE }, + { "top", CFG_ALIGN_TOP }, + { "bottom", CFG_ALIGN_BOTTOM }, + { "middle", CFG_ALIGN_MIDDLE }, + { NULL, -1 } +}; + +int map_get_id(struct TextMap *map, char *name) +{ + int i; + for (i=0; map[i].name != NULL; i++) { + if (strcmp(name, map[i].name) == 0) return map[i].id; + } + return -1; +} + +char* map_get_name(struct TextMap *map, short id) +{ + int i; + for (i=0; map[i].name != NULL; i++) { + if (id == map[i].id) return map[i].name; + } + return NULL; +} + +bool map_auto(char *name, char *name2, char *val, struct TextMap *map, short *var) +{ + if (strcmp(name, name2) != 0) return false; + int id = map_get_id(map, val); + if (id == -1) { + //printf("MAP FAIL: %s=%s : %d\n", name, val, id); sleep(1); + return false; + } + *var = id; + //printf("MAP AUTO: %s=%s : %d\n", name, val, id); sleep(1); + return true; +} + +bool cfg_map_auto(char *name, struct TextMap *map, short *var) +{ + return map_auto(name, cfg_name, cfg_val, map, var); +} + +bool cfg_map(char *name, char *val, short *var, short id) +{ + if (strcmp(name, cfg_name)==0 && strcmpi(val, cfg_val)==0) + { + *var = id; + return true; + } + return false; +} + +bool cfg_bool(char *name, short *var) +{ + return (cfg_map(name, "0", var, 0) || cfg_map(name, "1", var, 1)); +} + +void cfg_int(char *name, short *var, int count) +{ + char tmp[5]; + short i; + + if (count > 10) //avoid overflow + return; + + for (i = 0; i < count; i++) + { + sprintf(tmp, "%d", i); + cfg_map(name, tmp, var, i); + } +} + +/* Mapping */ + +//static char bg_path[100]; + +void CFG_Default() +{ + CFG.widescreen = CONF_GetAspectRatio(); + + if (CFG.widescreen) { + snprintf(CFG.theme_path, sizeof(CFG.theme_path), "SD:/wtheme/"); + } + else + { + snprintf(CFG.theme_path, sizeof(CFG.theme_path), "SD:/theme/"); + } +// CFG.simple = 0; +// CFG.video = CFG_VIDEO_DEFAULT; +// CFG.home = CFG_HOME_REBOOT; +// CFG.download = 0; +// CFG.language = CFG_LANG_CONSOLE; +// CFG.ocarina = 0; +// CFG.vipatch = 0; +// CFG.savesettings = 0; + CFG.parentalcontrol = 0; + CFG.maxcharacters = 38; + CFG.godmode = 0; +// CFG.installdownload = 0; +// CFG.hidesettingmenu = 0; + snprintf(CFG.covers_path, sizeof(CFG.covers_path), "SD:/images/"); + snprintf(CFG.disc_path, sizeof(CFG.disc_path), "SD:/images/disc/"); + snprintf(CFG.unlockCode, sizeof(CFG.unlockCode), "ab121b"); + + //all alignments are left top here + THEME.selection_x = 200; + THEME.selection_y = 40; + THEME.selection_w = 396; + THEME.selection_h = 280; + THEME.cover_x = 26; + THEME.cover_y = 55; + THEME.showID = 1; + THEME.id_x = 68; + THEME.id_y = 305; + THEME.region_x = 68; + THEME.region_y = 30; + THEME.power_x = 576; + THEME.power_y = 355; + THEME.home_x = 485;//215; + THEME.home_y = 367; + THEME.setting_x = 60;//-210 + THEME.setting_y = 367; + THEME.showHDD = -1; //default, non-force mode + THEME.showGameCnt = -1; //default, non-force mode + THEME.showToolTip = 1; //1 means use settings, 0 means force turn off + THEME.install_x = 16;//-280 + THEME.install_y = 355; + THEME.showBattery = 1; + THEME.showRegion = 1; + THEME.hddInfo_x = 0; + THEME.hddInfo_y = 330; + THEME.hddInfoAlign = CFG_ALIGN_CENTRE; + THEME.gameCnt_x = 0; + THEME.gameCnt_y = 350; + THEME.gameCntAlign = CFG_ALIGN_CENTRE; + THEME.battery1_x = 245; + THEME.battery1_y = 400; + THEME.battery2_x = 335; + THEME.battery2_y = 400; + THEME.battery3_x = 245; + THEME.battery3_y = 425; + THEME.battery4_x = 335; + THEME.battery4_y = 425; + THEME.info_r = 63; + THEME.info_g = 154; + THEME.info_b = 192; + THEME.clock_x = 0; + THEME.clock_y = -120; + THEME.clockAlign = CFG_ALIGN_CENTRE; + THEME.sdcard_x = 160; + THEME.sdcard_y = 390; + +} + + +char* strcopy(char *dest, char *src, int size) +{ + strncpy(dest,src,size); + dest[size-1] = 0; + return dest; +} + +char *cfg_get_title(u8 *id) +{ + int i; + for (i=0; iid); + if (title) return title; + return header->title; +} + +void title_set(char *id, char *title, u8 block) +{ + char *idt = cfg_get_title((u8*)id); + if (idt) { + // replace + strcopy(idt, title, TITLE_MAX); + } else { + cfg_title = realloc(cfg_title, (num_title+1) * sizeof(struct ID_Title)); + if (!cfg_title) { + // error + num_title = 0; + return; + } + // add + memcpy(cfg_title[num_title].id, id, 4); + cfg_title[num_title].id[4] = 0; + cfg_title[num_title].block = block; + strcopy(cfg_title[num_title].title, title, TITLE_MAX); + num_title++; + } +} + +u8 cfg_get_block(u8 *id) +{ + int i; + for (i=0; iid); +} + +// trim leading and trailing whitespace +// copy at max n or at max size-1 +char* trim_n_copy(char *dest, char *src, int n, int size) +{ + int len; + // trim leading white space + while (isspace(*src)) { src++; n--; } + len = strlen(src); + if (len > n) len = n; + // trim trailing white space + while (len > 0 && isspace(src[len-1])) len--; + if (len >= size) len = size-1; + strncpy(dest, src, len); + dest[len] = 0; + //printf("trim_copy: '%s' %d\n", dest, len); //sleep(1); + return dest; +} + +char* trimcopy(char *dest, char *src, int size) +{ + int len; + while (*src == ' ') src++; + len = strlen(src); + // trim trailing " \r\n" + while (len > 0 && strchr(" \r\n", src[len-1])) len--; + if (len >= size) len = size-1; + strncpy(dest, src, len); + dest[len] = 0; + return dest; +} + +void widescreen_set(char *name, char *val) +{ + cfg_name = name; + cfg_val = val; + + if (cfg_bool("widescreen", &CFG.widescreen)) //reset default + { + if (CFG.widescreen) { +// snprintf(CFG.covers_path, sizeof(CFG.covers_path), "SD:/wimages/"); + snprintf(CFG.theme_path, sizeof(CFG.theme_path), "SD:/wtheme/"); + } + else + { +// snprintf(CFG.covers_path, sizeof(CFG.covers_path), "SD:/images/"); + snprintf(CFG.theme_path, sizeof(CFG.theme_path), "SD:/theme/"); + } + } +} + + + +void cfg_set(char *name, char *val) +{ + cfg_name = name; + cfg_val = val; +/* + if (!CFG.widescreen &&(strcmp(name, "images_path") == 0)) { + strcopy(CFG.images_path, val, sizeof(CFG.images_path)); + snprintf(bg_path, sizeof(bg_path), "%sbg.png", CFG.images_path); //reset path + return; + } + + if (CFG.widescreen && strcmp(name, "wimages_path") == 0) { + strcopy(CFG.images_path, val, sizeof(CFG.images_path)); + snprintf(bg_path, sizeof(bg_path), "%swbg.png", CFG.images_path); //reset path + return; + } + + if (cfg_map_auto("video", map_video, &CFG.video)) + return; + + if (cfg_map_auto("language", map_language, &CFG.language)) + return; + + if (cfg_map_auto("layout", map_layout, &CFG.layout)) { + cfg_layout(); + } + + cfg_bool("ocarina", &CFG.ocarina); + cfg_bool("covers", &CFG.covers); + cfg_bool("download", &CFG.download); + cfg_bool("savesettings", &CFG.savesettings); + cfg_bool("installdownload", &CFG.installdownload); + cfg_bool("hidesettingmenu", &CFG.hidesettingmenu); + cfg_map("home", "exit", &CFG.home, CFG_HOME_EXIT); + cfg_map("home", "reboot", &CFG.home, CFG_HOME_REBOOT); + cfg_int("simple", &CFG.simple, 3); +*/ + if (!CFG.widescreen &&(strcmp(name, "theme_path") == 0)) { + strcopy(CFG.theme_path, val, sizeof(CFG.theme_path)); + return; + } + + if (CFG.widescreen && strcmp(name, "wtheme_path") == 0) { + strcopy(CFG.theme_path, val, sizeof(CFG.theme_path)); + return; + } + + if (strcmp(name, "cover_path") == 0) { + strcopy(CFG.covers_path, val, sizeof(CFG.covers_path)); + return; + } + + if (strcmp(name, "disc_path") == 0) { + strcopy(CFG.disc_path, val, sizeof(CFG.disc_path)); + return; + } + + cfg_int("parentalcontrol", &CFG.parentalcontrol, 4); + cfg_bool("godmode", &CFG.godmode); + + if (strcmp(name, "unlock_code") == 0) { + strcopy(CFG.unlockCode, val, sizeof(CFG.unlockCode)); + return; + } +} + +void theme_set(char *name, char *val) +{ + cfg_name = name; + cfg_val = val; + + if(strcmp(cfg_name, "gamelist_coords") == 0) { + int x,y,w,h; + if (sscanf(val, "%d,%d,%d,%d", &x, &y, &w, &h) == 4) { + THEME.selection_x = x - (x % 4); + THEME.selection_y = y; + THEME.selection_w = w; + THEME.selection_h = h; + } + } + + else if (strcmp(cfg_name, "covers_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.cover_x = x - (x % 4); + THEME.cover_y = y; + } + } + + else if (strcmp(cfg_name, "id_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.id_x = x - (x % 4); + THEME.id_y = y; + } + } + + else if (strcmp(cfg_name, "hddinfo_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.hddInfo_x = x - (x % 4); + THEME.hddInfo_y = y; + } + } + + else if (strcmp(cfg_name, "gamecount_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.gameCnt_x = x - (x % 4); + THEME.gameCnt_y = y; + } + } + + else if (strcmp(cfg_name, "region_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.region_x = x - (x % 4); + THEME.region_y = y; + } + } + + else if (strcmp(cfg_name, "power_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.power_x = x - (x % 4); + THEME.power_y = y; + } + } + + else if (strcmp(cfg_name, "home_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.home_x = x - (x % 4); + THEME.home_y = y; + } + } + + else if (strcmp(cfg_name, "setting_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.setting_x = x - (x % 4); + THEME.setting_y = y; + } + } + + else if (strcmp(cfg_name, "install_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.install_x = x - (x % 4); + THEME.install_y = y; + } + } + + else if (strcmp(cfg_name, "battery1_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.battery1_x = x - (x % 4); + THEME.battery1_y = y; + } + } + + else if (strcmp(cfg_name, "battery2_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.battery2_x = x - (x % 4); + THEME.battery2_y = y; + } + } + + else if (strcmp(cfg_name, "battery3_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.battery3_x = x - (x % 4); + THEME.battery3_y = y; + } + } + + else if (strcmp(cfg_name, "battery4_coords") == 0) { + int x,y; + if (sscanf(val, "%d,%d", &x, &y) == 2) { + THEME.battery4_x = x - (x % 4); + THEME.battery4_y = y; + } + } + + else if (strcmp(cfg_name, "clock_coords") == 0) { + short x,y; + if (sscanf(val, "%hd,%hd", &x, &y) == 2) { + THEME.clock_x = x - (x % 4); + THEME.clock_y = y; + } + } + + else if (strcmp(cfg_name, "sdcard_coords") == 0) { + short x,y; + if (sscanf(val, "%hd,%hd", &x, &y) == 2) { + THEME.sdcard_x = x - (x % 4); + THEME.sdcard_y = y; + } + } + + else if (strcmp(cfg_name, "info_color") == 0) { + short x,y,z; + if (sscanf(val, "%hd,%hd, %hd", &x, &y, &z) == 3) { + THEME.info_r = x; + THEME.info_g = y; + THEME.info_b = z; + } + } + + cfg_bool("show_id", &THEME.showID); + cfg_bool("show_tooltip", &THEME.showToolTip); + cfg_bool("show_hddinfo", &THEME.showHDD); + cfg_bool("show_gamecount", &THEME.showGameCnt); + cfg_bool("show_region", &THEME.showRegion); + cfg_bool("show_battery", &THEME.showBattery); + cfg_map_auto("hddinfo_align", map_alignment, &THEME.hddInfoAlign); + cfg_map_auto("gamecount_align", map_alignment, &THEME.gameCntAlign); + cfg_map_auto("clock_align", map_alignment, &THEME.clockAlign); + + /* + else if (strcmp(cfg_name, "entry_lines") == 0) { + int x; + if (sscanf(val, "%d", &x) == 1) { + ENTRIES_PER_PAGE = x; + } + } + + else if (strcmp(cfg_name, "max_characters") == 0) { + int x; + if (sscanf(val, "%d", &x) == 1) { + MAX_CHARACTERS = x; + } + }*/ +} + +void global_cfg_set(char *name, char *val) +{ + cfg_name = name; + cfg_val = val; + + if (strcmp(name, "video") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.video = i; + } + return; + } + else if (strcmp(name, "vpatch") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.vpatch =i; + } + return; + } + + else if (strcmp(name, "language") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.language = i; + } + return; + } + else if (strcmp(name, "ocarina") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.ocarina = i; + } + return; + } + else if (strcmp(name, "hddinfo") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.hddinfo = i; + } + return; + } + else if (strcmp(name, "sinfo") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.sinfo = i; + } + return; + } + else if (strcmp(name, "rumble") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.rumble = i; + } + return; + } + else if (strcmp(name, "volume") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.volume = i; + } + return; + } + else if (strcmp(name, "tooltips") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.tooltips = i; + } + return; + } + else if (strcmp(name, "password") == 0) { + strcopy(Settings.unlockCode, val, sizeof(Settings.unlockCode)); + return; + } + else if (strcmp(name, "parentalcontrol") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.parentalcontrol = i; + } + return; + } + else if (strcmp(name, "cios") == 0) { + int i; + if (sscanf(val, "%d", &i) == 1) { + Settings.cios = i; + } + return; + } +} + +// split line to part1 delimiter part2 +bool trimsplit(char *line, char *part1, char *part2, char delim, int size) +{ + char *eq = strchr(line, delim); + if (!eq) return false; + trim_n_copy(part1, line, eq-line, size); + trimcopy(part2, eq+1, size); + return true; +} +void cfg_parseline(char *line, void (*set_func)(char*, char*)) +{ + // split name = value + char tmp[200], name[100], val[100]; + strcopy(tmp, line, sizeof(tmp)); + char *eq = strchr(tmp, '='); + if (!eq) return; + *eq = 0; + trimcopy(name, tmp, sizeof(name)); + trimcopy(val, eq+1, sizeof(val)); + //printf("CFG: %s = %s\n", name, val); + set_func(name, val); +} + +void cfg_parsetitleline(char *line, void (*set_func)(char*, char*, u8)) +{ + // split name = value + char tmp[200], name[100], val[100]; + int block = 0; + strcopy(tmp, line, sizeof(tmp)); + char *eq = strchr(tmp, '='); + if (!eq) return; + *eq = 0; + trimcopy(name, tmp, sizeof(name)); + + char *blockpos = strrchr(eq+1, '='); + + if (!blockpos) + trimcopy(val, eq+1, sizeof(val)); + + else + { + *blockpos = 0; + trimcopy(val, eq+1, sizeof(val)); + if (sscanf(blockpos+1, "%d", &block) != 1) + { + block = 0; + } + } + set_func(name, val, block); +} + +bool cfg_parsefile(char *fname, void (*set_func)(char*, char*)) +{ + FILE *f; + char line[200]; + + //printf("opening(%s)\n", fname); + f = fopen(fname, "rb"); + if (!f) { + //printf("error opening(%s)\n", fname); + return false; + } + + while (fgets(line, sizeof(line), f)) { + // lines starting with # are comments + if (line[0] == '#') continue; + cfg_parseline(line, set_func); + } + return true; +} + +bool cfg_parsetitlefile(char *fname, void (*set_func)(char*, char*, u8)) +{ + FILE *f; + char line[200]; + + //printf("opening(%s)\n", fname); + f = fopen(fname, "rb"); + if (!f) { + //printf("error opening(%s)\n", fname); + return false; + } + + while (fgets(line, sizeof(line), f)) { + // lines starting with # are comments + if (line[0] == '#') continue; + cfg_parsetitleline(line, set_func); + } + return true; +} + +/* +void cfg_parsearg(int argc, char **argv) +{ + int i; + char *eq; + char pathname[200]; + for (i=1; ivideo = opt_v; + } + if (map_auto("language", opt_name, opt_val, map_language, &opt_l)) { + // valid option, assign + game->language = opt_l; + } + if (strcmp("ocarina", opt_name) == 0) { + if (sscanf(opt_val, "%hd", &opt_c) == 1) { + game->ocarina = opt_c; + } + } + if (strcmp("vipatch", opt_name) == 0) { + if (sscanf(opt_val, "%hd", &opt_c) == 1) { + game->vipatch = opt_c; + } + } + if (strcmp("ios", opt_name) == 0) { + if (sscanf(opt_val, "%hd", &opt_c) == 1) { + game->ios = opt_c; + } + } + if (strcmp("pctrl", opt_name) == 0) { + if (sscanf(opt_val, "%hd", &opt_c) == 1) { + game->parentalcontrol = opt_c; + } + } + } + // next opt + if (np) p = np + 1; else p = NULL; + } +} + +bool cfg_load_games() +{ + return cfg_parsefile("SD:/config/settings.cfg", &game_set); +} + +bool cfg_save_games() +{ + FILE *f; + int i; + mkdir("SD:/config/", 0777); + f = fopen("SD:/config/settings.cfg", "wb"); + if (!f) { + printf("Error saving %s\n", "settings.cfg"); + sleep(1); + return false; + } + fprintf(f, "# USB Loader settings file\n"); + fprintf(f, "# note: this file is automatically generated\n"); + fprintf(f, "# Num Games: %d\n", num_saved_games); + for (i=0; i +#include "disc.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define CFG_HOME_REBOOT 0 +#define CFG_HOME_EXIT 1 + +#define CFG_VIDEO_SYS 0 // system default +#define CFG_VIDEO_DEFAULT 1 +#define CFG_VIDEO_GAME 1 // game default +#define CFG_VIDEO_PATCH 2 // patch mode +#define CFG_VIDEO_PAL50 3 // force PAL +#define CFG_VIDEO_PAL60 4 // force PAL60 +#define CFG_VIDEO_NTSC 5 // force NTSC +#define CFG_VIDEO_COUNT 6 + +#define CFG_LANG_CONSOLE 0 +#define CFG_LANG_JAPANESE 1 +#define CFG_LANG_ENGLISH 2 +#define CFG_LANG_GERMAN 3 +#define CFG_LANG_FRENCH 4 +#define CFG_LANG_SPANISH 5 +#define CFG_LANG_ITALIAN 6 +#define CFG_LANG_DUTCH 7 +#define CFG_LANG_S_CHINESE 8 +#define CFG_LANG_T_CHINESE 9 +#define CFG_LANG_KOREAN 10 +#define CFG_LANG_COUNT 11 + +#define CFG_ALIGN_LEFT 0 +#define CFG_ALIGN_RIGHT 1 +#define CFG_ALIGN_CENTRE 2 +#define CFG_ALIGN_TOP 3 +#define CFG_ALIGN_BOTTOM 4 +#define CFG_ALIGN_MIDDLE 5 + +extern char *cfg_path; +//extern char *cfg_images_path; + +struct CFG +{ +// char *background; +// short covers; +// short simple; +// short video; +// short language; +// short ocarina; +// short vipatch; +// short home; +// short download; +// short installdownload; +// short hidesettingmenu; +// short savesettings; + short widescreen; + short parentalcontrol; + short maxcharacters; + short godmode; + char unlockCode[20]; + char covers_path[100]; + char theme_path[100]; + char disc_path[100]; +}; + +struct THEME +{ + int selection_x; + int selection_y; + int selection_w; + int selection_h; + int cover_x; + int cover_y; + short showID; + int id_x; + int id_y; + int region_x; + int region_y; + int power_x; + int power_y; + int home_x; + int home_y; + int battery1_x; + int battery2_x; + int battery3_x; + int battery4_x; + int battery1_y; + int battery2_y; + int battery3_y; + int battery4_y; +// short showPower; +// short showHome; + int setting_x; + int setting_y; + int install_x; + int install_y; + short showHDD; + short hddInfoAlign; + int hddInfo_x; + int hddInfo_y; + short showGameCnt; + short gameCntAlign; + int gameCnt_x; + int gameCnt_y; + short showRegion; + short showBattery; + short showToolTip; + //color + short info_r; + short info_g; + short info_b; + short clock_x; + short clock_y; + short clockAlign; + int sdcard_x; + int sdcard_y; +}; + +extern struct CFG CFG; +extern struct THEME THEME; +extern u8 ocarinaChoice; +extern u8 videoChoice; +extern u8 languageChoice; +extern u8 viChoice; +extern u8 iosChoice; +extern u8 parentalcontrolChoice; + +struct Game_CFG +{ + u8 id[8]; + u8 video; + u8 language; + u8 ocarina; + u8 vipatch; + u8 ios; + u8 parentalcontrol; +}; + + +void CFG_Default(); +void CFG_Load(int argc, char **argv); +struct Game_CFG* CFG_get_game_opt(u8 *id); +bool CFG_save_game_opt(u8 *id); +bool CFG_forget_game_opt(u8 *id); + +//Astidof - Begin of modification +enum { + ConsoleLangDefault, + jap, + eng, + ger, + fren, + esp, + it, + dut, + schin, + tchin, + kor +}; + +enum { + systemdefault, + discdefault, + patch, + pal50, + pal60, + ntsc +}; + +enum { + off, + on, +}; + +enum { + GameID, + GameRegion, + Both, + Neither, +}; + +enum { + i249, + i222, +}; + +enum { + ios249, + ios222, +}; + +enum { + HDDInfo, + Clock, +}; + +enum { + RumbleOff, + RumbleOn, +}; + +enum { + TooltipsOff, + TooltipsOn, +}; + +enum { + v10, + v20, + v30, + v40, + v50, + v60, + v70, + v80, + v90, + v100, + v0, +}; + +enum { + ParentalControlOff, + ParentalControlLevel1, + ParentalControlLevel2, + ParentalControlLevel3 +}; + +struct SSettings { + int video; + int language; + int ocarina; + int vpatch; + int sinfo; + int hddinfo; + int rumble; + int volume; + int tooltips; + char unlockCode[20]; + int parentalcontrol; + int cios; +}; + +void CFG_LoadGlobal(void); +bool cfg_save_global(void); +//Astidof - End of modification + +char *get_title(struct discHdr *header); +u8 get_block(struct discHdr *header); + +void CFG_Cleanup(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/disc.c b/source/disc.c new file mode 100644 index 00000000..19a48097 --- /dev/null +++ b/source/disc.c @@ -0,0 +1,310 @@ +#include +#include +#include +#include +#include +#include + + +#include "apploader.h" +#include "disc.h" +#include "video.h" +#include "wdvd.h" +#include "fst.h" + +/* Constants */ +#define PTABLE_OFFSET 0x40000 +#define WII_MAGIC 0x5D1C9EA3 + +/* Disc pointers */ +static u32 *buffer = (u32 *)0x93000000; +static u8 *diskid = (u8 *)0x80000000; +static char gameid[8]; + + +void __Disc_SetLowMem(void) +{ + /* Setup low memory */ + *(vu32 *)0x80000030 = 0x00000000; + *(vu32 *)0x80000060 = 0x38A00040; + *(vu32 *)0x800000E4 = 0x80431A80; + *(vu32 *)0x800000EC = 0x81800000; + *(vu32 *)0x800000F4 = 0x817E5480; + *(vu32 *)0x800000F8 = 0x0E7BE2C0; + *(vu32 *)0x800000FC = 0x2B73A840; + + /* Copy disc ID */ + memcpy((void *)0x80003180, (void *)0x80000000, 4); + + /* Flush cache */ + DCFlushRange((void *)0x80000000, 0x3F00); +} + +void __Disc_SetVMode(u8 videoselected) +{ + GXRModeObj *vmode = NULL; + + u32 progressive, tvmode, vmode_reg = 0; + + /* Get video mode configuration */ + progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable(); + tvmode = CONF_GetVideo(); + + /* Select video mode register */ + switch (tvmode) { + case CONF_VIDEO_PAL: + vmode_reg = (CONF_GetEuRGB60() > 0) ? 5 : 1; + break; + + case CONF_VIDEO_MPAL: + vmode_reg = 4; + break; + + case CONF_VIDEO_NTSC: + vmode_reg = 0; + break; + } + + switch (videoselected) { + case 0: + + /* Select video mode */ + switch(diskid[3]) { + /* PAL */ + case 'D': + case 'F': + case 'P': + case 'X': + case 'Y': + if (tvmode != CONF_VIDEO_PAL) { + vmode_reg = 5; + vmode = (progressive) ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf; + } + + break; + + /* NTSC or unknown */ + case 'E': + case 'J': + if (tvmode != CONF_VIDEO_NTSC) { + vmode_reg = 0; + vmode = (progressive) ? &TVNtsc480Prog : &TVNtsc480IntDf; + } + + break; + } + break; + + case 1: + vmode_reg = 1; + progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable(); + vmode = (progressive) ? &TVEurgb60Hz480Prog : &TVPal528IntDf; + break; + case 2: + vmode_reg = 5; + progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable(); + vmode = (progressive) ? &TVEurgb60Hz480Prog : &TVEurgb60Hz480IntDf; + break; + case 3: + vmode_reg = 0; + progressive = (CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable(); + vmode = (progressive) ? &TVNtsc480Prog : &TVNtsc480IntDf; + break; + case 4: + // vmode = VIDEO_GetPreferredMode(NULL); + break; + } + + /* Set video mode register */ + *(vu32 *)0x800000CC = vmode_reg; + + /* Set video mode */ + if (vmode) { + + VIDEO_Configure(vmode); + + /* Setup video */ + VIDEO_SetBlack(FALSE); + VIDEO_Flush(); + VIDEO_WaitVSync(); + + if (vmode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync(); + } +} + +void __Disc_SetTime(void) +{ + /* Extern */ + extern void settime(long long); + + /* Set proper time */ + settime(secs_to_ticks(time(NULL) - 946684800)); +} + +s32 __Disc_FindPartition(u64 *outbuf) +{ + u64 offset = 0, table_offset = 0; + + u32 cnt, nb_partitions; + s32 ret; + + /* Read partition info */ + ret = WDVD_UnencryptedRead(buffer, 0x20, PTABLE_OFFSET); + if (ret < 0) + return ret; + + /* Get data */ + nb_partitions = buffer[0]; + table_offset = buffer[1] << 2; + + /* Read partition table */ + ret = WDVD_UnencryptedRead(buffer, 0x20, table_offset); + if (ret < 0) + return ret; + + /* Find game partition */ + for (cnt = 0; cnt < nb_partitions; cnt++) { + u32 type = buffer[cnt * 2 + 1]; + + /* Game partition */ + if(!type) + offset = buffer[cnt * 2] << 2; + } + + /* No game partition found */ + if (!offset) + return -1; + + /* Set output buffer */ + *outbuf = offset; + + return 0; +} + + +s32 Disc_Init(void) +{ + /* Init DVD subsystem */ + return WDVD_Init(); +} + +s32 Disc_Open(void) +{ + s32 ret; + + /* Reset drive */ + ret = WDVD_Reset(); + if (ret < 0) + return ret; + + /* Read disc ID */ + return WDVD_ReadDiskId(diskid); +} + +s32 Disc_Wait(void) +{ + u32 cover = 0; + s32 ret; + + /* Wait for disc */ + while (!(cover & 0x2)) { + /* Get cover status */ + ret = WDVD_GetCoverStatus(&cover); + if (ret < 0) + return ret; + } + + return 0; +} + +s32 Disc_SetUSB(u8 *id, int ios222) +{ + /* Set USB mode */ + return WDVD_SetUSBMode(id, ios222); +} + +s32 Disc_ReadHeader(void *outbuf) +{ + /* Read disc header */ + return WDVD_UnencryptedRead(outbuf, sizeof(struct discHdr), 0); +} + +s32 Disc_IsWii(void) +{ + struct discHdr *header = (struct discHdr *)buffer; + + s32 ret; + + /* Read disc header */ + ret = Disc_ReadHeader(header); + if (ret < 0) + return ret; + + /* Check magic word */ + if (header->magic != WII_MAGIC) + return -1; + + return 0; +} + +s32 Disc_BootPartition(u64 offset, u8 videoselected, u8 cheat, u8 vipatch) +{ + entry_point p_entry; + + s32 ret; + + /* Open specified partition */ + ret = WDVD_OpenPartition(offset); + if (ret < 0) + return ret; + + /* Run apploader */ + ret = Apploader_Run(&p_entry, cheat, videoselected, vipatch); + if (ret < 0) + return ret; + + /* Setup low memory */ + __Disc_SetLowMem(); + + /* Set an appropiate video mode */ + __Disc_SetVMode(videoselected); + + /* Set time */ + __Disc_SetTime(); + + if (cheat == 1) { + /* OCARINA STUFF - FISHEARS*/ + memset(gameid, 0, 8); + memcpy(gameid, (char*)0x80000000, 6); + do_sd_code(gameid); + /* OCARINA STUFF - FISHEARS*/ + } + + /* Disconnect Wiimote */ + WPAD_Flush(0); + WPAD_Disconnect(0); + WPAD_Shutdown(); + + /* Shutdown IOS subsystems */ + SYS_ResetSystem(SYS_SHUTDOWN, 0, 0); + + /* Jump to entry point */ + p_entry(); + + return 0; +} + +s32 Disc_WiiBoot(u8 videoselected, u8 cheat, u8 vipatch) +{ + u64 offset; + s32 ret; + + /* Find game partition offset */ + ret = __Disc_FindPartition(&offset); + if (ret < 0) + return ret; + + /* Boot partition */ + return Disc_BootPartition(offset, videoselected, cheat, vipatch); +} diff --git a/source/disc.h b/source/disc.h new file mode 100644 index 00000000..f9f4aa2f --- /dev/null +++ b/source/disc.h @@ -0,0 +1,58 @@ +#ifndef _DISC_H_ +#define _DISC_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +/* Disc header structure */ +struct discHdr +{ + /* Game ID */ + u8 id[6]; + + /* Game version */ + u16 version; + + /* Audio streaming */ + u8 streaming; + u8 bufsize; + + /* Padding */ + u8 unused1[14]; + + /* Magic word */ + u32 magic; + + /* Padding */ + u8 unused2[4]; + + /* Game title */ + char title[64]; + + /* Encryption/Hashing */ + u8 encryption; + u8 h3_verify; + + /* Padding */ + u8 unused3[30]; +} ATTRIBUTE_PACKED; + +/* Prototypes */ +s32 Disc_Init(void); +s32 Disc_Open(void); +s32 Disc_Wait(void); +void __Disc_SetLowMem(void); +s32 Disc_SetUSB(u8 *, int ios222); +s32 Disc_ReadHeader(void *); +s32 Disc_IsWii(void); +s32 Disc_BootPartition(u64, u8, u8, u8); +s32 Disc_WiiBoot(u8, u8, u8); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/dns.c b/source/dns.c new file mode 100644 index 00000000..91fc1dea --- /dev/null +++ b/source/dns.c @@ -0,0 +1,122 @@ +#include "dns.h" + +/** + * Resolves a domainname to an ip address + * It makes use of net_gethostbyname from libogc, which in turn makes use of a Wii BIOS function + * Just like the net_gethostbyname function this function is NOT threadsafe! + * + * @param char* The domain name to resolve + * @return u32 The ipaddress represented by four bytes inside an u32 (in network order) + */ +u32 getipbyname(char *domain) +{ + //Care should be taken when using net_gethostbyname, + //it returns a static buffer which makes it not threadsafe + //TODO: implement some locking mechanism to make below code atomic + struct hostent *host = net_gethostbyname(domain); + + if(host == NULL) { + return 0; + } + + u32 *ip = (u32*)host->h_addr_list[0]; + return *ip; +} + + + +//Defines how many DNS entries should be cached by getipbynamecached() +#define MAX_DNS_CACHE_ENTRIES 20 + +//The cache is defined as a linked list, +//The last resolved domain name will always be at the front +//This will allow heavily used domainnames to always stay cached +struct dnsentry { + char *domain; + u32 ip; + struct dnsentry *nextnode; +} ; + +static struct dnsentry *firstdnsentry = NULL; +static int dnsentrycount = 0; + +/** + * Performs the same function as getipbyname(), + * except that it will prevent extremely expensive net_gethostbyname() calls by caching the result + */ +u32 getipbynamecached(char *domain) +{ + //Search if this domainname is already cached + struct dnsentry *node = firstdnsentry; + struct dnsentry *previousnode = NULL; + + while(node != NULL) + { + if(strcmp(node->domain, domain) == 0) + { + //DNS node found in the cache, move it to the front of the list + if(previousnode != NULL) + previousnode->nextnode = node->nextnode; + + if(node != firstdnsentry) + node->nextnode = firstdnsentry; + firstdnsentry = node; + + return node->ip; + } + //Go to the next element in the list + previousnode = node; + node = node->nextnode; + } + u32 ip = getipbyname(domain); + + //No cache of this domain could be found, create a cache node and add it to the front of the cache + struct dnsentry *newnode = malloc(sizeof(struct dnsentry)); + if(newnode == NULL) { + return ip; + } + + newnode->ip = ip; + newnode->domain = malloc(strlen(domain)+1); + if(newnode->domain == NULL) + { + free(newnode); + return ip; + } + strcpy(newnode->domain, domain); + + newnode->nextnode = firstdnsentry; + firstdnsentry = newnode; + dnsentrycount++; + + //If the cache grows too big delete the last (and probably least important) node of the list + if(dnsentrycount > MAX_DNS_CACHE_ENTRIES) + { + struct dnsentry *node = firstdnsentry; + struct dnsentry *previousnode = NULL; + + //Fetch the last two elements of the list + while(node->nextnode != NULL) + { + previousnode = node; + node = node->nextnode; + } + + if(node == NULL) + { + printf("Configuration error, MAX_DNS_ENTRIES reached while the list is empty\n"); + exit(1); + } else if(previousnode == NULL) + { + firstdnsentry = NULL; + } else { + previousnode->nextnode = NULL; + } + + free(node->domain); + free(node); + dnsentrycount--; + } + + return newnode->ip; +} diff --git a/source/dns.h b/source/dns.h new file mode 100644 index 00000000..28617246 --- /dev/null +++ b/source/dns.h @@ -0,0 +1,23 @@ +#ifndef _DNS_H_ +#define _DNS_H_ + +#include +#include +#include +#include + +#include //usleep + +#ifdef __cplusplus +extern "C" +{ +#endif + +u32 getipbyname(char *domain); +u32 getipbynamecached(char *domain); + +#ifdef __cplusplus +} +#endif + +#endif /* _DNS_H_ */ diff --git a/source/dvd_broadway.c b/source/dvd_broadway.c new file mode 100644 index 00000000..16e6a9e9 --- /dev/null +++ b/source/dvd_broadway.c @@ -0,0 +1,612 @@ +/* + * Copyright (C) 2008 Nuke (wiinuke@gmail.com) + * + * this file is part of GeckoOS for USB Gecko + * http://www.usbgecko.com + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvd_broadway.h" + +#define DI_CMDCTX_CNT 4 + +#define DVD_DISKIDSIZE 0x20 +#define DVD_DRVINFSIZE 0x20 + +#define IOCTL_DI_INQUIRY 0x12 +#define IOCTL_DI_READID 0x70 +#define IOCTL_DI_READ 0x71 +#define IOCTL_DI_WAITCVRCLOSE 0x79 +#define IOCTL_DI_COVER 0x7A +#define IOCTL_DI_RESETNOTIFY 0x7E +#define IOCTL_DI_RESET 0x8A +#define IOCTL_DI_OPENPART 0x8B +#define IOCTL_DI_CLOSEPART 0x8C +#define IOCTL_DI_UNENCREAD 0x8D +#define IOCTL_DI_ENABLE_DVD 0x8E +#define IOCTL_DI_SEEK 0xAB +#define IOCTL_DI_READ_DVDVIDEO 0xD0 +#define IOCTL_DI_STOPLASER 0xD2 +#define IOCTL_DI_OFFSET 0xD9 +#define IOCTL_DI_REQERROR 0xE0 +#define IOCTL_DI_STOPMOTOR 0xE3 +#define IOCTL_DI_SETOFFBASE 0xF0 +#define IOCTL_DI_GETOFFBASE 0xF1 +#define IOCTL_DI_SETCRYPTMODE 0xF2 +#define IOCTL_DI_GETCRYPTMODE 0xF3 +#define IOCTL_DI_SETDVDROMMODE 0xF4 +#define IOCTL_DI_GETDVDROMMODE 0xF5 + +#define _SHIFTL(v, s, w) \ + ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s))) +#define _SHIFTR(v, s, w) \ + ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1))) + +struct dicommand +{ + u32 diReg[8]; +}; + +struct dicontext +{ + lwp_node node; + dvdcallbacklow cb; + struct dicommand *cmd; +}; + +static s32 __dvd_fd = -1; +static u32 __dvd_spinupval = 1; +static lwp_queue __di_contextq; +static u32 __dvd_readlength = 0; +static u32 __dvd_cbinprogress = 0; +static u32 __dvd_reqinprogress = 0; +static u32 __dvd_lowinitcalled = 0; +static struct dicommand *__di_commands = NULL; +static struct dicontext __di_contexts[DI_CMDCTX_CNT]; +static u32 __di_regbuffer[0x08] ATTRIBUTE_ALIGN(32); +static u32 __di_regvalcache[0x08] ATTRIBUTE_ALIGN(32); +static u32 __di_lastticketerror[0x08] ATTRIBUTE_ALIGN(32); +static ioctlv __di_iovector[0x08] ATTRIBUTE_ALIGN(32); +static char __di_fs[] ATTRIBUTE_ALIGN(32) = "/dev/di"; + +extern u32 __IPC_ClntInit(); + +static __inline__ lwp_node* __lwp_queue_head(lwp_queue *queue) +{ + return (lwp_node*)queue; +} + +static __inline__ lwp_node* __lwp_queue_tail(lwp_queue *queue) +{ + return (lwp_node*)&queue->perm_null; +} + + +static __inline__ void __lwp_queue_init_empty(lwp_queue *queue) +{ + queue->first = __lwp_queue_tail(queue); + queue->perm_null = NULL; + queue->last = __lwp_queue_head(queue); +} + +static struct dicontext* __dvd_getcontext(dvdcallbacklow cb) +{ + struct dicontext *ctx; + + ctx = (struct dicontext*)__lwp_queue_get(&__di_contextq); + if(ctx!=NULL) ctx->cb = cb; + + return ctx; +} + +static s32 __dvd_iostransactionCB(s32 result,void *usrdata) +{ + struct dicontext *ctx = (struct dicontext*)usrdata; + + __dvd_reqinprogress = 0; + + if(ctx->cb!=NULL) { + __dvd_cbinprogress = 1; + if(result!=0) __dvd_readlength = 0; + ctx->cb(result); + __dvd_cbinprogress = 0; + } + __lwp_queue_append(&__di_contextq,&ctx->node); + + return 0; +} + +static s32 __dvd_ioscoverregisterCB(s32 result,void *usrdata) +{ + struct dicontext *ctx = (struct dicontext*)usrdata; + + __dvd_reqinprogress = 0; + __di_regvalcache[1] = __di_regbuffer[0]; + + if(ctx->cb!=NULL) { + __dvd_cbinprogress = 1; + ctx->cb(result); + __dvd_cbinprogress = 0; + } + __lwp_queue_append(&__di_contextq,&ctx->node); + + return 0; +} + +static s32 __dvd_ioscovercloseCB(s32 result,void *usrdata) +{ + struct dicontext *ctx = (struct dicontext*)usrdata; + + __dvd_reqinprogress = 0; + + if(ctx->cb!=NULL) { + __dvd_cbinprogress = 1; + ctx->cb(result); + __dvd_cbinprogress = 0; + } + __lwp_queue_append(&__di_contextq,&ctx->node); + + return 0; +} + +s32 bwDVD_LowInit() +{ + s32 i,ret = 0; + u32 ipclo,ipchi; + lwp_queue inactives; + struct dicontext *ctx; + + if(__dvd_lowinitcalled==0) { + ret = __IPC_ClntInit(); + if(ret<0) return ret; + + ipclo = (((u32)IPC_GetBufferLo()+0x1f)&~0x1f); + ipchi = (u32)IPC_GetBufferHi(); + if(ipchi>=(ipclo+(sizeof(struct dicommand)*DI_CMDCTX_CNT))) { + __di_commands = (struct dicommand*)ipclo; + IPC_SetBufferLo((void*)(ipclo+(sizeof(struct dicommand)*DI_CMDCTX_CNT))); + + memset(__di_commands,0,(sizeof(struct dicommand)*DI_CMDCTX_CNT)); + + i = 0; + __lwp_queue_init_empty(&__di_contextq); + __lwp_queue_initialize(&inactives,__di_contexts,DI_CMDCTX_CNT,sizeof(struct dicontext)); + while((ctx=(struct dicontext*)__lwp_queue_get(&inactives))!=NULL) { + ctx->cmd = &__di_commands[i]; + ctx->cb = NULL; + __lwp_queue_append(&__di_contextq,&ctx->node); + + i++; + } + } + + ret = IOS_Open(__di_fs,0); + if(ret<0) return ret; + + __dvd_fd = ret; +// __dvd_lowinitcalled = 1; + + // printf("DVD_LowInit(%d)\n",ret); + } + return 0; +} + +s32 bwDVD_LowInquiry(dvddrvinfo *info,dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_INQUIRY<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_INQUIRY,cmd->diReg,sizeof(struct dicommand),info,DVD_DRVINFSIZE,__dvd_iostransactionCB,ctx); + + return ret; +} + +s32 bwDVD_LowReadID(dvddiskid *diskID,dvdcallbacklow cb) +{ + s32 ret = 0; + struct dicontext *ctx; + struct dicommand *cmd; + +// printf("DVD_LowReadID()\n"); + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_READID<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_READID,cmd->diReg,sizeof(struct dicommand),diskID,DVD_DISKIDSIZE,__dvd_iostransactionCB,ctx); + +// printf("DVD_LowReadID(%d)\n",ret); + return ret; +} + + +s32 bwDVD_LowRead(void *buf,u32 len,u32 offset,dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + if(buf==NULL || ((u32)buf%32)!=0) return -1; + + __dvd_reqinprogress = 1; + __dvd_readlength = len; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_READ<<24); + cmd->diReg[1] = len; + cmd->diReg[2] = offset; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_READ,cmd->diReg,sizeof(struct dicommand),buf,len,__dvd_iostransactionCB,ctx); + + return ret; +} + +// never got this function working, probably removed from wii +s32 bwDVD_LowReadVideo(void *buf,u32 len,u32 offset,dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + __dvd_readlength = len; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_READ_DVDVIDEO<<24); + cmd->diReg[1] = len; + cmd->diReg[2] = offset; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_READ_DVDVIDEO,cmd->diReg,sizeof(struct dicommand),buf,len,__dvd_iostransactionCB,ctx); + + return ret; +} + + + +s32 bwDVD_LowStopLaser(dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_STOPLASER<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_STOPLASER,cmd->diReg,sizeof(struct dicommand),__di_regvalcache,0x20,__dvd_iostransactionCB,ctx); + + return ret; +} + +// never got this function working, probably removed from wii +s32 bwDVD_EnableVideo(dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_ENABLE_DVD<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_ENABLE_DVD,cmd->diReg,sizeof(struct dicommand),__di_regvalcache,0x20,__dvd_iostransactionCB,ctx); + + return ret; +} + +s32 bwDVD_LowSeek(u32 offset,dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_SEEK<<24); + cmd->diReg[1] = offset; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_SEEK,cmd->diReg,sizeof(struct dicommand),NULL,0,__dvd_iostransactionCB,ctx); + + return ret; +} + +s32 bwDVD_LowOffset(u64 offset,dvdcallbacklow cb) +{ + s32 ret; + u32 *off = (u32*)(void*)(&offset); + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_OFFSET<<24); + cmd->diReg[1] = 0; + if(off[0]) cmd->diReg[1] = 1; + cmd->diReg[2] = off[1]; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_OFFSET,cmd->diReg,sizeof(struct dicommand),__di_regvalcache,0x20,__dvd_iostransactionCB,ctx); + + return ret; +} + +s32 bwDVD_LowPrepareCoverRegister(dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_COVER<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_COVER,cmd->diReg,sizeof(struct dicommand),__di_regbuffer,0x20,__dvd_ioscoverregisterCB,ctx); + + return ret; +} + +s32 bwDVD_LowOpenPartition(u32 offset,void *eticket,u32 certin_len,void *certificate_in,void *certificate_out,dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + if(eticket!=NULL && ((u32)eticket%32)!=0) return -1; + if(certificate_in!=NULL && ((u32)certificate_in%32)!=0) return -1; + if(certificate_out!=NULL && ((u32)certificate_out%32)!=0) return -1; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_OPENPART<<24); + cmd->diReg[1] = offset; + + __di_iovector[0].data = cmd; + __di_iovector[0].len = sizeof(struct dicommand); + + __di_iovector[1].data = eticket; + if(eticket==NULL) __di_iovector[1].len = 0; + else __di_iovector[1].len = 676; + + __di_iovector[2].data = certificate_in; + if(certificate_in==NULL) __di_iovector[2].len = 0; + else __di_iovector[2].len = certin_len; + + __di_iovector[3].data = certificate_out; + __di_iovector[3].len = 18916; + __di_iovector[4].data = __di_lastticketerror; + __di_iovector[4].len = 0x20; + ret = IOS_IoctlvAsync(__dvd_fd,IOCTL_DI_OPENPART,3,2,__di_iovector,__dvd_iostransactionCB,ctx); + + return ret; +} + +s32 bwDVD_LowClosePartition(dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_CLOSEPART<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_CLOSEPART,cmd->diReg,sizeof(struct dicommand),NULL,0,__dvd_iostransactionCB,ctx); + + return ret; +} + +s32 bwDVD_LowUnencryptedRead(void *buf,u32 len,u32 offset,dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + __dvd_readlength = len; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_UNENCREAD<<24); + cmd->diReg[1] = len; + cmd->diReg[2] = offset; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_UNENCREAD,cmd->diReg,sizeof(struct dicommand),buf,len,__dvd_iostransactionCB,ctx); + + return ret; +} + +s32 bwDVD_LowWaitCoverClose(dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_WAITCVRCLOSE<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_WAITCVRCLOSE,cmd->diReg,sizeof(struct dicommand),NULL,0,__dvd_ioscovercloseCB,ctx); + + return ret; +} + +s32 bwDVD_LowResetNotify() +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + if(__dvd_cbinprogress==1) return -1; + + ctx = __dvd_getcontext(NULL); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_RESETNOTIFY<<24); + ret = IOS_Ioctl(__dvd_fd,IOCTL_DI_RESETNOTIFY,cmd->diReg,sizeof(struct dicommand),NULL,0); + + return ret; +} + +s32 bwDVD_LowReset(dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + +// printf("DVD_LowReset()\n"); + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_RESET<<24); + cmd->diReg[1] = __dvd_spinupval; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_RESET,cmd->diReg,sizeof(struct dicommand),NULL,0,__dvd_iostransactionCB,ctx); + +// printf("DVD_LowReset(%d)\n",ret); + return ret; +} + +s32 bwDVD_LowStopMotor(u8 stop1,u8 stop2,dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_STOPMOTOR<<24); + cmd->diReg[1] = (stop1<<24); + cmd->diReg[2] = (stop2<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_STOPMOTOR,cmd->diReg,sizeof(struct dicommand),__di_regvalcache,0x20,__dvd_iostransactionCB,ctx); + + return ret; + +} + +s32 bwDVD_LowRequestError(dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_REQERROR<<24); + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_REQERROR,cmd->diReg,sizeof(struct dicommand),__di_regvalcache,0x20,__dvd_iostransactionCB,ctx); + + return ret; +} + + +s32 bwDVD_SetDecryption(s32 mode, dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_SETCRYPTMODE<<24); + cmd->diReg[1] = mode; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_SETCRYPTMODE,cmd->diReg,sizeof(struct dicommand),__di_regvalcache,0x20,__dvd_iostransactionCB,ctx); + + return ret; + +} + +s32 bwDVD_SetOffset(u32 offset, dvdcallbacklow cb) +{ + s32 ret; + struct dicontext *ctx; + struct dicommand *cmd; + + __dvd_reqinprogress = 1; + + ctx = __dvd_getcontext(cb); + if(ctx==NULL) return IPC_ENOMEM; + + cmd = ctx->cmd; + cmd->diReg[0] = (IOCTL_DI_SETOFFBASE<<24); + cmd->diReg[1] = offset; + ret = IOS_IoctlAsync(__dvd_fd,IOCTL_DI_SETOFFBASE,cmd->diReg,sizeof(struct dicommand),__di_regvalcache,0x20,__dvd_iostransactionCB,ctx); + + return ret; + +} diff --git a/source/dvd_broadway.h b/source/dvd_broadway.h new file mode 100644 index 00000000..c0ca133b --- /dev/null +++ b/source/dvd_broadway.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008 Nuke (wiinuke@gmail.com) + * + * this file is part of GeckoOS for USB Gecko + * http://www.usbgecko.com + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DVD_BROADWAY_H__ +#define __DVD_BROADWAY_H__ + +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +typedef void (*dvdcallbacklow)(s32 result); + +s32 bwDVD_LowInit(); +s32 bwDVD_LowInquiry(dvddrvinfo *info,dvdcallbacklow cb); +s32 bwDVD_LowReadID(dvddiskid *diskID,dvdcallbacklow cb); +s32 bwDVD_LowClosePartition(dvdcallbacklow cb); +s32 bwDVD_LowOpenPartition(u32 offset,void *eticket,u32 certin_len,void *certificate_in,void *certificate_out,dvdcallbacklow cb); +s32 bwDVD_LowUnencryptedRead(void *buf,u32 len,u32 offset,dvdcallbacklow cb); +s32 bwDVD_LowReset(dvdcallbacklow cb); +s32 bwDVD_LowWaitCoverClose(dvdcallbacklow cb); +s32 bwDVD_LowRead(void *buf,u32 len,u32 offset,dvdcallbacklow cb); +s32 bwDVD_EnableVideo(dvdcallbacklow cb); +s32 bwDVD_LowReadVideo(void *buf,u32 len,u32 offset,dvdcallbacklow cb); +s32 bwDVD_SetDecryption(s32 mode, dvdcallbacklow cb); +s32 bwDVD_SetOffset(u32 offset, dvdcallbacklow cb); + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif diff --git a/source/filelist.h b/source/filelist.h new file mode 100644 index 00000000..6c72c440 --- /dev/null +++ b/source/filelist.h @@ -0,0 +1,212 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * imagelist.h + * Contains a list of all of the files in the images, fonts, sounds folders + ***************************************************************************/ + +#ifndef _FILELIST_H_ +#define _FILELIST_H_ + +#include + +extern const u8 font_ttf[]; +extern const u32 font_ttf_size; + +extern const u8 sdcard_png[]; +extern const u32 sdcard_png_size; + +extern const u8 bg_music_ogg[]; +extern const u32 bg_music_ogg_size; + +extern const u8 credits_music_ogg[]; +extern const u32 credits_music_ogg_size; + +extern const u8 credits_button_png[]; +extern const u32 credits_button_png_size; + +extern const u8 credits_button_over_png[]; +extern const u32 credits_button_over_png_size; + +extern const u8 button_over_pcm[]; +extern const u32 button_over_pcm_size; + +extern const u8 button_click_pcm[]; +extern const u32 button_click_pcm_size; + +extern const u8 button_click2_pcm[]; +extern const u32 button_click2_pcm_size; + +extern const u8 tooltip_png[]; +extern const u32 tooltip_png_size; + +extern const u8 startgame_arrow_left_png[]; +extern const u32 startgame_arrow_left_png_size; + +extern const u8 startgame_arrow_right_png[]; +extern const u32 startgame_arrow_right_png_size; + +extern const u8 tooltip_medium_png[]; +extern const u32 tooltip_medium_png_size; + +extern const u8 tooltip_large_png[]; +extern const u32 tooltip_large_png_size; + +extern const u8 credits_bg_png[]; +extern const u32 credits_bg_png_size; + +extern const u8 little_star_png[]; +extern const u32 little_star_png_size; + +extern const u8 background_png[]; +extern const u32 background_png_size; + +extern const u8 wbackground_png[]; +extern const u32 wbackground_png_size; + +extern const u8 bg_options_settings_png[]; +extern const u32 bg_options_settings_png_size; + +extern const u8 settings_background_png[]; +extern const u32 settings_background_png_size; + +extern const u8 nocover_png[]; +extern const u32 nocover_png_size; + +extern const u8 nodisc_png[]; +extern const u32 nodisc_png_size; + +extern const u8 button_install_png[]; +extern const u32 button_install_png_size; + +extern const u8 button_install_over_png[]; +extern const u32 button_install_over_png_size; + +extern const u8 dialogue_box_startgame_png[]; +extern const u32 dialogue_box_startgame_png_size; + +extern const u8 wdialogue_box_startgame_png[]; +extern const u32 wdialogue_box_startgame_png_size; + +extern const u8 button_dialogue_box_startgame_png[]; +extern const u32 button_dialogue_box_startgame_size; + +extern const u8 button_dialogue_box_png[]; +extern const u32 button_dialogue_box_size; + +extern const u8 keyboard_textbox_png[]; +extern const u32 keyboard_textbox_png_size; + +extern const u8 keyboard_key_png[]; +extern const u32 keyboard_key_png_size; + +extern const u8 keyboard_key_over_png[]; +extern const u32 keyboard_key_over_png_size; + +extern const u8 keyboard_mediumkey_png[]; +extern const u32 keyboard_mediumkey_png_size; + +extern const u8 keyboard_mediumkey_over_png[]; +extern const u32 keyboard_mediumkey_over_png_size; + +extern const u8 keyboard_largekey_png[]; +extern const u32 keyboard_largekey_png_size; + +extern const u8 keyboard_largekey_over_png[]; +extern const u32 keyboard_largekey_over_png_size; + +extern const u8 menu_button_png[]; +extern const u32 menu_button_size; + +extern const u8 menu_button_over_png[]; +extern const u32 menu_button_over_size; + +extern const u8 settings_button_png[]; +extern const u32 settings_button_size; + +extern const u8 settings_button_over_png[]; +extern const u32 settings_button_over_size; + +extern const u8 settings_menu_button_png[]; +extern const u32 settings_menu_button_size; + +extern const u8 wiimote_poweroff_png[]; +extern const u32 wiimote_poweroff_png_size; + +extern const u8 dialogue_box_png[]; +extern const u32 dialogue_box_png_size; + +extern const u8 wiimote_poweroff_over_png[]; +extern const u32 wiimote_poweroff_over_png_size; + +extern const u8 bg_options_png[]; +extern const u32 bg_options_png_size; + +extern const u8 bg_options_entry_png[]; +extern const u32 bg_options_entry_png_size; + +extern const u8 scrollbar_png[]; +extern const u32 scrollbar_png_size; + +extern const u8 scrollbar_arrowup_png[]; +extern const u32 scrollbar_arrowup_png_size; + +extern const u8 scrollbar_arrowup_over_png[]; +extern const u32 scrollbar_arrowup_over_png_size; + +extern const u8 scrollbar_arrowdown_png[]; +extern const u32 scrollbar_arrowdown_png_size; + +extern const u8 scrollbar_arrowdown_over_png[]; +extern const u32 scrollbar_arrowdown_over_png_size; + +extern const u8 scrollbar_box_png[]; +extern const u32 scrollbar_box_png_size; + +extern const u8 scrollbar_box_over_png[]; +extern const u32 scrollbar_box_over_png_size; + +extern const u8 progressbar_png[]; +extern const u32 progressbar_png_size; + +extern const u8 progressbar_empty_png[]; +extern const u32 progressbar_empty_png_size; + +extern const u8 progressbar_outline_png[]; +extern const u32 progressbar_outline_png_size; + +extern const u8 player1_point_png[]; +extern const u32 player1_point_png_size; + +extern const u8 player2_point_png[]; +extern const u32 player2_point_png_size; + +extern const u8 player3_point_png[]; +extern const u32 player3_point_png_size; + +extern const u8 player4_point_png[]; +extern const u32 player4_point_png_size; + +extern const u8 player1_grab_png[]; +extern const u32 player1_grab_png_size; + +extern const u8 player2_grab_png[]; +extern const u32 player2_grab_png_size; + +extern const u8 player3_grab_png[]; +extern const u32 player3_grab_png_size; + +extern const u8 player4_grab_png[]; +extern const u32 player4_grab_png_size; + +extern const u8 battery_bar_png[]; +extern const u32 battery_bar_png_size; + +extern const u8 battery_red_png[]; +extern const u32 battery_red_png_size; + +extern const u8 battery_png[]; +extern const u32 battery_png_size; + +#endif diff --git a/source/fonts/font.ttf b/source/fonts/font.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d4c461ca284c77bb2f6ac20c9cb73dea322765ef GIT binary patch literal 48364 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 XB~k1Rgu2~uZ=)MaT-1uI4()#e-X%@C literal 0 HcmV?d00001 diff --git a/source/fst.c b/source/fst.c new file mode 100644 index 00000000..d73235b7 --- /dev/null +++ b/source/fst.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2008 Nuke (wiinuke@gmail.com) + * + * this file is part of GeckoOS for USB Gecko + * http://www.usbgecko.com + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ogc/ipc.h" +#include "fst.h" +#include "dvd_broadway.h" +#include "wpad.h" + + +#define FSTDIRTYPE 1 +#define FSTFILETYPE 0 +#define ENTRYSIZE 0xC +#define FILEDIR "SD:/codes" + +#define MAX_FILENAME_LEN 128 + + +static vu32 dvddone = 0; + + +// Real basic +u32 do_sd_code(char *filename) +{ + FILE *fp; + u8 *filebuff; + u32 filesize; + u32 ret; + char filepath[128]; + + __io_wiisd.startup(); + ret = fatMountSimple("SD", &__io_wiisd); + + if (!ret) { + return 0; + } + + fflush(stdout); + + sprintf(filepath, FILEDIR "/%s", filename); + filepath[16] = 0x2E; + filepath[17] = 0x67; + filepath[18] = 0x63; + filepath[19] = 0x74; + filepath[20] = 0; + //printf("filename %s\n",filepath); + + fp = fopen(filepath, "rb"); + if (!fp) { + fatUnmount("SD"); + __io_wiisd.shutdown(); + return 0; + } + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + filebuff = (u8*) malloc (filesize); + if(filebuff == 0){ + fclose(fp); + sleep(2); + return 0; + } + + ret = fread(filebuff, 1, filesize, fp); + if(ret != filesize){ + free(filebuff); + fclose(fp); + fatUnmount("SD"); + __io_wiisd.shutdown(); + return 0; + } + + memcpy((void*)0x800027E8,filebuff,filesize); + *(vu8*)0x80001807 = 0x01; + + + + free(filebuff); + fclose(fp); + + fatUnmount("SD"); + __io_wiisd.shutdown(); + + return 1; +} + + diff --git a/source/fst.h b/source/fst.h new file mode 100644 index 00000000..e61d4b18 --- /dev/null +++ b/source/fst.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2008 Nuke (wiinuke@gmail.com) + * + * this file is part of GeckoOS for USB Gecko + * http://www.usbgecko.com + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FST_H__ +#define __FST_H__ + +//u32 do_fst(u32 fstlocation); +u32 do_sd_code(char *filename); +#endif diff --git a/source/fwrite_patch.h b/source/fwrite_patch.h new file mode 100644 index 00000000..54fedcc4 --- /dev/null +++ b/source/fwrite_patch.h @@ -0,0 +1,15 @@ +unsigned char fwrite_patch_bin[] = { + 0x7c, 0x84, 0x29, 0xd6, 0x39, 0x40, 0x00, 0x00, 0x94, 0x21, 0xff, 0xf0, + 0x93, 0xe1, 0x00, 0x0c, 0x7f, 0x8a, 0x20, 0x00, 0x40, 0x9c, 0x00, 0x64, + 0x3d, 0x00, 0xcd, 0x00, 0x3d, 0x60, 0xcd, 0x00, 0x3d, 0x20, 0xcd, 0x00, + 0x61, 0x08, 0x68, 0x14, 0x61, 0x6b, 0x68, 0x24, 0x61, 0x29, 0x68, 0x20, + 0x39, 0x80, 0x00, 0xd0, 0x38, 0xc0, 0x00, 0x19, 0x38, 0xe0, 0x00, 0x00, + 0x91, 0x88, 0x00, 0x00, 0x7c, 0x03, 0x50, 0xae, 0x54, 0x00, 0xa0, 0x16, + 0x64, 0x00, 0xb0, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x90, 0xc9, 0x00, 0x00, + 0x80, 0x09, 0x00, 0x00, 0x70, 0x1f, 0x00, 0x01, 0x40, 0x82, 0xff, 0xf8, + 0x80, 0x0b, 0x00, 0x00, 0x90, 0xe8, 0x00, 0x00, 0x54, 0x00, 0x37, 0xfe, + 0x7d, 0x4a, 0x02, 0x14, 0x7f, 0x8a, 0x20, 0x00, 0x41, 0x9c, 0xff, 0xc8, + 0x7c, 0xa3, 0x2b, 0x78, 0x83, 0xe1, 0x00, 0x0c, 0x38, 0x21, 0x00, 0x10, + 0x4e, 0x80, 0x00, 0x20 +}; +unsigned int fwrite_patch_bin_len = 136; diff --git a/source/geckomenu.h b/source/geckomenu.h new file mode 100644 index 00000000..458e6288 --- /dev/null +++ b/source/geckomenu.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008 Nuke (wiinuke@gmail.com) + * + * this file is part of GeckoOS for USB Gecko + * http://www.usbgecko.com + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GECKOMENU_H__ +#define __GECKOMENU_H__ + + +#define ROOTMENU 0 +#define ABOUTMENU 1 +#define CONFIGMENU 2 +#define REBOOTMENU 3 +#define root_itemcount 7 +#define about_itemcount 4 +#define config_itemcount 9 +#define rebooter_itemcount 6 + +u32 currentmenu; // 0 ROOT +u32 rootmenu_item; +u32 menufreeze; +u32 langselect; +u32 langsaved; +u32 pal60select; +u32 pal50select; +u32 viselect; +u32 ntscselect; +u32 hookselect; +u32 ocarinaselect; +u32 recoveryselect; +u32 regionfreeselect; +u32 nocopyselect; +u32 buttonskipselect; + +u32 doprogress(u32 progstate, u32 noelements); +void drawmenu(u32 menuid); +void drawselected(u32 menuidpos); +void processwpad(); +void clearscreen(u32 *framebuffer, u16 xscreen, u16 yscreen, u16 width, u16 height, u32 color); +void drawicon(u32 *framebuffer, u16 xscreen, u16 yscreen, u16 width, u16 height, u32 gicon); +u32 CvtRGB (u8 r1, u8 g1, u8 b1, u8 r2, u8 g2, u8 b2); + + +#endif // __GECKOLOAD_H__ diff --git a/source/http.c b/source/http.c new file mode 100644 index 00000000..c187e1af --- /dev/null +++ b/source/http.c @@ -0,0 +1,234 @@ +#include "http.h" + +/** + * Emptyblock is a statically defined variable for functions to return if they are unable + * to complete a request + */ +const struct block emptyblock = {0, NULL}; + +//The maximum amount of bytes to send per net_write() call +#define NET_BUFFER_SIZE 1024 + +// Write our message to the server +static s32 send_message(s32 server, char *msg) { + s32 bytes_transferred = 0; + s32 remaining = strlen(msg); + while (remaining) { + if ((bytes_transferred = net_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining)) > 0) { + remaining -= bytes_transferred; + usleep (20 * 1000); + } else if (bytes_transferred < 0) { + return bytes_transferred; + } else { + return -ENODATA; + } + } + return 0; +} + +/** + * Connect to a remote server via TCP on a specified port + * + * @param u32 ip address of the server to connect to + * @param u32 the port to connect to on the server + * @return s32 The connection to the server (negative number if connection could not be established) + */ +static s32 server_connect(u32 ipaddress, u32 socket_port) { + //Initialize socket + s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (connection < 0) return connection; + + struct sockaddr_in connect_addr; + memset(&connect_addr, 0, sizeof(connect_addr)); + connect_addr.sin_family = AF_INET; + connect_addr.sin_port = socket_port; + connect_addr.sin_addr.s_addr= ipaddress; + + //Attemt to open the socket + if (net_connect(connection, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) == -1) { + net_close(connection); + return -1; + } + return connection; +} + +//The amount of memory in bytes reserved initially to store the HTTP response in +//Be careful in increasing this number, reading from a socket on the Wii +//will fail if you request more than 20k or so +#define HTTP_BUFFER_SIZE 1024 * 5 + +//The amount of memory the buffer should expanded with if the buffer is full +#define HTTP_BUFFER_GROWTH 1024 * 5 + +/** + * This function reads all the data from a connection into a buffer which it returns. + * It will return an empty buffer if something doesn't go as planned + * + * @param s32 connection The connection identifier to suck the response out of + * @return block A 'block' struct (see http.h) in which the buffer is located + */ +struct block read_message(s32 connection) +{ + //Create a block of memory to put in the response + struct block buffer; + buffer.data = malloc(HTTP_BUFFER_SIZE); + buffer.size = HTTP_BUFFER_SIZE; + + if(buffer.data == NULL) { + return emptyblock; + } + + //The offset variable always points to the first byte of memory that is free in the buffer + u32 offset = 0; + + while(1) + { + //Fill the buffer with a new batch of bytes from the connection, + //starting from where we left of in the buffer till the end of the buffer + s32 bytes_read = net_read(connection, buffer.data + offset, buffer.size - offset); + + //Anything below 0 is an error in the connection + if(bytes_read < 0) + { + //printf("Connection error from net_read() Errorcode: %i\n", bytes_read); + return emptyblock; + } + + //No more bytes were read into the buffer, + //we assume this means the HTTP response is done + if(bytes_read == 0) + { + break; + } + + offset += bytes_read; + + //Check if we have enough buffer left over, + //if not expand it with an additional HTTP_BUFFER_GROWTH worth of bytes + if(offset >= buffer.size) + { + buffer.size += HTTP_BUFFER_GROWTH; + buffer.data = realloc(buffer.data, buffer.size); + + if(buffer.data == NULL) + { + return emptyblock; + } + } + } + + //At the end of above loop offset should be precisely the amount of bytes that were read from the connection + buffer.size = offset; + + //Shrink the size of the buffer so the data fits exactly in it + realloc(buffer.data, buffer.size); + + return buffer; +} + +/** + * Downloads the contents of a URL to memory + * This method is not threadsafe (because networking is not threadsafe on the Wii) + */ +struct block downloadfile(const char *url) +{ + //Check if the url starts with "http://", if not it is not considered a valid url + if(strncmp(url, "http://", strlen("http://")) != 0) + { + //printf("URL '%s' doesn't start with 'http://'\n", url); + return emptyblock; + } + + //Locate the path part of the url by searching for '/' past "http://" + char *path = strchr(url + strlen("http://"), '/'); + + //At the very least the url has to end with '/', ending with just a domain is invalid + if(path == NULL) + { + //printf("URL '%s' has no PATH part\n", url); + return emptyblock; + } + + //Extract the domain part out of the url + int domainlength = path - url - strlen("http://"); + + if(domainlength == 0) + { + //printf("No domain part in URL '%s'\n", url); + return emptyblock; + } + + char domain[domainlength + 1]; + strncpy(domain, url + strlen("http://"), domainlength); + domain[domainlength] = '\0'; + + //Parsing of the URL is done, start making an actual connection + u32 ipaddress = getipbynamecached(domain); + + if(ipaddress == 0) + { + //printf("\ndomain %s could not be resolved", domain); + return emptyblock; + } + + + s32 connection = server_connect(ipaddress, 80); + + if(connection < 0) { + //printf("Error establishing connection"); + return emptyblock; + } + + //Form a nice request header to send to the webserver + char* headerformat = "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: WiiEarthh 1.0\r\n\r\n";; + char header[strlen(headerformat) + strlen(domain) + strlen(path)]; + sprintf(header, headerformat, path, domain); + + //Do the request and get the response + send_message(connection, header); + struct block response = read_message(connection); + net_close(connection); + + //Search for the 4-character sequence \r\n\r\n in the response which signals the start of the http payload (file) + unsigned char *filestart = NULL; + u32 filesize = 0; + int i; + for(i = 3; i < response.size; i++) + { + if(response.data[i] == '\n' && + response.data[i-1] == '\r' && + response.data[i-2] == '\n' && + response.data[i-3] == '\r') + { + filestart = response.data + i + 1; + filesize = response.size - i - 1; + break; + } + } + + if(filestart == NULL) + { + //printf("HTTP Response was without a file\n"); + free(response.data); + return emptyblock; + } + + //Copy the file part of the response into a new memoryblock to return + struct block file; + file.data = malloc(filesize); + file.size = filesize; + + if(file.data == NULL) + { + //printf("No more memory to copy file from HTTP response\n"); + free(response.data); + return emptyblock; + } + + memcpy(file.data, filestart, filesize); + + //Dispose of the original response + free(response.data); + + return file; +} diff --git a/source/http.h b/source/http.h new file mode 100644 index 00000000..0698f0ce --- /dev/null +++ b/source/http.h @@ -0,0 +1,38 @@ +#ifndef _HTTP_H_ +#define _HTTP_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "dns.h" + +/** + * A simple structure to keep track of the size of a malloc()ated block of memory + */ +struct block +{ + u32 size; + unsigned char *data; +}; + +extern const struct block emptyblock; + +struct block downloadfile(const char *url); + +#ifdef __cplusplus +} +#endif + +#endif /* _HTTP_H_ */ diff --git a/source/images/background.png b/source/images/background.png new file mode 100644 index 0000000000000000000000000000000000000000..e3b6babe87084e073b448b28e749c40d927ec850 GIT binary patch literal 51389 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 Rs1j%pgQu&X%Q~loCIDE-B}@PS literal 0 HcmV?d00001 diff --git a/source/images/battery_bar.png b/source/images/battery_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..3aff74110f8d216e1f64ae10a42bc3d8c65d59b2 GIT binary patch literal 225 zcmV<703QE|P)3}~2@kc28EtH-F#K!m>xRFkddynKe7$4-w{~$g-2R;R99H7|a z0OH4Z?S}^Y*8xmoUy447D`V7Vq<&`+(;+Ky+?8!j1O|;e-Iy^1D}F44p8iI z0P$nI_CtgH>i{OPugLZT*-Y3Jd>m*8BH@0#J{SN8!qVY?s9PQnHV6Jk!(Rux1K*E^ z;Aj*NpaVY-#t?jqRK$G6<-mb1sF5AmH>j(+A=y}XItZFupYb`+9@=32FhC8~*FbE= bFcbj*3L4C&KisCX00000NkvXXu0mjfp;uSW literal 0 HcmV?d00001 diff --git a/source/images/bg_options.png b/source/images/bg_options.png new file mode 100644 index 0000000000000000000000000000000000000000..5b694e0a45c316ca24874fe46e8774140027260e GIT binary patch literal 1765 zcmeAS@N?(olHy`uVBq!ia0y~yVC(^62@W=(i2u2R@(c`YYdl>XLn>~)z3uNkC0gdd z$D3c77KsPxJHGn5MPvHj)@jN-S`Rg>*fO1FEBM5)IC(7WF!-4twWZ+UftH@f74Lr9 zo;l!LvASB^@pDbxhlg=;?&9eerx%|y-a59?^}M~T2}*lU z%uD0{@2~ML<+7OIf}(k;{B`DH-`%!W?%uoiZ(eEX*UNYA#Hf3pK7IP-)6>%#d>a0| zua1g}^6GVaT)j8$eNJB9KK<6m7vCRw6k1b}oBQ_hn>TN^_xAQ~*}Qo&A3y))lP5i2 zl~@7wZQi`Oq@-lZw{PDrUAq<*6%p~``PqZhNqmkKO=%+1Xid^%pgeqB;oIrH54^Op}EbUZb?CGlQvjjrqCf4K)|$i3H565G9d z_fh#5-+wzX1~e9YsoGmoQxoH&{NCi&W9#1A_u91H={%CqDiagzz7ZPX(U8?~*3m_| zOsdc(bl2q>TI|Ykb8Dr=?*MH%x-;yJj*f!E*D|S%i5=FxGiS~`ry=2g>R^QozjUwL zAA{JK7>hQh6)SdJ?&$tdQJwY2wztUO)yIOmx_!I%?~kv!v4}CGe7a!1zpkDhpZmdz zV7_CoD{kbNvA->|=4E5{64h-x0hXk;7Umci|Wi(s>Q)JU{&8VyT$3X9NTIEb36)l4PQ)6>Pc7d%?T zYR`M@)G043TU+154=*$^avWQGutJu9*4bwZ?&d8&n2>OgK}*Mse{I<7YYA5#AN=#D zro6u1J~l2c%AlcZ*S>vz?(XiHg@uI{T*qb?8OR+!?6&yg$^X9M;^KWv8ML&_c&n?c zHO(LX){xLYb#O*k`|8!J=U=;iy?gWOy8ZbN8MJonwy?MNkB*McOiNp4%yn#Xk-@uT zhu^+^TMjJ6?k7zb++R>yn##zirQ|oQYHysCg@p$~eG0pfh*Y(JwA3rQ|b8>i|KYMm-afHq4zZO3q&b3(H#lIzL z?Rk*GBh$@y-Oby0TY#_OB)99G$Rliupt7rK@4wPNWg%tz%WglBzjHdSw;Wi4O|7?l z`{vD(!-o%-6cq)rur%zCzY~7^c0l1l*>bT$o~h+x@m?D%LVn-uS@bcfX1SpF!=L;m zo3`xP6H_yh8L0T*cUxUuUD15!r?IZfOVU5Sj`&kxV;cL*m0{Jx$Zre2#ixJy7P6=4 w_Z=lBpEVYtRkLi@NP;R6iR3f#GwT_yUtW-^WydE7tiBjLUHx3vIVCg!06tM{V*mgE literal 0 HcmV?d00001 diff --git a/source/images/bg_options_entry.png b/source/images/bg_options_entry.png new file mode 100644 index 0000000000000000000000000000000000000000..13e87188f21357e4e42f8776bc039274116ec6ee GIT binary patch literal 1146 zcmV-=1cm#FP)0r^vpDbi%+r%=U;gj~{!0Ly25=d`UjQ}$ zI1mw0p@kQOxeLL+zi@Wp#_rDUdxyRLrVsur0CfO%vLFxe zsg*xlNXKc@d;bW)9DvBjMnqIRFRE%x)t=;|akjMBtiO4Famj~pGmr680PT|nfry9- zIN?7_0oxxR4bytLo0Tm4c%{{u&!g@I@9qPb=cG?W^m+vTARVRAkttYHt-FA!OThm)I4yy1WdVT&cj_e z+o*nYX@2%pHMx~aeg@mDT37p^YPUaKbI znyS_~Wrx&H3_;_~d|XIZXq;JDf$BBFu?KFlntMmQLp1A;RI zXYkJ8#Go)~Ojp7?OZ8?NBLkm^sGxyw05mF0@$@b3acA?iw=n?*x!T?!4!y_#JW-Q~ z=#>^;a$O+e;Y8FRQDHFx8IB8ncqcJJA8z$Vzi#ez6Yn>`Gj@oG3K{q&fF|Dg2$9Up z#s-WO@FJoL+j!j1?mq0S_xj`8AxQ6kev62RUeUle0ZJlrIfP(GQ812zVFdarNP@#& zcbNVBTc^|B9o{mNKSWOc6%Y|o;U@ebB4^b(9sC>k4t*0j+8^h?uk7q@bPjH-*)QHn z&gq_rsJMYI5Rs7y1`!xXU}#<*_tUtw+U>Qr_U^n2_rndfQf3V%! zd616A-v;L%Gwg|oiXZq8K`kjKLCWRiAX9Dc^oFhV_Db46`o?>=3XufdcTYrAC@%?Z znGEHml=~3cdxO!+>UL|;JNPbmc_1PsaL+vv(Q7f`I}tZqu1zMpy`!|X*4f_e?*AA> z?mch@f`|aVu z;hGcN5|Io*<>`XJ$3{d{%)o!{9D7w=8}<&r2Cyk2@n!cB5m9mc0}%(-+-uXe(EtDd M07*qoM6N<$g4O04X8-^I literal 0 HcmV?d00001 diff --git a/source/images/bg_options_settings.png b/source/images/bg_options_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..55cd5ed36d07d29e91ebf4b2d94a6cc9f91a36ab GIT binary patch literal 9572 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 literal 0 HcmV?d00001 diff --git a/source/images/button_install.png b/source/images/button_install.png new file mode 100644 index 0000000000000000000000000000000000000000..178c2796e4b8f624084b1421284966a7f6b65654 GIT binary patch literal 2173 zcmV-@2!i*CP)^1=ng2Yw#qsEUZijFkGDFH35n1doFEXgfJ{wqc&U5Ikj!V>VS(;J?4l3J%?ztJ8LlI?Qn#%4V~aN~Ht=%d!Lk7=Xju?KZVqEpY`YTbsv*BblC_n_#b~T)&9<>89elz%jKw8ERyTGLNZD=Vqi%E0AaW)2N@8l zR4P=hR>kXjXwq*hLp0&r2bshJt4@Hy-@DE69=dg?LN z*?@bVN2O9pWCSE?OyXB_MVbk${Y>KNRU^RQKaw}YzwaNO6%{6*&(p}rhybo!C!l9R z&ww(um;rodW=0T!<8xH0-*6`U$jCE^`XFrPA`@`;K3=dxQuB}vK&$A(m4uXx;!@JT zQ}=*`8b__4tz6Bn=c>kbU@^eVMMVFm&9?uQ-CQm)0TwJYuR!;UJ{IZJ)HIdLGeR!< z;#R*!#1(kuup2T>;*9@*=ia;;8Mu274+vN&ktmf4c)w`F+U*WC8ZDMddjSEp4v+yg zmY&fpXZjk>LKFsHT@e9}z}A8p?!Ss_JtkJAQjc~Lc$gn_H!nYg-nB(1e+SL$veSbC z+sSjur9vVP#Zzjb+|GP+TpW$klHb=dy`A(-JRI4|{m+E%xCrPHp$J|^>p*Kf*d#MC2G(vM1w1`0gRG$Qq+OTm0 z-Uv{5kBGNAKGj)TbF*`lO{FQFNpS{Dx^mm*o-RfOJ-&{V@!S*zof5yaBvvynqd^4z zQwhzU>VXbapUCCbLQg+eT1ut6bCfw_jb?*#nIetkit{yI&uF|?(m%rq&TrJt$}(yv zE#yH}=#>f2nI9Mg^a`R!uO})jpMWJbJ3A}dW!o_qfbZ94t1E2Mx2Z8P{)QxAChZ4< z2pmCo81Q*k_3({GW4;|$6U706=;ZViHCqiSy&#da0;@abz_rSm=K~H+kG*($B^%i( zoR-e>K$r}J;}nH9I4Odt@gP{Q*F{z0Pg$^GV&wZBa#T=o@UPC44$qt%t1i2h;C>vl z-F~8#?r8x~%RvHiLbO2&QUP#~z)e9Ih`0rz$CWAS0joz|jj7Jf!a3uw^PJ_Ae|<)A zm5Vo8>OKH_?qBT`o#*awGq)A0hXDykE?~V45VJ8b7ws{>cX=y$Wr;ln0}-TN)#|$4?G__O4<;=0~q`y`DyF zP-W>S8(lhz1n$PuiScviA3pul1Ao%Mx8&2k&T=Fq_Z{=#t2HN=H#6VZ%Lg2_sp-Jt zPbT6PuQ+-JV1KUV>CANHspI$E@e95CmcYFv30aH9&sp$BKXKce;~giFisFPTc>s_;a980-u%o4_AwTAv?pu)pvdG z!^698xO3wb#V>t;N$lWrERKOrLJKa=4lEVyt|-g@e*Nn8dvEznX5-dx4KaZ$*l`$18Icfei=&OFZe`xp=Nipd z+7~BZo;dQ{OH)UGcOhx5OWjwcCobOA`2T=TLL54*RK_0t&S3 zqoAP?2&DTO=y16jzTE!>O*%>SZI9RN|IPjf6g!5$=USL600000NkvXXu0mjf;Oi-f literal 0 HcmV?d00001 diff --git a/source/images/button_install_over.png b/source/images/button_install_over.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ad727bbfa8e21419e2dd08125ca424286af848 GIT binary patch literal 2971 zcmV;M3uN?(P)FK@Opx^=bn43mHHn)th4<1N5A>l z;xWkVf)&TkU^$<~@=t#KVfJ4q0N?`BWh)sbpE<_(1TuvsY!NJGOWCs1kg-ky++m<) zm-yoV_1(r5BWMFlAoD?;q@|mdjYltTZNs2o#!*XUu05MzTV+s685ryZ@~^>`)u_3 z2-fCnhD_ueqhXx@ym-CF015CK>@C=3*aqwpf40gbUw3pF^fv4TY?EyZw##I?EH9E= z`Z^NU3Bdd8^<~&P>?YfF_V{TI0{aB^2=*BEjL8s@m$2ZQNLVKXe~vx=HtaU+ zTd=zv5k1JIQmn3*BYkeznW|X1a;&k0Pp*H*8>#pGp$1Ne>$=)(+g6rksXWhBmSrkQ z5|yUu_&u(B4icY+74>yolA#FXXRyyyNz!Q&ykC{>~A3z{%d?#E#70NnK#(;ZXI&@ zDTA-q>l(ahy=X=7^4k2K&Jr0SLhtoG5M6g%y%zZ1*LaRuwujp<1ND1hmpB;DKFSFP4dEs>&(B%uYo7#$x}LLCi0t}&Js zcCKei-!|mqa)^Y$I)_fZj{)fdDv?ww1^7H~>!Lo2)L<|~#TgwVAXUjsYBQo$fWP}H z3L8e7vcOJuIcFyXqYRGQwN1zvY=>3H%=GMc=MMC0oyc}>}w zPSF!2?#VMb;kv*{Js}`@P>g`jI$Pu!SZmU^#-5@Gm^YgTetc~ivyL_Ps_RVEYLX6- zD<-%(?kZ%v>P)KT3S+9zBOnp*xr{cX&yf~^2A4!Ddb2obX}6U0q*^q|wYPuoW z&`d1zLoqidBuD~oB0pPX?^ihoW=24Ie&1MKsYUjJRF5KH0wOliwq-*?xk~XFoh{pi z*T2;x?=$?Q z8}uQak{S&ob#QQqDA@WMntkIqg)_zxt=IjzQZy=&5Aq(qbB(3yF#^S%1$~sQpEL&i_1 zyFnV%#Fm=`^1{}~M5Kev)>@=N38;A!^3=KW=je?FMeoVu!zfXGNUPKCsH*2Hzv3YR zwz_;}eX4U2rx)|cyf@E)?)q^@v^G0Q~7H0TS zX_e=X$8W)FgK(f~m8M#*H77ORjHrw?RRs7ot>Bo!AkQ)?U9si3(vjw770Qi$8);){ zyF=~piirj$0%ipu=LWIqy?;LbPqcB5P4bPum#saT^2C&1i61MbV0CmItZE6TyDJud5P1g=eyvo}WcT zz|%ns|50v91dg&KZX*wRMFMU?LLu+T&_a5LH<@amW8J!e8ChBYs^ugJsv-hFS0brW zBvSN1RE5$E3l>9Wrq%_tEchn|;Qtu<3_jTd_sNKYLAH|<^sxb)7#?dDbQ^6{e9d|(r|D;>GvMt^;5S}+blO% zI=rot&D&PV3>ocnYh5>5+4a9bN(qwe2i3u3N5Ndsn>!E1C`klN0y?iS-k&k9BrbIS zRXPeEB!k}bBn-AJ%iguUO1J3!sR$TRP{n@3=#TU>0NM_uS#qtEAUxTWG>YCYdYwp5 zBtx58kmetP1@$Nzdp=L%&2%{UBI$P@CcXBPEE+w7_qQq+FL#UHpSQJW=0fptQO5g3 zm;XtX2{)$&_#G_x%Xu>CBxgmyOkg_t&^eXo&%%lta=nM=p8@>+BD~p3_ki%OT)%{7?-oeVmLn|#OV;cMD+H9vBbDWc zn5g=%nzd0HjUHvA@DV)!IO@Ip3f_N?iR&wWb#149^$tloInnNPfrKpdo4iJrt(Kdp z^>^UpTj1gl_;J=Q0?H2&QNuQS* z%e&RJD?M-JV)RDO2WF5kA97rfr!%P2H{iYNh{guiz87&Wo#?Sfp7pVgz~mI|0Q@#& zvlR#3og`@Q#zBWVfGx+X9MrGgCh(;D^eoTFoWjGsCKEXiAZzGTE&&V(+*X1rR!BQdsvco)$19-icM#ByOzf8ma zOAu*gadc>x$}Oi-?*jO!x^^`=$>Y`&KPTqxN86a(e9jL&SD@u>q{FZYSv0aZu7Q+~ z&&o(dY6(Cgjd31<=m6mR0NulNUCgo_)cKC>mV(maYS_GWFFxrb)>A#H=V(|)i7gwE z@iF!LAmPEg9vUzQ$>|aSfTh+T25?9TtHmUu#xaD)L%ZxnZwma(|0`kqpM-5}$(Uw? zjE$OZ12jb;1?UvzQm?zc#d9&Fa_WCE_>cUv$7}xaW7gP{9fh<0gUA2X@oysqnMgh9 RR;K^}002ovPDHLkV1luP!kqvB literal 0 HcmV?d00001 diff --git a/source/images/credits_bg.png b/source/images/credits_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..54d797ddd6fd13aa7ba596088f3af6478e716e70 GIT binary patch literal 60848 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 literal 0 HcmV?d00001 diff --git a/source/images/credits_button_over.png b/source/images/credits_button_over.png new file mode 100644 index 0000000000000000000000000000000000000000..54e83dbc9540f8bef042aacba8178e25a4eff2a8 GIT binary patch literal 5039 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 FV1m_P0HFW? literal 0 HcmV?d00001 diff --git a/source/images/dialogue_box.png b/source/images/dialogue_box.png new file mode 100644 index 0000000000000000000000000000000000000000..d16b96cc057650f7ffbafc97296dfc0c318529da GIT binary patch literal 3834 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 literal 0 HcmV?d00001 diff --git a/source/images/dialogue_box_startgame.png b/source/images/dialogue_box_startgame.png new file mode 100644 index 0000000000000000000000000000000000000000..cd491ffed35bb41e91daaf0335fa4c2dde79d497 GIT binary patch literal 19284 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 nuL#Y zI01gj()88pkFo-H1bj0Xjy~ENJ;b?$WH{`MEQCP0xW=lA#e9Y@iywezS(;Ao08aA! z3*h^my#qIT?-9;9LBH3@YszW?%?@0q2N5nwP!&YFCcD*810Yec?f1v{ zsvKWU&%OjQ1wI=LM^B=xx?Z@3Q3O#zRdFt1dv_1u=_Jqh6X4TW5DrlVgb<>ELoGr5 zt%Kx63rP)$2%?H}j;+zQE9SGK1bFO{0U{C1g5fPhU(~DX?5PNQ+oB7z%i!JNYc z7>O!A1bpS=)52{A37r~H8XrmobP6HR*ld&lm>Ff|2@bjCP8X_2Ap(QaP#8Tg= zz{>+dQ=&>=V=03zbvLc>s+38)BQ>8*6SgUmJJfy2U>h*beYb1VRV*#9C9CrGQ{o;e zytVU=7rz5pmZryd zE@CEmeh7Rms!x;Q2z3M8V9?or}<}0e}tD?@@S6Q0+`=;wQ=sxi^#D~CP#}@p9 h_!{Du_U(QX{{U$Xfq%IEJhT7+002ovPDHLkV1f;>t*QV3 literal 0 HcmV?d00001 diff --git a/source/images/keyboard_largekey.png b/source/images/keyboard_largekey.png new file mode 100644 index 0000000000000000000000000000000000000000..975904577cd9406bf497c60255cd9d6b7803f5de GIT binary patch literal 1017 zcmV4%07>1vj**oV>%E^|kSVG{S%8)vxtAHT&;=uLk{4>%dqza@6`2#`KK>{X4DmMuP zT)9dm2$rR@bFyS#a;M#$ofNx!w<}+MKyKehT8U$&M%=^uy`yEuaE+tU$N`7twF}%w zi1pN0aY#7H+ z7J`(?@$v5w!AAr#QG;mo_jLynM@|UI6FHBJ|4#Laa4AWZ}<21++Z*u ziXx0L7$Y%68!$k?IfpTp+uOHE({%gQWb!32w7{nuz5e}MTQ{-RN)FLJMU251i?xO* za_rpM0eE;c8tq2FCmS1mtaG?hkU*gL3{?sVv6kUs$_lZR1e|lczq#q&PN#aaTzSaBP9cmv5(}X-b|4Ng`S=NRp(ynNDZGV>^uF-)8gqlhg4_(lo()FG)lz z#mF*Gk|aDoJq7q~7{{|}73BjL}J7yR}5;t${p zXdc1#0Qhlt=g#*2?p>lNDi0NDZtyF_I!IA{4aXEvL2G9Gh&arrwi9LDi+Ly%IE z1K{h(xrdwmKHYAI8{Mv+ffws)3jfUKq-n~V>EB728ea|L*e^n1)$bjRM!OWpK<@(w n`b&y6<{8B?(7)7Ax2^aWRVaIj!KG5S00000NkvXXu0mjfZhYO2 literal 0 HcmV?d00001 diff --git a/source/images/keyboard_largekey_over.png b/source/images/keyboard_largekey_over.png new file mode 100644 index 0000000000000000000000000000000000000000..c61c8a61ec0b4a531aef424a8fa6b945e8068606 GIT binary patch literal 1005 zcmV1v3W>4qCiW~_ABmxFihSVuj1q7)V2d+=&Kf_Hzsz8d6e;}wjNWi2>2y){m2RcV<%T+)o+O@4nBmoZxiL!o&N$vwJ(n8b_0f2M+VG2RuQD?(zya z0e%^m<*W4%ZB33t;Jd+a^vTBPA>J1h!=X;0=p-p6>bqNF({MMvBGlDSz_W2#UfdJp zXfpW<_;G7@-;X|cg!djZ!_4VSif#%*f|Q6c5o6%p>l3DzZ%=_Q$7T6)E=W#}U$^%k z`_aQKymy#$7`B!%LUhg&VoIbK2_bOx_KeH3lXKwHaakT0xpREKwY%TSQ4~05n8^&$ z0}NaOteu!PKinZS_0G-3+1J3>0bdM;qbKcH$PXy0R6B#6>ObUQ=Z9%8K^-a$&tYR0Gl zh%r((fn|+U4G0U@6Z3qW}moQ8fYQvra!l-i{(4Ol{8i*|x;v=ZX|{e3AxmZmFB zSfcmwu{2681X+3s(Pu-JEhz3;BR_-^WKPkJSGIBp(O*GqeqYu?khPZ(8nNzm5KUM@ zu;zd|h!FqVLDqVR5b7W+C0*A+gqS7Bk{`1UqLMBIK$<&Xs~tommJr#4^;N9dPY(6K z1|e2Gm|rM#&f%PsAforQ96+*$AW}FQ#aJNH&ft+8<*uDv94ZTzd5C;D`Je2MD$OLygx`?S6rR{3-H6Z zET^+otY_1Uv)|1ZkG6Jp@x`FsL-@tQN-Gc2i;O7Th zJ3E`(AK?p+bADyXOH06_D~U0CPh>gn?znz)N_BJjComqDxPG*g7fbsz}t7R7fXLuY$BaUH%Lj5ET*y;vYb+Rst!aph^Q0 zQmRx`Cm}9(PPofmVz6&_XNO{T&ub^SvmxEiv&YhUw)*sY@Ar0QRltPJWtn{4oKh_l#)^d0>=H&GGGvL!WiXL77ES2}u z?w$8_zu!kh&?4omYIp{FB^HGxx0d7MW1buxod6%kQM7N$n)l7laH#wJKE@c7QYh7Q zaP=g0XsuC7xVd$cEX%f@9Up%I!~%TM>vZql*u0L21bDAQs1!;GA_`+P+qbp>?v0XU zV1SQ%y)L3Px&-KO_^+!}+*t9cvV_ecg4UXMH#YRk$z;y}cUr9$q7)8rMM2>l&J`C$ zwBhnYDK$4#=TJ(~Znpt;4bTzM9-6h_TnW(Ctf;y0>S-(@NO>)Ou45=wXRSq*uw2ts zx6sFM!NfU-EqPU80IYN5*7}QJAeZp;5Q{vgC?N{?9>+OH(A{bfZBbAZZmz&es-cBh zt)(g3>qUU7Y#9T-tJ~_jPk0kS`Px^F5SKf%noG^p{|o$9=T~tul`!j{5SOL!BBP+d z|EjecVcyRV|LY8F|g$oc@0GOs3FD8>I@Ic}y`gJ;+Jv zd|oxy0F094BjAU@_N}d*!EKB&<)OmG12#>8R(D)$Ez{|YgYlS?)3e`zIF6$I1%M^Q zUEnLD^}UU5mv+0wwRXF?Yh2Fp&um7PWxSaDotCQmGL9l!f3$lgMoBWjzvi$5>^8gv jKE}W1@N@lieii=$g(Q24$Upeo00000NkvXXu0mjfb&<_& literal 0 HcmV?d00001 diff --git a/source/images/keyboard_mediumkey_over.png b/source/images/keyboard_mediumkey_over.png new file mode 100644 index 0000000000000000000000000000000000000000..4703e936b31cb823bff4aa6325420c27869fc890 GIT binary patch literal 952 zcmV;p14sOcP)OZ6o#L3?#NoPjy4t!*aQ|_Eu>DFDqu)GY+(9y`!mvPNEJvC@&|$|K>|yPRNEvF z*eX>jx88W|U9DxynwfiViaR5XWZ{fWy17RT5=hm}B z0VlvOS(?6D|5DcA9RlC=`h!ol1`jbNA?f!!OU`>wF~7!@CG*)7TjW0h&$2X~+yHnq z9)AV=INaSggAX2Ij6p;Y(e47ogZDV+anADo%?Y!Mcc;LYS(?6F0IWLi*PZ>xX7F%` zF^Z@n$Xbtfk|NG~ymMGRu z{ox2(7Ne`l*>fOM;EP^=@Fd7qBfL!vMGzHK6=M>%cXk1u9*xI)3GjI^41=fwg7;y7 z`l^MiPaSN&Fv6sQhzO#JF@~+dw#jGH!vuJ2k{%)fobwLre9(RMbiMmj1XaPP0v-{; z^tNEeK>`d!73)2=wBg&X-2~JFi zGgd&nTl^vcu+Ed07Bx4rb*x6YDih*LtP2nopmYxBJhAcGtxihoa23Ex!d0tQP7~`^ zSHS_!HzbVr!K$Nx+h*%Uw9|;={!6@N2R76j72Klz8d6P~iKl+W`mb!bq?FvC8u_*B zz$U=3@3(wn-R{EDn03jze4~W#BjKpvJFA#D1OLw%xHbo4wV8n{CK7YtT{^JAubzR? zMA|PvYDTg;1EYl7DtLnn*IU-{K&hREo17LwT2)ci2(U#3PH`o2e+l1MiAd12Mu4qi zjEbNuCK7Yt-8-CTNbq_8=ycM9eltoE#eKiAKXqKjbxFUaf`Sz5u$Z^g^h?~Gw z_XCR}XL|k*zzIM<>YVRYgoPF z`x)@_gW+hjz4H+!F{qjq%kE0VsSPz;u&UtA=Ul!$CBM4(6UeeOJzfD=K|BDy71gIn ze}I}Erq`ppyR4ovpW|#vd3}{vUH46vrgph9-cU#5@gCuC4j%&t9Up;z5&q`zTl02) aUH<|_wt;`c)68E00000l00009a7bBm000XU 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 TAtKSc00000NkvXXu0mjf3y-SD literal 0 HcmV?d00001 diff --git a/source/images/little_star.png b/source/images/little_star.png new file mode 100644 index 0000000000000000000000000000000000000000..de0da22c20de5913f6c33190586217dfebcd7af0 GIT binary patch literal 11046 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 literal 0 HcmV?d00001 diff --git a/source/images/menu_button.png b/source/images/menu_button.png new file mode 100644 index 0000000000000000000000000000000000000000..56ffd1dd0d5ecb4e72cd5275f4853626549a1172 GIT binary patch literal 4231 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∈%)%&AXJH= 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 IM6N<$g3920wEzGB literal 0 HcmV?d00001 diff --git a/source/images/player1_grab.png b/source/images/player1_grab.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb1f314991bde87974869d82c750183f356d78d GIT binary patch literal 1995 zcmb7_Yd8}M1IM@KQZe3g$z?9(aG1;KGM4)`V%5y%x@eK85LQmfC6=%?lX8j2C4?Cv zbv8upC`U_0rlDMh<+f>dD70}nyMyZX5sSr$p2gKy46oA7rL42vS&9OKRc0;oF`j}8#;ME@dsJ_RLucOHGpTB9R7D+1 z+e)F*=?eM13Z|x}Br)FtjYgA^tyVs|V(VwGPcn<}-Ot8feyvRRdf=p6hP{9W9X@)56srS|g;)_<0D5|QU9(q^zP=ibL2T&w1U`p$Bx!mQ8SyaI2hYHkJ4_k0ob6UB zwvRWv?)0G2g%&4xZg1Wki~o-E#$YmLX2Oe|lUoHDX}B+R!jFA3{*!foLXEfphdRew za*zcSy7xoQ;GmDSM*`u*37Q~-?P0kU&xEi6)gC$NqK|dik6<=7Y7jMUnjKkKrOIq< z%-~gfx_No!gp{>Dv5%i)Di!CP?+Ro8h@bCQ{NuCLnuOSS4T-_1ev+&Kjb4T0%t7YZ ze{L2O6=fGS4h;<(Xyx`PIui4J*pa zoAd^vV4wxs$F)nVG&7JHmJWOb>za@b@pD&_3WT?H`g!ZV<6l-Qs{23Ai;Fy~^%2`G z<^bMEolZ-FG_@EOxz{Nvd|zPWI|`(Ab6TU*#|dpYFjh{Z_tDmVtgfOUy+&2O9s0Vi|8NfSEUu*^cYgx{}c z!MJANH?R(1bS=<%IQ8=Q3(rGSsYO~}v8FcR(slN1;)OO9yDfr3#RY>~G_m&flQptE zP(rcm`J3$l?<%O$2^ERMdSz(iZ+!z~EWMY^^CnZ91PftKBg&q5ez}KJ`zn zBU_mNG(l6Iv%h{m3X>-IEYV&ZlxNu)53$aimPrVj*?lT9Q?1aqqdOBE%Lj&MZ?-DO zR%u&A{Te5C(=5kakLy)`_#!p=o}C@P48aa6aJ(}NX8|o3moCr36FRDv&lsJNkk!#- z#zyQ#@q$Lw5=q7vr9XWa)3QO*+Posyd%qF>=wRr?8Y(7b08+s5{+<9$fHcKj1O?PJ zfl}~0z=TctwUMc)!o2y!`O?4DaIKY%F~>NEB-6(hc^xdyG?+A{QaNUQgY>OgB`Wyz z=%F&~eF0DP&3Mq!8vBNe&XloFO4Qr~F4!NKBU4GfkG=bB+64={slDw^uBrVO5c2z| z2&ei}aL*iD`F!UDL#IVy1TLmr4qPxY($`Xy)dp5^fe#N3t-c`DzN}{oMA4LiI8$&5 zkRescf>Gp=20^*QwX3zjK>GQv6RR8KUHM_tUwa(dbANNJNBdu;*<|u~s0yIPq*j)J zx4ngHliN@5J)F3|0`&UGXg;zpqnKdc+@2#<24v5Yv*E|F6|stKX?Pm3Y>OJ_Sdu>GX6b@PYA%iYI~LS;n3;}IR`gi# zuyFF^(a#K7xWa7p^Ma7TO_M7(y1yNO23o&YUfzWpQwr0EaxPKw!~mlIow`0^i@EFq z;m53Zi)EWfcJw(MY#Wv1J5&9&G)(O^ z{LR9XO{~e5l?RGmhXv0(8=xn0#c6cgtdoZC^`HaPJ@-gf+j=hUFG!3*r9}ULH%EdC zt4HmEySaE+#R}wIr`gI0&@idqEnjDUYT1Spq$j=b-1Jssi!k6^X8yif=umuV!Q&5c zWnb%L1(X&1nMlNeA_v$zKhPDGsH#oIzB@(1(|=`p=319{Cz@CElOs-x2dGBTU?Ud@ zXY{^`mp1vW16hR)(8{$anWQF~8_gCfSRdYhPmoo3>_hgg$BeI?_7x6z5EZ#QR-a+1f Ws&=CN{@hPV1CAfVx;LXj)Bgp5H_|%* literal 0 HcmV?d00001 diff --git a/source/images/player1_point.png b/source/images/player1_point.png new file mode 100644 index 0000000000000000000000000000000000000000..c06c08c7db9abaa067f03abf1c4b6864b82613c1 GIT binary patch literal 2044 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 literal 0 HcmV?d00001 diff --git a/source/images/player2_point.png b/source/images/player2_point.png new file mode 100644 index 0000000000000000000000000000000000000000..6e952d24ecf910ba111cb7a327b5944557918b6b GIT binary patch literal 2128 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 literal 0 HcmV?d00001 diff --git a/source/images/player4_grab.png b/source/images/player4_grab.png new file mode 100644 index 0000000000000000000000000000000000000000..1e4fdc3d56667788abe27dd074fb343f2b1e55c9 GIT binary patch literal 2045 zcmb7FXIPR81AUPMuj9INpft8u1*o~!G4kkJ5%uXs( zZK|BhziN(54x2Il_S5|Hvu6WF2x5?Y@&AEZ&DnH1n!Zf3rEAlr=uR=y*ECdmgau0JUYgw zbL;Ni6H{NGKDADC;k+4OtJ2%h?PQO6_Y(Iyk~MXp$iyIeqDoal=m-pa17BLB>34N~ zX&_53lgAR&*4B3S_ZJxnlwh$~fwVsql&6V~xCe_Bd0<2F6oRvYNqRy9GH~<#m|pg7 z!d%J#!&v7cHO99yDVfmLkm={A=-hx7vn9eJ#oxime=1evc@y`la&TtOz$Is7;mo+F zpP$Z#5>#B}(PTt1J}iuBRr>+WZLyTChg|ydT(J08WgXkdq$Gpg?7^Qf;5tSyVe6yA zDzis7;6Lg53$8}v8P~6+$h?B|G4C&kXjRH54 z&cLVsX}23wkH+KioyiZwXVKuk4JwfO0^VF*eZ{Uc*BbkJ2mPQMjiuVE?$QN9#uqEgaB;ud#g;_7^7-yBs| znty@;_6mzY);{8d*xV7t)%h;C7Awa%xKO!_MNM1BQKk+8;KKz)+?7>SbLJM8YXgvz zpipE*(#3KVqiO>wlWXCj{9}+3oJR{m@HkrvdTt0T?dr9mPtXuZx@oN=AjVBS@tVpQ z5XWgsd4CkG{k#PneI{ue@h&R~l6^|xYi9hrGD=yJr_Ymc_F^S?WbuCQC2iQ5MyM*A zk}^~6m6PZij}{m{IIm(s)Kin$E;Y=n5VhDu2LaPmB84!3*gk!eug(FzLbQO&A3U9yN5M89Ly7QHmo>_hhB-sUYZ>Z_c>5O=kyksW z%`ff;uRKx9pE~P*FS?2KR0kF(!T0=$82Tl=>`GT8PeSzkn0^Mh!Xv?!jO@`a=<#j`t%fB|MLP|I@(p%*RBzM{siIZlTK9rX6cWBEL(zWIHq)@0qU zYjtf0z_P{?EPq!kc(9 zRC2hVE12+scA?wND0H?-otUy7>uFAh^PKooz|7%7zI@sNfuYB-DU4jyN=;BTr@Cr3 zkLe*RyDT*NXWkAvU^n{Yenw`I>~K#pJNBhCJNO4({IDmjCtDr;Iu>;7#!FvSQTqa2 z27XuOl61Bi>RFnAOZ1iH)cvV0>7sY8IsxX`0A0$tw#6F~q#Rbs-ov^f*Mq$GOY)XM zPC{K4F4HR6V9IzeQ`nuMZkf9*8Qt#z0li6$)Yfw>Fy9YwZo()#;q#Mu&wL0Fc@-fZ9K07bc7an8? z4_00GU7@Am`!?Xxhv{gp(cifW4!x&8*m=&ihZ~W)bVuYE!hK!qm&0z!$Z%9p^9%Jq zZUZnfccC`Zj69hRXo6*fce%`{;~X)YH*t0^}| z9kLV86uaqy4<1$vxNu1FwpE{qd6* zjy|dMC%duTvz}*Hu9rj>e(T%Lb3GtAhL>YLS>fvTOLr4HoT*cKqND$VpLPd=X<39` Ud2f>V;jIG>Hm=qb%fNzv0pqvO6aWAK literal 0 HcmV?d00001 diff --git a/source/images/player4_point.png b/source/images/player4_point.png new file mode 100644 index 0000000000000000000000000000000000000000..dd8f1ad323a8b64575729e87136c4d3333cafce4 GIT binary patch literal 2079 zcmV+)2;ldLP)TIolT)N7V`U6L7Ojk=Vt63Mcoc`g&K&9le zOr|M@ACRI+XaiHhpg>X60u@k#i*Ud1x%WOj&wD;Noclo|us_c8+kQLe{dykn@Asbf zJ@=l277K&HU@#aA27|$1Fc=I5gTY`h7z_r3!C){L35K33?N5AfIBX1|Cz8P7-<6tXa^|&;TkVNdl|YsyAU1%Qf(LkHn3Oi-Yp=a)^XQ zix#N{)FFqnWCM#GB<|$NlfmtFM>Js5rcJ5=cH}cG*}&o}5_jgznc($$BO0)6+cwpJ zF6478*}x)~#GNr?26#N4hz4xkx>YscKJr3Cykrl>S*&hR_O!d@mL`6k~ z5L^F*jj(_Jeu$5cSM%;LngNq0Y6gUYfnL-EH`K>!>t&RoJ~K1Zv<9@$2Upi@Nf9K^ zwi_l*o(N8tLta`!Qd9A2cwe?2K5<)!@QHo%&WLU?di{)xie5cGPGzMC=W@mzyF zdshep%F90&bz*FcG5U5%x+(Hfev=!JhBMv`ULpK7yb7*rNA+A!weH3rMMC`TSueuv zTcvQn>k?iCwP9mKS*`P4(~chR4Uw1foBF4S#J85>OmxY!(|Z}*NbkSk@e^x>0S6Bx zL3?`zeuG{D2Md$I<@!DLSWmqm<)gfBC%&p0&|)?Ns_BD2^60~G_RJx%?h6Avzu~bq zCfnN2!miwxg#q=y=fU09Q{tR9Ur_vHX(TSmkZ!ZeLmFuxv<)9yOpUw|Ka%ike#y-aA#JK4%_My`ArXchjWiA%xiDFEDUgaE}(#A;Bftf$LO?o zl)yK8mcfz3$>4C78QRN490*+zadqPFvGBX2y)eQe|9=oL>amf~*i;Gu|3z>*PeQlz z6yD?aliepp9EwMA74fT-d<+A`n-X#H4?$i1Aqa->3UHo)E=MUi4D3=Esa{{E@f3&R zQC!7J87$0mD z@pNxWFK4MEV?45*L>e>ZaY#*F1|NR-4y328keQw+Q!VT2(mv?jzGjVFN8>3D#Z$y@ zSMo5TAjJ~>Rq}yg3QOEKmLbcKca)!r@B9a<=tiTOu_U8Iq;{xn^EkM*%qUzJu$rU33kPBa;YGVjtkjWGn7l0~@(8-%i?Z8`9 zMg~F{lZhy#oi3RfAtT1r3AY82=980lA$+{J7-geMNdc0s_`A;*nNHdN_6EE=m65B< rTv2VPDd#%4w`Fu=!Q79J+Is*$ktIq)zB`BV00000NkvXXu0mjfx7}gL literal 0 HcmV?d00001 diff --git a/source/images/progressbar_empty.png b/source/images/progressbar_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..e72f0c43c485cecb86b7e48f5e7ca93f4c19826e GIT binary patch literal 224 zcmV<603ZK}P)fPhju3J4WPg*_8hP!^#m5XQYk%AkRQ zIw6O;jG?=vql;Xfm+*+L@O2=RiRm%Jn036*B1naf97voT11?)`9L7Z2vZBbk=)_x) zPPA`TCbk7}aD4-voT`BToo_f6Qebtu6r*;X*%1jA+;C<022R`WXKkXKsl000EdNklcG?{Yr%pRiV0iz7W?dTPLtEq&khk0@uns$0wN;*?*U2EBe%1& z>uR-{E0@b|b#>LPtgK|}&+*?85%KG*xvY7uxvlxFIezPawA&qb6ZK*BdflzBuZJ&G zGUv_j%?IX)cg(z>006+9z|ZCfeqPV}`JK&k&2`Q9oAe+#Ir;3a>)u|&ZES2P8q4M% z-EMcxIae?rnm?E?%wNox=44VS`Gud?n%f1nUf>sphRIx2OCZ zpYS`B8O?dkd(HiRZRi`2W;4yMmDvw1n&UnmPorJNod0qJ0}=7t3Ce<>-(h$1)JJ4o z^Imgb^Z&|#wA*dh%SNLS&N`ODH8lH>C%#?;0}*j>f}*+pBswoy()?EkdNm@s>avyJ zdBpK}Z2m?(5D^D5BAV}y1RLB+(1?fw={rB?HSh05XChe_E(Jtelh`y(U8Pb{ zJYGe+kAgp`*FnoXi;Rdkkk0!#uX$gHb|J6S1@$5Bh3!C2TO~nE(JFCm^rYiO`I*fOI<|c0`lnJOISGpSzB9EKz?MI001B-AXDnZSwPaX<$~2}_WJe@EE50#t+zZ=*9J^RO9OB=J^@b$_008wsT~Ht5 zUR(-@+}YU;XCdP(9RR>k$75VQP!}$?B5AjeU7nkpn+iygVOp0gS<{8&E}EI zbASIJT*_Kv2>}3xG9F9nfO?SEiJm(U*=QUR5deT8j)ywXs}WZQBt*pD+FRsI1OQ;* z!!fRTuepC!JbXYpuAj|jnw^RGgLUrC0st7yc)Zb^*Sy!<@7IPz|LD5v9^gu4J$p_> z50#h&mK*@!n~p}o&+}!?cg^|hHsM-3kXSuDQm@zD#zr;lNJ{3P=CnD>j%%K4u4}&Eqz6f>)p55~C-bURt@e-YOe(HiE{Fe=3K0?Sn2LqwwC1(u ww&u6y_-z~Tp8|r2h{J1gc$hjwM8uo=1yS5T9n6Mf$p8QV07*qoM6N<$f@jKha{vGU literal 0 HcmV?d00001 diff --git a/source/images/scrollbar.png b/source/images/scrollbar.png new file mode 100644 index 0000000000000000000000000000000000000000..032074db3c834395008be6a26bc75613c675d713 GIT binary patch literal 441 zcmeAS@N?(olHy`uVBq!ia0vp^A`A?S0vv2W)`t9$^*~O8r;B4q#jUq@Y_ksqh#V{Y z{w{Za>dWb#Apwgoy8aQevSh94ym-}tX`gn9-PbveQC zPi1X2`teKcX6e@R^-T6|&p+Et|5%apV)@j6Vm9;7i^;~XzrO9#>vG=rZ2Hr??=D`y z{{EKhuWj$~zS^n5CCS$=#B%WT-34y*FYX5_6c!ISUgB*k)oU&uu)cKut7qkmrl+3< z?Yg^8enq{M05!pf{|?tz*?u>2_`b{Ox|8eoQ|{M;ytd!+*`9P>KD>X|^u<-zx9?+? Ylt0UV^HqosFiIFaUHx3vIVCg!0P3W%^#A|> literal 0 HcmV?d00001 diff --git a/source/images/scrollbar_arrowdown.png b/source/images/scrollbar_arrowdown.png new file mode 100644 index 0000000000000000000000000000000000000000..ebd748c66eaaa0d953feb52042bdc41b73250e5f GIT binary patch literal 1091 zcmV-J1ibr+P)CF&?XRL;~_MwwR;$yh{>C!tZ??x3uW0)c;b4dlb!kH5xo);mUV;i^owrM-I z!jO_ ziDaPdqU{PmMkE1hiZRDyl|s2-G+XO{{oy1g`J_P{{B5V%x}ldVCC~Gi;i_l!S#Ca?o{K0%)^MpB zj#dUSKnqbK4dOujNC;5ouZ9x{m+VM`7`R(o)pA{bd=0SQjQWJ3qwWak`*ZnKyKS*o zqnT8O$&&1VhyhIiN`w!cC&MKd+ii@SSOx=nf?Tvf-oh0$ERPk7we9^{{pvWdV*&fn z53>1H$F|wa*)y~Aa8?%14qU~}#>o&^WLCIn@u5u5@55cw;qG>^R&MC^uK@eqxX*Ap z?g1hmaGLi`YjN?V^jut#sft-dL_|D-SV(>(Tt61flcheM28DuN+S41?CV`y@IEY6k zzh;>|>)iRp^n6S}!{KLvgC~Xy>jCThdB0ZP-QB-3DeT0+KJ->Pzvi?%{oGP6lNC2& z04y?1e1|>sEI9k?UA?qZJrJgZ`q z0_bAwgNv*!pwFh}G%8cT+PClQJ}guYuZ;2r`(J^BctqY`vlS}8!SP1CS2=uqr?mg& zX~LfLc{yp_`uW~o3+>y`CSZRG|3?ZdtgylgE3B}>3hM=~e*xzqIM?Z=HV*&*002ov JPDHLkV1m3X8|nZ6 literal 0 HcmV?d00001 diff --git a/source/images/scrollbar_arrowup.png b/source/images/scrollbar_arrowup.png new file mode 100644 index 0000000000000000000000000000000000000000..6cef2fa02aea06292b55a8056dfc669da94e86d1 GIT binary patch literal 1025 zcmV+c1pfPpP)3VnJRaZ1_9S&;r?Cf8huDPDN=OAIK|&ykgxG+Sg18hH2?>4qpT7LxQhu8eMd{pHV(6)<4m-l`VcZ(cGR$pljukkn@4R3(HH9l2pd6qq zQV;>VkVhF?Ud|QzmRrm0?Axb>=5xTlzgk(kdhvO)k&>`1AV}|hU>X7Y5wI<zfg00Z{j(pu@`=5tRqR6&K1umGF@PoT+Eh8=$l?ZDO9qHYWwZ@sYF zn%N%wG*g$cR{G@JR&`TTs89hZl?G)BrD-5d;(G!q77!=V5DX}wp&%e0p-e603YO!W z#$L;vCDVLX8=R@Ew9hwdn@dS93WAb6Qkw&8CIU_ZSOut@*LVcXqN{*pLlT4$jWd=n z>P2|ETHI^-fc|lzz;fzZJ-gCwHq0$eP&pkC0ZA()*jVAc2P`2y3^#mg+K5aBSg5E#O8)&k5shw6o{dj(`lEd9 z+veMzi+~_gFkvRcZbG+5T~EX70}Y|$uAKfIBQ!eXbH-OU zYW1{H_)xBxr{1mM&u?kD?6s#aY+p>m23qJ*%m}{ch`@DJ>ia4U0^AGikv+5>+i_jr zwQ=%1KU^~aN7aN-6h$PoR8sTM>Ve1Th)`}5AzUt$0Y)K2`nKoX`r*d+cCUYk4bwL> z0Ry&{&g)-P8qYjSJ=byvy&eOoZ&_C7q|@zo2g8x&{6@wWm27vRzoB6yYidWBgEG(x zq{(^}!8bA)O-<{WtddTpJSGH9rLr#L;_lHeM^3Nz8KD1|WqaxPzVF@s_4wwn)9E>u zEnD1&{(_F7J1DR}$HJ4ichXyis`$D_i7IR>@NS?+L6bD8h vCwoCQ;7`w>&1ccSDgT0RQcGWinxZ9DtHHhm z{2Oe3Z1!e%@5~$@X727PNV?f1#c&TCX5r2~^Sx)z`5wLtjWyO-V~xE`lhZbAZf)NL zu3Z9_-N#?w_0zCckx4m&W`sFmx*(o1%?fM66t4_grMNwJ?#wZowP=bI8 z1XT)!Ad1oWa-~cG4Fenp7Hf4CC@trb6fJYAYE8)PwffELmQhK2ZU|z6pP6Zs&fqyxr46y_d zum*w_zD}q6%v2;Ny z$rj~5LjotlclUOlEy`Ut?yUDRk!j7!MFFmZ*Vp~%!OpW6<<5DU+`j)aYq!>WnOPic zov_8HjVw1I-pqtojbP6ZCp+t*AK&ix9zNJ%b8CB{Dfrdhe(!k&E16PUG++f(lLKFT zw$XdL5MIxqZJ@9*V0{BlXTziPampRK)M&bR!!4EJ8qkSCM-{6QC!8pf!1yT_OB^CW zDT6TZ%7KHiUNGQk)1}7y=G!L=v&5ZGHhRyUGE@jEmzUv(XJm={_nvV5)_U)(=Nevu zz0t5l!x9ZkTyd6A{hzSJwCRA4ZufhS&cG61-tG7HD_F5g>oRC9q-JxfeE#W1@0~(; zD~FDS)_@wU=jqMz!paE0mOg{=fe`azy9=e&kD4y z&^1EG2yG)2G6z2CJX;IYc~7^Kr~QSAQ?XmSO)>uXeGk~Za{sM0)>vbWT`~I`=VuD4 ToT1tj00000NkvXXu0mjf+M2jr literal 0 HcmV?d00001 diff --git a/source/images/sdcard.png b/source/images/sdcard.png new file mode 100644 index 0000000000000000000000000000000000000000..0911f548b16f6323138ee38e7472e4ede1b60009 GIT binary patch literal 1686 zcmV;H25I?;P)U8P*7-ZbZ>KLZ*U+lnSp_Ufq@}0xwybFAi#%#fq@|}KQEO56)-X|e7nZL z$iTqBa9P*U#mSX{G{Bl%P*lRez;J+pfx##xwK$o9f#C}S14DXwNkIt%17i#W1A|CX zc0maP17iUL1A|C*NRTrF17iyV0~1e4YDEbH0|SF|enDkXW_m`6f}y3QrGjHhep0GJ zaAk2xYHqQDXI^rCQ9*uDVo7QW0|Nup4h9AW240u^5(W3f%sd4n162kpgNVo|1qcff zJ_s=cNG>fZg9jx8g8+j9g8_pBLjXe}Lp{R+hNBE`7{wV~7)u#fFy3PlV+vxLz;uCG zm^qSpA@ds+OO_6nTdaDlt*rOhEZL^9ePa)2-_4=K(Z%tFGm-NGmm}8}ZcXk5JW@PU zd4+f<@d@)yL(o<5icqT158+-B6_LH7;i6x}CW#w~Uy-Pgl#@Irl`kzV zeL|*8R$ca%T%Wv){2zs_iiJvgN^h0dsuZZ2sQy$tsNSU!s;Q*;LF<6_B%M@UD?LHI zSNcZ`78uqV#TeU~$eS{ozBIdFzSClfs*^S+dw;4dus<{M;#|MXC)T}S9v!D zcV!QCPhBq)ZyO(X-(bH4|NMaZz==UigLj2o41F2S6d@OB6%`R(5i>J(Puzn9wnW{e zu;hl6HK{k#IWjCVGqdJqU(99Cv(K+6*i`tgSi2;vbXD1#3jNBGs$DgVwO(~o>mN4i zHPtkqZIx>)Y(Ls5-Br|mx>vQYvH$Kwn@O`L|D75??eGkZnfg$5<;Xeg_o%+-I&+-3%01W^SH2RkDT>t<81ZP1_K>z@;j(q!3lK=n! zAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fdMgRZ;=t)FDRCwC7 zm`hI+Q5462ckawsKtTir1r!N(BPu>38W%21Ox!oF-Ma9T_$^$x>cWJ?*Ir$jus{+N zl~=?U$U`c&Gjm;ZW;(Z>wn8tbX*#)g=0E50Kj++2p)f0!VLWWezu>l@R@47no90e# zS=aCeG%{R-Ux@A#$?Y+o=LdDbzxtyQfJ%TU4W{b#XL*`Gn&LwdKB`iUZ7An>8EKgS zRPiTBTsK<{Up>yV{7@K_2+l_$V_ik8X+_`URpf>MABBW5o^Uw?6a+{v(2t{euUX8? z>jmDif<$Fw4HZ5kWcSFt4A+^&LliY1cDF?4_E>+bnpS%gp#dH+oy+%`Gzyq|Bpw^C zHmc1CmXnCGs4#rblIu(WDifhb)6jUuZoL)cf0=Fpfd(jA%oN?^KdmaKv?ldH+^uhe zM*t`!E>Oh6!Y@;t^rVDni4zw7b8Z+EY`{PG-d|JOa(lPIyC>VH{-LT2jYknFxQiA@;6{1Llf@WvaaHXA2OR6w9Q! z27Oq=L&0kUCoqkN2Q}vJR#uRqm44c&R?Ao;5~BXoR&?dr^Z92 gS_BZL|04J|0L1p=^KWP>V*mgE07*qoM6N<$f}*73ivR!s literal 0 HcmV?d00001 diff --git a/source/images/settings_background.png b/source/images/settings_background.png new file mode 100644 index 0000000000000000000000000000000000000000..7378501d72f4700c74b3aa1e3171cee090d38deb GIT binary patch literal 12068 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 literal 0 HcmV?d00001 diff --git a/source/images/settings_button.png b/source/images/settings_button.png new file mode 100644 index 0000000000000000000000000000000000000000..a87dea3a330f5fb7a9a2d54772e96c4813cb52f8 GIT binary patch literal 4435 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 Z{|EO%Fl!|4$Rz*(002ovPDHLkV1jbSgq#2X literal 0 HcmV?d00001 diff --git a/source/images/settings_button_over.png b/source/images/settings_button_over.png new file mode 100644 index 0000000000000000000000000000000000000000..f29a269fb7d9c9bbaf22bf2ff6d784ef9f97e0c3 GIT binary patch literal 7553 zcmV-{9e(18P)Ghw1IB$pK(J6vfj6i%_1=7K1BQQ3Zn*%&1R~LG zYI$t}CE0Ujz_>2}2;TsJ1&`J;TGMC^0~D`>A-Mqt3tqO^Xj22I)WV!g2gbc*Fif>% zf&ihn#lB_>pcCV;_sX3CcEbNfXU_noG3yn4wpEF1dU>PtgXN!A@tl%CjfoKa5x*CKvOXJTa zFl~b=E%9H0zKm1|D>j%B89B?qTL{1ImTG}Q$V0v7*JuNy4aHu9V=_kC7sbp~fa0zI49{Y;rHzn4u%I_} z+cFw|22ghOdDd%exF`4C^JZbgI6rZ?lA`q13N7I0TJU{p$9gZ@v2H^Fqy%PaVGEd& zzc4^7U<8JGl8o5U0>7r)wrKo*Umthsx*+iVAa(9G66ZFxn?YLZ`aVko=V8)tKB4x6 zUQ56PH~{4dwL@x0dVeV1A8B9)24f-%TP_TWyCN_G1B^}y5D@x~Zo8u0*5}MG>N*Mi zr`wTgr!Lra=X-9aBwQ5p#_#3!pHbWSF*N{W=oj?-hnhLu4s<�cK)=l3o-PcZFay zh0Dt7iB%DUu&3K~y}zrERofad;VT5dyWQ{<0G{Wm#;+wPR-Gik$n$)@=hwXbFzhOD zMyHtrL4QK+8MUW+|4e|xDs3o0iL?s4FevUhz;F%kMuO25tk}|w*cBk`>vmgzrv87! z&zx`d#?Bkf>0Hph?43y#N@}crzI5LOtyWAa3Y(liCA)p3@}5{Ojw(IS>p$5Cm$^uN#eq z6&wacswpXW2%Q@~$KC{mKVxA2Vz};1PaFcMq7Pw?s6E#0sbI{JF#HmfM7qVxfZ{F* zhD}X%3^14#*98c-sJ*7&D=~hVRMW4mjZOgp!7~8OX7dyn5(HCaNi}4ut29mL4Z_Es z!C+wcI|k-2M{CZ1kt!=r*a9FvruImH^Hi`!f-)&lU$sC9mSmIZ+Oh#>HMOl-u`hst zdb+Q_bK1m;?`$4Bdt|gBP!>A&tyW6`fjzT<)sxMrS8dD|{H_!{+H^WS1rB~+evgjw z4t1D6KHhYqLjBQA5s;Q;2+T1UIS`f`BbOIrh)`9&#b&Gv!@Z|jz(Cxg_BjohbBA2k z-ytv*qM8wC0HED&p8|qGuz6A@IAuoN1`vQql4RZ_dn71IozZ!JLZEz_H27yg>G!F9 zs_n}o&6a1v;14Y}C9A8t{3TSCZ*gsH%($h2fCu#j4Vv?f&cyjmvKKxHkwNHmI?meK zn$zue)q8vnK%~*Oxw)qLDr+X7>@2WtGJ!wiFc5%WYDFr@e3Z`2p05P-a;k8{3F9@N(e5Zox+2Y_L+g6+w&>Z$a?#d&zm z%wZs;0};ouVulGgKKmwJ|2nzke=}AddQ0D1Q8EBlHsDp%QC$b%kT^T!p8wCZ#T|J~cvChY ztfP;MSQ6A=hxDwN9bLf=({|ivn}MG7Rx4IF%*GmE02Bto<~6MnggVUO#xaX60ENB5 zy$mUcd~e2-HGQwP!LO>Z6t{{c{u1nvDUl7WOHI4+x^{P+pCuLb3lwqV#sGu_!*pe@ z5{$Am3>$n_YbHAxu$#n`jBLuonN8_v`NYOxm^tEDnT2D{~mIcGnkvx8f z!Fl}nvGefZL+APP=kxQyoK>kS)1aH~FRL#ZSmHa}bMr)X-PJPL79*dg+6q{{Hnru| zbaksz>#B=#qL9G=Gt8iG5g6$GUUr#t>U{FTs!lXi^4RCf9_@k_>4Y+2U#&Qei)AW90ih?E1Opblzh)amehb>(&Cm z+qZ9*+65Tzt*tG^9@~Z_C3|Aau%ikL8!$56B9oMm!J0Sk4EtI}5|B^L`W+;H~x_S7D6jqQBctz}}Gx`4>vlo?^k z7AXs%MNEe9d}Z4-*h)Zb43TrIHhJXl>vR#a*Py4%WZg0eLI?+{OKxDy=H}-7H}U)1 z+uLV;lWoXFjd>l0NF&dCe5Pb^BF9bVWP)EALly#J+7ENgoB=^VsHW=p!gjFdA#F$9 z4aWJi&ptaNAZFVsPeiCg3CN>IkCf+C7Yul1bpbggAdwW6pg}}Z)VR1gIYA0=8Fs+kW#cTjFbvPI2A`S6o1K9=4uPETunZtJmPqx5?d_9! zWL^4kX+Pv-aoaHPX+SLbE6EUZCZhTgjC05fk}36NHx44%x0ibU*|TRVQirg?01ggK zr+~*>E|VR$F%y}&{^AKBu3|?~^n|*y&fJ%VJ+Rmhw*nB3MVu~q6uvR~#=7)8NkjIK z;JP9zmmAz+sG}<3;C!2UD;rl|mK|nnVlrhe2l{QuCdA~sqFASY=+ZH*59v5Vn@+&id-@z zkZ!N3vVsa5Qnlhq8T2yhUSxy7&ZF|cEZ7>@AsMgWGh~c;C;)&h<6YHNTN0!jB%AlA zO&ri7^t**0v@o~BV28g55Zijdz@oa;Irk_KGB4($V6b|E(PnR|On3}FdOJtxa13Oo z78`P1_#EG_udl1N3NWgSJY@5aVHXGZN@jW1CaJa@*DG5e=`LbO*>be`1f>}*-7~3$ ziw-&==!4K;z}c=qsK>|0^YIA8Az%PLN5gyRbpZfQOtP(D_8_9i#*^gW2%OiB*g!E< z78!ZWoJJ}$zj%#fpt=qY4%EOFJT-uH_wHTweif4?Bv_CU#@^|DgMe?+hk;w<6hL{t zV_!jRRavI$ve}gRNw%pvoDsdq#vYqgPY^r=3qX)+XSIegZaE%amVAUNWR}2n=Hubf zZES3uaR!!QiA@#_Jv6AqMPL+J+AKT|^8_pFwUjZ$wyc?fIm3`Lk7iXH06{)W+8OkC zRy$R>Du4j+7&v*I0Qb(FJ4=I6hczB#G@C__yuDxKc~JPdPXzHCdl8+=^t)rp)z423 zD*XJb*y^~gJVOLvfE7027_iIOg86m09$kx1uCHIDiC-eyT4URp5&;^(0F%m&#W5d${P8?D#*;EuGAw*rI%GaFkJv%`+;uBddKDmr<-Pi!tYn4j zd86Mt8|(%=Eg1MkL$wSB+9Kcp^ame&p!OJTeEs#;S8}~4GAd@1t|K?C0T&i-vAi~nr$9AT*$c!z_>W}; z@07?QJNY6b4+~%9MV7fmno`W(vQ@UT8ucuc;qivz(s?riBAaG5q=3s#V2>Ni0 z6b#Nq;D{izs*?Z^sI2p_!L|&0uCnr6&G98L2$HPG(?r(tI>V4EK+JUyJjqLKSm$l_ z3JXzy19tN5r5cRTYSehqO2qEcuCoYOn_~iWf3rDhs6H>rp>v! zq7Nwm$`hgof+kX58C2Mr)m2ptG1(z2uW@-J=c&OEb4BYa83NmZ@enzp$T0+rJz80; zVLBaENzD&G{P0|W$WD1mHZw4$^mzi+MGQ$5FlURRIg0?v4R*+)U&`HisQ*-YR&puw zDm^Z96cKm@~`9uMdXVlc50CEu3re!KCC~`>&JS8;raxei5F$D~O5ac0}$1zZ4$nL)X{`-~efNi;V@1Ar2{{3^QD|zofiQ4l6 zh!qq1VnRT~MK)sz8F;u^X7!+=Dlp6qH2wB4HuZu=QrCt! z7KX6>;Iep7)CX+5GOg2P48r3PY~arW1pgjD`xn8}hlUYE%R9=qW6 zIj?t`|9{Yc-Yw0^{=Tci+n^7{Y*H%>!ykZKC)W zW>{eMHvr&S9Xxu*^L1TaQbShokvC%<(kT3gJHAIypg zI56DAh!Gj_QITdt0%n{~qbQ%o6Tj7-xW1p1*^e@#ZpI?4woE{Nq+K-id(fF01QOySW=CwFi!`n8vsgH$f9W2{%p9;?1+gSgB*aQ z$+1IfD^KDO?8v86tW}8pb~h$e15CH@A;k+xrtX>bCk>!Gd97W{EWHLv7T-5Uxb6%Do~eQft+n zbnao9V8}Ixt73{7)Irz)0lzKh3FE&P1%P$HV0HV9Vh#=ji5Wv;!!dzzOe(8SEIFq4 z<17k^9q~Bmt__3UW-Lcuml;#H<+P+70U&1G_DwpWfwFjiK&s0%T;5ZL>k>eb8`x4d zHojxgw{O4r6`vk@j#TrKh&@q7#QX~73hNP;(U~RL~ev}z? zTV5*>-qu*y5k&0IvXj@E5u^v>g5UG}yJ40$j3{`<3fj5E^_$4|0o z(kCYLNlncFnZ~1ZGJ^dWyPiLC{YKPS+gw-_bJ47m!s7lmG$3-#2sc=_n<(x54`J8& zrEWM^UDn=UnGSQ+g=oss=q4E4@Hy`76J3WnJQd3XzI6NeF z9Fh$=fL8^ho=wK%EF39g-q_e4c5dCDRJpp9Zm-1!wn@dD|7$*55PuF|GeC_()Rns7 zPZtJ&Wd?p#z*MOxTb#jQ;Jbe(W}v|G%!X%aHk~}m;^-L}?dLh|i5-stNID)2sEyOn zU_`d#sC8|(zxBm$L{80u%5|oaGDBQLb=e+uC#Tw@p?YT%)jaX22vlN|v(>p*%5{pe z=3yC7%hWO{du>ahOJ*=A`2O$d`u}B~I3zIQ=u=|H^E?_KlHGVtcH=1+Ld+mAhG9B7 z#-J3rxf{p5JD-orhHIB*h!H3*-61u2;CK_k6ABWe4z4+pSXKCVQGTiJ_onw`M&CAO zING)SN!(&J6%har6)U3gL5lr!`jl+R6S5h7V#Y8T98O?Eyk_gLd-MMB<`=#eJ4=)s zuQd;Uf$DNf#^sq=pag1Ov-Vop=FjcePU8)5@Mj$=p%gMr`( z96{grj;=X}I!C1pcocpHHN{{Q$@FoNO`nkQKFmf0#;{Lu$0(#fJ8W+49+9e=P(YYD zmsI;*K9bbcy}xXo!|9=5*Tr2vAU(8)TIzq)-%@MbQT&U&7g@-K-&a+!USIkUB_8aR%mAdD+gj3>jRj;gieI7tq(6;dx z2?VmXe?DAyVx9&{5jcWA6=T4)r3NsvBz{(;DcKDT#_({Q42}TC!0+^)ufP7Kqn)pR zD|RmPaTO(?EcHN_BF}F+d3uK=d(-uTEvLo1_;duUhG8F1fp;pMxU(q9v{)qy-9~qB4QYrKVLPw%7>XV8ZkljFz>X1MJ zGY-h*Jx&3}us=yh{Rm*d#cl81>R)^N7sncmt9j(n0#LXXhf`_u@O;yU&7 zZLiVTmB8RfQB~(FSNKpc4aA{l#(=;W5DNym1_LRPJWUaW57TfoR$zp~h}zimgMMrG zCe+mEB4Aty5DO@E9-B9NNLZ0?=UKK#H@Z&(+XE=n!#3O?z`kor`O+SnrzW#yVV)#? zHSC(iBl4V(MjsL@Fwms4w;5DbKbwSO0$@U5MC9Uv85I0^WW@LS8*jWFUiXu$Mp!9O?uxf(@W=mu;gq;;Z)6=!knoz zQ3*f-VvO+%iYo|^Xh_%ACwq59d#J7fa#N(HA`1Gz3b1M95;I6m4Tu@xMVYZOKnz1~ zK6PDdvsUDr)cZE+=5|OJyCf-6YaW0gK)f|lV;$Oe=*HWw>)~}nm#bJNUy@-K zI%W`Jt}QVlDpG2BGQn&R`tK0Ktn}H4yr&V_w?R>)ePRuUVTT07m?H2AfiX?T$1$;j z&QAwkt9{(re{D#CU$l1bt#dt*?a}}dpwxLdaYq>b9tjJ;tdq-ljRdnzLQ}O03&&j} zZjk!&x&#EB>$P0ZZ4gKe7u674@|tJtq5oo#3gy`p%7{2q=p!f3k|Hk>Ebz;-oM#V` zP?HF=3W*(|ni-O%BRZDUR60W1gIwG&os8pbG9vXfj7ddJ)v5&kKEituZll;yNVgmr_kcf#LIMyW)lo|^(Qvi&2 z>hXDbF&o1n={vKfWND$+W~5j^0x;qnfFuM+o>ElpVE)vY0K&w!F&S}kVWSvoiNKhW zmxUG)7-KJJ41%?-(biA>%!KWQ^Rhm^djVU@o~zF4OtFUq)1}_oB^9wrk?}eSX`MPf z0p`&$1q!&(c~DzLlSDzkRRqXQI;WnNRyaD+!%C&Bz*>we#gbetU z4E8ibiwKN3Oo*ik{ePtFO;L>fW_uj;*2A@XUx>+gXP3c>D*>biFfx8Irx+=q2$VMU z(l+`2-8`Cf2pnQd(IgqG%4`KnijZMBvER8%;>xi!yukWCwd|GD6_|pSCMnqp5_p^t zBT^E43N|PZG6F1Blc5z5LAy8cJKf1u0dZx3EC9x{FvmB6B2bzn#3re-7O4^fC~T2V zZ;=2MC?tK4470BmxXz;SLW6;|;b2Qf=Tn;kn3T>-)Ra#GhV}qR%@=TkMo6kDZf@?x zt(_amRRVG4fLMTWj8R6Vjd%`fyTJ8J(Ny0k)XjX%tU^u}}R@Z`#`4PrJ8Y&$Nwjt`dkB21o^K$^i0= z_w$&CnB!&P&`&2LkJ#gpO7n6ozW_OssYA8_NvvY#{>~~Y&}TV$Whr@YX?yo(+PQT< z(?Okc)ogg_0I30xyP%Z~lGz5!Z1qK6H~=p-AT?B+Q}Nmc%9+F@i;xY0SP>gwv&ix(Um92^`RfA#qH+v%oaOR=lSC_Ke4g%Gj?GJ)2hxy}EJ ziC!tT75j=CO!R#wD|?3pImlI|*l0_o)g=~Eb)Ly@ZMs@V*-BFm@>Q*^1asX48iW>K zJx3$GRJ>L6w22g7PfAj#J95?;NUQ4+vNRg)z8n^6^5GzxWUgMI&6m%`Om7rL{P>Rt zIsN8nx_roFP3BTB@RX`I_^elXZGv7}5rPLLNv&L(o)`)^gQW zS}F+5ZrEm~*NT7eBaz28Qw`+*13H7TxWEJF(gj08{t%@jttq7~Xbf6|=8XQ3Eu|DN zpxxItndu#VSXnI)lZ+IaNKFB3QEq?l*PczlK zwVNtP^K@i7DK!!!5+;K;hi@W((%$4!h8JKOG6I)`Jd%i(pe<<37)+ZhFxF{$lroWO zW1WWD(ZvVl`lP6Yh=j?^P2^90d^wZxbSCFfW>TwTe9<_9593bZu|jW*NTGsc1@zh%p^ zcT`9-)XmDPf5ARe(G(#T%rrdLp%xPu1xA{iNKN|354qG_FLF)D16k0Kud!R^n)(r| ze?F0;QeD2~?le_#rTbLD#+d%&O?PlB&GRFZZzdC!jFF6qrq_flpU_-^v7kk#?@6}S z^i73Gm7e~+U1d9w?tnn&L$m;aHIqs6w3%ji8R@6YeiHKZKwD|Xs=GZYo;k`?XL4Aq z$^L0cK7P-obyU1sg`v<7rOS`e4hU3Gu;`1XdB#jM60yNp-sD0Xs^WB{piFgIJ(Gh% zRlXb-<$WeGN^P&gP-rsLn`H4+50w-w{!E$|HxnN+S&y-aCbE7;)2XzFLun~PHTwf;bbC^5yHafW zQR;gTrBW(>o69uRR=gN7Upu8oCq7iNj;J)eycBml)@A~TP_4o3D3w!D3I&S&Y)L*G zB(9~lmT9P6^M`JwdqY3n8{H~IEUuYQ%JgEBBxF@Mo^L7>r79{)VJ&r1X-FnlNvrtn zF4It%xS=|OQ6$~-_nR(a(Fq~9GaB)s5(`X)D5VUgqExkmw67f&Cq5r1?n`BsX((^e zP?1u3uz_pRy@`rcE{#Mii&A0Q*Xc^B)zPJ(N^_j`6ovi9MkDiB$f>I+Kj)ff@kGvFTPH^_b zn94*duBphX*G#R5nQS}{6`t6Qf>Vz;{fP1-A{9s>F9wkcAr^V-+*rQ3=244~r$cK?Y0MZ2+Jgq6Mc+&o z-6;{j^=QFVM+JSOjBhGG{X@QrMW8Vj_5h5z78nrnKw=uwCW;sd+JgoQL1eP-)}#2n ze2Jz~?ng*Po{GgEDk_*1LTveJP9oJP(i^P0kwXFTI@<^wYi#lviXKjq2Zg2kVg^d2$2Zdg2tdVXb#$g z2BF220)!oRo5#Ptkp#+-sPSVm*o{Vu2PTNni^<~6aa?Z5v6}n|A&*3BNNEY0g0`Ts zOunKt=NkzcOeu}q^Yx9S??c@MzG#SW`&mu!>q$|EUrZQp4=fU4HbNc>w4+fvf~If` z0~*^q%4^Nt;{(_Bd><<53x@akN;lpX_y#Karx1n#F3-f9gpdcJbfYz-v;<8h91^^% z0Ab%34AZ``ONhnT{f*s(eX6%f9TkMEndkKt_=Gm4?VzFdh7XghiJL%!+be4)T7kJX zgY#6o!O34QdPfBzPfRAz+SbyKU~q77aBy&NaB%!h<2M2XIROcq@P+^Y002ovPDHLk FV1jQ?jp>1NKP1+bu zn(#~2)K>&5G*Edh-G$|`%d!jmnwfjYb7tk*&8m1nqodfuo28#q9|UhsBoVv21>9A%z)eN`l#<%Pp_h=6uPqi^|K@! zz?}4Ws@~~4diVvE5S3CIz4=MM>PR4fIaRl}_TApz&Lcd}3oFYj5$L{A%x6lE66S!f z;Y8Q-twFOd9!n%3O*#$;Vf@X$!S+CNKx2I(L~1LYffRKV5W=(qOt9U6!Qc@H4zjEg zIL$Z)2w~bOLYNM}Z?LDc31Bpi@`dM6ow-{D z&KlIx+*Udb50`8Wq{B2feDG#ZOFIDsk*ymOW)mzRMkwc%cutWO8M?M?3xqI%XX*#u z?(=uzn!%~1S*BVNrr8FYg7&uqVQs{Y+@@Q17^>AXI>8+ zp@1NmFwCN%&~QnOa#bR$Kdc62GBQrJoUTZU8AaqsObj!gZNeEZT zE?5dcJeSPnb8xzD8z6+~ZmJ(R-QU`!SAR|0nPQmpaM+}Tb6c*ytP1fO#i=IS0tjJV z^zT1$>g9vM9T>g}lFJaQYR05H%6Bzgn{laHx#L z-~V2#LU2)s3MqC_=#5v~p7fdHMHt=!lhBAh;0HBRAy`6OURF_|?NR{k$~^^y*`S1b z6s=gGUvGsIF|%M|%K}UsU~oPCQ&@|wEr6g9{xEWT<<#Z$7OH_1#%wGS$qJ0#)2kMLO z$HM1E@2oB42@iu6U|sQCmKc$FKw!UERpEj6Hrmd%0Sa&7etC23?&lLTYav}B9SjVE z7?H6CH8Ll;D&Sae%Q^&5SRk+bGQK!GHMbrzV0eA-X;O&oozV2h0_;*@=ONm%umV&H z($%r?(D3X$K%q)1n|6@X>it=iM1*nM5{NzRp#v&)fK*f0iT-RLl2_**Qyy_J>l+9zxc#Gqo3zFnM{|17q=5y^w| zp<3v0X%^e?SgQ7-I?vi3h(WDFx*naJ9ZD?6Bf9gMP6z6wu{3+Du@1F50*FE3J%j6s zsoA0QYCIx?QhBUV)R=~(rWS3x+c7{^sO{<5q1<|WNd}m_ZWaK>2_h#79{l3iF+dim z5#`Rzr%H4+gnK`Q6<)5&gT~O{C?EzEMoZ@x7KTY^aVpE~T&dkt2mNi112Qcg;)1ji zz2usn9@W>=-u<|r>vtrO1?++=wRxpxa{Q;ftJ16Sd}}dVAY1%SL02l5{i=R)^hYY` rI|dK;I5bekTkKC`%B|eWt+@6l7P|+K*DT3500000NkvXXu0mjfjFyj< literal 0 HcmV?d00001 diff --git a/source/images/startgame_arrow_right.png b/source/images/startgame_arrow_right.png new file mode 100644 index 0000000000000000000000000000000000000000..51637bf60bd6aeceb5db59e64e3c80c086dc7aa0 GIT binary patch literal 1381 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 literal 0 HcmV?d00001 diff --git a/source/images/wbackground.png b/source/images/wbackground.png new file mode 100644 index 0000000000000000000000000000000000000000..57c0a2ce4188d3ddb7f1ccc16b2e080f0dd8bc70 GIT binary patch literal 43881 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 JPDHLkV1mKX_=^Al literal 0 HcmV?d00001 diff --git a/source/images/wdialogue_box_startgame.png b/source/images/wdialogue_box_startgame.png new file mode 100644 index 0000000000000000000000000000000000000000..318bf0be7c4948fa40af40b7660c2f98003df0a4 GIT binary patch literal 19167 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 N002ovPDHLkV1kTC?%MzW literal 0 HcmV?d00001 diff --git a/source/images/wiimote_poweroff.png b/source/images/wiimote_poweroff.png new file mode 100644 index 0000000000000000000000000000000000000000..d56959eb2ac9b4b833a27da1f86129d03c1672ea GIT binary patch literal 2013 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 ZzX79(RA-zc&ddM+002ovPDHLkV1nA5oVNe~ literal 0 HcmV?d00001 diff --git a/source/input.cpp b/source/input.cpp new file mode 100644 index 00000000..a4ef1460 --- /dev/null +++ b/source/input.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * input.cpp + * Wii/GameCube controller management + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "menu.h" +#include "video.h" +#include "input.h" +#include "libwiigui/gui.h" + +int rumbleRequest[4] = {0,0,0,0}; +GuiTrigger userInput[4]; +static int rumbleCount[4] = {0,0,0,0}; + +/**************************************************************************** + * ShutoffRumble + ***************************************************************************/ + +void ShutoffRumble() +{ + for(int i=0;i<4;i++) + { + WPAD_Rumble(i, 0); + rumbleCount[i] = 0; + } +} + +/**************************************************************************** + * DoRumble + ***************************************************************************/ + +void DoRumble(int i) +{ + if(rumbleRequest[i] && rumbleCount[i] < 3) + { + WPAD_Rumble(i, 1); // rumble on + rumbleCount[i]++; + } + else if(rumbleRequest[i]) + { + rumbleCount[i] = 20; + rumbleRequest[i] = 0; + } + else + { + if(rumbleCount[i]) + rumbleCount[i]--; + WPAD_Rumble(i, 0); // rumble off + } +} + +/**************************************************************************** + * WPAD_Stick + * + * Get X/Y value from Wii Joystick (classic, nunchuk) input + ***************************************************************************/ + +s8 WPAD_Stick(u8 chan, u8 right, int axis) +{ + float mag = 0.0; + float ang = 0.0; + WPADData *data = WPAD_Data(chan); + + switch (data->exp.type) + { + case WPAD_EXP_NUNCHUK: + case WPAD_EXP_GUITARHERO3: + if (right == 0) + { + mag = data->exp.nunchuk.js.mag; + ang = data->exp.nunchuk.js.ang; + } + break; + + case WPAD_EXP_CLASSIC: + if (right == 0) + { + mag = data->exp.classic.ljs.mag; + ang = data->exp.classic.ljs.ang; + } + else + { + mag = data->exp.classic.rjs.mag; + ang = data->exp.classic.rjs.ang; + } + break; + + default: + break; + } + + /* calculate x/y value (angle need to be converted into radian) */ + if (mag > 1.0) mag = 1.0; + else if (mag < -1.0) mag = -1.0; + double val; + + if(axis == 0) // x-axis + val = mag * sin((PI * ang)/180.0f); + else // y-axis + val = mag * cos((PI * ang)/180.0f); + + return (s8)(val * 128.0f); +} diff --git a/source/input.h b/source/input.h new file mode 100644 index 00000000..aed6ab33 --- /dev/null +++ b/source/input.h @@ -0,0 +1,23 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * input.h + * Wii/GameCube controller management + ***************************************************************************/ + +#ifndef _INPUT_H_ +#define _INPUT_H_ + +#include +#include + +#define PI 3.14159265f +#define PADCAL 50 + +extern int rumbleRequest[4]; + +void ShutoffRumble(); +void DoRumble(int i); + +#endif diff --git a/source/kenobiwii.h b/source/kenobiwii.h new file mode 100644 index 00000000..bc3d0ed1 --- /dev/null +++ b/source/kenobiwii.h @@ -0,0 +1,264 @@ +/* + This file was autogenerated by raw2c. +Visit http://www.devkitpro.org +*/ + +const unsigned char kenobiwii[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x26, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x21, 0xff, 0x58, 0x90, 0x01, 0x00, 0x08, + 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0xac, 0x7c, 0x00, 0x00, 0x26, 0x90, 0x01, 0x00, 0x0c, + 0x7c, 0x09, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x10, 0x7c, 0x01, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x14, + 0xbc, 0x61, 0x00, 0x18, 0x7f, 0x20, 0x00, 0xa6, 0x63, 0x3a, 0x20, 0x00, 0x73, 0x5a, 0xf9, 0xff, + 0x7f, 0x40, 0x01, 0x24, 0xd8, 0x41, 0x00, 0x98, 0xd8, 0x61, 0x00, 0xa0, 0x3f, 0xe0, 0x80, 0x00, + 0x3e, 0x80, 0xcc, 0x00, 0xa3, 0x94, 0x40, 0x10, 0x63, 0x95, 0x00, 0xff, 0xb2, 0xb4, 0x40, 0x10, + 0x48, 0x00, 0x06, 0xb1, 0x3a, 0xa0, 0x00, 0x00, 0x3a, 0xc0, 0x00, 0x19, 0x3a, 0xe0, 0x00, 0xd0, + 0x3f, 0x00, 0xcd, 0x00, 0x63, 0xf2, 0x26, 0xa0, 0x80, 0x01, 0x00, 0xac, 0x90, 0x12, 0x00, 0x04, + 0x92, 0xb8, 0x64, 0x3c, 0x48, 0x00, 0x04, 0x85, 0x41, 0x82, 0x05, 0xfc, 0x2c, 0x1d, 0x00, 0x04, + 0x40, 0x80, 0x00, 0x10, 0x2c, 0x1d, 0x00, 0x01, 0x41, 0x80, 0x05, 0xec, 0x48, 0x00, 0x03, 0xa8, + 0x41, 0x82, 0x05, 0x48, 0x2c, 0x1d, 0x00, 0x06, 0x41, 0x82, 0x00, 0x8c, 0x2c, 0x1d, 0x00, 0x07, + 0x41, 0x82, 0x03, 0x8c, 0x2c, 0x1d, 0x00, 0x08, 0x41, 0x82, 0x05, 0xd8, 0x2c, 0x1d, 0x00, 0x09, + 0x41, 0x82, 0x00, 0xa0, 0x2c, 0x1d, 0x00, 0x10, 0x41, 0x82, 0x00, 0x98, 0x2c, 0x1d, 0x00, 0x2f, + 0x41, 0x82, 0x00, 0x70, 0x2c, 0x1d, 0x00, 0x30, 0x41, 0x82, 0x00, 0x78, 0x2c, 0x1d, 0x00, 0x38, + 0x41, 0x82, 0x05, 0x80, 0x2c, 0x1d, 0x00, 0x40, 0x41, 0x82, 0x03, 0x9c, 0x2c, 0x1d, 0x00, 0x41, + 0x41, 0x82, 0x03, 0xb0, 0x2c, 0x1d, 0x00, 0x44, 0x41, 0x82, 0x00, 0x68, 0x2c, 0x1d, 0x00, 0x50, + 0x41, 0x82, 0x00, 0x20, 0x2c, 0x1d, 0x00, 0x60, 0x41, 0x82, 0x00, 0x24, 0x2c, 0x1d, 0x00, 0x89, + 0x41, 0x82, 0x00, 0x50, 0x2c, 0x1d, 0x00, 0x99, 0x41, 0x82, 0x05, 0x64, 0x48, 0x00, 0x05, 0x68, + 0x80, 0x72, 0x00, 0x00, 0x48, 0x00, 0x04, 0x81, 0x48, 0x00, 0x05, 0x5c, 0x48, 0x00, 0x05, 0xe5, + 0x48, 0x00, 0x05, 0x54, 0x38, 0x80, 0x00, 0x01, 0x90, 0x92, 0x00, 0x00, 0x48, 0x00, 0x05, 0x48, + 0x48, 0x00, 0x04, 0x61, 0x3a, 0x00, 0x00, 0xa0, 0x63, 0xec, 0x26, 0xc4, 0x48, 0x00, 0x03, 0x6c, + 0x38, 0x60, 0x01, 0x20, 0x63, 0xec, 0x26, 0xc4, 0x48, 0x00, 0x04, 0x21, 0x48, 0x00, 0x05, 0x28, + 0x2f, 0x1d, 0x00, 0x10, 0x2e, 0x9d, 0x00, 0x44, 0x63, 0xe4, 0x1a, 0xb4, 0x3c, 0x60, 0x80, 0x00, + 0x60, 0x63, 0x03, 0x00, 0x48, 0x00, 0x05, 0x65, 0x38, 0x63, 0x0a, 0x00, 0x48, 0x00, 0x05, 0x5d, + 0x38, 0x63, 0x06, 0x00, 0x48, 0x00, 0x05, 0x55, 0x63, 0xec, 0x26, 0xb4, 0x92, 0xac, 0x00, 0x00, + 0x92, 0xac, 0x00, 0x04, 0x92, 0xac, 0x00, 0x08, 0x63, 0xe4, 0x26, 0xc4, 0x81, 0x24, 0x00, 0x18, + 0x80, 0x72, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x02, 0x40, 0x82, 0x00, 0x0c, 0x41, 0x96, 0x00, 0x0c, + 0x48, 0x00, 0x00, 0x20, 0x38, 0x60, 0x00, 0x00, 0x90, 0x6c, 0x00, 0x0c, 0x40, 0x82, 0x00, 0x14, + 0x40, 0x96, 0x00, 0x10, 0x61, 0x29, 0x04, 0x00, 0x91, 0x24, 0x00, 0x18, 0x48, 0x00, 0x02, 0x70, + 0x55, 0x29, 0x05, 0xa8, 0x91, 0x24, 0x00, 0x18, 0x41, 0x96, 0x04, 0xac, 0x41, 0x9a, 0x00, 0x08, + 0x39, 0x8c, 0x00, 0x04, 0x38, 0x60, 0x00, 0x04, 0x48, 0x00, 0x03, 0x61, 0x40, 0x99, 0x00, 0x10, + 0x39, 0x8c, 0x00, 0x04, 0x38, 0x60, 0x00, 0x04, 0x48, 0x00, 0x03, 0x51, 0x63, 0xe4, 0x26, 0xb4, + 0x80, 0x64, 0x00, 0x00, 0x80, 0x84, 0x00, 0x04, 0x7c, 0x72, 0xfb, 0xa6, 0x7c, 0x95, 0xfb, 0xa6, + 0x48, 0x00, 0x04, 0x74, 0x7c, 0x32, 0x43, 0xa6, 0x7c, 0x3a, 0x02, 0xa6, 0x7c, 0x73, 0x43, 0xa6, + 0x7c, 0x7b, 0x02, 0xa6, 0x54, 0x63, 0x05, 0xa8, 0x90, 0x60, 0x26, 0xdc, 0x54, 0x63, 0x06, 0x20, + 0x60, 0x63, 0x20, 0x00, 0x54, 0x63, 0x04, 0x5e, 0x7c, 0x7b, 0x03, 0xa6, 0x3c, 0x60, 0x80, 0x00, + 0x60, 0x63, 0x1a, 0xf4, 0x7c, 0x7a, 0x03, 0xa6, 0x4c, 0x00, 0x01, 0x2c, 0x7c, 0x00, 0x04, 0xac, + 0x4c, 0x00, 0x00, 0x64, 0x3c, 0x60, 0x80, 0x00, 0x60, 0x63, 0x26, 0xc4, 0x90, 0x23, 0x00, 0x14, + 0x7c, 0x61, 0x1b, 0x78, 0x7c, 0x73, 0x42, 0xa6, 0xbc, 0x41, 0x00, 0x24, 0x7c, 0x24, 0x0b, 0x78, + 0x7c, 0x32, 0x42, 0xa6, 0x90, 0x04, 0x00, 0x1c, 0x90, 0x24, 0x00, 0x20, 0x7c, 0x68, 0x02, 0xa6, + 0x90, 0x64, 0x00, 0x9c, 0x7c, 0x60, 0x00, 0x26, 0x90, 0x64, 0x00, 0x00, 0x7c, 0x61, 0x02, 0xa6, + 0x90, 0x64, 0x00, 0x04, 0x7c, 0x69, 0x02, 0xa6, 0x90, 0x64, 0x00, 0x08, 0x7c, 0x72, 0x02, 0xa6, + 0x90, 0x64, 0x00, 0x0c, 0x7c, 0x73, 0x02, 0xa6, 0x90, 0x64, 0x00, 0x10, 0x39, 0x20, 0x00, 0x00, + 0x7d, 0x32, 0xfb, 0xa6, 0x7d, 0x35, 0xfb, 0xa6, 0xd0, 0x04, 0x00, 0xa0, 0xd0, 0x24, 0x00, 0xa4, + 0xd0, 0x44, 0x00, 0xa8, 0xd0, 0x64, 0x00, 0xac, 0xd0, 0x84, 0x00, 0xb0, 0xd0, 0xa4, 0x00, 0xb4, + 0xd0, 0xc4, 0x00, 0xb8, 0xd0, 0xe4, 0x00, 0xbc, 0xd1, 0x04, 0x00, 0xc0, 0xd1, 0x24, 0x00, 0xc4, + 0xd1, 0x44, 0x00, 0xc8, 0xd1, 0x64, 0x00, 0xcc, 0xd1, 0x84, 0x00, 0xd0, 0xd1, 0xa4, 0x00, 0xd4, + 0xd1, 0xc4, 0x00, 0xd8, 0xd1, 0xe4, 0x00, 0xdc, 0xd2, 0x04, 0x00, 0xe0, 0xd2, 0x24, 0x00, 0xe4, + 0xd2, 0x44, 0x00, 0xe8, 0xd2, 0x64, 0x00, 0xec, 0xd2, 0x84, 0x00, 0xf0, 0xd2, 0xa4, 0x00, 0xf4, + 0xd2, 0xc4, 0x00, 0xf8, 0xd2, 0xe4, 0x00, 0xfc, 0xd3, 0x04, 0x01, 0x00, 0xd3, 0x24, 0x01, 0x04, + 0xd3, 0x44, 0x01, 0x08, 0xd3, 0x64, 0x01, 0x0c, 0xd3, 0x84, 0x01, 0x10, 0xd3, 0xa4, 0x01, 0x14, + 0xd3, 0xc4, 0x01, 0x18, 0xd3, 0xe4, 0x01, 0x1c, 0x3f, 0xe0, 0x80, 0x00, 0x63, 0xe5, 0x26, 0xb4, + 0x82, 0x05, 0x00, 0x00, 0x82, 0x25, 0x00, 0x04, 0x82, 0x65, 0x00, 0x0c, 0x2c, 0x13, 0x00, 0x00, + 0x41, 0x82, 0x00, 0x74, 0x2c, 0x13, 0x00, 0x02, 0x40, 0x82, 0x00, 0x18, 0x81, 0x24, 0x00, 0x14, + 0x39, 0x33, 0x00, 0x03, 0x91, 0x25, 0x00, 0x00, 0x91, 0x25, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x6c, + 0x7c, 0x10, 0x98, 0x00, 0x41, 0x82, 0x00, 0x38, 0x7c, 0x11, 0x98, 0x00, 0x41, 0x82, 0x00, 0x30, + 0x7d, 0x30, 0x8a, 0x14, 0x91, 0x25, 0x00, 0x0c, 0x82, 0x05, 0x00, 0x08, 0x2c, 0x10, 0x00, 0x00, + 0x41, 0x82, 0x00, 0x48, 0x80, 0x64, 0x00, 0x10, 0x7c, 0x10, 0x18, 0x00, 0x40, 0x82, 0x00, 0x10, + 0x3a, 0x00, 0x00, 0x00, 0x92, 0x05, 0x00, 0x08, 0x48, 0x00, 0x00, 0x30, 0x3a, 0x20, 0x00, 0x00, + 0x92, 0x25, 0x00, 0x0c, 0x81, 0x24, 0x00, 0x18, 0x61, 0x29, 0x04, 0x00, 0x91, 0x24, 0x00, 0x18, + 0x48, 0x00, 0x00, 0x30, 0x7e, 0x12, 0xfb, 0xa6, 0x7e, 0x35, 0xfb, 0xa6, 0x39, 0x20, 0x00, 0x01, + 0x91, 0x25, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x1c, 0x38, 0xa0, 0x00, 0x02, 0x63, 0xe4, 0x26, 0xa0, + 0x90, 0xa4, 0x00, 0x00, 0x38, 0x60, 0x00, 0x11, 0x48, 0x00, 0x01, 0xbd, 0x4b, 0xff, 0xfc, 0x1d, + 0x7c, 0x20, 0x00, 0xa6, 0x54, 0x21, 0x07, 0xfa, 0x54, 0x21, 0x04, 0x5e, 0x7c, 0x20, 0x01, 0x24, + 0x63, 0xe1, 0x26, 0xc4, 0x80, 0x61, 0x00, 0x00, 0x7c, 0x6f, 0xf1, 0x20, 0x80, 0x61, 0x00, 0x14, + 0x7c, 0x7a, 0x03, 0xa6, 0x80, 0x61, 0x00, 0x18, 0x7c, 0x7b, 0x03, 0xa6, 0x80, 0x61, 0x00, 0x9c, + 0x7c, 0x68, 0x03, 0xa6, 0xb8, 0x41, 0x00, 0x24, 0x80, 0x01, 0x00, 0x1c, 0x80, 0x21, 0x00, 0x20, + 0x4c, 0x00, 0x01, 0x2c, 0x7c, 0x00, 0x04, 0xac, 0x4c, 0x00, 0x00, 0x64, 0x92, 0xb2, 0x00, 0x00, + 0x48, 0x00, 0x02, 0x50, 0x2e, 0x9d, 0x00, 0x02, 0x38, 0x60, 0x00, 0x08, 0x63, 0xec, 0x26, 0xa8, + 0x48, 0x00, 0x00, 0xf9, 0x80, 0xac, 0x00, 0x00, 0x80, 0x6c, 0x00, 0x04, 0x98, 0x65, 0x00, 0x00, + 0x41, 0x94, 0x00, 0x10, 0xb0, 0x65, 0x00, 0x00, 0x41, 0x96, 0x00, 0x08, 0x90, 0x65, 0x00, 0x00, + 0x7c, 0x00, 0x28, 0xac, 0x7c, 0x00, 0x04, 0xac, 0x7c, 0x00, 0x2f, 0xac, 0x4c, 0x00, 0x01, 0x2c, + 0x48, 0x00, 0x02, 0x04, 0x48, 0x00, 0x01, 0x1d, 0x38, 0x60, 0x00, 0x04, 0x63, 0xec, 0x26, 0xa8, + 0x48, 0x00, 0x00, 0xb9, 0x82, 0x0c, 0x00, 0x00, 0x63, 0xec, 0x27, 0xe8, 0x48, 0x00, 0x00, 0x1c, + 0x48, 0x00, 0x01, 0x01, 0x38, 0x60, 0x00, 0x08, 0x63, 0xec, 0x26, 0xa8, 0x48, 0x00, 0x00, 0x9d, + 0x82, 0x0c, 0x00, 0x04, 0x81, 0x8c, 0x00, 0x00, 0x63, 0xfb, 0x26, 0xb0, 0x3a, 0x20, 0x0f, 0x80, + 0x48, 0x00, 0x02, 0x3d, 0x41, 0x82, 0x00, 0x20, 0x7e, 0x23, 0x8b, 0x78, 0x48, 0x00, 0x00, 0x7d, + 0x48, 0x00, 0x00, 0xd1, 0x41, 0x82, 0xff, 0xfc, 0x7d, 0x8c, 0x72, 0x14, 0x35, 0x6b, 0xff, 0xff, + 0x41, 0x81, 0xff, 0xe8, 0x80, 0x7b, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x08, + 0x48, 0x00, 0x00, 0x59, 0x7c, 0x00, 0x60, 0xac, 0x7c, 0x00, 0x04, 0xac, 0x7c, 0x00, 0x67, 0xac, + 0x4c, 0x00, 0x01, 0x2c, 0x48, 0x00, 0x01, 0x80, 0x7f, 0xc8, 0x02, 0xa6, 0x3c, 0x60, 0xa0, 0x00, + 0x48, 0x00, 0x00, 0x15, 0x76, 0x03, 0x08, 0x00, 0x56, 0x1d, 0x86, 0x3e, 0x7f, 0xc8, 0x03, 0xa6, + 0x4e, 0x80, 0x00, 0x20, 0x92, 0xf8, 0x68, 0x14, 0x90, 0x78, 0x68, 0x24, 0x92, 0xd8, 0x68, 0x20, + 0x80, 0xb8, 0x68, 0x20, 0x70, 0xa5, 0x00, 0x01, 0x40, 0x82, 0xff, 0xf8, 0x82, 0x18, 0x68, 0x24, + 0x90, 0xb8, 0x68, 0x14, 0x4e, 0x80, 0x00, 0x20, 0x7d, 0x48, 0x02, 0xa6, 0x7c, 0x69, 0x03, 0xa6, + 0x39, 0xc0, 0x00, 0x00, 0x48, 0x00, 0x00, 0x79, 0x48, 0x00, 0x00, 0x75, 0x4b, 0xff, 0xff, 0xad, + 0x41, 0x82, 0xff, 0xf4, 0x7f, 0xae, 0x61, 0xae, 0x39, 0xce, 0x00, 0x01, 0x42, 0x00, 0xff, 0xe8, + 0x7d, 0x48, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x7d, 0x48, 0x02, 0xa6, 0x7c, 0x69, 0x03, 0xa6, + 0x39, 0xc0, 0x00, 0x00, 0x7c, 0x6c, 0x70, 0xae, 0x48, 0x00, 0x00, 0x1d, 0x41, 0x82, 0xff, 0xf8, + 0x39, 0xce, 0x00, 0x01, 0x42, 0x00, 0xff, 0xf0, 0x7d, 0x48, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, + 0x38, 0x60, 0x00, 0xaa, 0x7f, 0xc8, 0x02, 0xa6, 0x54, 0x63, 0xa0, 0x16, 0x64, 0x63, 0xb0, 0x00, + 0x3a, 0xc0, 0x00, 0x19, 0x3a, 0xe0, 0x00, 0xd0, 0x3f, 0x00, 0xcd, 0x00, 0x4b, 0xff, 0xff, 0x69, + 0x56, 0x03, 0x37, 0xff, 0x7f, 0xc8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x7f, 0xc8, 0x02, 0xa6, + 0x3c, 0x60, 0xd0, 0x00, 0x4b, 0xff, 0xff, 0x51, 0x56, 0x03, 0x37, 0xff, 0x41, 0x82, 0xff, 0xf4, + 0x7f, 0xc8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x4b, 0xff, 0xff, 0xb9, 0x38, 0x60, 0x00, 0x08, + 0x63, 0xec, 0x26, 0xa8, 0x4b, 0xff, 0xff, 0x55, 0x80, 0xac, 0x00, 0x04, 0x81, 0x8c, 0x00, 0x00, + 0x63, 0xfb, 0x26, 0xb0, 0x62, 0xb1, 0xf8, 0x00, 0x7e, 0x0c, 0x28, 0x50, 0x48, 0x00, 0x00, 0xf1, + 0x41, 0x81, 0x00, 0x10, 0x82, 0x3b, 0x00, 0x00, 0x2c, 0x11, 0x00, 0x00, 0x41, 0x82, 0x00, 0x68, + 0x7e, 0x23, 0x8b, 0x78, 0x4b, 0xff, 0xff, 0x55, 0x4b, 0xff, 0xff, 0xa5, 0x4b, 0xff, 0xff, 0xa1, + 0x4b, 0xff, 0xfe, 0xd9, 0x41, 0x82, 0xff, 0xf4, 0x2c, 0x1d, 0x00, 0xcc, 0x41, 0x82, 0x00, 0x48, + 0x2c, 0x1d, 0x00, 0xbb, 0x41, 0x82, 0xff, 0xdc, 0x2c, 0x1d, 0x00, 0xaa, 0x40, 0x82, 0xff, 0xdc, + 0x7d, 0x8c, 0x72, 0x14, 0x35, 0x6b, 0xff, 0xff, 0x41, 0x80, 0x00, 0x2c, 0x4b, 0xff, 0xff, 0xb4, + 0x7e, 0xb5, 0xfb, 0xa6, 0x7e, 0xb2, 0xfb, 0xa6, 0x63, 0xe4, 0x26, 0xc4, 0x81, 0x24, 0x00, 0x18, + 0x55, 0x29, 0x05, 0xa8, 0x91, 0x24, 0x00, 0x18, 0x48, 0x00, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x80, + 0x4b, 0xff, 0xff, 0x25, 0x80, 0x92, 0x00, 0x00, 0x2c, 0x04, 0x00, 0x00, 0x40, 0x82, 0xf9, 0xf8, + 0xb3, 0x94, 0x40, 0x10, 0xc8, 0x41, 0x00, 0x98, 0xc8, 0x61, 0x00, 0xa0, 0x7f, 0x20, 0x00, 0xa6, + 0x80, 0x01, 0x00, 0xac, 0x7c, 0x08, 0x03, 0xa6, 0x80, 0x01, 0x00, 0x0c, 0x7c, 0x0f, 0xf1, 0x20, + 0x80, 0x01, 0x00, 0x10, 0x7c, 0x09, 0x03, 0xa6, 0x80, 0x01, 0x00, 0x14, 0x7c, 0x01, 0x03, 0xa6, + 0xb8, 0x61, 0x00, 0x18, 0x80, 0x01, 0x00, 0x08, 0x38, 0x21, 0x00, 0xa8, 0x4c, 0x00, 0x01, 0x2c, + 0x7c, 0x00, 0x04, 0xac, 0x4e, 0x80, 0x00, 0x20, 0x7e, 0x23, 0x20, 0x50, 0x3c, 0xa0, 0x48, 0x00, + 0x52, 0x25, 0x01, 0xba, 0x90, 0xa3, 0x00, 0x00, 0x7c, 0x00, 0x18, 0xac, 0x7c, 0x00, 0x04, 0xac, + 0x7c, 0x00, 0x1f, 0xac, 0x4c, 0x00, 0x01, 0x2c, 0x4e, 0x80, 0x00, 0x20, 0x7d, 0x70, 0x8b, 0xd7, + 0x7d, 0x4b, 0x89, 0xd6, 0x7d, 0x4a, 0x80, 0x50, 0x91, 0x5b, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, + 0x7f, 0xa8, 0x02, 0xa6, 0x63, 0xef, 0x27, 0xe8, 0x63, 0xe7, 0x18, 0x08, 0x3c, 0xc0, 0x80, 0x00, + 0x7c, 0xd0, 0x33, 0x78, 0x39, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x00, 0xd0, 0x60, 0x63, 0xc0, 0xde, + 0x80, 0x8f, 0x00, 0x00, 0x7c, 0x03, 0x20, 0x00, 0x40, 0x82, 0x00, 0x18, 0x80, 0x8f, 0x00, 0x04, + 0x7c, 0x03, 0x20, 0x00, 0x40, 0x82, 0x00, 0x0c, 0x39, 0xef, 0x00, 0x08, 0x48, 0x00, 0x00, 0x0c, + 0x7f, 0xa8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x6f, 0x00, 0x00, 0x80, 0x8f, 0x00, 0x04, + 0x39, 0xef, 0x00, 0x08, 0x71, 0x09, 0x00, 0x01, 0x2f, 0x89, 0x00, 0x00, 0x39, 0x20, 0x00, 0x00, + 0x54, 0x6a, 0x1f, 0x7e, 0x54, 0x65, 0x3f, 0x7e, 0x74, 0x6b, 0x10, 0x00, 0x54, 0x63, 0x01, 0xfe, + 0x40, 0x82, 0x00, 0x0c, 0x54, 0xcc, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x08, 0x7e, 0x0c, 0x83, 0x78, + 0x2e, 0x05, 0x00, 0x00, 0x2c, 0x0a, 0x00, 0x01, 0x41, 0xa0, 0x00, 0x2c, 0x41, 0xa2, 0x00, 0xe4, + 0x2c, 0x0a, 0x00, 0x03, 0x41, 0xa0, 0x01, 0xb0, 0x41, 0x82, 0x02, 0x54, 0x2c, 0x0a, 0x00, 0x05, + 0x41, 0x80, 0x02, 0xdc, 0x41, 0xa2, 0x04, 0xe8, 0x2c, 0x0a, 0x00, 0x07, 0x41, 0xa0, 0x05, 0x14, + 0x48, 0x00, 0x05, 0xf8, 0x7d, 0x8c, 0x1a, 0x14, 0x2c, 0x05, 0x00, 0x03, 0x41, 0x82, 0x00, 0x48, + 0x41, 0x81, 0x00, 0x60, 0x40, 0xbe, 0xff, 0x84, 0x2e, 0x05, 0x00, 0x01, 0x41, 0x91, 0x00, 0x2c, + 0x54, 0x8a, 0x84, 0x3e, 0x41, 0x92, 0x00, 0x10, 0x7c, 0x89, 0x61, 0xae, 0x39, 0x29, 0x00, 0x01, + 0x48, 0x00, 0x00, 0x0c, 0x7c, 0x89, 0x63, 0x2e, 0x39, 0x29, 0x00, 0x02, 0x35, 0x4a, 0xff, 0xff, + 0x40, 0xa0, 0xff, 0xe4, 0x4b, 0xff, 0xff, 0x54, 0x55, 0x8c, 0x00, 0x3a, 0x90, 0x8c, 0x00, 0x00, + 0x4b, 0xff, 0xff, 0x48, 0x7c, 0x89, 0x23, 0x78, 0x40, 0x9e, 0x04, 0xd0, 0x35, 0x29, 0xff, 0xff, + 0x41, 0x80, 0x04, 0xc8, 0x7c, 0xa9, 0x78, 0xae, 0x7c, 0xa9, 0x61, 0xae, 0x4b, 0xff, 0xff, 0xf0, + 0x39, 0xef, 0x00, 0x08, 0x40, 0xbe, 0xff, 0x24, 0x80, 0xaf, 0xff, 0xf8, 0x81, 0x6f, 0xff, 0xfc, + 0x54, 0xb1, 0x04, 0x3e, 0x54, 0xaa, 0x85, 0x3e, 0x54, 0xa5, 0x27, 0x3e, 0x2e, 0x85, 0x00, 0x01, + 0x41, 0x96, 0x00, 0x10, 0x41, 0xb5, 0x00, 0x14, 0x7c, 0x89, 0x61, 0xae, 0x48, 0x00, 0x00, 0x10, + 0x7c, 0x89, 0x63, 0x2e, 0x48, 0x00, 0x00, 0x08, 0x7c, 0x89, 0x61, 0x2e, 0x7c, 0x84, 0x5a, 0x14, + 0x7d, 0x29, 0x8a, 0x14, 0x35, 0x4a, 0xff, 0xff, 0x40, 0x80, 0xff, 0xd4, 0x4b, 0xff, 0xfe, 0xdc, + 0x54, 0x69, 0x07, 0xff, 0x41, 0x82, 0x00, 0x10, 0x55, 0x08, 0xf8, 0x7e, 0x71, 0x09, 0x00, 0x01, + 0x2f, 0x89, 0x00, 0x00, 0x2e, 0x85, 0x00, 0x04, 0x2d, 0x8a, 0x00, 0x05, 0x7d, 0x13, 0x43, 0x78, + 0x52, 0x68, 0x08, 0x3c, 0x40, 0x9e, 0x00, 0x78, 0x41, 0x8d, 0x04, 0xbc, 0x7d, 0x8c, 0x1a, 0x14, + 0x41, 0x8c, 0x00, 0x0c, 0x41, 0x94, 0x00, 0x30, 0x48, 0x00, 0x00, 0x1c, 0x40, 0x94, 0x00, 0x10, + 0x55, 0x8c, 0x00, 0x3a, 0x81, 0x6c, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1c, 0x55, 0x8c, 0x00, 0x3c, + 0xa1, 0x6c, 0x00, 0x00, 0x7c, 0x89, 0x20, 0xf8, 0x55, 0x29, 0x84, 0x3e, 0x7d, 0x6b, 0x48, 0x38, + 0x54, 0x84, 0x04, 0x3e, 0x7f, 0x0b, 0x20, 0x40, 0x70, 0xa9, 0x00, 0x03, 0x41, 0x82, 0x00, 0x18, + 0x2c, 0x09, 0x00, 0x02, 0x41, 0x82, 0x00, 0x18, 0x41, 0x81, 0x00, 0x1c, 0x40, 0x9a, 0x00, 0x20, + 0x48, 0x00, 0x00, 0x18, 0x41, 0x9a, 0x00, 0x18, 0x48, 0x00, 0x00, 0x10, 0x41, 0x99, 0x00, 0x10, + 0x48, 0x00, 0x00, 0x08, 0x41, 0x98, 0x00, 0x08, 0x61, 0x08, 0x00, 0x01, 0x40, 0x8e, 0xfe, 0x3c, + 0x41, 0x94, 0xfe, 0x38, 0x81, 0x6f, 0xff, 0xf8, 0x40, 0x9e, 0x00, 0x20, 0x70, 0x6c, 0x00, 0x08, + 0x41, 0x82, 0x00, 0x0c, 0x71, 0x0c, 0x00, 0x01, 0x41, 0x82, 0x00, 0x10, 0x39, 0x8b, 0x00, 0x10, + 0x51, 0x8b, 0x03, 0x36, 0x48, 0x00, 0x00, 0x08, 0x55, 0x6b, 0x07, 0x16, 0x91, 0x6f, 0xff, 0xf8, + 0x4b, 0xff, 0xfe, 0x08, 0x40, 0xbe, 0xfe, 0x04, 0x54, 0x69, 0x16, 0xba, 0x54, 0x6e, 0x87, 0xfe, + 0x2d, 0x8e, 0x00, 0x00, 0x2e, 0x05, 0x00, 0x04, 0x70, 0xae, 0x00, 0x03, 0x2e, 0x8e, 0x00, 0x02, + 0x41, 0x94, 0x00, 0x14, 0x41, 0x96, 0x00, 0x50, 0x7c, 0x64, 0x07, 0x34, 0x7c, 0x84, 0x7a, 0x14, + 0x48, 0x00, 0x00, 0x68, 0x54, 0x65, 0xa7, 0xff, 0x41, 0x82, 0x00, 0x0c, 0x7d, 0x27, 0x48, 0x2e, + 0x7c, 0x84, 0x4a, 0x14, 0x41, 0x8e, 0x00, 0x08, 0x7c, 0x8c, 0x22, 0x14, 0x2e, 0x8e, 0x00, 0x01, + 0x41, 0x96, 0x00, 0x08, 0x80, 0x84, 0x00, 0x00, 0x54, 0x63, 0x67, 0xff, 0x41, 0x82, 0x00, 0x3c, + 0x40, 0x90, 0x00, 0x0c, 0x7c, 0x84, 0x32, 0x14, 0x48, 0x00, 0x00, 0x30, 0x7c, 0x84, 0x82, 0x14, + 0x48, 0x00, 0x00, 0x28, 0x54, 0x65, 0xa7, 0xff, 0x41, 0x82, 0x00, 0x0c, 0x7d, 0x27, 0x48, 0x2e, + 0x7c, 0x84, 0x4a, 0x14, 0x40, 0x90, 0x00, 0x0c, 0x7c, 0xcc, 0x21, 0x2e, 0x4b, 0xff, 0xfd, 0x7c, + 0x7e, 0x0c, 0x21, 0x2e, 0x4b, 0xff, 0xfd, 0x74, 0x40, 0x90, 0x00, 0x0c, 0x7c, 0x86, 0x23, 0x78, + 0x4b, 0xff, 0xfd, 0x68, 0x7c, 0x90, 0x23, 0x78, 0x4b, 0xff, 0xfd, 0x60, 0x54, 0x89, 0x1e, 0x78, + 0x39, 0x29, 0x00, 0x40, 0x2c, 0x05, 0x00, 0x02, 0x41, 0x80, 0x00, 0x4c, 0x54, 0x6b, 0x67, 0xbf, + 0x2c, 0x0b, 0x00, 0x01, 0x41, 0x80, 0x00, 0x14, 0x41, 0x82, 0x00, 0x08, 0x48, 0x00, 0x00, 0x10, + 0x41, 0xbe, 0xfd, 0x38, 0x48, 0x00, 0x00, 0x08, 0x40, 0xbe, 0xfd, 0x30, 0x2c, 0x05, 0x00, 0x03, + 0x41, 0x81, 0x00, 0x10, 0x41, 0xa2, 0x00, 0x10, 0x7d, 0xe7, 0x48, 0x2e, 0x4b, 0xff, 0xfd, 0x1c, + 0x7d, 0xe7, 0x49, 0x2e, 0x7c, 0x64, 0x07, 0x34, 0x54, 0x84, 0x1a, 0x78, 0x7d, 0xef, 0x22, 0x14, + 0x4b, 0xff, 0xfd, 0x08, 0x40, 0xbe, 0xfd, 0x04, 0x7c, 0xa7, 0x4a, 0x14, 0x40, 0x92, 0x00, 0x14, + 0x54, 0x64, 0x04, 0x3e, 0x91, 0xe5, 0x00, 0x00, 0x90, 0x85, 0x00, 0x04, 0x4b, 0xff, 0xfc, 0xec, + 0x81, 0x25, 0x00, 0x04, 0x2c, 0x09, 0x00, 0x00, 0x41, 0xa2, 0xfc, 0xe0, 0x39, 0x29, 0xff, 0xff, + 0x91, 0x25, 0x00, 0x04, 0x81, 0xe5, 0x00, 0x00, 0x4b, 0xff, 0xfc, 0xd0, 0x40, 0xbe, 0xfc, 0xcc, + 0x54, 0x6b, 0x16, 0xba, 0x7f, 0x47, 0x5a, 0x14, 0x81, 0x3a, 0x00, 0x00, 0x54, 0x6e, 0x67, 0xbe, + 0x41, 0x92, 0x00, 0x84, 0x2e, 0x05, 0x00, 0x05, 0x40, 0x90, 0x01, 0x74, 0x2e, 0x05, 0x00, 0x03, + 0x40, 0x90, 0x00, 0x90, 0x2e, 0x05, 0x00, 0x01, 0x54, 0x65, 0x87, 0xff, 0x41, 0x82, 0x00, 0x08, + 0x7c, 0x8c, 0x22, 0x14, 0x2f, 0x0e, 0x00, 0x01, 0x40, 0x92, 0x00, 0x24, 0x41, 0xb9, 0x00, 0x18, + 0x41, 0x9a, 0x00, 0x0c, 0x88, 0x84, 0x00, 0x00, 0x48, 0x00, 0x00, 0xf8, 0xa0, 0x84, 0x00, 0x00, + 0x48, 0x00, 0x00, 0xf0, 0x80, 0x84, 0x00, 0x00, 0x48, 0x00, 0x00, 0xe8, 0x54, 0x73, 0xe5, 0x3e, + 0x41, 0xb9, 0x00, 0x20, 0x41, 0x9a, 0x00, 0x10, 0x99, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x01, + 0x48, 0x00, 0x00, 0x18, 0xb1, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x02, 0x48, 0x00, 0x00, 0x0c, + 0x91, 0x24, 0x00, 0x00, 0x38, 0x84, 0x00, 0x04, 0x36, 0x73, 0xff, 0xff, 0x40, 0x80, 0xff, 0xd4, + 0x4b, 0xff, 0xfc, 0x38, 0x54, 0x65, 0x87, 0xff, 0x41, 0x82, 0x00, 0x08, 0x7c, 0x84, 0x62, 0x14, + 0x71, 0xc5, 0x00, 0x01, 0x41, 0x82, 0x00, 0x9c, 0x7c, 0x84, 0x4a, 0x14, 0x48, 0x00, 0x00, 0x94, + 0x54, 0x6a, 0x87, 0xbe, 0x54, 0x8e, 0x16, 0xba, 0x7e, 0x67, 0x72, 0x14, 0x40, 0x92, 0x00, 0x08, + 0x3a, 0x6f, 0xff, 0xfc, 0x80, 0x9a, 0x00, 0x00, 0x81, 0x33, 0x00, 0x00, 0x71, 0x4b, 0x00, 0x01, + 0x41, 0x82, 0x00, 0x08, 0x7c, 0x9a, 0x23, 0x78, 0x71, 0x4b, 0x00, 0x02, 0x41, 0x82, 0x00, 0x10, + 0x7d, 0x33, 0x4b, 0x78, 0x40, 0xb2, 0x00, 0x08, 0x7e, 0x6c, 0x9a, 0x14, 0x54, 0x65, 0x67, 0x3f, + 0x2c, 0x05, 0x00, 0x09, 0x40, 0x80, 0x00, 0x54, 0x48, 0x00, 0x00, 0x79, 0x7c, 0x89, 0x22, 0x14, + 0x48, 0x00, 0x00, 0x40, 0x7c, 0x89, 0x21, 0xd6, 0x48, 0x00, 0x00, 0x38, 0x7d, 0x24, 0x23, 0x78, + 0x48, 0x00, 0x00, 0x30, 0x7d, 0x24, 0x20, 0x38, 0x48, 0x00, 0x00, 0x28, 0x7d, 0x24, 0x22, 0x78, + 0x48, 0x00, 0x00, 0x20, 0x7d, 0x24, 0x20, 0x30, 0x48, 0x00, 0x00, 0x18, 0x7d, 0x24, 0x24, 0x30, + 0x48, 0x00, 0x00, 0x10, 0x5d, 0x24, 0x20, 0x3e, 0x48, 0x00, 0x00, 0x08, 0x7d, 0x24, 0x26, 0x30, + 0x90, 0x9a, 0x00, 0x00, 0x4b, 0xff, 0xfb, 0x84, 0x2c, 0x05, 0x00, 0x0a, 0x41, 0x81, 0xfb, 0x7c, + 0xc0, 0x5a, 0x00, 0x00, 0xc0, 0x73, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0c, 0xec, 0x43, 0x10, 0x2a, + 0x48, 0x00, 0x00, 0x08, 0xec, 0x43, 0x00, 0xb2, 0xd0, 0x5a, 0x00, 0x00, 0x4b, 0xff, 0xfb, 0x5c, + 0x7d, 0x48, 0x02, 0xa6, 0x54, 0xa5, 0x1e, 0x78, 0x7d, 0x4a, 0x2a, 0x14, 0x80, 0x9a, 0x00, 0x00, + 0x81, 0x33, 0x00, 0x00, 0x7d, 0x48, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x40, 0xbe, 0xfb, 0x3c, + 0x54, 0x69, 0xc0, 0x3e, 0x7d, 0x8e, 0x63, 0x78, 0x48, 0x00, 0x00, 0x35, 0x41, 0x92, 0x00, 0x0c, + 0x7e, 0x31, 0x22, 0x14, 0x48, 0x00, 0x00, 0x08, 0x7d, 0x29, 0x22, 0x14, 0x54, 0x64, 0xc4, 0x3f, + 0x38, 0xa0, 0x00, 0x00, 0x41, 0x82, 0xfb, 0x14, 0x7d, 0x45, 0x88, 0xae, 0x7d, 0x45, 0x49, 0xae, + 0x38, 0xa5, 0x00, 0x01, 0x7c, 0x05, 0x20, 0x00, 0x4b, 0xff, 0xff, 0xec, 0x2e, 0x8a, 0x00, 0x04, + 0x55, 0x31, 0x36, 0xba, 0x2c, 0x11, 0x00, 0x3c, 0x7e, 0x27, 0x88, 0x2e, 0x40, 0x82, 0x00, 0x08, + 0x7d, 0xd1, 0x73, 0x78, 0x41, 0x96, 0x00, 0x08, 0xa2, 0x31, 0x00, 0x00, 0x55, 0x29, 0x56, 0xba, + 0x2c, 0x09, 0x00, 0x3c, 0x7d, 0x27, 0x48, 0x2e, 0x40, 0x82, 0x00, 0x08, 0x7d, 0xc9, 0x73, 0x78, + 0x41, 0x96, 0x00, 0x08, 0xa1, 0x29, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, 0x2c, 0x05, 0x00, 0x04, + 0x40, 0x80, 0x00, 0x28, 0x7c, 0x89, 0x23, 0x78, 0x7d, 0xc3, 0x62, 0x14, 0x55, 0xce, 0x00, 0x3c, + 0x4b, 0xff, 0xff, 0xad, 0x7c, 0x84, 0x20, 0xf8, 0x54, 0x84, 0x04, 0x3e, 0x7d, 0x2b, 0x20, 0x38, + 0x7e, 0x24, 0x20, 0x38, 0x4b, 0xff, 0xfb, 0xbc, 0x54, 0x6b, 0xe4, 0x3e, 0x4b, 0xff, 0xfb, 0xb4, + 0x7c, 0x9a, 0x23, 0x78, 0x54, 0x84, 0x18, 0x38, 0x40, 0x92, 0x00, 0x20, 0x40, 0x9e, 0x00, 0x0c, + 0x7d, 0xe8, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x7d, 0xe4, 0x7a, 0x14, 0x39, 0xef, 0x00, 0x07, + 0x55, 0xef, 0x00, 0x38, 0x4b, 0xff, 0xfa, 0x64, 0x2e, 0x05, 0x00, 0x03, 0x41, 0x91, 0x00, 0x5c, + 0x3c, 0xa0, 0x48, 0x00, 0x7d, 0x83, 0x62, 0x14, 0x55, 0x8c, 0x00, 0x3a, 0x40, 0x92, 0x00, 0x20, + 0x40, 0xbe, 0xfa, 0x48, 0x57, 0x44, 0x00, 0x3a, 0x7c, 0x8c, 0x20, 0x50, 0x50, 0x85, 0x01, 0xba, + 0x50, 0x65, 0x07, 0xfe, 0x90, 0xac, 0x00, 0x00, 0x4b, 0xff, 0xfa, 0x30, 0x40, 0xbe, 0xff, 0xbc, + 0x7d, 0x2c, 0x78, 0x50, 0x51, 0x25, 0x01, 0xba, 0x90, 0xac, 0x00, 0x00, 0x39, 0x8c, 0x00, 0x04, + 0x7d, 0x6f, 0x22, 0x14, 0x39, 0x6b, 0xff, 0xfc, 0x7d, 0x2b, 0x60, 0x50, 0x51, 0x25, 0x01, 0xba, + 0x90, 0xab, 0x00, 0x00, 0x4b, 0xff, 0xff, 0x94, 0x2e, 0x05, 0x00, 0x06, 0x41, 0x92, 0x00, 0x28, + 0x4b, 0xff, 0xfb, 0x20, 0x55, 0x8c, 0x84, 0x3e, 0x57, 0x44, 0x84, 0x3e, 0x57, 0x5a, 0x04, 0x3e, + 0x7c, 0x0c, 0x20, 0x00, 0x41, 0x80, 0xfb, 0xa4, 0x7c, 0x0c, 0xd0, 0x00, 0x40, 0x80, 0xfb, 0x9c, + 0x4b, 0xff, 0xf9, 0xd8, 0x57, 0x45, 0xff, 0xfe, 0x68, 0xa5, 0x00, 0x01, 0x71, 0x03, 0x00, 0x01, + 0x7c, 0x05, 0x18, 0x00, 0x41, 0x82, 0x00, 0x1c, 0x51, 0x1a, 0x0f, 0xbc, 0x6b, 0x5a, 0x00, 0x02, + 0x57, 0x45, 0xff, 0xff, 0x41, 0x82, 0x00, 0x08, 0x6b, 0x5a, 0x00, 0x01, 0x93, 0x4f, 0xff, 0xfc, + 0x53, 0x48, 0x07, 0xfe, 0x4b, 0xff, 0xf9, 0xa4, 0x2c, 0x0b, 0x00, 0x00, 0x40, 0x82, 0xf9, 0x94, + 0x40, 0x92, 0x00, 0x0c, 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14, 0x54, 0x69, 0x06, 0xff, + 0x40, 0x82, 0x00, 0x08, 0x40, 0x9e, 0x00, 0x10, 0x54, 0x65, 0x67, 0xfe, 0x7d, 0x08, 0x4c, 0x30, + 0x7d, 0x08, 0x2a, 0x78, 0x54, 0x85, 0x00, 0x1f, 0x41, 0x82, 0x00, 0x08, 0x7c, 0xa6, 0x2b, 0x78, + 0x54, 0x85, 0x80, 0x1f, 0x41, 0x82, 0x00, 0x08, 0x7c, 0xb0, 0x2b, 0x78, 0x4b, 0xff, 0xf9, 0x5c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +}; +const int kenobiwii_size = sizeof(kenobiwii); diff --git a/source/libwbfs/libwbfs.c b/source/libwbfs/libwbfs.c new file mode 100644 index 00000000..16faaebe --- /dev/null +++ b/source/libwbfs/libwbfs.c @@ -0,0 +1,618 @@ +// Copyright 2009 Kwiirk +// Licensed under the terms of the GNU GPL, version 2 +// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + + +#include "libwbfs.h" + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define ERROR(x) do {wbfs_error(x);goto error;}while(0) +#define ALIGN_LBA(x) (((x)+p->hd_sec_sz-1)&(~(p->hd_sec_sz-1))) +static int force_mode=0; +void wbfs_set_force_mode(int force) +{ + force_mode = force; +} +static u8 size_to_shift(u32 size) +{ + u8 ret = 0; + while(size) + { + ret++; + size>>=1; + } + return ret-1; +} +#define read_le32_unaligned(x) ((x)[0]|((x)[1]<<8)|((x)[2]<<16)|((x)[3]<<24)) + + +wbfs_t*wbfs_open_hd(rw_sector_callback_t read_hdsector, + rw_sector_callback_t write_hdsector, + void *callback_data, + int hd_sector_size, int num_hd_sector __attribute((unused)), int reset) +{ + int i=num_hd_sector,ret; + u8 *ptr,*tmp_buffer = wbfs_ioalloc(hd_sector_size); + u8 part_table[16*4]; + ret = read_hdsector(callback_data,0,1,tmp_buffer); + if(ret) + return 0; + //find wbfs partition + wbfs_memcpy(part_table,tmp_buffer+0x1be,16*4); + ptr = part_table; + for(i=0;i<4;i++,ptr+=16) + { + u32 part_lba = read_le32_unaligned(ptr+0x8); + wbfs_head_t *head = (wbfs_head_t *)tmp_buffer; + ret = read_hdsector(callback_data,part_lba,1,tmp_buffer); + // verify there is the magic. + if (head->magic == wbfs_htonl(WBFS_MAGIC)) + { + wbfs_t*p = wbfs_open_partition(read_hdsector,write_hdsector, + callback_data,hd_sector_size,0,part_lba,reset); + return p; + } + } + if(reset)// XXX make a empty hd partition.. + { + } + return 0; +} +wbfs_t*wbfs_open_partition(rw_sector_callback_t read_hdsector, + rw_sector_callback_t write_hdsector, + void *callback_data, + int hd_sector_size, int num_hd_sector, u32 part_lba, int reset) +{ + wbfs_t *p = wbfs_malloc(sizeof(wbfs_t)); + + wbfs_head_t *head = wbfs_ioalloc(hd_sector_size?hd_sector_size:512); + + //constants, but put here for consistancy + p->wii_sec_sz = 0x8000; + p->wii_sec_sz_s = size_to_shift(0x8000); + p->n_wii_sec = (num_hd_sector/0x8000)*hd_sector_size; + p->n_wii_sec_per_disc = 143432*2;//support for double layers discs.. + p->head = head; + p->part_lba = part_lba; + // init the partition + if (reset) + { + u8 sz_s; + wbfs_memset(head,0,hd_sector_size); + head->magic = wbfs_htonl(WBFS_MAGIC); + head->hd_sec_sz_s = size_to_shift(hd_sector_size); + head->n_hd_sec = wbfs_htonl(num_hd_sector); + // choose minimum wblk_sz that fits this partition size + for(sz_s=6;sz_s<11;sz_s++) + { + // ensure that wbfs_sec_sz is big enough to address every blocks using 16 bits + if(p->n_wii_sec <((1U<<16)*(1<wbfs_sec_sz_s = sz_s+p->wii_sec_sz_s; + }else + read_hdsector(callback_data,p->part_lba,1,head); + if (head->magic != wbfs_htonl(WBFS_MAGIC)) + ERROR("bad magic"); + if(!force_mode && hd_sector_size && head->hd_sec_sz_s != size_to_shift(hd_sector_size)) + ERROR("hd sector size doesn't match"); + if(!force_mode && num_hd_sector && head->n_hd_sec != wbfs_htonl(num_hd_sector)) + ERROR("hd num sector doesn't match"); + p->hd_sec_sz = 1<hd_sec_sz_s; + p->hd_sec_sz_s = head->hd_sec_sz_s; + p->n_hd_sec = wbfs_ntohl(head->n_hd_sec); + + p->n_wii_sec = (p->n_hd_sec/p->wii_sec_sz)*(p->hd_sec_sz); + + p->wbfs_sec_sz_s = head->wbfs_sec_sz_s; + p->wbfs_sec_sz = 1<wbfs_sec_sz_s; + p->n_wbfs_sec = p->n_wii_sec >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s); + p->n_wbfs_sec_per_disc = p->n_wii_sec_per_disc >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s); + p->disc_info_sz = ALIGN_LBA(sizeof(wbfs_disc_info_t) + p->n_wbfs_sec_per_disc*2); + + //printf("hd_sector_size %X wii_sector size %X wbfs sector_size %X\n",p->hd_sec_sz,p->wii_sec_sz,p->wbfs_sec_sz); + p->read_hdsector = read_hdsector; + p->write_hdsector = write_hdsector; + p->callback_data = callback_data; + + p->freeblks_lba = (p->wbfs_sec_sz - p->n_wbfs_sec/8)>>p->hd_sec_sz_s; + + if(!reset) + p->freeblks = 0; // will alloc and read only if needed + else + { + // init with all free blocks + p->freeblks = wbfs_ioalloc(ALIGN_LBA(p->n_wbfs_sec/8)); + wbfs_memset(p->freeblks,0xff,p->n_wbfs_sec/8); + } + p->max_disc = (p->freeblks_lba-1)/(p->disc_info_sz>>p->hd_sec_sz_s); + if(p->max_disc > p->hd_sec_sz - sizeof(wbfs_head_t)) + p->max_disc = p->hd_sec_sz - sizeof(wbfs_head_t); + + p->tmp_buffer = wbfs_ioalloc(p->hd_sec_sz); + p->n_disc_open = 0; + return p; +error: + wbfs_free(p); + wbfs_iofree(head); + return 0; + +} + +void wbfs_sync(wbfs_t*p) +{ + // copy back descriptors + if(p->write_hdsector){ + p->write_hdsector(p->callback_data,p->part_lba+0,1, p->head); + + if(p->freeblks) + p->write_hdsector(p->callback_data,p->part_lba+p->freeblks_lba,ALIGN_LBA(p->n_wbfs_sec/8)>>p->hd_sec_sz_s, p->freeblks); + } +} +void wbfs_close(wbfs_t*p) +{ + wbfs_sync(p); + + if(p->n_disc_open) + ERROR("trying to close wbfs while discs still open"); + + wbfs_iofree(p->head); + wbfs_iofree(p->tmp_buffer); + if(p->freeblks) + wbfs_iofree(p->freeblks); + + wbfs_free(p); + +error: + return; +} + +wbfs_disc_t *wbfs_open_disc(wbfs_t* p, u8 *discid) +{ + u32 i; + int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s; + wbfs_disc_t *d = 0; + for(i=0;imax_disc;i++) + { + if (p->head->disc_table[i]){ + p->read_hdsector(p->callback_data, + p->part_lba+1+i*disc_info_sz_lba,1,p->tmp_buffer); + if(wbfs_memcmp(discid,p->tmp_buffer,6)==0){ + d = wbfs_malloc(sizeof(*d)); + if(!d) + ERROR("allocating memory"); + d->p = p; + d->i = i; + d->header = wbfs_ioalloc(p->disc_info_sz); + if(!d->header) + ERROR("allocating memory"); + p->read_hdsector(p->callback_data, + p->part_lba+1+i*disc_info_sz_lba, + disc_info_sz_lba,d->header); + p->n_disc_open ++; +// for(i=0;in_wbfs_sec_per_disc;i++) +// printf("%d,",wbfs_ntohs(d->header->wlba_table[i])); + return d; + } + } + } + return 0; +error: + if(d) + wbfs_iofree(d); + return 0; + +} +void wbfs_close_disc(wbfs_disc_t*d) +{ + d->p->n_disc_open --; + wbfs_iofree(d->header); + wbfs_free(d); +} +// offset is pointing 32bit words to address the whole dvd, although len is in bytes +int wbfs_disc_read(wbfs_disc_t*d,u32 offset, u8 *data, u32 len) +{ + + wbfs_t *p = d->p; + u16 wlba = offset>>(p->wbfs_sec_sz_s-2); + u32 iwlba_shift = p->wbfs_sec_sz_s - p->hd_sec_sz_s; + u32 lba_mask = (p->wbfs_sec_sz-1)>>(p->hd_sec_sz_s); + u32 lba = (offset>>(p->hd_sec_sz_s-2))&lba_mask; + u32 off = offset&((p->hd_sec_sz>>2)-1); + u16 iwlba = wbfs_ntohs(d->header->wlba_table[wlba]); + u32 len_copied; + int err = 0; + u8 *ptr = data; + if(unlikely(iwlba==0)) + return 1; + if(unlikely(off)){ + off*=4; + err = p->read_hdsector(p->callback_data, + p->part_lba + (iwlba<tmp_buffer); + if(err) + return err; + len_copied = p->hd_sec_sz - off; + if(likely(len < len_copied)) + len_copied = len; + wbfs_memcpy(ptr, p->tmp_buffer + off, len_copied); + len -= len_copied; + ptr += len_copied; + lba++; + if(unlikely(lba>lba_mask && len)){ + lba=0; + iwlba = wbfs_ntohs(d->header->wlba_table[++wlba]); + if(unlikely(iwlba==0)) + return 1; + } + } + while(likely(len>=p->hd_sec_sz)) + { + u32 nlb = len>>(p->hd_sec_sz_s); + + if(unlikely(lba + nlb > p->wbfs_sec_sz)) // dont cross wbfs sectors.. + nlb = p->wbfs_sec_sz-lba; + err = p->read_hdsector(p->callback_data, + p->part_lba + (iwlba<hd_sec_sz_s; + ptr += nlb<hd_sec_sz_s; + lba += nlb; + if(unlikely(lba>lba_mask && len)){ + lba = 0; + iwlba =wbfs_ntohs(d->header->wlba_table[++wlba]); + if(unlikely(iwlba==0)) + return 1; + } + } + if(unlikely(len)){ + err = p->read_hdsector(p->callback_data, + p->part_lba + (iwlba<tmp_buffer); + if(err) + return err; + wbfs_memcpy(ptr, p->tmp_buffer, len); + } + return 0; +} + +// disc listing +u32 wbfs_count_discs(wbfs_t*p) +{ + u32 i,count=0; + for(i=0;imax_disc;i++) + if (p->head->disc_table[i]) + count++; + return count; + +} +u32 wbfs_sector_used(wbfs_t *p,wbfs_disc_info_t *di) +{ + u32 tot_blk=0,j; + for(j=0;jn_wbfs_sec_per_disc;j++) + if(wbfs_ntohs(di->wlba_table[j])) + tot_blk++; + return tot_blk; + +} +u32 wbfs_get_disc_info(wbfs_t*p, u32 index,u8 *header,int header_size,u32 *size)//size in 32 bit +{ + u32 i,count=0; + int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s; + for(i=0;imax_disc;i++) + if (p->head->disc_table[i]){ + if(count++==index) + { + p->read_hdsector(p->callback_data, + p->part_lba+1+i*disc_info_sz_lba,1,p->tmp_buffer); + if(header_size > (int)p->hd_sec_sz) + header_size = p->hd_sec_sz; + u32 magic = wbfs_ntohl(*(u32*)(p->tmp_buffer+24)); + if(magic!=0x5D1C9EA3){ + p->head->disc_table[i]=0; + return 1; + } + memcpy(header,p->tmp_buffer,header_size); + if(size) + { + u8 *header = wbfs_ioalloc(p->disc_info_sz); + p->read_hdsector(p->callback_data, + p->part_lba+1+i*disc_info_sz_lba,disc_info_sz_lba,header); + u32 sec_used = wbfs_sector_used(p,(wbfs_disc_info_t *)header); + wbfs_iofree(header); + *size = sec_used<<(p->wbfs_sec_sz_s-2); + } + return 0; + } + } + return 1; +} + +static void load_freeblocks(wbfs_t*p) +{ + if(p->freeblks) + return; + // XXX should handle malloc error.. + p->freeblks = wbfs_ioalloc(ALIGN_LBA(p->n_wbfs_sec/8)); + p->read_hdsector(p->callback_data,p->part_lba+p->freeblks_lba,ALIGN_LBA(p->n_wbfs_sec/8)>>p->hd_sec_sz_s, p->freeblks); + +} +u32 wbfs_count_usedblocks(wbfs_t*p) +{ + u32 i,j,count=0; + load_freeblocks(p); + for(i=0;in_wbfs_sec/(8*4);i++) + { + u32 v = wbfs_ntohl(p->freeblks[i]); + if(v == ~0U) + count+=32; + else if(v!=0) + for(j=0;j<32;j++) + if (v & (1<n_wbfs_sec/(8*4);i++) + { + u32 v = wbfs_ntohl(p->freeblks[i]); + if(v != 0) + { + for(j=0;j<32;j++) + if (v & (1<freeblks[i] = wbfs_htonl(v & ~(1<freeblks[i]); + p->freeblks[i] = wbfs_htonl(v | 1<wbfs_sec_sz_s-p->wii_sec_sz_s); + wiidisc_t *d = 0; + u8 *used = 0; + wbfs_disc_info_t *info = 0; + u8* copy_buffer = 0; + used = wbfs_malloc(p->n_wii_sec_per_disc); + if(!used) + ERROR("unable to alloc memory"); + if(!copy_1_1) + { + d = wd_open_disc(read_src_wii_disc,callback_data); + if(!d) + ERROR("unable to open wii disc"); + wd_build_disc_usage(d,sel,used); + wd_close_disc(d); + d = 0; + } + + + for(i=0;imax_disc;i++)// find a free slot. + if(p->head->disc_table[i]==0) + break; + if(i==p->max_disc) + ERROR("no space left on device (table full)"); + p->head->disc_table[i] = 1; + discn = i; + load_freeblocks(p); + + // build disc info + info = wbfs_ioalloc(p->disc_info_sz); + read_src_wii_disc(callback_data,0,0x100,info->disc_header_copy); + + copy_buffer = wbfs_ioalloc(p->wii_sec_sz); + if(!copy_buffer) + ERROR("alloc memory"); + tot=0; + cur=0; + if(spinner){ + // count total number to write for spinner + for(i=0; in_wbfs_sec_per_disc;i++) + if(copy_1_1 || block_used(used,i,wii_sec_per_wbfs_sect)) tot += wii_sec_per_wbfs_sect; + spinner(0,tot); + } + for(i=0; in_wbfs_sec_per_disc;i++){ + u16 bl = 0; + if(copy_1_1 || block_used(used,i,wii_sec_per_wbfs_sect)) { + u16 j; + + bl = alloc_block(p); + if (bl==0xffff) + ERROR("no space left on device (disc full)"); + for(j=0; jwbfs_sec_sz>>2)) + (j*(p->wii_sec_sz>>2)); + + read_src_wii_disc(callback_data,offset,p->wii_sec_sz,copy_buffer); + + //fix the partition table + if(offset == (0x40000>>2)) + wd_fix_partition_table(d, sel, copy_buffer); + p->write_hdsector(p->callback_data,p->part_lba+bl*(p->wbfs_sec_sz/p->hd_sec_sz)+j*(p->wii_sec_sz/p->hd_sec_sz), + p->wii_sec_sz/p->hd_sec_sz,copy_buffer); + cur++; + if(spinner) + spinner(cur,tot); + } + } + info->wlba_table[i] = wbfs_htons(bl); + } + // write disc info + int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s; + p->write_hdsector(p->callback_data,p->part_lba+1+discn*disc_info_sz_lba,disc_info_sz_lba,info); + wbfs_sync(p); +error: + if(d) + wd_close_disc(d); + if(used) + wbfs_free(used); + if(info) + wbfs_iofree(info); + if(copy_buffer) + wbfs_iofree(copy_buffer); + // init with all free blocks + + return 0; +} +u32 wbfs_rm_disc(wbfs_t*p, u8* discid) +{ + wbfs_disc_t *d = wbfs_open_disc(p,discid); + int i; + int discn = 0; + int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s; + if(!d) + return 1; + load_freeblocks(p); + discn = d->i; + for( i=0; i< p->n_wbfs_sec_per_disc; i++) + { + u32 iwlba = wbfs_ntohs(d->header->wlba_table[i]); + if (iwlba) + free_block(p,iwlba); + } + memset(d->header,0,p->disc_info_sz); + p->write_hdsector(p->callback_data,p->part_lba+1+discn*disc_info_sz_lba,disc_info_sz_lba,d->header); + p->head->disc_table[discn] = 0; + wbfs_close_disc(d); + wbfs_sync(p); + return 0; +} + +u32 wbfs_ren_disc(wbfs_t*p, u8* discid, u8* newname) +{ + wbfs_disc_t *d = wbfs_open_disc(p,discid); + int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s; + + if(!d) + return 1; + + memset(d->header->disc_header_copy+0x20, 0, 0x40); + strncpy(d->header->disc_header_copy+0x20, newname, 0x39); + + p->write_hdsector(p->callback_data,p->part_lba+1+d->i*disc_info_sz_lba,disc_info_sz_lba,d->header); + wbfs_close_disc(d); + return 0; +} + +// trim the file-system to its minimum size +u32 wbfs_trim(wbfs_t*p); + +// data extraction +u32 wbfs_extract_disc(wbfs_disc_t*d, rw_sector_callback_t write_dst_wii_sector,void *callback_data,progress_callback_t spinner) +{ + wbfs_t *p = d->p; + u8* copy_buffer = 0; + int i; + int src_wbs_nlb=p->wbfs_sec_sz/p->hd_sec_sz; + int dst_wbs_nlb=p->wbfs_sec_sz/p->wii_sec_sz; + copy_buffer = wbfs_ioalloc(p->wbfs_sec_sz); + if(!copy_buffer) + ERROR("alloc memory"); + + for( i=0; i< p->n_wbfs_sec_per_disc; i++) + { + u32 iwlba = wbfs_ntohs(d->header->wlba_table[i]); + if (iwlba) + { + + if(spinner) + spinner(i,p->n_wbfs_sec_per_disc); + p->read_hdsector(p->callback_data, p->part_lba + iwlba*src_wbs_nlb, src_wbs_nlb, copy_buffer); + write_dst_wii_sector(callback_data, i*dst_wbs_nlb, dst_wbs_nlb, copy_buffer); + } + } + wbfs_iofree(copy_buffer); + return 0; +error: + return 1; +} +u32 wbfs_extract_file(wbfs_disc_t*d, char *path); + +u32 wbfs_estimate_disc( + wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, + void *callback_data, + partition_selector_t sel) +{ + u8 *b; + int disc_info_sz_lba; + int i; + u32 tot; + u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s-p->wii_sec_sz_s); + wiidisc_t *d = 0; + u8 *used = 0; + wbfs_disc_info_t *info = 0; + + tot = 0; + + used = wbfs_malloc(p->n_wii_sec_per_disc); + if (!used) + { + ERROR("unable to alloc memory"); + } + + d = wd_open_disc(read_src_wii_disc, callback_data); + if (!d) + { + ERROR("unable to open wii disc"); + } + + wd_build_disc_usage(d,sel,used); + wd_close_disc(d); + d = 0; + + info = wbfs_ioalloc(p->disc_info_sz); + b = (u8 *)info; + read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy); + + fprintf(stderr, "estimating %c%c%c%c%c%c %s...\n",b[0], b[1], b[2], b[3], b[4], b[5], b + 0x20); + + for (i = 0; i < p->n_wbfs_sec_per_disc; i++) + { + if (block_used(used, i, wii_sec_per_wbfs_sect)) + { + tot++; + } + } + +error: + if (d) + wd_close_disc(d); + + if (used) + wbfs_free(used); + + if (info) + wbfs_iofree(info); + + return tot * ((p->wbfs_sec_sz / p->hd_sec_sz) * 512); +} diff --git a/source/libwbfs/libwbfs.h b/source/libwbfs/libwbfs.h new file mode 100644 index 00000000..d96c6628 --- /dev/null +++ b/source/libwbfs/libwbfs.h @@ -0,0 +1,223 @@ +#ifndef LIBWBFS_H +#define LIBWBFS_H + +#include "libwbfs_os.h" // this file is provided by the project wanting to compile libwbfs +#include "wiidisc.h" + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +typedef u32 be32_t; +typedef u16 be16_t; + + + +typedef struct wbfs_head +{ + be32_t magic; + // parameters copied in the partition for easy dumping, and bug reports + be32_t n_hd_sec; // total number of hd_sec in this partition + u8 hd_sec_sz_s; // sector size in this partition + u8 wbfs_sec_sz_s; // size of a wbfs sec + u8 padding3[2]; + u8 disc_table[0]; // size depends on hd sector size +}__attribute((packed)) wbfs_head_t ; + +typedef struct wbfs_disc_info +{ + u8 disc_header_copy[0x100]; + be16_t wlba_table[0]; +}wbfs_disc_info_t; + +// WBFS first wbfs_sector structure: +// +// ----------- +// | wbfs_head | (hd_sec_sz) +// ----------- +// | | +// | disc_info | +// | | +// ----------- +// | | +// | disc_info | +// | | +// ----------- +// | | +// | ... | +// | | +// ----------- +// | | +// | disc_info | +// | | +// ----------- +// | | +// |freeblk_tbl| +// | | +// ----------- +// + +// callback definition. Return 1 on fatal error (callback is supposed to make retries until no hopes..) +typedef int (*rw_sector_callback_t)(void*fp,u32 lba,u32 count,void*iobuf); +typedef void (*progress_callback_t)(int status,int total); + + +typedef struct wbfs_s +{ + wbfs_head_t *head; + + /* hdsectors, the size of the sector provided by the hosting hard drive */ + u32 hd_sec_sz; + u8 hd_sec_sz_s; // the power of two of the last number + u32 n_hd_sec; // the number of hd sector in the wbfs partition + + /* standard wii sector (0x8000 bytes) */ + u32 wii_sec_sz; + u8 wii_sec_sz_s; + u32 n_wii_sec; + u32 n_wii_sec_per_disc; + + /* The size of a wbfs sector */ + u32 wbfs_sec_sz; + u32 wbfs_sec_sz_s; + u16 n_wbfs_sec; // this must fit in 16 bit! + u16 n_wbfs_sec_per_disc; // size of the lookup table + + u32 part_lba; + /* virtual methods to read write the partition */ + rw_sector_callback_t read_hdsector; + rw_sector_callback_t write_hdsector; + void *callback_data; + + u16 max_disc; + u32 freeblks_lba; + u32 *freeblks; + u16 disc_info_sz; + + u8 *tmp_buffer; // pre-allocated buffer for unaligned read + + u32 n_disc_open; + +}wbfs_t; + +typedef struct wbfs_disc_s +{ + wbfs_t *p; + wbfs_disc_info_t *header; // pointer to wii header + int i; // disc index in the wbfs header (disc_table) +}wbfs_disc_t; + + +#define WBFS_MAGIC (('W'<<24)|('B'<<16)|('F'<<8)|('S')) + +/*! @brief open a MSDOS partitionned harddrive. This tries to find a wbfs partition into the harddrive + @param read_hdsector,write_hdsector: accessors to a harddrive + @hd_sector_size: size of the hd sector. Can be set to zero if the partition in already initialized + @num_hd_sector: number of sectors in this disc. Can be set to zero if the partition in already initialized + @reset: not implemented, This will format the whole harddrive with one wbfs partition that fits the whole disk. + calls wbfs_error() to have textual meaning of errors + @return NULL in case of error +*/ +wbfs_t*wbfs_open_hd(rw_sector_callback_t read_hdsector, + rw_sector_callback_t write_hdsector, + void *callback_data, + int hd_sector_size, int num_hd_sector, int reset); + +/*! @brief open a wbfs partition + @param read_hdsector,write_hdsector: accessors to the partition + @hd_sector_size: size of the hd sector. Can be set to zero if the partition in already initialized + @num_hd_sector: number of sectors in this partition. Can be set to zero if the partition in already initialized + @partition_lba: The partitio offset if you provided accessors to the whole disc. + @reset: initialize the partition with an empty wbfs. + calls wbfs_error() to have textual meaning of errors + @return NULL in case of error +*/ +wbfs_t*wbfs_open_partition(rw_sector_callback_t read_hdsector, + rw_sector_callback_t write_hdsector, + void *callback_data, + int hd_sector_size, int num_hd_sector, u32 partition_lba, int reset); + + +/*! @brief close a wbfs partition, and sync the metadatas to the disc */ +void wbfs_close(wbfs_t*); + +/*! @brief open a disc inside a wbfs partition use a 6 char discid+vendorid + @return NULL if discid is not present +*/ +wbfs_disc_t *wbfs_open_disc(wbfs_t* p, u8 *diskid); + +/*! @brief close a already open disc inside a wbfs partition */ +void wbfs_close_disc(wbfs_disc_t*d); + +u32 wbfs_sector_used(wbfs_t *p,wbfs_disc_info_t *di); + +/*! @brief accessor to the wii disc + @param d: a pointer to already open disc + @param offset: an offset inside the disc, *points 32bit words*, allowing to access 16GB data + @param len: The length of the data to fetch, in *bytes* + */ +// offset is pointing 32bit words to address the whole dvd, although len is in bytes +int wbfs_disc_read(wbfs_disc_t*d,u32 offset, u8 *data, u32 len); + +/*! @return the number of discs inside the paritition */ +u32 wbfs_count_discs(wbfs_t*p); +/*! get the disc info of ith disc inside the partition. It correspond to the first 0x100 bytes of the wiidvd + http://www.wiibrew.org/wiki/Wiidisc#Header + @param i: index of the disc inside the partition + @param header: pointer to 0x100 bytes to write the header + @size: optional pointer to a 32bit word that will get the size in 32bit words of the DVD taken on the partition. +*/ +u32 wbfs_get_disc_info(wbfs_t*p, u32 i,u8 *header,int header_size,u32 *size); + +/*! get the number of used block of the partition. + to be multiplied by p->wbfs_sec_sz (use 64bit multiplication) to have the number in bytes +*/ +u32 wbfs_count_usedblocks(wbfs_t*p); + +/******************* write access ******************/ + +/*! add a wii dvd inside the partition + @param read_src_wii_disc: a callback to access the wii dvd. offsets are in 32bit, len in bytes! + @callback_data: private data passed to the callback + @spinner: a pointer to a function that is regulary called to update a progress bar. + @sel: selects which partitions to copy. + @copy_1_1: makes a 1:1 copy, whenever a game would not use the wii disc format, and some data is hidden outside the filesystem. + */ +u32 wbfs_add_disc(wbfs_t*p,read_wiidisc_callback_t read_src_wii_disc, void *callback_data, + progress_callback_t spinner,partition_selector_t sel,int copy_1_1); + + +/*! remove a wiidvd inside a partition */ +u32 wbfs_rm_disc(wbfs_t*p, u8* discid); + +/*! rename a game */ +u32 wbfs_ren_disc(wbfs_t*p, u8* discid, u8* newname); + +/*! trim the file-system to its minimum size + This allows to use wbfs as a wiidisc container + */ +u32 wbfs_trim(wbfs_t*p); + +/*! extract a disc from the wbfs, unused sectors are just untouched, allowing descent filesystem to only really usefull space to store the disc. +Even if the filesize is 4.7GB, the disc usage will be less. + */ +u32 wbfs_extract_disc(wbfs_disc_t*d, rw_sector_callback_t write_dst_wii_sector,void *callback_data,progress_callback_t spinner); + +/*! extract a file from the wii disc filesystem. + E.G. Allows to extract the opening.bnr to install a game as a system menu channel + */ +u32 wbfs_extract_file(wbfs_disc_t*d, char *path); + +// remove some sanity checks +void wbfs_set_force_mode(int force); + +u32 wbfs_estimate_disc( + wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, + void *callback_data, + partition_selector_t sel); + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif diff --git a/source/libwbfs/libwbfs_os.h b/source/libwbfs/libwbfs_os.h new file mode 100644 index 00000000..7b3efbaa --- /dev/null +++ b/source/libwbfs/libwbfs_os.h @@ -0,0 +1,33 @@ +#ifndef LIBWBFS_GLUE_H +#define LIBWBFS_GLUE_H + +#include + +#define debug_printf(fmt, ...); + +#include +#define wbfs_fatal(x) do { printf("\nwbfs panic: %s\n\n",x); while(1); } while(0) +#define wbfs_error(x) do { printf("\nwbfs error: %s\n\n",x); } while(0) + +#include +#include + +#define wbfs_malloc(x) malloc(x) +#define wbfs_free(x) free(x) +#define wbfs_ioalloc(x) memalign(32, x) +#define wbfs_iofree(x) free(x) +#define wbfs_be16(x) (*((u16*)(x))) +#define wbfs_be32(x) (*((u32*)(x))) +#define wbfs_ntohl(x) (x) +#define wbfs_htonl(x) (x) +#define wbfs_ntohs(x) (x) +#define wbfs_htons(x) (x) + +#include + +#define wbfs_memcmp(x,y,z) memcmp(x,y,z) +#define wbfs_memcpy(x,y,z) memcpy(x,y,z) +#define wbfs_memset(x,y,z) memset(x,y,z) + + +#endif diff --git a/source/libwbfs/rijndael.c b/source/libwbfs/rijndael.c new file mode 100644 index 00000000..baf8c871 --- /dev/null +++ b/source/libwbfs/rijndael.c @@ -0,0 +1,398 @@ +/* Rijndael Block Cipher - rijndael.c + + Written by Mike Scott 21st April 1999 + mike@compapp.dcu.ie + + Permission for free direct or derivative use is granted subject + to compliance with any conditions that the originators of the + algorithm place on its exploitation. + +*/ + +#include +#include + +#define u8 unsigned char /* 8 bits */ +#define u32 unsigned long /* 32 bits */ +#define u64 unsigned long long + +/* rotates x one bit to the left */ + +#define ROTL(x) (((x)>>7)|((x)<<1)) + +/* Rotates 32-bit word left by 1, 2 or 3 byte */ + +#define ROTL8(x) (((x)<<8)|((x)>>24)) +#define ROTL16(x) (((x)<<16)|((x)>>16)) +#define ROTL24(x) (((x)<<24)|((x)>>8)) + +/* Fixed Data */ + +static u8 InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */ + +static u8 fbsub[256]; +static u8 rbsub[256]; +static u8 ptab[256],ltab[256]; +static u32 ftable[256]; +static u32 rtable[256]; +static u32 rco[30]; + +/* Parameter-dependent data */ + +int Nk,Nb,Nr; +u8 fi[24],ri[24]; +u32 fkey[120]; +u32 rkey[120]; + +static u32 pack(u8 *b) +{ /* pack bytes into a 32-bit Word */ + return ((u32)b[3]<<24)|((u32)b[2]<<16)|((u32)b[1]<<8)|(u32)b[0]; +} + +static void unpack(u32 a,u8 *b) +{ /* unpack bytes from a word */ + b[0]=(u8)a; + b[1]=(u8)(a>>8); + b[2]=(u8)(a>>16); + b[3]=(u8)(a>>24); +} + +static u8 xtime(u8 a) +{ + u8 b; + if (a&0x80) b=0x1B; + else b=0; + a<<=1; + a^=b; + return a; +} + +static u8 bmul(u8 x,u8 y) +{ /* x.y= AntiLog(Log(x) + Log(y)) */ + if (x && y) return ptab[(ltab[x]+ltab[y])%255]; + else return 0; +} + +static u32 SubByte(u32 a) +{ + u8 b[4]; + unpack(a,b); + b[0]=fbsub[b[0]]; + b[1]=fbsub[b[1]]; + b[2]=fbsub[b[2]]; + b[3]=fbsub[b[3]]; + return pack(b); +} + +static u8 product(u32 x,u32 y) +{ /* dot product of two 4-byte arrays */ + u8 xb[4],yb[4]; + unpack(x,xb); + unpack(y,yb); + return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]); +} + +static u32 InvMixCol(u32 x) +{ /* matrix Multiplication */ + u32 y,m; + u8 b[4]; + + m=pack(InCo); + b[3]=product(m,x); + m=ROTL24(m); + b[2]=product(m,x); + m=ROTL24(m); + b[1]=product(m,x); + m=ROTL24(m); + b[0]=product(m,x); + y=pack(b); + return y; +} + +u8 ByteSub(u8 x) +{ + u8 y=ptab[255-ltab[x]]; /* multiplicative inverse */ + x=y; x=ROTL(x); + y^=x; x=ROTL(x); + y^=x; x=ROTL(x); + y^=x; x=ROTL(x); + y^=x; y^=0x63; + return y; +} + +void gentables(void) +{ /* generate tables */ + int i; + u8 y,b[4]; + + /* use 3 as primitive root to generate power and log tables */ + + ltab[0]=0; + ptab[0]=1; ltab[1]=0; + ptab[1]=3; ltab[3]=1; + for (i=2;i<256;i++) + { + ptab[i]=ptab[i-1]^xtime(ptab[i-1]); + ltab[ptab[i]]=i; + } + + /* affine transformation:- each bit is xored with itself shifted one bit */ + + fbsub[0]=0x63; + rbsub[0x63]=0; + for (i=1;i<256;i++) + { + y=ByteSub((u8)i); + fbsub[i]=y; rbsub[y]=i; + } + + for (i=0,y=1;i<30;i++) + { + rco[i]=y; + y=xtime(y); + } + + /* calculate forward and reverse tables */ + for (i=0;i<256;i++) + { + y=fbsub[i]; + b[3]=y^xtime(y); b[2]=y; + b[1]=y; b[0]=xtime(y); + ftable[i]=pack(b); + + y=rbsub[i]; + b[3]=bmul(InCo[0],y); b[2]=bmul(InCo[1],y); + b[1]=bmul(InCo[2],y); b[0]=bmul(InCo[3],y); + rtable[i]=pack(b); + } +} + +void gkey(int nb,int nk,char *key) +{ /* blocksize=32*nb bits. Key=32*nk bits */ + /* currently nb,bk = 4, 6 or 8 */ + /* key comes as 4*Nk bytes */ + /* Key Scheduler. Create expanded encryption key */ + int i,j,k,m,N; + int C1,C2,C3; + u32 CipherKey[8]; + + Nb=nb; Nk=nk; + + /* Nr is number of rounds */ + if (Nb>=Nk) Nr=6+Nb; + else Nr=6+Nk; + + C1=1; + if (Nb<8) { C2=2; C3=3; } + else { C2=3; C3=4; } + + /* pre-calculate forward and reverse increments */ + for (m=j=0;j>8)])^ + ROTL16(ftable[(u8)(x[fi[m+1]]>>16)])^ + ROTL24(ftable[x[fi[m+2]]>>24]); + } + t=x; x=y; y=t; /* swap pointers */ + } + +/* Last Round - unroll if possible */ + for (m=j=0;j>8)])^ + ROTL16((u32)fbsub[(u8)(x[fi[m+1]]>>16)])^ + ROTL24((u32)fbsub[x[fi[m+2]]>>24]); + } + for (i=j=0;i>8)])^ + ROTL16(rtable[(u8)(x[ri[m+1]]>>16)])^ + ROTL24(rtable[x[ri[m+2]]>>24]); + } + t=x; x=y; y=t; /* swap pointers */ + } + +/* Last Round - unroll if possible */ + for (m=j=0;j>8)])^ + ROTL16((u32)rbsub[(u8)(x[ri[m+1]]>>16)])^ + ROTL24((u32)rbsub[x[ri[m+2]]>>24]); + } + for (i=j=0;i +// Licensed under the terms of the GNU GPL, version 2 +// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + +#include "wiidisc.h" + +void aes_set_key(u8 *key); +void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len); + +static void _decrypt_title_key(u8 *tik, u8 *title_key) +{ + u8 common_key[16]={ + 0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4, 0x48, 0xd9, 0xc5, 0x45, + 0x73, 0x81, 0xaa, 0xf7 + };; + u8 iv[16]; + + wbfs_memset(iv, 0, sizeof iv); + wbfs_memcpy(iv, tik + 0x01dc, 8); + aes_set_key(common_key); + //_aes_cbc_dec(common_key, iv, tik + 0x01bf, 16, title_key); + aes_decrypt(iv, tik + 0x01bf,title_key,16); +} +static u32 _be32(const u8 *p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; +} + +static void disc_read(wiidisc_t *d,u32 offset, u8 *data, u32 len) +{ + if(data){ + int ret=0; + if(len==0) + return ; + ret = d->read(d->fp,offset,len,data); + if(ret) + wbfs_fatal("error reading disc"); + } + if(d->sector_usage_table) + { + u32 blockno = offset>>13; + do + { + d->sector_usage_table[blockno]=1; + blockno+=1; + if(len>0x8000) + len-=0x8000; + }while(len>0x8000); + } +} + +static void partition_raw_read(wiidisc_t *d,u32 offset, u8 *data, u32 len) +{ + disc_read(d, d->partition_raw_offset + offset, data, len); +} + +static void partition_read_block(wiidisc_t *d,u32 blockno, u8 *block) +{ + u8*raw = d->tmp_buffer; + u8 iv[16]; + u32 offset; + if(d->sector_usage_table) + d->sector_usage_table[d->partition_block+blockno]=1; + offset = d->partition_data_offset + ((0x8000>>2) * blockno); + partition_raw_read(d,offset, raw, 0x8000); + + // decrypt data + memcpy(iv, raw + 0x3d0, 16); + aes_set_key(d->disc_key); + aes_decrypt(iv, raw + 0x400,block,0x7c00); +} + +static void partition_read(wiidisc_t *d,u32 offset, u8 *data, u32 len,int fake) +{ + u8 *block = d->tmp_buffer2; + u32 offset_in_block; + u32 len_in_block; + if(fake && d->sector_usage_table==0) + return; + + while(len) { + offset_in_block = offset % (0x7c00>>2); + len_in_block = 0x7c00 - (offset_in_block<<2); + if (len_in_block > len) + len_in_block = len; + if(!fake){ + partition_read_block(d,offset / (0x7c00>>2), block); + wbfs_memcpy(data, block + (offset_in_block<<2), len_in_block); + }else + d->sector_usage_table[d->partition_block+(offset/(0x7c00>>2))]=1; + data += len_in_block; + offset += len_in_block>>2; + len -= len_in_block; + } +} + + +static u32 do_fst(wiidisc_t *d,u8 *fst, const char *names, u32 i) +{ + u32 offset; + u32 size; + const char *name; + u32 j; + + name = names + (_be32(fst + 12*i) & 0x00ffffff); + size = _be32(fst + 12*i + 8); + + if (i == 0) { + for (j = 1; j < size && !d->extracted_buffer; ){ + j = do_fst(d,fst, names, j); + } + return size; + } + //printf("name %s\n",name); + + if (fst[12*i]) { + + for (j = i + 1; j < size && !d->extracted_buffer; ) + j = do_fst(d,fst, names, j); + + return size; + } else { + offset = _be32(fst + 12*i + 4); + if(d->extract_pathname && strcmp(name, d->extract_pathname)==0) + { + d->extracted_buffer = wbfs_ioalloc(size); + partition_read(d,offset, d->extracted_buffer, size,0); + }else + partition_read(d,offset, 0, size,1); + return i + 1; + } +} + +static void do_files(wiidisc_t*d) +{ + u8 *b = wbfs_ioalloc(0x480); // XXX: determine actual header size + u32 dol_offset; + u32 fst_offset; + u32 fst_size; + u32 apl_offset; + u32 apl_size; + u8 *apl_header = wbfs_ioalloc(0x20); + u8 *fst; + u32 n_files; + partition_read(d,0, b, 0x480,0); + + dol_offset = _be32(b + 0x0420); + fst_offset = _be32(b + 0x0424); + fst_size = _be32(b + 0x0428)<<2; + + apl_offset = 0x2440>>2; + partition_read(d,apl_offset, apl_header, 0x20,0); + apl_size = 0x20 + _be32(apl_header + 0x14) + _be32(apl_header + 0x18); + // fake read dol and partition + partition_read(d,apl_offset, 0, apl_size,1); + partition_read(d,dol_offset, 0, (fst_offset - dol_offset)<<2,1); + + + fst = wbfs_ioalloc(fst_size); + if (fst == 0) + wbfs_fatal("malloc fst"); + partition_read(d,fst_offset, fst, fst_size,0); + n_files = _be32(fst + 8); + + if (n_files > 1) + do_fst(d,fst, (char *)fst + 12*n_files, 0); + wbfs_iofree(b); + wbfs_iofree(apl_header); + wbfs_iofree(fst); +} + +static void do_partition(wiidisc_t*d) +{ + u8 *tik = wbfs_ioalloc(0x2a4); + u8 *b = wbfs_ioalloc(0x1c); + u64 tmd_offset; + u32 tmd_size; + u8 *tmd; + u64 cert_offset; + u32 cert_size; + u8 *cert; + u64 h3_offset; + + // read ticket, and read some offsets and sizes + partition_raw_read(d,0, tik, 0x2a4); + partition_raw_read(d,0x2a4>>2, b, 0x1c); + + tmd_size = _be32(b); + tmd_offset = _be32(b + 4); + cert_size = _be32(b + 8); + cert_offset = _be32(b + 0x0c); + h3_offset = _be32(b + 0x10); + d->partition_data_offset = _be32(b + 0x14); + d->partition_block = (d->partition_raw_offset+d->partition_data_offset)>>13; + tmd = wbfs_ioalloc(tmd_size); + if (tmd == 0) + wbfs_fatal("malloc tmd"); + partition_raw_read(d,tmd_offset, tmd, tmd_size); + + cert = wbfs_ioalloc(cert_size); + if (cert == 0) + wbfs_fatal("malloc cert"); + partition_raw_read(d,cert_offset, cert, cert_size); + + + _decrypt_title_key(tik, d->disc_key); + + partition_raw_read(d,h3_offset, 0, 0x18000); + wbfs_iofree(b); + wbfs_iofree(tik); + wbfs_iofree(cert); + wbfs_iofree(tmd); + + do_files(d); + +} +static int test_parition_skip(u32 partition_type,partition_selector_t part_sel) +{ + switch(part_sel) + { + case ALL_PARTITIONS: + return 0; + case REMOVE_UPDATE_PARTITION: + return (partition_type==1); + case ONLY_GAME_PARTITION: + return (partition_type!=0); + default: + return (partition_type!=part_sel); + } +} +static void do_disc(wiidisc_t*d) +{ + u8 *b = wbfs_ioalloc(0x100); + u64 partition_offset[32]; // XXX: don't know the real maximum + u64 partition_type[32]; // XXX: don't know the real maximum + u32 n_partitions; + u32 magic; + u32 i; + disc_read(d,0, b, 0x100); + magic=_be32(b+24); + if(magic!=0x5D1C9EA3){ + wbfs_error("not a wii disc"); + return ; + } + disc_read(d,0x40000>>2, b, 0x100); + n_partitions = _be32(b); + disc_read(d,_be32(b + 4), b, 0x100); + for (i = 0; i < n_partitions; i++){ + partition_offset[i] = _be32(b + 8 * i); + partition_type[i] = _be32(b + 8 * i+4); + } + for (i = 0; i < n_partitions; i++) { + d->partition_raw_offset = partition_offset[i]; + if(!test_parition_skip(partition_type[i],d->part_sel)) + do_partition(d); + } + wbfs_iofree(b); +} + +wiidisc_t *wd_open_disc(read_wiidisc_callback_t read,void*fp) +{ + wiidisc_t *d = wbfs_malloc(sizeof(wiidisc_t)); + if(!d) + return 0; + wbfs_memset(d,0,sizeof(wiidisc_t)); + d->read = read; + d->fp = fp; + d->part_sel = ALL_PARTITIONS; + d->tmp_buffer = wbfs_ioalloc(0x8000); + d->tmp_buffer2 = wbfs_malloc(0x8000); + + return d; +} +void wd_close_disc(wiidisc_t *d) +{ + wbfs_iofree(d->tmp_buffer); + wbfs_free(d->tmp_buffer2); + wbfs_free(d); +} +// returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error +// XXX pathname not implemented. files are extracted by their name. +// first file found with that name is returned. +u8 * wd_extract_file(wiidisc_t *d, partition_selector_t partition_type, char *pathname) +{ + u8 *retval = 0; + d->extract_pathname = pathname; + d->extracted_buffer = 0; + d->part_sel = partition_type; + do_disc(d); + d->extract_pathname = 0; + d->part_sel = ALL_PARTITIONS; + retval = d->extracted_buffer; + d->extracted_buffer = 0; + return retval; +} + +void wd_build_disc_usage(wiidisc_t *d, partition_selector_t selector, u8* usage_table) +{ + d->sector_usage_table = usage_table; + wbfs_memset(usage_table,0,143432*2); + d->part_sel = selector; + do_disc(d); + d->part_sel = ALL_PARTITIONS; + d->sector_usage_table = 0; +} + +void wd_fix_partition_table(wiidisc_t *d, partition_selector_t selector, u8* partition_table) +{ + u8 *b = partition_table; + u32 partition_offset; + u32 partition_type; + u32 n_partitions,i,j; + u32 *b32; + if(selector == ALL_PARTITIONS) + return; + n_partitions = _be32(b); + if(_be32(b + 4)-(0x40000>>2) >0x50) + wbfs_fatal("cannot modify this partition table. Please report the bug."); + + b += (_be32(b + 4)-(0x40000>>2))*4; + j=0; + for (i = 0; i < n_partitions; i++){ + partition_offset = _be32(b + 8 * i); + partition_type = _be32(b + 8 * i+4); + if(!test_parition_skip(partition_type,selector)) + { + b32 = (u32*)(b + 8 * j); + b32[0] = wbfs_htonl(partition_offset); + b32[1] = wbfs_htonl(partition_type); + j++; + } + } + b32 = (u32*)(partition_table); + *b32 = wbfs_htonl(j); +} + diff --git a/source/libwbfs/wiidisc.h b/source/libwbfs/wiidisc.h new file mode 100644 index 00000000..24a27f43 --- /dev/null +++ b/source/libwbfs/wiidisc.h @@ -0,0 +1,67 @@ +#ifndef WIIDISC_H +#define WIIDISC_H +#include +#include "libwbfs_os.h" // this file is provided by the project wanting to compile libwbfs and wiidisc + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ +#if 0 //removes extra automatic indentation by editors + } +#endif +// callback definition. Return 1 on fatal error (callback is supposed to make retries until no hopes..) +// offset points 32bit words, count counts bytes +typedef int (*read_wiidisc_callback_t)(void*fp,u32 offset,u32 count,void*iobuf); + +typedef enum{ + UPDATE_PARTITION_TYPE=0, + GAME_PARTITION_TYPE, + OTHER_PARTITION_TYPE, + // value in between selects partition types of that value + ALL_PARTITIONS=0xffffffff-3, + REMOVE_UPDATE_PARTITION, // keeps game + channel installers + ONLY_GAME_PARTITION, +}partition_selector_t; + +typedef struct wiidisc_s +{ + read_wiidisc_callback_t read; + void *fp; + u8 *sector_usage_table; + + // everything points 32bit words. + u32 disc_raw_offset; + u32 partition_raw_offset; + u32 partition_data_offset; + u32 partition_data_size; + u32 partition_block; + + u8 *tmp_buffer; + u8 *tmp_buffer2; + u8 disc_key[16]; + int dont_decrypt; + + partition_selector_t part_sel; + + char *extract_pathname; + u8 *extracted_buffer; +}wiidisc_t; + +wiidisc_t *wd_open_disc(read_wiidisc_callback_t read,void*fp); +void wd_close_disc(wiidisc_t *); +// returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error +u8 * wd_extract_file(wiidisc_t *d, partition_selector_t partition_type, char *pathname); + +void wd_build_disc_usage(wiidisc_t *d, partition_selector_t selector, u8* usage_table); + +// effectively remove not copied partition from the partition table. +void wd_fix_partition_table(wiidisc_t *d, partition_selector_t selector, u8* partition_table); + +#if 0 +{ +#endif +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif diff --git a/source/libwiigui/gui.h b/source/libwiigui/gui.h new file mode 100644 index 00000000..3459042a --- /dev/null +++ b/source/libwiigui/gui.h @@ -0,0 +1,839 @@ +/*!\mainpage libwiigui Documentation + * + * \section Introduction + * libwiigui is a GUI library for the Wii, created to help structure the + * design of a complicated GUI interface, and to enable an author to create + * a sophisticated, feature-rich GUI. It was originally conceived and written + * after I started to design a GUI for Snes9x GX, and found libwiisprite and + * GRRLIB inadequate for the purpose. It uses GX for drawing, and makes use + * of PNGU for displaying images and FreeTypeGX for text. It was designed to + * be flexible and is easy to modify - don't be afraid to change the way it + * works or expand it to suit your GUI's purposes! If you do, and you think + * your changes might benefit others, please share them so they might be + * added to the project! + * + * \section Quickstart + * Start from the supplied template example. For more advanced uses, see the + * source code for Snes9x GX, FCE Ultra GX, and Visual Boy Advance GX. + + * \section Contact + * If you have any suggestions for the library or documentation, or want to + * contribute, please visit the libwiigui website: + + * http://code.google.com/p/libwiigui/ + * \section Credits + * This library was wholly designed and written by Tantric. Thanks to the + * authors of PNGU and FreeTypeGX, of which this library makes use. Thanks + * also to the authors of GRRLIB and libwiisprite for laying the foundations. + * +*/ + +#ifndef LIBWIIGUI_H +#define LIBWIIGUI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pngu/pngu.h" +#include "FreeTypeGX.h" +#include "video.h" +#include "filelist.h" +#include "input.h" +#include "oggplayer.h" + +extern FreeTypeGX *fontSystem; + +#define SCROLL_INITIAL_DELAY 20 +#define SCROLL_LOOP_DELAY 3 +#define PAGESIZE 9 +#define MAX_OPTIONS 170 + +typedef void (*UpdateCallback)(void * e); + +enum +{ + ALIGN_LEFT, + ALIGN_RIGHT, + ALIGN_CENTRE, + ALIGN_TOP, + ALIGN_BOTTOM, + ALIGN_MIDDLE +}; + +enum +{ + STATE_DEFAULT, + STATE_SELECTED, + STATE_CLICKED, + STATE_HELD, + STATE_DISABLED +}; + +enum +{ + SOUND_PCM, + SOUND_OGG +}; + +enum +{ + IMAGE_TEXTURE, + IMAGE_COLOR, + IMAGE_DATA +}; + +enum +{ + TRIGGER_SIMPLE, + TRIGGER_HELD, + TRIGGER_BUTTON_ONLY, + TRIGGER_BUTTON_ONLY_IN_FOCUS +}; + +typedef struct _paddata { + u16 btns_d; + u16 btns_u; + u16 btns_h; + s8 stickX; + s8 stickY; + s8 substickX; + s8 substickY; + u8 triggerL; + u8 triggerR; +} PADData; + +#define EFFECT_SLIDE_TOP 1 +#define EFFECT_SLIDE_BOTTOM 2 +#define EFFECT_SLIDE_RIGHT 4 +#define EFFECT_SLIDE_LEFT 8 +#define EFFECT_SLIDE_IN 16 +#define EFFECT_SLIDE_OUT 32 +#define EFFECT_FADE 64 +#define EFFECT_SCALE 128 +#define EFFECT_COLOR_TRANSITION 256 + +//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc +class GuiSound +{ + public: + //!Constructor + //!\param s Pointer to the sound data + //!\param l Length of sound data + //!\param t Sound format type (SOUND_PCM or SOUND_OGG) + GuiSound(const u8 * s, int l, int t); + GuiSound(const u8 * s, int l, int t, int v); + //!Destructor + ~GuiSound(); + //!Start sound playback + void Play(); + //!Stop sound playback + void Stop(); + //!Pause sound playback + void Pause(); + //!Resume sound playback + void Resume(); + //!Checks if the sound is currently playing + //!\return true if sound is playing, false otherwise + bool IsPlaying(); + //!Set sound volume + //!\param v Sound volume (0-100) + void SetVolume(int v); + //!Set the sound to loop playback (only applies to OGG) + //!\param l Loop (true to loop) + void SetLoop(bool l); + protected: + const u8 * sound; //!< Pointer to the sound data + int type; //!< Sound format type (SOUND_PCM or SOUND_OGG) + s32 length; //!< Length of sound data + s32 voice; //!< Currently assigned ASND voice channel + s32 volume; //!< Sound volume (0-100) + bool loop; //!< Loop sound playback +}; + +//!Menu input trigger management. Determine if action is neccessary based on input data by comparing controller input data to a specific trigger element. +class GuiTrigger +{ + public: + //!Constructor + GuiTrigger(); + //!Destructor + ~GuiTrigger(); + //!Sets a simple trigger. Requires: element is selected, and trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a held trigger. Requires: element is selected, and trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetHeldTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a button-only trigger. Requires: Trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a button-only trigger. Requires: trigger button is pressed and parent window of element is in focus + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Get X/Y value from Wii Joystick (classic, nunchuk) input + //!\param right Controller stick (left = 0, right = 1) + //!\param axis Controller stick axis (x-axis = 0, y-axis = 1) + //!\return Stick value + s8 WPAD_Stick(u8 right, int axis); + //!Move menu selection left (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved left, false otherwise + bool Left(); + //!Move menu selection right (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved right, false otherwise + bool Right(); + //!Move menu selection up (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved up, false otherwise + bool Up(); + //!Move menu selection down (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved down, false otherwise + bool Down(); + + u8 type; //!< trigger type (TRIGGER_SIMPLE, TRIGGER_HELD, TRIGGER_BUTTON_ONLY, TRIGGER_BUTTON_ONLY_IN_FOCUS) + s32 chan; //!< Trigger controller channel (0-3, -1 for all) + WPADData wpad; //!< Wii controller trigger data + PADData pad; //!< GameCube controller trigger data +}; + +extern GuiTrigger userInput[4]; + +//!Primary GUI class. Most other classes inherit from this class. +class GuiElement +{ + public: + //!Constructor + GuiElement(); + //!Destructor + ~GuiElement(); + //!Set the element's parent + //!\param e Pointer to parent element + void SetParent(GuiElement * e); + //!Gets the current leftmost coordinate of the element + //!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values + //!\return left coordinate + int GetLeft(); + //!Gets the current topmost coordinate of the element + //!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values + //!\return top coordinate + int GetTop(); + //!Sets the minimum y offset of the element + //!\param y Y offset + void SetMinY(int y); + //!Gets the minimum y offset of the element + //!\return Minimum Y offset + int GetMinY(); + //!Sets the maximum y offset of the element + //!\param y Y offset + void SetMaxY(int y); + //!Gets the maximum y offset of the element + //!\return Maximum Y offset + int GetMaxY(); + //!Sets the minimum x offset of the element + //!\param x X offset + void SetMinX(int x); + //!Gets the minimum x offset of the element + //!\return Minimum X offset + int GetMinX(); + //!Sets the maximum x offset of the element + //!\param x X offset + void SetMaxX(int x); + //!Gets the maximum x offset of the element + //!\return Maximum X offset + int GetMaxX(); + //!Gets the current width of the element. Does not currently consider the scale + //!\return width + int GetWidth(); + //!Gets the height of the element. Does not currently consider the scale + //!\return height + int GetHeight(); + //!Sets the size (width/height) of the element + //!\param w Width of element + //!\param h Height of element + void SetSize(int w, int h); + //!Checks whether or not the element is visible + //!\return true if visible, false otherwise + bool IsVisible(); + //!Checks whether or not the element is selectable + //!\return true if selectable, false otherwise + bool IsSelectable(); + //!Checks whether or not the element is clickable + //!\return true if clickable, false otherwise + bool IsClickable(); + //!Checks whether or not the element is holdable + //!\return true if holdable, false otherwise + bool IsHoldable(); + //!Sets whether or not the element is selectable + //!\param s Selectable + void SetSelectable(bool s); + //!Sets whether or not the element is clickable + //!\param c Clickable + void SetClickable(bool c); + //!Sets whether or not the element is holdable + //!\param c Holdable + void SetHoldable(bool d); + //!Gets the element's current state + //!\return state + int GetState(); + //!Gets the controller channel that last changed the element's state + //!\return Channel number (0-3, -1 = no channel) + int GetStateChan(); + //!Sets the element's alpha value + //!\param a alpha value + void SetAlpha(int a); + //!Gets the element's alpha value + //!Considers alpha, alphaDyn, and the parent element's GetAlpha() value + //!\return alpha + int GetAlpha(); + //!Sets the element's scale + //!\param s scale (1 is 100%) + void SetScale(float s); + //!Gets the element's current scale + //!Considers scale, scaleDyn, and the parent element's GetScale() value + float GetScale(); + //!Set a new GuiTrigger for the element + //!\param t Pointer to GuiTrigger + void SetTrigger(GuiTrigger * t); + //!\overload + //!\param i Index of trigger array to set + //!\param t Pointer to GuiTrigger + void SetTrigger(u8 i, GuiTrigger * t); + //!Checks whether rumble was requested by the element + //!\return true is rumble was requested, false otherwise + bool Rumble(); + //!Sets whether or not the element is requesting a rumble event + //!\param r true if requesting rumble, false if not + void SetRumble(bool r); + //!Set an effect for the element + //!\param e Effect to enable + //!\param a Amount of the effect (usage varies on effect) + //!\param t Target amount of the effect (usage varies on effect) + void SetEffect(int e, int a, int t=0); + //!Sets an effect to be enabled on wiimote cursor over + //!\param e Effect to enable + //!\param a Amount of the effect (usage varies on effect) + //!\param t Target amount of the effect (usage varies on effect) + void SetEffectOnOver(int e, int a, int t=0); + //!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110) + void SetEffectGrow(); + //!Gets the current element effects + //!\return element effects + int GetEffect(); + //!Checks whether the specified coordinates are within the element's boundaries + //!\param x X coordinate + //!\param y Y coordinate + //!\return true if contained within, false otherwise + bool IsInside(int x, int y); + //!Sets the element's position + //!\param x X coordinate + //!\param y Y coordinate + void SetPosition(int x, int y); + //!Updates the element's effects (dynamic values) + //!Called by Draw(), used for animation purposes + void UpdateEffects(); + //!Sets a function to called after after Update() + //!Callback function can be used to response to changes in the state of the element, and/or update the element's attributes + void SetUpdateCallback(UpdateCallback u); + //!Checks whether the element is in focus + //!\return true if element is in focus, false otherwise + int IsFocused(); + //!Sets the element's visibility + //!\param v Visibility (true = visible) + virtual void SetVisible(bool v); + //!Sets the element's focus + //!\param f Focus (true = in focus) + virtual void SetFocus(int f); + //!Sets the element's state + //!\param s State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED) + //!\param c Controller channel (0-3, -1 = none) + virtual void SetState(int s, int c = -1); + //!Resets the element's state to STATE_DEFAULT + virtual void ResetState(); + //!Gets whether or not the element is in STATE_SELECTED + //!\return true if selected, false otherwise + virtual int GetSelected(); + //!Sets the element's alignment respective to its parent element + //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) + //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) + virtual void SetAlignment(int hor, int vert); + //!Called constantly to allow the element to respond to the current input data + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + virtual void Update(GuiTrigger * t); + //!Called constantly to redraw the element + virtual void Draw(); + protected: + //int position2; //! B Scrollbariable + bool visible; //!< Visibility of the element. If false, Draw() is skipped + int focus; //!< Element focus (-1 = focus disabled, 0 = not focused, 1 = focused) + int width; //!< Element width + int height; //!< Element height + int xoffset; //!< Element X offset + int yoffset; //!< Element Y offset + int ymin; //!< Element's min Y offset allowed + int ymax; //!< Element's max Y offset allowed + int xmin; //!< Element's min X offset allowed + int xmax; //!< Element's max X offset allowed + int xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects) + int yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects) + int alpha; //!< Element alpha value (0-255) + f32 scale; //!< Element scale (1 = 100%) + int alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects) + f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects) + bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event + int effects; //!< Currently enabled effect(s). 0 when no effects are enabled + int effectAmount; //!< Effect amount. Used by different effects for different purposes + int effectTarget; //!< Effect target amount. Used by different effects for different purposes + int effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event + int effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element + int effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element + int alignmentHor; //!< Horizontal element alignment, respective to parent element (LEFT, RIGHT, CENTRE) + int alignmentVert; //!< Horizontal element alignment, respective to parent element (TOP, BOTTOM, MIDDLE) + int state; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED) + int stateChan; //!< Which controller channel is responsible for the last change in state + bool selectable; //!< Whether or not this element selectable (can change to SELECTED state) + bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state) + bool holdable; //!< Whether or not this element is holdable (can change to HELD state) + GuiTrigger * trigger[5]; //!< GuiTriggers (input actions) that this element responds to + GuiElement * parentElement; //!< Parent element + UpdateCallback updateCB; //!< Callback function to call when this element is updated +}; + +//!Allows GuiElements to be grouped together into a "window" +class GuiWindow : public GuiElement +{ + public: + //!Constructor + GuiWindow(); + //!\overload + //!\param w Width of window + //!\param h Height of window + GuiWindow(int w, int h); + //!Destructor + ~GuiWindow(); + //!Appends a GuiElement to the GuiWindow + //!\param e The GuiElement to append. If it is already in the GuiWindow, it is removed first + void Append(GuiElement* e); + //!Inserts a GuiElement into the GuiWindow at the specified index + //!\param e The GuiElement to insert. If it is already in the GuiWindow, it is removed first + //!\param i Index in which to insert the element + void Insert(GuiElement* e, u32 i); + //!Removes the specified GuiElement from the GuiWindow + //!\param e GuiElement to be removed + void Remove(GuiElement* e); + //!Removes all GuiElements + void RemoveAll(); + //!Returns the GuiElement at the specified index + //!\param index The index of the element + //!\return A pointer to the element at the index, NULL on error (eg: out of bounds) + GuiElement* GetGuiElementAt(u32 index) const; + //!Returns the size of the list of elements + //!\return The size of the current element list + u32 GetSize(); + //!Sets the visibility of the window + //!\param v visibility (true = visible) + void SetVisible(bool v); + //!Resets the window's state to STATE_DEFAULT + void ResetState(); + //!Sets the window's state + //!\param s State + void SetState(int s); + //!Gets the index of the GuiElement inside the window that is currently selected + //!\return index of selected GuiElement + int GetSelected(); + //!Sets the window focus + //!\param f Focus + void SetFocus(int f); + //!Change the focus to the specified element + //!This is intended for the primary GuiWindow only + //!\param e GuiElement that should have focus + void ChangeFocus(GuiElement * e); + //!Changes window focus to the next focusable window or element + //!If no element is in focus, changes focus to the first available element + //!If B or 1 button is pressed, changes focus to the next available element + //!This is intended for the primary GuiWindow only + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void ToggleFocus(GuiTrigger * t); + //!Moves the selected element to the element to the left or right + //!\param d Direction to move (-1 = left, 1 = right) + void MoveSelectionHor(int d); + //!Moves the selected element to the element above or below + //!\param d Direction to move (-1 = up, 1 = down) + void MoveSelectionVert(int d); + //!Draws all the elements in this GuiWindow + void Draw(); + //!Updates the window and all elements contains within + //!Allows the GuiWindow and all elements to respond to the input data specified + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void Update(GuiTrigger * t); + protected: + std::vector _elements; //!< Contains all elements within the GuiWindow +}; + +//!Converts image data into GX-useable RGBA8. Currently designed for use only with PNG files +class GuiImageData +{ + public: + //!Constructor + //!Converts the image data to RGBA8 - expects PNG format + //!\param i Image data + GuiImageData(const u8 * i); + GuiImageData(const char * imgPath, const u8 * buffer); + //!Destructor + ~GuiImageData(); + //!Gets a pointer to the image data + //!\return pointer to image data + u8 * GetImage(); + //!Gets the image width + //!\return image width + int GetWidth(); + //!Gets the image height + //!\return image height + int GetHeight(); + protected: + u8 * data; //!< Image data + int height; //!< Height of image + int width; //!< Width of image +}; + +//!Display, manage, and manipulate images in the GUI +class GuiImage : public GuiElement +{ + public: + //!Constructor + GuiImage(); + //!\overload + //!\param img Pointer to GuiImageData element + GuiImage(GuiImageData * img); + //!\overload + //!Sets up a new image from the image data specified + //!\param img + //!\param w Image width + //!\param h Image height + GuiImage(u8 * img, int w, int h); + //!\overload + //!Creates an image filled with the specified color + //!\param w Image width + //!\param h Image height + //!\param c Image color + GuiImage(int w, int h, GXColor c); + //!Destructor + ~GuiImage(); + //!Sets the image rotation angle for drawing + //!\param a Angle (in degrees) + void SetAngle(float a); + //!Sets the number of times to draw the image horizontally + //!\param t Number of times to draw the image + void SetTile(int t); + // not NULL set horizontal scale to 0.8 //added + void SetWidescreen(short w); + //!Constantly called to draw the image + void Draw(); + //!Gets the image data + //!\return pointer to image data + u8 * GetImage(); + //!Sets up a new image using the GuiImageData object specified + //!\param img Pointer to GuiImageData object + void SetImage(GuiImageData * img); + //!\overload + //!\param img Pointer to image data + //!\param w Width + //!\param h Height + void SetImage(u8 * img, int w, int h); + //!Gets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + GXColor GetPixel(int x, int y); + //!Sets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + //!\param color Pixel color + void SetPixel(int x, int y, GXColor color); + //!Directly modifies the image data to create a color-striped effect + //!Alters the RGB values by the specified amount + //!\param s Amount to increment/decrement the RGB values in the image + void ColorStripe(int s); + //!Sets a stripe effect on the image, overlaying alpha blended rectangles + //!Does not alter the image data + //!\param s Alpha amount to draw over the image + void SetStripe(int s); + protected: + int imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA) + u8 * image; //!< Poiner to image data. May be shared with GuiImageData data + f32 imageangle; //!< Angle to draw the image + int tile; //!< Number of times to draw (tile) the image horizontally + int stripe; //!< Alpha value (0-255) to apply a stripe effect to the texture + short widescreen; //added +}; + +//!Display, manage, and manipulate text in the GUI +class GuiText : public GuiElement +{ + public: + //!Constructor + //!\param t Text + //!\param s Font size + //!\param c Font color + GuiText(const char * t, int s, GXColor c); + //!\overload + //!\Assumes SetPresets() has been called to setup preferred text attributes + //!\param t Text + GuiText(const char * t); + //!Destructor + ~GuiText(); + //!Sets the text of the GuiText element + //!\param t Text + void SetText(const char * t); + //!Sets up preset values to be used by GuiText(t) + //!Useful when printing multiple text elements, all with the same attributes set + //!\param sz Font size + //!\param c Font color + //!\param w Maximum width of texture image (for text wrapping) + //!\param s Font size + //!\param h Text alignment (horizontal) + //!\param v Text alignment (vertical) + void SetPresets(int sz, GXColor c, int w, u16 s, int h, int v); + //!Sets the font size + //!\param s Font size + void SetFontSize(int s); + //!Sets the maximum width of the drawn texture image + //!If the text exceeds this, it is wrapped to the next line + //!\param w Maximum width + void SetMaxWidth(int w); + //!Sets the font color + //!\param c Font color + void SetColor(GXColor c); + //!Sets the FreeTypeGX style attributes + //!\param s Style attributes + void SetStyle(u16 s); + //!Sets the text alignment + //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) + //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) + void SetAlignment(int hor, int vert); + //!Constantly called to draw the text + void Draw(); + protected: + wchar_t* text; //!< Unicode text value + int size; //!< Font size + int maxWidth; //!< Maximum width of the generated text object (for text wrapping) + u16 style; //!< FreeTypeGX style attributes + GXColor color; //!< Font color +}; + +//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) +class GuiButton : public GuiElement +{ + public: + //!Constructor + //!\param w Width + //!\param h Height + GuiButton(int w, int h); + //!Destructor + ~GuiButton(); + //!Sets the button's image + //!\param i Pointer to GuiImage object + void SetImage(GuiImage* i); + //!Sets the button's image on over + //!\param i Pointer to GuiImage object + void SetImageOver(GuiImage* i); + //!Sets the button's image on hold + //!\param i Pointer to GuiImage object + void SetAngle(float a); + void SetImageHold(GuiImage* i); + //!Sets the button's image on click + //!\param i Pointer to GuiImage object + void SetImageClick(GuiImage* i); + //!Sets the button's icon + //!\param i Pointer to GuiImage object + void SetIcon(GuiImage* i); + //!Sets the button's icon on over + //!\param i Pointer to GuiImage object + void SetIconOver(GuiImage* i); + //!Sets the button's icon on hold + //!\param i Pointer to GuiImage object + void SetIconHold(GuiImage* i); + //!Sets the button's icon on click + //!\param i Pointer to GuiImage object + void SetIconClick(GuiImage* i); + //!Sets the button's label + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabel(GuiText* t, int n = 0); + //!Sets the button's label on over (eg: different colored text) + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabelOver(GuiText* t, int n = 0); + //!Sets the button's label on hold + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabelHold(GuiText* t, int n = 0); + //!Sets the button's label on click + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabelClick(GuiText* t, int n = 0); + //!Sets the sound to play on over + //!\param s Pointer to GuiSound object + void SetSoundOver(GuiSound * s); + //!Sets the sound to play on hold + //!\param s Pointer to GuiSound object + void SetSoundHold(GuiSound * s); + //!Sets the sound to play on click + //!\param s Pointer to GuiSound object + void SetSoundClick(GuiSound * s); + //!Constantly called to draw the GuiButtons ToolTip + //!Sets the button's Tooltip on over + //!\param i Pointer to GuiImage object, t Pointer to GuiText, x & y Positioning + void SetToolTip(GuiImage* i, GuiText * t, int x, int y); + //!Constantly called to draw the GuiButton + void Draw(); + //!Constantly called to allow the GuiButton to respond to updated input data + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void Update(GuiTrigger * t); + //!Deactivate/Activate pointing on Games while B scrolling + void ScrollIsOn(int f); + protected: + GuiImage * image; //!< Button image (default) + GuiImage * imageOver; //!< Button image for STATE_SELECTED + GuiImage * imageHold; //!< Button image for STATE_HELD + GuiImage * imageClick; //!< Button image for STATE_CLICKED + GuiImage * icon; //!< Button icon (drawn after button image) + GuiImage * iconOver; //!< Button icon for STATE_SELECTED + GuiImage * iconHold; //!< Button icon for STATE_HELD + GuiImage * iconClick; //!< Button icon for STATE_CLICKED + GuiImage * toolTip; //!< Tooltip for STATE_SELECTED + GuiText * toolTipTxt;//!< Tooltip Text + time_t time1, time2;//!< Tooltip timeconstants + GuiText * label[3]; //!< Label(s) to display (default) + GuiText * labelOver[3]; //!< Label(s) to display for STATE_SELECTED + GuiText * labelHold[3]; //!< Label(s) to display for STATE_HELD + GuiText * labelClick[3]; //!< Label(s) to display for STATE_CLICKED + GuiSound * soundOver; //!< Sound to play for STATE_SELECTED + GuiSound * soundHold; //!< Sound to play for STATE_HELD + GuiSound * soundClick; //!< Sound to play for STATE_CLICKED +}; + +typedef struct _keytype { + char ch, chShift; +} Key; + +//!On-screen keyboard +class GuiKeyboard : public GuiWindow +{ + public: + GuiKeyboard(char * t, u32 m); + ~GuiKeyboard(); + void Update(GuiTrigger * t); + char kbtextstr[256]; + protected: + u32 kbtextmaxlen; + Key keys[4][11]; + int shift; + int caps; + GuiText * kbText; + GuiImage * keyTextboxImg; + GuiText * keyCapsText; + GuiImage * keyCapsImg; + GuiImage * keyCapsOverImg; + GuiButton * keyCaps; + GuiText * keyShiftText; + GuiImage * keyShiftImg; + GuiImage * keyShiftOverImg; + GuiButton * keyShift; + GuiText * keyBackText; + GuiImage * keyBackImg; + GuiImage * keyBackOverImg; + GuiButton * keyBack; + GuiImage * keySpaceImg; + GuiImage * keySpaceOverImg; + GuiButton * keySpace; + GuiButton * keyBtn[4][11]; + GuiImage * keyImg[4][11]; + GuiImage * keyImgOver[4][11]; + GuiText * keyTxt[4][11]; + GuiImageData * keyTextbox; + GuiImageData * key; + GuiImageData * keyOver; + GuiImageData * keyMedium; + GuiImageData * keyMediumOver; + GuiImageData * keyLarge; + GuiImageData * keyLargeOver; + GuiSound * keySoundOver; + GuiSound * keySoundClick; + GuiTrigger * trigA; + GuiTrigger * trigB; +}; + +typedef struct _optionlist { + int length; + char name[MAX_OPTIONS][60]; + char value[MAX_OPTIONS][30]; +} OptionList; + +//!Display a list of menu options +class GuiOptionBrowser : public GuiElement +{ + public: + GuiOptionBrowser(int w, int h, OptionList * l, const u8 *imagebg, int scrollbar); + GuiOptionBrowser(int w, int h, OptionList * l, const char * themePath, const u8 *imagebg, int scrollbar, int start); + ~GuiOptionBrowser(); + void SetCol2Position(int x); + int FindMenuItem(int c, int d); + int GetClickedOption(); + int GetSelectedOption(); + void ResetState(); + void SetFocus(int f); + void Draw(); + void Update(GuiTrigger * t); + GuiText * optionVal[PAGESIZE]; + protected: + int selectedItem; + int listOffset; + + OptionList * options; + int optionIndex[PAGESIZE]; + GuiButton * optionBtn[PAGESIZE]; + GuiText * optionTxt[PAGESIZE]; + GuiImage * optionBg[PAGESIZE]; + + GuiButton * arrowUpBtn; + GuiButton * arrowDownBtn; + GuiButton * scrollbarBoxBtn; + + GuiImage * bgOptionsImg; + GuiImage * bgOptionsOverImg; + GuiImage * scrollbarImg; + GuiImage * arrowDownImg; + GuiImage * arrowDownOverImg; + GuiImage * arrowUpImg; + GuiImage * arrowUpOverImg; + GuiImage * scrollbarBoxImg; + GuiImage * scrollbarBoxOverImg; + + GuiImageData * bgOptions; + GuiImageData * bgOptionsOver; + GuiImageData * bgOptionsEntry; + GuiImageData * scrollbar; + GuiImageData * arrowDown; + GuiImageData * arrowDownOver; + GuiImageData * arrowUp; + GuiImageData * arrowUpOver; + GuiImageData * scrollbarBox; + GuiImageData * scrollbarBoxOver; + + GuiSound * btnSoundOver; + GuiSound * btnSoundClick; + GuiTrigger * trigA; + GuiTrigger * trigB; + GuiTrigger * trigHeldA; +}; +#endif diff --git a/source/libwiigui/gui_button.cpp b/source/libwiigui/gui_button.cpp new file mode 100644 index 00000000..7729c135 --- /dev/null +++ b/source/libwiigui/gui_button.cpp @@ -0,0 +1,355 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_button.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +static int scrollison; + +/** + * Constructor for the GuiButton class. + */ + +GuiButton::GuiButton(int w, int h) +{ + width = w; + height = h; + image = NULL; + imageOver = NULL; + imageHold = NULL; + imageClick = NULL; + icon = NULL; + iconOver = NULL; + iconHold = NULL; + iconClick = NULL; + toolTip = NULL; + toolTipTxt = NULL; + + for(int i=0; i < 3; i++) + { + label[i] = NULL; + labelOver[i] = NULL; + labelHold[i] = NULL; + labelClick[i] = NULL; + } + + soundOver = NULL; + soundHold = NULL; + soundClick = NULL; + selectable = true; + holdable = false; + clickable = true; +} + +/** + * Destructor for the GuiButton class. + */ +GuiButton::~GuiButton() +{ +} + +void GuiButton::SetImage(GuiImage* img) +{ + image = img; + if(img) img->SetParent(this); +} +void GuiButton::SetImageOver(GuiImage* img) +{ + imageOver = img; + if(img) img->SetParent(this); +} +void GuiButton::SetImageHold(GuiImage* img) +{ + imageHold = img; + if(img) img->SetParent(this); +} +void GuiButton::SetImageClick(GuiImage* img) +{ + imageClick = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIcon(GuiImage* img) +{ + icon = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIconOver(GuiImage* img) +{ + iconOver = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIconHold(GuiImage* img) +{ + iconHold = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIconClick(GuiImage* img) +{ + iconClick = img; + if(img) img->SetParent(this); +} +void GuiButton::SetLabel(GuiText* txt, int n) +{ + label[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelOver(GuiText* txt, int n) +{ + labelOver[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelHold(GuiText* txt, int n) +{ + labelHold[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelClick(GuiText* txt, int n) +{ + labelClick[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetSoundOver(GuiSound * snd) +{ + soundOver = snd; +} +void GuiButton::SetSoundHold(GuiSound * snd) +{ + soundHold = snd; +} +void GuiButton::SetSoundClick(GuiSound * snd) +{ + soundClick = snd; +} + +//No delay for now +void GuiButton::SetToolTip(GuiImage* img, GuiText * txt, int x, int y) +{ + if(img) + { + + toolTip = img; + img->SetParent(this); + img->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + img->SetPosition(x,y); + if(txt) + { + toolTipTxt = txt; + txt->SetParent(img); + } + + } +} +/** + * Draw the button on screen + */ +void GuiButton::Draw() +{ + if(!this->IsVisible()) + return; + + // draw image + if((state == STATE_SELECTED || state == STATE_HELD) && imageOver) + imageOver->Draw(); + else if(image) + image->Draw(); + // draw icon + if((state == STATE_SELECTED || state == STATE_HELD) && iconOver) + iconOver->Draw(); + else if(icon) + icon->Draw(); + // draw text + for(int i=0; i<3; i++) + { + if((state == STATE_SELECTED || state == STATE_HELD) && labelOver[i]) + labelOver[i]->Draw(); + else if(label[i]) + label[i]->Draw(); + } + + //draw ToolTip + if(state == STATE_SELECTED && toolTip) + { + if (time2 == 0) + time(&time2); + + time(&time1); + + if (difftime(time1, time2) >= 2) { + toolTip->Draw(); + if (toolTipTxt) + { + toolTipTxt->Draw(); + } + } + } + + this->UpdateEffects(); +} + +void GuiButton::ScrollIsOn(int f) +{ + scrollison = f; +} + +void GuiButton::Update(GuiTrigger * t) +{ + if(state == STATE_CLICKED || state == STATE_DISABLED || !t) + return; + else if(parentElement && parentElement->GetState() == STATE_DISABLED) + return; + + if(state != STATE_SELECTED && toolTip) { + time2 = 0; + } + + + #ifdef HW_RVL + // cursor + if(t->wpad.ir.valid) + { + if(this->IsInside(t->wpad.ir.x, t->wpad.ir.y)) + { + if(state == STATE_DEFAULT) // we weren't on the button before! + { + if(scrollison == 0) { + this->SetState(STATE_SELECTED, t->chan); + } + + if(this->Rumble() && scrollison == 0) + rumbleRequest[t->chan] = 1; + + if(soundOver && scrollison == 0) + soundOver->Play(); + + if(effectsOver && !effects && scrollison == 0) + { + // initiate effects + effects = effectsOver; + effectAmount = effectAmountOver; + effectTarget = effectTargetOver; + } + } + } + else + { + if(state == STATE_SELECTED && (stateChan == t->chan || stateChan == -1)) + this->ResetState(); + + if(effectTarget == effectTargetOver && effectAmount == effectAmountOver) + { + // initiate effects (in reverse) + effects = effectsOver; + effectAmount = -effectAmountOver; + effectTarget = 100; + } + } + } + #endif + + // button triggers + if(this->IsClickable() && scrollison == 0) + { + s32 wm_btns, wm_btns_trig, cc_btns, cc_btns_trig; + for(int i=0; i<6; i++) + { + if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan)) + { + // higher 16 bits only (wiimote) + wm_btns = t->wpad.btns_d << 16; + wm_btns_trig = trigger[i]->wpad.btns_d << 16; + + // lower 16 bits only (classic controller) + cc_btns = t->wpad.btns_d >> 16; + cc_btns_trig = trigger[i]->wpad.btns_d >> 16; + + if( + (t->wpad.btns_d > 0 && + wm_btns == wm_btns_trig || + (cc_btns == cc_btns_trig && t->wpad.exp.type == EXP_CLASSIC)) || + (t->pad.btns_d == trigger[i]->pad.btns_d && t->pad.btns_d > 0)) + { + if(t->chan == stateChan || stateChan == -1) + { + if(state == STATE_SELECTED) + { + this->SetState(STATE_CLICKED, t->chan); + + if(soundClick) + soundClick->Play(); + } + else if(trigger[i]->type == TRIGGER_BUTTON_ONLY) + { + this->SetState(STATE_CLICKED, t->chan); + } + else if(trigger[i]->type == TRIGGER_BUTTON_ONLY_IN_FOCUS && + parentElement->IsFocused()) + { + this->SetState(STATE_CLICKED, t->chan); + } + } + } + } + } + } + + if(this->IsHoldable()) + { + bool held = false; + s32 wm_btns, wm_btns_h, wm_btns_trig, cc_btns, cc_btns_h, cc_btns_trig; + + for(int i=0; i<6; i++) + { + if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan)) + { + // higher 16 bits only (wiimote) + wm_btns = t->wpad.btns_d << 16; + wm_btns_h = t->wpad.btns_h << 16; + wm_btns_trig = trigger[i]->wpad.btns_h << 16; + + // lower 16 bits only (classic controller) + cc_btns = t->wpad.btns_d >> 16; + cc_btns_h = t->wpad.btns_h >> 16; + cc_btns_trig = trigger[i]->wpad.btns_h >> 16; + + if( + (t->wpad.btns_d > 0 && + wm_btns == wm_btns_trig || + (cc_btns == cc_btns_trig && t->wpad.exp.type == EXP_CLASSIC)) || + (t->pad.btns_d == trigger[i]->pad.btns_h && t->pad.btns_d > 0)) + { + if(trigger[i]->type == TRIGGER_HELD && state == STATE_SELECTED && + (t->chan == stateChan || stateChan == -1)) + this->SetState(STATE_CLICKED, t->chan); + } + + if( + (t->wpad.btns_h > 0 && + wm_btns_h == wm_btns_trig || + (cc_btns_h == cc_btns_trig && t->wpad.exp.type == EXP_CLASSIC)) || + (t->pad.btns_h == trigger[i]->pad.btns_h && t->pad.btns_h > 0)) + { + if(trigger[i]->type == TRIGGER_HELD) + held = true; + } + + if(!held && state == STATE_HELD && stateChan == t->chan) + { + this->ResetState(); + } + else if(held && state == STATE_CLICKED && stateChan == t->chan) + { + this->SetState(STATE_HELD, t->chan); + } + } + } + } + + if(updateCB) + updateCB(this); +} diff --git a/source/libwiigui/gui_customoptionbrowser.cpp b/source/libwiigui/gui_customoptionbrowser.cpp new file mode 100644 index 00000000..ba2fcacc --- /dev/null +++ b/source/libwiigui/gui_customoptionbrowser.cpp @@ -0,0 +1,531 @@ +/**************************************************************************** + * libwiigui + * + * gui_customoptionbrowser.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +#include "../wpad.h" +#include "gui_customoptionbrowser.h" + +#include + + +#define GAMESELECTSIZE 30 + +static int scrollbaron = 0; +//int vol; +extern const int vol; +/** + * Constructor for the GuiCustomOptionBrowser class. + */ +GuiCustomOptionBrowser::GuiCustomOptionBrowser(int w, int h, customOptionList * l, const char *themePath, const char *custombg, const u8 *imagebg, int scrollon) +{ + width = w; + height = h; + options = l; + size = ((l->length > PAGESIZE)? PAGESIZE: l->length); + scrollbaron = scrollon; + selectable = true; + listOffset = this->FindMenuItem(-1, 1); + selectedItem = 0; + focus = 1; // allow focus + char imgPath[100]; + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trigHeldA = new GuiTrigger; + trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A); + btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM, vol); + + snprintf(imgPath, sizeof(imgPath), "%s%s", themePath, custombg); + bgOptions = new GuiImageData(imgPath, imagebg); + + bgOptionsImg = new GuiImage(bgOptions); + bgOptionsImg->SetParent(this); + bgOptionsImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + + snprintf(imgPath, sizeof(imgPath), "%sbg_options_entry.png", themePath); + bgOptionsEntry = new GuiImageData(imgPath, bg_options_entry_png); + if (scrollbaron == 1) { + snprintf(imgPath, sizeof(imgPath), "%sscrollbar.png", themePath); + scrollbar = new GuiImageData(imgPath, scrollbar_png); + scrollbarImg = new GuiImage(scrollbar); + scrollbarImg->SetParent(this); + scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarImg->SetPosition(0, 4); + + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_arrowdown.png", themePath); + arrowDown = new GuiImageData(imgPath, scrollbar_arrowdown_png); + arrowDownImg = new GuiImage(arrowDown); + arrowDownOver = new GuiImageData(imgPath, scrollbar_arrowdown_png); + arrowDownOverImg = new GuiImage(arrowDownOver); + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_arrowup.png", themePath); + arrowUp = new GuiImageData(imgPath, scrollbar_arrowup_png); + arrowUpImg = new GuiImage(arrowUp); + arrowUpOver = new GuiImageData(imgPath, scrollbar_arrowup_png); + arrowUpOverImg = new GuiImage(arrowUpOver); + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_box.png", themePath); + scrollbarBox = new GuiImageData(imgPath, scrollbar_box_png); + scrollbarBoxImg = new GuiImage(scrollbarBox); + scrollbarBoxOver = new GuiImageData(imgPath, scrollbar_box_png); + scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver); + + arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight()); + arrowUpBtn->SetParent(this); + arrowUpBtn->SetImage(arrowUpImg); + arrowUpBtn->SetImageOver(arrowUpOverImg); + arrowUpBtn->SetImageHold(arrowUpOverImg); + arrowUpBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + arrowUpBtn->SetPosition(width/2-18+7,-18); + arrowUpBtn->SetSelectable(false); + arrowUpBtn->SetTrigger(trigA); + arrowUpBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowUpBtn->SetSoundClick(btnSoundClick); + + arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight()); + arrowDownBtn->SetParent(this); + arrowDownBtn->SetImage(arrowDownImg); + arrowDownBtn->SetImageOver(arrowDownOverImg); + arrowDownBtn->SetImageHold(arrowDownOverImg); + arrowDownBtn->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + arrowDownBtn->SetPosition(width/2-18+7,18); + arrowDownBtn->SetSelectable(false); + arrowDownBtn->SetTrigger(trigA); + arrowDownBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowDownBtn->SetSoundClick(btnSoundClick); + + scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight()); + scrollbarBoxBtn->SetParent(this); + scrollbarBoxBtn->SetImage(scrollbarBoxImg); + scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg); + scrollbarBoxBtn->SetImageHold(scrollbarBoxOverImg); + scrollbarBoxBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + scrollbarBoxBtn->SetSelectable(false); + scrollbarBoxBtn->SetEffectOnOver(EFFECT_SCALE, 50, 120); + scrollbarBoxBtn->SetMinY(0); + scrollbarBoxBtn->SetMaxY(height-30); + scrollbarBoxBtn->SetHoldable(true); + scrollbarBoxBtn->SetTrigger(trigHeldA); + } + + optionIndex = new int[size]; + optionVal = new GuiText * [size]; + optionBtn = new GuiButton * [size]; + optionTxt = new GuiText * [size]; + optionBg = new GuiImage * [size]; + + for(int i=0; i < size; i++) + { + optionTxt[i] = new GuiText(options->name[i], 20, (GXColor){0, 0, 0, 0xff}); + optionTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionTxt[i]->SetPosition(24,0); + + optionBg[i] = new GuiImage(bgOptionsEntry); + + optionVal[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); + optionVal[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionVal[i]->SetPosition(250,0); + + optionBtn[i] = new GuiButton(width-28,GAMESELECTSIZE); + optionBtn[i]->SetParent(this); + optionBtn[i]->SetLabel(optionTxt[i], 0); + optionBtn[i]->SetLabel(optionVal[i], 1); + optionBtn[i]->SetImageOver(optionBg[i]); + optionBtn[i]->SetPosition(5,GAMESELECTSIZE*i+4); + optionBtn[i]->SetRumble(false); + optionBtn[i]->SetTrigger(trigA); + optionBtn[i]->SetSoundClick(btnSoundClick); + } +} + +/** + * Destructor for the GuiCustomOptionBrowser class. + */ +GuiCustomOptionBrowser::~GuiCustomOptionBrowser() +{ + if (scrollbaron == 1) { + delete arrowUpBtn; + delete arrowDownBtn; + delete scrollbarBoxBtn; + delete scrollbarImg; + delete arrowDownImg; + delete arrowDownOverImg; + delete arrowUpImg; + delete arrowUpOverImg; + delete scrollbarBoxImg; + delete scrollbarBoxOverImg; + delete scrollbar; + delete arrowDown; + delete arrowDownOver; + delete arrowUp; + delete arrowUpOver; + delete scrollbarBox; + delete scrollbarBoxOver; + } + delete bgOptionsImg; + delete bgOptions; + delete bgOptionsEntry; + + delete trigA; + delete btnSoundClick; + +// delete optionBg; + for(int i = 0; i < size; i++) + { + delete optionTxt[i]; + delete optionVal[i]; + delete optionBg[i]; + delete optionBtn[i]; + } + delete [] optionIndex; + delete [] optionVal; + delete [] optionBtn; + delete [] optionTxt; + delete [] optionBg; +} + +void GuiCustomOptionBrowser::SetCol2Position(int x) +{ + for(int i = 0; i < size; i++) + optionVal[i]->SetPosition(x,0); +} + +void GuiCustomOptionBrowser::SetFocus(int f) +{ + focus = f; + + for(int i = 0; i < size; i++) + optionBtn[i]->ResetState(); + + if(f == 1) + optionBtn[selectedItem]->SetState(STATE_SELECTED); +} + +void GuiCustomOptionBrowser::ResetState() +{ + if(state != STATE_DISABLED) + { + state = STATE_DEFAULT; + stateChan = -1; + } + + for(int i = 0; i < size; i++) + { + optionBtn[i]->ResetState(); + } +} + +int GuiCustomOptionBrowser::GetClickedOption() +{ + int found = -1; + for(int i = 0; i < size; i++) + { + if(optionBtn[i]->GetState() == STATE_CLICKED) + { + optionBtn[i]->SetState(STATE_SELECTED); + found = optionIndex[i]; + break; + } + } + return found; +} + +int GuiCustomOptionBrowser::GetSelectedOption() +{ + int found = -1; + for(int i = 0; i < size; i++) + { + if(optionBtn[i]->GetState() == STATE_SELECTED) + { + found = optionIndex[i]; + break; + } + } + return found; +} + +/**************************************************************************** + * FindMenuItem + * + * Help function to find the next visible menu item on the list + ***************************************************************************/ + +int GuiCustomOptionBrowser::FindMenuItem(int currentItem, int direction) +{ + int nextItem = currentItem + direction; + + if(nextItem < 0 || nextItem >= options->length) + return -1; + + if(strlen(options->name[nextItem]) > 0) + return nextItem; + else + return FindMenuItem(nextItem, direction); +} + +/** + * Draw the button on screen + */ +void GuiCustomOptionBrowser::Draw() +{ + if(!this->IsVisible()) + return; + + bgOptionsImg->Draw(); + + int next = listOffset; + + for(int i=0; i < size; i++) + { + if(next >= 0) + { + optionBtn[i]->Draw(); + next = this->FindMenuItem(next, 1); + } + else + break; + } + + if(scrollbaron == 1) { + scrollbarImg->Draw(); + arrowUpBtn->Draw(); + arrowDownBtn->Draw(); + scrollbarBoxBtn->Draw(); + } + this->UpdateEffects(); +} + +void GuiCustomOptionBrowser::Update(GuiTrigger * t) +{ int next, prev, lang = options->length; + + if(state == STATE_DISABLED || !t) + return; + + + // scrolldelay affects how fast the list scrolls + // when the arrows are clicked + float scrolldelay = 3.5; + + + if (scrollbaron == 1) { + // update the location of the scroll box based on the position in the option list + + + arrowUpBtn->Update(t); + arrowDownBtn->Update(t); + scrollbarBoxBtn->Update(t); + } + next = listOffset; + + for(int i=0; i < size; i++) + { + if(next >= 0) + { + if(optionBtn[i]->GetState() == STATE_DISABLED) + { + optionBtn[i]->SetVisible(true); + optionBtn[i]->SetState(STATE_DEFAULT); + } + + optionTxt[i]->SetText(options->name[next]); + optionVal[i]->SetText(options->value[next]); + optionIndex[i] = next; + next = this->FindMenuItem(next, 1); + } + else + { + optionBtn[i]->SetVisible(false); + optionBtn[i]->SetState(STATE_DISABLED); + } + + if(focus) + { + if(i != selectedItem && optionBtn[i]->GetState() == STATE_SELECTED) + optionBtn[i]->ResetState(); + else if(i == selectedItem && optionBtn[i]->GetState() == STATE_DEFAULT) + optionBtn[selectedItem]->SetState(STATE_SELECTED, t->chan); + } + + optionBtn[i]->Update(t); + + if(optionBtn[i]->GetState() == STATE_SELECTED) + { + selectedItem = i; + } + } + + // pad/joystick navigation + if(!focus) + return; // skip navigation + + if (scrollbaron == 1) { + + if (t->Down() || + arrowDownBtn->GetState() == STATE_CLICKED || ////////////////////////////////////////////down + arrowDownBtn->GetState() == STATE_HELD) + { + + next = this->FindMenuItem(optionIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == size-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + } + else if(optionBtn[selectedItem+1]->IsVisible()) + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem++; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + }WPAD_ScanPads(); + u8 cnt, buttons = NULL; + /* Get pressed buttons */ + for (cnt = 0; cnt < 4; cnt++) + buttons |= WPAD_ButtonsHeld(cnt); + if (buttons == WPAD_BUTTON_A) { + + } else { + arrowDownBtn->ResetState(); + + } + + } + else if(t->Up() || + arrowUpBtn->GetState() == STATE_CLICKED || ////////////////////////////////////////////up + arrowUpBtn->GetState() == STATE_HELD) + { + prev = this->FindMenuItem(optionIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + } + else + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + selectedItem--; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + }WPAD_ScanPads(); + u8 cnt, buttons = NULL; + /* Get pressed buttons */ + for (cnt = 0; cnt < 4; cnt++) + buttons |= WPAD_ButtonsHeld(cnt); + if (buttons == WPAD_BUTTON_A) { + + } else { + arrowUpBtn->ResetState(); + + } + } + + if(scrollbarBoxBtn->GetState() == STATE_HELD && + scrollbarBoxBtn->GetStateChan() == t->chan && + t->wpad.ir.valid && options->length > size) + { + scrollbarBoxBtn->SetPosition(width/2-18+7,0); + int position = t->wpad.ir.y - 50 - scrollbarBoxBtn->GetTop(); + + listOffset = (position * lang)/180 - selectedItem; + + if(listOffset <= 0) + { + listOffset = 0; + selectedItem = 0; + } + else if(listOffset+size >= lang) + { + listOffset = lang-size; + selectedItem = size-1; + } + + } + int positionbar = 237*(listOffset + selectedItem) / lang; + + if(positionbar > 216) + positionbar = 216; + scrollbarBoxBtn->SetPosition(width/2-18+7, positionbar+8); + + + if(t->Right()) + { + if(listOffset < lang && lang > size) + { + listOffset =listOffset+ size; + if(listOffset+size >= lang) + listOffset = lang-size; + } + } + else if(t->Left()) + { + if(listOffset > 0) + { + listOffset =listOffset- size; + if(listOffset < 0) + listOffset = 0; + } + } + + } else { + + + if(t->Down()) + { + next = this->FindMenuItem(optionIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == size-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + } + else if(optionBtn[selectedItem+1]->IsVisible()) + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem++; + } + } + } + else if(t->Up()) + { + prev = this->FindMenuItem(optionIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + } + else + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + selectedItem--; + } + } + } + } + + if(updateCB) + updateCB(this); +} diff --git a/source/libwiigui/gui_customoptionbrowser.h b/source/libwiigui/gui_customoptionbrowser.h new file mode 100644 index 00000000..2ea016bb --- /dev/null +++ b/source/libwiigui/gui_customoptionbrowser.h @@ -0,0 +1,85 @@ +#include "gui.h" + +class customOptionList { + public: + customOptionList(int size) { + name = new char * [size]; + value = new char * [size]; + for (int i = 0; i < size; i++) + { + name[i] = new char[30]; + value[i] = new char[20]; + } + length = size; + }; + ~customOptionList(){ + for (int i = 0; i < length; i++) + { + delete [] name[i]; + delete [] value[i]; + } + delete [] name; + delete [] value; + }; + + public: + int length; + char ** name; + char ** value; +}; + +//!Display a list of menu options +class GuiCustomOptionBrowser : public GuiElement +{ + public: + GuiCustomOptionBrowser(int w, int h, customOptionList * l, const char * themePath, const char *custombg, const u8 *imagebg, int scrollbar); + ~GuiCustomOptionBrowser(); + void SetCol2Position(int x); + int FindMenuItem(int c, int d); + int GetClickedOption(); + int GetSelectedOption(); + void ResetState(); + void SetFocus(int f); + void Draw(); + void Update(GuiTrigger * t); + GuiText ** optionVal; + protected: + int selectedItem; + int listOffset; + int size; + + customOptionList * options; + int * optionIndex; + GuiButton ** optionBtn; + GuiText ** optionTxt; + GuiImage ** optionBg; + + GuiButton * arrowUpBtn; + GuiButton * arrowDownBtn; + GuiButton * scrollbarBoxBtn; + + GuiImage * bgOptionsImg; + GuiImage * scrollbarImg; + GuiImage * arrowDownImg; + GuiImage * arrowDownOverImg; + GuiImage * arrowUpImg; + GuiImage * arrowUpOverImg; + GuiImage * scrollbarBoxImg; + GuiImage * scrollbarBoxOverImg; + + GuiImageData * bgOptions; + GuiImageData * bgOptionsEntry; + GuiImageData * scrollbar; + GuiImageData * arrowDown; + GuiImageData * arrowDownOver; + GuiImageData * arrowUp; + GuiImageData * arrowUpOver; + GuiImageData * scrollbarBox; + GuiImageData * scrollbarBoxOver; + + GuiSound * btnSoundOver; + GuiSound * btnSoundClick; + GuiTrigger * trigA; + GuiTrigger * trigB; + GuiTrigger * trigHeldA; +}; diff --git a/source/libwiigui/gui_element.cpp b/source/libwiigui/gui_element.cpp new file mode 100644 index 00000000..778c70d9 --- /dev/null +++ b/source/libwiigui/gui_element.cpp @@ -0,0 +1,577 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_element.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +/** + * Constructor for the Object class. + */ +GuiElement::GuiElement() +{ + xoffset = 0; + yoffset = 0; + xmin = 0; + xmax = 0; + ymin = 0; + ymax = 0; + width = 0; + height = 0; + alpha = 255; + scale = 1; + state = STATE_DEFAULT; + stateChan = -1; + trigger[0] = NULL; + trigger[1] = NULL; + trigger[2] = NULL; + trigger[3] = NULL; + trigger[4] = NULL; + trigger[6] = NULL; + parentElement = NULL; + rumble = true; + selectable = false; + clickable = false; + holdable = false; + visible = true; + focus = -1; // cannot be focused + updateCB = NULL; + yoffsetDyn = 0; + xoffsetDyn = 0; + alphaDyn = -1; + scaleDyn = 1; + effects = 0; + effectAmount = 0; + effectTarget = 0; + effectsOver = 0; + effectAmountOver = 0; + effectTargetOver = 0; + + // default alignment - align to top left + alignmentVert = ALIGN_TOP; + alignmentHor = ALIGN_LEFT; +} + +/** + * Destructor for the GuiElement class. + */ +GuiElement::~GuiElement() +{ +} + +void GuiElement::SetParent(GuiElement * e) +{ + parentElement = e; +} +/** + * Get the left position of the GuiElement. + * @see SetLeft() + * @return Left position in pixel. + */ +int GuiElement::GetLeft() +{ + int x = 0; + int pWidth = 0; + int pLeft = 0; + + if(parentElement) + { + pWidth = parentElement->GetWidth(); + pLeft = parentElement->GetLeft(); + } + + if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT)) + pLeft += xoffsetDyn; + + switch(alignmentHor) + { + case ALIGN_LEFT: + x = pLeft; + break; + case ALIGN_CENTRE: + x = pLeft + (pWidth/2) - (width/2); + break; + case ALIGN_RIGHT: + x = pLeft + pWidth - width; + break; + } + return x + xoffset; +} + +/** + * Get the top position of the GuiElement. + * @see SetTop() + * @return Top position in pixel. + */ +int GuiElement::GetTop() +{ + int y = 0; + int pHeight = 0; + int pTop = 0; + + if(parentElement) + { + pHeight = parentElement->GetHeight(); + pTop = parentElement->GetTop(); + } + + if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT)) + pTop += yoffsetDyn; + + switch(alignmentVert) + { + case ALIGN_TOP: + y = pTop; + break; + case ALIGN_MIDDLE: + y = pTop + (pHeight/2) - (height/2); + break; + case ALIGN_BOTTOM: + y = pTop + pHeight - height; + break; + } + return y + yoffset; +} + +void GuiElement::SetMinX(int x) +{ + xmin = x; +} + +int GuiElement::GetMinX() +{ + return xmin; +} + +void GuiElement::SetMaxX(int x) +{ + xmax = x; +} + +int GuiElement::GetMaxX() +{ + return xmax; +} + +void GuiElement::SetMinY(int y) +{ + ymin = y; +} + +int GuiElement::GetMinY() +{ + return ymin; +} + +void GuiElement::SetMaxY(int y) +{ + ymax = y; +} + +int GuiElement::GetMaxY() +{ + return ymax; +} + +/** + * Get the width of the GuiElement. + * @see SetWidth() + * @return Width of the GuiElement. + */ +int GuiElement::GetWidth() +{ + return width; +} + +/** + * Get the height of the GuiElement. + * @see SetHeight() + * @return Height of the GuiElement. + */ +int GuiElement::GetHeight() +{ + return height; +} + +/** + * Set the width and height of the GuiElement. + * @param[in] Width Width in pixel. + * @param[in] Height Height in pixel. + * @see SetWidth() + * @see SetHeight() + */ +void GuiElement::SetSize(int w, int h) +{ + + width = w; + height = h; +} + +/** + * Get visible. + * @see SetVisible() + * @return true if visible, false otherwise. + */ +bool GuiElement::IsVisible() +{ + return visible; +} + +/** + * Set visible. + * @param[in] Visible Set to true to show GuiElement. + * @see IsVisible() + */ +void GuiElement::SetVisible(bool v) +{ + visible = v; +} + +void GuiElement::SetAlpha(int a) +{ + alpha = a; +} + +int GuiElement::GetAlpha() +{ + int a; + + if(alphaDyn >= 0) + a = alphaDyn; + else + a = alpha; + + if(parentElement) + a *= parentElement->GetAlpha()/255.0; + + return a; +} + +void GuiElement::SetScale(float s) +{ + scale = s; +} + +float GuiElement::GetScale() +{ + float s = scale * scaleDyn; + + if(parentElement) + s *= parentElement->GetScale(); + + return s; +} + +int GuiElement::GetState() +{ + return state; +} + +int GuiElement::GetStateChan() +{ + return stateChan; +} + +void GuiElement::SetState(int s, int c) +{ + state = s; + stateChan = c; +} + +void GuiElement::ResetState() +{ + if(state != STATE_DISABLED) + { + state = STATE_DEFAULT; + stateChan = -1; + } +} + +void GuiElement::SetClickable(bool c) +{ + clickable = c; +} + +void GuiElement::SetSelectable(bool s) +{ + selectable = s; +} + +void GuiElement::SetHoldable(bool d) +{ + holdable = d; +} + +bool GuiElement::IsSelectable() +{ + if(state == STATE_DISABLED || state == STATE_CLICKED) + return false; + else + return selectable; +} + +bool GuiElement::IsClickable() +{ + if(state == STATE_DISABLED || + state == STATE_CLICKED || + state == STATE_HELD) + return false; + else + return clickable; +} + +bool GuiElement::IsHoldable() +{ + if(state == STATE_DISABLED) + return false; + else + return holdable; +} + +void GuiElement::SetFocus(int f) +{ + focus = f; +} + +int GuiElement::IsFocused() +{ + return focus; +} + +void GuiElement::SetTrigger(GuiTrigger * t) +{ + if(!trigger[0]) + trigger[0] = t; + else if(!trigger[1]) + trigger[1] = t; + else if(!trigger[2]) + trigger[2] = t; + else if(!trigger[3]) + trigger[3] = t; + else if(!trigger[4]) + trigger[4] = t; + else if(!trigger[5]) + trigger[5] = t; + else // both were assigned, so we'll just overwrite the first one + trigger[0] = t; +} + +void GuiElement::SetTrigger(u8 i, GuiTrigger * t) +{ + trigger[i] = t; +} + +bool GuiElement::Rumble() +{ + return rumble; +} + +void GuiElement::SetRumble(bool r) +{ + rumble = r; +} + +int GuiElement::GetEffect() +{ + return effects; +} + +void GuiElement::SetEffect(int eff, int amount, int target) +{ + if(eff & EFFECT_SLIDE_IN) + { + // these calculations overcompensate a little + if(eff & EFFECT_SLIDE_TOP) + yoffsetDyn = -screenheight; + else if(eff & EFFECT_SLIDE_LEFT) + xoffsetDyn = -screenwidth; + else if(eff & EFFECT_SLIDE_BOTTOM) + yoffsetDyn = screenheight; + else if(eff & EFFECT_SLIDE_RIGHT) + xoffsetDyn = screenwidth; + } + if(eff & EFFECT_FADE && amount > 0) + { + alphaDyn = 0; + } + else if(eff & EFFECT_FADE && amount < 0) + { + alphaDyn = alpha; + } + + effects |= eff; + effectAmount = amount; + effectTarget = target; +} + +void GuiElement::SetEffectOnOver(int eff, int amount, int target) +{ + effectsOver |= eff; + effectAmountOver = amount; + effectTargetOver = target; +} + +void GuiElement::SetEffectGrow() +{ + SetEffectOnOver(EFFECT_SCALE, 4, 110); +} + +void GuiElement::UpdateEffects() +{ + if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT)) + { + if(effects & EFFECT_SLIDE_IN) + { + if(effects & EFFECT_SLIDE_LEFT) + { + xoffsetDyn += effectAmount; + + if(xoffsetDyn >= 0) + { + xoffsetDyn = 0; + effects = 0; + } + } + else if(effects & EFFECT_SLIDE_RIGHT) + { + xoffsetDyn -= effectAmount; + + if(xoffsetDyn <= 0) + { + xoffsetDyn = 0; + effects = 0; + } + } + else if(effects & EFFECT_SLIDE_TOP) + { + yoffsetDyn += effectAmount; + + if(yoffsetDyn >= 0) + { + yoffsetDyn = 0; + effects = 0; + } + } + else if(effects & EFFECT_SLIDE_BOTTOM) + { + yoffsetDyn -= effectAmount; + + if(yoffsetDyn <= 0) + { + yoffsetDyn = 0; + effects = 0; + } + } + } + else + { + if(effects & EFFECT_SLIDE_LEFT) + { + xoffsetDyn -= effectAmount; + + if(xoffsetDyn <= -screenwidth) + effects = 0; // shut off effect + } + else if(effects & EFFECT_SLIDE_RIGHT) + { + xoffsetDyn += effectAmount; + + if(xoffsetDyn >= screenwidth) + effects = 0; // shut off effect + } + else if(effects & EFFECT_SLIDE_TOP) + { + yoffsetDyn -= effectAmount; + + if(yoffsetDyn <= -screenheight) + effects = 0; // shut off effect + } + else if(effects & EFFECT_SLIDE_BOTTOM) + { + yoffsetDyn += effectAmount; + + if(yoffsetDyn >= screenheight) + effects = 0; // shut off effect + } + } + } + if(effects & EFFECT_FADE) + { + alphaDyn += effectAmount; + + if(effectAmount < 0 && alphaDyn <= 0) + { + alphaDyn = 0; + effects = 0; // shut off effect + } + else if(effectAmount > 0 && alphaDyn >= alpha) + { + alphaDyn = alpha; + effects = 0; // shut off effect + } + } + if(effects & EFFECT_SCALE) + { + scaleDyn += effectAmount/100.0; + + if((effectAmount < 0 && scaleDyn <= effectTarget/100.0) + || (effectAmount > 0 && scaleDyn >= effectTarget/100.0)) + { + scaleDyn = effectTarget/100.0; + effects = 0; // shut off effect + } + } +} + +void GuiElement::Update(GuiTrigger * t) +{ + if(updateCB) + updateCB(this); +} + +void GuiElement::SetUpdateCallback(UpdateCallback u) +{ + updateCB = u; +} + +void GuiElement::SetPosition(int xoff, int yoff) +{ + xoffset = xoff; + yoffset = yoff; +} + +void GuiElement::SetAlignment(int hor, int vert) +{ + alignmentHor = hor; + alignmentVert = vert; +} + +int GuiElement::GetSelected() +{ + return -1; +} + +/** + * Draw an element on screen. + */ +void GuiElement::Draw() +{ +} + +/** + * Check if a position is inside the GuiElement. + * @param[in] x X position in pixel. + * @param[in] y Y position in pixel. + */ +bool GuiElement::IsInside(int x, int y) +{ + if(x > this->GetLeft() && x < (this->GetLeft()+width) + && y > this->GetTop() && y < (this->GetTop()+height)) + return true; + return false; +} diff --git a/source/libwiigui/gui_gamebrowser.cpp b/source/libwiigui/gui_gamebrowser.cpp new file mode 100644 index 00000000..32ee2f9f --- /dev/null +++ b/source/libwiigui/gui_gamebrowser.cpp @@ -0,0 +1,615 @@ +/**************************************************************************** + * libwiigui + * + * gui_gamebrowser.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +#include "../wpad.h" + +#include +#include "gui_gamebrowser.h" +#include "cfg.h" + +#define GAMESELECTSIZE 30 +extern const int vol; +/** + * Constructor for the GuiGameBrowser class. + */ +GuiGameBrowser::GuiGameBrowser(int w, int h, struct discHdr * l, int gameCnt, const char *themePath, const u8 *imagebg, int selected, int offset) +{ + width = w; + height = h; + this->gameCnt = gameCnt; + gameList = l; + pagesize = (gameCnt > PAGESIZE) ? PAGESIZE : gameCnt; + scrollbaron = (gameCnt > PAGESIZE) ? 1 : 0; + selectable = true; + listOffset = (offset == 0) ? this->FindMenuItem(-1, 1) : offset; + selectedItem = selected - offset; + focus = 1; // allow focus + char imgPath[100]; + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trigHeldA = new GuiTrigger; + trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A); + btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM, vol); + + snprintf(imgPath, sizeof(imgPath), "%sbg_options.png", themePath); + bgGames = new GuiImageData(imgPath, imagebg); + + bgGameImg = new GuiImage(bgGames); + bgGameImg->SetParent(this); + bgGameImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + + snprintf(imgPath, sizeof(imgPath), "%sbg_options_entry.png", themePath); + bgGamesEntry = new GuiImageData(imgPath, bg_options_entry_png); + if (scrollbaron == 1) { + snprintf(imgPath, sizeof(imgPath), "%sscrollbar.png", themePath); + scrollbar = new GuiImageData(imgPath, scrollbar_png); + scrollbarImg = new GuiImage(scrollbar); + scrollbarImg->SetParent(this); + scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarImg->SetPosition(0, 4); + + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_arrowdown.png", themePath); + arrowDown = new GuiImageData(imgPath, scrollbar_arrowdown_png); + arrowDownImg = new GuiImage(arrowDown); + arrowDownOver = new GuiImageData(imgPath, scrollbar_arrowdown_png); + arrowDownOverImg = new GuiImage(arrowDownOver); + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_arrowup.png", themePath); + arrowUp = new GuiImageData(imgPath, scrollbar_arrowup_png); + arrowUpImg = new GuiImage(arrowUp); + arrowUpOver = new GuiImageData(imgPath, scrollbar_arrowup_png); + arrowUpOverImg = new GuiImage(arrowUpOver); + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_box.png", themePath); + scrollbarBox = new GuiImageData(imgPath, scrollbar_box_png); + scrollbarBoxImg = new GuiImage(scrollbarBox); + scrollbarBoxOver = new GuiImageData(imgPath, scrollbar_box_png); + scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver); + + arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight()); + arrowUpBtn->SetParent(this); + arrowUpBtn->SetImage(arrowUpImg); + arrowUpBtn->SetImageOver(arrowUpOverImg); + arrowUpBtn->SetImageHold(arrowUpOverImg); + arrowUpBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + arrowUpBtn->SetPosition(width/2-18+7,-18); + arrowUpBtn->SetSelectable(false); + arrowUpBtn->SetTrigger(trigA); + arrowUpBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowUpBtn->SetSoundClick(btnSoundClick); + + arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight()); + arrowDownBtn->SetParent(this); + arrowDownBtn->SetImage(arrowDownImg); + arrowDownBtn->SetImageOver(arrowDownOverImg); + arrowDownBtn->SetImageHold(arrowDownOverImg); + arrowDownBtn->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + arrowDownBtn->SetPosition(width/2-18+7,18); + arrowDownBtn->SetSelectable(false); + arrowDownBtn->SetTrigger(trigA); + arrowDownBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowDownBtn->SetSoundClick(btnSoundClick); + + scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight()); + scrollbarBoxBtn->SetParent(this); + scrollbarBoxBtn->SetImage(scrollbarBoxImg); + scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg); + scrollbarBoxBtn->SetImageHold(scrollbarBoxOverImg); + scrollbarBoxBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + scrollbarBoxBtn->SetSelectable(false); + scrollbarBoxBtn->SetEffectOnOver(EFFECT_SCALE, 50, 120); + scrollbarBoxBtn->SetMinY(0); + scrollbarBoxBtn->SetMaxY(height-30); + scrollbarBoxBtn->SetHoldable(true); + scrollbarBoxBtn->SetTrigger(trigHeldA); + } + + gameIndex = new int[pagesize]; + game = new GuiButton * [pagesize]; + gameTxt = new GuiText * [pagesize]; + gameBg = new GuiImage * [pagesize]; + + char buffer[CFG.maxcharacters + 4]; + + for(int i=0; i < pagesize; i++) + { + if (strlen(get_title(&gameList[i])) < (u32)(CFG.maxcharacters + 3)) + { + sprintf(buffer, "%s", get_title(&gameList[i])); + } + else + { + sprintf(buffer, get_title(&gameList[i]), CFG.maxcharacters); + buffer[CFG.maxcharacters] = '\0'; + strncat(buffer, "...", 3); + } + + gameTxt[i] = new GuiText(buffer, 20, (GXColor){0, 0, 0, 0xff}); + gameTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + gameTxt[i]->SetPosition(24,0); + + gameBg[i] = new GuiImage(bgGamesEntry); + + game[i] = new GuiButton(width-28,GAMESELECTSIZE); + game[i]->SetParent(this); + game[i]->SetLabel(gameTxt[i]); + game[i]->SetImageOver(gameBg[i]); + game[i]->SetPosition(5,GAMESELECTSIZE*i+4); + game[i]->SetRumble(false); + game[i]->SetTrigger(trigA); + game[i]->SetSoundClick(btnSoundClick); + } +} + +/** + * Destructor for the GuiGameBrowser class. + */ +GuiGameBrowser::~GuiGameBrowser() +{ + if (scrollbaron == 1) { + delete arrowUpBtn; + delete arrowDownBtn; + delete scrollbarBoxBtn; + delete scrollbarImg; + delete arrowDownImg; + delete arrowDownOverImg; + delete arrowUpImg; + delete arrowUpOverImg; + delete scrollbarBoxImg; + delete scrollbarBoxOverImg; + delete scrollbar; + delete arrowDown; + delete arrowDownOver; + delete arrowUp; + delete arrowUpOver; + delete scrollbarBox; + delete scrollbarBoxOver; + } + delete bgGameImg; + delete bgGames; + delete bgGamesEntry; + + delete trigA; + delete btnSoundClick; + +// delete optionBg; + for(int i=0; iResetState(); + + if(f == 1) + game[selectedItem]->SetState(STATE_SELECTED); +} + +void GuiGameBrowser::ResetState() +{ + if(state != STATE_DISABLED) + { + state = STATE_DEFAULT; + stateChan = -1; + } + + for(int i=0; iResetState(); + } +} + +int GuiGameBrowser::GetOffset() +{ + return listOffset; +} +int GuiGameBrowser::GetClickedOption() +{ + int found = -1; + for(int i=0; iGetState() == STATE_CLICKED) + { + game[i]->SetState(STATE_SELECTED); + found = gameIndex[i]; + break; + } + } + return found; +} + +int GuiGameBrowser::GetSelectedOption() +{ + int found = -1; + for(int i=0; iGetState() == STATE_SELECTED) + { + game[i]->SetState(STATE_SELECTED); + found = gameIndex[i]; + break; + } + } + return found; +} + +/**************************************************************************** + * FindMenuItem + * + * Help function to find the next visible menu item on the list + ***************************************************************************/ + +int GuiGameBrowser::FindMenuItem(int currentItem, int direction) +{ + int nextItem = currentItem + direction; + + if(nextItem < 0 || nextItem >= gameCnt) + return -1; + + if(strlen(get_title(&gameList[nextItem])) > 0) + return nextItem; + else + return FindMenuItem(nextItem, direction); +} + +/** + * Draw the button on screen + */ +void GuiGameBrowser::Draw() +{ + if(!this->IsVisible()) + return; + + bgGameImg->Draw(); + + int next = listOffset; + + for(int i=0; i= 0) + { + game[i]->Draw(); + next = this->FindMenuItem(next, 1); + } + else + break; + } + + if(scrollbaron == 1) { + scrollbarImg->Draw(); + arrowUpBtn->Draw(); + arrowDownBtn->Draw(); + scrollbarBoxBtn->Draw(); + } + this->UpdateEffects(); +} + +void GuiGameBrowser::Update(GuiTrigger * t) +{ + if(state == STATE_DISABLED || !t) + return; + + int next, prev; + static int position2; + // scrolldelay affects how fast the list scrolls + // when the arrows are clicked + float scrolldelay = 3.5; + + + if (scrollbaron == 1) { + // update the location of the scroll box based on the position in the option list + arrowUpBtn->Update(t); + arrowDownBtn->Update(t); + scrollbarBoxBtn->Update(t); + } + + next = listOffset; + char buffer[CFG.maxcharacters + 4]; + + for(int i=0; i= 0) + { + if(game[i]->GetState() == STATE_DISABLED) + { + game[i]->SetVisible(true); + game[i]->SetState(STATE_DEFAULT); + } + + if (strlen(get_title(&gameList[next])) < (u32)(CFG.maxcharacters + 3)) + { + sprintf(buffer, "%s", get_title(&gameList[next])); + } + else + { + sprintf(buffer, get_title(&gameList[next]), CFG.maxcharacters); + buffer[CFG.maxcharacters] = '\0'; + strncat(buffer, "...", 3); + } + + gameTxt[i]->SetText(buffer); + gameIndex[i] = next; + next = this->FindMenuItem(next, 1); + } + else + { + game[i]->SetVisible(false); + game[i]->SetState(STATE_DISABLED); + } + + if(focus) + { + if(i != selectedItem && game[i]->GetState() == STATE_SELECTED) + game[i]->ResetState(); + else if(i == selectedItem && game[i]->GetState() == STATE_DEFAULT) + game[selectedItem]->SetState(STATE_SELECTED, t->chan); + } + + game[i]->Update(t); + + if(game[i]->GetState() == STATE_SELECTED) + { + selectedItem = i; + } + } + + // pad/joystick navigation + if(!focus) + return; // skip navigation + + if (scrollbaron == 1) { + + if (t->Down() || + arrowDownBtn->GetState() == STATE_CLICKED || ////////////////////////////////////////////down + arrowDownBtn->GetState() == STATE_HELD) + { + + + next = this->FindMenuItem(gameIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == pagesize-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + } + else if(game[selectedItem+1]->IsVisible()) + { + game[selectedItem]->ResetState(); + game[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem++; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + }WPAD_ScanPads(); + u8 cnt, buttons = NULL; + /* Get pressed buttons */ + for (cnt = 0; cnt < 4; cnt++) + buttons |= WPAD_ButtonsHeld(cnt); + if (buttons == WPAD_BUTTON_A) { + + } else { + arrowDownBtn->ResetState(); + + } + + } + else if(t->Up() || + arrowUpBtn->GetState() == STATE_CLICKED || ////////////////////////////////////////////up + arrowUpBtn->GetState() == STATE_HELD) + { + prev = this->FindMenuItem(gameIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + } + else + { + game[selectedItem]->ResetState(); + game[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + selectedItem--; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + } + + WPAD_ScanPads(); + u8 cnt, buttons = NULL; + /* Get pressed buttons */ + for (cnt = 0; cnt < 4; cnt++) + buttons |= WPAD_ButtonsHeld(cnt); + if (buttons == WPAD_BUTTON_A) { + + } else { + arrowUpBtn->ResetState(); + + } + } + + WPAD_ScanPads(); + u8 cnt, buttons = NULL; + int position1 = 0; + + + position1 = t->wpad.ir.y; + + if (position2 == 0 && position1 > 0) { + position2 = position1; + } + + for (cnt = 0; cnt < 4; cnt++) + buttons |= WPAD_ButtonsHeld(cnt); + + if (buttons == WPAD_BUTTON_B && position1 > 0) { + scrollbarBoxBtn->ScrollIsOn(1); + if (position2 > position1) { + + prev = this->FindMenuItem(gameIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + } + else + { + game[selectedItem]->ResetState(); + game[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + selectedItem--; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + } + + } else if (position2 < position1) { + + + next = this->FindMenuItem(gameIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == pagesize-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + } + else if(game[selectedItem+1]->IsVisible()) + { + game[selectedItem]->ResetState(); + game[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem++; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + } + } + + } else if (!buttons) { + scrollbarBoxBtn->ScrollIsOn(0); + position2 = 0; + } + + if(scrollbarBoxBtn->GetState() == STATE_HELD && + scrollbarBoxBtn->GetStateChan() == t->chan && + t->wpad.ir.valid && gameCnt > pagesize) + { + scrollbarBoxBtn->SetPosition(width/2-18+7,0); + int position = t->wpad.ir.y - 50 - scrollbarBoxBtn->GetTop(); + + listOffset = (position * gameCnt)/180 - selectedItem; + + if(listOffset <= 0) + { + listOffset = 0; + selectedItem = 0; + } + else if(listOffset+pagesize >= gameCnt) + { + listOffset = gameCnt - pagesize; + selectedItem = pagesize-1; + } + + } + int positionbar = 237*(listOffset + selectedItem) / gameCnt; + + if(positionbar > 216) + positionbar = 216; + scrollbarBoxBtn->SetPosition(width/2-18+7, positionbar+8); + + + if(t->Right()) + { + if(listOffset < gameCnt && gameCnt > pagesize) + { + listOffset =listOffset+ pagesize; + if(listOffset+pagesize >= gameCnt) + listOffset = gameCnt-pagesize; + } + } + else if(t->Left()) + { + if(listOffset > 0) + { + listOffset =listOffset- pagesize; + if(listOffset < 0) + listOffset = 0; + } + } + + } else { + + + if(t->Down()) + { + next = this->FindMenuItem(gameIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == pagesize-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + } + else if(game[selectedItem+1]->IsVisible()) + { + game[selectedItem]->ResetState(); + game[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem++; + } + } + } + else if(t->Up()) + { + prev = this->FindMenuItem(gameIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + } + else + { + game[selectedItem]->ResetState(); + game[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + selectedItem--; + } + } + } + } + + if(updateCB) + updateCB(this); +} diff --git a/source/libwiigui/gui_gamebrowser.h b/source/libwiigui/gui_gamebrowser.h new file mode 100644 index 00000000..6b6661f8 --- /dev/null +++ b/source/libwiigui/gui_gamebrowser.h @@ -0,0 +1,88 @@ +#ifndef _GUIGAMEBROWSER_H_ +#define _GUIGAMEBROWSER_H_ + +#include "gui.h" +#include "../disc.h" +/* +class GameBrowserList { + public: + GameBrowserList(int size) { + name = new char * [size]; + + for (int i = 0; i < size; i++) + { + name[i] = new char[50]; + } + length = size; + }; + ~GameBrowserList(){ + for (int i = 0; i < length; i++) + { + delete [] name[i]; + } + delete [] name; + }; + + public: + int length; + char ** name; +}; +*/ + +class GuiGameBrowser : public GuiElement +{ + public: + GuiGameBrowser(int w, int h, struct discHdr * l, int gameCnt, const char *themePath, const u8 *imagebg, int selected = 0, int offset = 0); + ~GuiGameBrowser(); + int FindMenuItem(int c, int d); + int GetClickedOption(); + int GetSelectedOption(); + void ResetState(); + void SetFocus(int f); + void Draw(); + void Update(GuiTrigger * t); + int GetOffset(); + //GuiText * optionVal[PAGESIZE]; + protected: + int selectedItem; + int listOffset; + int scrollbaron; + int pagesize; + + struct discHdr * gameList; + int gameCnt; + + int * gameIndex; + GuiButton ** game; + GuiText ** gameTxt; + GuiImage ** gameBg; + + GuiButton * arrowUpBtn; + GuiButton * arrowDownBtn; + GuiButton * scrollbarBoxBtn; + + GuiImage * bgGameImg; + GuiImage * scrollbarImg; + GuiImage * arrowDownImg; + GuiImage * arrowDownOverImg; + GuiImage * arrowUpImg; + GuiImage * arrowUpOverImg; + GuiImage * scrollbarBoxImg; + GuiImage * scrollbarBoxOverImg; + + GuiImageData * bgGames; + GuiImageData * bgGamesEntry; + GuiImageData * scrollbar; + GuiImageData * arrowDown; + GuiImageData * arrowDownOver; + GuiImageData * arrowUp; + GuiImageData * arrowUpOver; + GuiImageData * scrollbarBox; + GuiImageData * scrollbarBoxOver; + + GuiSound * btnSoundOver; + GuiSound * btnSoundClick; + GuiTrigger * trigA; + GuiTrigger * trigHeldA; +}; +#endif diff --git a/source/libwiigui/gui_image.cpp b/source/libwiigui/gui_image.cpp new file mode 100644 index 00000000..e89fcbae --- /dev/null +++ b/source/libwiigui/gui_image.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_image.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +/** + * Constructor for the GuiImage class. + */ +GuiImage::GuiImage() +{ + image = NULL; + width = 0; + height = 0; + imageangle = 0; + tile = -1; + stripe = 0; + widescreen = 0; + imgType = IMAGE_DATA; +} + +GuiImage::GuiImage(GuiImageData * img) +{ + image = img->GetImage(); + width = img->GetWidth(); + height = img->GetHeight(); + imageangle = 0; + tile = -1; + stripe = 0; + widescreen = 0; + imgType = IMAGE_DATA; +} + +GuiImage::GuiImage(u8 * img, int w, int h) +{ + image = img; + width = w; + height = h; + imageangle = 0; + tile = -1; + stripe = 0; + widescreen = 0; + imgType = IMAGE_TEXTURE; +} + +GuiImage::GuiImage(int w, int h, GXColor c) +{ + image = (u8 *)memalign (32, w * h * 4); + width = w; + height = h; + imageangle = 0; + tile = -1; + stripe = 0; + widescreen = 0; + imgType = IMAGE_COLOR; + + if(!image) + return; + + int x, y; + + for(y=0; y < h; y++) + { + for(x=0; x < w; x++) + { + this->SetPixel(x, y, c); + } + } + int len = w*h*4; + if(len%32) len += (32-len%32); + DCFlushRange(image, len); +} + +/** + * Destructor for the GuiImage class. + */ +GuiImage::~GuiImage() +{ + if(imgType == IMAGE_COLOR && image) + free(image); +} + +u8 * GuiImage::GetImage() +{ + return image; +} + +void GuiImage::SetImage(GuiImageData * img) +{ + image = img->GetImage(); + width = img->GetWidth(); + height = img->GetHeight(); + imgType = IMAGE_DATA; +} + +void GuiImage::SetImage(u8 * img, int w, int h) +{ + image = img; + width = w; + height = h; + imgType = IMAGE_TEXTURE; +} + +void GuiImage::SetAngle(float a) +{ + imageangle = a; +} + +void GuiImage::SetTile(int t) +{ + tile = t; +} + +void GuiImage::SetWidescreen(short w) +{ + widescreen = w; +} + +GXColor GuiImage::GetPixel(int x, int y) +{ + if(!image || this->GetWidth() <= 0 || x < 0 || y < 0) + return (GXColor){0, 0, 0, 0}; + + u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1); + GXColor color; + color.a = *(image+offset); + color.r = *(image+offset+1); + color.g = *(image+offset+32); + color.b = *(image+offset+33); + return color; +} + +void GuiImage::SetPixel(int x, int y, GXColor color) +{ + if(!image || this->GetWidth() <= 0 || x < 0 || y < 0) + return; + + u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1); + *(image+offset) = color.a; + *(image+offset+1) = color.r; + *(image+offset+32) = color.g; + *(image+offset+33) = color.b; +} + +void GuiImage::SetStripe(int s) +{ + stripe = s; +} + +void GuiImage::ColorStripe(int shift) +{ + int x, y; + GXColor color; + int alt = 0; + + for(y=0; y < this->GetHeight(); y++) + { + if(y % 3 == 0) + alt ^= 1; + + for(x=0; x < this->GetWidth(); x++) + { + color = GetPixel(x, y); + + if(alt) + { + if(color.r < 255-shift) + color.r += shift; + else + color.r = 255; + if(color.g < 255-shift) + color.g += shift; + else + color.g = 255; + if(color.b < 255-shift) + color.b += shift; + else + color.b = 255; + + color.a = 255; + } + else + { + if(color.r > shift) + color.r -= shift; + else + color.r = 0; + if(color.g > shift) + color.g -= shift; + else + color.g = 0; + if(color.b > shift) + color.b -= shift; + else + color.b = 0; + + color.a = 255; + } + SetPixel(x, y, color); + } + } +} + +/** + * Draw the button on screen + */ +void GuiImage::Draw() +{ + if(!image || !this->IsVisible() || tile == 0) + return; + + float currScale = this->GetScale(); + int currLeft = this->GetLeft(); + + if(tile > 0) + { + for(int i=0; iGetTop(), width, height, image, imageangle, widescreen ? currScale*0.8 : currScale, currScale, this->GetAlpha()); + } + else + { + // temporary (maybe), used to correct offset for scaled images + if(scale != 1) + currLeft = currLeft - width/2 + (width*scale)/2; + + Menu_DrawImg(currLeft, this->GetTop(), width, height, image, imageangle, widescreen ? currScale*0.8 : currScale, currScale, this->GetAlpha()); + } + + if(stripe > 0) + for(int y=0; y < this->GetHeight(); y+=6) + Menu_DrawRectangle(currLeft,this->GetTop()+y,this->GetWidth(),3,(GXColor){0, 0, 0, stripe},1); + + this->UpdateEffects(); +} diff --git a/source/libwiigui/gui_imagedata.cpp b/source/libwiigui/gui_imagedata.cpp new file mode 100644 index 00000000..21b5f2e3 --- /dev/null +++ b/source/libwiigui/gui_imagedata.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_imagedata.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +/** + * Constructor for the GuiImageData class. + */ +GuiImageData::GuiImageData(const u8 * img) +{ + data = NULL; + width = 0; + height = 0; + + if(img) + { + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromBuffer(img); + + if(!ctx) + return; + + int res = PNGU_GetImageProperties(ctx, &imgProp); + + if(res == PNGU_OK) + { + int len = imgProp.imgWidth * imgProp.imgHeight * 4; + if(len%32) len += (32-len%32); + data = (u8 *)memalign (32, len); + + if(data) + { + res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255); + + if(res == PNGU_OK) + { + width = imgProp.imgWidth; + height = imgProp.imgHeight; + DCFlushRange(data, len); + } + else + { + free(data); + data = NULL; + } + } + } + PNGU_ReleaseImageContext (ctx); + } +} + +/** + * Constructor for the GuiImageData class. + */ +GuiImageData::GuiImageData(const char * imgPath, const u8 * buffer) +{ + data = NULL; + width = 0; + height = 0; + + if(imgPath) + { + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromDevice(imgPath); + + if(ctx) + { + int res = PNGU_GetImageProperties(ctx, &imgProp); + + if(res == PNGU_OK) + { + int len = imgProp.imgWidth * imgProp.imgHeight * 4; + if(len%32) len += (32-len%32); + data = (u8 *)memalign (32, len); + + if(data) + { + res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255); + + if(res == PNGU_OK) + { + width = imgProp.imgWidth; + height = imgProp.imgHeight; + DCFlushRange(data, len); + } + else + { + free(data); + data = NULL; + } + } + } + PNGU_ReleaseImageContext (ctx); + } + } + + if (!data) //use buffer data instead + { + width = 0; + height = 0; + if(buffer) + { + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromBuffer(buffer); + + if(!ctx) + return; + + int res = PNGU_GetImageProperties(ctx, &imgProp); + + if(res == PNGU_OK) + { + int len = imgProp.imgWidth * imgProp.imgHeight * 4; + if(len%32) len += (32-len%32); + data = (u8 *)memalign (32, len); + + if(data) + { + res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255); + + if(res == PNGU_OK) + { + width = imgProp.imgWidth; + height = imgProp.imgHeight; + DCFlushRange(data, len); + } + else + { + free(data); + data = NULL; + } + } + } + PNGU_ReleaseImageContext (ctx); + } + } +} + +/** + * Destructor for the GuiImageData class. + */ +GuiImageData::~GuiImageData() +{ + if(data) + { + free(data); + data = NULL; + } +} + +u8 * GuiImageData::GetImage() +{ + return data; +} + +int GuiImageData::GetWidth() +{ + return width; +} + +int GuiImageData::GetHeight() +{ + return height; +} diff --git a/source/libwiigui/gui_keyboard.cpp b/source/libwiigui/gui_keyboard.cpp new file mode 100644 index 00000000..066307e4 --- /dev/null +++ b/source/libwiigui/gui_keyboard.cpp @@ -0,0 +1,330 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_keyboard.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +/** + * Constructor for the GuiKeyboard class. + */ +extern const int vol; +GuiKeyboard::GuiKeyboard(char * t, u32 max) +{ + width = 540; + height = 400; + shift = 0; + caps = 0; + selectable = true; + focus = 0; // allow focus + alignmentHor = ALIGN_CENTRE; + alignmentVert = ALIGN_MIDDLE; + strncpy(kbtextstr, t, max); + kbtextstr[max] = 0; + kbtextmaxlen = max; + + Key thekeys[4][11] = { + { + {'1','!'}, + {'2','@'}, + {'3','#'}, + {'4','$'}, + {'5','%'}, + {'6','^'}, + {'7','&'}, + {'8','*'}, + {'9','('}, + {'0',')'}, + {'\0','\0'} + }, + { + {'q','Q'}, + {'w','W'}, + {'e','E'}, + {'r','R'}, + {'t','T'}, + {'y','Y'}, + {'u','U'}, + {'i','I'}, + {'o','O'}, + {'p','P'}, + {'-','_'} + }, + { + {'a','A'}, + {'s','S'}, + {'d','D'}, + {'f','F'}, + {'g','G'}, + {'h','H'}, + {'j','J'}, + {'k','K'}, + {'l','L'}, + {':',';'}, + {'\'','"'} + }, + + { + {'z','Z'}, + {'x','X'}, + {'c','C'}, + {'v','V'}, + {'b','B'}, + {'n','N'}, + {'m','M'}, + {',','<'}, + {'.','>'}, + {'/','?'}, + {'\0','\0'} + } + }; + memcpy(keys, thekeys, sizeof(thekeys)); + + keyTextbox = new GuiImageData(keyboard_textbox_png); + keyTextboxImg = new GuiImage(keyTextbox); + keyTextboxImg->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + keyTextboxImg->SetPosition(0, 0); + this->Append(keyTextboxImg); + + kbText = new GuiText(kbtextstr, 20, (GXColor){0, 0, 0, 0xff}); + kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + kbText->SetPosition(0, 13); + this->Append(kbText); + + key = new GuiImageData(keyboard_key_png); + keyOver = new GuiImageData(keyboard_key_over_png); + keyMedium = new GuiImageData(keyboard_mediumkey_png); + keyMediumOver = new GuiImageData(keyboard_mediumkey_over_png); + keyLarge = new GuiImageData(keyboard_largekey_png); + keyLargeOver = new GuiImageData(keyboard_largekey_over_png); + + keySoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + keySoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM, vol); + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trigB = new GuiTrigger; + trigB->SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + keyBackImg = new GuiImage(keyMedium); + keyBackOverImg = new GuiImage(keyMediumOver); + keyBackText = new GuiText("Back", 20, (GXColor){0, 0, 0, 0xff}); + keyBack = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyBack->SetImage(keyBackImg); + keyBack->SetImageOver(keyBackOverImg); + keyBack->SetLabel(keyBackText); + keyBack->SetSoundOver(keySoundOver); + keyBack->SetSoundClick(keySoundClick); + keyBack->SetTrigger(trigA); + keyBack->SetTrigger(trigB); + keyBack->SetPosition(10*42+40, 0*42+80); + keyBack->SetEffectGrow(); + this->Append(keyBack); + + keyCapsImg = new GuiImage(keyMedium); + keyCapsOverImg = new GuiImage(keyMediumOver); + keyCapsText = new GuiText("Caps", 20, (GXColor){0, 0, 0, 0xff}); + keyCaps = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyCaps->SetImage(keyCapsImg); + keyCaps->SetImageOver(keyCapsOverImg); + keyCaps->SetLabel(keyCapsText); + keyCaps->SetSoundOver(keySoundOver); + keyCaps->SetSoundClick(keySoundClick); + keyCaps->SetTrigger(trigA); + keyCaps->SetPosition(0, 2*42+80); + keyCaps->SetEffectGrow(); + this->Append(keyCaps); + + keyShiftImg = new GuiImage(keyMedium); + keyShiftOverImg = new GuiImage(keyMediumOver); + keyShiftText = new GuiText("Shift", 20, (GXColor){0, 0, 0, 0xff}); + keyShift = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyShift->SetImage(keyShiftImg); + keyShift->SetImageOver(keyShiftOverImg); + keyShift->SetLabel(keyShiftText); + keyShift->SetSoundOver(keySoundOver); + keyShift->SetSoundClick(keySoundClick); + keyShift->SetTrigger(trigA); + keyShift->SetPosition(21, 3*42+80); + keyShift->SetEffectGrow(); + this->Append(keyShift); + + keySpaceImg = new GuiImage(keyLarge); + keySpaceOverImg = new GuiImage(keyLargeOver); + keySpace = new GuiButton(keyLarge->GetWidth(), keyLarge->GetHeight()); + keySpace->SetImage(keySpaceImg); + keySpace->SetImageOver(keySpaceOverImg); + keySpace->SetSoundOver(keySoundOver); + keySpace->SetSoundClick(keySoundClick); + keySpace->SetTrigger(trigA); + keySpace->SetPosition(0, 4*42+80); + keySpace->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + keySpace->SetEffectGrow(); + this->Append(keySpace); + + for(int i=0; i<4; i++) + { + for(int j=0; j<11; j++) + { + if(keys[i][j].ch != '\0') + { + keyImg[i][j] = new GuiImage(key); + keyImgOver[i][j] = new GuiImage(keyOver); + keyTxt[i][j] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); + keyTxt[i][j]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + keyTxt[i][j]->SetPosition(0, -10); + keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight()); + keyBtn[i][j]->SetImage(keyImg[i][j]); + keyBtn[i][j]->SetImageOver(keyImgOver[i][j]); + keyBtn[i][j]->SetSoundOver(keySoundOver); + keyBtn[i][j]->SetSoundClick(keySoundClick); + keyBtn[i][j]->SetTrigger(trigA); + keyBtn[i][j]->SetLabel(keyTxt[i][j]); + keyBtn[i][j]->SetPosition(j*42+21*i+40, i*42+80); + keyBtn[i][j]->SetEffectGrow(); + this->Append(keyBtn[i][j]); + } + } + } +} + +/** + * Destructor for the GuiKeyboard class. + */ +GuiKeyboard::~GuiKeyboard() +{ + delete kbText; + delete keyTextbox; + delete keyTextboxImg; + delete keyCapsText; + delete keyCapsImg; + delete keyCapsOverImg; + delete keyCaps; + delete keyShiftText; + delete keyShiftImg; + delete keyShiftOverImg; + delete keyShift; + delete keyBackText; + delete keyBackImg; + delete keyBackOverImg; + delete keyBack; + delete keySpaceImg; + delete keySpaceOverImg; + delete keySpace; + delete key; + delete keyOver; + delete keyMedium; + delete keyMediumOver; + delete keyLarge; + delete keyLargeOver; + delete keySoundOver; + delete keySoundClick; + delete trigA; + delete trigB; + + for(int i=0; i<4; i++) + { + for(int j=0; j<11; j++) + { + if(keys[i][j].ch != '\0') + { + delete keyImg[i][j]; + delete keyImgOver[i][j]; + delete keyTxt[i][j]; + delete keyBtn[i][j]; + } + } + } +} + +void GuiKeyboard::Update(GuiTrigger * t) +{ + if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) + return; + + for (u8 i = 0; i < _elements.size(); i++) + { + try { _elements.at(i)->Update(t); } + catch (const std::exception& e) { } + } + + if(keySpace->GetState() == STATE_CLICKED) + { + if(strlen(kbtextstr) < kbtextmaxlen) + { + kbtextstr[strlen(kbtextstr)] = ' '; + kbText->SetText(kbtextstr); + } + keySpace->SetState(STATE_SELECTED, t->chan); + } + else if(keyBack->GetState() == STATE_CLICKED) + { + kbtextstr[strlen(kbtextstr)-1] = 0; + kbText->SetText(kbtextstr); + keyBack->SetState(STATE_SELECTED, t->chan); + } + else if(keyShift->GetState() == STATE_CLICKED) + { + shift ^= 1; + keyShift->SetState(STATE_SELECTED, t->chan); + } + else if(keyCaps->GetState() == STATE_CLICKED) + { + caps ^= 1; + keyCaps->SetState(STATE_SELECTED, t->chan); + } + + char txt[2] = { 0, 0 }; + + for(int i=0; i<4; i++) + { + for(int j=0; j<11; j++) + { + if(keys[i][j].ch != '\0') + { + if(shift || caps) + txt[0] = keys[i][j].chShift; + else + txt[0] = keys[i][j].ch; + + keyTxt[i][j]->SetText(txt); + + if(keyBtn[i][j]->GetState() == STATE_CLICKED) + { + if(strlen(kbtextstr) < kbtextmaxlen) + { + if(shift || caps) + { + kbtextstr[strlen(kbtextstr)] = keys[i][j].chShift; + if(shift) shift ^= 1; + } + else + { + kbtextstr[strlen(kbtextstr)] = keys[i][j].ch; + } + } + kbText->SetText(kbtextstr); + keyBtn[i][j]->SetState(STATE_SELECTED, t->chan); + } + } + } + } + + this->ToggleFocus(t); + + if(focus) // only send actions to this window if it's in focus + { + // pad/joystick navigation + if(t->Right()) + this->MoveSelectionHor(1); + else if(t->Left()) + this->MoveSelectionHor(-1); + else if(t->Down()) + this->MoveSelectionVert(1); + else if(t->Up()) + this->MoveSelectionVert(-1); + } +} diff --git a/source/libwiigui/gui_optionbrowser.cpp b/source/libwiigui/gui_optionbrowser.cpp new file mode 100644 index 00000000..487ca019 --- /dev/null +++ b/source/libwiigui/gui_optionbrowser.cpp @@ -0,0 +1,653 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_optionbrowser.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +#include "../wpad.h" + +#include + + +#define GAMESELECTSIZE 30 + +static int scrollbaron, startat, loaded = 0; +/** + * Constructor for the GuiOptionBrowser class. + */ +GuiOptionBrowser::GuiOptionBrowser(int w, int h, OptionList * l, const u8 *imagebg, int scrollon) +{ + width = w; + height = h; + options = l; + scrollbaron = scrollon; + selectable = true; + listOffset = this->FindMenuItem(-1, 1); + selectedItem = 0; + focus = 1; // allow focus + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trigHeldA = new GuiTrigger; + trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A); + + btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM); + + bgOptions = new GuiImageData(imagebg); + bgOptionsImg = new GuiImage(bgOptions); + bgOptionsImg->SetParent(this); + bgOptionsImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + + bgOptionsEntry = new GuiImageData(bg_options_entry_png); + if (scrollbaron == 1) { + scrollbar = new GuiImageData(scrollbar_png); + scrollbarImg = new GuiImage(scrollbar); + scrollbarImg->SetParent(this); + scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarImg->SetPosition(0, 4); + + arrowDown = new GuiImageData(scrollbar_arrowdown_png); + arrowDownImg = new GuiImage(arrowDown); + arrowDownOver = new GuiImageData(scrollbar_arrowdown_png); + arrowDownOverImg = new GuiImage(arrowDownOver); + arrowUp = new GuiImageData(scrollbar_arrowup_png); + arrowUpImg = new GuiImage(arrowUp); + arrowUpOver = new GuiImageData(scrollbar_arrowup_png); + arrowUpOverImg = new GuiImage(arrowUpOver); + scrollbarBox = new GuiImageData(scrollbar_box_png); + scrollbarBoxImg = new GuiImage(scrollbarBox); + scrollbarBoxOver = new GuiImageData(scrollbar_box_png); + scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver); + + arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight()); + arrowUpBtn->SetParent(this); + arrowUpBtn->SetImage(arrowUpImg); + arrowUpBtn->SetImageOver(arrowUpOverImg); + arrowUpBtn->SetImageHold(arrowUpOverImg); + arrowUpBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + arrowUpBtn->SetPosition(width/2-18+7,-18); + arrowUpBtn->SetSelectable(false); + arrowUpBtn->SetTrigger(trigA); + arrowUpBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowUpBtn->SetSoundClick(btnSoundClick); + + arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight()); + arrowDownBtn->SetParent(this); + arrowDownBtn->SetImage(arrowDownImg); + arrowDownBtn->SetImageOver(arrowDownOverImg); + arrowDownBtn->SetImageHold(arrowDownOverImg); + arrowDownBtn->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + arrowDownBtn->SetPosition(width/2-18+7,18); + arrowDownBtn->SetSelectable(false); + arrowDownBtn->SetTrigger(trigA); + arrowDownBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowDownBtn->SetSoundClick(btnSoundClick); + + scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight()); + scrollbarBoxBtn->SetParent(this); + scrollbarBoxBtn->SetImage(scrollbarBoxImg); + scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg); + scrollbarBoxBtn->SetImageHold(scrollbarBoxOverImg); + scrollbarBoxBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + scrollbarBoxBtn->SetSelectable(false); + scrollbarBoxBtn->SetEffectOnOver(EFFECT_SCALE, 50, 120); + scrollbarBoxBtn->SetMinY(0); + scrollbarBoxBtn->SetMaxY(height); + scrollbarBoxBtn->SetHoldable(true); + scrollbarBoxBtn->SetTrigger(trigHeldA); + } + +// optionBg = new GuiImage(bgOptionsEntry); + for(int i=0; iname[i], 20, (GXColor){0, 0, 0, 0xff}); + optionTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionTxt[i]->SetPosition(24,0); + + optionBg[i] = new GuiImage(bgOptionsEntry); + + optionVal[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); + optionVal[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionVal[i]->SetPosition(250,0); + + optionBtn[i] = new GuiButton(width-28,GAMESELECTSIZE); + optionBtn[i]->SetParent(this); + optionBtn[i]->SetLabel(optionTxt[i], 0); + optionBtn[i]->SetLabel(optionVal[i], 1); + optionBtn[i]->SetImageOver(optionBg[i]); + optionBtn[i]->SetPosition(5,GAMESELECTSIZE*i+4); + optionBtn[i]->SetRumble(false); + optionBtn[i]->SetTrigger(trigA); + optionBtn[i]->SetSoundClick(btnSoundClick); + } +} + +/** + * Constructor for the GuiOptionBrowser class. + */ +GuiOptionBrowser::GuiOptionBrowser(int w, int h, OptionList * l, const char *themePath, const u8 *imagebg, int scrollon, int start) +{ + width = w; + height = h; + options = l; + startat = start; + loaded = 0; + scrollbaron = scrollon; + selectable = true; + listOffset = this->FindMenuItem(-1, 1); + selectedItem = 0; + focus = 1; // allow focus + char imgPath[100]; + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trigHeldA = new GuiTrigger; + trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A); + btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM); + + snprintf(imgPath, sizeof(imgPath), "%sbg_options.png", themePath); + bgOptions = new GuiImageData(imgPath, imagebg); + + bgOptionsImg = new GuiImage(bgOptions); + bgOptionsImg->SetParent(this); + bgOptionsImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + + snprintf(imgPath, sizeof(imgPath), "%sbg_options_entry.png", themePath); + bgOptionsEntry = new GuiImageData(imgPath, bg_options_entry_png); + if (scrollbaron == 1) { + snprintf(imgPath, sizeof(imgPath), "%sscrollbar.png", themePath); + scrollbar = new GuiImageData(imgPath, scrollbar_png); + scrollbarImg = new GuiImage(scrollbar); + scrollbarImg->SetParent(this); + scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarImg->SetPosition(0, 4); + + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_arrowdown.png", themePath); + arrowDown = new GuiImageData(imgPath, scrollbar_arrowdown_png); + arrowDownImg = new GuiImage(arrowDown); + arrowDownOver = new GuiImageData(imgPath, scrollbar_arrowdown_png); + arrowDownOverImg = new GuiImage(arrowDownOver); + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_arrowup.png", themePath); + arrowUp = new GuiImageData(imgPath, scrollbar_arrowup_png); + arrowUpImg = new GuiImage(arrowUp); + arrowUpOver = new GuiImageData(imgPath, scrollbar_arrowup_png); + arrowUpOverImg = new GuiImage(arrowUpOver); + snprintf(imgPath, sizeof(imgPath), "%sscrollbar_box.png", themePath); + scrollbarBox = new GuiImageData(imgPath, scrollbar_box_png); + scrollbarBoxImg = new GuiImage(scrollbarBox); + scrollbarBoxOver = new GuiImageData(imgPath, scrollbar_box_png); + scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver); + + arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight()); + arrowUpBtn->SetParent(this); + arrowUpBtn->SetImage(arrowUpImg); + arrowUpBtn->SetImageOver(arrowUpOverImg); + arrowUpBtn->SetImageHold(arrowUpOverImg); + arrowUpBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + arrowUpBtn->SetPosition(width/2-18+7,-18); + arrowUpBtn->SetSelectable(false); + arrowUpBtn->SetTrigger(trigA); + arrowUpBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowUpBtn->SetSoundClick(btnSoundClick); + + arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight()); + arrowDownBtn->SetParent(this); + arrowDownBtn->SetImage(arrowDownImg); + arrowDownBtn->SetImageOver(arrowDownOverImg); + arrowDownBtn->SetImageHold(arrowDownOverImg); + arrowDownBtn->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + arrowDownBtn->SetPosition(width/2-18+7,18); + arrowDownBtn->SetSelectable(false); + arrowDownBtn->SetTrigger(trigA); + arrowDownBtn->SetEffectOnOver(EFFECT_SCALE, 50, 130); + arrowDownBtn->SetSoundClick(btnSoundClick); + + scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight()); + scrollbarBoxBtn->SetParent(this); + scrollbarBoxBtn->SetImage(scrollbarBoxImg); + scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg); + scrollbarBoxBtn->SetImageHold(scrollbarBoxOverImg); + scrollbarBoxBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + scrollbarBoxBtn->SetSelectable(false); + scrollbarBoxBtn->SetEffectOnOver(EFFECT_SCALE, 50, 120); + scrollbarBoxBtn->SetMinY(0); + scrollbarBoxBtn->SetMaxY(height-30); + scrollbarBoxBtn->SetHoldable(true); + scrollbarBoxBtn->SetTrigger(trigHeldA); + } + +// optionBg = new GuiImage(bgOptionsEntry); + for(int i=0; iname[i], 20, (GXColor){0, 0, 0, 0xff}); + optionTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionTxt[i]->SetPosition(24,0); + + optionBg[i] = new GuiImage(bgOptionsEntry); + + optionVal[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); + optionVal[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionVal[i]->SetPosition(250,0); + + optionBtn[i] = new GuiButton(width-28,GAMESELECTSIZE); + optionBtn[i]->SetParent(this); + optionBtn[i]->SetLabel(optionTxt[i], 0); + optionBtn[i]->SetLabel(optionVal[i], 1); + optionBtn[i]->SetImageOver(optionBg[i]); + optionBtn[i]->SetPosition(5,GAMESELECTSIZE*i+4); + optionBtn[i]->SetTrigger(trigA); + optionBtn[i]->SetSoundClick(btnSoundClick); + } +} + +/** + * Destructor for the GuiOptionBrowser class. + */ +GuiOptionBrowser::~GuiOptionBrowser() +{ + if (scrollbaron == 1) { + delete arrowUpBtn; + delete arrowDownBtn; + delete scrollbarBoxBtn; + delete scrollbarImg; + delete arrowDownImg; + delete arrowDownOverImg; + delete arrowUpImg; + delete arrowUpOverImg; + delete scrollbarBoxImg; + delete scrollbarBoxOverImg; + delete scrollbar; + delete arrowDown; + delete arrowDownOver; + delete arrowUp; + delete arrowUpOver; + delete scrollbarBox; + delete scrollbarBoxOver; + } + delete bgOptionsImg; + delete bgOptions; + delete bgOptionsEntry; + loaded = 0; + + delete trigA; + delete btnSoundClick; + +// delete optionBg; + for(int i=0; iSetPosition(x,0); +} + +void GuiOptionBrowser::SetFocus(int f) +{ + focus = f; + + for(int i=0; iResetState(); + + if(f == 1) + optionBtn[selectedItem]->SetState(STATE_SELECTED); +} + +void GuiOptionBrowser::ResetState() +{ + if(state != STATE_DISABLED) + { + state = STATE_DEFAULT; + stateChan = -1; + } + + for(int i=0; iResetState(); + } +} + +int GuiOptionBrowser::GetClickedOption() +{ + int found = -1; + for(int i=0; iGetState() == STATE_CLICKED) + { + optionBtn[i]->SetState(STATE_SELECTED); + found = optionIndex[i]; + break; + } + } + return found; +} + +int GuiOptionBrowser::GetSelectedOption() +{ + int found = -1; + for(int i=0; iGetState() == STATE_SELECTED) + { + optionBtn[i]->SetState(STATE_SELECTED); + found = optionIndex[i]; + break; + } + } + return found; +} + +/**************************************************************************** + * FindMenuItem + * + * Help function to find the next visible menu item on the list + ***************************************************************************/ + +int GuiOptionBrowser::FindMenuItem(int currentItem, int direction) +{ + int nextItem = currentItem + direction; + + if(nextItem < 0 || nextItem >= options->length) + return -1; + + if(strlen(options->name[nextItem]) > 0) + return nextItem; + else + return FindMenuItem(nextItem, direction); +} + +/** + * Draw the button on screen + */ +void GuiOptionBrowser::Draw() +{ + if(!this->IsVisible()) + return; + + bgOptionsImg->Draw(); + + int next = listOffset; + + for(int i=0; i= 0) + { + optionBtn[i]->Draw(); + next = this->FindMenuItem(next, 1); + } + else + break; + } + + if(scrollbaron == 1) { + scrollbarImg->Draw(); + arrowUpBtn->Draw(); + arrowDownBtn->Draw(); + scrollbarBoxBtn->Draw(); + } + this->UpdateEffects(); +} + +void GuiOptionBrowser::Update(GuiTrigger * t) +{ int next, prev, lang = options->length; + + //go to the last game selected + if ((loaded == 0) && (startat>0)) + { + + if (startat > (lang-9)){ + listOffset= (lang-9); + selectedItem=startat; + optionBtn[selectedItem]->SetState(STATE_SELECTED, t->chan); + } + else if (startat < 9){ + selectedItem=startat; + optionBtn[selectedItem]->SetState(STATE_SELECTED, t->chan); + } + else { + listOffset = (startat-4); + selectedItem=startat; + optionBtn[selectedItem]->SetState(STATE_SELECTED, t->chan);} + this->SetFocus(1); + loaded = 1; + } + + if(state == STATE_DISABLED || !t) + return; + + + // scrolldelay affects how fast the list scrolls + // when the arrows are clicked + float scrolldelay = 3.5; + + + if (scrollbaron == 1) { + // update the location of the scroll box based on the position in the option list + + + arrowUpBtn->Update(t); + arrowDownBtn->Update(t); + scrollbarBoxBtn->Update(t); + } + next = listOffset; + + for(int i=0; i= 0) + { + if(optionBtn[i]->GetState() == STATE_DISABLED) + { + optionBtn[i]->SetVisible(true); + optionBtn[i]->SetState(STATE_DEFAULT); + } + + optionTxt[i]->SetText(options->name[next]); + optionVal[i]->SetText(options->value[next]); + optionIndex[i] = next; + next = this->FindMenuItem(next, 1); + } + else + { + optionBtn[i]->SetVisible(false); + optionBtn[i]->SetState(STATE_DISABLED); + } + + if(focus) + { + if(i != selectedItem && optionBtn[i]->GetState() == STATE_SELECTED) + optionBtn[i]->ResetState(); + else if(i == selectedItem && optionBtn[i]->GetState() == STATE_DEFAULT) + optionBtn[selectedItem]->SetState(STATE_SELECTED, t->chan); + } + + optionBtn[i]->Update(t); + + if(optionBtn[i]->GetState() == STATE_SELECTED) + { + selectedItem = i; + } + } + + // pad/joystick navigation + if(!focus) + return; // skip navigation + + if (scrollbaron == 1) { + + if (t->Down() || + arrowDownBtn->GetState() == STATE_CLICKED || ////////////////////////////////////////////down + arrowDownBtn->GetState() == STATE_HELD) + { + + next = this->FindMenuItem(optionIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == PAGESIZE-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + } + else if(optionBtn[selectedItem+1]->IsVisible()) + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem++; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + }WPAD_ScanPads(); + u8 cnt, buttons = NULL; + /* Get pressed buttons */ + for (cnt = 0; cnt < 4; cnt++) + buttons |= WPAD_ButtonsHeld(cnt); + if (buttons == WPAD_BUTTON_A) { + + } else { + arrowDownBtn->ResetState(); + + } + + } + else if(t->Up() || + arrowUpBtn->GetState() == STATE_CLICKED || ////////////////////////////////////////////up + arrowUpBtn->GetState() == STATE_HELD) + { + prev = this->FindMenuItem(optionIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + } + else + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + selectedItem--; + } + scrollbarBoxBtn->Draw(); + usleep(10000 * scrolldelay); + + + }WPAD_ScanPads(); + u8 cnt, buttons = NULL; + /* Get pressed buttons */ + for (cnt = 0; cnt < 4; cnt++) + buttons |= WPAD_ButtonsHeld(cnt); + if (buttons == WPAD_BUTTON_A) { + + } else { + arrowUpBtn->ResetState(); + + } + } + + if(scrollbarBoxBtn->GetState() == STATE_HELD && + scrollbarBoxBtn->GetStateChan() == t->chan && + t->wpad.ir.valid && options->length > PAGESIZE) + { + scrollbarBoxBtn->SetPosition(width/2-18+7,0); + int position = t->wpad.ir.y - 50 - scrollbarBoxBtn->GetTop(); + + listOffset = (position * lang)/180 - selectedItem; + + if(listOffset <= 0) + { + listOffset = 0; + selectedItem = 0; + } + else if(listOffset+PAGESIZE >= lang) + { + listOffset = lang-PAGESIZE; + selectedItem = PAGESIZE-1; + } + + } + int positionbar = 237*(listOffset + selectedItem) / lang; + + if(positionbar > 216) + positionbar = 216; + scrollbarBoxBtn->SetPosition(width/2-18+7, positionbar+8); + + + if(t->Right()) + { + if(listOffset < lang && lang > PAGESIZE) + { + listOffset =listOffset+ PAGESIZE; + if(listOffset+PAGESIZE >= lang) + listOffset = lang-PAGESIZE; + } + } + else if(t->Left()) + { + if(listOffset > 0) + { + listOffset =listOffset- PAGESIZE; + if(listOffset < 0) + listOffset = 0; + } + } + + } else { + + + if(t->Down()) + { + next = this->FindMenuItem(optionIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == PAGESIZE-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + } + else if(optionBtn[selectedItem+1]->IsVisible()) + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem++; + } + } + } + else if(t->Up()) + { + prev = this->FindMenuItem(optionIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + } + else + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + selectedItem--; + } + } + } + } + + if(updateCB) + updateCB(this); +} diff --git a/source/libwiigui/gui_sound.cpp b/source/libwiigui/gui_sound.cpp new file mode 100644 index 00000000..3db3bf8c --- /dev/null +++ b/source/libwiigui/gui_sound.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_sound.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +/** + * Constructor for the GuiSound class. + */ +GuiSound::GuiSound(const u8 * snd, s32 len, int t) +{ + sound = snd; + length = len; + type = t; + voice = -1; + volume = 100; + loop = false; +} + +GuiSound::GuiSound(const u8 * snd, s32 len, int t, int v) +{ + sound = snd; + length = len; + type = t; + voice = -1; + volume = v; + loop = false; +} + +/** + * Destructor for the GuiSound class. + */ +GuiSound::~GuiSound() +{ + if(type == SOUND_OGG) + StopOgg(); +} + +void GuiSound::Play() +{ + int vol; + + switch(type) + { + case SOUND_PCM: + vol = 255*(volume/100.0); + voice = ASND_GetFirstUnusedVoice(); + if(voice >= 0) + ASND_SetVoice(voice, VOICE_STEREO_16BIT, 48000, 0, + (u8 *)sound, length, vol, vol, NULL); + break; + + case SOUND_OGG: + voice = 0; + if(loop) + PlayOgg(mem_open((char *)sound, length), 0, OGG_INFINITE_TIME); + else + PlayOgg(mem_open((char *)sound, length), 0, OGG_ONE_TIME); + SetVolumeOgg(255*(volume/100.0)); + break; + } +} + +void GuiSound::Stop() +{ + if(voice < 0) + return; + + switch(type) + { + case SOUND_PCM: + ASND_StopVoice(voice); + break; + + case SOUND_OGG: + StopOgg(); + break; + } +} + +void GuiSound::Pause() +{ + if(voice < 0) + return; + + switch(type) + { + case SOUND_PCM: + ASND_PauseVoice(voice, 1); + break; + + case SOUND_OGG: + PauseOgg(1); + break; + } +} + +void GuiSound::Resume() +{ + if(voice < 0) + return; + + switch(type) + { + case SOUND_PCM: + ASND_PauseVoice(voice, 0); + break; + + case SOUND_OGG: + PauseOgg(0); + break; + } +} + +bool GuiSound::IsPlaying() +{ + if(ASND_StatusVoice(voice) == SND_WORKING || ASND_StatusVoice(voice) == SND_WAITING) + return true; + else + return false; +} + +void GuiSound::SetVolume(int vol) +{ + volume = vol; + + if(voice < 0) + return; + + int newvol = 255*(volume/100.0); + + switch(type) + { + case SOUND_PCM: + ASND_ChangeVolumeVoice(voice, newvol, newvol); + break; + + case SOUND_OGG: + SetVolumeOgg(255*(volume/100.0)); + break; + } +} + +void GuiSound::SetLoop(bool l) +{ + loop = l; +} diff --git a/source/libwiigui/gui_text.cpp b/source/libwiigui/gui_text.cpp new file mode 100644 index 00000000..f3254a36 --- /dev/null +++ b/source/libwiigui/gui_text.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_text.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +static int currentSize = 0; +static int presetSize = 0; +static int presetMaxWidth = 0; +static int presetAlignmentHor = 0; +static int presetAlignmentVert = 0; +static u16 presetStyle = 0; +static GXColor presetColor = (GXColor){255, 255, 255, 255}; + +/** + * Constructor for the GuiText class. + */ +GuiText::GuiText(const char * t, int s, GXColor c) +{ + text = NULL; + size = s; + color = c; + alpha = c.a; + style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE; + maxWidth = 0; + + alignmentHor = ALIGN_CENTRE; + alignmentVert = ALIGN_MIDDLE; + + if(t) + text = fontSystem->charToWideChar((char *)t); +} + +/** + * Constructor for the GuiText class, uses presets + */ +GuiText::GuiText(const char * t) +{ + text = NULL; + size = presetSize; + color = presetColor; + alpha = presetColor.a; + style = presetStyle; + maxWidth = presetMaxWidth; + + alignmentHor = presetAlignmentHor; + alignmentVert = presetAlignmentVert; + + if(t) + text = fontSystem->charToWideChar((char *)t); +} + +/** + * Destructor for the GuiText class. + */ +GuiText::~GuiText() +{ + if(text) + { + delete text; + text = NULL; + } +} + +void GuiText::SetText(const char * t) +{ + if(text) + delete text; + + text = NULL; + + if(t) + text = fontSystem->charToWideChar((char *)t); +} + +void GuiText::SetPresets(int sz, GXColor c, int w, u16 s, int h, int v) +{ + presetSize = sz; + presetColor = c; + presetStyle = s; + presetMaxWidth = w; + presetAlignmentHor = h; + presetAlignmentVert = v; +} + +void GuiText::SetFontSize(int s) +{ + size = s; +} + +void GuiText::SetMaxWidth(int w) +{ + maxWidth = w; +} + +void GuiText::SetColor(GXColor c) +{ + color = c; + alpha = c.a; +} + +void GuiText::SetStyle(u16 s) +{ + style = s; +} + +void GuiText::SetAlignment(int hor, int vert) +{ + style = 0; + + switch(hor) + { + case ALIGN_LEFT: + style |= FTGX_JUSTIFY_LEFT; + break; + case ALIGN_RIGHT: + style |= FTGX_JUSTIFY_RIGHT; + break; + default: + style |= FTGX_JUSTIFY_CENTER; + break; + } + switch(vert) + { + case ALIGN_TOP: + style |= FTGX_ALIGN_TOP; + break; + case ALIGN_BOTTOM: + style |= FTGX_ALIGN_BOTTOM; + break; + default: + style |= FTGX_ALIGN_MIDDLE; + break; + } + + alignmentHor = hor; + alignmentVert = vert; +} + +/** + * Draw the text on screen + */ +void GuiText::Draw() +{ + if(!text) + return; + + if(!this->IsVisible()) + return; + + GXColor c = color; + c.a = this->GetAlpha(); + + int newSize = size*this->GetScale(); + + if(newSize != currentSize) + { + fontSystem->changeSize(newSize); + currentSize = newSize; + } + + int voffset = 0; + + if(alignmentVert == ALIGN_MIDDLE) + voffset = -newSize/2 + 2; + + if(maxWidth > 0) // text wrapping + { + int lineheight = newSize + 6; + int strlen = wcslen(text); + int i = 0; + int ch = 0; + int linenum = 0; + int lastSpace = -1; + int lastSpaceIndex = -1; + wchar_t * tmptext[20]; + + while(ch < strlen) + { + if(i == 0) + tmptext[linenum] = new wchar_t[strlen + 1]; + + tmptext[linenum][i] = text[ch]; + tmptext[linenum][i+1] = 0; + + if(text[ch] == ' ' || ch == strlen-1) + { + if(fontSystem->getWidth(tmptext[linenum]) >= maxWidth) + { + if(lastSpace >= 0) + { + tmptext[linenum][lastSpaceIndex] = 0; // discard space, and everything after + ch = lastSpace; // go backwards to the last space + lastSpace = -1; // we have used this space + lastSpaceIndex = -1; + } + linenum++; + i = -1; + } + else if(ch == strlen-1) + { + linenum++; + } + } + if(text[ch] == ' ' && i >= 0) + { + lastSpace = ch; + lastSpaceIndex = i; + } + ch++; + i++; + } + + if(alignmentVert == ALIGN_MIDDLE) + voffset = voffset - (lineheight*linenum)/2 + lineheight/2; + + for(i=0; i < linenum; i++) + { + fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, tmptext[i], c, style); + delete tmptext[i]; + } + } + else + { + fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style); + } + this->UpdateEffects(); +} diff --git a/source/libwiigui/gui_trigger.cpp b/source/libwiigui/gui_trigger.cpp new file mode 100644 index 00000000..fe7a4f45 --- /dev/null +++ b/source/libwiigui/gui_trigger.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_trigger.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +static int scrollDelay = 0; + +/** + * Constructor for the GuiTrigger class. + */ +GuiTrigger::GuiTrigger() +{ + chan = -1; + memset(&wpad, 0, sizeof(WPADData)); + memset(&pad, 0, sizeof(PADData)); +} + +/** + * Destructor for the GuiTrigger class. + */ +GuiTrigger::~GuiTrigger() +{ +} + +/** + * Sets a simple trigger. Requires: + * - Element is selected + * - Trigger button is pressed + */ +void GuiTrigger::SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_SIMPLE; + chan = ch; + wpad.btns_d = wiibtns; + pad.btns_d = gcbtns; +} + +/** + * Sets a held trigger. Requires: + * - Element is selected + * - Trigger button is pressed and held + */ +void GuiTrigger::SetHeldTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_HELD; + chan = ch; + wpad.btns_h = wiibtns; + pad.btns_h = gcbtns; +} + +/** + * Sets a button trigger. Requires: + * - Trigger button is pressed + */ +void GuiTrigger::SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_BUTTON_ONLY; + chan = ch; + wpad.btns_d = wiibtns; + pad.btns_d = gcbtns; +} + +/** + * Sets a button trigger. Requires: + * - Trigger button is pressed + * - Parent window is in focus + */ +void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_BUTTON_ONLY_IN_FOCUS; + chan = ch; + wpad.btns_d = wiibtns; + pad.btns_d = gcbtns; +} + +/**************************************************************************** + * WPAD_Stick + * + * Get X/Y value from Wii Joystick (classic, nunchuk) input + ***************************************************************************/ + +s8 GuiTrigger::WPAD_Stick(u8 right, int axis) +{ + #ifdef HW_RVL + + float mag = 0.0; + float ang = 0.0; + + switch (wpad.exp.type) + { + case WPAD_EXP_NUNCHUK: + case WPAD_EXP_GUITARHERO3: + if (right == 0) + { + mag = wpad.exp.nunchuk.js.mag; + ang = wpad.exp.nunchuk.js.ang; + } + break; + + case WPAD_EXP_CLASSIC: + if (right == 0) + { + mag = wpad.exp.classic.ljs.mag; + ang = wpad.exp.classic.ljs.ang; + } + else + { + mag = wpad.exp.classic.rjs.mag; + ang = wpad.exp.classic.rjs.ang; + } + break; + + default: + break; + } + + /* calculate x/y value (angle need to be converted into radian) */ + if (mag > 1.0) mag = 1.0; + else if (mag < -1.0) mag = -1.0; + double val; + + if(axis == 0) // x-axis + val = mag * sin((PI * ang)/180.0f); + else // y-axis + val = mag * cos((PI * ang)/180.0f); + + return (s8)(val * 128.0f); + + #else + return 0; + #endif +} + +bool GuiTrigger::Left() +{ + u32 wiibtn = WPAD_BUTTON_LEFT; + + if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_LEFT + || pad.stickX < -PADCAL + || WPAD_Stick(0,0) < -PADCAL) + { + if(wpad.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) + || pad.btns_d & PAD_BUTTON_LEFT) + { + scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + return true; + } + else if(scrollDelay == 0) + { + scrollDelay = SCROLL_LOOP_DELAY; + return true; + } + else + { + if(scrollDelay > 0) + scrollDelay--; + } + } + return false; +} + +bool GuiTrigger::Right() +{ + u32 wiibtn = WPAD_BUTTON_RIGHT; + + if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_RIGHT + || pad.stickX > PADCAL + || WPAD_Stick(0,0) > PADCAL) + { + if(wpad.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT) + || pad.btns_d & PAD_BUTTON_RIGHT) + { + scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + return true; + } + else if(scrollDelay == 0) + { + scrollDelay = SCROLL_LOOP_DELAY; + return true; + } + else + { + if(scrollDelay > 0) + scrollDelay--; + } + } + return false; +} + +bool GuiTrigger::Up() +{ + u32 wiibtn = WPAD_BUTTON_UP; + + if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_UP + || pad.stickY > PADCAL + || WPAD_Stick(0,1) > PADCAL) + { + if(wpad.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_UP) + || pad.btns_d & PAD_BUTTON_UP) + { + scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + return true; + } + else if(scrollDelay == 0) + { + scrollDelay = SCROLL_LOOP_DELAY; + return true; + } + else + { + if(scrollDelay > 0) + scrollDelay--; + } + } + return false; +} + +bool GuiTrigger::Down() +{ + u32 wiibtn = WPAD_BUTTON_DOWN; + + if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_DOWN + || pad.stickY < -PADCAL + || WPAD_Stick(0,1) < -PADCAL) + { + if(wpad.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN) + || pad.btns_d & PAD_BUTTON_DOWN) + { + scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + return true; + } + else if(scrollDelay == 0) + { + scrollDelay = SCROLL_LOOP_DELAY; + return true; + } + else + { + if(scrollDelay > 0) + scrollDelay--; + } + } + return false; +} diff --git a/source/libwiigui/gui_window.cpp b/source/libwiigui/gui_window.cpp new file mode 100644 index 00000000..b8abea49 --- /dev/null +++ b/source/libwiigui/gui_window.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_window.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +GuiWindow::GuiWindow() +{ + width = 0; + height = 0; + focus = 0; // allow focus +} + +GuiWindow::GuiWindow(int w, int h) +{ + width = w; + height = h; + focus = 0; // allow focus +} + +GuiWindow::~GuiWindow() +{ +} + +void GuiWindow::Append(GuiElement* e) +{ + if (e == NULL) + return; + + Remove(e); + _elements.push_back(e); + e->SetParent(this); +} + +void GuiWindow::Insert(GuiElement* e, u32 index) +{ + if (e == NULL || index > (_elements.size() - 1)) + return; + + Remove(e); + _elements.insert(_elements.begin()+index, e); + e->SetParent(this); +} + +void GuiWindow::Remove(GuiElement* e) +{ + if (e == NULL) + return; + + for (u8 i = 0; i < _elements.size(); i++) + { + if(e == _elements.at(i)) + { + _elements.erase(_elements.begin()+i); + break; + } + } +} + +void GuiWindow::RemoveAll() +{ + _elements.clear(); +} + +GuiElement* GuiWindow::GetGuiElementAt(u32 index) const +{ + if (index >= _elements.size()) + return NULL; + return _elements.at(index); +} + +u32 GuiWindow::GetSize() +{ + return _elements.size(); +} + +void GuiWindow::Draw() +{ + if(_elements.size() == 0 || !this->IsVisible()) + return; + + for (u8 i = 0; i < _elements.size(); i++) + { + try { _elements.at(i)->Draw(); } + catch (const std::exception& e) { } + } + + this->UpdateEffects(); + + if(parentElement && state == STATE_DISABLED) + //Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1); + Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, 0x70},1); +} + +void GuiWindow::ResetState() +{ + if(state != STATE_DISABLED) + state = STATE_DEFAULT; + + for (u8 i = 0; i < _elements.size(); i++) + { + try { _elements.at(i)->ResetState(); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::SetState(int s) +{ + state = s; + + for (u8 i = 0; i < _elements.size(); i++) + { + try { _elements.at(i)->SetState(s); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::SetVisible(bool v) +{ + visible = v; + + for (u8 i = 0; i < _elements.size(); i++) + { + try { _elements.at(i)->SetVisible(v); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::SetFocus(int f) +{ + focus = f; + + if(f == 1) + this->MoveSelectionVert(1); + else + this->ResetState(); +} + +void GuiWindow::ChangeFocus(GuiElement* e) +{ + if(parentElement) + return; // this is only intended for the main window + + for (u8 i = 0; i < _elements.size(); i++) + { + if(e == _elements.at(i)) + _elements.at(i)->SetFocus(1); + else if(_elements.at(i)->IsFocused() == 1) + _elements.at(i)->SetFocus(0); + } +} + +void GuiWindow::ToggleFocus(GuiTrigger * t) +{ + if(parentElement) + return; // this is only intended for the main window + + int found = -1; + int newfocus = -1; + u8 i; + + // look for currently in focus element + for (i = 0; i < _elements.size(); i++) + { + try + { + if(_elements.at(i)->IsFocused() == 1) + { + found = i; + break; + } + } + catch (const std::exception& e) { } + } + + // element with focus not found, try to give focus + if(found == -1) + { + for (i = 0; i < _elements.size(); i++) + { + try + { + if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set) + { + _elements.at(i)->SetFocus(1); // give this element focus + break; + } + } + catch (const std::exception& e) { } + } + } + // change focus + else if(t->wpad.btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_1 | WPAD_CLASSIC_BUTTON_PLUS) + || t->pad.btns_d & PAD_BUTTON_B) + { + for (i = found; i < _elements.size(); i++) + { + try + { + if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set) + { + newfocus = i; + _elements.at(i)->SetFocus(1); // give this element focus + _elements.at(found)->SetFocus(0); // disable focus on other element + break; + } + } + catch (const std::exception& e) { } + } + + if(newfocus == -1) + { + for (i = 0; i < found; i++) + { + try + { + if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set) + { + _elements.at(i)->SetFocus(1); // give this element focus + _elements.at(found)->SetFocus(0); // disable focus on other element + break; + } + } + catch (const std::exception& e) { } + } + } + } +} + +int GuiWindow::GetSelected() +{ + // find selected element + int found = -1; + for (u8 i = 0; i < _elements.size(); i++) + { + try + { + if(_elements.at(i)->GetState() == STATE_SELECTED) + { + found = i; + break; + } + } + catch (const std::exception& e) { } + } + return found; +} + +// set element to left/right as selected +// there's probably a more clever way to do this, but this way works +void GuiWindow::MoveSelectionHor(int dir) +{ + int found = -1; + u16 left = 0; + u16 top = 0; + u8 i = 0; + + int selected = this->GetSelected(); + + if(selected >= 0) + { + left = _elements.at(selected)->GetLeft(); + top = _elements.at(selected)->GetTop(); + } + + // look for a button on the same row, to the left/right + for (i = 0; i < _elements.size(); i++) + { + try + { + if(_elements.at(i)->IsSelectable()) + { + if(_elements.at(i)->GetLeft()*dir > left*dir && _elements.at(i)->GetTop() == top) + { + if(found == -1) + found = i; + else if(_elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir) + found = i; // this is a better match + } + } + } + catch (const std::exception& e) { } + } + if(found >= 0) + goto matchfound; + + // match still not found, let's try the first button in the next row + for (i = 0; i < _elements.size(); i++) + { + try + { + if(_elements.at(i)->IsSelectable()) + { + if(_elements.at(i)->GetTop()*dir > top*dir) + { + if(found == -1) + found = i; + else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir) + found = i; // this is a better match + else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir + && + _elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir) + found = i; // this is a better match + } + } + } + catch (const std::exception& e) { } + } + + // match found + matchfound: + if(found >= 0) + { + _elements.at(found)->SetState(STATE_SELECTED); + if(selected >= 0) + _elements.at(selected)->ResetState(); + } +} + +void GuiWindow::MoveSelectionVert(int dir) +{ + int found = -1; + u16 left = 0; + u16 top = 0; + u8 i = 0; + + int selected = this->GetSelected(); + + if(selected >= 0) + { + left = _elements.at(selected)->GetLeft(); + top = _elements.at(selected)->GetTop(); + } + + // look for a button above/below, with the least horizontal difference + for (i = 0; i < _elements.size(); i++) + { + try + { + if(_elements.at(i)->IsSelectable()) + { + if(_elements.at(i)->GetTop()*dir > top*dir) + { + if(found == -1) + found = i; + else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir) + found = i; // this is a better match + else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir + && + abs(_elements.at(i)->GetLeft() - left) < + abs(_elements.at(found)->GetLeft() - left)) + found = i; + } + } + } + catch (const std::exception& e) { } + } + if(found >= 0) + goto matchfound; + + // match found + matchfound: + if(found >= 0) + { + _elements.at(found)->SetState(STATE_SELECTED); + if(selected >= 0) + _elements.at(selected)->ResetState(); + } +} + +void GuiWindow::Update(GuiTrigger * t) +{ + if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) + return; + + for (u8 i = 0; i < _elements.size(); i++) + { + try { _elements.at(i)->Update(t); } + catch (const std::exception& e) { } + } + + this->ToggleFocus(t); + + if(focus) // only send actions to this window if it's in focus + { + // pad/joystick navigation + if(t->Right()) + this->MoveSelectionHor(1); + else if(t->Left()) + this->MoveSelectionHor(-1); + else if(t->Down()) + this->MoveSelectionVert(1); + else if(t->Up()) + this->MoveSelectionVert(-1); + } + + if(updateCB) + updateCB(this); +} diff --git a/source/main.cpp b/source/main.cpp new file mode 100644 index 00000000..c26614a7 --- /dev/null +++ b/source/main.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * demo.cpp + * Basic template/demonstration of libwiigui capabilities. For a + * full-featured app using many more extensions, check out Snes9x GX. + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "FreeTypeGX.h" +#include "video.h" +#include "audio.h" +#include "menu.h" +#include "input.h" +#include "filelist.h" +#include "main.h" +#include "http.h" +#include "dns.h" + +#include "disc.h" +#include "wbfs.h" +#include "sys.h" +#include "video2.h" +#include "wpad.h" +#include "cfg.h" +#include +#include + + +/* Constants */ +#define CONSOLE_XCOORD 260 +#define CONSOLE_YCOORD 115 +#define CONSOLE_WIDTH 340 +#define CONSOLE_HEIGHT 218 + +FreeTypeGX *fontSystem; +int ExitRequested = 0; +bool netcheck = false; + +/*Networking - Forsaekn*/ +int Net_Init(char *ip){ + + s32 res; + while ((res = net_init()) == -EAGAIN) + { + usleep(100 * 1000); //100ms + } + + if (if_config(ip, NULL, NULL, true) < 0) { + printf(" Error reading IP address, exiting"); + usleep(1000 * 1000 * 1); //1 sec + return FALSE; + } + return TRUE; +} + +void ExitApp() +{ + ShutoffRumble(); + StopGX(); + ShutdownAudio(); + //WPAD_Flush(0); + //WPAD_Disconnect(0); + //WPAD_Shutdown(); + //exit(0); +} + +void +DefaultSettings() +{ + Settings.video = discdefault; + Settings.vpatch = off; + Settings.language = ConsoleLangDefault; + Settings.ocarina = off; + Settings.hddinfo = HDDInfo; + Settings.sinfo = ((THEME.showID) ? GameID : Neither); + Settings.rumble = RumbleOn; + if (THEME.showRegion) + { + Settings.sinfo = ((Settings.sinfo == GameID) ? Both : GameRegion); + } + Settings.volume = v80; + Settings.tooltips = TooltipsOn; + snprintf(Settings.unlockCode, sizeof(Settings.unlockCode), "ab121b"); + Settings.parentalcontrol = 0; + Settings.cios = ios249; + + CFG_LoadGlobal(); +} + + +int +main(int argc, char *argv[]) +{ + + s32 ret2; + + __io_wiisd.startup(); + fatMountSimple("SD", &__io_wiisd); + + CFG_Load(argc, argv); + + DefaultSettings(); + + fatUnmount("SD"); + __io_wiisd.shutdown(); + + /* Load Custom IOS */ + if(Settings.cios == ios222) { + ret2 = IOS_ReloadIOS(222); + if (ret2 < 0) { + Settings.cios = ios249; + ret2 = IOS_ReloadIOS(249); + } + } else { + ret2 = IOS_ReloadIOS(249); + } + + if (ret2 < 0) { + printf("ERROR: cIOS could not be loaded!"); + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + } + + Sys_Init(); + //Video_SetMode(); + //Con_Init(CONSOLE_XCOORD, CONSOLE_YCOORD, CONSOLE_WIDTH, CONSOLE_HEIGHT); + //Wpad_Init(); + + PAD_Init(); + InitVideo(); // Initialise video + InitAudio(); // Initialize audio + + + fontSystem = new FreeTypeGX(); + fontSystem->loadFont(font_ttf, font_ttf_size, 0); + fontSystem->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE); + + InitGUIThreads(); + MainMenu(MENU_CHECK); + return 0; +} diff --git a/source/main.h b/source/main.h new file mode 100644 index 00000000..7af49813 --- /dev/null +++ b/source/main.h @@ -0,0 +1,21 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * demo.h + ***************************************************************************/ + +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include "FreeTypeGX.h" + +extern struct SSettings Settings; + +void ExitApp(); +extern int ExitRequested; +extern FreeTypeGX *fontSystem; +extern bool netcheck; +extern int Net_Init(char *ip); + +#endif diff --git a/source/menu.cpp b/source/menu.cpp new file mode 100644 index 00000000..fd39eca4 --- /dev/null +++ b/source/menu.cpp @@ -0,0 +1,4080 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * menu.cpp + * Menu flow routines - handles all menu logic + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //CLOCK +#include //CLOCK +#include + +#include "libwiigui/gui.h" +#include "menu.h" +#include "main.h" +#include "input.h" +#include "http.h" +#include "dns.h" +#include "partition.h" +#include "wbfs.h" +#include "utils.h" +#include "usbstorage.h" +#include "disc.h" +#include "filelist.h" +#include "wdvd.h" +#include "libwbfs/libwbfs.h" +#include "sys.h" +#include "patchcode.h" +#include "wpad.h" +#include "cfg.h" +#include "libwiigui/gui_customoptionbrowser.h" +#include "libwiigui/gui_gamebrowser.h" + +#define MAX_CHARACTERS 38 + +static GuiImage * coverImg = NULL; +static GuiImageData * cover = NULL; + +//char GamesHDD[320][14]; + +static struct discHdr *gameList = NULL; +static GuiImageData * pointer[4]; +static GuiImage * bgImg = NULL; +static GuiButton * btnLogo = NULL; +static GuiImageData * background = NULL; +static char prozent[10] = "0%"; +static char timet[50] = " "; +static GuiText prTxt(prozent, 26, (GXColor){0, 0, 0, 255}); +static GuiText timeTxt(prozent, 26, (GXColor){0, 0, 0, 255}); +static GuiText *GameIDTxt = NULL; +static GuiText *GameRegionTxt = NULL; +static GuiSound * bgMusic = NULL; +static GuiSound * creditsMusic = NULL; +static wbfs_t *hdd = NULL; +static u32 gameCnt = 0; +static s32 gameSelected = 0, gameStart = 0; +static GuiWindow * mainWindow = NULL; +static lwp_t guithread = LWP_THREAD_NULL; +static bool guiHalt = true; +static GuiImageData progressbar(progressbar_png); +static GuiImage progressbarImg(&progressbar); +static double progressDone = 0; +static double progressTotal = 1; +int godmode = 0; +int height = 224; +int width = 160; +static int startat = 0; +static int offset = 0, networkisinitialized = 0; +int vol = Settings.volume; + +//downloadvariables +static char missingFiles[500][12]; //fixed +static int cntMissFiles = 0; + +int direction = 0; // direction the gameprompt slides in + +static char gameregion[7]; +//power button fix +extern u8 shutdown; + + +//Wiilight stuff +static vu32 *_wiilight_reg = (u32*)0xCD0000C0; +void wiilight(int enable){ // Toggle wiilight (thanks Bool for wiilight source) + u32 val = (*_wiilight_reg&~0x20); + if(enable) val |= 0x20; + *_wiilight_reg=val;} + +//Prototypes +int WindowPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label); +static void HaltGui(); +static void ResumeGui(); + + +//libfat helper functions +int isSdInserted() { return __io_wiisd.isInserted(); } + +//Initialise SD CARD +int SDCard_Init() +{ + __io_wiisd.startup(); + if (!isSdInserted()){ + printf("No SD card inserted!"); + return -1; + + } if (!fatMountSimple ("SD", &__io_wiisd)){ + printf("Failed to mount front SD card!"); + return -1; + } + + return 1; +} + +void SDCARD_deInit() +{ + //First unmount all the devs... + fatUnmount ("SD"); + //...and then shutdown em! + __io_wiisd.shutdown(); +} + +bool findfile(const char * filename, const char * path) +{ +DIR *dir; +struct dirent *file; + +dir = opendir(path); + +char temp[11]; +while ((file = readdir(dir))) +{ + snprintf(temp,sizeof(temp),"%s",file->d_name); + if (!strncmpi(temp,filename,11)) + { + //WindowPrompt(path, filename,"go" ,0); + closedir(dir); + return true; + } + } + closedir(dir); + return false; +} + +/**************************************************************************** + * ResumeGui + * + * Signals the GUI thread to start, and resumes the thread. This is called + * after finishing the removal/insertion of new elements, and after initial + * GUI setup. + ***************************************************************************/ +static void +ResumeGui() +{ + guiHalt = false; + LWP_ResumeThread (guithread); +} + +/**************************************************************************** + * HaltGui + * + * Signals the GUI thread to stop, and waits for GUI thread to stop + * This is necessary whenever removing/inserting new elements into the GUI. + * This eliminates the possibility that the GUI is in the middle of accessing + * an element that is being changed. + ***************************************************************************/ +static void +HaltGui() +{ + guiHalt = true; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(guithread)) + usleep(50); +} + +/**************************************************************************** + * WindowCredits + * Display credits + ***************************************************************************/ +static void WindowCredits(void * ptr) +{ + int angle = 0; + + if(btnLogo->GetState() != STATE_CLICKED) { + return; + } + + bgMusic->Stop(); + creditsMusic = new GuiSound(credits_music_ogg, credits_music_ogg_size, SOUND_OGG, 40); + creditsMusic->SetVolume(40); + creditsMusic->SetLoop(1); + creditsMusic->Play(); + + btnLogo->ResetState(); + + bool exit = false; + int i = 0; + int y = 95; + + GuiWindow creditsWindow(screenwidth,screenheight); + GuiWindow creditsWindowBox(580,448); + creditsWindowBox.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiImageData creditsBox(credits_bg_png); + GuiImage creditsBoxImg(&creditsBox); + creditsBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + creditsWindowBox.Append(&creditsBoxImg); + + GuiImageData star(little_star_png); + GuiImage starImg(&star); + starImg.SetWidescreen(CFG.widescreen); //added + starImg.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + starImg.SetPosition(500,335); + + int numEntries = 15; + GuiText * txt[numEntries]; + + txt[i] = new GuiText("Official Site: http://code.google.com/p/usbloader-gui/", 20, (GXColor){255, 255, 255, 255}); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=26; + + txt[i]->SetPresets(22, (GXColor){255, 255, 255, 255}, 0, + FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP); + + txt[i] = new GuiText("Coding:"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(100,y); + i++; + + txt[i] = new GuiText("dimok"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=22; + + txt[i] = new GuiText("nIxx"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=22; + + txt[i] = new GuiText("hungyip84"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=22; + + txt[i] = new GuiText("giantpune"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=24; + + txt[i] = new GuiText("Design:"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(100,y); + i++; + + txt[i] = new GuiText("cyrex"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=22; + + txt[i] = new GuiText("NeoRame"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=22; + + txt[i] = new GuiText("WiiShizza"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=24; + + txt[i] = new GuiText("Ocarina & Vidpatch thanks to:"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(100,y); + i++; + y+=22; + + txt[i] = new GuiText("Fishears & WiiPower"); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); txt[i]->SetPosition(320,y); + i++; + y+=26; + + txt[i] = new GuiText("Special thanks to Tantric for libwiigui"); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); + i++; + y+=22; + + txt[i] = new GuiText("and to Waninkoko & Kwiirk for the USB Loader "); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); + i++; + y+=22; + + txt[i] = new GuiText("and releasing the source code ;)"); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); + i++; + y+=22; + + for(i=0; i < numEntries; i++) + creditsWindowBox.Append(txt[i]); + + + creditsWindow.Append(&creditsWindowBox); + creditsWindow.Append(&starImg); + + while(!exit) + { + creditsWindow.Draw(); + + angle ++; + angle = int(angle) % 360; + usleep(12000); + starImg.SetAngle(angle); + + for(i=3; i >= 0; i--) + { + #ifdef HW_RVL + if(userInput[i].wpad.ir.valid) + Menu_DrawImg(userInput[i].wpad.ir.x-48, userInput[i].wpad.ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad.ir.angle, CFG.widescreen? 0.8 : 1, 1, 255); + if(Settings.rumble == RumbleOn){ + DoRumble(i); + } + #endif + } + + Menu_Render(); + + for(i=0; i < 4; i++) + { + if(userInput[i].wpad.btns_d || userInput[i].pad.btns_d) + exit = true; + } + } + + // clear buttons pressed + for(i=0; i < 4; i++) + { + userInput[i].wpad.btns_d = 0; + userInput[i].pad.btns_d = 0; + } + creditsMusic->Stop(); + for(i=0; i < numEntries; i++) + delete txt[i]; + + delete creditsMusic; + bgMusic->SetLoop(1); + bgMusic->Play(); +} + +/**************************************************************************** + * WiiMenuWindowPrompt + * Display Menu WindowPrompt + ***************************************************************************/ + +int +WiiMenuWindowPrompt(const char *title, const char *btn1Label, const char *btn2Label, const char *btn3Label) +{ + int choice = -1; + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + GuiImageData btnOutline(button_dialogue_box_png); + + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,55); + + GuiText btn1Txt(btn1Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn1.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn1.SetPosition(-50, -120); + btn1.SetImage(&btn1Img); + btn1.SetLabel(&btn1Txt); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnClick); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + GuiText btn2Txt(btn2Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn2.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn2.SetPosition(50, -120); + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetSoundClick(&btnClick); + btn2.SetTrigger(&trigA); + btn2.SetEffectGrow(); + + GuiText btn3Txt(btn3Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn3Img(&btnOutline); + GuiButton btn3(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn3.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn3.SetPosition(0, -65); + btn3.SetLabel(&btn3Txt); + btn3.SetImage(&btn3Img); + btn3.SetSoundOver(&btnSoundOver); + btn3.SetSoundClick(&btnClick); + btn3.SetTrigger(&trigB); + btn3.SetTrigger(&trigA); + btn3.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&btn1); + promptWindow.Append(&btn2); + promptWindow.Append(&btn3); + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + while(choice == -1) + { + VIDEO_WaitVSync(); + if(shutdown == 1) + { + wiilight(0); + Sys_Shutdown(); + } + if(btn1.GetState() == STATE_CLICKED) { + choice = 1; + } + else if(btn2.GetState() == STATE_CLICKED) { + choice = 2; + } + else if(btn3.GetState() == STATE_CLICKED) { + choice = 0; + } + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return choice; +} + +/**************************************************************************** + * WindowPrompt + * + * Displays a prompt window to user, with information, an error message, or + * presenting a user with a choice + ***************************************************************************/ +int +WindowPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label) +{ + int choice = -1; + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + GuiImageData btnOutline(button_dialogue_box_png); + + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,55); + GuiText msgTxt(msg, 22, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-40); + msgTxt.SetMaxWidth(430); + + GuiText btn1Txt(btn1Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + + if(btn2Label) + { + btn1.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn1.SetPosition(40, -45); + } + else + { + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn1.SetPosition(0, -45); + } + + btn1.SetLabel(&btn1Txt); + btn1.SetImage(&btn1Img); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnClick); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + GuiText btn2Txt(btn2Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn2.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn2.SetPosition(-40, -45); + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetSoundClick(&btnClick); + btn2.SetTrigger(&trigB); + btn2.SetTrigger(&trigA); + btn2.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&btn1); + + if(btn2Label) + promptWindow.Append(&btn2); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + while(choice == -1) + { + VIDEO_WaitVSync(); + if(shutdown == 1) + { + wiilight(0); + Sys_Shutdown(); + } + if(btn1.GetState() == STATE_CLICKED) { + choice = 1; + } + else if(btn2.GetState() == STATE_CLICKED) { + choice = 0; + } + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return choice; +} + +/**************************************************************************** + * DownloadWindowPrompt + * Display download + ***************************************************************************/ +int +DownloadWindowPrompt() +{ + int choice = -1; + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + GuiImageData btnOutline(button_dialogue_box_png); + + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt("Cover Download", 26, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,55); + + GuiText btn1Txt("3D Covers", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn1.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn1.SetPosition(-50, -120); + btn1.SetImage(&btn1Img); + btn1.SetLabel(&btn1Txt); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnClick); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + GuiText btn2Txt("Normal Covers", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn2.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn2.SetPosition(50, -120); + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetSoundClick(&btnClick); + btn2.SetTrigger(&trigA); + btn2.SetEffectGrow(); + + GuiText btn3Txt("Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn3Img(&btnOutline); + GuiButton btn3(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn3.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn3.SetPosition(-50, -65); + btn3.SetLabel(&btn3Txt); + btn3.SetImage(&btn3Img); + btn3.SetSoundOver(&btnSoundOver); + btn3.SetSoundClick(&btnClick); + btn3.SetTrigger(&trigB); + btn3.SetTrigger(&trigA); + btn3.SetEffectGrow(); + + GuiText btn4Txt("Disc Images", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn4Img(&btnOutline); + GuiButton btn4(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn4.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn4.SetPosition(50, -65); + btn4.SetLabel(&btn4Txt); + btn4.SetImage(&btn4Img); + btn4.SetSoundOver(&btnSoundOver); + btn4.SetSoundClick(&btnClick); + btn4.SetTrigger(&trigA); + btn4.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&btn1); + promptWindow.Append(&btn2); + promptWindow.Append(&btn3); + promptWindow.Append(&btn4); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + while(choice == -1) + { + VIDEO_WaitVSync(); + if(btn1.GetState() == STATE_CLICKED) { + choice = 2; + } + else if(btn2.GetState() == STATE_CLICKED) { + choice = 1; + } + else if(btn4.GetState() == STATE_CLICKED) { + choice = 3; + } + else if(btn3.GetState() == STATE_CLICKED) { + choice = 0; + } + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return choice; +} + +/**************************************************************************** + * DeviceWait + ***************************************************************************/ +int +DeviceWait(const char *title, const char *msg, const char *btn1Label, const char *btn2Label) +{ + int i = 30; + char timer[20]; + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + + GuiImageData btnOutline(button_dialogue_box_png); + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText timerTxt(timer, 26, (GXColor){0, 0, 0, 255}); + timerTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + timerTxt.SetPosition(0,200); + + GuiText titleTxt(title, 26, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,60); + + GuiText msgTxt(msg, 22, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,0); + msgTxt.SetMaxWidth(430); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&timerTxt); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + s32 ret2; + while(i >= 0) + { + sprintf(timer, "%u s left", i); + timerTxt.SetText(timer); + VIDEO_WaitVSync(); + if(Settings.cios == ios222) { + ret2 = IOS_ReloadIOS(222); + } else { + ret2 = IOS_ReloadIOS(249); + } + sleep(1); + ret2 = WBFS_Init(WBFS_DEVICE_USB); + if(ret2>=0) + break; + + i--; + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return ret2; +} + +/**************************************************************************** + * GameWindowPrompt + * + * Displays a prompt window to user, with information, an error message, or + * presenting a user with a choice + ***************************************************************************/ +int GameWindowPrompt() +{ + int choice = -1, angle = 0; + char sizeText[15]; + f32 size = 0.0; + char ID[4]; + char IDFull[7]; + char gameName[CFG.maxcharacters + 4]; + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + GuiImageData btnOutline(button_dialogue_box_png); + GuiImageData imgLeft(startgame_arrow_left_png); + GuiImageData imgRight(startgame_arrow_right_png); + + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + GuiTrigger trigL; + trigL.SetButtonOnlyTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + GuiTrigger trigR; + trigR.SetButtonOnlyTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + GuiTrigger trigPlus; + trigPlus.SetButtonOnlyTrigger(-1, WPAD_BUTTON_PLUS | WPAD_CLASSIC_BUTTON_PLUS, 0); + GuiTrigger trigMinus; + trigMinus.SetButtonOnlyTrigger(-1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, 0); + + char imgPath[100]; + + if (CFG.widescreen) + snprintf(imgPath, sizeof(imgPath), "%swdialogue_box_startgame.png", CFG.theme_path); + else + snprintf(imgPath, sizeof(imgPath), "%sdialogue_box_startgame.png", CFG.theme_path); + + GuiImageData dialogBox(imgPath, CFG.widescreen ? wdialogue_box_startgame_png : dialogue_box_startgame_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText msgTxt("", 22, (GXColor){50, 50, 50, 255}); + GuiButton nameBtn(120,50); + nameBtn.SetLabel(&msgTxt); + nameBtn.SetLabelOver(&msgTxt); + nameBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + nameBtn.SetPosition(0,-122); + nameBtn.SetSoundOver(&btnSoundOver); + nameBtn.SetSoundClick(&btnClick); + + if (CFG.godmode == 1){ + nameBtn.SetTrigger(&trigA); + nameBtn.SetEffectGrow(); + } + + GuiText sizeTxt("", 22, (GXColor){50, 50, 50, 255}); //TODO: get the size here + sizeTxt.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + sizeTxt.SetPosition(-60,70); + + GuiImage diskImg; + diskImg.SetWidescreen(CFG.widescreen); + diskImg.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + diskImg.SetAngle(angle); + + GuiButton btn1(160, 160); + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + btn1.SetPosition(0, -20); + btn1.SetImage(&diskImg); + + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnClick); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + //btn1.SetEffectGrow(); just commented it out if anybody wants to use it again. + + GuiText btn2Txt("Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + //check if unlocked + if (CFG.godmode == 1) + { + btn2.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn2.SetPosition(40, -40); + } + else + { + btn2.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn2.SetPosition(0, -40); + } + + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetSoundClick(&btnClick); + btn2.SetTrigger(&trigB); + btn2.SetTrigger(&trigA); + btn2.SetEffectGrow(); + + GuiText btn3Txt("Settings", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn3Img(&btnOutline); + GuiButton btn3(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn3.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn3.SetPosition(-50, -40); + btn3.SetLabel(&btn3Txt); + btn3.SetImage(&btn3Img); + btn3.SetSoundOver(&btnSoundOver); + btn3.SetSoundClick(&btnClick); + btn3.SetTrigger(&trigA); + btn3.SetEffectGrow(); + + GuiImage btnLeftImg(&imgLeft); + GuiButton btnLeft(imgLeft.GetWidth(), imgLeft.GetHeight()); + btnLeft.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + btnLeft.SetPosition(20, 0); + btnLeft.SetImage(&btnLeftImg); + btnLeft.SetSoundOver(&btnSoundOver); + btnLeft.SetSoundClick(&btnClick); + btnLeft.SetTrigger(&trigA); + btnLeft.SetTrigger(&trigL); + btnLeft.SetTrigger(&trigMinus); + btnLeft.SetEffectGrow(); + + GuiImage btnRightImg(&imgRight); + GuiButton btnRight(imgRight.GetWidth(), imgRight.GetHeight()); + btnRight.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + btnRight.SetPosition(-20, 0); + btnRight.SetImage(&btnRightImg); + btnRight.SetSoundOver(&btnSoundOver); + btnRight.SetSoundClick(&btnClick); + btnRight.SetTrigger(&trigA); + btnRight.SetTrigger(&trigR); + btnRight.SetTrigger(&trigPlus); + btnRight.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&nameBtn); + promptWindow.Append(&sizeTxt); + promptWindow.Append(&btn1); + promptWindow.Append(&btn2); + promptWindow.Append(&btnLeft); + promptWindow.Append(&btnRight); + + //check if unlocked + if (CFG.godmode == 1) + { + promptWindow.Append(&btn3); + } + + short changed = 3; + GuiImageData * diskCover = NULL; + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + + while (changed) + { + if (changed == 1){ + promptWindow.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_IN, 50); + } + if (changed == 2){ + promptWindow.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_IN, 50); + } + + changed = 0; + + struct discHdr * header = &gameList[gameSelected]; + WBFS_GameSize(header->id, &size); + + snprintf(sizeText, sizeof(sizeText), "%.2fGB", size); //set size text + + snprintf (ID,sizeof(ID),"%c%c%c", header->id[0], header->id[1], header->id[2]); + snprintf (IDFull,sizeof(IDFull),"%c%c%c%c%c%c", header->id[0], header->id[1], header->id[2],header->id[3], header->id[4], header->id[5]); + + //set name + if (strlen(get_title(header)) < (u32)(CFG.maxcharacters + 3)) { + sprintf(gameName, "%s", get_title(header)); + } + else { + strncpy(gameName, get_title(header), CFG.maxcharacters); + gameName[CFG.maxcharacters] = '\0'; + strncat(gameName, "...", 3); + } + + snprintf(imgPath,sizeof(imgPath),"%s%s.png", CFG.disc_path, ID); //changed to current id + + if (diskCover) + delete diskCover; + + diskCover = new GuiImageData(imgPath,0); + + if (!diskCover->GetImage()) + { + delete diskCover; + snprintf(imgPath, sizeof(imgPath), "%s%s.png", CFG.disc_path, IDFull); //changed to current full id + diskCover = new GuiImageData(imgPath, 0); + if (!diskCover->GetImage()) + { + delete diskCover; + diskCover = new GuiImageData(imgPath,nodisc_png); + } + } + + diskImg.SetImage(diskCover); + sizeTxt.SetText(sizeText); + msgTxt.SetText(gameName); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + float speedup = 1; //speedup increases while disc is selected + + while(choice == -1) + { + VIDEO_WaitVSync(); + //angle++; + angle = int(angle+speedup) % 360; + //disc speedup and slowdown + if (btn1.GetState() == STATE_SELECTED) { //if mouse over + if (speedup < 11) // speed up + { + speedup = (speedup+0.20); + } + } + else //if not mouse over + { + if (speedup > 1) {speedup = (speedup-0.05);} //slow down + } + if (speedup < 1) + { + speedup = 1; + } + diskImg.SetAngle(angle); + + if(shutdown == 1) //for power button + { + wiilight(0); + Sys_Shutdown(); + } + + if(btn1.GetState() == STATE_CLICKED) { //boot + choice = 1; + SDCARD_deInit(); + } + + else if(btn2.GetState() == STATE_CLICKED) { //back + choice = 0; + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + mainWindow->SetState(STATE_DEFAULT); + wiilight(0); + } + + else if(btn3.GetState() == STATE_CLICKED) { //settings + choice = 2; + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + } + + else if(nameBtn.GetState() == STATE_CLICKED) { //rename + choice = 3; + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + } + + else if(btnRight.GetState() == STATE_CLICKED) { + promptWindow.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_OUT, 50); + changed = 1; + gameSelected = (gameSelected + 1) % gameCnt; + btnRight.ResetState(); + break; + } + + else if(btnLeft.GetState() == STATE_CLICKED) { + promptWindow.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_OUT, 50); + changed = 2; + gameSelected = (gameSelected - 1 + gameCnt) % gameCnt; + btnLeft.ResetState(); + break; + } + } + + + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + + ResumeGui(); + } + delete diskCover; + + return choice; +} + +/**************************************************************************** + * DiscWait + ***************************************************************************/ +int +DiscWait(const char *title, const char *msg, const char *btn1Label, const char *btn2Label) +{ + int choice = -1; + u32 cover = 0; + s32 ret; + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + GuiImageData btnOutline(button_dialogue_box_png); + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,60); + GuiText msgTxt(msg, 22, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-40); + msgTxt.SetMaxWidth(430); + + GuiText btn1Txt(btn1Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + + if(btn2Label) + { + btn1.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn1.SetPosition(40, -45); + } + else + { + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn1.SetPosition(0, -45); + } + + btn1.SetLabel(&btn1Txt); + btn1.SetImage(&btn1Img); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnClick); + btn1.SetTrigger(&trigB); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + GuiText btn2Txt(btn2Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn2.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn2.SetPosition(-20, -25); + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetSoundClick(&btnClick); + btn2.SetTrigger(&trigA); + btn2.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&btn1); + + if(btn2Label) + promptWindow.Append(&btn2); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + while(!(cover & 0x2)) + { + VIDEO_WaitVSync(); + if(btn1.GetState() == STATE_CLICKED) { + choice = 1; + break; + } + ret = WDVD_GetCoverStatus(&cover); + if (ret < 0) + return ret; + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return 0; +} + +/**************************************************************************** + * FormatingPartition + ***************************************************************************/ +int +FormatingPartition(const char *title, partitionEntry *entry) +{ + int ret; + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + + GuiImageData btnOutline(button_dialogue_box_png); + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,60); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + VIDEO_WaitVSync(); + ret = WBFS_Format(entry->sector, entry->size); + + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return ret; +} + + +/**************************************************************************** + * NetworkInit + ***************************************************************************/ +char * NetworkInitPromp(int choice2) +{ + char myIP [16]; + char * IP = 0; + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + + GuiImageData btnOutline(button_dialogue_box_png); + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt("Initializing Network", 26, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,60); + + char msg[20] = " "; + GuiText msgTxt(msg, 22, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-40); + + GuiText btn1Txt("Cancel", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn1.SetPosition(0, -45); + btn1.SetLabel(&btn1Txt); + btn1.SetImage(&btn1Img); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnClick); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&btn1); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + VIDEO_WaitVSync(); + + while (!IP) + { + + Net_Init(myIP); + IP = myIP; + if (IP) { + sprintf(msg, "IP: %s", IP); + msgTxt.SetText(msg); + cntMissFiles = 0; + u32 i = 0; + char filename[11]; + // char filenameshort[10]; + bool found1 = false; + bool found2 = false; + for (i = 0; i < gameCnt && cntMissFiles < 500; i++) + { + struct discHdr* header = &gameList[i]; + if (choice2 != 3) { + + snprintf (filename,sizeof(filename),"%c%c%c.png", header->id[0], header->id[1], header->id[2]); + found2 = findfile(filename, CFG.covers_path); + snprintf(filename,sizeof(filename),"%c%c%c%c%c%c.png",header->id[0], header->id[1], header->id[2], + header->id[3], header->id[4], header->id[5]); //full id + found1 = findfile(filename, CFG.covers_path); + if (!found1 && !found2) //if could not find any image + { + snprintf(missingFiles[cntMissFiles],11,"%s",filename); + cntMissFiles++; + } + } + else if (choice2 == 3) { + snprintf (filename,sizeof(filename),"%c%c%c.png", header->id[0], header->id[1], header->id[2]); + found2 = findfile(filename, CFG.disc_path); + snprintf(filename,sizeof(filename),"%c%c%c%c%c%c.png",header->id[0], header->id[1], header->id[2], + header->id[3], header->id[4], header->id[5]); //full id + found1 = findfile(filename,CFG.disc_path); + if (!found1 && !found2) + { + snprintf(missingFiles[cntMissFiles],11,"%s",filename); + cntMissFiles++; + } + } + } + break; + } + + if(btn1.GetState() == STATE_CLICKED) { //pending: this should be inside the for loop + IP = 0; + break; + } + + } + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return IP; +} + +/**************************************************************************** + * ShowProgress + * + * Updates the variables used by the progress window for drawing a progress + * bar. Also resumes the progress window thread if it is suspended. + ***************************************************************************/ +void +ShowProgress (s32 done, s32 total) +{ + + static time_t start; + static u32 expected; + + f32 percent; //, size; + u32 d, h, m, s; + + //first time + if (!done) { + start = time(0); + expected = 300; + } + + //Elapsed time + d = time(0) - start; + + if (done != total) { + //Expected time + if (d) + expected = (expected * 3 + d * total / done) / 4; + + //Remaining time + d = (expected > d) ? (expected - d) : 0; + } + + //Calculate time values + h = d / 3600; + m = (d / 60) % 60; + s = d % 60; + + //Calculate percentage/size + percent = (done * 100.0) / total; + //size = (hdd->wbfs_sec_sz / GB_SIZE) * total; + + progressTotal = total; + progressDone = done; + + sprintf(prozent, "%0.2f%%", percent); + prTxt.SetText(prozent); + sprintf(timet,"Time left: %d:%02d:%02d",h,m,s); + timeTxt.SetText(timet); + progressbarImg.SetTile(100*progressDone/progressTotal); + +} + +/**************************************************************************** + * ProgressWindow + * + * Opens a window, which displays progress to the user. Can either display a + * progress bar showing % completion, or a throbber that only shows that an + * action is in progress. + ***************************************************************************/ +int +ProgressWindow(const char *title, const char *msg) +{ + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiImageData btnOutline(button_dialogue_box_png); + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiImageData progressbarOutline(progressbar_outline_png); + GuiImage progressbarOutlineImg(&progressbarOutline); + progressbarOutlineImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarOutlineImg.SetPosition(25, 40); + + GuiImageData progressbarEmpty(progressbar_empty_png); + GuiImage progressbarEmptyImg(&progressbarEmpty); + progressbarEmptyImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarEmptyImg.SetPosition(25, 40); + progressbarEmptyImg.SetTile(100); + + GuiImageData progressbar(progressbar_png); + + progressbarImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarImg.SetPosition(25, 40); + + GuiText titleTxt(title, 26, (GXColor){70, 70, 10, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,60); + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + msgTxt.SetPosition(0,130); + + prTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + prTxt.SetPosition(0, 40); + + timeTxt.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + timeTxt.SetPosition(0,-30); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&progressbarEmptyImg); + promptWindow.Append(&progressbarImg); + promptWindow.Append(&progressbarOutlineImg); + promptWindow.Append(&prTxt); + promptWindow.Append(&timeTxt); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + s32 ret; + + ret = wbfs_add_disc(hdd, __WBFS_ReadDVD, NULL, ShowProgress, ONLY_GAME_PARTITION, 0); + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + if (ret < 0) { + return ret; + } + return 0; +} + +/**************************************************************************** + * ProgressWindow + * + * Opens a window, which displays progress to the user. Can either display a + * progress bar showing % completion, or a throbber that only shows that an + * action is in progress. + ***************************************************************************/ +int +ProgressDownloadWindow(int choice2) +{ + + int i = 0, cntNotFound = 0; +// char filename[11]; + + GuiWindow promptWindow(472,320); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + + GuiImageData btnOutline(button_dialogue_box_png); + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiImageData progressbarOutline(progressbar_outline_png); + GuiImage progressbarOutlineImg(&progressbarOutline); + progressbarOutlineImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarOutlineImg.SetPosition(25, 40); + + GuiImageData progressbarEmpty(progressbar_empty_png); + GuiImage progressbarEmptyImg(&progressbarEmpty); + progressbarEmptyImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarEmptyImg.SetPosition(25, 40); + progressbarEmptyImg.SetTile(100); + + GuiImageData progressbar(progressbar_png); + + progressbarImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarImg.SetPosition(25, 40); + + GuiText titleTxt("Downloading file:", 26, (GXColor){70, 70, 10, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,60); + char msg[25] = " "; + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + msgTxt.SetPosition(0,130); + char msg2[15] = " "; + GuiText msg2Txt(msg2, 26, (GXColor){0, 0, 0, 255}); + msg2Txt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + msg2Txt.SetPosition(0,100); + + prTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + prTxt.SetPosition(0, 40); + + GuiText btn1Txt("Cancel", 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn1.SetPosition(0, -45); + btn1.SetLabel(&btn1Txt); + btn1.SetImage(&btn1Img); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnClick); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&msg2Txt); + promptWindow.Append(&progressbarEmptyImg); + promptWindow.Append(&progressbarImg); + promptWindow.Append(&progressbarOutlineImg); + promptWindow.Append(&prTxt); + promptWindow.Append(&btn1); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + //check if directory exist and if not create one + struct stat st; + if(stat(CFG.covers_path, &st) != 0) { + char dircovers[100]; + snprintf(dircovers,strlen(CFG.covers_path),"%s",CFG.covers_path); + if (mkdir(dircovers, 0777) == -1) { + WindowPrompt("Error:","Can't create directory","OK",0); + cntMissFiles = 0; + } + } + if(stat(CFG.disc_path,&st) != 0) { + char dirdiscs[100]; + snprintf(dirdiscs,strlen(CFG.disc_path),"%s",CFG.disc_path); + if (mkdir(dirdiscs, 0777) == -1) { + WindowPrompt("Error:","Can't create directory","OK",0); + cntMissFiles = 0; + } + } + + while (i < cntMissFiles) { + + + + sprintf(prozent, "%i%%", 100*i/cntMissFiles); + prTxt.SetText(prozent); + progressbarImg.SetTile(100*i/cntMissFiles); + + sprintf(msg, "%i file(s) left", cntMissFiles - i); + msgTxt.SetText(msg); + sprintf(msg2, "%s", missingFiles[i]); + msg2Txt.SetText(msg2); + + //download boxart image + char imgPath[100]; + char URLFile[100]; + if (choice2 == 2) { + sprintf(URLFile,"http://www.theotherzone.com/wii/3d/176/248/%s",missingFiles[i]); // For 3D Covers + sprintf(imgPath,"%s%s", CFG.covers_path, missingFiles[i]); + } + if(choice2 == 3) { + sprintf(URLFile,"http://www.theotherzone.com/wii/diskart/160/160/%s",missingFiles[i]); + sprintf(imgPath,"%s%s", CFG.disc_path, missingFiles[i]); + } + if(choice2 == 1) { + sprintf(URLFile,"http://www.theotherzone.com/wii/resize/160/224/%s",missingFiles[i]); + sprintf(imgPath,"%s%s", CFG.covers_path, missingFiles[i]); + } + + struct block file = downloadfile(URLFile); + + if (file.size == 36864 || file.size <= 1024 || file.size == 7386 || file.data == NULL) { + cntNotFound++; + i++; + } else { + + if(file.data != NULL) + { + // save png to sd card + FILE *pfile; + pfile = fopen(imgPath, "wb"); + if (!pfile) + return -1; + fwrite(file.data,1,file.size,pfile); + fclose (pfile); + free(file.data); + } + + i++; + } + + if(btn1.GetState() == STATE_CLICKED) { + cntNotFound = cntMissFiles-i+cntNotFound; + break; + } + + } + + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + + if (cntNotFound != 0) { + return cntNotFound; + } else { + return 0; + } +} + + +/**************************************************************************** + * UpdateGUI + * + * Primary thread to allow GUI to respond to state changes, and draws GUI + ***************************************************************************/ + +static void * +UpdateGUI (void *arg) +{ + while(1) + { + if(guiHalt) + { + LWP_SuspendThread(guithread); + } + else + { + mainWindow->Draw(); + + #ifdef HW_RVL + for(int i=3; i >= 0; i--) // so that player 1's cursor appears on top! + { + if(userInput[i].wpad.ir.valid) + Menu_DrawImg(userInput[i].wpad.ir.x-48, userInput[i].wpad.ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad.ir.angle, CFG.widescreen? 0.8 : 1, 1, 255); + if(Settings.rumble == RumbleOn) + { + DoRumble(i); + } + } + #endif + + Menu_Render(); + + for(int i=0; i < 4; i++) + mainWindow->Update(&userInput[i]); + + if(ExitRequested) + { + for(int a = 0; a < 255; a += 15) + { + mainWindow->Draw(); + Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, a},1); + Menu_Render(); + } + ExitApp(); + } + } + } + return NULL; +} + +/**************************************************************************** + * InitGUIThread + * + * Startup GUI threads + ***************************************************************************/ +void +InitGUIThreads() +{ + LWP_CreateThread (&guithread, UpdateGUI, NULL, NULL, 0, 70); +} + +/**************************************************************************** + * EntryCmp + ***************************************************************************/ +s32 __Menu_EntryCmp(const void *a, const void *b) +{ + struct discHdr *hdr1 = (struct discHdr *)a; + struct discHdr *hdr2 = (struct discHdr *)b; + + /* Compare strings */ + return stricmp(get_title(hdr1), get_title(hdr2)); +} + +/**************************************************************************** + * Get Gamelist + ***************************************************************************/ + +s32 __Menu_GetEntries(void) +{ + struct discHdr *buffer = NULL; + struct discHdr *buffer2 = NULL; + struct discHdr *header = NULL; + + u32 cnt, len; + s32 ret; + + /* Get list length */ + ret = WBFS_GetCount(&cnt); + if (ret < 0) + return ret; + + /* Buffer length */ + len = sizeof(struct discHdr) * cnt; + + /* Allocate memory */ + buffer = (struct discHdr *)memalign(32, len); + if (!buffer) + return -1; + + /* Clear buffer */ + memset(buffer, 0, len); + + /* Get header list */ + ret = WBFS_GetHeaders(buffer, cnt, sizeof(struct discHdr)); + if (ret < 0) + goto err; + + if (CFG.parentalcontrol && !CFG.godmode) + { + u32 cnt2 = 0; + + for (u32 i = 0; i < cnt; i++) + { + header = &buffer[i]; + if (get_block(header) < CFG.parentalcontrol) + { + buffer2 = (discHdr *) realloc(buffer2, (cnt2+1) * sizeof(struct discHdr)); + if (!buffer2) + { + free(buffer); + return -1; + } + + memcpy((buffer2 + cnt2), (buffer + i), sizeof(struct discHdr)); + cnt2++; + } + } + free(buffer); + buffer = buffer2; + buffer2 = NULL; + cnt = cnt2; + } + + /* Sort entries */ + qsort(buffer, cnt, sizeof(struct discHdr), __Menu_EntryCmp); + + /* Free memory */ + if (gameList) + free(gameList); + + /* Set values */ + gameList = buffer; + gameCnt = cnt; + + /* Reset variables */ + gameSelected = gameStart = 0; + + return 0; + +err: + /* Free memory */ + if (buffer) + free(buffer); + + return ret; +} + +/**************************************************************************** + * OnScreenKeyboard + * + * Opens an on-screen keyboard window, with the data entered being stored + * into the specified variable. + ***************************************************************************/ +static int OnScreenKeyboard(char * var, u16 maxlen) +{ + int save = -1; + + GuiKeyboard keyboard(var, maxlen); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + + GuiImageData btnOutline(button_dialogue_box_png); + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetSimpleTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + GuiText okBtnTxt("OK", 22, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(25, -25); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetSoundClick(&btnClick); + okBtn.SetTrigger(&trigA); + okBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Cancel", 22, (GXColor){0, 0, 0, 255}); + GuiImage cancelBtnImg(&btnOutline); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + cancelBtn.SetPosition(-25, -25); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetSoundClick(&btnClick); + cancelBtn.SetTrigger(&trigA); + cancelBtn.SetTrigger(&trigB); + cancelBtn.SetEffectGrow(); + + keyboard.Append(&okBtn); + keyboard.Append(&cancelBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&keyboard); + mainWindow->ChangeFocus(&keyboard); + ResumeGui(); + + while(save == -1) + { + VIDEO_WaitVSync(); + + if(okBtn.GetState() == STATE_CLICKED) + save = 1; + else if(cancelBtn.GetState() == STATE_CLICKED) + save = 0; + } + + if(save) + { + snprintf(var, maxlen, "%s", keyboard.kbtextstr); + } + + HaltGui(); + mainWindow->Remove(&keyboard); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return save; +} + + +/**************************************************************************** + * MenuInstall + ***************************************************************************/ + +static int MenuInstall() +{ + int menu = MENU_NONE; + static struct discHdr headerdisc ATTRIBUTE_ALIGN(32); + + if(Settings.cios == ios222) { + Disc_SetUSB(NULL, 1); + } else { + Disc_SetUSB(NULL, 0); + } + + int ret, choice = 0; + char *name; + static char buffer[MAX_CHARACTERS + 4]; + + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + + GuiImageData battery(battery_png); + GuiImageData batteryRed(battery_red_png); + GuiImageData batteryBar(battery_bar_png); + + + #ifdef HW_RVL + int i = 0, level; + char txt[3]; + GuiText * batteryTxt[4]; + GuiImage * batteryImg[4]; + GuiImage * batteryBarImg[4]; + GuiButton * batteryBtn[4]; + + for(i=0; i < 4; i++) + { + + if(i == 0) + sprintf(txt, "P%d", i+1); + else + sprintf(txt, "P%d", i+1); + + batteryTxt[i] = new GuiText(txt, 22, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + batteryTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i] = new GuiImage(&battery); + batteryImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i]->SetPosition(36, 0); + batteryImg[i]->SetTile(0); + batteryBarImg[i] = new GuiImage(&batteryBar); + batteryBarImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryBarImg[i]->SetPosition(33, 0); + + batteryBtn[i] = new GuiButton(40, 20); + batteryBtn[i]->SetLabel(batteryTxt[i]); + batteryBtn[i]->SetImage(batteryBarImg[i]); + batteryBtn[i]->SetIcon(batteryImg[i]); + batteryBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + batteryBtn[i]->SetRumble(false); + batteryBtn[i]->SetAlpha(70); + } + + + batteryBtn[0]->SetPosition(THEME.battery1_x, THEME.battery1_y); + batteryBtn[1]->SetPosition(THEME.battery2_x, THEME.battery2_y); + batteryBtn[2]->SetPosition(THEME.battery3_x, THEME.battery3_y); + batteryBtn[3]->SetPosition(THEME.battery4_x, THEME.battery4_y); + #endif + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + + if (THEME.showBattery) + { + #ifdef HW_RVL + w.Append(batteryBtn[0]); + w.Append(batteryBtn[1]); + w.Append(batteryBtn[2]); + w.Append(batteryBtn[3]); + #endif + } + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) // controller connected + { + level = (userInput[i].wpad.battery_level / 100.0) * 4; + if(level > 4) level = 4; + batteryImg[i]->SetTile(level); + + if(level == 0) + batteryBarImg[i]->SetImage(&batteryRed); + else + batteryBarImg[i]->SetImage(&batteryBar); + + batteryBtn[i]->SetAlpha(255); + } + else // controller not connected + { + batteryImg[i]->SetTile(0); + batteryImg[i]->SetImage(&battery); + batteryBtn[i]->SetAlpha(70); + } + } + #endif + + ret = DiscWait("Insert Disk","Waiting...","Cancel",0); + if (ret < 0) { + WindowPrompt ("Error reading Disc",0,"Back",0); + menu = MENU_DISCLIST; + break; + } + ret = Disc_Open(); + if (ret < 0) { + WindowPrompt ("Could not open Disc",0,"Back",0); + menu = MENU_DISCLIST; + break; + } + + ret = Disc_IsWii(); + if (ret < 0) { + choice = WindowPrompt ("Not a Wii Disc","Insert a Wii Disc!","OK","Back"); + + if (choice == 1) { + menu = MENU_INSTALL; + break; + } else + menu = MENU_DISCLIST; + break; + } + + Disc_ReadHeader(&headerdisc); + name = headerdisc.title; + if (strlen(name) < (22 + 3)) { + memset(buffer, 0, sizeof(buffer)); + sprintf(name, "%s", name); + } else { + strncpy(buffer, name, MAX_CHARACTERS); + strncat(buffer, "...", 3); + sprintf(name, "%s", buffer); + } + + ret = WBFS_CheckGame(headerdisc.id); + if (ret) { + WindowPrompt ("Game is already installed:",name,"Back",0); + menu = MENU_DISCLIST; + break; + } + hdd = GetHddInfo(); + if (!hdd) { + WindowPrompt ("No HDD found!","Error!!","Back",0); + menu = MENU_DISCLIST; + break; + } + + f32 freespace, used; + + WBFS_DiskSpace(&used, &freespace); + u32 estimation = wbfs_estimate_disc(hdd, __WBFS_ReadDVD, NULL, ONLY_GAME_PARTITION); + f32 gamesize = ((f32) estimation)/1073741824; + char gametxt[50]; + sprintf(gametxt, "Installing game %.2fGB:", gamesize); + if (gamesize > freespace) { + char errortxt[50]; + sprintf(errortxt, "Game Size: %.2fGB, Free Space: %.2fGB", gamesize, freespace); + choice = WindowPrompt("Not enough free space!",errortxt,"Go on", "Return"); + if (choice == 1) { + ret = ProgressWindow(gametxt, name); + if (ret != 0) { + WindowPrompt ("Install error!",0,"Back",0); + menu = MENU_DISCLIST; + break; + } + else { + __Menu_GetEntries(); //get the entries again + wiilight(1); + WindowPrompt ("Successfully installed:",name,"OK",0); + menu = MENU_DISCLIST; + wiilight(0); + break; + } + } else { + menu = MENU_DISCLIST; + break; + } + + } + else { + ret = ProgressWindow(gametxt, name); + if (ret != 0) { + WindowPrompt ("Install error!",0,"Back",0); + menu = MENU_DISCLIST; + break; + } else { + __Menu_GetEntries(); //get the entries again + wiilight(1); + WindowPrompt ("Successfully installed:",name,"OK",0); + menu = MENU_DISCLIST; + wiilight(0); + break; + } + } + + if (shutdown == 1) + Sys_Shutdown(); + + } + + + HaltGui(); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + delete batteryTxt[i]; + delete batteryImg[i]; + delete batteryBarImg[i]; + delete batteryBtn[i]; + } + #endif + + mainWindow->Remove(&w); + ResumeGui(); + return menu; +} + +/**************************************************************************** + * MenuDiscList + ***************************************************************************/ + +static int MenuDiscList() +{ + int menu = MENU_NONE; + char imgPath[100]; + + f32 freespace, used, size = 0.0; + u32 nolist; + char text[MAX_CHARACTERS + 4]; //text2[20]; + int choice = 0, selectedold = 100; + s32 ret; + + //CLOCK + struct tm * timeinfo; + char theTime[80]; + int counter = 0; + + WBFS_DiskSpace(&used, &freespace); + + if (!gameCnt) { + nolist = 1; + } + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + + snprintf(imgPath, sizeof(imgPath), "%sbutton_install.png", CFG.theme_path); + GuiImageData btnInstall(imgPath, button_install_png); + snprintf(imgPath, sizeof(imgPath), "%sbutton_install_over.png", CFG.theme_path); + GuiImageData btnInstallOver(imgPath, button_install_over_png); + + snprintf(imgPath, sizeof(imgPath), "%ssettings_button.png", CFG.theme_path); + GuiImageData btnSettings(imgPath, settings_button_png); + snprintf(imgPath, sizeof(imgPath), "%ssettings_button_over.png", CFG.theme_path); + GuiImageData btnSettingsOver(imgPath, settings_button_over_png); + + snprintf(imgPath, sizeof(imgPath), "%swiimote_poweroff.png", CFG.theme_path); + GuiImageData btnpwroff(imgPath, wiimote_poweroff_png); + snprintf(imgPath, sizeof(imgPath), "%swiimote_poweroff_over.png", CFG.theme_path); + GuiImageData btnpwroffOver(imgPath, wiimote_poweroff_over_png); + snprintf(imgPath, sizeof(imgPath), "%smenu_button.png", CFG.theme_path); + GuiImageData btnhome(imgPath, menu_button_png); + snprintf(imgPath, sizeof(imgPath), "%smenu_button_over.png", CFG.theme_path); + GuiImageData btnhomeOver(imgPath, menu_button_over_png); + snprintf(imgPath, sizeof(imgPath), "%sSDcard.png", CFG.theme_path); + GuiImageData btnsdcard(imgPath, sdcard_png); + + GuiImageData battery(battery_png); + GuiImageData batteryRed(battery_red_png); + GuiImageData batteryBar(battery_bar_png); + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + char spaceinfo[30]; + sprintf(spaceinfo,"%.2fGB of %.2fGB free",freespace,(freespace+used)); + GuiText usedSpaceTxt(spaceinfo, 18, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + usedSpaceTxt.SetAlignment(THEME.hddInfoAlign, ALIGN_TOP); + usedSpaceTxt.SetPosition(THEME.hddInfo_x, THEME.hddInfo_y); + + char GamesCnt[15]; + sprintf(GamesCnt,"Games: %i",gameCnt); + GuiText gamecntTxt(GamesCnt, 18, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + gamecntTxt.SetAlignment(THEME.gameCntAlign, ALIGN_TOP); + gamecntTxt.SetPosition(THEME.gameCnt_x,THEME.gameCnt_y); + + GuiImageData tooltipLarge(tooltip_large_png); + GuiImage tooltipLargeImg(&tooltipLarge); + + GuiText ttinstallTxt("Install a game", 22, (GXColor){0, 0, 0, 255}); //TOOLTIP DATA FOR INSTALL BUTTON + GuiImageData ttinstall(tooltip_medium_png); + GuiImage ttinstallImg(&ttinstall); + + GuiImage installBtnImg(&btnInstall); + GuiImage installBtnImgOver(&btnInstallOver); + installBtnImg.SetWidescreen(CFG.widescreen); //added + installBtnImgOver.SetWidescreen(CFG.widescreen); //added + GuiButton installBtn(btnInstall.GetWidth(), btnInstall.GetHeight()); + installBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + installBtn.SetPosition(THEME.install_x, THEME.install_y); + installBtn.SetImage(&installBtnImg); + installBtn.SetImageOver(&installBtnImgOver); + installBtn.SetSoundOver(&btnSoundOver); + installBtn.SetSoundClick(&btnClick); + installBtn.SetTrigger(&trigA); + installBtn.SetEffectGrow(); + if (Settings.tooltips == TooltipsOn && THEME.showToolTip != 0) + installBtn.SetToolTip(&ttinstallImg,&ttinstallTxt,175,-30); + + GuiText ttsettingsTxt("Settings", 22, (GXColor){0, 0, 0, 255}); //TOOLTIP DATA FOR SETTINGS BUTTON + GuiImageData ttsettings(tooltip_png); + GuiImage ttsettingsImg(&ttsettings); + + GuiImage settingsBtnImg(&btnSettings); + settingsBtnImg.SetWidescreen(CFG.widescreen); //added + GuiImage settingsBtnImgOver(&btnSettingsOver); + settingsBtnImgOver.SetWidescreen(CFG.widescreen); //added + GuiButton settingsBtn(btnSettings.GetWidth(), btnSettings.GetHeight()); + settingsBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + settingsBtn.SetPosition(THEME.setting_x, THEME.setting_y); + settingsBtn.SetImage(&settingsBtnImg); + settingsBtn.SetImageOver(&settingsBtnImgOver); + settingsBtn.SetSoundOver(&btnSoundOver); + settingsBtn.SetSoundClick(&btnClick); + settingsBtn.SetTrigger(&trigA); + settingsBtn.SetEffectGrow(); + if (Settings.tooltips == TooltipsOn && THEME.showToolTip != 0) + settingsBtn.SetToolTip(&ttsettingsImg,&ttsettingsTxt,65,-30); + + GuiText tthomeTxt("Back to HBC or Wii Menu", 22, (GXColor){0, 0, 0, 255}); //TOOLTIP DATA FOR HOME BUTTON + GuiImageData tthome(tooltip_large_png); + GuiImage tthomeImg(&tthome); + + GuiImage homeBtnImg(&btnhome); + homeBtnImg.SetWidescreen(CFG.widescreen); //added + GuiImage homeBtnImgOver(&btnhomeOver); + homeBtnImgOver.SetWidescreen(CFG.widescreen); //added + GuiButton homeBtn(btnhome.GetWidth(), btnhome.GetHeight()); + homeBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + homeBtn.SetPosition(THEME.home_x, THEME.home_y); + homeBtn.SetImage(&homeBtnImg); + homeBtn.SetImageOver(&homeBtnImgOver); + homeBtn.SetSoundOver(&btnSoundOver); + homeBtn.SetSoundClick(&btnClick); + homeBtn.SetTrigger(&trigA); + homeBtn.SetTrigger(&trigHome); + homeBtn.SetEffectGrow(); + if (Settings.tooltips == TooltipsOn && THEME.showToolTip != 0) + homeBtn.SetToolTip(&tthomeImg,&tthomeTxt,15,-30); + + GuiText ttpoweroffTxt("Power off the Wii", 22, (GXColor){0, 0, 0, 255}); //TOOLTIP DATA FOR POWER BUTTON + GuiImageData ttpoweroff(tooltip_medium_png); + GuiImage ttpoweroffImg(&ttpoweroff); + + + GuiImage poweroffBtnImg(&btnpwroff); + GuiImage poweroffBtnImgOver(&btnpwroffOver); + poweroffBtnImg.SetWidescreen(CFG.widescreen); + poweroffBtnImgOver.SetWidescreen(CFG.widescreen); + GuiButton poweroffBtn(btnpwroff.GetWidth(), btnpwroff.GetHeight()); + poweroffBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + poweroffBtn.SetPosition(THEME.power_x, THEME.power_y); + poweroffBtn.SetImage(&poweroffBtnImg); + poweroffBtn.SetImageOver(&poweroffBtnImgOver); + poweroffBtn.SetSoundOver(&btnSoundOver); + poweroffBtn.SetSoundClick(&btnClick); + poweroffBtn.SetTrigger(&trigA); + poweroffBtn.SetEffectGrow(); + if (Settings.tooltips == TooltipsOn && THEME.showToolTip != 0) + poweroffBtn.SetToolTip(&ttpoweroffImg,&ttpoweroffTxt,-10,-30); + + GuiImage sdcardImg(&btnsdcard); + sdcardImg.SetWidescreen(CFG.widescreen); + GuiButton sdcardBtn(btnsdcard.GetWidth(), btnsdcard.GetHeight()); + sdcardBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + sdcardBtn.SetPosition(THEME.sdcard_x, THEME.sdcard_y); + sdcardBtn.SetImage(&sdcardImg); + sdcardBtn.SetSoundOver(&btnSoundOver); + sdcardBtn.SetSoundClick(&btnClick); + sdcardBtn.SetTrigger(&trigA); + sdcardBtn.SetEffectGrow(); + + //Downloading Covers + GuiText ttDownloadTxt("Click to Download Covers", 20, (GXColor){0, 0, 0, 255}); //TOOLTIP DATA FOR DOWNLOAD + GuiImageData ttDownload(tooltip_large_png); + GuiImage ttDownloadImg(&ttDownload); + + GuiButton DownloadBtn(160,224); + DownloadBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + DownloadBtn.SetPosition(THEME.cover_x,THEME.cover_y);//(20, 300); + DownloadBtn.SetSoundOver(&btnSoundOver); + if (CFG.godmode == 1){ + if (Settings.tooltips == TooltipsOn && THEME.showToolTip != 0){ + DownloadBtn.SetToolTip(&ttDownloadImg,&ttDownloadTxt,205,-30); + DownloadBtn.SetTrigger(&trigA); + } + } + + #ifdef HW_RVL + int i = 0, level; + char txt[3]; + GuiText * batteryTxt[4]; + GuiImage * batteryImg[4]; + GuiImage * batteryBarImg[4]; + GuiButton * batteryBtn[4]; + + for(i=0; i < 4; i++) + { + + if(i == 0) + sprintf(txt, "P%d", i+1); + else + sprintf(txt, "P%d", i+1); + + batteryTxt[i] = new GuiText(txt, 22, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + batteryTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i] = new GuiImage(&battery); + batteryImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i]->SetPosition(36, 0); + batteryImg[i]->SetTile(0); + batteryBarImg[i] = new GuiImage(&batteryBar); + batteryBarImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryBarImg[i]->SetPosition(33, 0); + + batteryBtn[i] = new GuiButton(40, 20); + batteryBtn[i]->SetLabel(batteryTxt[i]); + batteryBtn[i]->SetImage(batteryBarImg[i]); + batteryBtn[i]->SetIcon(batteryImg[i]); + batteryBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + batteryBtn[i]->SetRumble(false); + batteryBtn[i]->SetAlpha(70); + } + + batteryBtn[0]->SetPosition(THEME.battery1_x, THEME.battery1_y); + batteryBtn[1]->SetPosition(THEME.battery2_x, THEME.battery2_y); + batteryBtn[2]->SetPosition(THEME.battery3_x, THEME.battery3_y); + batteryBtn[3]->SetPosition(THEME.battery4_x, THEME.battery4_y); + #endif + + GuiGameBrowser gameBrowser(THEME.selection_w, THEME.selection_h, gameList, gameCnt, CFG.theme_path, bg_options_png, startat, offset); + gameBrowser.SetPosition(THEME.selection_x, THEME.selection_y); + gameBrowser.SetAlignment(ALIGN_LEFT, ALIGN_CENTRE); + + GuiText clockTime(theTime, 30, (GXColor){138, 138, 138, 255}); + clockTime.SetAlignment(THEME.clockAlign, ALIGN_BOTTOM); + clockTime.SetPosition(THEME.clock_x, THEME.clock_y); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + + if((Settings.hddinfo == HDDInfo && THEME.showHDD == -1) || THEME.showHDD == 1) //force show hdd info + { + w.Append(&usedSpaceTxt); + } + if((Settings.hddinfo == HDDInfo && THEME.showGameCnt == -1) || THEME.showGameCnt == 1) //force show game cnt info + { + w.Append(&gamecntTxt); + } + + w.Append(&sdcardBtn); + w.Append(&poweroffBtn); + if (CFG.godmode) + w.Append(&installBtn); + w.Append(&homeBtn); + w.Append(&settingsBtn); + w.Append(&DownloadBtn); + + if(Settings.hddinfo == Clock) + { + w.Append(&clockTime); + } + + if (THEME.showBattery) + { + #ifdef HW_RVL + w.Append(batteryBtn[0]); + w.Append(batteryBtn[1]); + w.Append(batteryBtn[2]); + w.Append(batteryBtn[3]); + #endif + } + + mainWindow->Append(&gameBrowser); + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + + VIDEO_WaitVSync (); + + //CLOCK + if ((Settings.hddinfo == Clock)&&(counter % 2000 == 0)) { + time_t rawtime = time(0); + timeinfo = localtime (&rawtime); + strftime(theTime, sizeof(theTime), "%H:%M", timeinfo); + clockTime.SetText(theTime); + } + counter++; + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) // controller connected + { + level = (userInput[i].wpad.battery_level / 100.0) * 4; + if(level > 4) level = 4; + batteryImg[i]->SetTile(level); + + if(level == 0) + batteryBarImg[i]->SetImage(&batteryRed); + else + batteryBarImg[i]->SetImage(&batteryBar); + + batteryBtn[i]->SetAlpha(255); + } + else // controller not connected + { + batteryImg[i]->SetTile(0); + batteryImg[i]->SetImage(&battery); + batteryBtn[i]->SetAlpha(70); + } + } + #endif + + if(shutdown == 1) + { + Sys_Shutdown(); + } + if(poweroffBtn.GetState() == STATE_CLICKED) + { + + choice = WindowPrompt ("Shutdown System","Are you sure?","Yes","No"); + if(choice == 1) + { + WPAD_Flush(0); + WPAD_Disconnect(0); + WPAD_Shutdown(); + Sys_Shutdown(); + //exit(0); + } else { + poweroffBtn.ResetState(); + gameBrowser.SetFocus(1); + } + + } + else if(homeBtn.GetState() == STATE_CLICKED) + { + + choice = WiiMenuWindowPrompt ("Exit USB ISO Loader ?","Wii Menu","Back to Loader","Back"); + if(choice == 1) + { + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); // Back to System Menu + } + else if (choice == 2) + { + if (*(unsigned int*) 0x80001800) exit(0); + // Channel Version + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + //exit(0); //Back to HBC + } else { + homeBtn.ResetState(); + gameBrowser.SetFocus(1); + } + + } + else if(installBtn.GetState() == STATE_CLICKED) + { + choice = WindowPrompt ("Install a game?",0,"Yes","No"); + if (choice == 1) + { + menu = MENU_INSTALL; + break; + } + else + { + installBtn.ResetState(); + gameBrowser.SetFocus(1); + } + } + + else if(sdcardBtn.GetState() == STATE_CLICKED) + { + __io_wiisd.shutdown(); + __io_wiisd.startup(); + break; + } + + else if(DownloadBtn.GetState() == STATE_CLICKED) + { + choice = DownloadWindowPrompt(); // ask for download choice + + if (choice != 0) + { + char * myIP; + int choice2 = choice; + + myIP = NetworkInitPromp(choice2); + networkisinitialized = 1; + if( !myIP ) + { + WindowPrompt("Network init error", 0, "ok",0); + netcheck = false; + } + else netcheck = true; + + if (netcheck) + { + + if (missingFiles != NULL && cntMissFiles > 0) + + { + char tempCnt[40]; + i = 0; + + sprintf(tempCnt,"Missing %i files",cntMissFiles); + choice = WindowPrompt("Download Boxart image?",tempCnt,"Yes","No"); + //WindowPrompt("Downloading","Please Wait Downloading Covers",0,0); + if (choice == 1) + { + ret = ProgressDownloadWindow(choice2); + if (ret == 0) { + WindowPrompt("Download finished",0,"OK",0); + } else { + sprintf(tempCnt,"%i files not found on the server!",ret); + WindowPrompt("Download finished",tempCnt,"OK",0); + } + } + } + else + { + WindowPrompt("No file missing!",0,"OK",0); + } + } + } + DownloadBtn.ResetState(); + gameBrowser.SetFocus(1); + }//end download + + else if(settingsBtn.GetState() == STATE_CLICKED) + { startat = gameBrowser.GetSelectedOption(); + offset = gameBrowser.GetOffset(); + menu = MENU_SETTINGS; + break; + + } + + + //Get selected game under cursor + int selectimg, promptnumber; + promptnumber = 0; + char ID[4]; + char IDfull[7]; + selectimg = gameBrowser.GetSelectedOption(); + gameSelected = gameBrowser.GetClickedOption(); + + + + if (gameSelected > 0) //if click occured + selectimg = gameSelected; + + if ((selectimg >= 0) && (selectimg < (s32) gameCnt)) + { + if (selectimg != selectedold) + { + selectedold = selectimg; + struct discHdr *header = &gameList[selectimg]; + snprintf (ID,sizeof(ID),"%c%c%c", header->id[0], header->id[1], header->id[2]); + snprintf (IDfull,sizeof(IDfull),"%c%c%c%c%c%c", header->id[0], header->id[1], header->id[2],header->id[3], header->id[4], header->id[5]); + w.Remove(&DownloadBtn); + w.Remove(coverImg); + + if (GameIDTxt) + { + w.Remove(GameIDTxt); + delete GameIDTxt; + GameIDTxt = NULL; + } + if(GameRegionTxt) + { + w.Remove(GameRegionTxt); + delete GameRegionTxt; + GameRegionTxt = NULL; + } + + switch(header->id[3]) + { + case 'E': + sprintf(gameregion,"NTSC U"); + break; + + case 'J': + sprintf(gameregion,"NTSC J"); + break; + + case 'P': + case 'D': + case 'F': + case 'X': + case 'S': + case 'Y': + sprintf(gameregion," PAL "); + break; + } + + //load game cover + if (cover) + { + delete cover; + cover = NULL; + } + + snprintf(imgPath, sizeof(imgPath), "%s%s.png", CFG.covers_path, ID); + cover = new GuiImageData(imgPath,0); //load short id + if (!cover->GetImage()) //if could not load the short id image + { + delete cover; + snprintf(imgPath, sizeof(imgPath), "%s%s.png", CFG.covers_path, IDfull); + cover = new GuiImageData(imgPath, 0); //load full id image + if (!cover->GetImage()) + { + delete cover; + snprintf(imgPath, sizeof(imgPath), "%snoimage.png", CFG.covers_path); + cover = new GuiImageData(imgPath, nocover_png); //load no image + } + } + + if (coverImg) + { + delete coverImg; + coverImg = NULL; + } + coverImg = new GuiImage(cover); + coverImg->SetWidescreen(CFG.widescreen); + + DownloadBtn.SetImage(coverImg); + w.Append(&DownloadBtn); + + if ((Settings.sinfo == GameID) || (Settings.sinfo == Both)){ + GameIDTxt = new GuiText(IDfull, 22, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + GameIDTxt->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + GameIDTxt->SetPosition(THEME.id_x,THEME.id_y); + GameIDTxt->SetEffect(EFFECT_FADE, 20); + w.Append(GameIDTxt); + } + + if ((Settings.sinfo == GameRegion) || (Settings.sinfo == Both)){ + GameRegionTxt = new GuiText(gameregion, 22, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + GameRegionTxt->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + GameRegionTxt->SetPosition(THEME.region_x, THEME.region_y); + GameRegionTxt->SetEffect(EFFECT_FADE, 20); + w.Append(GameRegionTxt); + } + } + } + + if ((gameSelected >= 0) && (gameSelected < (s32)gameCnt)) + { + struct discHdr *header = &gameList[gameSelected]; + WBFS_GameSize(header->id, &size); + if (strlen(get_title(header)) < (MAX_CHARACTERS + 3)) { + sprintf(text, "%s", get_title(header)); + } + else { + strncpy(text, get_title(header), MAX_CHARACTERS); + text[MAX_CHARACTERS] = '\0'; + strncat(text, "...", 3); + } + + + bool returnHere = true; + while (returnHere) + { + returnHere = false; + wiilight(1); + choice = GameWindowPrompt(); + header = &gameList[gameSelected]; //reset header + + if(choice == 1) + { + + wiilight(0); + + int ios2 = 0; + switch(iosChoice) + { + case i249: + ios2 = 0; + break; + + case i222: + ios2 = 1; + break; + + default: + ios2 = 0; + break; + } + + if(networkisinitialized == 1 || ios2 == 1 || Settings.cios == ios222) { + + WPAD_Flush(0); + WPAD_Disconnect(0); + WPAD_Shutdown(); + + WDVD_Close(); + + USBStorage_Deinit(); + + if(ios2 == 1) { + IOS_ReloadIOS(222); + } else { + IOS_ReloadIOS(249); + } + + ret = WBFS_Init(WBFS_DEVICE_USB); + + PAD_Init(); + Wpad_Init(); + WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); + WPAD_SetVRes(WPAD_CHAN_ALL, screenwidth, screenheight); + + ret = Disc_Init(); + ret = WBFS_Open(); + + } + + /* Set USB mode */ + ret = Disc_SetUSB(header->id, ios2); + if (ret < 0) { + sprintf(text, "Error: %i", ret); + WindowPrompt( + "Failed to set USB:", + text, + "OK",0); + } + else { + /* Open disc */ + ret = Disc_Open(); + if (ret < 0) { + sprintf(text, "Error: %i", ret); + WindowPrompt( + "Failed to boot:", + text, + "OK",0); + } + else { + menu = MENU_EXIT; + } + } + } + else if (choice == 2) + { + wiilight(0); + if (GameSettings(header) == 1) //if deleted + { + menu = MENU_DISCLIST; + break; + } + returnHere = true; + } + + else if (choice == 3) //&& (CFG.godmode == 1)) + { + wiilight(0); + //enter new game title + char entered[40]; + snprintf(entered, sizeof(entered), "%s", get_title(header)); + entered[39] = '\0'; + OnScreenKeyboard(entered, 40); + WBFS_RenameGame(header->id, entered); + __Menu_GetEntries(); + menu = MENU_DISCLIST; + } + + + else if(choice == 0) + gameBrowser.SetFocus(1); + } + } + } + + HaltGui(); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + delete batteryTxt[i]; + delete batteryImg[i]; + delete batteryBarImg[i]; + delete batteryBtn[i]; + } + #endif + + mainWindow->Remove(&gameBrowser); + mainWindow->Remove(&w); + ResumeGui(); + return menu; +} + +/**************************************************************************** + * MenuFormat + ***************************************************************************/ + +static int MenuFormat() +{ + int menu = MENU_NONE; + char imgPath[100]; + + OptionList options; + partitionEntry partitions[MAX_PARTITIONS]; + + u32 cnt, sector_size, selected = 2000; + int choice, ret; + char text[ISFS_MAXPATH]; + + s32 ret2; + ret2 = Partition_GetEntries(partitions, §or_size); + + //create the partitionlist + for (cnt = 0; cnt < MAX_PARTITIONS; cnt++) { + partitionEntry *entry = &partitions[cnt]; + + /* Calculate size in gigabytes */ + f32 size = entry->size * (sector_size / GB_SIZE); + + if (size) { + sprintf(options.name[cnt], "Partition %d:", cnt+1); + sprintf (options.value[cnt],"%.2fGB", size); + } else { + sprintf(options.name[cnt], "Partition %d:", cnt+1); + sprintf (options.value[cnt],"(Can't be formated)"); + } + } + + options.length = cnt; + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + //btnClick.SetVolume(vol); + //btnSoundOver.SetVolume(vol); + snprintf(imgPath, sizeof(imgPath), "%swiimote_poweroff.png", CFG.theme_path); + GuiImageData btnpwroff(imgPath, wiimote_poweroff_png); + snprintf(imgPath, sizeof(imgPath), "%swiimote_poweroff_over.png", CFG.theme_path); + GuiImageData btnpwroffOver(imgPath, wiimote_poweroff_over_png); + snprintf(imgPath, sizeof(imgPath), "%smenu_button.png", CFG.theme_path); + GuiImageData btnhome(imgPath, menu_button_png); + snprintf(imgPath, sizeof(imgPath), "%smenu_button_over.png", CFG.theme_path); + GuiImageData btnhomeOver(imgPath, menu_button_over_png); + GuiImageData battery(battery_png); + GuiImageData batteryRed(battery_red_png); + GuiImageData batteryBar(battery_bar_png); + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText titleTxt("Select the Partition", 18, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(10,40); + + GuiText titleTxt2("you want to format:", 18, (GXColor){0, 0, 0, 255}); + titleTxt2.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt2.SetPosition(20,60); + + GuiImage poweroffBtnImg(&btnpwroff); + GuiImage poweroffBtnImgOver(&btnpwroffOver); + poweroffBtnImg.SetWidescreen(CFG.widescreen); + poweroffBtnImgOver.SetWidescreen(CFG.widescreen); + GuiButton poweroffBtn(btnpwroff.GetWidth(), btnpwroff.GetHeight()); + poweroffBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + poweroffBtn.SetPosition(THEME.power_x, THEME.power_y); + poweroffBtn.SetImage(&poweroffBtnImg); + poweroffBtn.SetImageOver(&poweroffBtnImgOver); + poweroffBtn.SetSoundOver(&btnSoundOver); + poweroffBtn.SetSoundClick(&btnClick); + poweroffBtn.SetTrigger(&trigA); + poweroffBtn.SetEffectGrow(); + + GuiImage exitBtnImg(&btnhome); + GuiImage exitBtnImgOver(&btnhomeOver); + exitBtnImg.SetWidescreen(CFG.widescreen); + exitBtnImgOver.SetWidescreen(CFG.widescreen); + GuiButton exitBtn(btnhome.GetWidth(), btnhome.GetHeight()); + exitBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + exitBtn.SetPosition(240, 367); + exitBtn.SetImage(&exitBtnImg); + exitBtn.SetImageOver(&exitBtnImgOver); + exitBtn.SetSoundOver(&btnSoundOver); + exitBtn.SetSoundClick(&btnClick); + exitBtn.SetTrigger(&trigA); + exitBtn.SetTrigger(&trigHome); + exitBtn.SetEffectGrow(); + + #ifdef HW_RVL + int i = 0, level; + char txt[3]; + GuiText * batteryTxt[4]; + GuiImage * batteryImg[4]; + GuiImage * batteryBarImg[4]; + GuiButton * batteryBtn[4]; + + for(i=0; i < 4; i++) + { + + if(i == 0) + sprintf(txt, "P%d", i+1); + else + sprintf(txt, "P%d", i+1); + + batteryTxt[i] = new GuiText(txt, 22, (GXColor){THEME.info_r, THEME.info_g, THEME.info_b, 255}); + batteryTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i] = new GuiImage(&battery); + batteryImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i]->SetPosition(36, 0); + batteryImg[i]->SetTile(0); + batteryBarImg[i] = new GuiImage(&batteryBar); + batteryBarImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryBarImg[i]->SetPosition(33, 0); + + batteryBtn[i] = new GuiButton(40, 20); + batteryBtn[i]->SetLabel(batteryTxt[i]); + batteryBtn[i]->SetImage(batteryBarImg[i]); + batteryBtn[i]->SetIcon(batteryImg[i]); + batteryBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + batteryBtn[i]->SetRumble(false); + batteryBtn[i]->SetAlpha(70); + } + + batteryBtn[0]->SetPosition(THEME.battery1_x, THEME.battery1_y); + batteryBtn[1]->SetPosition(THEME.battery2_x, THEME.battery2_y); + batteryBtn[2]->SetPosition(THEME.battery3_x, THEME.battery3_y); + batteryBtn[3]->SetPosition(THEME.battery4_x, THEME.battery4_y); + #endif + + GuiOptionBrowser optionBrowser(THEME.selection_w, THEME.selection_h, &options, CFG.theme_path, bg_options_png, 1, 0); + optionBrowser.SetPosition(THEME.selection_x, THEME.selection_y); + optionBrowser.SetAlignment(ALIGN_LEFT, ALIGN_CENTRE); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&titleTxt2); + w.Append(&poweroffBtn); + w.Append(&exitBtn); + + if (THEME.showBattery) + { + #ifdef HW_RVL + w.Append(batteryBtn[0]); + w.Append(batteryBtn[1]); + w.Append(batteryBtn[2]); + w.Append(batteryBtn[3]); + #endif + } + + mainWindow->Append(&w); + mainWindow->Append(&optionBrowser); + + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) // controller connected + { + level = (userInput[i].wpad.battery_level / 100.0) * 4; + if(level > 4) level = 4; + batteryImg[i]->SetTile(level); + + if(level == 0) + batteryBarImg[i]->SetImage(&batteryRed); + else + batteryBarImg[i]->SetImage(&batteryBar); + + batteryBtn[i]->SetAlpha(255); + } + else // controller not connected + { + batteryImg[i]->SetTile(0); + batteryImg[i]->SetImage(&battery); + batteryBtn[i]->SetAlpha(70); + } + } + #endif + + selected = optionBrowser.GetClickedOption(); + + for (cnt = 0; cnt < MAX_PARTITIONS; cnt++) { + if (cnt == selected) { + partitionEntry *entry = &partitions[selected]; + if (entry->size) { + sprintf(text, "Partition %d : %.2fGB", selected+1, entry->size * (sector_size / GB_SIZE)); + choice = WindowPrompt( + "Do you want to format:", + text, + "Yes", + "No"); + if(choice == 1) { + ret = FormatingPartition("Formatting, please wait...", entry); + if (ret < 0) { + WindowPrompt("Error:","Failed formating","Return",0); + menu = MENU_SETTINGS; + + } else { + WBFS_Open(); + sprintf(text, "%s formated!", text); + WindowPrompt("Success:",text,"OK",0); + menu = MENU_DISCLIST; + } + } + } + } + } + if (shutdown == 1) + Sys_Shutdown(); + + if(poweroffBtn.GetState() == STATE_CLICKED) + { + choice = WindowPrompt ("Shutdown System","Are you sure?","Yes","No"); + if(choice == 1) + { + WPAD_Flush(0); + WPAD_Disconnect(0); + WPAD_Shutdown(); + Sys_Shutdown(); + } + + } else if(exitBtn.GetState() == STATE_CLICKED) + { + choice = WindowPrompt ("Return to Wii Menu","Are you sure?","Yes","No"); + if(choice == 1) + { + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + //exit(0); //zum debuggen schneller + } + } + } + + + HaltGui(); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + delete batteryTxt[i]; + delete batteryImg[i]; + delete batteryBarImg[i]; + delete batteryBtn[i]; + } + #endif + + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + ResumeGui(); + return menu; +} + +/**************************************************************************** + * MenuSettings + ***************************************************************************/ + +static int MenuSettings() +{ + //__Disc_SetLowMem(); + int menu = MENU_NONE; + int ret; + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, vol); + + char imgPath[100]; + + GuiImageData btnOutline(settings_menu_button_png); + snprintf(imgPath, sizeof(imgPath), "%ssettings_background.png", CFG.theme_path); + GuiImageData settingsbg(imgPath, settings_background_png); + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + GuiText titleTxt("Settings", 28, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,40); + + GuiImage settingsbackground(&settingsbg); + GuiButton settingsbackgroundbtn(settingsbackground.GetWidth(), settingsbackground.GetHeight()); + settingsbackgroundbtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + settingsbackgroundbtn.SetPosition(0, 0); + settingsbackgroundbtn.SetImage(&settingsbackground); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + backBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage backBtnImg(&btnOutline); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + backBtn.SetPosition(-180, 400); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnClick); + backBtn.SetTrigger(&trigA); + backBtn.SetTrigger(&trigB); + backBtn.SetEffectGrow(); + + const char * text = "Unlock"; + if (CFG.godmode == 1) + text = "Lock"; + GuiText lockBtnTxt(text, 22, (GXColor){0, 0, 0, 255}); + lockBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage lockBtnImg(&btnOutline); + GuiButton lockBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + lockBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + lockBtn.SetPosition(180, 400); + lockBtn.SetLabel(&lockBtnTxt); + lockBtn.SetImage(&lockBtnImg); + lockBtn.SetSoundOver(&btnSoundOver); + lockBtn.SetSoundClick(&btnClick); + lockBtn.SetTrigger(&trigA); + lockBtn.SetEffectGrow(); + + GuiImageData logo(credits_button_png); + GuiImage logoImg(&logo); + GuiImageData logoOver(credits_button_over_png); + GuiImage logoImgOver(&logoOver); + btnLogo = new GuiButton(logoImg.GetWidth(), logoImg.GetHeight()); + btnLogo->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btnLogo->SetPosition(0, -35); + btnLogo->SetImage(&logoImg); + btnLogo->SetImageOver(&logoImgOver); + btnLogo->SetEffectGrow(); + btnLogo->SetSoundOver(&btnSoundOver); + btnLogo->SetSoundClick(&btnClick); + btnLogo->SetTrigger(&trigA); + btnLogo->SetUpdateCallback(WindowCredits); + + customOptionList options2(9); + GuiCustomOptionBrowser optionBrowser2(396, 280, &options2, CFG.theme_path, "bg_options_settings", bg_options_settings_png, 0); + optionBrowser2.SetPosition(0, 90); + optionBrowser2.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser2.SetCol2Position(150); + GuiWindow w(screenwidth, screenheight); + + int pageToDisplay = 1; + while ( pageToDisplay > 0) //set pageToDisplay to 0 to quit + { + menu = MENU_NONE; + if ( pageToDisplay == 1) + { + sprintf(options2.name[0], "Video Mode"); + sprintf(options2.name[1], "VIDTV Patch"); + sprintf(options2.name[2], "Language"); + sprintf(options2.name[3], "Ocarina"); + sprintf(options2.name[4], "Display"); + sprintf(options2.name[5], "Clock"); //CLOCK + sprintf(options2.name[6], "Rumble"); //RUMBLE + sprintf(options2.name[7], "Volume"); + sprintf(options2.name[8], " "); + + HaltGui(); + w.Append(&settingsbackgroundbtn); + w.Append(&titleTxt); + w.Append(&backBtn); + w.Append(&lockBtn); + w.Append(btnLogo); + + mainWindow->Append(&w); + mainWindow->Append(&optionBrowser2); + + ResumeGui(); + } + else if ( pageToDisplay == 2 ) + { + sprintf(options2.name[0], "Tooltips"); + sprintf(options2.name[1], "Password"); + sprintf(options2.name[2], "Parental Ctrl"); + sprintf(options2.name[3], "Standard cIOS"); + sprintf(options2.name[4], " "); + sprintf(options2.name[5], " "); + sprintf(options2.name[6], " "); + sprintf(options2.name[7], " "); + sprintf(options2.name[8], " "); + + } + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + if ( pageToDisplay == 1 ) + { + if(Settings.video > 5) + Settings.video = 0; + if(Settings.language > 10) + Settings.language = 0; + if(Settings.ocarina > 1) + Settings.ocarina = 0; + if(Settings.vpatch > 1) + Settings.vpatch = 0; + if(Settings.sinfo > 3) + Settings.sinfo = 0; + if(Settings.hddinfo > 1) + Settings.hddinfo = 0; //CLOCK + if(Settings.rumble > 1) + Settings.rumble = 0; //RUMBLE + if(Settings.volume > 10) + Settings.volume = 0; + + if (Settings.video == discdefault) sprintf (options2.value[0],"Disc Default"); + else if (Settings.video == systemdefault) sprintf (options2.value[0],"System Default"); + else if (Settings.video == patch) sprintf (options2.value[0],"Auto Patch"); + else if (Settings.video == pal50) sprintf (options2.value[0],"Force PAL50"); + else if (Settings.video == pal60) sprintf (options2.value[0],"Force PAL60"); + else if (Settings.video == ntsc) sprintf (options2.value[0],"Force NTSC"); + + if (Settings.vpatch == on) sprintf (options2.value[1],"On"); + else if (Settings.vpatch == off) sprintf (options2.value[1],"Off"); + + if (Settings.language == ConsoleLangDefault) sprintf (options2.value[2],"Console Default"); + else if (Settings.language == jap) sprintf (options2.value[2],"Japanese"); + else if (Settings.language == ger) sprintf (options2.value[2],"German"); + else if (Settings.language == eng) sprintf (options2.value[2],"English"); + else if (Settings.language == fren) sprintf (options2.value[2],"French"); + else if (Settings.language == esp) sprintf (options2.value[2],"Spanish"); + else if (Settings.language == it) sprintf (options2.value[2],"Italian"); + else if (Settings.language == dut) sprintf (options2.value[2],"Dutch"); + else if (Settings.language == schin) sprintf (options2.value[2],"S. Chinese"); + else if (Settings.language == tchin) sprintf (options2.value[2],"T. Chinese"); + else if (Settings.language == kor) sprintf (options2.value[2],"Korean"); + + if (Settings.ocarina == on) sprintf (options2.value[3],"On"); + else if (Settings.ocarina == off) sprintf (options2.value[3],"Off"); + + if (Settings.sinfo == GameID) sprintf (options2.value[4],"Game ID"); + else if (Settings.sinfo == GameRegion) sprintf (options2.value[4],"Game Region"); + else if (Settings.sinfo == Both) sprintf (options2.value[4],"Both"); + else if (Settings.sinfo == Neither) sprintf (options2.value[4],"Neither"); + + if (Settings.hddinfo == HDDInfo) sprintf (options2.value[5],"Off"); + else if (Settings.hddinfo == Clock) sprintf (options2.value[5],"On"); + + if (Settings.rumble == RumbleOn) sprintf (options2.value[6],"On"); + else if (Settings.rumble == RumbleOff) sprintf (options2.value[6],"Off"); + + if (Settings.volume == v10) sprintf (options2.value[7],"10"); + else if (Settings.volume == v20) sprintf (options2.value[7],"20"); + else if (Settings.volume == v30) sprintf (options2.value[7],"30"); + else if (Settings.volume == v40) sprintf (options2.value[7],"40"); + else if (Settings.volume == v50) sprintf (options2.value[7],"50"); + else if (Settings.volume == v60) sprintf (options2.value[7],"60"); + else if (Settings.volume == v70) sprintf (options2.value[7],"70"); + else if (Settings.volume == v80) sprintf (options2.value[7],"80"); + else if (Settings.volume == v90) sprintf (options2.value[7],"90"); + else if (Settings.volume == v100) sprintf (options2.value[7],"100"); + else if (Settings.volume == v0) sprintf (options2.value[7],"Off"); + + sprintf(options2.value[8], "Go to page 2"); + + ret = optionBrowser2.GetClickedOption(); + + switch (ret) + { + case 0: + Settings.video++; + break; + case 1: + Settings.vpatch++; + break; + case 2: + Settings.language++; + break; + case 3: + Settings.ocarina++; + break; + case 4: // Game Code and Region + Settings.sinfo++; + break; + case 5: //CLOCK + Settings.hddinfo++; + break; + case 6: //Rumble + Settings.rumble++; + break; + case 7: + Settings.volume++; + break; + case 8: + pageToDisplay = 2; + menu = MENU_EXIT; + break; + } + } + + if ( pageToDisplay == 2 ) + { + if ( Settings.tooltips > 1 ) + Settings.tooltips = 0; + if ( Settings.parentalcontrol > 3 ) + Settings.parentalcontrol = 0; + if ( Settings.cios > 1 ) + Settings.cios = 0; + + if (Settings.tooltips == TooltipsOn) sprintf (options2.value[0],"On"); + else if (Settings.tooltips == TooltipsOff) sprintf (options2.value[0],"Off"); + + if ( CFG.godmode != 1) sprintf(options2.value[1], "********"); + else if (!strcmp("", Settings.unlockCode)) sprintf(options2.value[1], ""); + else sprintf(options2.value[1], Settings.unlockCode); + + + if (Settings.parentalcontrol == ParentalControlOff) sprintf (options2.value[2],"Not yet"); + else if (Settings.parentalcontrol == ParentalControlLevel1) sprintf (options2.value[2],"not working"); + else if (Settings.parentalcontrol == ParentalControlLevel2) sprintf (options2.value[2],"broken"); + else if (Settings.parentalcontrol == ParentalControlLevel3) sprintf (options2.value[2],"coming soon"); + + if (Settings.cios == ios249) sprintf (options2.value[3],"249"); + else if (Settings.cios == ios222) sprintf (options2.value[3],"222"); + + sprintf(options2.value[4], " "); + sprintf(options2.value[5], " "); + sprintf(options2.value[6], " "); + sprintf(options2.value[7], " "); + sprintf(options2.value[8], "Go to page 1"); + + ret = optionBrowser2.GetClickedOption(); + + switch (ret) + { + case 0: + Settings.tooltips++; + break; + case 1: // Modify Password + if ( CFG.godmode == 1) + { + char entered[20] = ""; + strncpy(entered, Settings.unlockCode, sizeof(entered)); + int result = OnScreenKeyboard(entered, 20); + if ( result == 1 ) + { + strncpy(Settings.unlockCode, entered, sizeof(Settings.unlockCode)); + WindowPrompt("Password Changed","Password has been changed","OK",0); + cfg_save_global(); + } + } + else + { + WindowPrompt("Password change","Console should be unlocked to modify it.","OK",0); + } + break; + case 2: + if ( CFG.godmode == 1) + { + Settings.parentalcontrol++; + } + else + { + WindowPrompt("Parental Control","Console should be unlocked to modify it.","OK",0); + } + break; + case 3: + Settings.cios++; + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + + break; + case 8: + pageToDisplay = 1; + menu = MENU_EXIT; + break; + } + } + + if(shutdown == 1) + Sys_Shutdown(); + + if(backBtn.GetState() == STATE_CLICKED) + { + //Add the procedure call to save the global configuration + cfg_save_global(); + menu = MENU_DISCLIST; + pageToDisplay = 0; + break; + } + + if(lockBtn.GetState() == STATE_CLICKED) + { + if (!strcmp("", Settings.unlockCode)) + { + CFG.godmode = !CFG.godmode; + } + else if ( CFG.godmode == 0 ) + { + //password check to unlock Install,Delete and Format + char entered[20] = ""; + int result = OnScreenKeyboard(entered, 20); + if ( result == 1 ) + { + if (!strcmp(entered, Settings.unlockCode)) //if password correct + { + if (CFG.godmode == 0) + { + WindowPrompt("Correct Password","Install, Rename, and Delete are unlocked.","OK",0); + CFG.godmode = 1; + __Menu_GetEntries(); + menu = MENU_DISCLIST; + } + } + else + { + WindowPrompt("Wrong Password","USB Loader is protected.","OK",0); + } + } + } + else + { + int choice = WindowPrompt ("Lock Console","Are you sure?","Yes","No"); + if(choice == 1) + { + WindowPrompt("Console Locked","USB Loader is now protected.","OK",0); + CFG.godmode = 0; + __Menu_GetEntries(); + menu = MENU_DISCLIST; + } + } + if ( CFG.godmode == 1) + { + lockBtnTxt.SetText("Lock"); + } + else + { + lockBtnTxt.SetText("Unlock"); + } + lockBtn.ResetState(); + } + } + + } + HaltGui(); + delete btnLogo; + btnLogo = NULL; + mainWindow->Remove(&optionBrowser2); + mainWindow->Remove(&w); + ResumeGui(); + return menu; +} + + + +/******************************************************************************** +*Game specific settings +*********************************************************************************/ +int GameSettings(struct discHdr * header) +{ + bool exit = false; + int ret; + int retVal = 0; + + char gameName[31]; + + if (strlen(get_title(header)) < (27 + 3)) { + sprintf(gameName, "%s", get_title(header)); + } + else { + strncpy(gameName, get_title(header), 27); + gameName[27] = '\0'; + strncat(gameName, "...", 3); + } + + customOptionList options3(5); + sprintf(options3.name[0], "Video Mode"); + sprintf(options3.name[1], "VIDTV Patch"); + sprintf(options3.name[2], "Language"); + sprintf(options3.name[3], "Ocarina"); + sprintf(options3.name[4], "IOS"); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, vol); + + char imgPath[100]; + + GuiImageData btnOutline(settings_menu_button_png); + snprintf(imgPath, sizeof(imgPath), "%ssettings_background.png", CFG.theme_path); + GuiImageData settingsbg(imgPath, settings_background_png); + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + GuiText titleTxt(gameName, 28, (GXColor){0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,40); + + GuiImage settingsbackground(&settingsbg); + GuiButton settingsbackgroundbtn(settingsbackground.GetWidth(), settingsbackground.GetHeight()); + settingsbackgroundbtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + settingsbackgroundbtn.SetPosition(0, 0); + settingsbackgroundbtn.SetImage(&settingsbackground); + + GuiText saveBtnTxt("Save", 22, (GXColor){0, 0, 0, 255}); + saveBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage saveBtnImg(&btnOutline); + GuiButton saveBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + saveBtn.SetScale(0.9); + saveBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + saveBtn.SetPosition(-180, 400); + saveBtn.SetLabel(&saveBtnTxt); + saveBtn.SetImage(&saveBtnImg); + saveBtn.SetSoundOver(&btnSoundOver); + saveBtn.SetTrigger(&trigA); + saveBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Back", 22, (GXColor){0, 0, 0, 255}); + cancelBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage cancelBtnImg(&btnOutline); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetScale(0.9); + cancelBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + cancelBtn.SetPosition(180, 400); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetTrigger(&trigA); + cancelBtn.SetTrigger(&trigB); + cancelBtn.SetEffectGrow(); + + GuiText deleteBtnTxt("Uninstall", 22, (GXColor){0, 0, 0, 255}); + deleteBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage deleteBtnImg(&btnOutline); + GuiButton deleteBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + deleteBtn.SetScale(0.9); + deleteBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + deleteBtn.SetPosition(0, 400); + deleteBtn.SetLabel(&deleteBtnTxt); + deleteBtn.SetImage(&deleteBtnImg); + deleteBtn.SetSoundOver(&btnSoundOver); + deleteBtn.SetTrigger(&trigA); + deleteBtn.SetEffectGrow(); + + GuiCustomOptionBrowser optionBrowser3(396, 280, &options3, CFG.theme_path, "bg_options_settings", bg_options_settings_png, 0); + optionBrowser3.SetPosition(0, 90); + optionBrowser3.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser3.SetCol2Position(150); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&settingsbackgroundbtn); + w.Append(&titleTxt); + w.Append(&deleteBtn); + w.Append(&saveBtn); + w.Append(&cancelBtn); + + mainWindow->Append(&w); + mainWindow->Append(&optionBrowser3); + + ResumeGui(); + + struct Game_CFG* game_cfg = CFG_get_game_opt(header->id); + + if (game_cfg) + { + videoChoice = game_cfg->video; + languageChoice = game_cfg->language; + ocarinaChoice = game_cfg->ocarina; + viChoice = game_cfg->vipatch; + iosChoice = game_cfg->ios; + } + else + { + videoChoice = Settings.video; + languageChoice = Settings.language; + ocarinaChoice = Settings.ocarina; + viChoice = Settings.vpatch; + if(Settings.cios == ios222) { + iosChoice = i222; + } else { + iosChoice = i249; + } + } + + while(!exit) + { + + VIDEO_WaitVSync (); + + if (videoChoice == discdefault) sprintf (options3.value[0],"Disc Default"); + else if (videoChoice == systemdefault) sprintf (options3.value[0],"System Default"); + else if (videoChoice == patch) sprintf (options3.value[0],"Auto Patch"); + else if (videoChoice == pal50) sprintf (options3.value[0],"Force PAL50"); + else if (videoChoice == pal60) sprintf (options3.value[0],"Force PAL60"); + else if (videoChoice == ntsc) sprintf (options3.value[0],"Force NTSC"); + + if (viChoice == on) sprintf (options3.value[1],"ON"); + else if (viChoice == off) sprintf (options3.value[1],"OFF"); + + if (languageChoice == ConsoleLangDefault) sprintf (options3.value[2],"Console Default"); + else if (languageChoice == jap) sprintf (options3.value[2],"Japanese"); + else if (languageChoice == ger) sprintf (options3.value[2],"German"); + else if (languageChoice == eng) sprintf (options3.value[2],"English"); + else if (languageChoice == fren) sprintf (options3.value[2],"French"); + else if (languageChoice == esp) sprintf (options3.value[2],"Spanish"); + else if (languageChoice == it) sprintf (options3.value[2],"Italian"); + else if (languageChoice == dut) sprintf (options3.value[2],"Dutch"); + else if (languageChoice == schin) sprintf (options3.value[2],"S. Chinese"); + else if (languageChoice == tchin) sprintf (options3.value[2],"T. Chinese"); + else if (languageChoice == kor) sprintf (options3.value[2],"Korean"); + + if (ocarinaChoice == on) sprintf (options3.value[3],"ON"); + else if (ocarinaChoice == off) sprintf (options3.value[3],"OFF"); + + if (iosChoice == i249) sprintf (options3.value[4],"249"); + else if (iosChoice == i222) sprintf (options3.value[4],"222"); + + if(shutdown == 1) + Sys_Shutdown(); + + ret = optionBrowser3.GetClickedOption(); + + switch (ret) + { + case 0: + videoChoice = (videoChoice + 1) % CFG_VIDEO_COUNT; + break; + case 1: + viChoice = (viChoice + 1) % 2; + break; + case 2: + languageChoice = (languageChoice + 1) % CFG_LANG_COUNT; + break; + case 3: + ocarinaChoice = (ocarinaChoice + 1) % 2; + break; + case 4: + iosChoice = (iosChoice + 1) % 2; + break; + } + + if(saveBtn.GetState() == STATE_CLICKED) + { + if (CFG_save_game_opt(header->id)) + { + WindowPrompt("Successfully Saved", 0, "OK", 0); + } + else + { + WindowPrompt("Save Failed", 0, "OK", 0); + } + + saveBtn.ResetState(); + optionBrowser3.SetFocus(1); + } + + if (cancelBtn.GetState() == STATE_CLICKED) + { + exit = true; + break; + } + + if (deleteBtn.GetState() == STATE_CLICKED) + { + int choice = WindowPrompt( + "Do you really want to delete:", + gameName, + "Yes","Cancel"); + + if (choice == 1) + { + ret = WBFS_RemoveGame(header->id); + if (ret < 0) + { + WindowPrompt( + "Can't delete:", + gameName, + "OK",0); + } + else { + __Menu_GetEntries(); + WindowPrompt( + "Successfully deleted:", + gameName, + "OK",0); + retVal = 1; + } + break; + } + else if (choice == 0) + { + deleteBtn.ResetState(); + optionBrowser3.SetFocus(1); + } + + } + } + + HaltGui(); + mainWindow->Remove(&optionBrowser3); + mainWindow->Remove(&w); + ResumeGui(); + return retVal; +} + +/**************************************************************************** + * MenuCheck + ***************************************************************************/ +static int MenuCheck() +{ + int menu = MENU_NONE; + int i = 0; + int choice; + s32 ret2; + OptionList options; + options.length = i; + partitionEntry partitions[MAX_PARTITIONS]; + + VIDEO_WaitVSync (); + + + ret2 = WBFS_Init(WBFS_DEVICE_USB); + if (ret2 < 0) + { + fatUnmount("SD"); + __io_wiisd.shutdown(); + ret2 = DeviceWait("No USB Device:", "Waiting for USB Device 30 secs", 0, 0); + PAD_Init(); + Wpad_Init(); + WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); + WPAD_SetVRes(WPAD_CHAN_ALL, screenwidth, screenheight); + __io_wiisd.startup(); + fatMountSimple("SD", &__io_wiisd); + } + if (ret2 < 0) { + WindowPrompt ("ERROR:","USB-Device not found!", "ok", 0); + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + } else { + PAD_Init(); + Wpad_Init(); + WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); + WPAD_SetVRes(WPAD_CHAN_ALL, screenwidth, screenheight); + __io_wiisd.startup(); + fatMountSimple("SD", &__io_wiisd); + } + + ret2 = Disc_Init(); + if (ret2 < 0) { + WindowPrompt ("Error","Could not initialize DIP module!", "ok", 0); + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + } + + ret2 = WBFS_Open(); + + if (ret2 < 0) { + + choice = WindowPrompt("No WBFS partition found!", + "You need to format a partition.", + "Format", + "Return"); + if(choice == 0) + { + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + + } else { + /* Get partition entries */ + u32 sector_size; + ret2 = Partition_GetEntries(partitions, §or_size); + if (ret2 < 0) { + + WindowPrompt ("No partitions found!",0, "Restart", 0); + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + + } + menu = MENU_FORMAT; + + } + } + + if(shutdown == 1) + Sys_Shutdown(); + + //Spieleliste laden + __Menu_GetEntries(); + + + menu = MENU_DISCLIST; + + + + return menu; +} + +/**************************************************************************** + * MainMenu + ***************************************************************************/ +int MainMenu(int menu) +{ + + int currentMenu = menu; + char imgPath[100]; + + #ifdef HW_RVL + snprintf(imgPath, sizeof(imgPath), "%splayer1_point.png", CFG.theme_path); + pointer[0] = new GuiImageData(imgPath, player1_point_png); + snprintf(imgPath, sizeof(imgPath), "%splayer2_point.png", CFG.theme_path); + pointer[1] = new GuiImageData(imgPath, player2_point_png); + snprintf(imgPath, sizeof(imgPath), "%splayer3_point.png", CFG.theme_path); + pointer[2] = new GuiImageData(imgPath, player3_point_png); + snprintf(imgPath, sizeof(imgPath), "%splayer4_point.png", CFG.theme_path); + pointer[3] = new GuiImageData(imgPath, player4_point_png); + #endif + + mainWindow = new GuiWindow(screenwidth, screenheight); + + if (CFG.widescreen) + snprintf(imgPath, sizeof(imgPath), "%swbackground.png", CFG.theme_path); + else + snprintf(imgPath, sizeof(imgPath), "%sbackground.png", CFG.theme_path); + + background = new GuiImageData(imgPath, CFG.widescreen? wbackground_png : background_png); + + bgImg = new GuiImage(background); + mainWindow->Append(bgImg); + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + ResumeGui(); + + bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, SOUND_OGG, vol); + bgMusic->SetVolume(vol); + bgMusic->SetLoop(1); //loop music + bgMusic->Play(); // startup music + + while(currentMenu != MENU_EXIT) + { + bgMusic->SetVolume(vol); + switch (currentMenu) + { + case MENU_CHECK: + currentMenu = MenuCheck(); + break; + case MENU_FORMAT: + currentMenu = MenuFormat(); + break; + case MENU_INSTALL: + currentMenu = MenuInstall(); + break; + case MENU_SETTINGS: + currentMenu = MenuSettings(); + break; + case MENU_DISCLIST: + currentMenu = MenuDiscList(); + break; + default: // unrecognized menu + currentMenu = MenuCheck(); + break; + } + + switch (Settings.volume) + { + case v10: + vol = 10; + break; + case v20: + vol = 20; + break; + case v30: + vol = 30; + break; + case v40: + vol = 40; + break; + case v50: + vol = 50; + break; + case v60: + vol = 60; + break; + case v70: + vol = 70; + break; + case v80: + vol = 80; + break; + case v90: + vol = 90; + break; + case v100: + vol = 100; + break; + case v0: + vol = 0; + break; + default: + vol = 80; + break; + } + + } + + + bgMusic->Stop(); + delete bgMusic; + delete background; + delete bgImg; + delete mainWindow; + delete pointer[0]; + delete pointer[1]; + delete pointer[2]; + delete pointer[3]; + + delete cover; + delete coverImg; + + mainWindow = NULL; + fatUnmount("SD"); + __io_wiisd.shutdown(); + ExitApp(); + + struct discHdr *header = &gameList[gameSelected]; + struct Game_CFG* game_cfg = CFG_get_game_opt(header->id); + + if (game_cfg) + { + videoChoice = game_cfg->video; + languageChoice = game_cfg->language; + ocarinaChoice = game_cfg->ocarina; + viChoice = game_cfg->vipatch; + iosChoice = game_cfg->ios; + } + else + { + videoChoice = Settings.video; + languageChoice = Settings.language; + ocarinaChoice = Settings.ocarina; + viChoice = Settings.vpatch; + iosChoice = i249; + } + + switch(languageChoice) + { + case ConsoleLangDefault: + configbytes[0] = 0xCD; + break; + + case jap: + configbytes[0] = 0x00; + break; + + case eng: + configbytes[0] = 0x01; + break; + + case ger: + configbytes[0] = 0x02; + break; + + case fren: + configbytes[0] = 0x03; + break; + + case esp: + configbytes[0] = 0x04; + break; + + case it: + configbytes[0] = 0x05; + break; + + case dut: + configbytes[0] = 0x06; + break; + + case schin: + configbytes[0] = 0x07; + break; + + case tchin: + configbytes[0] = 0x08; + break; + + case kor: + configbytes[0] = 0x09; + break; + //wenn nicht genau klar ist welches + default: + configbytes[0] = 0xCD; + break; + } + + u32 videoselected = 0; + + switch(videoChoice) + { + case discdefault: + videoselected = 0; + break; + + case pal50: + videoselected = 1; + break; + + case pal60: + videoselected = 2; + break; + + case ntsc: + videoselected = 3; + + case systemdefault: + + videoselected = 4; + break; + case patch: + + videoselected = 5; + break; + default: + videoselected = 3; + break; + } + + u32 cheat = 0; + switch(ocarinaChoice) + { + case on: + cheat = 1; + break; + + case off: + cheat = 0; + break; + + default: + cheat = 1; + break; + } + + u8 vipatch = 0; + switch(viChoice) + { + case on: + vipatch = 1; + break; + + case off: + vipatch = 0; + break; + + default: + vipatch = 0; + break; + } + + int ret = 0; + ret = Disc_WiiBoot(videoselected, cheat, vipatch); + if (ret < 0) { + printf(" ERROR: BOOT ERROR! (ret = %d)\n", ret); + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + } + + return 0; +} diff --git a/source/menu.h b/source/menu.h new file mode 100644 index 00000000..7e8bd317 --- /dev/null +++ b/source/menu.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * menu.h + * Menu flow routines - handles all menu logic + ***************************************************************************/ + +#ifndef _MENU_H_ +#define _MENU_H_ + +#include + +void InitGUIThreads(); +int MainMenu (int menuitem); +void wiilight(int enable); +int GameSettings(struct discHdr *); +enum +{ + MENU_EXIT = -1, + MENU_NONE, + MENU_SETTINGS, + MENU_DISCLIST, + MENU_FORMAT, + MENU_INSTALL, + MENU_CHECK, + MENU_GAME_SETTINGS +}; + +#endif diff --git a/source/oggplayer.c b/source/oggplayer.c new file mode 100644 index 00000000..6e562e17 --- /dev/null +++ b/source/oggplayer.c @@ -0,0 +1,350 @@ +/* + Copyright (c) 2008 Francisco Muñoz 'Hermes' + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are + permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + - The names of the contributors may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oggplayer.h" +#include + +/* OGG control */ + +#define READ_SAMPLES 4096 // samples that it must read before to send +#define MAX_PCMOUT 4096 // minimum size to read ogg samples +typedef struct +{ + OggVorbis_File vf; + vorbis_info *vi; + int current_section; + + // OGG file operation + int fd; + int mode; + int eof; + int flag; + int volume; + int seek_time; + + /* OGG buffer control */ + short pcmout[2][READ_SAMPLES + MAX_PCMOUT * 2]; /* take 4k out of the data segment, not the stack */ + int pcmout_pos; + int pcm_indx; + +} private_data_ogg; + +static private_data_ogg private_ogg; + +// OGG thread control + +#define STACKSIZE 8192 + +static u8 oggplayer_stack[STACKSIZE]; +static lwpq_t oggplayer_queue; +static lwp_t h_oggplayer; +static int ogg_thread_running = 0; + +static void ogg_add_callback(int voice) +{ + if (ogg_thread_running <= 0) + { + SND_StopVoice(0); + return; + } + + if (private_ogg.flag & 128) + return; // Ogg is paused + + if (private_ogg.pcm_indx >= READ_SAMPLES) + { + if (SND_AddVoice(0, + (void *) private_ogg.pcmout[private_ogg.pcmout_pos], + private_ogg.pcm_indx << 1) == 0) + { + private_ogg.pcmout_pos ^= 1; + private_ogg.pcm_indx = 0; + private_ogg.flag = 0; + LWP_ThreadSignal(oggplayer_queue); + } + } + else + { + if (private_ogg.flag & 64) + { + private_ogg.flag &= ~64; + LWP_ThreadSignal(oggplayer_queue); + } + } +} + +static void * ogg_player_thread(private_data_ogg * priv) +{ + int first_time = 1; + + ogg_thread_running = 0; + //init + LWP_InitQueue(&oggplayer_queue); + + priv[0].vi = ov_info(&priv[0].vf, -1); + + SND_Pause(0); + + priv[0].pcm_indx = 0; + priv[0].pcmout_pos = 0; + priv[0].eof = 0; + priv[0].flag = 0; + priv[0].current_section = 0; + + ogg_thread_running = 1; + + while (!priv[0].eof) + { + long ret; + if (ogg_thread_running <= 0) + break; + + if (priv[0].flag) + LWP_ThreadSleep(oggplayer_queue); // wait only when i have samples to send + + if (ogg_thread_running <= 0) + break; + + if (priv[0].flag == 0) // wait to all samples are sended + { + if (SND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos]) + && SND_StatusVoice(0) != SND_UNUSED) + { + priv[0].flag |= 64; + continue; + } + if (priv[0].pcm_indx < READ_SAMPLES) + { + priv[0].flag = 3; + + if (priv[0].seek_time >= 0) + { + ov_time_seek(&priv[0].vf, priv[0].seek_time); + priv[0].seek_time = -1; + } + + ret + = ov_read( + &priv[0].vf, + (void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx], + MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section); + priv[0].flag &= 192; + if (ret == 0) + { + /* EOF */ + if (priv[0].mode & 1) + ov_time_seek(&priv[0].vf, 0); // repeat + else + priv[0].eof = 1; // stops + // + } + else if (ret < 0) + { + /* error in the stream. Not a problem, just reporting it in + case we (the app) cares. In this case, we don't. */ + if (ret != OV_HOLE) + { + if (priv[0].mode & 1) + ov_time_seek(&priv[0].vf, 0); // repeat + else + priv[0].eof = 1; // stops + } + } + else + { + /* we don't bother dealing with sample rate changes, etc, but + you'll have to*/ + priv[0].pcm_indx += ret >> 1; //get 16 bits samples + } + } + else + priv[0].flag = 1; + } + + if (priv[0].flag == 1) + { + if (SND_StatusVoice(0) == SND_UNUSED || first_time) + { + first_time = 0; + if (priv[0].vi->channels == 2) + { + SND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0, + (void *) priv[0].pcmout[priv[0].pcmout_pos], + priv[0].pcm_indx << 1, priv[0].volume, + priv[0].volume, ogg_add_callback); + priv[0].pcmout_pos ^= 1; + priv[0].pcm_indx = 0; + priv[0].flag = 0; + } + else + { + SND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0, + (void *) priv[0].pcmout[priv[0].pcmout_pos], + priv[0].pcm_indx << 1, priv[0].volume, + priv[0].volume, ogg_add_callback); + priv[0].pcmout_pos ^= 1; + priv[0].pcm_indx = 0; + priv[0].flag = 0; + } + } + else + { + // if(priv[0].pcm_indx==0) priv[0].flag=0; // all samples sended + } + + } + + } + ov_clear(&priv[0].vf); + priv[0].fd = -1; + priv[0].pcm_indx = 0; + ogg_thread_running = 0; + + return 0; +} + +void StopOgg() +{ + SND_StopVoice(0); + if (ogg_thread_running > 0) + { + ogg_thread_running = -2; + LWP_ThreadSignal(oggplayer_queue); + LWP_JoinThread(h_oggplayer, NULL); + + while (((volatile int) ogg_thread_running) != 0) + { + ;;; + } + } +} + +int PlayOgg(int fd, int time_pos, int mode) +{ + StopOgg(); + + ogg_thread_running = 0; + + private_ogg.fd = fd; + private_ogg.mode = mode; + private_ogg.eof = 0; + private_ogg.volume = 127; + private_ogg.flag = 0; + private_ogg.seek_time = -1; + + if (time_pos > 0) + private_ogg.seek_time = time_pos; + + if (fd < 0) + { + private_ogg.fd = -1; + return -1; + } + if (ov_open((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0) < 0) + { + mem_close(private_ogg.fd); // mem_close() can too close files from devices + private_ogg.fd = -1; + ogg_thread_running = -1; + return -1; + } + + if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread, + &private_ogg, oggplayer_stack, STACKSIZE, 80) == -1) + { + ogg_thread_running = -1; + ov_clear(&private_ogg.vf); + private_ogg.fd = -1; + return -1; + } + LWP_ThreadSignal(oggplayer_queue); + while (((volatile int) ogg_thread_running) == 0) + { + ;;; + } + return 0; +} + +void PauseOgg(int pause) +{ + if (pause) + { + private_ogg.flag |= 128; + } + else + { + if (private_ogg.flag & 128) + { + private_ogg.flag |= 64; + private_ogg.flag &= ~128; + if (ogg_thread_running > 0) + { + LWP_ThreadSignal(oggplayer_queue); + // while(((volatile int )private_ogg.flag)!=1 && ((volatile int )ogg_thread_running)>0) {;;;} + } + } + + } +} + +int StatusOgg() +{ + if (ogg_thread_running <= 0) + return -1; // Error + + if (private_ogg.eof) + return 255; // EOF + + if (private_ogg.flag & 128) + return 2; // paused + return 1; // running +} + +void SetVolumeOgg(int volume) +{ + private_ogg.volume = volume; + + SND_ChangeVolumeVoice(0, volume, volume); +} + +s32 GetTimeOgg() +{ + int ret; + if (ogg_thread_running <= 0) + return 0; + if (private_ogg.fd < 0) + return 0; + ret = ((s32) ov_time_tell(&private_ogg.vf)); + if (ret < 0) + ret = 0; + + return ret; +} + +void SetTimeOgg(s32 time_pos) +{ + if (time_pos >= 0) + private_ogg.seek_time = time_pos; +} diff --git a/source/oggplayer.h b/source/oggplayer.h new file mode 100644 index 00000000..5c4610d1 --- /dev/null +++ b/source/oggplayer.h @@ -0,0 +1,170 @@ +/* + Copyright (c) 2008 Francisco Muñoz 'Hermes' + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are + permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + - The names of the contributors may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OGGPLAYER_H__ +#define __OGGPLAYER_H__ + +#include +#include "tremor/ivorbiscodec.h" +#include "tremor/ivorbisfile.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define OGG_ONE_TIME 0 +#define OGG_INFINITE_TIME 1 + +#define OGG_STATUS_RUNNING 1 +#define OGG_STATUS_ERR -1 +#define OGG_STATUS_PAUSED 2 +#define OGG_STATUS_EOF 255 + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* Player OGG functions */ +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +/* int PlayOgg(int fd, int time_pos, int mode); + + Play an Ogg file. This file can be loaded from memory (mem_open(void *ogg, int size_ogg)) or from device with open("device:file.ogg",O_RDONLY,0); + + NOTE: The file is closed by the player when you call PlayOgg(), StopOgg() or if it fail. + + -- Params --- + + fd: file descriptor from open() or mem_open() + + time_pos: initial time position in the file (in milliseconds). For example, use 30000 to advance 30 seconds + + mode: Use OGG_ONE_TIME or OGG_INFINITE_TIME. When you use OGG_ONE_TIME the sound stops and StatusOgg() return OGG_STATUS_EOF + + return: 0- Ok, -1 Error + + */ + +int PlayOgg(int fd, int time_pos, int mode); + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +/* void StopOgg(); + + Stop an Ogg file. + + NOTE: The file is closed and the player thread is released + + -- Params --- + + + */ + +void StopOgg(); + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +/* void PauseOgg(int pause); + + Pause an Ogg file. + + -- Params --- + + pause: 0 -> continue, 1-> pause + + */ + +void PauseOgg(int pause); + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +/* int StatusOgg(); + + Return the Ogg status + + -- Params --- + + + return: OGG_STATUS_RUNNING + OGG_STATUS_ERR -> not initialized? + OGG_STATUS_PAUSED + OGG_STATUS_EOF -> player stopped by End Of File + + */ + +int StatusOgg(); + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +/* void SetVolumeOgg(int volume); + + Set the Ogg playing volume. + NOTE: it change the volume of voice 0 (used for the Ogg player) + + -- Params --- + + volume: 0 to 255 (max) + + */ + +void SetVolumeOgg(int volume); + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +/* s32 GetTimeOgg(); + + Return the Ogg time from the starts of the file + + -- Params --- + + return: 0 -> Ok or error condition (you must ignore this value) + >0 -> time in milliseconds from the starts + + */ + +s32 GetTimeOgg(); + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +/* void SetTimeOgg(s32 time_pos); + + Set the time position + + NOTE: The file is closed by the player when you call PlayOgg(), StopOgg() or if it fail. + + -- Params --- + + time_pos: time position in the file (in milliseconds). For example, use 30000 to advance 30 seconds + + */ + +void SetTimeOgg(s32 time_pos); + +/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/partition.c b/source/partition.c new file mode 100644 index 00000000..32dc5711 --- /dev/null +++ b/source/partition.c @@ -0,0 +1,51 @@ +#include +#include +#include + +#include "partition.h" +#include "usbstorage.h" +#include "utils.h" + +/* 'partition table' structure */ +typedef struct { + /* Zero bytes */ + u8 padding[446]; + + /* Partition table entries */ + partitionEntry entries[MAX_PARTITIONS]; +} ATTRIBUTE_PACKED partitionTable; + + +s32 Partition_GetEntries(partitionEntry *outbuf, u32 *outval) +{ + static partitionTable table ATTRIBUTE_ALIGN(32); + + u32 cnt, sector_size; + s32 ret; + + /* Get sector size */ + ret = USBStorage_GetCapacity(§or_size); + if (ret < 0) + return ret; + + /* Read partition table */ + ret = USBStorage_ReadSectors(0, 1, &table); + if (ret < 0) + return ret; + + /* Swap endianess */ + for (cnt = 0; cnt < 4; cnt++) { + partitionEntry *entry = &table.entries[cnt]; + + entry->sector = swap32(entry->sector); + entry->size = swap32(entry->size); + } + + /* Set partition entries */ + memcpy(outbuf, table.entries, sizeof(table.entries)); + + /* Set sector size */ + *outval = sector_size; + + return 0; +} diff --git a/source/partition.h b/source/partition.h new file mode 100644 index 00000000..113fe6c0 --- /dev/null +++ b/source/partition.h @@ -0,0 +1,42 @@ +#ifndef _PARTITION_H_ +#define _PARTITION_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* 'partition entry' structure */ +typedef struct { + /* Boot indicator */ + u8 boot; + + /* Starting CHS */ + u8 start[3]; + + /* Partition type */ + u8 type; + + /* Ending CHS */ + u8 end[3]; + + /* Partition sector */ + u32 sector; + + /* Partition size */ + u32 size; +} ATTRIBUTE_PACKED partitionEntry; + +/* Constants */ +#define MAX_PARTITIONS 4 + +/* Prototypes */ +s32 Partition_GetEntries(partitionEntry *, u32 *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/patchcode.c b/source/patchcode.c new file mode 100644 index 00000000..51a6a1bc --- /dev/null +++ b/source/patchcode.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2008 Nuke (wiinuke@gmail.com) + * + * this file is part of GeckoOS for USB Gecko + * http://www.usbgecko.com + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "geckomenu.h" +#include "apploader.h" +#include "patchcode.h" +#include "fwrite_patch.h" + +extern void patchhook(u32 address, u32 len); +extern void patchhook2(u32 address, u32 len); +extern void patchhook3(u32 address, u32 len); +extern void patchhook4(u32 address, u32 len); +extern void multidolpatchone(u32 address, u32 len); +extern void multidolpatchtwo(u32 address, u32 len); + +extern void regionfreejap(u32 address, u32 len); +extern void regionfreeusa(u32 address, u32 len); +extern void regionfreepal(u32 address, u32 len); + +extern void removehealthcheck(u32 address, u32 len); + +extern void copyflagcheck1(u32 address, u32 len); +extern void copyflagcheck2(u32 address, u32 len); +extern void copyflagcheck3(u32 address, u32 len); +extern void copyflagcheck4(u32 address, u32 len); +extern void copyflagcheck5(u32 address, u32 len); + +extern void patchupdatecheck(u32 address, u32 len); + +extern void movedvdhooks(u32 address, u32 len); + + +extern void patchhookdol(u32 address, u32 len); +extern void langvipatch(u32 address, u32 len, u8 langbyte); +extern void vipatch(u32 address, u32 len); +extern u32 regionfreeselect; + +static const u32 viwiihooks[4] = { + 0x7CE33B78,0x38870034,0x38A70038,0x38C7004C +}; + +static const u32 multidolpatch1[2] = { + 0x3C03FFB4,0x28004F43 +}; + +static const u32 healthcheckhook[2] = { + 0x41810010,0x881D007D +}; + +static const u32 updatecheckhook[3] = { + 0x80650050,0x80850054,0xA0A50058 +}; + +static const u32 multidolpatch2[2] = { + 0x3F608000, 0x807B0018 +}; + +static const u32 recoveryhooks[3] = { + 0xA00100AC,0x5400073E,0x2C00000F +}; + +static const u32 nocopyflag1[3] = { + 0x540007FF, 0x4182001C, 0x80630068 +}; + +static const u32 nocopyflag2[3] = { + 0x540007FF, 0x41820024, 0x387E12E2 +}; + +// this one is for the GH3 and VC saves +//static const u32 nocopyflag3[5] = { +// 0x2C030000, 0x40820010, 0x88010020, 0x28000002, 0x41820234 +//}; + +static const u32 nocopyflag3[5] = { + 0x2C030000, 0x41820200,0x48000058,0x38610100 +}; +// this removes the display warning for no copy VC and GH3 saves +static const u32 nocopyflag4[4] = { + 0x80010008, 0x2C000000, 0x4182000C, 0x3BE00001 +}; + +static const u32 nocopyflag5[3] = { + 0x801D0024,0x540007FF,0x41820024 +}; + +static const u32 movedvdpatch[3] = { + 0x2C040000, 0x41820120, 0x3C608109 +}; + + + +static const u32 regionfreehooks[5] = { + 0x7C600774, 0x2C000001, 0x41820030,0x40800010,0x2C000000 +}; + +static const u32 fwritepatch[8] = { + 0x9421FFD0,0x7C0802A6,0x90010034,0xBF210014,0x7C9B2378,0x7CDC3378,0x7C7A1B78,0x7CB92B78 // bushing fwrite +}; + +static const u32 kpadhooks[4] = { + 0x9A3F005E,0x38AE0080,0x389FFFFC,0x7E0903A6 +}; + +static const u32 kpadoldhooks[6] = { + 0x801D0060, 0x901E0060, 0x801D0064, 0x901E0064, 0x801D0068, 0x901E0068 +}; + +static const u32 joypadhooks[4] = { + 0x3AB50001, 0x3A73000C, 0x2C150004, 0x3B18000C +}; + +static const u32 langpatch[3] = { + 0x7C600775, 0x40820010, 0x38000000 +}; + +static const u32 vipatchcode[3] = { + 0x4182000C,0x4180001C,0x48000018 +}; + +static const u32 wpadlibogc[5] = { +// 0x38A00140, 0x7C095878, 0x7D600078, 0x901F0010,0x913F0014 +// 0x7FA00124, 0x8001001C, 0x83810008, 0x83A1000C,0x7C0803A6 + 0x90A402E0,0x806502E4,0x908502E4,0x2C030000,0x906402E4 +}; + +void dogamehooks(void *addr, u32 len) +{ + void *addr_start = addr; + void *addr_end = addr+len; + + while(addr_start < addr_end) + { + + switch(hooktype) + { + + case 0: + + break; + + case 1: + if(memcmp(addr_start, viwiihooks, sizeof(viwiihooks))==0){ + // printf("\n\n\n"); + // printf("found at address %x\n", addr_start); + // sleep(2); + patchhook((u32)addr_start, len); + patched = 1; + hooktype = 1; + } + break; + +/* + case 2: + if(memcmp(addr_start, kpadhooks, sizeof(kpadhooks))==0){ + patchhook((u32)addr_start, len); + patched = 1; + } + + if(memcmp(addr_start, kpadoldhooks, sizeof(kpadoldhooks))==0){ + patchhook((u32)addr_start, len); + patched = 1; + } + break; + + case 3: + if(memcmp(addr_start, joypadhooks, sizeof(joypadhooks))==0){ + patchhook((u32)addr_start, len); + patched = 1; + } + break; + + case 4: + if(memcmp(addr_start, recoveryhooks, sizeof(recoveryhooks))==0){ + patchhook3((u32)addr_start, len); + } + break; +*/ + case 2: + + if(memcmp(addr_start, viwiihooks, sizeof(viwiihooks))==0){ + patchhook2((u32)addr_start, len); + } + + break; + +/* + case 6: + // jap region free + if(memcmp(addr_start, regionfreehooks, sizeof(regionfreehooks))==0){ + regionfreejap((u32)addr_start, len); + } + + // usa region free + if(memcmp(addr_start, regionfreehooks, sizeof(regionfreehooks))==0){ + regionfreeusa((u32)addr_start, len); + } + + // pal region free + if(memcmp(addr_start, regionfreehooks, sizeof(regionfreehooks))==0){ + regionfreepal((u32)addr_start, len); + } + + // skip disc update + if(memcmp(addr_start, updatecheckhook, sizeof(updatecheckhook))==0){ + patchupdatecheck((u32)addr_start, len); + } + break; + + + case 7: + if(memcmp(addr_start, healthcheckhook, sizeof(healthcheckhook))==0){ + removehealthcheck((u32)addr_start, len); + } + break; + + // no copy flags + case 8: + // Remove the actual flag so can copy back + if(memcmp(addr_start, nocopyflag5, sizeof(nocopyflag5))==0){ + copyflagcheck5((u32)addr_start, len); + } + + + if(memcmp(addr_start, nocopyflag1, sizeof(nocopyflag1))==0){ + copyflagcheck1((u32)addr_start, len); + } + + if(memcmp(addr_start, nocopyflag2, sizeof(nocopyflag2))==0){ + copyflagcheck2((u32)addr_start, len); + } + + // no VC and GH3 save + if(memcmp(addr_start, nocopyflag3, sizeof(nocopyflag2))==0){ + copyflagcheck3((u32)addr_start, len); + } + // no VC and GH3 save display remove + if(memcmp(addr_start, nocopyflag4, sizeof(nocopyflag4))==0){ + copyflagcheck4((u32)addr_start, len); + } + + break; + + case 9: + if(memcmp(addr_start, movedvdpatch, sizeof(movedvdpatch))==0){ + movedvdhooks((u32)addr_start, len); + } + break; +*/ + // multidol + case 3: + + if(memcmp(addr_start, multidolpatch1, sizeof(multidolpatch1))==0){ + multidolpatchone((u32)addr_start, len); + } + if(memcmp(addr_start, multidolpatch2, sizeof(multidolpatch2))==0){ + multidolpatchtwo((u32)addr_start, len); + } + break; + } + addr_start += 4; + } +} + +// Not used yet, for patching DOL once loaded into memory and befor execution +void patchdol(void *addr, u32 len) +{ + + void *addr_start = addr; + void *addr_end = addr+len; + + while(addr_start < addr_end) + { + if(memcmp(addr_start, wpadlibogc, sizeof(wpadlibogc))==0) { + // printf("\n\n\n"); + // printf("found at address %x\n", addr_start); + // sleep(10); + // patchhookdol((u32)addr_start, len); + patched = 1; + break; + } + addr_start += 4; + } +} + +void langpatcher(void *addr, u32 len) +{ + + void *addr_start = addr; + void *addr_end = addr+len; + + while(addr_start < addr_end) + { + + if(memcmp(addr_start, langpatch, sizeof(langpatch))==0) { + if(configbytes[0] != 0xCD){ + langvipatch((u32)addr_start, len, configbytes[0]); + } + } + addr_start += 4; + } +} + +void patchdebug(void *addr, u32 len) +{ + + void *addr_start = addr; + void *addr_end = addr+len; + + while(addr_start < addr_end) + { + + if(memcmp(addr_start, fwritepatch, sizeof(fwritepatch))==0) { + + memcpy(addr_start,fwrite_patch_bin,fwrite_patch_bin_len); + // apply patch + } + addr_start += 4; + } +} + +void vidolpatcher(void *addr, u32 len) +{ + + void *addr_start = addr; + void *addr_end = addr+len; + + while(addr_start < addr_end) + { + if(memcmp(addr_start, vipatchcode, sizeof(vipatchcode))==0) { + vipatch((u32)addr_start, len); + } + addr_start += 4; + } +} + + diff --git a/source/patchcode.h b/source/patchcode.h new file mode 100644 index 00000000..381fcaa9 --- /dev/null +++ b/source/patchcode.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008 Nuke (wiinuke@gmail.com) + * + * this file is part of GeckoOS for USB Gecko + * http://www.usbgecko.com + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PATCHCODE_H__ +#define __PATCHCODE_H__ +#ifdef __cplusplus +extern "C" +{ +#endif +// Globals +u32 hooktype; +int patched; +u8 configbytes[2]; +u32 regionfree; + +// Function prototypes +void dogamehooks(void *addr, u32 len); +void langpatcher(void *addr, u32 len); +void vidolpatcher(void *addr, u32 len); +void patchdebug(void *addr, u32 len); + + + +#ifdef __cplusplus +} +#endif + +#endif // __PATCHCODE_H__ diff --git a/source/patchhook.S b/source/patchhook.S new file mode 100644 index 00000000..bddd9b7c --- /dev/null +++ b/source/patchhook.S @@ -0,0 +1,508 @@ + + # (c) Nuke www.usbgecko.com. Licensed under GPL V2 +.text +#include "ppc.h" + + +.globl patchhook # r3 address +patchhook: + mtctr r4 + lis r6, 0x4E80 + ori r6, r6, 0x0020 # blr +findblr: + lwz r5, 0(r3) + cmpw r6, r5 + beq writebranch + addi r3, r3, 4 # next word + bdnz findblr # loop length + b exit # stop unhooked game hanging + +writebranch: + lis r4, 0x8000 # 800018A0 hook location (source) + ori r4, r4, 0x18A8 + subf r4, r3, r4 # subtract r3 from r4 and place in r4 + lis r5, 0x3FF + ori r5, r5, 0xFFFF # 0x3FFFFFF + and r4, r4, r5 + lis r5, 0x4800 # 0x48000000 + or r4, r4, r5 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exit: + blr # return + +.globl patchhook2 # r3 address +patchhook2: + mtctr r4 + lis r6, 0x4E80 + ori r6, r6, 0x0020 # blr +findblr2: + lwz r5, 0(r3) + cmpw r6, r5 + beq writebranch2 + addi r3, r3, 4 # next word + bdnz findblr2 # loop length + b exit2 # stop unhooked game hanging + +writebranch2: + lis r4, 0x8000 # 81700000 our temp patcher + ori r4, r4, 0x18a8 + subf r4, r3, r4 # subtract r3 from r4 and place in r4 + lis r5, 0x3FF + ori r5, r5, 0xFFFF # 0x3FFFFFF + and r4, r4, r5 + lis r5, 0x4800 # 0x48000000 + or r4, r4, r5 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exit2: + blr # return + +.globl patchhook3 # r3 address +patchhook3: + mtctr r4 + lis r6, 0x4BFF + ori r6, r6, 0xE955 # blr +findbne: + lwz r5, 0(r3) + cmpw r6, r5 + beq writebl + addi r3, r3, 4 # next word + bdnz findbne # loop length + b exit3 # stop unhooked game hanging + +writebl: + lis r4, 0x4BFF # 81700000 our temp patcher + ori r4, r4, 0xEA91 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exit3: + blr # return + +.globl patchhook4 # r3 address +patchhook4: + mtctr r4 + lis r6, 0x4082 + ori r6, r6, 0x001C # blr +findregion: + lwz r5, 0(r3) + cmpw r6, r5 + beq writebr + addi r3, r3, 4 # next word + bdnz findregion # loop length + b exit4 # stop unhooked game hanging + +writebr: + lis r4, 0x4800 + ori r4, r4, 0x001C + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exit4: + blr # return + +.globl multidolpatchone # r3 address +multidolpatchone: + mtctr r4 + lis r6, 0x3800 + ori r6, r6, 0x0001 # (li r0,1) +findmulti: + lwz r5, 0(r3) + cmpw r6, r5 + beq writemulti + subi r3, r3, 4 # go back + bdnz findmulti # loop length + b exit5 # stop unhooked game hanging + +writemulti: + lis r4, 0x8170 # 81700000 + ori r4, r4, 0x0020 + subf r18, r3, r4 # subf r18,(source),(dest) + lis r6, 0x4800 + ori r6,r6,1 + rlwimi r6,r18,0,6,29 + stw r6,0(r3) + stw r6,0(r19) + stw r3,4(r19) + dcbf r0, r3 + sync + icbi r0, r3 + isync +exit5: + blr # return + +.globl multidolpatchtwo # r3 address +multidolpatchtwo: + mtctr r4 + lis r6, 0x3F60 + ori r6, r6, 0x8000 # (lis r27,-32768) +findmulti2: + lwz r5, 0(r3) + cmpw r6, r5 + beq writemulti2 + addi r3, r3, 4 # go forward + bdnz findmulti2 # loop length + b exit6 # stop unhooked game hanging + +writemulti2: + lis r4, 0x8170 # 81700020 + ori r4, r4, 0x0000 + subf r18, r3, r4 # subf r18,(source),(dest) + lis r6, 0x4800 + ori r6,r6,1 + rlwimi r6,r18,0,6,29 + stw r6,0(r3) + stw r6,0(r19) + stw r3,4(r19) + dcbf r0, r3 + sync + icbi r0, r3 + isync +exit6: + blr # return + +.globl langvipatch # r3 address, r4 len, r5 lang byte +langvipatch: + mtctr r4 + lis r6, 0x8861 + ori r6, r6, 0x0008 # lbz r3, 8(sp) +findlang: + lwz r7, 0(r3) + cmpw r6, r7 + beq patchlang + addi r3, r3, 4 # next word + bdnz findlang # loop length + b exitlang # stop unhooked game hanging + +patchlang: + + lis r4, 0x3860 # 0x38600001 li %r3, 1 # eng + add r4, r4, r5 +gofinal: + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitlang: + blr # return + +.globl vipatch # r3 address +vipatch: + mtctr r4 + lis r6, 0x5400 + ori r6, r6, 0xFFFE +findvi: + lwz r5, 0(r3) + cmpw r6, r5 + beq patchvi + addi r3, r3, 4 # next word + bdnz findvi # loop length + b exitvi # stop unhooked game hanging + +patchvi: + lis r4, 0x8000 + ori r4, r4, 0x0003 + lbz r5, 0(r4) + cmpwi r5, 0x45 # USA + beq patchusa + cmpwi r5, 0x4A + beq patchjap2 # JAP + b exitvi +patchjap2: + lis r4, 0x3800 + ori r4, r4, 0x0001 + b gofinal2 +patchusa: + lis r4, 0x3800 + ori r4, r4, 0x0000 +gofinal2: + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitvi: + blr # return + +.globl regionfreejap # r3 address +regionfreejap: + mtctr r4 + lis r6, 0x2C1B + ori r6, r6, 0x0000 # blr +findjap: + lwz r5, 0(r3) + cmpw r6, r5 + beq writenop + addi r3, r3, 4 # next word + bdnz findjap # loop length + b exitjap # stop unhooked game hanging + +writenop: + addi r3, r3, 4 # next word + lis r4, 0x6000 # nop + ori r4, r4, 0x0000 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitjap: + blr # return + +.globl regionfreeusa # r3 address +regionfreeusa: + mtctr r4 + lis r6, 0x281B + ori r6, r6, 0x0001 # blr +findusa: + lwz r5, 0(r3) + cmpw r6, r5 + beq writenop1 + addi r3, r3, 4 # next word + bdnz findusa # loop length + b exitusa # stop unhooked game hanging + +writenop1: + addi r3, r3, 4 # next word + lis r4, 0x6000 # nop + ori r4, r4, 0x0000 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitusa: + blr # return + +.globl regionfreepal # r3 address +regionfreepal: + mtctr r4 + lis r6, 0x281B + ori r6, r6, 0x0002 # blr +findpal: + lwz r5, 0(r3) + cmpw r6, r5 + beq writenop2 + addi r3, r3, 4 # next word + bdnz findpal # loop length + b exitpal # stop unhooked game hanging + +writenop2: + addi r3, r3, 4 # next word + lis r4, 0x6000 # nop + ori r4, r4, 0x0000 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 + + lis r6, 0x4082 + ori r6, r6, 0x001C # bne loc_81377A2C +findextra: #this is just the bne to b patch + lwz r5, 0(r3) + cmpw r6, r5 + beq writeb + addi r3, r3, 4 # next word + bdnz findextra # loop length + b exitpal # stop unhooked game hanging + +writeb: + addi r3, r3, 4 # next word + lis r4, 0x4800 + ori r4, r4, 0x001c # b loc_81377A2C + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitpal: + blr # return + +.globl removehealthcheck # r3 address +removehealthcheck: + mtctr r4 + lis r6, 0x4182 + ori r6, r6, 0x004C # blr +findhe: + lwz r5, 0(r3) + cmpw r6, r5 + beq writebhe + addi r3, r3, 4 # next word + bdnz findhe # loop length + b exithe # stop unhooked game hanging + +writebhe: + lis r4, 0x6000 + ori r4, r4, 0x0000 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exithe: + blr # return + + + +.globl patchupdatecheck # r3 address +patchupdatecheck: + mtctr r4 + lis r6, 0x4082 + ori r6, r6, 0x0020 # blr +finduc: + lwz r5, 0(r3) + cmpw r6, r5 + beq writenopuc + addi r3, r3, 4 # next word + bdnz finduc # loop length + b exituc # stop unhooked game hanging + +writenopuc: + lis r4, 0x6000 + ori r4, r4, 0x0000 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exituc: + blr # return + + + + +.globl copyflagcheck1 # r3 address +copyflagcheck1: + mtctr r4 + lis r6, 0x5400 + ori r6, r6, 0x07FF +findncf1: + lwz r5, 0(r3) + cmpw r6, r5 + beq writencf1 + subi r3, r3, 4 # next word + bdnz findncf1 # loop length + b exitncf1 # stop unhooked game hanging + +writencf1: + lis r4, 0x7C00 + ori r4, r4, 0x0000 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitncf1: + blr # return + +.globl copyflagcheck2 # r3 address +copyflagcheck2: + mtctr r4 + lis r6, 0x5400 + ori r6, r6, 0x07FF +findncf2: + lwz r5, 0(r3) + cmpw r6, r5 + beq writencf2 + subi r3, r3, 4 # next word + bdnz findncf2 # loop length + b exitncf2 # stop unhooked game hanging + +writencf2: + lis r4, 0x7C00 + ori r4, r4, 0x0000 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitncf2: + blr # return + + +.globl copyflagcheck3 # r3 address +copyflagcheck3: +findncf3: + addi r3, r3, 20 # go back one dword (4 bytes) + lwz r5, 0(r3) +writencf3: + lis r4, 0x3860 + ori r4, r4, 0x0001 # li r3,1 + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitncf3: + blr # return + + +.globl copyflagcheck4 # r3 address +copyflagcheck4: + mtctr r4 + lis r6, 0x3BE0 + ori r6, r6, 0x0001 # li r31,1 +findncf4: + lwz r5, 0(r3) + cmpw r6, r5 + beq writencf4 + addi r3, r3, 4 # next word + bdnz findncf4 # loop length + b exitncf4 # stop unhooked game hanging + +writencf4: + lis r4, 0x3BE0 + ori r4, r4, 0x0000 # change this to 3BE00000 (li r31,0) + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitncf4: + blr # return + +.globl copyflagcheck5 # r3 address +copyflagcheck5: + mtctr r4 + lis r6, 0x4182 + ori r6, r6, 0x0024 # beq loc_8134AA60 +findncf5: + lwz r5, 0(r3) + cmpw r6, r5 + beq writencf5 + addi r3, r3, 4 # next word + bdnz findncf5 # loop length + b exitncf5 # stop unhooked game hanging + +writencf5: + #addi r3, r3, 8 # skip 2 + + lis r4, 0x801D + ori r4, r4, 0x0024 # change to 801D0024 (lwz r0,36(r29)) + stw r4, 0(r3) + dcbf r0, r3 + icbi r0, r3 + + addi r3, r3, 4 # next word + + lis r4, 0x5400 + ori r4, r4, 0x003C # change to 5400003C (rlwinm r0,r0,0,0,30) + stw r4, 0(r3) + dcbf r0, r3 + icbi r0, r3 + + addi r3, r3, 4 # next word + + lis r4, 0x901D + ori r4, r4, 0x0024 # change to 901D0024 (stw r0,36(r29)) + stw r4, 0(r3) + dcbf r0, r3 + icbi r0, r3 + + addi r3, r3, 4 # next word + + lis r4, 0x4800 + ori r4, r4, 0x0018 # change to 48000018 (b 0x8134aa60) + stw r4, 0(r3) + dcbf r0, r3 + icbi r0, r3 +exitncf5: + blr # return + +.globl movedvdhooks # r3 address +movedvdhooks: + lis r6, 0x4182 + ori r6, r6, 0x0120 # beq loc_813A7938 +findmd1: + addi r3, r3, 4 # next word + lwz r5, 0(r3) +writemd1: + lis r4, 0x6000 + ori r4, r4, 0x0000 # nop + stw r4, 0(r3) # result in r3 + dcbf r0, r3 # data cache block flush + icbi r0, r3 +exitmd1: + blr # return + diff --git a/source/ppc.h b/source/ppc.h new file mode 100644 index 00000000..ae90eb10 --- /dev/null +++ b/source/ppc.h @@ -0,0 +1,83 @@ + + +/* Condition Register Bit Fields */ + +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + + +/* General Purpose Registers */ + +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +/* Define Floating Point Registers */ + +#define f0 0 +#define f1 1 +#define f2 2 +#define f3 3 +#define f4 4 +#define f5 5 +#define f6 6 +#define f7 7 +#define f8 8 +#define f9 9 +#define f10 10 +#define f11 11 +#define f12 12 +#define f13 13 +#define f14 14 +#define f15 15 +#define f16 16 +#define f17 17 +#define f18 18 +#define f19 19 +#define f20 20 +#define f21 21 +#define f22 22 +#define f23 23 +#define f24 24 +#define f25 25 +#define f26 26 +#define f27 27 +#define f28 28 +#define f29 29 +#define f30 30 +#define f31 31 diff --git a/source/sdhc.c b/source/sdhc.c new file mode 100644 index 00000000..a7935ec7 --- /dev/null +++ b/source/sdhc.c @@ -0,0 +1,159 @@ +#include +#include +#include +#include + +#include "sdhc.h" + +/* IOCTL comamnds */ +#define IOCTL_SDHC_INIT 0x01 +#define IOCTL_SDHC_READ 0x02 +#define IOCTL_SDHC_WRITE 0x03 +#define IOCTL_SDHC_ISINSERTED 0x04 + +#define SDHC_HEAPSIZE 0x8000 + +/* Variables */ +static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/sdio/sdhc"; + +static s32 hid = -1, fd = -1; +static u32 sector_size = SDHC_SECTOR_SIZE; + + +bool SDHC_Init(void) +{ + s32 ret; + + /* Already open */ + if (fd > 0) + return true; + + /* Create heap */ + if (hid < 0) { + hid = iosCreateHeap(SDHC_HEAPSIZE); + if (hid < 0) + goto err; + } + + /* Open SDHC device */ + fd = IOS_Open(fs, 0); + if (fd < 0) + goto err; + + /* Initialize SDHC */ + ret = IOS_IoctlvFormat(hid, fd, IOCTL_SDHC_INIT, ":"); + if (ret) + goto err; + + return true; + +err: + /* Close SDHC device */ + if (fd > 0) { + IOS_Close(fd); + fd = -1; + } + + return false; +} + +bool SDHC_Close(void) +{ + /* Close SDHC device */ + if (fd > 0) { + IOS_Close(fd); + fd = -1; + } + + return true; +} + +bool SDHC_IsInserted(void) +{ + s32 ret; + + /* Check if SD card is inserted */ + ret = IOS_IoctlvFormat(hid, fd, IOCTL_SDHC_ISINSERTED, ":"); + + return (!ret) ? true : false; +} + +bool SDHC_ReadSectors(u32 sector, u32 count, void *buffer) +{ + void *buf = (void *)buffer; + u32 len = (sector_size * count); + + s32 ret; + + /* Device not opened */ + if (fd < 0) + return false; + + /* Buffer not aligned */ + if ((u32)buffer & 0x1F) { + /* Allocate memory */ + buf = iosAlloc(hid, len); + if (!buf) + return false; + } + + /* Read data */ + ret = IOS_IoctlvFormat(hid, fd, IOCTL_SDHC_READ, "ii:d", sector, count, buf, len); + + /* Copy data */ + if (buf != buffer) { + memcpy(buffer, buf, len); + iosFree(hid, buf); + } + + return (!ret) ? true : false; +} + +bool SDHC_WriteSectors(u32 sector, u32 count, void *buffer) +{ + void *buf = (void *)buffer; + u32 len = (sector_size * count); + + s32 ret; + + /* Device not opened */ + if (fd < 0) + return false; + + /* Buffer not aligned */ + if ((u32)buffer & 0x1F) { + /* Allocate memory */ + buf = iosAlloc(hid, len); + if (!buf) + return false; + + /* Copy data */ + memcpy(buf, buffer, len); + } + + /* Read data */ + ret = IOS_IoctlvFormat(hid, fd, IOCTL_SDHC_WRITE, "ii:d", sector, count, buf, len); + + /* Free memory */ + if (buf != buffer) + iosFree(hid, buf); + + return (!ret) ? true : false; +} + +bool SDHC_ClearStatus(void) +{ + return true; +} + + +const DISC_INTERFACE __io_sdhc = { + DEVICE_TYPE_WII_SD, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_SD, + (FN_MEDIUM_STARTUP)&SDHC_Init, + (FN_MEDIUM_ISINSERTED)&SDHC_IsInserted, + (FN_MEDIUM_READSECTORS)&SDHC_ReadSectors, + (FN_MEDIUM_WRITESECTORS)&SDHC_WriteSectors, + (FN_MEDIUM_CLEARSTATUS)&SDHC_ClearStatus, + (FN_MEDIUM_SHUTDOWN)&SDHC_Close +}; diff --git a/source/sdhc.h b/source/sdhc.h new file mode 100644 index 00000000..9f6f3c56 --- /dev/null +++ b/source/sdhc.h @@ -0,0 +1,22 @@ +#ifndef _SDHC_H_ +#define _SDHC_H_ + +/* Constants */ +#define SDHC_SECTOR_SIZE 0x200 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Prototypes */ +bool SDHC_Init(void); +bool SDHC_Close(void); +bool SDHC_ReadSectors(u32, u32, void *); +bool SDHC_WriteSectors(u32, u32, void *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/sounds/bg_music.ogg b/source/sounds/bg_music.ogg new file mode 100644 index 0000000000000000000000000000000000000000..229f42d7eb16406a4638d48657bfbd8321787339 GIT binary patch literal 223108 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%0ANm;8z>I{og>idjlCM>im`Z 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 literal 0 HcmV?d00001 diff --git a/source/sounds/button_click.pcm b/source/sounds/button_click.pcm new file mode 100644 index 0000000000000000000000000000000000000000..de3d55e3bfe93b57942bea05e10832a4faec5a5b GIT binary patch literal 7204 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 V;4lJ*5jc#%VFV5%@c#jU{{e^U>fZnW literal 0 HcmV?d00001 diff --git a/source/sounds/button_over.pcm b/source/sounds/button_over.pcm new file mode 100644 index 0000000000000000000000000000000000000000..64f519cfd74945140b23a9908a514bbd675a0681 GIT binary patch literal 32256 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 literal 0 HcmV?d00001 diff --git a/source/sounds/credits_music.ogg b/source/sounds/credits_music.ogg new file mode 100644 index 0000000000000000000000000000000000000000..6e3efeda1e0f0017c85201d50723d7b63e0ebbe2 GIT binary patch literal 96468 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�S=g3V&mVtO+howB9*}9-&#_f%`*-VduNy zOVRM5g4{mYGTdy@3%-nl?%xOsfAxankaNSZ7m%x!hn+FVuqL~i1=9la^}5amhu3Tr!^|B{i*b99{G$x>0db5&?^amAj_&}{*zN8(1)JZ?ySZ!OQiXJVKd z=>$Gs2sz%>WHi{~fZ^zroz~S48;8Qc&PpZ=`OkfwB!8w@v-jFMrb}lWRjwtW!3b`Q zurp#*ba|xnJ34n;dcR2stY0ayX97dTZy)v4rfM$kAJ#$4+F6&-l`8XCo1W7uEqjw& z&&1J#4p6NYsAEuIHxHq!3}FRA>rkz79d|pP`?}6~?lx(_vDxNFGr@7QoDo};idjMhk$9&v8(m{V|h9DK$_#O(jaAfi}!Vle#U^wd(O zC)rQO3d+x*JQ=;k-ks~U&X#(@pd~xr;!&t?B{otGRUTN2|LWw2(z&v0ZCPgS8aY(( z(s4V$`|5|1@@)}({WlAW!`$O@Gkk(VE(cst^OS02i9(rQ{bxaWC3M$8^PZ$NQlrUyeH3p?E2;1hm!3fF+~k&bCt zsb!YH*Se>sLeIwFYGVi+ywuD1n$wB`hK$5JKc>2(-VTmol{rnPsP<^f7g+@=JhUm? zf8TPPI$JY!kA}p;MTVr_tRK|vLqn$48u4BY7=LWIRY8yQIAmHZO3}?uSt4U$Rq#j( z{3SA-*l)Hs0}&b4C{pz-#C{jWam}gu5Cek_5aGJzlI+qq=Ctb_y}4U;)uMw$QfbcV z48{WZpC$`f&EL?12#SeqR>PV4#>xxWP^J5|58*TTxdG6q2ihF)_V|4n|14!Ku0xepeMS)4d-O&vE{z z(J>8te!9fbog%yWi3x{ds;TNi;?DeJbsXVg5?Qu09j4ni47Ns2Mm3e}{A<0jol4>x zRc(KIABUWOc6`k&b%nXaf}t#YuqNt8N2}%~4R_)W@p#CSgE;9(X@&l5{$@;bK&4y5 zn(2ou#j>faz>2kc5gb40>SNHUx4j7sn&+s&#p4*=xfZxsQjUGAimW=_#U*jurstgg zK<{=sciJyGSM~;GOi6zX^PgUrj+0vux|YKtb{x`&E~tdJh>HRcE_q&;P$|`OxKZ` z;LY!%73qjqOQsIe`x~ZG$DP|*WAKS#*p~Q;p@atGkss#ZQ^2WzbKkij46z1_O)*Ab zXX9!Uj4?Uj1-^tpPw0mNX#uOv=S+d=pOQcr=}GH{8As?lsG}keZP^$|xf`^x{B3}V zUwN5)>Cxh_a%cYVY78E4dWKn_QG7MO)~v!y6tuGOGAa-6vBZBsZBE+kcaWez_*$8t zL5@Gctn70bv+~r-80f2QUF^}}8xsWdi+ z%y!SRbYR)9DZAn8C6cEy7ec|Qf3|g;h6-@1P63&dA&Smy}$!rkqy;j;W

G8h8t>z;Jv!>&8A-H~LGr(l#EceTN*tC^1et4)v% zsl7*0`Xj&nd!RXG6D7v1_HyZw91npdWQRmmRzn>=P6dajM9}t_l5F{DK5quHGc5G4 zy&L^zP3#n(d9_gaE3*y@Nld~9EPKrqEGFqYEe^rCpYMp8+sF9l zUwX@dKBEAFY`T!cpCBh4jD_qUNtL9(eQXA1@3MYeU{9AOJE8op;`gz{Og*x!xK&*8 z5{|l%F6Qp3kC%M?*Cryk6k`joq_t&fkVR@hld^LIRzJs47U}Nu;_PrOWlw^ef#k+w zkw8_#F>lMz1gzJ%5$n)9x?5a_$F{K>2V(*9Ss}#FK05OA~+J1u6F;lO%M=1v$)@B;(mlF+k|bS2@^7rdWTY}bsa4*y z$?k*0G>xyCBri<-<|^Mx)s?SO*!DLn5I1Dsh9D$yowG;3+VL4lovU-F_l=h(ZJm#o zBgHC^Q>N9Nn4GBy$6K*b`2K0{;&Dc{-13mlpBKBx7Y$!LYA(ST5R(+BAsDjU0R0;l zO&Ja0sBD66miYIvU=QvOyK~({Rt)*>xjb$7kz;d0%^1Q8IiCO+3nLqxuM#6K`FK7! zZFKy?wnB6isjFQu@Lca|oAs~>o2GLL)oz>FJ1@>@xS%O2Y#7o!x$g7@in-5XAFOkc!g3U(0?Z~)^8*j zkG0v_7+Kjln-K@~nqpTxai6gH?p{rJx5Jgi2|xV7{V`L<=}#h=NSF8|QE2E0{&vs+6X)tq0NPE5S5<+ZlvxelzAH;dLElq4XB5W@UqaR^a)-+%cd2*5QOX zxTZ5wFn94ZA2eL^%A~;3qO^p1prFHHVTObmed zie4-@e{3%HO^r}YZ$&Mr?#;q;7MShS4G_Z_ilcp3J<5D2W{smss(ECCes5XnjK9eA zsk-$@diAdp+%A;eiH5#i($81xVkT)~8Ir@q_)+RG)ek#cT49^O!v5 z8-1}}V~dp*u}w30MxsDO<-YCh+T`z>U#oT5Fk7%V=9w3*A4#}NN9La#mUSyvs zo2akny|QKNHrDHPjxMRp+>)3pDFRC;+)hs@I2%w{83>I54<&)phTO$tBb?J&8E`_r zf(t&Lnc|Zw_eWyO4aOS3J~E|FU|l0l_zbsO97PvX7!a#zZT@05{C#3~(`nK%<3|5& z|FAI#QS-Fmw0bJB>K*6{6DLx1UKb$x0G=q>#SN+r1l13?W_RcN7`R)ly#2EgXx2Pl z`14@LIh81w)5n!rv`RAFe+&9U*Y#`xP4n??$PoYH-Q`oPB^g9oo>3x-u5N8$SGJfn?-Yqy$EfPpZk21QPf-ym%`%jGirjHTheY&y z{_yb6nGfNPGgDAFkOqlgwIychdh0xp&Ywe83va7RCIhl1D73=(i3Ma;m_5O zp^>+4U4d~JV?1tpxV&Nt$fy#!hX2tTfgS(dEI|%eG}_OlhZZ1D9#jk{iT%b1~-9sssT1 zYd<37?{>uB{fLWW6Ibbt$mm)d;T5G7xv;XYUowh{%V15Fwbk{d&9x>xdZSxeKNzTQ zkx|IL+ar2TktsMaH#4`_59-)ozf}WYxXLmc)WFbpqqt<^4@oVoeKBiM%m5;KbqWHL z5bm(6t|EOSdfjp74j&OCQJ5u);?MNR3`}D~__v zRvJ9RfeA`g6k_yuzvHY;D!lwe1aos9bir;?$iTKnA$qJ* zqP%fL|+jz zKIoGCid?w@#@Dqjv`)OQl-z>olWs%L!*YJzS>2w>P-skfMuB0=6 z(4xQ4xtFNCZv!}Pw&@qt$1R`bRSL(#tF#_y&MNzmYHL2J72id+T3yQF7(DIZo)a zVxJ9VT;QefkQM#uz11~c!Tv_YDrtn#q2|c!fCs>o!#j64Hsa?Ki2$=>e0wB`;Igez};<4$?Jd6Uvgz$-q-3ZlJ1sh3FY$B4Rtvi;q$!kvEU;AKYjmdl|E5whQu z=qZW~yXw&cdz+m1yG+Ld({yfax}UWN;QRDtk@gJeJ&`BhUrDOU4#RN;(=lyd ztnG6NC*2Yu=oh(&I?nTYeYnR#_C3GVFfR_@Z?W5UUOIjw{CD1+7ivh2Zj^gCmaYc2 zksjP;hV0{J$+NF5Ya6|Lc=SG`PD9le%p{~SQt&RYrhR!1q1{)TZduS9)5gqazn^#K zk;&>Bx(nGn<6gY!ag%S~9kR6U?!~Xrg~L;z@tz)Z1v6)w|0eF#}WWOuT8^n$ufF#AipVnde z*2Ds|S`{yf68i)}kyl`bKiw$<_Mv5N(eLVulM;ko;C6hAv4jIN$hUD%Zl_fl@0>MJ zvbwV#dl45(HgqkyzT@()JP_fGIPv$j#i(wu+!F&?Zox;d_m{Kn!I*2TK=ZTCaKjY^ zR>zH(iMlxtf=-$%kw;dfpO#Sp+KVR*u&3x0|0654ayL^p6A=7sq| zg9Pn&YjaW_T_nY{`tH@7GGv$6w2XF{7npA->WOu`cjdNi(Zk9SnfiDZHmUi}ND~V> z7HAdzlp-x4k{kRPd53C-1H{bKiqi-&!I6B%bji$iaGR_8Of=u6+Ag?4bi~rQxjck&`p`BZNAHDJW)ylHueLm8nfG^4Vp{ zGSXS`UdCq`5&dm0#OcXapYzFy9$enNGQO}w)L|ArXVKB?Y9nm`;c*9xCqO#}C!@qEz7!6>5!eCB4F zlX}tCp|peau9&CzNgM>9HrprlW=|SyTQGgJ*Lj$HBW;32U2*Z@Pxz3IlE=pUV&uwf z#`<)^*=aOxc+LtX0#pLcs`5#6Rc{p9U3}7AeoG8Y7AftlSDHxv);e`h-er{k;gP`PDe&@bg}W;B&xb(XrVnMu*lKZ2DpT*KIp%IIbW)Y=(%g@m%xExIyq}z zN``M-f2L%9!KV~29c-eHjfB9U8o~VXo6c!%@fe;1dzN-PYX~$`?St^gc10*kv9@Fn zKZB2RgbY7+i~!m4Ej^`xAZU*lyShj==D{dBvFw0GAumHFi0S=1xitWj&-Nvpc>V{K zhY^Fsy!XbrmOlyeewi}&&i)jNxb z)}ed^q;a#C2Xi<-jscuG0dV_o86?{cb;qlL&{mph`X-5kyOrWuz;8w|@ zsQ5d1Se?B3)2x$(Ab%wT0JB2#d=!^OK@#9&6ej@p<2E~I2TUaNK2v4A6JBSFeZ`i@ zQ!L{kr*6{%UGx7I*mvzp9E!L^3|3im{l}R72B-d_|7|>+^xS8N^!(tP$PcE^*MLo_ zrO?vzW4Q0uh`yMg?}wv(UrG5r_sf|k4M)x}WzCklCOD;+g3pS5a2~dn>~XWoHH+Cw zS&%}auD16yB|I;_@lL!qJe|vTO9L$Fzwh1X#ek=!NdLw?e(S`KQ9uo6wSMkouU`qD z?`T&X4Tli}fm0TlT}8IlFMeE(`B1DJVXLFE8BHnQg*a*H4zC@vwy+nsR&&yb^O9co z$De=CS83L0-nIDCyHrarDQN^hD_CA>e>g=|o|tz$>biv3mU~|b!jLDJ&gwd(zZN~r z9UV`&kL*H1LC{E*29KHhUpgR4lezA$K6v$5)qwdaa@-o$vJ~37I+LR&m?Zf3*>LoF$T8m}=B#_VuyBO1oI!8tA+_5vie z7HYMDNo;JUrs&;hH}>5x31{upi5$awfABf*dYO4@$w>F6l5Bw7ygL*%Dlnv9+iJ-IS)}_(a8Na1fgqEwSJf$e7sdb$#I3 zY~gyCAVu^_)6NflOSIVetvWHuO8CRfo*?OJVkKqdb2yPWKsbf^OarCj6Esci8%fiV zrg?wywJUM6!5yQN-)?19tuL&W92*kbEBdy$hn5ljX-kzcv5YbM#i+EsGK;C|$=?SdiRKJUCX=o*(#**SWTc_&d0DS9D$3oS5aAc?~KJR)ejr ze!`twU7!|J!}3A*@LH2H9q*Et7-NOTG~LZMQbeAYhhR08Aa z#!UA+Xos~5m)p|TH!pJrJ_JT}VqEV;wJ%l+kn(JpbRRD(H=$BK7dHFGlR8T8XP=fa zH?iv_2PG_R3q@N`9B)SgG&0#4+G3|`yM>dFDvz>}ly9Jvu-eK{4M*g1zG(94Ljx8G zGf#2}+Sj2-=0E3l%gsb)Nbh|nr_PY5!39gDyGl*eqea8l!4Izr$-FO>DagNURwAD0 z3k#%+Ie!M}pM;dZ^{Ju+>GmN(91v1q?#<40-)7n_f6}Av_?0;aY2|_+5OFnyLs4#o zFWb55tYKn}fNJ1`_^z15OD2}7HtBKF&wPQ&9j!OVXjvfh84quH8n;`2_d(b?ok53m z6CWtI#PcI;%CUut1x+(mHbhDg65d+%rw_bfwMe&xLY!#oS?>eR{;1fREx1yV-UnTG zMpj5y?#W>zvhw5ffTJjU&8bybnK}+WVzVp(Jgiwso#gUYYzsE8nZ3@6NgSKmZrJxh zeKr*BiGw}wTiAOVn(+zwx+L-`+JC|0m3?Fd*30S8I6{H_@@-|z{p6M4F=5;G!}ZTw z#f`_X>RL9*h8aeL^i%^=wjYrGKA%LrnL8^F6jZfC8l~J%vK+lD{eHVRp9Cby@CuvV z{9UVC$+sxA0ah%3rMTK*ap7@6L%|?6u>4ACs|!P^I+)!jdkR+Esng5{#dR-ILLu0s zOec-`A)Ab|j6d^9rI|gQ)U^pwrfmmV`)#h9K2l>V76}>y`b|cAUHd2KC+VpQ78a}~ zWmy3}%AJZ5k?hGiv~UWoT2oVQ)&q(2a(|w=yFijw|2=-^q5hv6hJ|{;y!3_DF!q}n zOHy9p8ec?weOC=x8eNtI*AfMe$I6)`2P=n;iq!R(Z>!{Ja#)K2dD-UJ9K>Q`5^rKNK2UynLo+9Ja2?1~ z4SX)1F{g#_%c5>wBu1$jxK`<_`Q({qf&#ymPY0MF)x&m=Z%V4mG+IkeU>57sOr<{| z>NhEN&%R*&j58C#%fXqv`Msa)nVv);4?=~pqW73A*jccp>e~r1?6i9(j*#|oFAsb5 zgcz-abx?Fj0)j<%{R;b3LHqx|%U7w=+BO_)M~IMBkw79JL0lREvn zdqC?Y^oTBf|1?jjS@I)+Vs!8v;+NM>3dV)!r8lkQF+jh#!t0^^sZ~bB)=eXLa3cx2 zFkx%B$;<%+9P#8N;x@}25v=G@ z_{Uz6itt1%a|VR_20fDIv*|8VY;|lLGWd3js`TD16=>Rb`FL;KuZ*k~X2Ma9+w#GJ zLLbRrJmAgH9B5O%60zz`kC+(!k<|{q+!8)eW{2QW-K8$HDCN+_2xF@xk#fd-wE0F6 z;@6r+y4Zl0?HbUBplqsZ&T&BXRz}q?d*+t|#!KO>_;dCzy>RfEvJAB|QhEhfb$niI z%2fJ&sy-IP@d@uHS?)BG;3IapV}CAH)|rBx^|5{QOnXw8)im8VJm;2Rt!0wk!Pr}r zmxB?IfG()m6S~@;cJEqt1~FKKV%oxN(2%&0Q*MXPcP{MADb(X&Ipi2x&C7SknPJW( zy-T;RykkVxl`kP3jb_O^g}gMxHCm@y;mZ{5F0c0f;FvE2-GQ2hlR2`xAMQGPedJbV zwnSFlmv`zreQ}nEORIufnxE4?iB`-sh3zj=!?y}V@S`>0r6V!tfb%Z30<{3q)4`i6 zYQuNU?1Ia8MBTqCx=w#BNm!#RqNwza;>i@H_+|?%Nyy)5F8-706v55H<;e42h&m5{ zs{i=yA1g&sY1zt(LUwkgY|ghRAyoD}_I8d^DKk6sDC3ZEviCWa?3FzZ=ZM3>;T)X9 z!CAN8M$+IDw1)&?d(Igh)eKyUu4#FU(0giO;VN`9cqn1 z|1Gi5;C}qkZFd-#MpnY}O0V*FPNK5$6j(q{s_7@oR_a5POW^5 zzuHcDBTCf%@Ofc>oUk!eH|vd?!!^K)qhA;6d5FiS8-fnL#M(_}|JU1lm^W^(Tre_2 zpzcQpWJN>>{zST8X8lJ8-t#GVuuge+>#Kz~t8Qe&lWS69fB1jR6?Z>qt9h*+VFl==R$E?RDv8>D)8wuL;&nw}FUygOJ7W-oiE|F)k$`NB=pqE!f&T-Y{L6X>c=o)J5a_UUrbd3OUCnxAP@JM^Q+A zNE9DhDHIa@gS^%3WjE>?>U)gci1V7e>nH0!%?3qZ4gN8cX}AFoHP46Qhh?JjX6@!8 ziILRp&|7IK8NK(O=r%Jj;;nLq>M5jNufdM#W;%pBB}(KV8}203++kGc76hp1(28Dv zxw^)*@8=`Z;&kmTV?dF;AYyU^F?)9{oujosUNNmNwc_}Vm z0<(tiR!GMFcO_v)T9WrQne-4I`O2{+!tuZazw9ha3kwh5TRHVTxBDZMYQ;3x#VXS% zxa>bR={3_YoA9G7dozGkb-ydY|X}=N6(L4YnH| zT@BaQJp$|V4UeLLXPI2N>!VaDKU+rhvDf_@&7zG{`rlLij}z9$vDd8ab{n_XM0NRbiU&TM+r4P6^G9Xy!{U}E@r~b z{bd?@gVkF5M^v}@lB9^A{NQu2Q)0lv(X92|0+Fx5>WXiFlkUH?Ien)vZ?xyi$4Am- zvlGqPjHb@Jd#<$<%rR*Ve{sQ+y2vcvc66y3y>rO_R!Z2ncHvUzH;Sq?-ZNAvoH2*_ z+hUNVZwD~i)j|6j7?wrkJ)F5TZ$%MNggv6L%sw(l4))a{0#DVaT)tYK%bfFredqfQDG2vapc%@F|HJ*56EIjX z>dwV$!+~m~?s!4QC@?mqlew5yiaE7Z7cA+T>cG;$BnWa;JR@_gTv~r0+oNi9y+gW4 zts$)}LVNVfdkp11;Il9+?fBab85&k%&-1BC6>;uiEP+GpD%W1EkBYIx$LOW=W2^@W zX057cp85~E79>1Ab zsOm`OqcW{WE4Rzf`*JC~q-mLMEL69RA6AUdwq`F{yiCQK;PLnd4RgtV`Bu<*l%q~| zNdW$;1w8Gnn+MC}%D$OX>1a0BA2{x_RlzCD-Cre<|K4HX9Du(TdWn)O4F)m&XDVEI zW-+I3r5|V&GJCT4k}b~M`v4GiDCT{q|MXc<)1~te`f6(2#D~RYv7bp7*HN<7d&9S^ zl|zn#Clx41oe|h)jf&uF+&rnY}t@JQE{D0kCFo9`C}WdBWO1tgk2`J-sUD#G&0)%8v# zqZ75!e|O`*=hqCU_6CeX&G+WEEcC8YCS;n#MNr<`P5Ph+$juIwPfc?5-|Ca*Q>d=| z0`uc0yh#G7lZ^441_RgPDK+t2Q+R7hW{GmP+Mr~>?)c}R`8LL=4y@k&)0(;kN5*5o zHQ3*!>-=So5;hC)0oFzYfi#N%o8*`~P>?=b0-f!lOwGMnU~@<6wq26_ zXLR#-ncluYFw$mB9iNnVA!uYl+N1FC3bSQgWxcZ`i5y;19Bxr;Y(0Y9oXH6g7)*?ByzwrllYP{-_G$bl{>SWp{CD|u2JPayCL#`+ZaW<%J>@R_mH&hp z8FuVU$>UasGAu-F`NZ+r!>v@Aq_9C;Q?~0>&W)VH1>I;Gr`s?Xjv_v-sY5RCCxcgM zG<67=aRkHc2@K<@_9Ad7IX|j=^S(m_X>Aw=12#L1BhZq`6w5p*6&1{)Z~5cHC&I&e z(lF6%Ld)ZmI%P*=rrNh0%F~3~nv&H+WW>b~ji_eOcJGm)jXPta zmG;}bsQve4W)2uzDw#@K33THd&Gog)1;%4G^7JC=fn?TPsJWj9#L{u5FfI2k$v5kRF zyz_eNF+n4|Y^MdH+|tM$Bme(kh%rn5YgU|)N&s&z-i{F{OsuyF4C^W`_*P!g^t-Ye z-qSN<2YEA5)`Mu1u$5GDIVq{JHS@^9hAx+|J)z4`iV=sN9o$)>hOAj|YX|x4I_s!9 z-Ib|YO&N`#g6EVpoF!sl?r)l~eOOvHAoa%REt#X-Y( z_q?}@_@_S-nsGK`!kyHQBM}R-FxN^8J*_|V?RH)-eh~f5G?4&d_EQa;T&h}(^wjHg z&N)4dNLgJN{lSJ9w6d~!u=Dm?_o-Twv+-=}PyJfdgoLtER0~K0*fUc+oFSzLApv#M z8amJGs8~iFx9@`Uw6$=B@SO0^iot##ncha~*0tv}5OEKfa`SynePpT3M#lV%+kivJK= zH+pBuEbiQrI_DSmpUxxkT5N!KkD4Zw&ejR%g^OGk^B0_@VQv)LvK~uKU>J$p;R*-S zotiX?bN$gc_9@i=-ZVGE+{1+x}A4aB$UipGITPN?yTG{0ftL{MnyU z>*J%~qv{D{#p;}-_zbTLJ~z0ZNdCm_^?9*&eVd$bb}2hr!rTTq%Vg>j5Y&mNMI;oY z$pmAYpxxVxD7ZNEn{H_eR8?;=>NwPH0ZR-OtVZIRln{&CuZ(-F@Lmx&;)LPKf;we{ zqfBibf<)9b>K}b-%n@x%Q7Ns6QvLgOhSioX^uybL2Z&{FexJ7`_t?OeBiH3F^rJy` z_DTJ@rbEdERuTEl2RU8N2@5?~;RM?cAErb?z%5?2IRQ+fAz~l@l2J6%a=bX_5wSD5 z0wlt9qBQXLCbDTlDe65qm^v|Zg9y|^?pi_Vs8#K~jeSIYELPflZOZbx2Ch)*w=*?E zE=jrIxcOi%kF+;ZaICGKjIj0^R2K0-hC-U4)~}TVa}Sl`e4sVJ!|*>D*QUp0&hvU- zg1kE2JGKp2XGIhUX#;QS)bQq>n(MJ&<+=KjbiGx^fwRY+IQS!{|H$no=t(AhB!0N@ zH%bfAo}^`y^K`UrrVvNju?9`LAL=H-!{T9^n5qM($ z6Dft!XIXaoaupQCi99RLDPnIbJ12YQ_@;(cMDM)|=k!&1E*?M1XW?x!o|P|{>8WH? zbtT@KX^4R&6xYX&+Z-vG-A+nav>6=%+iN!Gjvk#mL|yc(T|y3iyW=VrkPm z_u522X~F8PAhqLpUqDPsC;*&q**Jbf(v?;90dUdHEbFL} znd z=LD)M;ckg8o~Py{?E4Qx#zsLYOogE6TlSDb5{lFQz^yQ6O5b`f%vXwi4W?#yJ)vH@ zZ2{n?$vj%nnX@*TzxL1CXrQ-geYHNoMhwDaHJ6eeqFY0aqG#?fppKixpIcWu6|pXK zVJGv$88A!3I0R%F*uxvrK*G>i8?JmZ!a~#F98JFM{;UYo41pY#IzKfvf~x1hZ5F8s zqeGMaUcrp#lp9U~u8((I)0x@XYx85B!1||a7(u|3bAUXvtuI1qdEFz-{B}FKz@D{; zUO6+H>u5zy?jyCMWDc0RUadmEq+WrHs_gx^wtvp}rZyL0`KEynE}FD`G>u*{CcVG1 z53P-Cw+n4*gRNX2@lulCEpI;xy#X(4jL2YR+M1hi&95X5GuATnd}hg2v!_JNE}_S{ zSUz0#T0&pXddR`m7*?y&aZJn#JuLdIBT$sM+Y~4~7hNyw<6ChnS&-`cFL$xjrE)mt zz4luu~$t)@}kWQ{GNzqZw2HDEQ%*Dr|COw|@PTcEB z%A-Cin$Ji#6Dn8w9jrBGTc`GR!xP#y6!x)UMP%D|Fx-D`*SBZLpU*4(oS|H?Cw)yn zpJgKTAk7)0rb0sHYBqtq7#e6C!jLHh)eL?>qIxmpz4Ue8K9)g;L>@ylpTlQZ`Nc_gIKTFG z@poVbI7-FymfGQD0aDvYp{}#n&5hbWDtE5=`SQ}AR!eIjk~0mvMOjwRCOC&n7}TRb%*2{(@~- z>R|h)?=aO00SG#*sZ{4i)ZU7A`!qJ-e=4?5gYLFaBXVe4j2;McB5*7^tc8=5Bi&=$UcaYKJZ(#8}B+9Ey%4>;YHGeJvEj8pu;-!WYXVA^S<3>004P&YSDbT@U3`Q18 zS=(5Nt|ho4yY5QRBj{7QN{CMCpMPH!&2tO4FvM%h%F35L#FdAu940<*_C-F_3z~N; zcAb@8R4>SNtFCY`x`Ft+)NUtzCfELj7c7+j^&QoN*y215KcvvdD_W|{5)eL~&O%J2 ztmTz%(n8Ph_k50EuUd;AV+U3(4EnWc)Y0LqKskdbP3yXyEo#UizI9@vQk@x0#Y(}X z7ZG}q5Cnu`8Rrmv6vyXtg|neEw{oHzcEF@YAz_YfU$c|qs8TwO5Ndj*L~~xBlkPUT z+GI$8g38+$bR&n%Q4BJ+7)j*@6G)E+^^^mDZFD3Fw_V`qlK+yykYo}k8l*eW;7vv~ zh);WEqlkGT2VKsp@8V9$^l+ZgGQ1z}+EhN7@Jx0s+C#q;D>9TchZ_d zy*_nk2CKMQAr|^D-a(jFZfD)Z=u7n|%_y zFvj*<{W#4%wVufs!I=Sl))WN*8grBj=nDl*SKhewAeL*CZ56V!CD#^ zZHL1K+jlPQc{{G$9@R@{0dY;)94{2WD*bgtgb_xWAs_}hQ0~w1Z#ng7bbk(f+G%i{ zS*|2dhbWRH=4v1=S4Ro66@oY;K+xJ-h%O6caxg2rX!C{eQuXqdaoqtc{7%qm-;DJ zduXgNxNO#zvEc_iOU3^`baDRwqQ(CQW5IdiW1wSZ&j|&Gbhq31`Tc6!RIR_Bs2ISeK+cEO%YusyBHj^2Sj)Vand3a&lE--F+Bu{rP zd(8swNbgcNCIm*z>zacj%_95HWoI+A4w|28$an2{N%Bkde^DF5)C+s$y)+{S>;3%v z09h1(rd<7dQPJEJ`1>nh&;LN6B$Fk>u!zGg)vjXMtD~_6kTT`bU^6<#XhoWUyh{}- zRy%7C9QaIi9om*1Y9Lp_BB&mLGh{4yzOo+bmnDI8@SPXerxus+?-nQzUGCaWG$N^D zZ71LtODdk2E8%8pqX!c4CvkY^AU#`DygNvMWjFKQa5$@GWWyzohb#W#SB9V3-T(^- zYZ%${on|g($ovLR>YmY1aBxT+f@t6})!l2+)8qkcfXQQ|Rkqq>FOjb^i$(wkB$;2| zQjk?VP&&&3fabkmhL4kwzy&OMT7IlV1XPm+evb1pmLC*{4t~8mK9N3ks8K?1pnp_f z){i(e`i+zw!^#I-SF%tc| zGnZ-;4GVP14>ZBgH+(j$hP_Wk4UetF2Js?8OJ^#(=4r>U=ik?)c}nTcp8)fYg(Aj4 zrivNu_aM_Avk@3h3ol$_=x&#VMr0BDBLj9cj&1jPF9esJ@fiXiP*DvQ&wF&04f8Ja zuRETh4>7ko3yM$U7%)GwEm`u)T{zJ#MnN1JmiRa zl$EW0a1*^1x>2xx&hpKenu1Q@LOlcI{3&Z?fVZA|_*()xM++rIJ2Vaqq{iJ-qd32;T} zC!;i78R_bEgNjej-|KS+ulkoX@G#M0In6p6*r{ILJqc;FJtEr9q2kdr!JEmXB6D{s zr8=5!>32N~9#+q5*kwwDBeQ3ZT>}UwID$@!LG|bm5{bKCfA+KUNjBuB-?LUDbA^OE z)#GOqNFH8xiQdi&!<;#k(Zld4p_e{+W&PvYn`@x`Ni-KSG2R(bSJs`g-egpYn$&Wo%Ze;4yXI+%Zx$83Yb7pf~qPY9ute;mA^MII8003nL zMH&IwQGOERQ+2(#xDejtsQRiGS%XD3i$ID^S!5{FmZ+#3GN-2)YR@>>CPyQr3)Ac$ z){8es2Q0_x>A1LyxQR->byqRxBZL?Kd*8>mJ|*?FFqk}v){o38XqVR2!W9{F=-vrW zGuyTo?})w{jMcJB!Ongi1me#K*X%_KVkG{46+H`Js5@PK#wq95ObUAjK+Kbkd6h+pV0{JU>eyqaZafwUeOz?LIOUBl73C6AG+3+HjsCj`)gE?3B`;(pO~ z?X=5oZBpSgy_usjSqPbgr;wv!&B%;~`=tw}=*C6|-Vy5iCnDB29HWPd03RJ(8KQMb*g{FStF;yy}LZB5(Bv_&S_uY zcGyii`8Rfn=0EeK=6n5vG ze!?L}LC?>{eOZ)zV5aP!9rxj2{9Ss5t>w=Gz|WPfkfpg#@3&0Zp2(#s?P%4`2fQV| zVFgE){LH!|$MNmQecucBYQ?UhD`Oh>+F6ty*zQnuZ&Tc7Z?Blha+Htm5@;~uTU(x5 zNlCr({F|kODVmORM#{5;5oeG(>>n;!}7wN?(u(`Q){~gi?^>>y#b8z!eg>lt|xd|Nesi?s%B> z3Wm@zrYdJGEN!UMRX88EEs+i4>0mBBj6R`R>24dsJ~2N&9FbEh$jZ}25C_H%WJEG2 zjtnbe?|uo5&NW?mag@InoQvrQLZ_FV&^3vvyL;PC1S*nmXfW#db236Z|E1kRR61d7 zu8F+6vpt8|i?7tdFHU~lW9SB?7x_nHC$P*ycYIO-TZVbO{!NJGXIb6fDZ{eeLg#I- zwz-6xX}WCx2Ze}(33<}K;ZbxYYW@hP%Fq?e$7iZL1x?a5e<4PBW)n38i^g`6(@x{1 z`^q@;FfKCqPiplvB}b9V`Ss|DTQ<8@5k)QE_uW4C~? zf3g~%Cc2J(ZOjxZA+y-vZs}@!UM1V>3YiiW?g*oAXL7}il~zEwR4~HcE!>{maieh} z=>EB-VsR%x#{Cas1%~n$pmR~*W9%oSLWB-eh=Cz~xhcHS!*kXeUiCocjpk+IC^wmQ zXyiKzcQnt9YE%%u+6)(dSmIFw*?4G>w_E8$Sob_0CH3J)*gX2Jv7+pUtP<`>E(t&Z z+u;vR&AgJrCgY7|MTOt2&G&5omf7H*zt&G>)4y_|)(Ic&$lw6@1^-@bv369j%xY5< z>sGutb1fsxUW`SX+{PIE0r;RNSC6_1Bbm-9Swu?4f$SKJf3Q%C)j@8{a*#*^cS+|a zoiWwEcFz6vT1`dUM)j@|$!)`Bevr4HhPeL=c#uB39ll@ZB&u`%Nb?2+*Nb9=a-rv{ z?U|<=2?vKGkbJG84X~=Oeep?7R;S8s z@8#F;R>k=2#8n@ zVN|-{(oHY(BBs{8B7q|pKnMTJj*E!+E&p1UsxBkv)3t3TmfbC7u`4hK_)v<7i$;dX zru9;@(D5^ykpfS{Ka0A#k0!Ze)6_9c1uK6L=qj6GZRrPFW5*Pc6EeVSSfNLu^APxM7*NYVm01uMCoPOB+o^|oY7gSej*!fHFS1Oc5 z##rDLP9Tqk6LeMHsc!SX%O9V(ZR8$ew7Iz{i|TW~Q#xta_QIla(_)t(5j!O%xlv&? zU-xEs4;J4_1TbowUd}-i8^-%A!x)oNqvYT-^w*{u{@0`1BU~(2>Up<>BPA+ zk*8tfFeB>$-X^qhUvpx7q{0V!N1Svt43IaFU6l4 zg^TW#^qN%!>^FE#be466&+haeAXDFyc(Cu(s#FMB^z*(r*gaXg8kL8kmB56 z%wn_h!u{a-fAs@NQT9*eow8j+KIl}Vb)aSuAq;HYr`jCHAff_%Erq<0ih}OSXXC^BWW9%)b8AS8& zSlGv|uTK9vcm+pR;$VI>!+CI8Jp z*3V)#-D;t7WmSD0t%n@N#oVeL0dmu-R&S!XPtY@^psX3P!hpQhW{H4YWot`Ua5h{Q zgE`9t`EM`%R`Bk$aSo?M4H&jDXl3!zaJ|OIi<<*`N`=2u5H1U+lAZTO*G z*YjU~ha56_nHze_^XR#H)xlo3O8%~;+lmZrTYq5ger1Ye|BM~)TKcc&$8OC?htDa3 z0Tx9X(UK7s@1Lxr#6a<(kJ=+Q=|5C_jpkt*i zC<$w^B?1{^m_C2(6_lsQ9NYO&R>i&eP6YtIzU6)b$T$3pMq2 zXUMp~-Fjj=fpI(1asFBT`361ah0@FC4|LV2Z;N&oBaB*mI%6`heby4=JuBqHz9y8} zc17t8=5?aH$*gU1BqaRHRJ7`HIPrkjP*$^kVLWiZU)S@y!81a5;#QzQx)Zs9@Bgtb zH2>GM_@8?sq`?59KzX}s)VsLR>hj{uE|-LiHJr=Gx7|gRb@de|>Mcz^{e$Pu%S+pj z)T*5`jKo#HF7bvvU#gV@DiHsEN%Xf$?p|>*^g_~$4y}&|v$moTL9G%(#Am}jyV{@n zCQ>p7=kF0J&_uAUXJ-V}Mj$i4u<%V3m>KPuQvJc8P1DDioz?M_kG2an76k4_rA zcY9Z&x2&`N=YK^(rbaa zo=7xsJg(B=AD*;&IN}Vw<`}+xtd79Hf5mdz8Ss;dI%o424ccM zVZNtJrWMjp-uGVp&yNs5mW=TOotR7R2)!rsty3PRYJ{9RhV8Kp*P!3P%Hid-lt*u0 z?pv3rhah%=1a=H)M+>NhJ&WqstrHys45?57@9yh5xukT(Ed66`S-ms#cT`saUIv$J#@pRowhtbAb7I(NFBKwqVG zA2?2to}vbW8Mk3}(}u}MZROz#6Fi?3!Y7V+F%emAi!-s_pgM&hZQr=66rCB)r{9nYY%>IRiY+gQ#?{ z22-R_jxCc^Woz2qk|EZix0zePi+XqDhkG4)v?R?LwF!eW+5b9kIWp#psGP}LAgH#_ z1lFVDXn*$S+D;z><`Dgzl+5YWaWvZ+9(@?0ETZ6yBu>{n%ehlc3D~3fgZm8iKVtVg zTyJR?Iu>on$__`fC-=RNGa6$Eb3}vd()&DLZKbee{?D3GF->y?YpdF6Q(pc|!B>V#;a{I(Zyb2a8>B5L8;{ zH2$deS2mZybx12x5dOG5kNsA3=a@Ldya@nYB#oXPz4mV%WXvMQr70iNv48IQ z5ct>I=z7~KA;3>tbv8vuBp2Y`zb*}J@#7&Dz&eOgc{YYajHAz7>8mlzyVT6F%U4EC zmq-^cYpdb32X%E-q;u+9$|eO@>KEwFlWb=JQ6l|-pE6$dfR{HouiAzLZSbOhECM5= zGK)cD${UCN% zXXAO+4)SWVD{FJ%x#+7fXp-!>H6q+h^ix|HDo#-OSkVw%KFIAOV40*E>A%X+mZfq?^?Ql!P4oj$LbTBYZ4`2S+g4 zyh)6ecJ`BVVw}dyf2>ijbd6#jsEpb0!zENaf9dsJ|Eq8^fQK*~X>5SQyi94(RR91x z_!uAxh@o=;f()aseEkvP(B1jFL)PS`ANyu92JE~Z0 z(i(+$ulC=qgN&kOq~!%~_xRuDXBZF+zSZZJ)E8ik_Y~ooiapi_-+kOrO$8L*nJ({x zR@39@KpX{GlQgGBG@hrBcGqZ_6r6;QY(f1oG<$!cwt!S>d@_~HZ{9IrIZ5=7=jY@^ zRoac%o?zqjwhO>tJ9P9v#F9gxXbT?3f$a+Un0zoS-He(sZ;n&X_K(o?4h&?{TI{#N znvk=5!?XE=aa(2+6fYx(X5;ao63BtL$Ap*Cv9@8lRhp54cz?NjT7!qUaI3m;Pqxa~ zoJxPFYg(d2;E;kxaNW|rpH#6OZ0c%g_ zyy+h^6Z>kT7Ys+f2EwhWiX3nfID~s}@UD0Qh%Z#rQ&~Zlg5Ui2=-p+>mNiQ6=G~S7>xvjh#Ns>F(#94tBEys|ppHOf~ED82@>YJ1RMKsbsd5-g5d&RoVEo~mueg_2#<^hI#D%3`kQ4rp;+n6`6% ze8$A$Rf|&o7yGwY44pOa)~IInKnD6tV0RXv6b|N_DQ4L%zaxjD2;CQVo=YL^!gvk_ zQIN)|QN8G0@H$fmjP9&I2t?o)3C_K>)2^EYO|8!}`q?R+c{O*~deR3Wy`DKLKExT6 z^=Y^1R0Wb(XWP!WG>%7}w~V=M1C7!cz7HnvZ_U-?Yww!UTU%^3&BeVF!a;UEC>4a7 zxk_%n_Hj#t#R3ASqgUT9eHgUaI};ip+fLj#Y{gmL=Gk>T`-Msi2 z=S3rm+}xX-A9Hd8fOq}0*b(ssm-*U(g|>J}QY27xBt2Ca`g}a2;R4+g zK4LeMYIbLjezsf^5Tp~}(kq5ar4P7OAR*Bk?CqGN*Guq)?!mb?f=jg~xK%DuJ+SMJ zdfj%Hu!I5$JQA+_Wkffty%xxOES#N;^`$q{LJ+H!a8jNWJhUtlAN;rkrK~YMmiYg$O_16pb7>1xIpyT2@t*pQbkQ&GK zinL2|CZ@JOGzP{Urv202(=9|~@@M11gamQ(;>Z)B*PV!uoAaQ}@b?ZK!7>|t4~wT( zUj-C6J*o?J!|73(^?Kfplt665Uw>%BSY&}F7`hf*+*+u%LE3$Bsw=yx;?gk=ZnH1^ z$Pkfw^QW{Cob#_ZUCB%K;Mko49&xuL z*4X+_p%^<8L@4i}H)hYnbgzLedT7F;t!d^q9$#<(tkX@A6ot}6v1h}(Iu!H_swTXz zXtysMQTBUiaRdE^$+PZ(M>I$B$95_`#3{WPlH^%Vqa2a)La_ZOCy2b44{%FsP?I~= z6GZd~imArDK19?Z6cnKKETX}GuBu;&jq>2jAN;(Ek4<)JO*%z5<7tkF;1N3qD8e+b z9A~1r#Z?DCtsff1rmYtX;ALe^(!R&r+eI#euh>%D-3QhvgWflnB5?nzB-SvETQ&6) zN#eBQYT|?-)2Z-m3gKiPr!oS zDZoorR$V*nlZKZjyJe?w%io-RHr@$s2if}RX=TVeZUEXG<-1rqylv)^odCr11-IF2 zfEEa7?&w4<@itjV$EU+4fa-x=(%swNa9Lqk)NEmx`;M0MJc^dJPS?}O=DE{y)I9%P z1tk|z*BbkYHcU^EWHYHEbYUTXP~6OgFlVQ3C=$IFioPGqZ8s^PP&X#?}{g-u z5FU$e*wxm46WaO=1ejZ} zqz_(Ii?g0P35tJ0SJb~i*ohMjgRvIVg#curfhH?-oR3tG;;+mR-6{=A%l6RtU}sdK;P zS8Hm&59NcSpEDiV>19a!(VT^Fhr4&F@e^@^o<4a^;D31pJK5Vg3KH3D^I1AkLh~;#9lIq<2!^39aKdQbD`9}`> zg1lV<{JlMzt6f1IA_?q&v>(A#E{xeb|MZ)w0EzqMCTz5F8V<|IT*k@BBnJi2ew`U9 z1nagVqeg)a^xgWyoyFe5sIjyY;vAwTB8R+Ki}6g~G`}GXpC)=O$GeAD6>>b>0p^{o z{9d7|mo<<9(*N9>vc5!a5{ajZzH|LY+j(}unr|1$0?;OGyTveczJESZY9up`J5de* ziW3W?4l6>hmrH7E75dy`1d-uj99f62pqo)DWR zF(XwtuXxEn?IFqnUc~Gi%95#6Cx~NuNVBKduNJ^cO70e>%|0EzL$?}*QF7(I zN0N}gPsiBHUAx=7PLH&W<3E6XiP+H&mUTnZa>fb8Z_)PqRIcSeZmo}s#2j8azmkB* zzag*!yf^_!*V8v9DI9=%E1;w%);-C4EN_AFZd-mRNSK`2pD8rmcCTpT3(wRuOL8yfU(=Nx@*Q>l%rSY%c^j z`7jp3H;>!v|I8UM9vc^RS#FgVnr+U%{OL}FuCg_~lav}RQ?2N|_>%g4pY23a0v=P( z+$oQr*jZMi9RcRvY4&Tn50~N? zEc`>!G+V$u(RYvHU0mK7hSc7{RK&;hhjZLjo~lk$2uA*`X*&Ne)|35YX`A;2jbBZ+ zf!gnTrh40>!BMG;D|ttgup97|1Iy(}OzzA{F+8>Llh~OfYN0_2NW1jfFPYjHupHpy zhg)S8$fOhLYyA1Gyv&6ip6KS%ON;mT<&aPP3JdY0CTl1f#Pj8UczF)yplKCyJ zE)pHrjEO*G5UI_^x9?JA`F&{%B4 zbi5~M+K$<{J67Uy3L+xK_t=mg3ZXHidm|G(fBoalxG!%bSggc#Wv6=5>Cbp_2$Y8| zQCvH+taJdQ z=!g>RBV;K?1Kh%F!tP?Q6k0D>=F3mY8u}xayxD9$$_R=qjLg}-wT>q*gfibBac1T)jBnab$GpY4RY_FnY24{}6SSQBD2<`ybdS;?JZ} zQb0hu8A|7r5D7s=x}3GDNYOM!g95xzUL%VCIhZF|}s2h;BtLS*j^Bzqt8O#k6P!cn*TJ(%S2Y z?g*~hk`G|heEuRJWsu3JTD6MQ6j*t%ke{H|u~GOkxo_Uh&i3bY`7_#EzVVJJm8q3- zk2yal{WcQMNHN2vfs5_V2DRirGBi7~!4UK9t><4M5LI@I8jAh*bC&S0Y9y3!b+*B7 zBk4$R3zK|NLMS)QBU@7ADTzz|-!wLp;gnQul+Ct?q1-yNysz>BxCc!{(~R1TwaN=ZGSCX-^*nz{c(_TRN?N{ zq1q0o)39fq);4l(TT)|^gn&U9OKIIg!!I9e>c6SP>$H=I-czsnBj{sjV_VNG&jv5w zfYZ#QKVH8Bkn&geJnW@0;hN*e?Q=2DhrHZFA?|0PSxdGT1iUce4a$+2c3u;d=vsg) zhE-9^GCckTbjtHGXv$*Yq)W+P>^3N z&$16=C8x!y_v|?tYZx>k-1K68@U~5SGZu?ol|J2*lxW*%n!otqF}IpRcI8jXX1sH< zlit3aljxdj2R!16*A5)aC$OOd8G|UTH7}scG+AT3ru;~l)HMydMhMq5nBz|PY7bS+ zw{?hMI*WE^h`|SD9T))ESw@LA(<>hUCoo1p9-WuOFxqzRt_ojzWx>q`^Fr>@Rz>bY zwrAmki!`mq=L&49n0;_yjg={BfX7O_bFEN)30>#=CQgs3hl;i^sjan9;(Gl5o*Apn%}W5@=mlK41ScS;M{u40EQ;<38<=KpcSIpEcA9%`nAPk$1b?EDGClr8pbk?v zUgY7lwK1}~I@&nt9-2$a-aS%ARF#s|1_t^$lX_$M8?M+bi!#JLx$)0Yr8Z6kp22dQ z>i$S)38_=ndff8TDqy?nbMdRI1{o|E=udKVv=7lA-w$ih#f5r68i^;9=tkqU*Jzah zc?5rI*hbg0@!mQpg_3wF%=gbwOBrf`_*XavlWD+(Kh^&I z^;!EBKuWCUU9JBFSeIG+ruu~ivV?z_Gg2z@exk%*w2sv2n6Jf&|9N}jLwYu4m!QH8 zag4Bdk#@|&V<+GKqeTU{MK6bwNd3+5xjHRK3!Zc`&F$_p%c&9qMGHl*&q95&QiEYX zX?@dbD0rz4&c(M0lSqejP$^^D7#Z8JkgW}hN1;aq^4rZT#B6>u!nDuoztX|!4Y4h( zT^*7{g}PAYznZ%S$zza6)rpFOLM$~2i&`&EkG|y?zhiNt2t3IjU&>r%D2SIxJa@)~ z=6$HuW3*Mp#_fK6+*|S1mry@gnUK)*f~6o^HOMCGUES9(3}SZ%DS&BwHA1_!x;-$v zK)~`it4$;v+v{#9w>m{121dg;v_;cfS%-EGT{Ol8PoNW;G&HeW?MVosGJUhnq-<0I zkn@}|PE{&2UaR*e%DcM&Fq*SqqTy^T^c;*w5Z6Ga+gq(2kJT8uNo#-j+a;Z-BfMc; zVm`#z-cqExp5jV=m+S;D{4mROFDhOzZ+gos#mwFj5*d=_Zwo@eA`m3ZPWR$} zznHqzoj9*6@3}^&rJ>M$PLQfo#mUtr_iUN!i2_U!*SM}UB>9D(Sqju8)sei{j?OO7 z$hysgbS*IhY{rG1i>zidMLm`~_o^49pOInPBoqT-9NwP;yyx?jA-p!5K)2Nt*fa|M zMtTJ!`&%xNpA$+^1lp`H>J@cU%E{S zAUZD}u&HwckR$Pe@L*HrBkR_0OFjbD6!d4PqO#$rdT&7|1_TNPj!fh%Bnj?O3~Xot zNlOro{ngu4)Ss$qFIva!@QxLnjhC$>Y}Xx0s{Ru=|H3I%vi&@Nx+e5EFP$5mPy@BD z|2#V`SA?s-nMY*>B#U>toZZ;AIE|S7E4MZ6*gQC>b)Il7WP?y@%A+L;lRoXoBNklS4uHRyUO^I*VH}0W0Ti@4e z;?sAnQ!X>NQ_x%dwo-EU_Ek+gztB4Q7}B(!X^X&b$8BDdCQZpVn)by$g3KNEtxlhL z$0iP?m-@u8xWuqkQ?Os?4l`1XZf0~0o(KKjn4xpbyRNZGbNH8tbf8l&dKAp@q)6^% z)boCUyy^RseagY-%zMF>n!=ce!R!HG0{gmW=gr5Ly9I9t1#@3OgzyeKmNFFM8ei=q z110=9IF?NyczzjTyVKJuP?1+e5?JLBL0jh-)M8yHt6Xv{ z5QWx`OVej+DDZl=TRlRq(SMg3h$n~IoY)npwu3WXjMz*OZz&irHpn}%D7r6Eks&uEdD=m-u)ZBAyAbx{XYBS07`zz1i zb1jKBt|+vU8&nW%7`)9g4+(XhZ;UUZ)4k}8p*Yyz4d0uEgJ?32{%=Zx9-B!KKiVdX zcV6U>^G_;Zz@Ivl34KEC(FY&|_a zc`#><=3}*;UR>_Ejg@hqoQMRETSGQkgJVeJU6^e~K-yU2b$hvL@j52^gl^raBA1vj zt@ys+cI*tAj9e-X!J3674?CnG!3=!6!997sdcyWXMvz28$}3$NccAbo2u?M%$_fqBrJTm8FD z9941mrpkM}!iKiKg5J;!D6UQzIGOsUa@I|v5fbl`INd-ven*inN6`XD66dUyPTWUA z`|N3IoNUh*=90F;n4UqlH3X$sEIl3W-8L<^D=^X5cQOt^wu<^h3MztA+nx zB=YTlqm8rB15i^ecZJj8-Or5JCh;N5C#Gl9WvyYdbB*@#?N0Bg z+K=q81~@He8H-YF=%YLmWH)FLr`klC?)Fc=)#cZRt>5YML>Vn- z?ST&euxg+ql9#D})LyF4Wgh36u;Ng$5-fpy9jn-79KIk%3aPtUQjB#=5K!JLPvetp zC}0x_{dJ&WZmN0s;uG12WmFAz5VyX0$NC{hb0Fo1;sUiYYFt@J>*=oXPE#6zy8ydG z-1)>qJ2o#gKH_rm0uo&amc#kC26$BCBEZ(K{?dALi3dFG*-?S$@2+z{iF8x4uyD%p z^T8R8ldq&yiT3rde$fY!_2&Ix-J9q4f8?pY;jZq z&H-Lj2EP0Owtw8Q%(0jB@Mtp0%qYG)bbhJikv+lp9=|f^YR)&bk<`yFhp)c3O&I{e zo(wJL_g*^zY(tA~mxjxWUtSv$5gyNY@-pxd?`dZ68~9qIEUYf_8RE6Ah-kT&NUIb1 z4f>?k*BTh&*Ul5n*B%QAIsq-tk37`vXaI;6enA6^Svhh{$}o0MbH3QgZ|a!?J#N*D z07XtjL85Z2z1%U4VuagEU+oDC{pY*nx4%puUO4NeD4dU=a^=y(U-AWXv})@9cVYkW zLZ{fR|7@8ADqL>=N4+K+_I>eiCd<=Gd!{bJ#`erqb9(!h!iyW1g6&9`^TPU@#c2_6 zTIsxfD@~Z`aFHVFynVcLx2p%?HrlDDo70i1U%mP;Ol!ttLZ@^sSP}zIPFE{uypF^OSk_qb>Jck04=~w*9<)px1=z;AC{K8VdH@`W>QMXN!^^ z3cHP+fvB~-b%x!4CzpIByWa3#7j&^bo7TyZYmk-`lvZ%}L7~vMx$ozV`Cl;I$aiW^ zEB|X|@~6ff{H_56vK4!!w$rss&w^21R54ricI$zO!|>gZK;R0>%rm=0Y@R;zRHA8e zT+@=fF%!n28tPFyaa>zc5#Sl<7vleyR@nxkJPy<$k9Ja`2?%SPuPi!D>J(q%z#|ze z?OB+WfKu;ZxWvKpd69v8uyDrnN!hnnh!9V5bZnd(n%QAk>TTtFEwh)`qtp9w6-D}( zL;{?qCV2E*K{Dc}-`uW3Lz8@L7_vE3Wk_6cL9S`rE30aXckw9O&1|#sk2P+jKFIp08ua1oTD(dZ z{K6>{{3PX4b@&Btx44h8g|M4$vEQlB4et#_Fx^-xXtoOcG@yFuKP=s>@&-|ipZJ#G z34S)se<-z9;H8A)N!^(S25sDLDTT|e<{30yeMzUwL!xrP>h5@h@Fc3@g`&vaLWT9Pp=WWS~T&!xoFMMupr;0-DniDcA zfy0BSN1*EG)oK&qNISywQz9LPN}4IYuSfclHtP2CL$%xcy!#)#GBjWMgJmy&Xcekw z;5}yl0nf8z1S}bjRs){RN=7ffVzgy!J2}6i`{7ZU#SHci{v5ic{we3VQIC?#b-L=m zgbjt|7J3quI-k_oOf%fALT&v`@QpID3*DwaAN}yuK+{LcJV1Oii6_yJH+UxUX6O}$a*Z|EgU#m! z%Nkb!o;O4{o&FYn(pXXPmU8*>nn})WHAdn=Oo3+%`tFt2@_Eirqkuc2H~gXpq=UGX zko~y3+MiQ8zURJmKx!%V8Q&dFV^!MPyIWcK^x@Qxh&Y{L=lLNjR`l5^CXhe)g!apc z34|SCs!tdMc0xq1|Lhn37pJvuz?u!%Cw)zYxuvD0^m)=Ie}7iep>OB9C?Ufdkh{%tJ0~GC zKw{;pAJFYBw;rjvI@Ficx`4-@P5#wizrMAbQ%9(qY=rru38Rg=JkNz1upTl$n%W2f zVAJk9O&$Wr979WXyTFQJ%>WsOIM6z88pvFi4gd&R+*VlDuQ^vma&#JE_U@2C$(%$P znO-eq*+JAQhCOp4fQGqOw^rj_rJD$d5^mX$1cL3{x~xuLEmz-?RI!K55Jli7x#T%G z?38?ky#*H9M}^r1Chkd=$g2^nDPB0DVOHi6tMV+%BzLAt+AoqQPP;gRM+yvgL zS8}>p?EKw6D9$dB9E``KinS7DjN!H=Jx*8w_>ndeNT<=;rb4L@JO5;HU8#fxniT4* znW<6lfxV^^mbXsC{#p_7_v6}8f2qXp7-2o@1kMmpN5FJ7M82`_8gG4DQ`@zgZ-5Y0 z!v=G9b3JX|OKn@LoW&zHt(N0$zPOvVYirzpFo7I+?gN$i>7ha1H*C5O1;8Nz2p-S@ zSZs1XF*VpqQs9dS1b3awGq<JwK)q4=`YWwaGIXAkIOC2I?yx3b zL)E29f8()#$}|@z-XgdEXo*YJzPgobnFD|l0&wq{ertPX48}Uo0eKy&&+5%AEXJ$gX;wC- zmHsj8Q2r!L?D1Z%CHu*~oz)jg(QMrYK_<|TK25I){I}ICmZDyOc~a;h%-KKW@7m_Z zT@rab-d*=OII$%6c%rYPEB=`oiF0uskQ>L>V3U=H(0R#2|6Z?CSg4>68;!tosbt~R zhRN4Mx2p2qviPp4AQdi*>W?1{J=a>mHSyGycf@ylY;Dca?fKMKZbv%PPK1jP^6U~1 zFxCG#Um!LZq~G830!$?MY$-1QeY3stk;LK{&a7Fo6RF#RDfI_oOc~hJAzK#k2;%*+ zX<2gn4g4VH(!cXb8P$z9B#Vv%$lV+j+A@qZj-H$x{oCg0TB3r4&F03e`?Kn1o!v?^ zY9DY|w_wgK<}lQR*;S|7qQ@ea1jcoIm7!&BY#-K=z^`*#_skJ~%Jb3CfE65dR+V%S zenduq)ag0+EX6IvFKnd_y1qUc3%OHpglt{u-T`K6qoYAP8eWAM#i2DjD0k~EASeNz zB@~y0lgl@mVu65W*oD}=Wez>uDE5BLILm$NIG~LMfSwz8ZudpY{@Zqt&u5dPi&s(# zwOKv@Q(_YXy)EHy%%uld-=lKMiOs4zv-v;XZw$%RT3nHMMF_l&wsF;&STm?sZ2#C% z$mH45R`zAv;b3ibt+eO@2{!$*1h^=m5NW)&^zXCjHtN*x%YtJaxu^Rdk_R?NU;Q^8 zl)8-#p8&U_T*?{KGq-t?`yL!z%o>CMuGgV*8L-y?5c0BWe$00fNu8i3dCTWopJU`} z2W`AJp03Oq*xST@N`B%_>u)0}(+!%EQD37TSl>I^Pdj)Wu(i11sfLScqdBLh`AVRS z|AI9apd!qP$%*$@eSK+MZJt3bV&M>Kx0q5laBz2ifAm!CSNsshqH#r6r=d1xq4Efi zt|L0ZOW8Ou(Q>%F&Ykn6g9h0p4D89@iy4jR0IK{1K+vBM%l*o4Y98QtH5Xo5Z#dSq zyQMq*Y&5~2Ysyd1;uk11x0?EH)4$n*h9fl-lPd4cHKtRp{?1& zZ%h;9OPpw^|Bv{}Xf{d)cd(9q<{R}bGOu^_~HQ|0M7+9*!>@f?UPk{ z_O;j6O7=W}^|JH1p^6o*U+wO$#7VO?4bPKNQx$c4MD$A6;BoxWfMd$gOaOR1gQJgW z>($iU6vz`-D717Y+RmQK!EpH3`hy{#el@06-uXB0GqiWMS5GMnj_%FGaZ&N5E0=V# zsNf^xmmK~yx8v-cP4X%1*B|h+0+$>+9CmUnLA2^(Pv9uf4A6P+!|+BHkJ$BNh7K;9 zdXMCXgXFHjxXco{w|Aan z*G58(zo{lH{xB|A{5~+w<5frI<(CH!rlKHT4_zp3b7o<93$Jka+?QZnLojoc3CR~| zN$PWPN5)SoKPl#))16OFlq11+sF1fbT~GdZ8b=bhKga>XmaLIkf}gmKy%-pebD^1w zt{B=Ug3eN6wlk!)jl0iifV+AwBTZ z{Z%NOC|lD{?}iR|V8C0$I+|beT4T~Qyn1qj{rMdyCFp8(WkiwX>Z6tSTMH{cuIz(E@ZDT z!q!!G%%Q`&v1Z|+cwaO&JEY=4e<$4+B6#`Hv7DFfl8okn%81;-_?}4%{V5La!q@^4 zim6>0i3sx9Yljp(DBNlukJU}x%H%A5(m<#44S}6+eTd}z>^GS4aq#Xjmd5_(VUH%w zRF#2ZY{sCf?L#9NPZ+<6mULA>0steyLUQf%6{QgY8);WR$Yqg#@pZ+^GjwDd@>eG} zOBI$2P_&heetpW!j3?ZL^h944JZLMpumOnOnqWmfcXKTsUJ0shXm&&lI4t2u%x5gB z7e)jgoulr{Y4nzLQh1H{V+S~&fon$?>;^bP2xR5mja2o`(S{Wq%4n7=r@n@;|$5kH%Uyy?w-LPhiOKs7;I;)|I=d9o!etczhLj3dmGHu zQ|ecmI|BhT{uclNVVuqXwLXp3T} z)V1Z_E3%QO!tP?(0D(~bRHt@J;9w+-eC3U}<=o6Jm;Tk13VimD8*>Bq%}#civ}-k| zj)Ef4tQ;JX_@OllE5I~2K|P!HaI0@<$|GoJZ{~02j`v3U{C90~uqhezqacLIn? z$yqDI2*vlp41(2JnOXN0@=O-j4e~w-ntg}dYyP*{i+n3LCL*Xmm9XoI`d#)5a_F;K zG_N1l!{fLcQ|#y>>z3cQi+NzFoD#@e98MTPAUE-XvvI z%o%$8lgG*X=&loDJlFA~comrZX~!da>W1EUqK0yPR>^vw0l$lkj1h4C-Grb!wcuyE zO#TrzF`Rc)a{2McWmWC|#~l3x3z^#h>g6=hs~#zrM?;yY;bf6|ZHWP60a^fuWjdtl8HJBPUmMa5f=2gK12 zi}HZs9e_B~*|B z*{|50qC;%2rx$zRHsI++*a--KA$h&99p7%$z~fJIXynX4Ti$lK@`{l(SH#ZFB=$IS ze=o@_O_QzAJmDAc!OG&gE%|HeMm)<~mc>Jx-pn8WfMrvDj>^SC*{>5bxo z65^0Z1IZg1YWT$+%JHKkPMdiO zC6z#ULpV{C-^g5WLUeeOT-0zKgyt$Y2?RqWG{ zw=@|RpOemDfKUM1nm;8&--JgE`2M}6ryUZ*>XisC z`|_m1@x?48te`utc4G=Shylr=OrfGXQ*6r z*x^cxCDYD!8pR*QLk>mlIGDAEJF^3KTSD{=ba zcfpT6`oX6LQNo$aJ3m6}=MUyH{tKtB`?Ind!NszM7v9F@6q&WBdpCIJj+9%0#s1q? zxU-@RzefVtWESqNb(OB>&A~&a;q5MJ#qG}#soEMLM+pdn zRxbcLtZ(PZtbFs`_853=ukWA)c-nTgDFeQ791vTL>ADhZ*JZ(~f;(y)`fVey_wZ4L z{<_`VQt)wm_X(s>rr&N`62#HUt@`A-!Hs4(fTew$d8l;NAL&ItH3eeU^w>jJb%0?y zbJxd04R#1t77Z4CNU3BwKnshY=iK#rSJz`VjR!ZG-*q5FK56UEL*AV~GlhoVH#(O> z`|B&2;?=>Z_au4!#y*6mNE5mOc)t!%Umam%Xul2s#CVNTm;kR+&V-kmzh-kDG?&_z zywFV!Xt}xXsFZ&mQyluu2|DQtC4bSnwn5w#dkvnVsBJ9URPy0@3lrp>xDSb#J#Tsl zdt7U6pmWH>XYgUWm-k&BRaHUzinUT!GwqPktvn}(GDg<=u#-h8>VPsr1s{)U=nZC( zHn6Nb?Ac81U^N69oxcSk-%G@V9=5FB?yqT8<~E457*Hg!4M1~M#Iq~vN8VY(@!3G& zVGB?d43&eN7Eo8Wf8@TxH{p+Ec4Ys${A_^&h4)bZ26-m#<~@B3d1Y|(!}(llmVdac zQPKU|a|Ew@_5PGnJ^dp5`yS2c2aNhX z|DIKH)j}r2Ue;D%^hKQvUJFPy?Wb?lfmZOAda}(5KW97Z&`hXF>&lG{pCle-)zdm# zwc}aDq>xt`ndfubA>y*0aW7lx(Y_`mT>_vuWp;b#%EgnIOYQ-@8sDMNgx+g(Ox@>e|Go= zken)ezqTSwiH|egc1}{sb@Ca_t}NTpMN-!!RTLmFUzJ3Dqxs+}cz$h>1YFu0t=kT zhWc{oxyoVs{hb5Fc*gTJ2U`^#$JacX1=CB?OU4b(9#(yUu7d%ZnCajtdaqBf>WHWj zW&QL>hLCw-mI14{4$ zie&P2JI}Q`I*%7kPh5u+PWI}h&Ztt!IezKr^IYVHpSkOFMT|}q@FRhjN1aw3lE8-~ z@ZV_Ej;n)2oAj+<>18|J%M9YMGm$3NRi<(!q!fKf>0kQ?WBo@{Y~r#Q&F@q zPkO$8y}_m2ww3PLqi9G=*g?gJC!dS5vhNVig?0R3I$(Fl$?Ieu!)@P2>wX;hBlwmP zZ@=$6&B94BH<028!yn91IKVEBu|&DmbDP(qRYbpVQ9~$iu3CB6gk*_|=%%=EZ^^jX zoFv|=UI;e~(S}SRgXZ&*O~Z#)D{8l^?Akh0F{vO1@k<=?*c7mc;|EH*bUd_3!pBH;?&`YRDc?<%kdeMMkAM<2cQkzW!L_? zi{wK$djoBJO+Sg3IZxVvfrZ^`7haulliVKmN1-DxO~SuEVVSdi95gY#f{{9~71}X5 zTKt9iO%GcMj@BM-vEG~CR?i9=;aPK{!cR>o#o8%zZBjta0izdPLxayU(7m;erEjS zeR=QXRqn!p&3X!C0KUqqU*`Nk09aPuT`>m_6P-<$cqMz$-56Ivk7^H=Klv2yxjc>l zc?udsyEe3Nz2idL4Wuoc+fSqVt%w^$+2Ubw?>-a|crA0SVNRU`>cXx$&V(#EJ2R1z z=-*z1^Ls@X^}UnO4Qsft`lu^V`=-aOx@kWBV+i!*_UM%qjQPhl;}56pbltAN zGsYB>qiMw^o@MAX_U6tlbHTz|b#Pl}3})##xib13o?bH|ozoh|?)wdMJ$-zB#p*jz z4QJVhh}`mZ!Y3|mR{y14b-qhy7Z?Kj!Y_|t>AukoYIq$IMtX(PciQ{~86RXQkKucI zSUIU1BWGt6NzJ|$hJ-<&ZkvPv#V(#gg~GYf4mdY+TgD2at6-L6l2BA#|7OD_dx1qZoS{f9a&53X|KMMy_@QgiR+AAr(y%&04T`3){(Z0 zfJB&*?6&A?u@|oky;M)Wa$c6*XgpWkhQM2s}+MAx=2z-le631L#b z8>n>G5g+^5|3aHuGtr$P^pUgeD_C=vZ^pUPDqJa%=|kJ4MV=1j-zg6#xcJI0CN55w zs)T)f?GhW@S4R8w7}B_(7i_K4y#z4Iu5-MKyp3YFdb*SbdEvIf)2H4KXY%w9CB*5J z-Q}UT|LTm04k788gLv)@;YN@K&>&0)CUBqLbMnBysvih!eDM0+v6Zndt8;Gkh;%({U3LaTfXiA#(tr5paCeHJbgM@O zy={qzg?c>O%33SKseHd6wo(3zoPH|u%^|_l@l-SQ1%84BQxcd=s=oQ%XsR?(D0f2% z*<*wJ`wLWssNu+*eM9ia_8`*hO{k_Zj4mt2ZRczO`$)Mf|95i&_rKxBwX<;J(lqdZ zwXvhNzP6>dw!XfrzG=YUcd)z;QBi_GsD;T|m9jUm>T9_CS}uyQx^_)+70>beL`@{> zg!}qpPJa*txv=lc(ctNM%x;|%B^Dl z+|^f4`p1B@zGI{FKg+b&TEHtE5dnvs!Qd?gwfg-hv7s|LRgPbw7qW!S&0oB$`w?J@ z?{~|8ujoG6z^OM@Bk*GDBe&sck_wo88Q*m~zr#PvtYEv<%M8wb5VZ%A7=A>~Ux(wI z`KnSK(4X6l3hPhgJxG3B{Cg5#%4SawuPymuS9(gl+fA~ov*C%5n7xz|<+2zkzjEHYXz) z*7Q(fzM10wsD;|%-&X4VRzXJEp6CW*$q_PhD$c3j*?-s&N%7{i!;?hsL`^#gQ!1}D zQueAqi}(>j3)Q1eu6B<$i5?@M-*;&q)uTvLwUkvU$0qQ)kW)FR2S@j711UI5YB&k&pi(T zpmAI<*7yA{j`IpPAR<%Wq@?s=BP$xTAF4=#o^u^ht;kw`T&IwH4^=j5Oo~?>Uz@;q zy`^o=`D{XY)cPk9K}k(Cs;rMW$av*YJ@@da*h}@)5&cy4GxDC%^Wyl#Qd2k)eMiFa zB}*tb91GIR#=L=hyN#415s9)Hd(2S!$_OPICBAj(Ln9ouVn^Ty8xJW0sM_IW1}}#= zh}5l%|0Qn9a9_V)@Z|0;z#1s}A)SF{!2DvcN-)Yrs&@vlx*o~&O$F776A!*PHh+YX ze6OTJsPSQwSP?X%-LdHAq+_a=@Aa(V1ch18Xlu~D%LKbBAEoIIJ$UVC32~+fd~`u1 zWKptdY`y^flV@O~+I48-zkTV0lgUyc+E}Np87yWC}C--)@FFir`G{?cXST@EYtr#i=ZlDHZK)Qy{S&>fGNrp zPKUcWEzug%BH&ydI6V6T^6Pgvg*=4dhv8NyF>>pvI`amf`43k7!$J(yQTk9AN0^^y zVEuWM<@PO1?TGuTT~26+iU;woEl<<3uE>FhOO$LNVmHU455JkA5Idr(3lpb`VMhKF z9?9=&xMcVJ%_HHBBXV9P%h}E_#KuTw(lKH0>c!i9uO65?Etd9bk7VCuy?*Jtl;D6^ z(d}%}$CGgBLDwIdFznlV89Q(KAcBhPH#LzODpZ449Yj()Ub|nflc@ zRJUh(W1Ul?8Uw`(nfC+NrjMPqJw#ogY=MZ55H7U?!U5WUcj)|)6WN_KO%yFLljTfU zAbrjR5a3It86s6yS0DzHrT8mA$xD*aBf4|*uV!A*AOFXXXm=3V^7WryUr}c zbK)h(6++7hhHsu){hrNR-wG@D9$z?8EQVJfsUD1ZtLRV@ROD95*&*j5vcIxCX3{Mm zEf?J6z4?hPl+lnOcfm%-!>{Vy#D0O&ePemkZNvL6>5?jh#p1tZ6|k3I&7Fi&`rHGB z7tkRTko3uZSB5;$7Eg<(Cz0nRDp(-zhPvP<;+46!(7#A|J^yB-o?6(5LGsjWs>CPl z;lFb%%>|o~e4gxfR%Y)BDqV7Kz9!KE?vC&9o#vnSPz?>mdN@jvuk9?9N`vnSN8UI7 zm0Y@Goq&DNRF06$?2e4vpVS|{t7k%-dfGt*-PiEvlVLz}IIv%ME%;yI5@N~h7K7n` zoVzUfiQwgwkr6N(=|%1Un^RHlP~A~jRa2-f`lw=$161cmNyMlPT67!_tS@fw9(Q04 z{E*3z_4O^gr3r$l2Oo&EvxEQ82!%6;FUexX=796=2fLvR>d1Pv#1Uz4r71W;ieT49{4Wl$vTRz;YE9Lua|zS9BNQ*7rNEkSF$R*SqB^p;?E|qt^b#uOkEEgOmC_zTjpe6- znBmm}a7U2zYWE0rZ}tiKH9c=92kM^}Rs{60k|7YDU_wYv`Ml#)C}>?@)G|yQqk4}* zy*amkaJ)59e(^~GQs1m$C^{xj$T;yJc)t7)ojSYypuLRng98??pLG>R9ps{EGmf$_ zAMBMVuTQDD@R9zj$W;kJaE>`I@?9v=xBa4*%5tOgDZT0yAa?`6ZFncA@^(+9zVk;* zq2vM=CPh_qo>woS*VfEM{RWs}z@V;k*RF$AQ_a^>M5a=XW+R{xHnMECy?iGjenFpR(eUkq;zP)$V-d%lwvxQqX)O zpSu=g)5d4maM*c?HfUJ$JSXzmm23(2{=xBIjL&D-w5mJiP2L0Nr*RbX-u0d}BZ99Q z@4Uxv1A3VCBiwpx$XB4PD!65(X|utp3rW55J%?KMz7C8!13>?(s>^MRga+0UMrDej ztzOUc7!IhWoxr*7iU8WaJicb+4u-G3c&`_)AZ=*8kvrXAY2I#eA=vM@ZEr%DMYgC$ z`S4IduvBS@c5Ew%^#cx>%5^RO;LWA z849%L-_*p}G#MM)4ZT^1qhym&yLARPWjc6aCnO6qc*tg-jxt?fQiDkH*UOUJaF=$R z77iXU$gVe9EsP735fKrguca{P-)z-!gAS=~d#%IVQg3ao_nSuJ%+CRGOm9T|V0ser zvdAWT$!yBT00@?9^>c+Zuek>fuZV>-53LQ&x64&@=UD3mCL{V@c?lS4-BKFFW>+UX z&pEBF=si&2EFCM-tMi&`Jn)$=a!o3ks~@X(IWqC3Oze7s0&`{-8i`9((SN?KW9Qdi z@d2`w1+4UjBHG0mSH7jc75ldQA5Q5-{HbMc08(PU$){H|HR?cj%hAn*_`GeY+H;sj zg;#?`c+e+=`CCG#p8|;yK<6DPUUs*g(SGd%SBg z=yVrFLs_<0{jjK*CXyNrVIr^WzjRn|%?~a{46hYn$6;}byEGg6(swcfB&F=9m4hlY8 ztKNkVtQ}RaVby$9bup2Z==t4H_n$P4%DA@4pl#+=Uv@oZ9fpc$BS(Hee%f*nC*Dya^!D|_toku{@BT38t-eH%r0=>|fn~6?OL>7SQ zp?VbR{hIxunvBg^+zq=~WIRyFlgH)dK{i^oK5>Lh&de@>xcd#B`T~)=wfI#vW=Z_l zX4?x%MWn>qSn43Q{bZAMS9t%S;jMi0JVv|Oco|CuHBK(ECME&JlsPlTq2Y$L61|=f zF6V9*=E%iYDiIrlQi@JK7ysQJxOA_W?mo zpb<4aBQjDd?dn40BN<^$n;+j*sP>_18G-y^`05Lyf%^k$tDqUvrrBGuAL?;N#88l@ zK}Hi`s-kDftiRoH;{!Q?OR>e&1(aFcDO28{$S2y-w`KbNxO4&>2@9KW{ttRW1hxsJZKB{fTU zp5jJ7U>{a!*Y9}rx{hjN**wW5%FgNhcan%Is=gHl5$Ih>S5Ot)>iaD7bo=x0W#wS5 zK0lc?`2BiYtBPCLLQ$g*C&siSB|J1uQHF99;)@X_Jm5*BerNHoSKEWwvdXUVz}34HY1L)R=#~X z>Rs}8ac$HmG~*0B>_(d(-t5726>INy{C>dhESS}W77$hV;vnvxw zB=R~}YFxx1o)ir=HCF#DzT<^RUBP<5U61r)Y{N+|GR@ZP?WAWPlU6Ox-43UD{6IQ} zK=C{y?#x{`8jfR%(H|K3xefjE9%=~#jfx~9A)lX&=O3{$3uFYzV;RSM*_=UiMR%`J z_2KD2c_T%TIn&lTco@<6#@0dr<^U$DLU??P7M@LXxQ}jNK%vwQm5Qi=Tbpf8%QUXn z9LI0wM~J@c?6KZ}XN=qwGb`p~ANd?#ouA)?J9*7Nvra`2%Y@4e*Hj_@wJ-w$81z#}cT=FPXS6npG*`Kz-|W zw>Ob#wCL}=IL&d8@~7N#!49{cx})o6jd$?Mjbz>F{?_kF&kIi4o--|A zsLo2gmoZjr*qbeF;EkW0#rF?dgtR^3S$PNY)nVcO`>(RQ0$!Z!q3UeYk*0q{-^3kB zpU&=vm83#JXSK}DJ&cV0_b;cEQB7N@%265BUbOzS7%Z|Ey1?Wg45m zbzqRQ8y0-Me&guC(LL~3V(nuQRaboqJ}onT16K-3*)E(6gPwS6jCqxQFui7rx|W-7 z({?TDm)5uP)b#srMdspyKbFS8&zto{9R+K5^oj(6kpB`U&7TN26fnnwpUAc(hny&= zIa6wi57tsqfken!H}7UJVOadt8Hz$C-#+PoeURh~{;X-NhQNOy^6bjX1ms0Ye9iLD zNuWkuEWEDOAlY~vCMxW5R9#H;$I@!&t+wtI9w?012^Hr4NUVr7JJhoRES>}0=b_Ir zO^E&AIg2?LEdU+Y3`GRZZ%c!^uj^fJsp!{q`+?X*SDNMSih6O!)%mgXN?Tp}?p{X$ zT%U+(wXIP(ge*Okwce=*nk*<{RdD5Q?W8d7W3q0@Xe62|DlQBAU?cIv)9k>qj1iCb z*871*ou}t|8WE7g^{S}D{oP@pOc;quIjv3lV}jX&Ayz8HXX!>l~o^t5GZ)L8Oae9=QrJp_~d-*n4#;O8MOu z%Db*ho7Um9(91;EQ_8jfA?m!}l6)V&kE5w&Wo2q0cRPLP<6@{jz zIdZ3{m>ep+QNfhY_~ zGfeu{ow470;0~YF;Hn6ElQ;O;*WEVg%+KnRTfR-({J>w9Z!!h&U^WrW{X)Z2U;yFc zLK=tbLnbarZ_v@A@@8VN`<&)Ml4ty!_Zm)6EKC}e{-A0H^=F8`W}EJBqLS?fhp<#( zJ$??pkJ~R&$@xRfwtRQd!-ccb@IM#&m{XuzFQ_IlJaL>T;j$^)?J);msOMo^nf%=Z z#)f+H<-^4$zaV@VcAc;GDaiEc&?6BuS0S^B%A}v|xv~&3amm{fX6lzhm_aX`+eO7V zhHE9fJ{tm@?p@B~{$SA%v2+u1B>H8e$Y}Z~LSlcWzs`iVn{w9#;r0TAaOq9pv4Lwq zp$k|h3$OoV+QSoW3Fyc zingjp4z_wEn3E#8Nv(|0CjSpPd46e<__g^bLFVP-2aT(IlCRz@@lOnxQaD4#Qe;*( zJIRrLuRWKHO#y`VnH3Z3+pgnb4zmMVZr6%`%{CAL@W2|EH;aL3{aJUh=YPvTa$nJ_ z>>O?X6PFc@TC63M_Ro{(@1vd2e$z}9($PVzqbug{0Pf1S&(JGNP?P$IZnQpVJZPlm zXpCfzmi*1%u5u=$*Q zPe51;QQJ?JA3i(7{8k7srJeSp5ThQR5)&heg?@K@yHsukGhRr$%rRXU^wYzs>sJMLi9E1q zfnV4T3xXEpk_r=S07FoEy6$p~TO(hCZvE16v)T5U%8Ht+s~Lo(V8)o=Z98hZku*?O zN%RlNtMz))ZVy{`_e+jZTWmdg6VGG7cHzJP_tJSfR=h_Q9KOYMdD#Cu--7C6j>F?o z`2qQ!Yb7^_CeOYN)5~~lrzcHCofR!WBYtg)c@F;?lm^KwTX|bz zPN&tWcZYjU>ZgdF6Y%42@*L$c^-R44E~)CJ3`c#CK<{xb4*y3jQnU5PyA;D=j~Kp*xdNAtzz@!+K^A*)mI!q6K*ShkFTgp++9~H z?kRg~X}L{tMjuqX#qNRn7vr5nErds4d_0j5A2A&M6r1h<` zi-)hLTB&YO`426ZHN`q;OIM#m;lY!1Z9n7qBfo-I13DC5!!`r6YG?^jJNMd4G8!aF;my1? zOq!pR)(n`uOLN6nviyt<>~E75U1`AGs@KY?b&4<*wtPFyGb5zT#wm( z!H{xY58XwiUU9p8oa{%v!)>|hiX0J-t3qrx zy9F)T!ZV#4_O9`s`Ze3~wavR9mArXppBn@R26k=mQ-u-dPf1jhbJQ4kEkT~E5{iRU zt|IM&l|UM-qt#nb0t#+F&T^T$M+WTPQSNknTey4HTAR??^V;%3ZJp zywa)!5KMDiabF(W+#~kjf2SPy-c@IsxD~Vk+`*2C@_kGpteD9-W z2ubZwdO%bUcA_PzLp^J60yV|@ddfe+c62Jl1L)hJPI}qw9i}Ht1QX>KSkWo<1_W%a z^BAmZZy)L>xUDwxR*Fa_EUk0$tVI4ywfxsgeQu)OP>k@jld1Qd^ETGje;9cwYSKqF z&W&8~TE2LMx_F~Api{TSX)Q~#x33tr=1Z_kMS zH&-er!?C86jwkOZzsKTl4AN?TR3mi{g?v&$^5?*`EvbPeme)oN3U_g2cf7BJaN&0{ zjV^aBsgyTz=V;^j@4@cDD{mMyX`;k6Od~w%N63qRBIa6?W2?Eggtw~MUPTrG06?i3 z19vW+Uvbl)KkA(~u{JcDgk3Xu~V&xW0Ym zu*GnEgL*Em+i<@B)|(H4#tTIxbGG-%{&&zFIVuGknE(S{2-EoXt0ciFnFeI%IeI_Z z@Eym^*BT8W|DN}0Itzo@u4x`yo5C<3ha$*nwST#*xB9!@tC)IT)Sj^Xi{T8Q>wL5I zH&(3@5{h5Ka0;hgi#%~O)LmN}_CxhX2 znldNS0U1o`z}92j;q|NzHqV`YJ;^gn&$r5t{Jh%J6{I1z_v**ki*`-Q? zE?Mm;>8&I-;P~mxd{?`9;u|eZYG$?4xhuWnTW4=PmZuN2F4j6>Mj`nFXnT1q;w}@AAY*#*lZi*?}iS1NR48Er~ zim*M4R6RkTFi$=rKl!q0ad}wW!`^AhAPYj&gfD8DN;X{nboEAYDS_g;UO{N|PS`e~ zD-7$MUEaz!M?ZaC_;7m!m#$~`5(FF1hH**f`scy1E#8LhNV0Kzs+PTR*Q*57Q9kW( zg>S!}h>4)@z}(%XicF&$HCll%#-h)t$H^PQWs07Xv^ zSHtiyv>0u55p^YCJCoLo@tKX|CDU=+M>(Rh__7ezQwhT>WKUy+*P>s%=-n=OY zSr%^zxSa~vl07{IrFhxNSwz(`Js~;mzPSsIW;29is7K)D&fU86JZhNAkb&?mZz!v$ zq53JPD#=fMRwE+YyQQgA#i4)XuRgz=DqJjur*P$Sz+{()UI{fEors1jOv~3jRZ-6B z6?IPC*6_q>)7=B9~p|WdNy{b90CMBWpvqLRhQJn~Xd%=_5`scQ9gS zp{vdfjBHGCBV)TK=Mj;X{PKp4LHgmFxAjCA$u5NV+b~4^&*02MXvbk4)a=XH7dszzOm?%dVWc9s7DB7S8?E`7%> zwv*t=?(jU0jkkoILP@G;4j%9CgG!MU>(|pGQE)X-|IxLhV|wkf`mV&OOQo0fRC#3N z*Q7J_jxfRHd^h~Iyr^y0p4C;-_n-50sR8ZoZ96w}NBfa633l&iC@<;I$Fd<{nIOvHBrN>quZWbD+*j z%j2f`G6W|MFE2Jsc{lXxFRjFcSm!*@g=A0R$n3rS;xoc{j>^VZBkQtxz+6piWSDd- zn={E1eHqfyqXdbO`q2-4%paL*Uy%o42184)NmCtFfu{au>5!b1nvsIRh0n5^YRUl* z{L~H^f8h}Wy%n|^U*(`+Jg0xeBAkj74Rn_>JPNjc9mv{VX&9#Cf9H}Xf9|59-5|Vb z)udsR{L6Zp*~6XV#PUY>WBn*{W0Y(|5(PyF3!9Q9&-2aGebt1PG}PADmmC_{a!t>0bKc|1kb0r0R>rm+LQ$sXrMtTW!lcCCjT6kPGq$&p_6=zPGp zg*9j>eW0dR7_tzGC)=S0%zFA8^iVSdrwt-3qZ(q**EqX%X3@#)ypZ3a#p;Kr%hlTp zQBo7O8eYBI4cn7R<4V=HnrY|MH}VYRK2m@NR8VL4Wi_7tL$v0nh1QGhjCci4vNqTv zTU?LctvYREPi`R-TW61q1y-N{kA~N2dvHhiYc9^{qZ{;|UeTI=!>5(rmMl@%H7$#f z-!FWYdL=Vhc^a^_e|&mYv;I6`H0gGD5g5cRkyV6Po=)VJRsYrYc1JSA{pZro$Ev6d zKBB|KN}#1mvYsrnyZ23Ah)8_$!qZo zY23C6tIOW4pI8^NWcNGTxsVxxbAj7~u6NPnZ?Apa`FT5}EvBJHe#vsp0x&p9Wo=+J z;0rWFd8e_k3}_$NesAL~7P-;MLn)!-hN)UVsr&L*!8vc_{-pq4-7{D~gw*Rbs)}O6sJg)UIft%= zt0lc3G*qNF`}PO_YCJh_Tdo{nMG%#F+6AMT6n)sel>$U}PVKsHvkn)P+u6MKf0 z&Dy!`(>KFP4N8JP@QG?m3NPJ17`Jm(Swa*>p2t2F4-K|!=6PUg_8I(_vulF>Kn4}y z4>M$!yGu*a>nP%OIh|DTRqW+k>fqChP8C*Gcj7qH&mn}iqjTAdT3>~6nqud|Ga${f zekv%@td)pq%CC&;1F#3%n3!gV#kqxf^?*9FmwHAHmM4D&E`i9$}$ z!6Akc-iK^An2pEeW#|QoM0Kta=X#7Id-k1~FJ+IZmrPuZ^8qruKlk%2(UTCT51K@* zp(6f7{+vlO3wVSkFBER}eil_a`|4=ODoUc;`6V^)3yTaB&%%aho$Tn>iElGa@7TJ1 zbyHWi$o1wsg#_^*k}|N(9}Piv%A~6q8DXt6AEIX;E6O@`dWHHE2I{+s3xhK2+WKZk zb18koZ8ZrwAHyp2kkwCPgZ^ar(`8VjCnL5FA1s70YK<+ef@hOPA4YaeB|02rFz*At zpZj|uCE6|5l!z|;;fcI?gM4TDu3c+sxkfPQFvNlzlI<+AIIzz#lZm-*3*Jdr%=*4Y z-&tEqOrO8)rXdF+%tX}0?c(b>NP zcIsfPOq^iLz3vY8pZ=E~vAcj;l*v0trLW!PaZr10B-yma3h!eK7KvB49}Hd^;WWg? z3@PX??4htSSfla`yaJ7vm~?q`$3Mv?^)$CeeNU7({dmu~ZVbO4YAyQi=s()JBe|Pq zpKD79s9Xt=ua@6JcY=@i_dXl|vMWcZ(ZkuD4pk zj+J}(N7=WePCyd3#fg^jl18v9!FPHnS# zdXj|onUoh0xacZVwl#u<#N>Wl;=ST=#Md$FmAQaAilU=Pt=N;f5gX*@-L+~1wz=IC z%wwhu?NYG3x$>*Ba_j%TeEfdKmhf2WuX9WYUipsuaF9PV{q@S5)DO3RUr95(>wJ!B z8PPK9mP6HxZ3!+MZnmiU-KB2kn2ksSe$8+uk!%LOf~1H7lPIWzdLuIqF}n zu|$97xJgDz{aN&sub5E-aRuMJ4r9~&KFA(ve&vGr)Auiv{5Xa?o{=K*3UZelk_`{Su7OQ!BhcOh zdJ*R6`O{%`hljYefbqoGN6!MYH-oyJ4B?7Kaj?HaHx#$9?IGDPi;gZD1*S+UC-h>k~|5x?&tk~ zTzq6v$rG{>9tDKurhRV*gvaQT;T-_{dgAlxlfl z-mV(BV1&8*HYH&G$Si(mqLLLvf`nQ(JRf|Y7&S}_{mC9S2ED~5i+aQv;drA|-(>jG z4zK1#6ObU~^N3cP0q>Ose~%qVII5}B``@v#SZQO(lVI|&PiCssZ`KH#h$X#exz;dQ zGI=|rv_TFelJDw2%yb@D$j3D`UY&e(;l~f&zedM3opbzBC41lKhjYSooz}#6JYb>& zQ2n6Bj^_TUqbjmx#$c!PTbI302?^K{Ts9RI`A})-=utswoJBQ^&?uH-w^pWo>rBMI zy%BYLx!ksS8nkW$C(*9?qk9do2V|$_9|Q2hS#JfyW}ayX-EjTocxk!$gP+u|WskYg zxZ6$tITs?In#COCY~9gnDfZ_=NcI~_#??}K+vNC^D-An9e=;2taQIpUTMvJ64%6Dl z#-GMXXWsP_7W-}1+t=$T1m1a7omKk1b8GWR)9>J$h)|r5lb>u7wRJbLTK>wY3;oJ0 z6wRO)@9lS|c-Y6U$1~h*JN*yG+KB>_T_##?kH9z2nb6cR2HY=EE}Fv1=(jQi!Nt!_ znv%TDiirxgeaeoPV_z6=u^)+~{2Ocv`7yF4dCa(7TujdjGVuu+yA}}P+(%lSEY|k7 z6;eA0h7taR&kH^~Jojcc>hL|*%-@ATjcp6RcEJq9EVadg%FhAUGta6K#vu=w7IFey z6_`i%R!nPcrh)z$EM>c%qDNYOuoQr$9h^ZF@)R%QawdaS=L0~j@v*CigW1=NUT-80 zv5I*Cr+Hq<$j?RVL9Tq~6uS3&#yf*00+(915Y6lw{ z>qAVI{H;>*r@ldQp0Kd4e2NCmkPOAKkn&}z#D_|YVSBf6yRr||5vo~gZ#Jh@{R$_O z0nAT4-ne=&O!ySRisCAkz)p0zkoWi-Ox*pa0YU_tf)8tn#<$ zHmBxaZ*@q*zNcE@-$}CagJtmn1{z7w6=EP-eA^k+rK}kLIre%E9=9r?bffA9&83}M z$@S1z#-F7tl06(qhuAi1E(vD?>lslP1IA8|fsaPgg$G@hcN5~8M|+_na$;o++{nY+ z{_B+Wb`0eJf3^@Gb`_@_tyy(AFt=WNGt$| z8@ng&osxceD$l*y!73)*Rs3?q;FFc3qIA8rFHE)O!17K^s!U6;`TPp_5SObopF1I_ zZ+7Lb#99w&@{2z9ZrFPeM(=O!m4%D`0+>G*y^$l2uS!wQvkK^`w9==$yC}2uEGML3 z;0+9}!-<7gIenBd1dMRt8;>xJ{?^ z4wf^&xz8j6QHHk$_r}zI7{}R%R>EXVImSRS@HM3KylS5A8-oa9-r9-xojWZ-HzXbf zC?V}f&RD+0i}AA*9*-RF1f^@v>W(E}%K0vBExURz_=8T12y7z1y3}p)X{c;+?wU1X zBVYxwv_BEWY?^HC&b@nbiBmU1Oei2<&-T^Eq(}i4a6frtcdd8Zee?FEve6Dwld8$Y=Rqumy5gqd zh3j83bALB>0E)lXO5-*t2UsLfmv`SS0)%GLG*K6l=PP95ey%u1h#K=g)|Sm5OA>0k zj*s1GzE^qA`*~?P{9lVtPQ+>5{(coGv);m*vWdb?{ji#q5w2_gMgCo|iOnm2G&zaM z>0P@dLjW4QVWk7PA6$N))(v6Dq*5tbo?R>Q z-*+|ez5C9t^!Mt8FKa!4oEm~#^vI^gr+&nvq2|D@*ZX}j#sVWRW$fMhM{DW|xlL!3 zMra9O|A@QoJ|aBuyVe&VJ1m_ADnyeN_xxx8>;6u>j22e$36Tb4IxtQPA_x{b! z{r6@2#Mcb4@(6vm?cs?%Rp&vX23hZ{%3B!#Omh4>+AUA0&Z0OlH_u2?bnZdOssYa> za*xb+QDlE{pn}w~@${ltQA>zbO0gq{2Z9D8B3Z>KMz>7!dVzZB@65OCuB@B$aAd;W z;%P9H%Ao_IHH)0`t&;!8u&%58>>oDnKb|+VGBR)0yAlEnFz!E!Vsfojd1v>wGcyuk z)f9K;3TBdsn*WvFCbq8Jt%q3IM8(3lPMv-k0)} z7hJrw^x`I9=m#%MqWN-;bR_!6eE7t;5~-{&v1lSgQ8#~LCL*lypW4cLQRtRN3OH<# zLD3TQBRa6}EE+08-@QbO^pcQZOU{MV$^0T+Csy&Finrp6`rlxtEE#8HJ6K}qBk79p z>eb|Qb-&>CuE2qkb!ETCRdtsop+=v;PMJD8h}S#yJc^lD~8%Pm%er%UiqB_(DBgIPLz84%6PsNTUx3IeHq^ zQ{0iPm#9hjJ$If>gHb+@3ygNg=CX1LqvwD|HxT_*Dy*sC13Du$v{1NSF2xA1r1K#X zsBi)2Lf$siyGjPLZGQ;#Gd2Lpc=&Jghs8g&pAN!-9PUFz=>k{L&7+;VU0Irl-JXb;0U_K>Bdq_4AUp={4mQkcx-}ozC~N zjhzjp#O6J@Ru{RB@k4vaTQ@%wu$M~)6=AP^G z!I@eblQh~x=%rwB38knA$fK2SkoB3nlIvMV0vkrL#L>er)MG_Vq!Vj$2m2SD^bH%+ z0L?Mmy~P#Gc7VD807~vZF~9J^`of(AD^H$}HWxxFwjRC3?l>H}mGvz*DQB<9NiWSO z%9rFd^);C(&9A}_O5O&qclTpTsm&$6IsVld8CYQ+&!gLw^mVF<6C*10Me#~hLCBjG zXwC#WIh@PGveCq|P0XzeXr!(cL^NBgGe(+`c}O70xw>KeYGYv5Ovcjo-mT9r0`48v zI6UaW^zT32-@}&rJWBa)6Lj_niPh|Y4$0pRD))EwRGOcB%;j#qSWs^Lmt*+~Jhne@ z8DG(N4fT8fAw9+;S)XnZW}hjQSdnwRwcclPSB=@HG@F}vm_#2B_A~b$gUuq7_Xe*f z6AQC0dN1s{TK{n$nd0hQ=WKI%L2+l5b}|)=@F?1cdQZXN)D87n_{$=Zl4@_5UV#y++=qW6#KlBmCx=t*K<*|`17S# zUSrX{;}$Q%c}~3~RUDJ}bauCoA6^wR?4QE@PG`5I{b$$dwEN*MESK}$gkLKFF+;mLb#DCFHox0G8x;{a63G(wMJvG@Y|Ji3dOj_|~2LJ`F)5@Q! zh@C8oD2)E-+E}P2aoXcMmRp0WUaQa_=B9e8WM+FY;&60i+;tZ7Fa_s`fH-PU=QoLY zMCxCO@r4-OoW9~lb5k;_;2WdVG3eKZ@UeO&{}cM4X2Vf?Xg>X}d5tQ!ou|vulZ4)l zU1(T1txViH)n%=t8UIo~h=6-wC%FJRfqCq#ya(Y{JpPid=?PRfWj%RCQD7TAxR7ZC z`12v}^|JY^saODz>&i@=xn;0%^p>v3X)d$^^jQsEt{EpTe7uF19DxM+wX8s z#OwGNU&u?zxRU|O4zEpmO@F^VrGyN_ErF{Uj5(*t>S~HAIP7o>X+Fhsx>w;`TOOXP zi|=GB*|}`wbm6*A%IX217G3i8vo;cpr_93IU{?lbDGVo2+KVjH<+h`bVoLCrkjal|BIWe5DwkV1HtNeC#(K94f53#@)fC`->vh;>VFX#_`)iKW!tf zkUoidLj(TAxbZ8aF=U@9|hwzhr6!(tLf=1lTQO!4hwtoKOk>_)Wcz zErzEqi1G;JpM5y|LW4~04D>bLndA7h--a-9`CYt}H|r|6MMztEcIoI|pC0AFkbxk|kf<=`&j`wzycZJ5>7nXXHd-XOQA2NZ?P% zx44=^%zJw#9FTW*@X7rXYM(^oL7BXIaTkK`6-4=R1>u!98b)AFJ4sVXn%p*i+5GJ?rQ^U5Er z|9AGU+|kDwn)=zE>THYifMYM=Dj5Xi1qgBLYI2?qQNH>5nb`c$%lm2Qude*+)IiTZ zm-vRBPqbe;l=}#MG?9Mr=LYp-9XM$rn)>izIDPdC6w@46+)&3ym~4KV(@@1nh>L z-gIjJOwE)3X!x$WB4+ti+Gei5YuU<_mU)40Wq$sT$K}u@sxiGaX`RJltxy))8Z=5XLKIiLGfxm!$jBd%&?(vPe)f&aPFM@ z_L2Hd3czd;ePYgb;aoJX2o)@u_N5r`Ff4v32CPYDzaQ-jZJH{unnwvmeY;#~MtIKbalxf2?k4VI-%UbY+516yVbf!INCw5!kZ9OY5(|=kA zafzUmy8JmY+3W1i&g9#KsE6?fPtGj)oZu%KvgP4Lbsp%Rc`lp!eNC3ji%%eKFa^Su zH%vgQ9bLa?OV|EAFGM@UHY5CGUj655-H<*Y(y%^w^b$l^S^g3=@jRBl!S)8!FMlHU1=DA$$33dLC9}a0plDFSnKDg=oN%&YQ?$Tq= zz*{{#4e$q)|B5&8U z8m{^`3fs+Kcz0=6(=Z%EA%=WA$JsW;JoysmMuqJQ6bi(k{1k+R$iVi}H-wW03x!KM zN~+EiG_Exi`NB<7pgJBNOz-mMkr85+zXHIMZS%}R^VE&`LG+|@fH1~&hBbY4I8%NH zp8B2p6f5nq5vh}kQaB+2Q(*hjEQ}^CZ-JZ>e%abR!~V_MXyN!jJt6;pdcyIp7vO&6 z$}9fok?|dc8AW9kwXL<^>MOc%urKYKJW2;>tDei-qm{?$h8pP)EpJq z_q^Y}U|U6KVi7%=fi9kf)F5X-yjCbLM4SyNzrVbqrV~p&g{K|0|0VT zgRgD_p0V-uR{2g+BL7yd2nT3iPr=Mq#ZYCC#VFJ%9zWsO>RFV1H3U!7W=$y4A}0^V zC0b21ri`jhHB#J4X2bTIF;?<7gfqq0-e$`8lrLTL*B^qBVc{?dLw(|8D_wkaFUf6b zJb1|o-@#YcXRsr51{(xWkz@b>Ext3l64qUF4QyAtLjrT7iUJ3I_qHlt|M7d*{52F{ zYctL+j#2{JgVe(x_JeaaOVvZiAJ%b2&%|ZeR7`|A<^JvbxBM@kCcKN>r5aF)3+wCt zlLW+PsXh<6-B|Fe_|Egpbvf;qqI|4<=O3GYdq17>c+~Mc z1K>0(>FxPiHuu9%8La&ML9^ng)_RM!6P7dneDXZxl0dSttF<_Xmvfp^zx?eErhJvM zw}E%$DssI!)zxlkko6&|w>Nz0B1$41i#fb3Ku{ycg2GZWR>_y2J#XKfiV^n+wP0m5 zBve7%b_NT-VG}LDAWwKCC}x}dGI)nUhj2Zv?8+CK#XWNwh;~$?o5y;QJQmQ0{Yw?3M0K74bo_C+O?DpK052Wkwwmk;Pj#4J9*^-nCGY;NQDDDm?Or#AC1gzCFhG6PPs!9UH?v?10&XM`$%qe3OP)XQzBDcxZ2AJu= z&NzLJccJxo5XxRBueo5hyz}GgSzc}z1?|`rYb^~k#{hJFUcam@PVTA2R?i<|COFaK zjuDnx7UB+a@Kf_A{p(L;?JX>mXo1pWp68kJqD>lP<9;@)gF}r$9&pgrReuUhBem#1 z+PKb&^O+6Th*C*k6Q% zrvBLc!E3a4uQ0zqL$#NJGyoB2kGm$92@|}yg=m%6jv|?&mg8YJ-w}QkdbW0AC8cbq z4%5E3*Sm#x?N;1e?XpXW?J-x&b1lbuw?`x)ok)m?5IjN_kZSYEM`%^z;ULco$2~M% zuW*F<^KS}Zd=*13@)zi<4VN+*+4`jTCKB`yd^Szdh=pxqKqY9P-2mgY`H>C8i#;1ZrYo-N#@@tZ)AbPUd$vrb&S&bS?jYMD}1rn z7nnYsTGe?WMCN$4=aO<$Iu;K9q?j`Brep3p`g>=^6`H5p&+O+L&dBEZYG~tbq?Ue{ zB(*X(dmf}(kJl?+=)g5av}-Oul+ml>NIyziG&dWJ_?))%4KARn6S8c3 zcA4)JfZ*#8$lrQZwA`zRzcE4ko++pEn+pQF5x2cEpAd|RJAqx-ya%A3f1`$@q&p=2 zorV;5@6}D~ySc447rXu2F(nZqU0u4mCCsWJtL?>9Ob4y^NVDSxqE*h8Brx7o%pi%M zYu=|}tk&v)Z=pdsM+$mwS=wsbxS?4{=pGm|z0-?nTu3q;sUDH&?wTJC*j)Ml5Jp0my-UqOp$%ZVKlxAL5JJi?<&a&F= zUD@3L9sY5Fd{K%Bt7}!pn75l|Jnb?rw$+B#JsxZO_cWu1Up02ES4{?FhDO(Yc?tY$P)#ywWqHbvVU9?`d}`qlth5~xJ)&`f zApLNL{$j#CQ19)F{Udti>s9Ph_Pfde{jx3Z)4i0O?5d}i=Rq@pwt4XhWZ$5JzeOAC0hoEz@>e$ALsaA0 zY)!UT+`ptyiwpj&ypuQEZc9Q^#?5i+SFT|S#d*K7{-|G3lQK^ zuMZ4wU^`dAzJanenr__nqCQ57j8-+`Px^wdclXE%ZbTJpZs?1!n$HwCRaXxx43}_I zBz;CdWapb^Of_ZxX`+ramx)sj|JyNRj1RgYs^bWGGP}^zF(8h}87{)hQ#mBhx_gL0 zS?3&!^0r%W?j-rz-Cim5nm@c5nxYIjGy1ak!nJSWv+XyHg8R!J=>2)Meals22-{QfzO|9Xj-oy)$fm*3%XoVFS^zAM*F7kyIOsd%SaZ`%JP#kr*t z?_Ds&3{z!0eR!OZUIQBfG)~61+Kx0@7ur3eOe&^Di1s}G1RK2{7-)V%MMymB{HN65 z4okMjk*2^`(xvAM=r+H9o(Mx0zQXa!5TFW_f8oy|5oMdir5k#nPp6XQ2}zxNd z8u|_ul~Pw2p}peCkJ8snZ6gtMIj8GHoQ^1o``^)^l=&3WQJYc`4%s72XGY!$*m({thpG{ST)MbrO zgnu65iHJ+hdCv`|6O|;0Ilz8sXTO_VV_koAqUp5aRMJ9+^3II5U~;`_Mt+FWXkzjN zVTP%}+-Mg4va@|?{F<7NGmy@T76n9_0}cuRTcgfCM3A>!uhxIwldrwsBQ9HkP6GowOKbkg2y%)rFHJ4w<0)Zp1(ibuEQbXL4~Nq%QxK)b!MDbB+i zywNQ$pM1WzX)<3~XF7UHbazAb$h)`4F_i{SJ%aBGHn;_g@)zpCsNlSW%b&z~e;s*r z{b%?=SOSn{9kyl4HkSh{IWd?>hG(qsX&eRCNMI8KsD;2lV&07<^+e!TCqFu+xm$j6 zLHnK=EGUrNZyPjsPo3_{8qtzel3^I_y3^7FiohyX_R&R^qWnQi&f>X-*E|b$pYN#c zJ^)4#gPn`&M)GqRUaG1op;qu4%_6B&6ZEEJ6k+Ns)g?HGu*e&J=nb%wJaK`~#1k!6 z?^T6+V(`pP)$aAx?tMUF3$fB`((AQ5&m66?EsK~i3!%+>z?+we{Fx*3Op5GRD!wwX zN|JmD@3GhBOjQ|J7n%Q7E3wQxLw5Sx1}9+MLbs2YXqhS4fnC*5zKkn=j7? z-ps-;^|TKX+M&alNI#+J-!y0H$}i~|H7DebDhU+ZXezKe>-3=T`hI**VzOB7{`v!9 z*a)`m?kptH#?A@ZG^CqSQjCd^Png#?4oaD)Xx#{j_oO%$myUhUFhdvCU4gUe6c4AG ze|+`7>Da8$kebAM<>uFf0q-Qf*Pd1hv>+Nn|o&UAVM5wtI{6NU63W2FrQ zn%Ae*@5{tgPnE9JX({X|flU9qBj2*mb+9m>*vqm=*k4H_q$X{ml13p^KBJZXZ~oq7 zZkE-Z*is4r?u%*#Kr6zWwaaiO@G3m(Mt@jm2}j z4+>;PD0@%#e)l>VZ=Uj&r1vWj=J3V`yOX@TUn`48WrB+)OIt-F(sw$MQZ3n@xkr(d z&uhYHjS%{VQZ+H+F3BUX$Odj-38@(COd=azO}X0uykO|>l}b5+U>tp>&whXoeb2ol z8>FDBtPE3FpI?ctrU!#nK!b*<9 z+poS9aR91(&&Ka6sk=W7ol)=`yOXIq#bEtTYK-j)idp)&2*7i+QtuC41kBB_R@hFR zr{qq1ZyQ^Fu(;Gqo0O-AsvxH>-_(5EN*DR??7A{gP?O^;?LPbI15%q7RmNPwsCW1C zuh<%?B>DI2BkNCDW?S)`pG|UJEy1x1;$7%>m-(GNI2gxL!X-eSYSFK$chM)44iQiO z`@JVy@>@{1Qv)w%C86|=o^UC?g!pt~rsdn^+SR@N<_wZ`a=D=oB*cT*00G(02+m3% z)vt`s!0%1H3=bdFlhIJ4y=?x9sNVsLjws?&5&xOyP`)Lv5-~L{XLK8k*xNxL@weq8 zRQw16my`)9Ix`(q0-EZ!pH!cySbDjk>>l#ddO5)3tD5a{8nL7Q;BE;gptsn3j;o1t z_~A*%mw%oAV_QDn>^c&ew)pn7eQ`P3Jf3s)so|Z)goNWzhWOl9);jy9`i@j;Z{5+& zvb40I)I_x@*_Kk)rVou2PJc2&bcV3L(GGnyI$W4c`%}5-U&NFCgqc;-b*6e0BL{^N z-H>kfB#OqWebkjf?9}e`uA%h7<0tPq6fu#6kRyCIW?~E%;1_{k3c10LjXJ`s3Ww-I zPD@hIFnmM=9UZkEWl8ox!tCr@N6uWrX4Ahu-8?!)KR(InIe=|qlMe6e0SF9xJ|X1i z(Y#d1yJhJiLT;S*?pXfn7vz)wN7PxrHT{Nff0U>Q7=*M60*Zptxgn@Dh@eP+6p#j` zVQj+!K|)Hpq@+Z0#Mo4%BnFJGN#__a*jPV2$MbxT?@#Z4;C8T^>O9C)*?agK_j*gAac^G!Oq zcw7SmIaYV0?4uXJ^>mt*>%x)rY4XRO>wC!x01qrz(AOl2@n;gt0G<^fo|h}9FY(^@ zezh}Ci_jNhZp2sXJC%xC`XoCqer!0;AwW_>(ans%_X>FooKpeb9}~HWmhnfDLb%RZ zu!}>fX?i>d<3NxKELn>NQxe)lDG{AzWM*KnvTT8HJPh=zxo5 zviv(CFOAz%SP8jj@3teBNHe+Vgrl$RC}l%Adaz2#5+ zft*RUqu;*B2eh5^}x73Y_%|3yI}o6_}=Iguo-s6;(fl(OzMiJ2(= zUaCI;kbnJ>8YiRu-S5#%Q&E{{)cqBsY!AQt@|kgztRn5k{hPL{oVO=7y>stYsi=K! z#ctIbI;H33VQ=1>Y`boX>=7(raBGL&176ZAm3j7`Jc$=+#Hz*LO7k>!#!ihkNa5v# zD;O713nl4cStPs(fhBI~b=An1oxaVTFUwG&BjV6*P$wLvO16@jp#F_Q23OUOxn%36 zz&OT#X1w5tI=eStYr_H9VEbGPxDv`Cpmmr6zM5M7$+Pg@{6Y12WW_gtE*pK|5o3J2 z?dXhzb=WRTb?*L9owICNkOAC=AZ-3{{z3WR`Yf%Du)5vgoNp&Ba(z3ui}m-1KaWps zV0I+f9Nn#QeDeNWa<&lGVlfkd{R(4WX>@fL0_`?yieC^Axxo~K` znz@?VDT<9y-prMhINJ7SI`nPyuFP!5ercx(BI{H^*xHT4)Sk>482gnPUVvYV=K>3W z!W+e8+35pBnw(9&+dLzh4KaAoDa?@{U8(QDgch4Cuh&)XY=-Y+5w9l%^PS7qTS4IU z9Tr@Jyz$gdgDN_!jR{v#(o%(%^CdT_wH0e=F6-+h0DN_iqmEDXgwjVWdqBW@OZmjp zG5_iAJ&JxC_%t$bUx)H4JOyP*vsc z6{zMXkjf8aZiR@cPR3kj*6CziR#YA>6H6@{UF+YTmvT?lE~lio?i~AbYZ4)bTf!R! zEN`ICo)&uN4YJ0YotHeDqkAui{3O@G;b#`Il(x1v#eEJ)3v5!TM`Ujsxj04;8jf71 zV+9$DAYaPFNlpvf90cENi1^GU@8~bj+i1g^l881>>{K8yrV4mlfy!doTM3@sEv_D= z7{`>6#=IiBi5x2B;mEe{R!mU!)!P*tJ}{=aL+GrH_rt8F=9|6X-IQ8mO~N@q+qN=C zDW7bt)|}=&d)YE=NuR=ZOe4bULn3dvd)d1T?d`vE0=v&G=U;v{%{^XZuOtlnPdkj&S?-+CxF)M>@s9Z8uO^o3EdV=SLFoHvIkh*QYaR zAt4L%gjn*L&m||Se_+lIV-6QVEk>8mGFv{aAoC<5M;$11-zULyCoMO_)DA8BVk@5w zj*|Vy(%WDjJV!si*q^_c1j)M)=_5P70bZBfU3l2aG}B_BmR~XAf8Wzfy;@YWWs>vR z|7K}k#}LS;z}fU5GHFf;fJB^|dD_5_Vd&k>ca;5)&BJZyt$TNYkW~OzNpJ*DM^0(#(?K*BK|E&j-5-;*hp-t z67SxUEx1Rh7EJ9kttfrdK9XBj2US1GgOQ`7v0>rVo}y{`E?&L63&{%w8J4il#=&?gBny3e-t_I=`DtzTkn}={1sc3 zvtT+GoK{fSZ^g&ev?Gz&svGyR#Zxe_fNa{x9N<3$`<#P9%q??PC+`xcVY@qbYXnWN zqE0o0>Nq|ymsRbh>2@OaqThis+@5qR#hj|I%*r1X7x~@r@z*<$Ib|I)d9LJ~>K67= zxq`xp8hGk+SKu-W?%3)beYT+SjYC<=r#CJ}ML!eC~iu+cYtQX|19cW^BWbkLK+qa+V$kZMi>pI1m z@BO~oo&);m4Q`|6qW4w)&zKLcZ#mH-2+dP6(>P9Ec|q)E{a@EB@dk>xv4z;Cpzq6v z>`9w5Y=4GIh2*8R#AxfjR<)Jkutm@J2;c)nat`6<^1X;BJ9FbzkxCM-zJ{0HA|bxrU$EnnuO0^dK(BcLEd@QWm~Pth;^rA>hvA39_) z+yOfOgsQ`y8O)hpi@8MMWq_5lo(ldKt;qWWzH!s0UGa~H)u5J(!DnLBqN&4d%oECNXP%vR7eex^$?qdeD(!CGC zqdvW76#GR;i@`q}>0g|6c~7aT0vF!;Ix+K{|8&wcIcYX)N+}QhL9*eMo$RD|y?+t6 z?;+_Q`B)v4xJ8+jy3{bup2Y3*kgKpjP!!y7#Muyvk6)Cn;ucUGZeMZ<< zkP~-F`q>Y+61J1D)GdWhMK|Ay{eO*W%9%PfU0tM0Fy!D5%7Y>JdLw5}m9x7JJ-wYJ)+R$J1MOBNn^dw&9j*KHbb z_G<1<3Ff7L{MMt}A^j6pJgxpPjrXQXq8aC-WDhuAt}>++t?r@lpG1i77@Yr3*v$(% z4uU`d+1mj+6MD0~!HsTf$FJY;2zOaT{*zXzHL1(!WN{e!E6or6_#)M=wiV3BuPsuc zmyLGFhc)c(ZGNS{Tqdmn`#uqaNc2SDD&r+pGf8Twyb*{p2jwl99q>P3cIi11m$4}F zUO;n~fn?sB(n*2j<$k-sWqY-+>-3ZB5(Vpr@ULBay*3ZUu_r}b+$5d5g1NlDfa1KJ zDl;=HROx(nhwItTqmGkQD741mtAWKI%$mV&<&>%NL_MJ7X?CWA|K!YXvbH`}aW%C5 z%%>!Ih+l`j1ND&5u?ANNFwt1}Q=jkaY`#)kcF^?6-H~*UcL(04p@pD4-pJw0VA3`2 zNg`39F@GJWVA13$BG9*Ul0kNV;|q!IVvhWnb}~4gz|TcyssSNQki4x(*T~aqek5w4muZIH?;~Q$9_Gp( z{5PUs7Y6-V{Nzy}a9g~vKFf82y(a*dEdX z`sB-K3w2i{>A;3`a2@oB>OgvCb5xvaNTmYpmlEY|<9`RuiU4{cK$rSJ5&)!0awuef z61x(*@#dUdo_kxpM`9Ikbb;g92WGiWORcv!UkzQJ&4RI9_%PB|^SGG$RejoFn9O+W z-oFPfX-bZyyl|twN{l>)2)rV7VwBX_!*Or+8Z&f`Wgk%dAr=oqP#|l>b5iCD$&=`g zjcnxYZ!i3JN*?BhPt5JRo6LnM;mms~I~2-0;&PauP5+)0=Pz%ot(Y`D22}X#{>wVh z`>)1Tig^owU;|uq#@^)xe6b&!3&{B8E*_27ZOZwR##h{^Zp`*e!h~Rhn~N6t1c&XN zLRi1T7Td0_N;g{94UQeAAR;v991u?AzX=~|@E)l3Z9(h+uY%0Du}-8m>#3}QQ1{YP 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 +#include + +#include "sys.h" + +/* Constants */ +#define CERTS_LEN 0x280 + +/* Variables */ +static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys"; +u8 shutdown = 0; + +void __Sys_ResetCallback(void) +{ + /* Reboot console */ + Sys_Reboot(); +} + +void __Sys_PowerCallback(void) +{ + /* Poweroff console */ + shutdown = 1; +} + + +void Sys_Init(void) +{ + /* Initialize video subsytem */ + //VIDEO_Init(); + + /* Set RESET/POWER button callback */ + SYS_SetResetCallback(__Sys_ResetCallback); + SYS_SetPowerCallback(__Sys_PowerCallback); +} + +void Sys_Reboot(void) +{ + /* Restart console */ + STM_RebootSystem(); +} + +void Sys_Shutdown(void) +{ + /* Poweroff console */ + if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) { + s32 ret; + + /* Set LED mode */ + ret = CONF_GetIdleLedMode(); + if(ret >= 0 && ret <= 2) + STM_SetLedMode(ret); + + /* Shutdown to idle */ + STM_ShutdownToIdle(); + } else { + /* Shutdown to standby */ + STM_ShutdownToStandby(); + } +} + +void Sys_LoadMenu(void) +{ + /* Return to the Wii system menu */ + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); +} + +s32 Sys_GetCerts(signed_blob **certs, u32 *len) +{ + static signed_blob certificates[CERTS_LEN] ATTRIBUTE_ALIGN(32); + + s32 fd, ret; + + /* Open certificates file */ + fd = IOS_Open(certs_fs, 1); + if (fd < 0) + return fd; + + /* Read certificates */ + ret = IOS_Read(fd, certificates, sizeof(certificates)); + + /* Close file */ + IOS_Close(fd); + + /* Set values */ + if (ret > 0) { + *certs = certificates; + *len = sizeof(certificates); + } + + return ret; +} diff --git a/source/sys.h b/source/sys.h new file mode 100644 index 00000000..fbfdcac1 --- /dev/null +++ b/source/sys.h @@ -0,0 +1,20 @@ +#ifndef _SYS_H_ +#define _SYS_H_ +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +/* Prototypes */ +void Sys_Init(void); +void Sys_Reboot(void); +void Sys_Shutdown(void); +void Sys_LoadMenu(void); +s32 Sys_GetCerts(signed_blob **, u32 *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/usbstorage.c b/source/usbstorage.c new file mode 100644 index 00000000..de46e74d --- /dev/null +++ b/source/usbstorage.c @@ -0,0 +1,186 @@ +/*------------------------------------------------------------- + +usbstorage_starlet.c -- USB mass storage support, inside starlet +Copyright (C) 2009 Kwiirk + +If this driver is linked before libogc, this will replace the original +usbstorage driver by svpe from libogc +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#include +#include +#include +#include + +/* IOCTL commands */ +#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8)) +#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1) +#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2) +#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3) +#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4) +#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5) +#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6) + +#define UMS_HEAPSIZE 0x8000 + +/* Variables */ +static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc"; + +static s32 hid = -1, fd = -1; +static u32 sector_size; + + +inline s32 __USBStorage_isMEM2Buffer(const void *buffer) +{ + u32 high_addr = ((u32)buffer) >> 24; + + return (high_addr == 0x90) || (high_addr == 0xD0); +} + + +s32 USBStorage_GetCapacity(u32 *_sector_size) +{ + if (fd > 0) { + s32 ret; + + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size); + + if (ret && _sector_size) + *_sector_size = sector_size; + + return ret; + } + + return IPC_ENOENT; +} + +s32 USBStorage_Init(void) +{ + s32 ret; + + /* Already open */ + if (fd > 0) + return 0; + + /* Create heap */ + if (hid < 0) { + hid = iosCreateHeap(UMS_HEAPSIZE); + if (hid < 0) + return IPC_ENOMEM; + } + + /* Open USB device */ + fd = IOS_Open(fs, 0); + if (fd < 0) + return fd; + + /* Initialize USB storage */ + IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":"); + + /* Get device capacity */ + ret = USBStorage_GetCapacity(NULL); + if (!ret) + goto err; + + return 0; + +err: + /* Close USB device */ + if (fd > 0) { + IOS_Close(fd); + fd = -1; + } + + return -1; +} + +void USBStorage_Deinit(void) +{ + /* Close USB device */ + if (fd > 0) { + IOS_Close(fd); + fd = -1; + } +} + +s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) +{ + void *buf = (void *)buffer; + u32 len = (sector_size * numSectors); + + s32 ret; + + /* Device not opened */ + if (fd < 0) + return fd; + + /* MEM1 buffer */ + if (!__USBStorage_isMEM2Buffer(buffer)) { + /* Allocate memory */ + buf = iosAlloc(hid, len); + if (!buf) + return IPC_ENOMEM; + } + + /* Read data */ + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buf, len); + + /* Copy data */ + if (buf != buffer) { + memcpy(buffer, buf, len); + iosFree(hid, buf); + } + + return ret; +} + +s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) +{ + void *buf = (void *)buffer; + u32 len = (sector_size * numSectors); + + s32 ret; + + /* Device not opened */ + if (fd < 0) + return fd; + + /* MEM1 buffer */ + if (!__USBStorage_isMEM2Buffer(buffer)) { + /* Allocate memory */ + buf = iosAlloc(hid, len); + if (!buf) + return IPC_ENOMEM; + + /* Copy data */ + memcpy(buf, buffer, len); + } + + /* Write data */ + ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buf, len); + + /* Free memory */ + if (buf != buffer) + iosFree(hid, buf); + + return ret; +} diff --git a/source/usbstorage.h b/source/usbstorage.h new file mode 100644 index 00000000..6f8fcbf2 --- /dev/null +++ b/source/usbstorage.h @@ -0,0 +1,21 @@ +#ifndef _USBSTORAGE_H_ +#define _USBSTORAGE_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +/* Prototypes */ +s32 USBStorage_GetCapacity(u32 *); +s32 USBStorage_Init(void); +void USBStorage_Deinit(void); +s32 USBStorage_ReadSectors(u32, u32, void *); +s32 USBStorage_WriteSectors(u32, u32, void *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/utils.c b/source/utils.c new file mode 100644 index 00000000..a29f37e3 --- /dev/null +++ b/source/utils.c @@ -0,0 +1,8 @@ +#include +#include + + +u32 swap32(u32 x) +{ + return (x >> 24) | ((x << 8) & 0x00FF0000UL) | ((x >> 8) & 0x0000FF00UL) | (x << 24); +} diff --git a/source/utils.h b/source/utils.h new file mode 100644 index 00000000..3a4862bf --- /dev/null +++ b/source/utils.h @@ -0,0 +1,15 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +/* Constants */ +#define KB_SIZE 1024.0 +#define MB_SIZE 1048576.0 +#define GB_SIZE 1073741824.0 + +/* Macros */ +#define round_up(x,n) (-(-(x) & -(n))) + +/* Prototypes */ +u32 swap32(u32); + +#endif diff --git a/source/video.cpp b/source/video.cpp new file mode 100644 index 00000000..6a2ff0d5 --- /dev/null +++ b/source/video.cpp @@ -0,0 +1,327 @@ +/**************************************************************************** + * libwiigui Template + * Tantric 2009 + * + * video.cpp + * Video routines + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "input.h" +#include "libwiigui/gui.h" + +#include "cfg.h" + +#define DEFAULT_FIFO_SIZE 256 * 1024 +static unsigned int *xfb[2] = { NULL, NULL }; // Double buffered +static int whichfb = 0; // Switch +static GXRModeObj *vmode; // Menu video mode +static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32); +static Mtx GXmodelView2D; +int screenheight; +int screenwidth; + +/**************************************************************************** + * UpdatePadsCB + * + * called by postRetraceCallback in InitGCVideo - scans gcpad and wpad + ***************************************************************************/ +static void +UpdatePadsCB () +{ + #ifdef HW_RVL + WPAD_ScanPads(); + #endif + PAD_ScanPads(); + + for(int i=3; i >= 0; i--) + { + #ifdef HW_RVL + memcpy(&userInput[i].wpad, WPAD_Data(i), sizeof(WPADData)); + #endif + + userInput[i].chan = i; + userInput[i].pad.btns_d = PAD_ButtonsDown(i); + userInput[i].pad.btns_u = PAD_ButtonsUp(i); + userInput[i].pad.btns_h = PAD_ButtonsHeld(i); + userInput[i].pad.stickX = PAD_StickX(i); + userInput[i].pad.stickY = PAD_StickY(i); + userInput[i].pad.substickX = PAD_SubStickX(i); + userInput[i].pad.substickY = PAD_SubStickY(i); + userInput[i].pad.triggerL = PAD_TriggerL(i); + userInput[i].pad.triggerR = PAD_TriggerR(i); + } +} + +/**************************************************************************** + * StartGX + * + * Initialises GX and sets it up for use + ***************************************************************************/ +static void +StartGX () +{ + GXColor background = { 0, 0, 0, 0xff }; + + /*** Clear out FIFO area ***/ + memset (&gp_fifo, 0, DEFAULT_FIFO_SIZE); + + /*** Initialise GX ***/ + GX_Init (&gp_fifo, DEFAULT_FIFO_SIZE); + GX_SetCopyClear (background, 0x00ffffff); + + GX_SetDispCopyGamma (GX_GM_1_0); + GX_SetCullMode (GX_CULL_NONE); +} + +/**************************************************************************** + * ResetVideo_Menu + * + * Reset the video/rendering mode for the menu +****************************************************************************/ +void +ResetVideo_Menu() +{ + Mtx44 p; + f32 yscale; + u32 xfbHeight; + + VIDEO_Configure (vmode); + VIDEO_Flush(); + VIDEO_WaitVSync(); + if (vmode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync(); + else + while (VIDEO_GetNextField()) + VIDEO_WaitVSync(); + + // clears the bg to color and clears the z buffer + GXColor background = {0, 0, 0, 255}; + GX_SetCopyClear (background, 0x00ffffff); + + yscale = GX_GetYScaleFactor(vmode->efbHeight,vmode->xfbHeight); + xfbHeight = GX_SetDispCopyYScale(yscale); + GX_SetScissor(0,0,vmode->fbWidth,vmode->efbHeight); + GX_SetDispCopySrc(0,0,vmode->fbWidth,vmode->efbHeight); + GX_SetDispCopyDst(vmode->fbWidth,xfbHeight); + GX_SetCopyFilter(vmode->aa,vmode->sample_pattern,GX_TRUE,vmode->vfilter); + GX_SetFieldMode(vmode->field_rendering,((vmode->viHeight==2*vmode->xfbHeight)?GX_ENABLE:GX_DISABLE)); + + if (vmode->aa) + GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + else + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + // setup the vertex descriptor + // tells the flipper to expect direct data + GX_ClearVtxDesc(); + GX_InvVtxCache (); + GX_InvalidateTexAll(); + + GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc (GX_VA_CLR0, GX_DIRECT); + + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GX_SetZMode (GX_FALSE, GX_LEQUAL, GX_TRUE); + + GX_SetNumChans(1); + GX_SetNumTexGens(1); + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + guMtxIdentity(GXmodelView2D); + guMtxTransApply (GXmodelView2D, GXmodelView2D, 0.0F, 0.0F, -50.0F); + GX_LoadPosMtxImm(GXmodelView2D,GX_PNMTX0); + + guOrtho(p,0,479,0,639,0,300); + GX_LoadProjectionMtx(p, GX_ORTHOGRAPHIC); + + GX_SetViewport(0,0,vmode->fbWidth,vmode->efbHeight,0,1); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + GX_SetAlphaUpdate(GX_TRUE); +} + +/**************************************************************************** + * InitVideo + * + * This function MUST be called at startup. + * - also sets up menu video mode + ***************************************************************************/ + +void +InitVideo () +{ + VIDEO_Init(); + vmode = VIDEO_GetPreferredMode(NULL); // get default video mode + + // widescreen fix + if(CFG.widescreen) + { + vmode->viWidth = VI_MAX_WIDTH_PAL-12; + vmode->viXOrigin = ((VI_MAX_WIDTH_PAL - vmode->viWidth) / 2) + 2; + } + + VIDEO_Configure (vmode); + + screenheight = 480; + screenwidth = vmode->fbWidth; + + // Allocate the video buffers + xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode)); + xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode)); + + // A console is always useful while debugging + console_init (xfb[0], 20, 64, vmode->fbWidth, vmode->xfbHeight, vmode->fbWidth * 2); + + // Clear framebuffers etc. + VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK); + VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK); + VIDEO_SetNextFramebuffer (xfb[0]); + + // video callback + VIDEO_SetPostRetraceCallback ((VIRetraceCallback)UpdatePadsCB); + + VIDEO_SetBlack (FALSE); + VIDEO_Flush (); + VIDEO_WaitVSync (); + if (vmode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync (); + + StartGX(); + ResetVideo_Menu(); + // Finally, the video is up and ready for use :) +} + +/**************************************************************************** + * StopGX + * + * Stops GX (when exiting) + ***************************************************************************/ +void StopGX() +{ + GX_AbortFrame(); + GX_Flush(); + + VIDEO_SetBlack(TRUE); + VIDEO_Flush(); +} + +/**************************************************************************** + * Menu_Render + * + * Renders everything current sent to GX, and flushes video + ***************************************************************************/ +void Menu_Render() +{ + GX_DrawDone (); + + whichfb ^= 1; // flip framebuffer + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); + GX_CopyDisp(xfb[whichfb],GX_TRUE); + VIDEO_SetNextFramebuffer(xfb[whichfb]); + VIDEO_Flush(); + VIDEO_WaitVSync(); +} + +/**************************************************************************** + * Menu_DrawImg + * + * Draws the specified image on screen using GX + ***************************************************************************/ +void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], + f32 degrees, f32 scaleX, f32 scaleY, u8 alpha) +{ + if(data == NULL) + return; + + GXTexObj texObj; + + GX_InitTexObj(&texObj, data, width,height, GX_TF_RGBA8,GX_CLAMP, GX_CLAMP,GX_FALSE); + GX_LoadTexObj(&texObj, GX_TEXMAP0); + GX_InvalidateTexAll(); + + GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); + GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); + + Mtx m,m1,m2, mv; + width *=.5; + height*=.5; + guMtxIdentity (m1); + guMtxScaleApply(m1,m1,scaleX,scaleY,1.0); + Vector axis = (Vector) {0 , 0, 1 }; + guMtxRotAxisDeg (m2, &axis, degrees); +// guMtxConcat(m2,m1,m); + guMtxConcat(m1,m2,m); + + guMtxTransApply(m,m, xpos+width,ypos+height,0); + guMtxConcat (GXmodelView2D, m, mv); + GX_LoadPosMtxImm (mv, GX_PNMTX0); + + GX_Begin(GX_QUADS, GX_VTXFMT0,4); + GX_Position3f32(-width, -height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(width, -height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(width, height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(1, 1); + + GX_Position3f32(-width, height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(0, 1); + GX_End(); + GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0); + + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); +} + +/**************************************************************************** + * Menu_DrawRectangle + * + * Draws a rectangle at the specified coordinates using GX + ***************************************************************************/ +void Menu_DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled) +{ + u8 fmt; + long n; + int i; + f32 x2 = x+width; + f32 y2 = y+height; + Vector v[] = {{x,y,0.0f}, {x2,y,0.0f}, {x2,y2,0.0f}, {x,y2,0.0f}, {x,y,0.0f}}; + + if(!filled) + { + fmt = GX_LINESTRIP; + n = 5; + } + else + { + fmt = GX_TRIANGLEFAN; + n = 4; + } + + GX_Begin(fmt, GX_VTXFMT0, n); + for(i=0; i + +void InitVideo (); +void StopGX(); +void ResetVideo_Menu(); +void Menu_Render(); +void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], f32 degrees, f32 scaleX, f32 scaleY, u8 alphaF ); +void Menu_DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled); + +extern int screenheight; +extern int screenwidth; + +#endif diff --git a/source/video2.c b/source/video2.c new file mode 100644 index 00000000..95b54103 --- /dev/null +++ b/source/video2.c @@ -0,0 +1,136 @@ +#include +#include + +#include "sys.h" +#include "video2.h" + +/* Video variables */ +static void *framebuffer = NULL; +static GXRModeObj *vmode = NULL; + + +void Con_Init(u32 x, u32 y, u32 w, u32 h) +{ + /* Create console in the framebuffer */ + CON_InitEx(vmode, x, y, w, h); +} + +void Con_Clear(void) +{ + /* Clear console */ + printf("\x1b[2J"); + fflush(stdout); +} + +void Con_ClearLine(void) +{ + s32 cols, rows; + u32 cnt; + + printf("\r"); + fflush(stdout); + + /* Get console metrics */ + CON_GetMetrics(&cols, &rows); + + /* Erase line */ + for (cnt = 1; cnt < cols; cnt++) { + printf(" "); + fflush(stdout); + } + + printf("\r"); + fflush(stdout); +} + +void Con_FgColor(u32 color, u8 bold) +{ + /* Set foreground color */ + printf("\x1b[%u;%um", color + 30, bold); + fflush(stdout); +} + +void Con_BgColor(u32 color, u8 bold) +{ + /* Set background color */ + printf("\x1b[%u;%um", color + 40, bold); + fflush(stdout); +} + +void Con_FillRow(u32 row, u32 color, u8 bold) +{ + s32 cols, rows; + u32 cnt; + + /* Set color */ + printf("\x1b[%u;%um", color + 40, bold); + fflush(stdout); + + /* Get console metrics */ + CON_GetMetrics(&cols, &rows); + + /* Save current row and col */ + printf("\x1b[s"); + fflush(stdout); + + /* Move to specified row */ + printf("\x1b[%u;0H", row); + fflush(stdout); + + /* Fill row */ + for (cnt = 0; cnt < cols; cnt++) { + printf(" "); + fflush(stdout); + } + + /* Load saved row and col */ + printf("\x1b[u"); + fflush(stdout); + + /* Set default color */ + Con_BgColor(0, 0); + Con_FgColor(7, 1); +} + +void Video_Configure(GXRModeObj *rmode) +{ + /* Configure the video subsystem */ + VIDEO_Configure(rmode); + + /* Setup video */ + VIDEO_SetBlack(FALSE); + VIDEO_Flush(); + VIDEO_WaitVSync(); + + if (rmode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync(); +} + +void Video_SetMode(void) +{ + /* Select preferred video mode */ + vmode = VIDEO_GetPreferredMode(NULL); + + /* Allocate memory for the framebuffer */ + framebuffer = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode)); + + /* Configure the video subsystem */ + VIDEO_Configure(vmode); + + /* Setup video */ + VIDEO_SetNextFramebuffer(framebuffer); + VIDEO_SetBlack(FALSE); + VIDEO_Flush(); + VIDEO_WaitVSync(); + + if (vmode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync(); + + /* Clear the screen */ + Video_Clear(COLOR_BLACK); +} + +void Video_Clear(s32 color) +{ + VIDEO_ClearFrameBuffer(vmode, framebuffer, color); +} diff --git a/source/video2.h b/source/video2.h new file mode 100644 index 00000000..d7c916d6 --- /dev/null +++ b/source/video2.h @@ -0,0 +1,27 @@ +#ifndef _VIDEO2_H_ +#define _VIDEO2_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Prototypes */ +void Con_Init(u32, u32, u32, u32); +void Con_Clear(void); +void Con_ClearLine(void); +void Con_FgColor(u32, u8); +void Con_BgColor(u32, u8); +void Con_FillRow(u32, u32, u8); + +void Video_Configure(GXRModeObj *); +void Video_SetMode(void); +void Video_Clear(s32); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/wbfs.c b/source/wbfs.c new file mode 100644 index 00000000..0554bb0c --- /dev/null +++ b/source/wbfs.c @@ -0,0 +1,531 @@ +#include +#include +#include +#include +#include + +#include "sdhc.h" +#include "usbstorage.h" +#include "utils.h" +#include "video.h" +#include "wdvd.h" +#include "wbfs.h" + +#include "libwbfs/libwbfs.h" + +/* Constants */ +#define MAX_NB_SECTORS 32 + +/* WBFS HDD */ +static wbfs_t *hdd = NULL; + +/* WBFS callbacks */ +static rw_sector_callback_t readCallback = NULL; +static rw_sector_callback_t writeCallback = NULL; + +/* Variables */ + +static u32 nb_sectors, sector_size; +void __WBFS_Spinner(s32 x, s32 max) +{ + static time_t start; + static u32 expected; + + f32 percent, size; + u32 d, h, m, s; + + /* First time */ + if (!x) { + start = time(0); + expected = 300; + } + + /* Elapsed time */ + d = time(0) - start; + + if (x != max) { + /* Expected time */ + if (d) + expected = (expected * 3 + d * max / x) / 4; + + /* Remaining time */ + d = (expected > d) ? (expected - d) : 0; + } + + /* Calculate time values */ + h = d / 3600; + m = (d / 60) % 60; + s = d % 60; + + /* Calculate percentage/size */ + percent = (x * 100.0) / max; + size = (hdd->wii_sec_sz / GB_SIZE) * max; + + //Con_ClearLine(); + + /* Show progress */ + if (x != max) { + printf(" %.2f%% of %.2fGB (%c) ETA: %d:%02d:%02d\r", percent, size, "/|\\-"[(x / 10) % 4], h, m, s); + fflush(stdout); + } else + printf(" %.2fGB copied in %d:%02d:%02d\n", size, h, m, s); +} + +wbfs_t *GetHddInfo(void) +{ + return hdd; +} + +s32 __WBFS_ReadDVD(void *fp, u32 lba, u32 len, void *iobuf) +{ + void *buffer = NULL; + + u64 offset; + u32 mod, size; + s32 ret; + + /* Calculate offset */ + offset = ((u64)lba) << 2; + + /* Calcualte sizes */ + mod = len % 32; + size = len - mod; + + /* Read aligned data */ + if (size) { + ret = WDVD_UnencryptedRead(iobuf, size, offset); + if (ret < 0) + goto out; + } + + /* Read non-aligned data */ + if (mod) { + /* Allocate memory */ + buffer = memalign(32, 0x20); + if (!buffer) + return -1; + + /* Read data */ + ret = WDVD_UnencryptedRead(buffer, 0x20, offset + size); + if (ret < 0) + goto out; + + /* Copy data */ + memcpy(iobuf + size, buffer, mod); + } + + /* Success */ + ret = 0; + +out: + /* Free memory */ + if (buffer) + free(buffer); + + return ret; +} + +s32 __WBFS_ReadUSB(void *fp, u32 lba, u32 count, void *iobuf) +{ + u32 cnt = 0; + s32 ret; + + /* Do reads */ + while (cnt < count) { + void *ptr = ((u8 *)iobuf) + (cnt * sector_size); + u32 sectors = (count - cnt); + + /* Read sectors is too big */ + if (sectors > MAX_NB_SECTORS) + sectors = MAX_NB_SECTORS; + + /* USB read */ + ret = USBStorage_ReadSectors(lba + cnt, sectors, ptr); + if (ret < 0) + return ret; + + /* Increment counter */ + cnt += sectors; + } + + return 0; +} + +s32 __WBFS_WriteUSB(void *fp, u32 lba, u32 count, void *iobuf) +{ + u32 cnt = 0; + s32 ret; + + /* Do writes */ + while (cnt < count) { + void *ptr = ((u8 *)iobuf) + (cnt * sector_size); + u32 sectors = (count - cnt); + + /* Write sectors is too big */ + if (sectors > MAX_NB_SECTORS) + sectors = MAX_NB_SECTORS; + + /* USB write */ + ret = USBStorage_WriteSectors(lba + cnt, sectors, ptr); + if (ret < 0) + return ret; + + /* Increment counter */ + cnt += sectors; + } + + return 0; +} + +s32 __WBFS_ReadSDHC(void *fp, u32 lba, u32 count, void *iobuf) +{ + u32 cnt = 0; + s32 ret; + + /* Do reads */ + while (cnt < count) { + void *ptr = ((u8 *)iobuf) + (cnt * sector_size); + u32 sectors = (count - cnt); + + /* Read sectors is too big */ + if (sectors > MAX_NB_SECTORS) + sectors = MAX_NB_SECTORS; + + /* SDHC read */ + ret = SDHC_ReadSectors(lba + cnt, sectors, ptr); + if (!ret) + return -1; + + /* Increment counter */ + cnt += sectors; + } + + return 0; +} + +s32 __WBFS_WriteSDHC(void *fp, u32 lba, u32 count, void *iobuf) +{ + u32 cnt = 0; + s32 ret; + + /* Do writes */ + while (cnt < count) { + void *ptr = ((u8 *)iobuf) + (cnt * sector_size); + u32 sectors = (count - cnt); + + /* Write sectors is too big */ + if (sectors > MAX_NB_SECTORS) + sectors = MAX_NB_SECTORS; + + /* SDHC write */ + ret = SDHC_WriteSectors(lba + cnt, sectors, ptr); + if (!ret) + return -1; + + /* Increment counter */ + cnt += sectors; + } + + return 0; +} + +s32 WBFS_Init(u32 device) +{ + s32 ret; + + switch (device) { + case WBFS_DEVICE_USB: + /* Initialize USB storage */ + ret = USBStorage_Init(); + if (ret >= 0) { + /* Setup callbacks */ + readCallback = __WBFS_ReadUSB; + writeCallback = __WBFS_WriteUSB; + /* Device info */ + /* Get USB capacity */ + nb_sectors = USBStorage_GetCapacity(§or_size); + if (!nb_sectors) + return -1; + } + else + return ret; + break; + case WBFS_DEVICE_SDHC: + /* Initialize SDHC */ + ret = SDHC_Init(); + + if (ret) { + /* Setup callbacks */ + readCallback = __WBFS_ReadSDHC; + writeCallback = __WBFS_WriteSDHC; + + /* Device info */ + nb_sectors = 0; + sector_size = SDHC_SECTOR_SIZE; + } + else + return -1; + break; + } + + return 0; +} +//s32 WBFS_Init(void) +//{ +// s32 ret; +// +// /* Initialize USB storage */ +// ret = USBStorage_Init(); +// if (ret < 0) +// return ret; +// +// /* Get USB capacity */ +// nb_sectors = USBStorage_GetCapacity(§or_size); +// if (!nb_sectors) +// return -1; +// +// return 0; +//} + +/* +s32 WBFS_Init(u32 device, u32 timeout) +{ + u32 cnt; + s32 ret; + + // Wrong timeout + if (!timeout) + return -1; + + // Try to mount device + for (cnt = 0; cnt < timeout; cnt++) { + switch (device) { + case WBFS_DEVICE_USB: { + // Initialize USB storage + ret = USBStorage_Init(); + + if (ret >= 0) { + // Setup callbacks + readCallback = __WBFS_ReadUSB; + writeCallback = __WBFS_WriteUSB; + + // Device info + nb_sectors = USBStorage_GetCapacity(§or_size); + + goto out; + } + } + + case WBFS_DEVICE_SDHC: { + // Initialize SDHC + ret = SDHC_Init(); + + if (ret) { + // Setup callbacks + readCallback = __WBFS_ReadSDHC; + writeCallback = __WBFS_WriteSDHC; + + // Device info + nb_sectors = 0; + sector_size = SDHC_SECTOR_SIZE; + + goto out; + } else + ret = -1; + } + + default: + return -1; + } + + // Sleep 1 second + sleep(1); + } + +out: + return ret; +} +*/ + +s32 WBFS_Open(void) +{ + /* Close hard disk */ + if (hdd) + wbfs_close(hdd); + + /* Open hard disk */ + hdd = wbfs_open_hd(readCallback, writeCallback, NULL, sector_size, nb_sectors, 0); + if (!hdd) + return -1; + + return 0; +} + +s32 WBFS_Close(void) + +{ + /* Close hard disk */ + if (hdd) + wbfs_close(hdd); + + return 0; +} + +s32 WBFS_Format(u32 lba, u32 size) +{ + wbfs_t *partition = NULL; + + /* Reset partition */ + partition = wbfs_open_partition(readCallback, writeCallback, NULL, sector_size, size, lba, 1); + if (!partition) + return -1; + + /* Free memory */ + wbfs_close(partition); + + return 0; +} + +s32 WBFS_GetCount(u32 *count) +{ + /* No device open */ + if (!hdd) + return -1; + + /* Get list length */ + *count = wbfs_count_discs(hdd); + + return 0; +} + +s32 WBFS_GetHeaders(void *outbuf, u32 cnt, u32 len) +{ + u32 idx, size; + s32 ret; + + /* No device open */ + if (!hdd) + return -1; + + for (idx = 0; idx < cnt; idx++) { + u8 *ptr = ((u8 *)outbuf) + (idx * len); + + /* Get header */ + ret = wbfs_get_disc_info(hdd, idx, ptr, len, &size); + if (ret < 0) + return ret; + } + + return 0; +} + +s32 WBFS_CheckGame(u8 *discid) +{ + wbfs_disc_t *disc = NULL; + + /* Try to open game disc */ + disc = wbfs_open_disc(hdd, discid); + if (disc) { + /* Close disc */ + wbfs_close_disc(disc); + + return 1; + } + + return 0; +} + +s32 WBFS_AddGame(void) +{ + s32 ret; + + /* No device open */ + if (!hdd) + return -1; + + /* Add game to device */ + ret = wbfs_add_disc(hdd, __WBFS_ReadDVD, NULL, __WBFS_Spinner, ALL_PARTITIONS, 0); + if (ret < 0) + return ret; + + return 0; +} + +s32 WBFS_RemoveGame(u8 *discid) +{ + s32 ret; + + /* No device open */ + if (!hdd) + return -1; + + /* Remove game from USB device */ + ret = wbfs_rm_disc(hdd, discid); + if (ret < 0) + return ret; + + return 0; +} + +s32 WBFS_GameSize(u8 *discid, f32 *size) +{ + wbfs_disc_t *disc = NULL; + + u32 sectors; + + /* No device open */ + if (!hdd) + return -1; + + /* Open disc */ + disc = wbfs_open_disc(hdd, discid); + if (!disc) + return -2; + + /* Get game size in sectors */ + sectors = wbfs_sector_used(hdd, disc->header); + + /* Close disc */ + wbfs_close_disc(disc); + + /* Copy value */ + *size = (hdd->wbfs_sec_sz / GB_SIZE) * sectors; + + return 0; +} + +s32 WBFS_DiskSpace(f32 *used, f32 *free) +{ + f32 ssize; + u32 cnt; + + /* No device open */ + if (!hdd) + return -1; + + /* Count used blocks */ + cnt = wbfs_count_usedblocks(hdd); + + /* Sector size in GB */ + ssize = hdd->wbfs_sec_sz / GB_SIZE; + + /* Copy values */ + *free = ssize * cnt; + *used = ssize * (hdd->n_wbfs_sec - cnt); + + return 0; +} + +s32 WBFS_RenameGame(u8 *discid, const void *newname) +{ + s32 ret; + + /* No USB device open */ + if (!hdd) + return -1; + ret = wbfs_ren_disc(hdd, discid,(u8*)newname); + if (ret < 0) + return ret; + + return 0; +} diff --git a/source/wbfs.h b/source/wbfs.h new file mode 100644 index 00000000..7c177e47 --- /dev/null +++ b/source/wbfs.h @@ -0,0 +1,43 @@ +#ifndef _WBFS_H_ +#define _WBFS_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "libwbfs/libwbfs.h" +/* Device list */ +enum { + WBFS_DEVICE_USB = 1, /* USB device */ + WBFS_DEVICE_SDHC /* SDHC device */ +}; + +/* Macros */ +#define WBFS_MIN_DEVICE 1 +#define WBFS_MAX_DEVICE 2 + +/* Prototypes */ + +s32 WBFS_Init(u32); +s32 WBFS_Open(void); +s32 WBFS_Close(void); +s32 WBFS_Format(u32, u32); +s32 WBFS_GetCount(u32 *); +s32 WBFS_GetHeaders(void *, u32, u32); +s32 __WBFS_ReadDVD(void *fp, u32 lba, u32 len, void *iobuf); +wbfs_t *GetHddInfo(void); +s32 WBFS_CheckGame(u8 *); +s32 WBFS_AddGame(void); +s32 WBFS_RemoveGame(u8 *); +s32 WBFS_GameSize(u8 *, f32 *); +s32 WBFS_DiskSpace(f32 *, f32 *); +s32 WBFS_RenameGame(u8 *, const void *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/wdvd.c b/source/wdvd.c new file mode 100644 index 00000000..352ae5ba --- /dev/null +++ b/source/wdvd.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include + +/* 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_STOPMOTOR 0xE3 +#define IOCTL_DI_SETUSBMODE 0xF4 +#define IOCTL_DI_SETWBFSMODE 0xfe +#define IOCTL_DI_DISABLERESET 0xF6 + +/* 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Reset drive */ + inbuf[0] = IOCTL_DI_RESET << 24; + inbuf[1] = 1; + + 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Read disc ID */ + inbuf[0] = IOCTL_DI_READID << 24; + + 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Drive seek */ + inbuf[0] = IOCTL_DI_SEEK << 24; + inbuf[1] = (u32)(offset >> 2); + + 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); + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Set offset */ + inbuf[0] = IOCTL_DI_OFFSET << 24; + inbuf[1] = (off[0]) ? 1: 0; + inbuf[2] = (off[1] >> 2); + + 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Stop laser */ + inbuf[0] = IOCTL_DI_STOPLASER << 24; + + 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Stop motor */ + inbuf[0] = IOCTL_DI_STOPMOTOR << 24; + + 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) +{ + u8 *vector = NULL; + + u32 *buffer = NULL; + s32 ret; + + /* Allocate memory */ + buffer = (u32 *)memalign(32, 0x5000); + if (!buffer) + return -1; + + /* Set vector pointer */ + vector = (u8 *)buffer; + + memset(buffer, 0, 0x5000); + + /* Open partition */ + buffer[0] = (u32)(buffer + 0x10); + buffer[1] = 0x20; + buffer[3] = 0x024A; + buffer[6] = (u32)(buffer + 0x380); + buffer[7] = 0x49E4; + buffer[8] = (u32)(buffer + 0x360); + buffer[9] = 0x20; + + buffer[(0x40 >> 2)] = IOCTL_DI_OPENPART << 24; + buffer[(0x40 >> 2) + 1] = offset >> 2; + + ret = IOS_Ioctlv(di_fd, IOCTL_DI_OPENPART, 3, 2, (ioctlv *)vector); + + /* Free memory */ + free(buffer); + + if (ret < 0) + return ret; + + return (ret == 1) ? 0 : -ret; +} + +s32 WDVD_ClosePartition(void) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Close partition */ + inbuf[0] = IOCTL_DI_CLOSEPART << 24; + + 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Unencrypted read */ + inbuf[0] = IOCTL_DI_UNENCREAD << 24; + inbuf[1] = len; + inbuf[2] = (u32)(offset >> 2); + + 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Disc read */ + inbuf[0] = IOCTL_DI_READ << 24; + inbuf[1] = len; + inbuf[2] = (u32)(offset >> 2); + + 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_WaitForDisc(void) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Wait for disc */ + inbuf[0] = IOCTL_DI_WAITCVRCLOSE << 24; + + 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) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Get cover status */ + inbuf[0] = IOCTL_DI_GETCOVER << 24; + + 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_DisableReset(u8 val) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Disable/Enable reset */ + inbuf[0] = IOCTL_DI_DISABLERESET << 24; + inbuf[1] = val; + + ret = IOS_Ioctl(di_fd, IOCTL_DI_DISABLERESET, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf)); + if (ret < 0) + return ret; + + return (ret == 1) ? 0 : -ret; +} + +s32 WDVD_SetUSBMode(u8 *id, int ios222) +{ + s32 ret; + + memset(inbuf, 0, sizeof(inbuf)); + + /* Set USB mode */ + if(ios222 == 1) { + inbuf[0] = IOCTL_DI_SETWBFSMODE << 24; + } else { + inbuf[0] = IOCTL_DI_SETUSBMODE << 24; + } + inbuf[1] = (id) ? 1 : 0; + + /* Copy ID */ + if (id) + memcpy(&inbuf[2], id, 6); + + ret = IOS_Ioctl(di_fd, IOCTL_DI_SETUSBMODE, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf)); + if (ret < 0) + return ret; + + return (ret == 1) ? 0 : -ret; +} diff --git a/source/wdvd.h b/source/wdvd.h new file mode 100644 index 00000000..3626d59f --- /dev/null +++ b/source/wdvd.h @@ -0,0 +1,35 @@ +#ifndef _WDVD_H_ +#define _WDVD_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* 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); +s32 WDVD_ClosePartition(void); +s32 WDVD_UnencryptedRead(void *, u32, u64); +s32 WDVD_Read(void *, u32, u64); +s32 WDVD_WaitForDisc(void); +s32 WDVD_GetCoverStatus(u32 *); +s32 WDVD_DisableReset(u8); +s32 WDVD_SetUSBMode(u8 *, int ios222); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/wpad.c b/source/wpad.c new file mode 100644 index 00000000..2f8df22b --- /dev/null +++ b/source/wpad.c @@ -0,0 +1,71 @@ +#include +#include + +#include "sys.h" +#include "wpad.h" + +/* Constants */ +#define MAX_WIIMOTES 4 + +extern u8 shutdown; + +void __Wpad_PowerCallback(s32 chan) +{ + /* Poweroff console */ + shutdown = 1; +} + + +s32 Wpad_Init(void) +{ + s32 ret; + + /* Initialize Wiimote subsystem */ + ret = WPAD_Init(); + if (ret < 0) + return ret; + + /* Set POWER button callback */ + WPAD_SetPowerButtonCallback(__Wpad_PowerCallback); + + return ret; +} + +void Wpad_Disconnect(void) +{ + u32 cnt; + + /* Disconnect Wiimotes */ + for (cnt = 0; cnt < MAX_WIIMOTES; cnt++) + WPAD_Disconnect(cnt); + + /* Shutdown Wiimote subsystem */ + WPAD_Shutdown(); +} + +u32 Wpad_GetButtons(void) +{ + u32 buttons = 0, cnt; + + /* Scan pads */ + WPAD_ScanPads(); + + /* Get pressed buttons */ + for (cnt = 0; cnt < MAX_WIIMOTES; cnt++) + buttons |= WPAD_ButtonsDown(cnt); + + return buttons; +} + +u32 Wpad_WaitButtons(void) +{ + u32 buttons = 0; + + /* Wait for button pressing */ + while (!buttons) { + buttons = Wpad_GetButtons(); + VIDEO_WaitVSync(); + } + + return buttons; +} diff --git a/source/wpad.h b/source/wpad.h new file mode 100644 index 00000000..2679c8a9 --- /dev/null +++ b/source/wpad.h @@ -0,0 +1,23 @@ +#ifndef _WPAD_H_ +#define _WPAD_H_ + +#include + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Prototypes */ +s32 Wpad_Init(void); +void Wpad_Disconnect(void); +u32 Wpad_GetButtons(void); +u32 Wpad_WaitButtons(void); + +#ifdef __cplusplus +} +#endif + +#endif