Compare commits

...

3 Commits

Author SHA1 Message Date
dimok321 7210addaf2 *Added support for starting .wbfs game files from fat32/ntfs partitions on a sector size > 512 (tested with 4096)
*modified libcustomfat and ntfs fragment fetch function to support >512 bytes per sector
*Added new ehcmodule (thanks rodries)
*Added real support of using both ports simultaniously without shutting down the other (thanks rodries for the ehcmodule works on this). There is no longer the limitation that the settings have to be on SD card for this. (ONLY HERMES CIOS)
*Moved a few settings to Feature Settings and added a new Hard Drive Settings
*Changed Wiinnertag path to only point to the path and not to the file. You must correct the path manually in custom path settings or reset you configs for this change or Winnertag won't work!!
*Removed a few compile warnings for devkitPPC R23
2011-06-22 17:57:37 +00:00
dimok321 e510233154 *Added new ehcmodules with better and more drives support on Hermes IOS (thx rodries)
*Fixed reset of the loader when loading game with IOS reload and disabled WiiTDB titles (Issue 1874)
*Added new 'Inherit' or 'Use global' setting for game settings. If that option is set than the global setting is used for that option. (Issue 1842)
*Fixed timeout timer on startup to count correctly. (Issue 1907)
*Added two new video modes to force progressive video mode, 'FORCE PAL480p' and 'FORCE NTSC480p' (basically the same but oh well) (Issue 1902)
*Added the new 'Return to' procedure for the d2x v4 IOS for Test purpose (didn't test it, need feedback on this one). The old method is used if this procedure fails. Please test it on problematic games (e.g. PoP). (Issue 1892)
2011-05-28 19:52:00 +00:00
dimok321 0e7d37b18b *Fixed crash with loading .iso files
*Fixed freeze in theme menu when its empty
*Optimized the game list loading on fat/ntfs/ext. This should speed up the loading process.
*Added cache of game titles. This will speed up the startup after the cache file is written (in other words on second start of this rev). A TitlesCache.bin will be created in the same path as the wiitdb.xml for this. This should especial speed up the startup of fat/ntfs/ext partitions by a lot if no sub folders with the game titles are used, like GAMEID.wbfs only. That must have been painfully slow before on a lot of games. Should be at about the same speed as with sub folders now. I would still recommend to use sub folders.
*Removed wiilight (disc slot) blinking when switching USB port on Hermes cIOSes (thanks rodries)
*Added the ehcmodule sources from rodries to the branches
*Updated language files
2011-02-11 17:41:52 +00:00
679 changed files with 27269 additions and 103876 deletions

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>2.0 r1069</version>
<release_date>201102061836</release_date>
<no_ios_reload/>
<short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
Features are automatic widescreen detection, coverdownload, parental control, theme support and many more.
Credits:
Coding: Dimok, nIxx, giantpune, ardi, Hungyip84, DrayX7, Lustar, r-win, WiiShizzza
Artworks: cyrex, NeoRame
WiiTDB / Hosting covers: Lustar
Hosting updates files: CorneliousJD
USBLoader sources: Waninkoko, Kwiirk, Hermes
Languages files updates: Kinyo and translaters
Hosting themes: Deak Phreak
Libwiigui: Tantric
Libogc/Devkit: Shagkur and Wintermute
FreeTypeGX: Armin Tamzarian.
Links:
USB Loader GX Project Page and Support Site:
http://code.google.com/p/usbloader-gui/
Help Website:
http://usbloadergx.koureio.net/
WiiTDB Site:
http://wiitdb.com
Themes Site:
http://wii.spiffy360.com
Languages Translaters Page:
http://gbatemp.net/index.php?showtopic=155252
Libwiigui Website:
http://wiibrew.org/wiki/Libwiigui/
FreeTypeGX Project Page:
http://code.google.com/p/freetypegx/
Gettext Official Page:
http://www.gnu.org/software/gettext/gettext.html
</long_description>
</app>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
#
# to use this file rename Make.config.default to Make.config
# or create a new Make.config
#
# you can here add defines
#
# in example i have included a switch to diseble
# the gecko-debug stuff. so also in source gecko.c+gecko.h
#
# NOTE when add, remove or change a define here then a "make clean" is needed
#
CFLAGS += -DNO_DEBUG DDEBUG_WBFS

281
Makefile
View File

@ -1,281 +0,0 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := boot
BUILD := build
SOURCES := source \
source/libwiigui \
source/images \
source/fonts \
source/sounds \
source/Controls \
source/system \
source/libs/libwbfs \
source/language \
source/mload \
source/mload/modules \
source/patches \
source/usbloader \
source/xml \
source/network \
source/settings \
source/settings/menus \
source/prompts \
source/wad \
source/banner \
source/BoxCover \
source/cheats \
source/homebrewboot \
source/themes \
source/menu \
source/memory \
source/FileOperations \
source/ImageOperations \
source/SoundOperations \
source/utils \
source/utils/minizip \
source/usbloader/wbfs
DATA := data
INCLUDES := source
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O3 -Wall -Wno-multichar -Wno-unused-parameter -Wextra $(MACHDEP) $(INCLUDE)
CXXFLAGS = -Xassembler -aln=$@.lst $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00000,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size
-include $(PROJECTDIR)/Make.config
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lpngu -lpng -lgd -lm -lz -lwiiuse -lbte -lasnd -logc -lfreetype -lvorbisidec \
-lmad -lmxml -ljpeg -lzip -lcustomfat -lcustomntfs -lcustomext2fs
#---------------------------------------------------------------------------------
# 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 PROJECTDIR := $(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
#---------------------------------------------------------------------------------
SVNREV := $(shell bash ./svnrev.sh)
export CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
export CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
ELFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.elf)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin)))
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)))
WAVFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.wav)))
DOLFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.dol)))
MP3FILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.mp3)))
#---------------------------------------------------------------------------------
# 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) $(addsuffix .o,$(DOLFILES))\
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(MP3FILES:.mp3=.mp3.o) \
$(WAVFILES:.wav=.wav.o) $(addsuffix .o,$(ELFFILES)) $(CURDIR)/data/magic_patcher.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$(CURDIR)/source/libs/libfat/ \
-L$(CURDIR)/source/libs/libntfs/ -L$(CURDIR)/source/libs/libext2fs/ \
-L$(LIBOGC_LIB)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) lang all clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@/bin/bash ./buildtype.sh
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
# @echo debug...
# start geckoreader.exe
channel:
@[ -d build ] || mkdir -p build
@/bin/bash ./buildtype.sh FULLCHANNEL
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
lang:
@[ -d build ] || mkdir -p build
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
#---------------------------------------------------------------------------------
theme:
@[ -d build ] || mkdir -p build
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
#---------------------------------------------------------------------------------
all:
@[ -d build ] || mkdir -p build
@./buildtype.sh
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile language
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
run:
$(MAKE)
@echo Done building ...
@echo Now Run That Shit ...
wiiload $(OUTPUT).dol
#---------------------------------------------------------------------------------
reload:
wiiload -r $(OUTPUT).dol
#---------------------------------------------------------------------------------
release:
$(MAKE)
cp boot.dol ./hbc/boot.dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
language: $(wildcard $(PROJECTDIR)/Languages/*.lang) $(wildcard $(PROJECTDIR)/Themes/*.them)
#---------------------------------------------------------------------------------
# This rule links in binary data with .ttf, .png, and .mp3 extensions
#---------------------------------------------------------------------------------
%.elf.o : %.elf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.dol.o : %.dol
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.ttf.o : %.ttf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.png.o : %.png
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.ogg.o : %.ogg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.pcm.o : %.pcm
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.wav.o : %.wav
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.mp3.o : %.mp3
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.certs.o : %.certs
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.dat.o : %.dat
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.bin.o : %.bin
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.tik.o : %.tik
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
%.tmd.o : %.tmd
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
export PATH := $(PROJECTDIR)/gettext-bin:$(PATH)
%.pot: $(CFILES) $(CPPFILES)
@echo Updating Languagefiles ...
@touch $(PROJECTDIR)/Languages/$(TARGET).pot
@xgettext -C -cTRANSLATORS --from-code=utf-8 --sort-output --no-wrap --no-location -ktr -ktrNOOP -o$(PROJECTDIR)/Languages/$(TARGET).pot -p $@ $^
@echo Updating Themefiles ...
@touch $(PROJECTDIR)/Themes/$(TARGET).pot
@xgettext -C -cTRANSLATORS --from-code=utf-8 -F --no-wrap --add-location -kthInt -kthColor -kthAlign -o$(PROJECTDIR)/Themes/$(TARGET).pot -p $@ $^
%.lang: $(PROJECTDIR)/Languages/$(TARGET).pot
@msgmerge -U -N --no-wrap --no-location --backup=none -q $@ $<
@touch $@
%.them: $(PROJECTDIR)/Themes/$(TARGET).pot
@msgmerge -U -N --no-wrap --no-location --backup=none -q $@ $<
@touch $@
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

View File

@ -1,431 +0,0 @@
# USB Loader GX theme source file.
# don't delete/change this line (é).
# ONLY the value before the '-' char needs to be entered in msgstr ""
# not the complete text.
# It is important that the image folder is defined for the images to load.
# The image folder should be in the same folder as the .them file and include the theme images.
msgid ""
msgstr ""
"Project-Id-Version: USB Loader GX\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-01-20 15:51+0100\n"
"PO-Revision-Date: 2009-10-01 01:00+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Theme-Title: Example\n"
"Image-Folder: Example\n"
"Last-Themer: Example\n"
"Theme-Team: Example\n"
"Theme-Version: Example\n"
msgid "r=0 g=0 b=0 a=255 - prompt windows text color"
msgstr ""
msgid "r=0 g=0 b=0 a=255 - settings text color"
msgstr ""
msgid "9 - game list browser page size"
msgstr ""
msgid "r=0 g=0 b=0 a=255 - game browser list text color"
msgstr ""
msgid "r=0 g=0 b=0 a=255 - game browser list text color over"
msgstr ""
msgid "left - carousel layout left arrow align hor"
msgstr ""
msgid "top - carousel layout left arrow align ver"
msgstr ""
msgid "20 - carousel layout left arrow pos x"
msgstr ""
msgid "65 - carousel layout left arrow pos y"
msgstr ""
msgid "right - carousel layout right arrow align hor"
msgstr ""
msgid "top - carousel layout right arrow align ver"
msgstr ""
msgid "-20 - carousel layout right arrow pos x"
msgstr ""
msgid "65 - carousel layout right arrow pos y"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - carousel game name text color"
msgstr ""
msgid "0 - game grid layout pos x"
msgstr ""
msgid "20 - game grid layout pos y"
msgstr ""
msgid "255 - tooltip alpha"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - hdd info color"
msgstr ""
msgid "center - hdd info align hor"
msgstr ""
msgid "top - hdd info align ver"
msgstr ""
msgid "0 - hdd info pos x"
msgstr ""
msgid "400 - hdd info pos y"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - game count color"
msgstr ""
msgid "center - game count align hor"
msgstr ""
msgid "top - game count align ver"
msgstr ""
msgid "0 - game count pos x"
msgstr ""
msgid "420 - game count pos y"
msgstr ""
msgid "16 - install btn pos x"
msgstr ""
msgid "355 - install btn pos y"
msgstr ""
msgid "371 - settings btn pos y"
msgstr ""
msgid "64 - settings btn pos x"
msgstr ""
msgid "371 - home menu btn pos y"
msgstr ""
msgid "489 - home menu btn pos x"
msgstr ""
msgid "355 - power off btn pos y"
msgstr ""
msgid "576 - power off btn pos x"
msgstr ""
msgid "160 - sd card btn pos x"
msgstr ""
msgid "395 - sd card btn pos y"
msgstr ""
msgid "405 - HBC btn pos y"
msgstr ""
msgid "410 - HBC btn pos x"
msgstr ""
msgid "26 - cover/download btn pos x"
msgstr ""
msgid "58 - cover/download btn pos y"
msgstr ""
msgid "305 - gameID btn pos y"
msgstr ""
msgid "68 - gameID btn pos x"
msgstr ""
msgid "r=138 g=138 b=138 a=240 - clock color"
msgstr ""
msgid "left - clock align hor"
msgstr ""
msgid "top - clock align ver"
msgstr ""
msgid "275 - clock pos x"
msgstr ""
msgid "335 - clock pos y"
msgstr ""
msgid "260 - list layout favorite btn pos x"
msgstr ""
msgid "288 - list layout favorite btn pos x widescreen"
msgstr ""
msgid "13 - list layout favorite btn pos y"
msgstr ""
msgid "300 - list layout search btn pos x"
msgstr ""
msgid "320 - list layout search btn pos x widescreen"
msgstr ""
msgid "13 - list layout search btn pos y"
msgstr ""
msgid "340 - list layout abc/sort btn pos x"
msgstr ""
msgid "352 - list layout abc/sort btn pos x widescreen"
msgstr ""
msgid "13 - list layout abc/sort btn pos y"
msgstr ""
msgid "380 - list layout list btn pos x"
msgstr ""
msgid "384 - list layout list btn pos x widescreen"
msgstr ""
msgid "13 - list layout list btn pos y"
msgstr ""
msgid "416 - list layout grid btn pos x widescreen"
msgstr ""
msgid "420 - list layout grid btn pos x"
msgstr ""
msgid "13 - list layout grid btn pos y"
msgstr ""
msgid "448 - list layout carousel btn pos x widescreen"
msgstr ""
msgid "460 - list layout carousel btn pos x"
msgstr ""
msgid "13 - list layout carousel btn pos y"
msgstr ""
msgid "480 - list layout lock btn pos x widescreen"
msgstr ""
msgid "500 - list layout lock btn pos x"
msgstr ""
msgid "13 - list layout lock btn pos y"
msgstr ""
msgid "512 - list layout dvd btn pos x widescreen"
msgstr ""
msgid "540 - list layout dvd btn pos x"
msgstr ""
msgid "13 - list layout dvd btn pos y"
msgstr ""
msgid "280 - game list layout height"
msgstr ""
msgid "396 - game list layout width"
msgstr ""
msgid "200 - game list layout pos x"
msgstr ""
msgid "49 - game list layout pos y"
msgstr ""
msgid "200 - grid layout favorite btn pos x"
msgstr ""
msgid "224 - grid layout favorite btn pos x widescreen"
msgstr ""
msgid "13 - grid layout favorite btn pos y"
msgstr ""
msgid "240 - grid layout search btn pos x"
msgstr ""
msgid "256 - grid layout search btn pos x widescreen"
msgstr ""
msgid "13 - grid layout search btn pos y"
msgstr ""
msgid "280 - grid layout abc/sort btn pos x"
msgstr ""
msgid "288 - grid layout abc/sort btn pos x widescreen"
msgstr ""
msgid "13 - grid layout abc/sort btn pos y"
msgstr ""
msgid "320 - grid layout list btn pos x"
msgstr ""
msgid "320 - grid layout list btn pos x widescreen"
msgstr ""
msgid "13 - grid layout list btn pos y"
msgstr ""
msgid "352 - grid layout grid btn pos x widescreen"
msgstr ""
msgid "360 - grid layout grid btn pos x"
msgstr ""
msgid "13 - grid layout grid btn pos y"
msgstr ""
msgid "384 - grid layout carousel btn pos x widescreen"
msgstr ""
msgid "400 - grid layout carousel btn pos x"
msgstr ""
msgid "13 - grid layout carousel btn pos y"
msgstr ""
msgid "416 - grid layout lock btn pos x widescreen"
msgstr ""
msgid "440 - grid layout lock btn pos x"
msgstr ""
msgid "13 - grid layout lock btn pos y"
msgstr ""
msgid "448 - grid layout dvd btn pos x widescreen"
msgstr ""
msgid "480 - grid layout dvd btn pos x"
msgstr ""
msgid "13 - grid layout dvd btn pos y"
msgstr ""
msgid "400 - game grid layout height"
msgstr ""
msgid "640 - game grid layout width"
msgstr ""
msgid "200 - carousel layout favorite btn pos x"
msgstr ""
msgid "224 - carousel layout favorite btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout favorite btn pos y"
msgstr ""
msgid "240 - carousel layout search btn pos x"
msgstr ""
msgid "256 - carousel layout search btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout search btn pos y"
msgstr ""
msgid "280 - carousel layout abc/sort btn pos x"
msgstr ""
msgid "288 - carousel layout abc/sort btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout abc/sort btn pos y"
msgstr ""
msgid "320 - carousel layout list btn pos x"
msgstr ""
msgid "320 - carousel layout list btn pos x widescreen"
msgstr ""
msgid "13 - carousel layout list btn pos y"
msgstr ""
msgid "352 - carousel layout grid btn pos x widescreen"
msgstr ""
msgid "360 - carousel layout grid btn pos x"
msgstr ""
msgid "13 - carousel layout grid btn pos y"
msgstr ""
msgid "384 - carousel layout carousel btn pos x widescreen"
msgstr ""
msgid "400 - carousel layout carousel btn pos x"
msgstr ""
msgid "13 - carousel layout carousel btn pos y"
msgstr ""
msgid "416 - carousel layout lock btn pos x widescreen"
msgstr ""
msgid "440 - carousel layout lock btn pos x"
msgstr ""
msgid "13 - carousel layout lock btn pos y"
msgstr ""
msgid "448 - carousel layout dvd btn pos x widescreen"
msgstr ""
msgid "480 - carousel layout dvd btn pos x"
msgstr ""
msgid "13 - carousel layout dvd btn pos y"
msgstr ""
msgid "400 - game carousel layout height"
msgstr ""
msgid "640 - game carousel layout width"
msgstr ""
msgid "-20 - game carousel layout pos y"
msgstr ""
msgid "0 - game carousel layout pos x"
msgstr ""
msgid "1 - show hdd info: 1 for on and 0 for off"
msgstr ""
msgid "1 - show game count: 1 for on and 0 for off"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - game id text color"
msgstr ""
msgid "r=55 g=190 b=237 a=255 - region info text color"
msgstr ""
msgid "30 - region info text pos y"
msgstr ""
msgid "68 - region info text pos x"
msgstr ""
msgid "1 - Enable tooltips: 0 for off and 1 for on"
msgstr ""

944
bin/ehcmodule_5.c Normal file
View File

@ -0,0 +1,944 @@
#define size_ehcmodule_5 26234
unsigned char ehcmodule_5[26234] __attribute__((aligned (32)))={
127, 69, 76, 70, 1, 2, 1, 97, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 40, 0, 0, 0, 1, 19, 112, 0, 0, 0, 0, 0, 52, 0, 0, 0,
0, 0, 0, 6, 6, 0, 52, 0, 32, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160,
0, 0, 0, 160, 0, 240, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 212, 0, 0, 0, 160, 0, 0, 0, 160, 0, 0, 0, 52, 0, 0, 0,
52, 0, 240, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 212, 0, 240, 0,
0, 0, 0, 64, 0, 0, 0, 0, 1, 0, 0, 1, 8, 19, 112, 0, 0, 19, 112, 0, 0, 0, 0, 90, 208, 0, 0, 90, 208, 0, 240, 0, 5, 0,
0, 0, 4, 0, 0, 0, 1, 0, 0, 91, 216, 19, 112, 96, 0, 19, 112, 96, 0, 0, 0, 10, 162, 0, 2, 153, 40, 0, 240, 0, 6, 0, 0,
0, 4, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 4, 0, 0, 0, 9, 19, 112, 0, 0, 0, 0, 0, 125, 0, 0, 0,
120, 0, 0, 0, 126, 0, 0, 48, 0, 0, 0, 0, 127, 19, 114, 247, 40, 227, 160, 0, 0, 227, 160, 16, 0, 229, 159, 49, 0, 225,
47, 255, 19, 229, 159, 192, 252, 229, 156, 192, 0, 225, 160, 0, 0, 231, 156, 193, 11, 225, 160, 0, 0, 225, 47, 255,
28, 225, 160, 0, 0, 225, 160, 0, 0, 227, 160, 176, 63, 234, 255, 255, 245, 225, 160, 0, 0, 225, 160, 0, 0, 227, 160,
176, 64, 234, 255, 255, 241, 227, 160, 0, 0, 238, 7, 15, 21, 225, 47, 255, 30, 225, 160, 0, 0, 225, 160, 0, 0, 225,
160, 0, 0, 227, 24, 0, 16, 10, 0, 0, 18, 227, 200, 128, 16, 227, 160, 32, 16, 229, 135, 32, 0, 225, 160, 0, 0, 225,
160, 32, 13, 225, 160, 0, 0, 229, 159, 208, 144, 225, 160, 0, 0, 233, 45, 95, 254, 225, 160, 0, 0, 235, 0, 0, 15, 232,
189, 95, 254, 225, 160, 0, 0, 225, 160, 208, 2, 227, 16, 0, 1, 10, 0, 0, 2, 225, 160, 0, 0, 227, 160, 0, 4, 235, 0,
0, 5, 227, 24, 0, 1, 10, 0, 0, 1, 229, 159, 240, 88, 225, 160, 0, 0, 229, 159, 240, 84, 225, 160, 0, 0, 229, 159, 240,
80, 225, 160, 0, 0, 229, 159, 32, 76, 225, 47, 255, 18, 225, 160, 0, 0, 238, 19, 15, 16, 225, 47, 255, 30, 225, 160,
0, 0, 225, 160, 0, 0, 238, 3, 15, 16, 225, 47, 255, 30, 225, 160, 0, 0, 225, 160, 0, 0, 69, 72, 67, 95, 67, 70, 71,
0, 18, 52, 0, 1, 0, 0, 0, 0, 19, 112, 16, 157, 19, 114, 195, 128, 19, 114, 249, 40, 255, 255, 30, 128, 255, 255, 30,
156, 255, 255, 29, 68, 19, 112, 13, 61, 225, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, 40,
2, 208, 16, 40, 2, 216, 4, 40, 0, 208, 7, 40, 1, 209, 19, 224, 7, 40, 16, 208, 12, 40, 17, 209, 14, 224, 11, 75, 8,
104, 24, 224, 11, 72, 7, 224, 9, 75, 7, 34, 1, 96, 26, 32, 0, 224, 4, 72, 6, 224, 2, 72, 6, 224, 0, 72, 6, 188, 2, 71,
8, 19, 112, 96, 48, 19, 112, 73, 29, 19, 112, 106, 200, 19, 112, 66, 25, 19, 112, 67, 97, 255, 255, 253, 102, 181, 112,
28, 12, 28, 5, 240, 5, 252, 105, 28, 6, 32, 1, 66, 64, 240, 5, 252, 88, 14, 43, 115, 35, 12, 43, 115, 99, 10, 43, 115,
163, 124, 34, 124, 99, 6, 18, 4, 27, 67, 19, 124, 162, 115, 229, 2, 18, 67, 19, 124, 226, 6, 45, 67, 19, 28, 32, 96,
29, 48, 12, 33, 4, 240, 5, 252, 88, 124, 35, 124, 96, 6, 27, 4, 0, 67, 24, 124, 163, 33, 4, 2, 27, 67, 24, 124, 227,
67, 24, 240, 5, 252, 75, 28, 48, 240, 5, 252, 48, 32, 0, 188, 112, 188, 2, 71, 8, 181, 8, 75, 12, 28, 1, 34, 32, 104,
24, 240, 5, 252, 81, 40, 0, 209, 13, 72, 9, 240, 5, 252, 40, 240, 4, 252, 99, 32, 200, 240, 0, 255, 33, 240, 4, 252,
104, 32, 200, 240, 0, 255, 28, 231, 244, 188, 8, 188, 2, 71, 8, 19, 112, 96, 48, 19, 112, 96, 84, 181, 8, 75, 4, 28,
1, 104, 24, 240, 5, 251, 252, 188, 8, 188, 1, 71, 0, 70, 192, 19, 112, 96, 48, 181, 240, 176, 139, 144, 4, 145, 5, 28,
8, 28, 17, 28, 23, 146, 7, 240, 5, 252, 8, 76, 129, 104, 35, 43, 0, 209, 0, 224, 241, 168, 9, 240, 3, 254, 8, 75, 126,
96, 24, 40, 0, 208, 4, 35, 128, 154, 9, 1, 27, 66, 154, 208, 4, 35, 1, 74, 122, 66, 91, 96, 19, 224, 224, 78, 121, 72,
122, 104, 51, 24, 26, 42, 0, 208, 104, 43, 0, 219, 102, 75, 116, 104, 26, 28, 81, 209, 98, 28, 53, 75, 112, 104, 48,
104, 28, 33, 31, 34, 16, 52, 31, 24, 18, 67, 140, 146, 2, 33, 16, 28, 34, 240, 3, 255, 166, 40, 0, 209, 0, 224, 195,
120, 35, 43, 67, 209, 11, 120, 99, 43, 73, 209, 8, 120, 163, 43, 83, 209, 5, 120, 227, 43, 79, 209, 2, 75, 103, 96,
51, 224, 8, 104, 43, 43, 0, 208, 2, 35, 0, 96, 43, 231, 218, 35, 1, 66, 91, 96, 43, 121, 98, 121, 163, 2, 18, 4, 27,
24, 211, 121, 34, 77, 95, 24, 155, 121, 226, 28, 40, 6, 18, 24, 155, 10, 219, 147, 3, 154, 3, 75, 91, 33, 0, 96, 26,
34, 128, 1, 18, 240, 5, 250, 143, 75, 84, 104, 26, 75, 85, 66, 154, 209, 30, 32, 7, 35, 0, 70, 132, 70, 102, 64, 30,
209, 4, 16, 218, 152, 2, 73, 82, 0, 146, 80, 80, 24, 226, 122, 18, 42, 0, 208, 10, 16, 218, 92, 168, 33, 1, 64, 177,
67, 8, 84, 168, 154, 2, 28, 16, 154, 3, 24, 128, 144, 2, 34, 128, 51, 1, 1, 210, 66, 147, 209, 227, 75, 63, 34, 31,
104, 27, 153, 5, 51, 31, 67, 147, 34, 128, 2, 18, 147, 3, 145, 2, 78, 60, 146, 6, 224, 97, 155, 4, 32, 15, 10, 93, 104,
51, 67, 133, 66, 157, 208, 63, 73, 56, 75, 57, 104, 10, 96, 53, 66, 154, 209, 33, 75, 57, 28, 40, 104, 28, 28, 33, 240,
5, 251, 33, 75, 55, 8, 193, 0, 138, 88, 210, 35, 0, 147, 1, 35, 7, 64, 24, 70, 140, 35, 0, 144, 0, 224, 9, 72, 47, 70,
97, 92, 64, 28, 1, 65, 25, 32, 1, 66, 8, 208, 0, 25, 18, 51, 1, 153, 0, 66, 139, 211, 242, 60, 1, 64, 44, 25, 21, 75,
34, 104, 28, 27, 100, 44, 16, 220, 10, 44, 16, 208, 9, 34, 128, 152, 3, 33, 0, 2, 18, 240, 5, 250, 34, 44, 0, 221, 8,
224, 0, 36, 16, 28, 40, 28, 33, 154, 3, 240, 3, 254, 255, 40, 0, 208, 29, 154, 4, 152, 6, 4, 209, 12, 73, 26, 67, 28,
60, 66, 187, 216, 0, 28, 28, 154, 3, 152, 2, 24, 137, 28, 34, 240, 5, 249, 198, 152, 2, 28, 33, 240, 5, 251, 28, 155,
2, 152, 4, 25, 27, 27, 63, 16, 164, 25, 0, 147, 2, 144, 4, 47, 0, 209, 155, 224, 5, 32, 128, 2, 0, 176, 11, 188, 240,
188, 2, 71, 8, 152, 5, 153, 7, 240, 5, 251, 39, 32, 0, 231, 245, 70, 192, 19, 112, 107, 88, 19, 112, 106, 208, 19, 112,
96, 24, 19, 112, 96, 12, 128, 0, 0, 1, 127, 255, 255, 255, 19, 112, 123, 128, 19, 112, 106, 212, 19, 112, 131, 128,
181, 56, 28, 12, 240, 5, 250, 214, 30, 5, 209, 38, 44, 0, 208, 36, 104, 34, 42, 0, 208, 33, 120, 17, 120, 83, 6, 9,
4, 27, 67, 11, 120, 145, 2, 9, 67, 11, 120, 209, 67, 11, 43, 6, 209, 21, 123, 17, 123, 83, 6, 9, 4, 27, 67, 11, 123,
145, 2, 9, 67, 11, 123, 209, 67, 11, 43, 122, 208, 2, 43, 136, 209, 7, 224, 2, 72, 5, 33, 21, 224, 1, 72, 4, 33, 20,
240, 4, 250, 238, 28, 40, 188, 56, 188, 2, 71, 8, 70, 192, 19, 112, 1, 153, 181, 240, 176, 145, 75, 206, 33, 128, 104,
24, 240, 5, 250, 97, 33, 32, 240, 5, 250, 144, 144, 8, 240, 0, 251, 131, 240, 5, 250, 211, 33, 120, 240, 5, 250, 140,
153, 8, 72, 199, 240, 5, 250, 120, 72, 198, 154, 8, 28, 1, 35, 0, 240, 5, 250, 72, 73, 196, 144, 9, 32, 205, 240, 4,
250, 109, 33, 0, 36, 1, 145, 7, 145, 11, 145, 6, 39, 0, 152, 8, 169, 15, 34, 0, 240, 5, 250, 122, 144, 14, 155, 14,
43, 0, 209, 246, 44, 0, 208, 2, 152, 9, 240, 5, 250, 67, 74, 185, 158, 15, 35, 0, 96, 19, 46, 0, 209, 87, 75, 183, 104,
27, 43, 0, 208, 5, 75, 182, 104, 27, 43, 0, 209, 1, 74, 181, 96, 19, 36, 0, 47, 0, 208, 222, 75, 178, 104, 27, 43, 0,
208, 218, 75, 175, 104, 27, 43, 0, 209, 214, 75, 175, 104, 27, 43, 0, 208, 9, 240, 3, 253, 88, 40, 0, 208, 5, 240, 3,
253, 84, 40, 0, 208, 1, 240, 3, 253, 80, 75, 168, 104, 27, 147, 4, 43, 0, 209, 36, 77, 167, 75, 167, 104, 42, 58, 1,
66, 154, 216, 30, 78, 159, 76, 165, 35, 1, 96, 51, 104, 32, 33, 1, 74, 164, 240, 3, 254, 26, 155, 4, 96, 51, 40, 0,
208, 9, 35, 128, 104, 42, 0, 155, 66, 154, 209, 4, 104, 35, 33, 128, 2, 9, 24, 91, 96, 35, 75, 154, 74, 156, 104, 25,
104, 18, 66, 145, 211, 1, 34, 0, 96, 26, 75, 145, 36, 0, 104, 27, 43, 0, 209, 153, 152, 9, 73, 138, 240, 5, 249, 219,
36, 1, 231, 147, 120, 51, 120, 112, 6, 27, 4, 0, 67, 24, 120, 179, 2, 27, 67, 24, 120, 243, 67, 24, 56, 1, 40, 6, 217,
0, 226, 152, 240, 4, 255, 69, 0, 10, 0, 73, 2, 151, 2, 151, 2, 151, 0, 7, 0, 92, 38, 1, 37, 1, 226, 150, 123, 51, 123,
116, 6, 27, 4, 36, 67, 28, 123, 179, 73, 119, 2, 27, 67, 28, 123, 243, 67, 28, 28, 32, 240, 5, 249, 53, 40, 0, 209,
11, 125, 51, 125, 117, 6, 27, 4, 45, 67, 29, 125, 179, 2, 27, 67, 29, 125, 243, 38, 1, 67, 29, 226, 122, 28, 32, 73,
120, 240, 5, 249, 35, 40, 0, 208, 0, 226, 108, 125, 51, 125, 117, 6, 27, 4, 45, 67, 29, 125, 179, 34, 1, 2, 27, 67,
29, 125, 243, 39, 0, 67, 29, 75, 103, 38, 1, 96, 26, 75, 103, 96, 24, 72, 110, 240, 0, 251, 48, 75, 109, 34, 4, 104,
27, 104, 155, 96, 154, 240, 1, 248, 39, 226, 87, 122, 50, 122, 115, 6, 18, 4, 27, 67, 19, 122, 178, 2, 18, 67, 19, 122,
242, 67, 19, 154, 6, 66, 154, 209, 0, 226, 70, 240, 1, 248, 46, 38, 1, 37, 0, 226, 68, 126, 51, 126, 116, 6, 27, 4,
36, 67, 28, 126, 179, 124, 50, 2, 27, 67, 28, 126, 243, 6, 18, 67, 28, 124, 115, 4, 27, 67, 19, 124, 178, 2, 18, 67,
19, 124, 242, 67, 26, 146, 4, 125, 51, 125, 117, 6, 27, 4, 45, 67, 29, 125, 179, 2, 27, 67, 29, 125, 243, 67, 29, 155,
6, 43, 0, 209, 16, 123, 51, 43, 0, 209, 13, 122, 50, 122, 115, 122, 176, 6, 18, 4, 27, 67, 19, 2, 0, 67, 3, 122, 240,
67, 24, 240, 1, 248, 10, 28, 6, 224, 0, 38, 0, 153, 4, 28, 32, 25, 73, 145, 10, 0, 201, 240, 5, 249, 164, 34, 0, 28,
37, 146, 5, 224, 7, 104, 40, 104, 105, 240, 5, 249, 156, 155, 5, 53, 8, 51, 1, 147, 5, 153, 5, 154, 10, 66, 145, 219,
243, 73, 48, 104, 11, 147, 5, 43, 0, 208, 0, 225, 213, 154, 15, 123, 16, 123, 83, 6, 0, 4, 27, 67, 3, 123, 144, 2, 0,
67, 3, 123, 208, 67, 3, 72, 51, 66, 131, 209, 0, 225, 38, 66, 131, 216, 31, 43, 6, 216, 11, 43, 5, 211, 0, 225, 180,
43, 1, 209, 0, 224, 159, 43, 0, 208, 119, 43, 2, 208, 0, 225, 70, 225, 171, 43, 27, 216, 6, 43, 26, 211, 0, 224, 172,
43, 12, 208, 0, 225, 61, 224, 156, 74, 37, 66, 147, 209, 0, 224, 167, 50, 1, 66, 147, 208, 0, 225, 52, 224, 246, 72,
34, 66, 131, 209, 0, 224, 226, 66, 131, 216, 68, 74, 32, 66, 147, 209, 0, 224, 182, 66, 147, 216, 8, 58, 12, 66, 147,
209, 0, 225, 17, 50, 2, 66, 147, 208, 0, 225, 31, 225, 20, 74, 25, 66, 147, 209, 0, 225, 22, 50, 1, 66, 147, 208, 0,
225, 22, 224, 169, 70, 192, 19, 112, 96, 48, 19, 112, 96, 109, 0, 152, 150, 128, 19, 112, 1, 65, 19, 112, 106, 240,
19, 112, 106, 196, 19, 112, 106, 200, 19, 112, 96, 20, 19, 112, 107, 84, 19, 114, 199, 32, 0, 0, 15, 254, 19, 112, 106,
192, 19, 112, 107, 128, 19, 114, 199, 36, 19, 112, 96, 121, 19, 112, 21, 69, 19, 112, 96, 60, 85, 77, 83, 3, 85, 77,
83, 1, 85, 77, 83, 130, 85, 77, 83, 16, 85, 77, 83, 128, 73, 196, 66, 139, 209, 0, 225, 63, 66, 139, 216, 7, 73, 194,
66, 139, 208, 119, 73, 194, 66, 139, 208, 0, 224, 219, 224, 220, 74, 192, 66, 147, 209, 0, 225, 36, 50, 1, 66, 147,
208, 0, 224, 210, 225, 20, 46, 0, 209, 0, 225, 55, 105, 162, 105, 35, 136, 21, 106, 34, 136, 27, 136, 16, 104, 34, 2,
25, 10, 27, 120, 18, 67, 11, 2, 41, 10, 45, 67, 13, 146, 5, 4, 45, 104, 162, 12, 45, 120, 18, 149, 0, 2, 5, 10, 0, 67,
40, 4, 0, 12, 0, 144, 1, 107, 32, 4, 27, 144, 2, 12, 27, 28, 48, 153, 5, 240, 1, 251, 44, 225, 3, 46, 0, 209, 0, 225,
17, 104, 35, 28, 48, 120, 25, 104, 163, 136, 26, 105, 35, 240, 1, 251, 12, 224, 247, 46, 0, 208, 0, 225, 5, 104, 35,
105, 34, 120, 24, 104, 163, 120, 25, 105, 163, 240, 0, 255, 46, 224, 235, 38, 0, 37, 1, 225, 4, 154, 11, 42, 0, 209,
1, 240, 0, 254, 203, 240, 3, 249, 119, 39, 0, 28, 5, 40, 0, 219, 3, 75, 151, 34, 1, 96, 26, 39, 1, 155, 15, 38, 1, 122,
25, 122, 90, 6, 9, 4, 18, 67, 10, 122, 153, 122, 219, 2, 9, 67, 10, 67, 19, 147, 6, 150, 11, 224, 230, 75, 141, 153,
5, 38, 1, 96, 25, 37, 0, 39, 0, 224, 223, 104, 35, 104, 26, 75, 138, 224, 97, 104, 35, 37, 0, 120, 222, 75, 136, 120,
27, 66, 179, 208, 16, 75, 135, 104, 27, 43, 0, 208, 12, 240, 3, 249, 40, 240, 0, 254, 206, 240, 0, 254, 180, 75, 129,
112, 30, 240, 0, 254, 146, 240, 3, 249, 62, 28, 5, 75, 126, 112, 30, 224, 165, 35, 1, 96, 11, 154, 5, 75, 121, 72, 124,
96, 26, 240, 0, 249, 164, 75, 123, 34, 4, 104, 27, 39, 0, 104, 155, 96, 154, 240, 0, 254, 154, 77, 120, 28, 40, 240,
3, 250, 74, 75, 119, 96, 24, 104, 35, 43, 0, 208, 1, 104, 42, 96, 26, 75, 116, 104, 29, 224, 135, 104, 35, 105, 34,
104, 24, 104, 163, 38, 1, 104, 25, 240, 3, 251, 254, 75, 111, 28, 5, 120, 26, 42, 0, 209, 0, 224, 148, 70, 105, 34,
23, 92, 81, 112, 25, 104, 35, 40, 0, 221, 2, 104, 25, 72, 105, 224, 1, 104, 25, 72, 105, 240, 1, 248, 24, 224, 133,
104, 35, 105, 34, 104, 24, 104, 163, 104, 25, 240, 3, 252, 134, 224, 97, 75, 100, 104, 26, 66, 81, 65, 74, 96, 26, 224,
105, 104, 35, 104, 26, 75, 85, 96, 26, 38, 1, 231, 106, 122, 17, 122, 83, 6, 9, 4, 27, 67, 11, 122, 145, 122, 210, 2,
9, 67, 11, 67, 26, 104, 37, 35, 0, 146, 6, 147, 13, 120, 42, 42, 95, 209, 26, 120, 106, 42, 68, 209, 23, 120, 170, 42,
86, 209, 20, 120, 234, 42, 68, 209, 17, 77, 82, 74, 69, 96, 43, 104, 227, 33, 1, 96, 17, 43, 4, 209, 6, 104, 161, 168,
13, 34, 4, 240, 4, 254, 134, 155, 13, 96, 43, 240, 3, 255, 12, 224, 17, 104, 227, 43, 4, 209, 4, 104, 161, 168, 13,
34, 4, 240, 4, 254, 121, 28, 40, 153, 13, 240, 3, 255, 67, 144, 7, 40, 0, 208, 46, 75, 53, 34, 1, 96, 26, 38, 1, 37,
0, 224, 43, 240, 3, 251, 66, 38, 1, 28, 5, 40, 0, 209, 42, 35, 1, 74, 60, 66, 91, 96, 19, 224, 37, 75, 45, 34, 1, 96,
26, 104, 35, 105, 33, 104, 24, 104, 163, 104, 26, 247, 255, 251, 159, 28, 5, 38, 1, 224, 24, 154, 7, 42, 0, 208, 18,
104, 35, 105, 34, 104, 25, 104, 163, 152, 7, 104, 27, 240, 4, 251, 17, 38, 1, 37, 0, 224, 10, 38, 1, 37, 6, 224, 6,
37, 1, 38, 1, 66, 109, 39, 1, 224, 2, 38, 1, 37, 1, 66, 109, 153, 4, 0, 203, 24, 228, 224, 7, 104, 32, 104, 97, 240,
4, 255, 141, 154, 4, 52, 8, 50, 1, 146, 4, 155, 4, 153, 10, 66, 139, 219, 243, 224, 9, 38, 1, 37, 1, 224, 1, 38, 1,
37, 6, 66, 109, 224, 2, 37, 0, 38, 1, 149, 6, 74, 12, 36, 0, 104, 19, 43, 0, 208, 4, 152, 9, 73, 23, 240, 4, 255, 31,
36, 1, 46, 0, 209, 0, 228, 213, 152, 15, 28, 41, 240, 4, 255, 117, 228, 208, 87, 70, 83, 2, 85, 77, 83, 131, 87, 70,
83, 1, 87, 70, 83, 3, 19, 112, 96, 20, 19, 112, 106, 196, 19, 112, 1, 12, 19, 112, 107, 56, 19, 112, 21, 69, 19, 112,
96, 60, 19, 114, 199, 32, 19, 114, 199, 36, 19, 112, 96, 16, 19, 112, 96, 137, 19, 112, 96, 164, 19, 112, 106, 204,
19, 112, 96, 12, 19, 112, 96, 24, 0, 152, 150, 128, 74, 3, 35, 128, 104, 17, 2, 27, 67, 11, 96, 19, 71, 112, 70, 192,
13, 4, 0, 204, 75, 2, 74, 3, 104, 25, 64, 10, 96, 26, 71, 112, 13, 4, 0, 204, 255, 255, 127, 255, 181, 16, 247, 255,
255, 243, 32, 128, 240, 3, 254, 16, 33, 32, 240, 4, 255, 1, 76, 9, 96, 32, 32, 4, 240, 4, 255, 12, 104, 33, 34, 0, 32,
4, 240, 4, 255, 47, 247, 255, 255, 215, 32, 4, 240, 4, 254, 216, 188, 16, 188, 1, 71, 0, 70, 192, 19, 112, 96, 32, 181,
16, 28, 4, 75, 15, 28, 8, 0, 137, 24, 9, 104, 26, 0, 73, 35, 1, 240, 4, 254, 171, 75, 12, 33, 16, 96, 24, 72, 11, 240,
3, 255, 18, 33, 16, 72, 10, 240, 3, 255, 25, 75, 10, 34, 55, 96, 28, 75, 9, 32, 4, 104, 27, 104, 155, 96, 154, 240,
4, 254, 179, 188, 16, 188, 1, 71, 0, 19, 112, 96, 32, 19, 112, 96, 28, 13, 128, 0, 56, 13, 128, 0, 60, 19, 112, 106,
224, 19, 112, 96, 60, 181, 112, 76, 21, 75, 21, 38, 2, 66, 118, 28, 33, 104, 24, 34, 0, 96, 38, 240, 4, 254, 191, 75,
18, 77, 18, 104, 27, 104, 154, 35, 0, 96, 147, 74, 17, 104, 40, 96, 19, 240, 4, 254, 134, 104, 40, 240, 4, 254, 205,
35, 1, 66, 91, 96, 43, 104, 35, 43, 0, 209, 3, 75, 11, 104, 27, 96, 35, 224, 0, 96, 38, 32, 4, 240, 4, 254, 125, 75,
2, 104, 24, 188, 112, 188, 2, 71, 8, 19, 112, 106, 216, 19, 112, 96, 32, 19, 112, 96, 60, 19, 112, 96, 28, 19, 112,
106, 224, 19, 112, 106, 220, 75, 2, 34, 0, 96, 24, 75, 2, 96, 26, 71, 112, 19, 112, 106, 228, 19, 112, 106, 224, 181,
248, 76, 34, 38, 16, 104, 35, 77, 33, 67, 179, 96, 35, 104, 43, 73, 32, 104, 154, 121, 19, 121, 87, 6, 27, 4, 63, 67,
31, 121, 147, 2, 27, 67, 31, 121, 211, 67, 31, 104, 11, 43, 0, 208, 18, 28, 56, 240, 0, 248, 56, 40, 0, 220, 20, 74,
22, 35, 0, 96, 19, 75, 22, 96, 24, 32, 4, 240, 4, 254, 66, 104, 43, 34, 55, 104, 155, 64, 23, 96, 95, 224, 22, 75, 17,
104, 27, 43, 0, 208, 8, 28, 56, 240, 0, 248, 33, 104, 43, 34, 55, 104, 155, 64, 23, 96, 95, 224, 2, 35, 55, 64, 31,
96, 87, 104, 35, 67, 51, 96, 35, 75, 9, 104, 26, 67, 22, 96, 30, 32, 0, 188, 248, 188, 2, 71, 8, 70, 192, 13, 128, 0,
60, 19, 112, 96, 60, 19, 112, 106, 224, 19, 112, 106, 220, 19, 112, 106, 228, 13, 128, 0, 56, 71, 24, 70, 192, 181,
112, 28, 12, 28, 5, 240, 4, 254, 67, 28, 6, 32, 1, 66, 64, 240, 4, 254, 50, 104, 34, 75, 17, 66, 154, 209, 25, 75, 16,
73, 17, 34, 1, 67, 19, 96, 75, 28, 32, 34, 8, 240, 4, 252, 219, 28, 32, 27, 100, 8, 164, 33, 8, 60, 2, 240, 4, 254,
54, 2, 36, 35, 234, 10, 36, 6, 27, 67, 35, 96, 43, 28, 40, 33, 4, 240, 4, 254, 44, 28, 48, 240, 4, 254, 17, 188, 112,
188, 1, 71, 0, 230, 0, 1, 112, 19, 112, 4, 153, 19, 112, 96, 36, 181, 56, 28, 4, 240, 4, 253, 202, 44, 38, 208, 72,
44, 38, 216, 5, 44, 36, 208, 9, 44, 37, 208, 0, 224, 169, 224, 14, 44, 57, 208, 112, 44, 60, 208, 0, 224, 163, 224,
110, 73, 83, 75, 84, 72, 84, 96, 75, 34, 8, 240, 4, 252, 163, 72, 82, 224, 150, 72, 82, 73, 82, 247, 255, 255, 171,
76, 77, 75, 81, 77, 82, 96, 99, 34, 8, 28, 40, 28, 33, 240, 4, 252, 148, 28, 40, 33, 8, 240, 4, 253, 242, 75, 77, 77,
78, 96, 99, 34, 8, 28, 40, 28, 33, 240, 4, 252, 136, 28, 40, 33, 8, 240, 4, 253, 230, 75, 73, 77, 74, 96, 99, 34, 8,
28, 33, 28, 40, 240, 4, 252, 124, 28, 40, 33, 8, 240, 4, 253, 218, 75, 59, 72, 69, 96, 99, 28, 33, 34, 8, 240, 4, 252,
113, 72, 66, 224, 100, 72, 66, 73, 66, 247, 255, 255, 121, 76, 52, 75, 65, 77, 57, 96, 99, 34, 8, 28, 40, 28, 33, 240,
4, 252, 98, 28, 40, 33, 8, 240, 4, 253, 192, 75, 60, 77, 53, 96, 99, 34, 8, 28, 40, 28, 33, 240, 4, 252, 86, 28, 40,
33, 8, 240, 4, 253, 180, 75, 55, 77, 49, 96, 99, 34, 8, 28, 33, 28, 40, 240, 4, 252, 74, 28, 40, 33, 8, 240, 4, 253,
168, 75, 34, 72, 50, 96, 99, 28, 33, 34, 8, 240, 4, 252, 63, 72, 47, 224, 50, 72, 47, 224, 0, 72, 47, 73, 47, 247, 255,
255, 69, 76, 26, 75, 46, 77, 31, 96, 99, 34, 8, 28, 40, 28, 33, 240, 4, 252, 46, 28, 40, 33, 8, 240, 4, 253, 140, 75,
41, 77, 27, 96, 99, 34, 8, 28, 40, 28, 33, 240, 4, 252, 34, 28, 40, 33, 8, 240, 4, 253, 128, 75, 36, 77, 23, 96, 99,
34, 8, 28, 33, 28, 40, 240, 4, 252, 22, 28, 40, 33, 8, 240, 4, 253, 116, 75, 8, 72, 31, 96, 99, 28, 33, 34, 8, 240,
4, 252, 11, 72, 28, 33, 8, 240, 4, 253, 105, 32, 0, 188, 56, 188, 2, 71, 8, 70, 192, 19, 112, 96, 36, 19, 112, 0, 96,
255, 255, 30, 120, 32, 32, 93, 232, 32, 32, 64, 140, 255, 255, 31, 112, 19, 112, 0, 188, 255, 255, 31, 140, 19, 112,
0, 196, 255, 255, 30, 52, 19, 112, 0, 204, 255, 255, 31, 104, 32, 32, 91, 20, 32, 32, 62, 108, 255, 255, 30, 176, 255,
255, 30, 204, 255, 255, 29, 116, 255, 255, 30, 168, 32, 32, 94, 132, 32, 32, 93, 148, 32, 32, 63, 96, 255, 255, 33,
48, 255, 255, 33, 76, 255, 255, 31, 244, 255, 255, 33, 40, 181, 56, 77, 11, 35, 0, 104, 42, 73, 10, 240, 4, 252, 201,
76, 10, 73, 10, 34, 0, 96, 32, 104, 40, 240, 4, 253, 4, 104, 32, 240, 4, 252, 211, 104, 32, 240, 4, 253, 26, 188, 56,
188, 1, 71, 0, 70, 192, 19, 112, 96, 44, 0, 152, 150, 128, 19, 112, 96, 52, 19, 112, 106, 232, 181, 8, 1, 67, 26, 27,
0, 155, 24, 24, 0, 192, 247, 255, 255, 216, 188, 8, 188, 1, 71, 0, 0, 0, 181, 0, 74, 5, 2, 192, 104, 19, 104, 17, 26,
201, 213, 0, 104, 19, 66, 129, 217, 249, 188, 1, 71, 0, 13, 128, 0, 16, 181, 8, 75, 24, 120, 26, 30, 83, 65, 154, 75,
23, 96, 26, 240, 3, 252, 204, 75, 22, 33, 4, 96, 24, 28, 24, 240, 4, 252, 225, 240, 3, 252, 206, 34, 0, 28, 1, 72, 18,
240, 3, 253, 3, 33, 160, 2, 73, 72, 16, 240, 4, 252, 201, 75, 16, 33, 128, 96, 24, 240, 4, 252, 122, 33, 32, 240, 4,
252, 169, 75, 13, 96, 24, 240, 3, 251, 37, 40, 0, 219, 3, 247, 255, 250, 7, 32, 0, 224, 1, 32, 1, 66, 64, 188, 8, 188,
2, 71, 8, 19, 112, 1, 12, 19, 112, 107, 80, 19, 114, 195, 128, 19, 112, 14, 77, 19, 113, 131, 128, 19, 112, 96, 48,
19, 112, 96, 44, 181, 240, 7, 65, 213, 27, 34, 128, 78, 14, 77, 15, 76, 15, 35, 0, 1, 146, 104, 49, 0, 152, 104, 137,
104, 47, 49, 68, 24, 9, 104, 8, 66, 187, 209, 5, 7, 193, 212, 7, 73, 9, 32, 2, 96, 8, 224, 3, 64, 32, 40, 3, 209, 0,
96, 10, 51, 1, 43, 4, 209, 233, 188, 240, 188, 1, 71, 0, 19, 112, 96, 60, 19, 112, 107, 80, 0, 0, 32, 3, 19, 112, 107,
84, 181, 240, 176, 131, 147, 1, 155, 8, 76, 14, 0, 91, 104, 38, 28, 13, 28, 23, 147, 0, 32, 10, 247, 255, 255, 79, 104,
43, 154, 1, 64, 59, 66, 147, 208, 9, 104, 35, 27, 155, 213, 0, 104, 38, 154, 0, 66, 147, 211, 240, 32, 2, 66, 64, 224,
0, 32, 0, 176, 3, 188, 240, 188, 2, 71, 8, 70, 192, 13, 128, 0, 16, 181, 56, 28, 4, 240, 3, 251, 27, 33, 0, 28, 5, 34,
96, 28, 32, 240, 4, 251, 64, 35, 64, 96, 163, 35, 128, 4, 91, 99, 101, 96, 35, 96, 99, 188, 56, 188, 1, 71, 0, 181,
16, 75, 12, 36, 0, 104, 27, 108, 26, 42, 7, 220, 13, 73, 10, 104, 12, 0, 228, 24, 164, 0, 97, 25, 12, 106, 25, 1, 100,
25, 12, 50, 1, 100, 26, 28, 32, 247, 255, 255, 215, 28, 32, 188, 16, 188, 2, 71, 8, 70, 192, 19, 112, 96, 60, 19, 112,
107, 64, 181, 240, 28, 4, 176, 133, 28, 8, 28, 14, 147, 3, 28, 23, 240, 4, 250, 147, 35, 0, 98, 35, 5, 53, 35, 128,
13, 45, 1, 91, 27, 93, 96, 224, 66, 175, 210, 1, 28, 61, 224, 49, 32, 128, 1, 64, 24, 54, 11, 54, 3, 54, 150, 2, 33,
1, 28, 38, 54, 16, 145, 1, 224, 20, 152, 2, 240, 4, 250, 121, 34, 0, 198, 1, 97, 50, 155, 2, 33, 128, 28, 24, 35, 128,
1, 91, 1, 73, 24, 192, 24, 109, 144, 2, 66, 189, 211, 0, 28, 61, 154, 1, 50, 1, 146, 1, 66, 189, 210, 8, 152, 1, 33,
0, 15, 195, 34, 4, 66, 130, 65, 75, 6, 27, 43, 0, 209, 223, 66, 189, 208, 4, 28, 40, 153, 10, 240, 4, 251, 194, 26,
109, 155, 3, 4, 40, 67, 24, 240, 4, 250, 80, 35, 128, 4, 91, 96, 160, 100, 37, 96, 35, 96, 99, 176, 5, 28, 40, 188,
240, 188, 2, 71, 8, 0, 0, 181, 240, 176, 139, 28, 5, 247, 255, 255, 133, 28, 6, 32, 0, 46, 0, 209, 0, 224, 145, 99,
245, 105, 42, 126, 107, 126, 47, 97, 104, 146, 3, 147, 7, 47, 0, 209, 25, 35, 8, 147, 0, 35, 160, 104, 105, 34, 8, 0,
155, 28, 48, 247, 255, 255, 140, 247, 255, 255, 108, 28, 4, 28, 56, 44, 0, 208, 121, 107, 96, 99, 229, 240, 4, 250,
30, 154, 3, 96, 48, 99, 180, 42, 0, 208, 4, 79, 58, 224, 3, 28, 52, 39, 128, 224, 0, 79, 56, 104, 235, 154, 7, 147,
4, 42, 0, 208, 2, 35, 128, 0, 91, 67, 31, 105, 235, 150, 9, 5, 91, 13, 91, 147, 5, 154, 5, 35, 128, 4, 91, 58, 1, 147,
6, 146, 8, 155, 5, 154, 3, 147, 0, 28, 32, 28, 59, 153, 4, 247, 255, 255, 92, 154, 3, 155, 4, 26, 18, 146, 3, 154, 7,
24, 27, 147, 4, 42, 0, 208, 1, 155, 6, 96, 99, 154, 8, 155, 5, 24, 128, 66, 3, 209, 2, 34, 128, 6, 18, 24, 191, 155,
3, 43, 0, 221, 11, 247, 255, 255, 38, 30, 6, 208, 52, 107, 112, 99, 245, 240, 4, 249, 218, 99, 166, 96, 32, 28, 52,
231, 213, 35, 128, 4, 91, 96, 99, 105, 43, 158, 9, 148, 3, 43, 0, 208, 29, 126, 42, 146, 4, 42, 0, 209, 25, 247, 255,
255, 14, 28, 4, 32, 0, 44, 0, 208, 27, 107, 96, 99, 229, 240, 4, 249, 192, 155, 3, 34, 128, 96, 24, 99, 156, 35, 128,
0, 91, 6, 18, 64, 123, 67, 19, 154, 4, 28, 32, 146, 0, 33, 0, 34, 0, 247, 255, 255, 20, 104, 162, 35, 128, 4, 27, 67,
19, 96, 163, 28, 48, 224, 0, 32, 0, 176, 11, 188, 240, 188, 2, 71, 8, 128, 0, 0, 128, 128, 0, 1, 128, 181, 56, 76, 19,
37, 32, 104, 35, 104, 155, 120, 25, 120, 90, 6, 9, 4, 18, 67, 10, 120, 153, 120, 219, 2, 9, 67, 10, 67, 19, 224, 18,
104, 34, 67, 171, 104, 146, 32, 10, 96, 19, 247, 255, 253, 243, 104, 35, 104, 155, 120, 25, 120, 90, 6, 9, 4, 18, 67,
10, 120, 153, 120, 219, 2, 9, 67, 10, 67, 19, 66, 29, 209, 234, 188, 56, 188, 1, 71, 0, 19, 112, 96, 60, 181, 56, 76,
19, 37, 32, 104, 35, 104, 155, 120, 25, 120, 90, 6, 9, 4, 18, 67, 10, 120, 153, 120, 219, 2, 9, 67, 10, 67, 19, 224,
18, 104, 34, 67, 43, 104, 146, 32, 10, 96, 19, 247, 255, 253, 201, 104, 35, 104, 155, 120, 25, 120, 90, 6, 9, 4, 18,
67, 10, 120, 153, 120, 219, 2, 9, 67, 10, 67, 19, 66, 29, 208, 234, 188, 56, 188, 1, 71, 0, 19, 112, 96, 60, 181, 248,
28, 12, 40, 0, 209, 33, 77, 28, 76, 29, 79, 29, 38, 0, 104, 43, 104, 155, 126, 25, 126, 90, 6, 9, 4, 18, 67, 10, 126,
153, 126, 219, 2, 9, 67, 10, 67, 19, 105, 34, 108, 82, 66, 147, 211, 6, 105, 98, 108, 82, 66, 147, 216, 2, 247, 255,
255, 142, 224, 25, 32, 10, 54, 1, 247, 255, 253, 147, 66, 190, 209, 226, 224, 18, 40, 1, 209, 16, 224, 6, 32, 10, 54,
1, 247, 255, 253, 137, 66, 190, 209, 3, 224, 8, 77, 6, 79, 8, 38, 0, 104, 43, 104, 155, 105, 154, 108, 99, 66, 154,
208, 239, 32, 0, 188, 248, 188, 2, 71, 8, 70, 192, 19, 112, 96, 60, 19, 114, 195, 160, 0, 0, 19, 136, 181, 0, 7, 67,
213, 21, 75, 12, 104, 27, 104, 154, 75, 11, 108, 81, 64, 11, 43, 3, 209, 2, 35, 128, 1, 155, 100, 83, 75, 6, 104, 27,
104, 154, 75, 6, 108, 145, 64, 11, 43, 3, 209, 2, 35, 128, 1, 155, 100, 147, 188, 1, 71, 0, 70, 192, 19, 112, 96, 60,
0, 0, 32, 3, 181, 16, 75, 19, 28, 4, 104, 27, 52, 16, 104, 155, 0, 164, 25, 28, 34, 128, 104, 99, 1, 146, 66, 19, 209,
0, 64, 83, 34, 46, 67, 147, 96, 99, 32, 5, 247, 255, 253, 106, 34, 128, 104, 99, 1, 146, 66, 19, 208, 0, 64, 83, 34,
46, 67, 147, 96, 99, 32, 5, 247, 255, 253, 94, 75, 4, 32, 5, 96, 99, 247, 255, 253, 89, 188, 16, 188, 1, 71, 0, 19,
112, 96, 60, 0, 0, 24, 1, 181, 240, 176, 131, 75, 36, 28, 5, 104, 27, 53, 16, 104, 155, 0, 173, 25, 93, 104, 107, 74,
33, 29, 44, 64, 26, 38, 4, 42, 1, 208, 4, 4, 154, 213, 51, 247, 255, 255, 192, 224, 48, 39, 136, 1, 127, 34, 4, 67,
147, 67, 59, 96, 35, 32, 60, 247, 255, 253, 40, 104, 35, 74, 24, 32, 50, 64, 19, 96, 35, 247, 255, 253, 33, 75, 22,
34, 128, 147, 0, 28, 32, 28, 33, 0, 82, 35, 0, 247, 255, 253, 156, 40, 0, 208, 2, 104, 107, 72, 17, 224, 20, 104, 35,
34, 4, 66, 26, 209, 16, 62, 1, 46, 0, 209, 220, 34, 128, 1, 146, 67, 19, 33, 42, 67, 139, 96, 107, 32, 10, 96, 106,
247, 255, 253, 2, 72, 8, 224, 1, 32, 1, 66, 64, 176, 3, 188, 240, 188, 2, 71, 8, 19, 112, 96, 60, 0, 0, 32, 1, 255,
255, 254, 213, 0, 0, 19, 136, 255, 255, 248, 48, 255, 255, 251, 161, 181, 16, 75, 20, 28, 4, 104, 27, 52, 16, 104, 155,
0, 164, 25, 28, 34, 128, 104, 99, 1, 146, 66, 19, 209, 0, 64, 83, 34, 46, 67, 147, 96, 99, 32, 5, 247, 255, 252, 230,
34, 128, 104, 99, 1, 146, 66, 19, 208, 0, 64, 83, 34, 46, 67, 147, 96, 99, 32, 5, 247, 255, 252, 218, 75, 5, 32, 60,
96, 99, 247, 255, 252, 213, 32, 1, 188, 16, 188, 2, 71, 8, 70, 192, 19, 112, 96, 60, 0, 0, 24, 1, 32, 0, 71, 112, 75,
5, 48, 16, 104, 27, 0, 128, 104, 155, 24, 24, 35, 128, 1, 155, 96, 67, 32, 0, 71, 112, 70, 192, 19, 112, 96, 60, 74,
5, 32, 0, 104, 19, 104, 153, 35, 128, 1, 155, 100, 75, 104, 18, 104, 146, 100, 147, 71, 112, 70, 192, 19, 112, 96, 60,
181, 0, 75, 10, 104, 27, 104, 154, 35, 128, 108, 81, 1, 155, 66, 25, 209, 0, 100, 83, 75, 5, 104, 27, 104, 154, 35,
128, 108, 145, 1, 155, 66, 25, 209, 0, 100, 147, 32, 0, 188, 2, 71, 8, 19, 112, 96, 60, 75, 6, 33, 0, 104, 26, 35, 1,
66, 91, 28, 16, 103, 17, 103, 147, 48, 152, 50, 160, 96, 1, 96, 19, 71, 112, 70, 192, 19, 112, 96, 60, 75, 6, 120, 27,
30, 90, 65, 147, 74, 5, 0, 152, 96, 19, 74, 5, 24, 195, 0, 219, 104, 16, 51, 88, 24, 192, 71, 112, 19, 112, 1, 12, 19,
112, 107, 80, 19, 112, 96, 60, 181, 16, 73, 19, 120, 9, 30, 72, 65, 129, 72, 18, 0, 140, 96, 1, 72, 17, 24, 97, 104,
0, 0, 201, 24, 64, 111, 4, 33, 0, 44, 0, 208, 16, 128, 25, 128, 89, 28, 1, 49, 96, 136, 8, 4, 0, 10, 4, 14, 0, 67, 32,
128, 152, 136, 73, 4, 9, 10, 8, 14, 9, 67, 1, 128, 217, 33, 1, 32, 0, 112, 17, 188, 16, 188, 2, 71, 8, 70, 192, 19,
112, 1, 12, 19, 112, 107, 80, 19, 112, 96, 60, 181, 0, 28, 3, 224, 8, 120, 90, 58, 4, 6, 18, 14, 18, 42, 1, 217, 4,
120, 26, 26, 137, 24, 155, 41, 0, 209, 244, 26, 24, 188, 2, 71, 8, 181, 240, 176, 133, 124, 130, 124, 195, 6, 18, 4,
27, 67, 19, 125, 2, 28, 5, 2, 18, 67, 19, 125, 66, 67, 26, 208, 103, 34, 0, 146, 3, 146, 1, 224, 83, 6, 36, 4, 9, 2,
18, 67, 12, 67, 20, 158, 3, 67, 35, 25, 156, 122, 98, 122, 163, 6, 18, 4, 27, 67, 19, 122, 226, 2, 18, 67, 19, 123,
34, 67, 26, 208, 58, 39, 0, 151, 2, 28, 46, 224, 36, 6, 0, 4, 9, 2, 18, 67, 8, 67, 16, 67, 3, 25, 221, 123, 170, 123,
235, 6, 18, 4, 27, 67, 19, 124, 42, 124, 104, 2, 18, 67, 19, 67, 24, 208, 1, 240, 2, 255, 250, 122, 106, 122, 171, 6,
18, 4, 27, 67, 19, 122, 234, 123, 40, 2, 18, 67, 19, 67, 24, 208, 1, 240, 2, 255, 237, 154, 2, 55, 18, 50, 1, 146, 2,
121, 35, 157, 2, 70, 156, 122, 96, 122, 161, 122, 226, 123, 35, 69, 101, 219, 209, 28, 53, 6, 6, 4, 8, 67, 48, 2, 18,
67, 16, 67, 24, 240, 2, 255, 215, 158, 1, 154, 3, 54, 1, 50, 13, 150, 1, 146, 3, 124, 104, 158, 1, 124, 172, 124, 233,
125, 42, 125, 107, 66, 134, 219, 163, 6, 36, 4, 8, 67, 32, 2, 18, 67, 16, 67, 24, 240, 2, 255, 193, 176, 5, 188, 240,
188, 1, 71, 0, 0, 0, 181, 248, 30, 5, 209, 4, 75, 28, 34, 48, 112, 26, 112, 93, 224, 47, 76, 26, 28, 46, 28, 48, 33,
10, 240, 4, 248, 128, 28, 48, 28, 15, 33, 10, 240, 4, 248, 119, 23, 251, 24, 255, 64, 95, 55, 48, 75, 20, 112, 39, 60,
1, 28, 6, 66, 156, 209, 236, 75, 15, 34, 0, 118, 154, 45, 0, 218, 2, 34, 45, 112, 26, 34, 1, 35, 16, 72, 10, 224, 0,
51, 1, 92, 193, 41, 48, 208, 251, 66, 72, 65, 65, 26, 91, 73, 6, 224, 2, 84, 136, 51, 1, 50, 1, 92, 200, 40, 0, 209,
249, 84, 136, 188, 248, 188, 1, 71, 0, 70, 192, 19, 114, 197, 96, 19, 114, 197, 121, 19, 114, 197, 111, 181, 248, 30,
4, 209, 4, 75, 24, 34, 48, 112, 26, 112, 92, 224, 40, 77, 22, 28, 47, 63, 10, 28, 32, 33, 10, 240, 4, 248, 23, 28, 32,
28, 14, 33, 10, 240, 4, 248, 30, 54, 48, 112, 46, 61, 1, 28, 4, 66, 189, 209, 240, 74, 12, 35, 0, 118, 147, 28, 17,
35, 16, 224, 0, 51, 1, 92, 202, 42, 48, 208, 251, 66, 81, 65, 74, 26, 155, 73, 6, 34, 0, 224, 2, 84, 136, 51, 1, 50,
1, 92, 200, 40, 0, 209, 249, 84, 136, 188, 248, 188, 1, 71, 0, 19, 114, 197, 96, 19, 114, 197, 121, 181, 16, 40, 0,
209, 4, 75, 24, 34, 48, 112, 26, 112, 88, 224, 40, 75, 22, 33, 15, 28, 28, 60, 8, 28, 10, 64, 2, 9, 0, 42, 9, 221, 0,
50, 7, 50, 48, 112, 26, 59, 1, 66, 163, 209, 244, 74, 14, 35, 0, 118, 19, 35, 48, 112, 19, 35, 120, 112, 83, 35, 16,
224, 0, 51, 1, 92, 209, 41, 48, 208, 251, 66, 74, 65, 74, 26, 155, 73, 6, 34, 2, 224, 2, 84, 136, 51, 1, 50, 1, 92,
200, 40, 0, 209, 249, 84, 136, 188, 16, 188, 1, 71, 0, 19, 114, 197, 96, 19, 114, 197, 119, 180, 15, 181, 240, 176,
133, 171, 10, 203, 64, 34, 128, 1, 146, 169, 3, 128, 10, 147, 2, 36, 0, 77, 46, 79, 46, 224, 81, 28, 114, 146, 1, 43,
37, 208, 12, 70, 106, 115, 19, 168, 3, 240, 3, 255, 41, 25, 4, 158, 1, 66, 172, 220, 68, 168, 3, 240, 3, 255, 222, 224,
64, 120, 115, 43, 115, 208, 46, 43, 115, 216, 4, 43, 100, 208, 7, 43, 105, 209, 53, 224, 4, 43, 117, 208, 9, 43, 120,
209, 48, 224, 20, 155, 2, 29, 26, 146, 2, 104, 24, 247, 255, 255, 26, 224, 19, 155, 2, 29, 26, 146, 2, 104, 24, 247,
255, 255, 85, 28, 56, 240, 3, 255, 2, 25, 4, 28, 56, 66, 172, 220, 27, 224, 24, 155, 2, 29, 26, 146, 2, 104, 24, 247,
255, 255, 127, 72, 16, 240, 3, 254, 244, 25, 4, 66, 172, 220, 14, 72, 13, 224, 10, 155, 2, 29, 26, 146, 2, 104, 30,
28, 48, 240, 3, 254, 232, 25, 4, 66, 172, 220, 2, 28, 48, 240, 3, 255, 158, 158, 1, 54, 1, 120, 51, 43, 0, 209, 170,
176, 5, 188, 240, 188, 8, 176, 4, 71, 24, 0, 0, 13, 171, 19, 114, 197, 96, 181, 240, 28, 12, 176, 133, 28, 6, 33, 0,
32, 0, 247, 255, 252, 176, 126, 35, 43, 0, 209, 6, 74, 218, 33, 8, 96, 19, 104, 32, 240, 2, 254, 69, 96, 96, 105, 33,
41, 0, 208, 9, 126, 99, 104, 160, 43, 0, 208, 2, 240, 2, 254, 59, 224, 1, 240, 2, 254, 64, 96, 224, 126, 35, 43, 0,
209, 3, 75, 207, 104, 27, 105, 219, 224, 6, 126, 99, 43, 0, 208, 1, 75, 205, 224, 0, 75, 205, 104, 27, 147, 2, 77, 204,
75, 205, 153, 2, 28, 40, 96, 25, 34, 96, 240, 2, 255, 104, 33, 0, 34, 48, 152, 2, 240, 3, 254, 69, 75, 195, 34, 0, 104,
27, 28, 32, 100, 26, 75, 197, 34, 1, 104, 25, 64, 74, 96, 26, 247, 255, 251, 121, 75, 195, 100, 168, 96, 24, 126, 34,
35, 15, 146, 1, 64, 26, 146, 3, 155, 3, 28, 7, 34, 128, 105, 176, 2, 29, 1, 146, 155, 1, 67, 2, 105, 225, 67, 42, 43,
0, 209, 1, 72, 186, 224, 5, 5, 72, 35, 128, 9, 64, 5, 219, 67, 3, 28, 24, 67, 16, 240, 3, 253, 158, 77, 176, 35, 64,
96, 171, 75, 180, 33, 255, 104, 27, 34, 255, 108, 91, 2, 9, 4, 18, 64, 25, 64, 26, 2, 9, 10, 18, 67, 10, 14, 25, 67,
10, 33, 224, 64, 11, 33, 2, 67, 11, 6, 27, 67, 26, 96, 104, 96, 42, 107, 120, 240, 3, 253, 130, 35, 128, 153, 1, 4,
91, 97, 40, 97, 107, 41, 0, 208, 16, 9, 203, 153, 3, 106, 114, 1, 27, 24, 91, 64, 218, 28, 19, 7, 218, 213, 3, 105,
170, 35, 128, 67, 19, 224, 2, 105, 171, 34, 128, 67, 147, 97, 171, 77, 150, 75, 156, 105, 170, 28, 40, 64, 19, 97, 171,
33, 96, 240, 2, 253, 195, 108, 173, 224, 4, 28, 40, 33, 96, 240, 2, 253, 189, 107, 173, 45, 0, 209, 248, 152, 2, 73,
141, 34, 96, 240, 2, 254, 224, 75, 146, 120, 27, 43, 0, 208, 4, 75, 145, 72, 145, 104, 25, 247, 255, 254, 218, 75, 144,
34, 1, 96, 26, 77, 130, 35, 0, 147, 1, 153, 1, 74, 139, 49, 1, 145, 1, 72, 140, 104, 17, 247, 254, 255, 192, 104, 43,
33, 32, 105, 152, 240, 2, 253, 173, 104, 42, 73, 124, 39, 2, 108, 75, 105, 145, 34, 255, 2, 18, 64, 26, 2, 16, 34, 255,
4, 18, 64, 26, 10, 18, 67, 2, 14, 24, 67, 2, 32, 224, 64, 3, 67, 59, 6, 24, 28, 19, 67, 3, 96, 11, 104, 43, 33, 32,
105, 152, 240, 2, 253, 125, 247, 255, 251, 163, 247, 254, 255, 201, 154, 1, 42, 4, 208, 6, 28, 3, 51, 9, 209, 3, 72,
118, 247, 255, 254, 158, 231, 200, 75, 114, 34, 0, 96, 26, 75, 109, 28, 7, 120, 27, 43, 0, 208, 3, 72, 113, 28, 57,
247, 255, 254, 145, 47, 0, 209, 3, 75, 93, 104, 27, 43, 0, 208, 15, 75, 92, 104, 27, 104, 154, 75, 107, 50, 68, 104,
27, 0, 155, 24, 211, 104, 27, 34, 5, 64, 19, 43, 5, 208, 2, 75, 84, 34, 1, 96, 26, 66, 121, 65, 121, 145, 1, 29, 122,
208, 1, 41, 0, 208, 65, 247, 255, 251, 66, 77, 79, 33, 32, 104, 43, 105, 152, 240, 3, 254, 144, 104, 43, 33, 32, 105,
152, 240, 2, 253, 39, 75, 82, 104, 42, 104, 27, 105, 145, 108, 91, 34, 255, 2, 18, 64, 26, 2, 16, 34, 255, 4, 18, 64,
26, 10, 18, 67, 2, 14, 24, 67, 2, 32, 224, 64, 3, 32, 2, 67, 3, 6, 24, 28, 19, 67, 3, 96, 11, 104, 43, 33, 32, 105,
152, 240, 3, 254, 78, 247, 255, 251, 66, 126, 34, 42, 0, 208, 98, 9, 211, 32, 15, 64, 16, 1, 27, 24, 27, 106, 113, 34,
1, 64, 154, 67, 145, 28, 10, 73, 70, 104, 9, 6, 9, 15, 201, 64, 153, 28, 11, 67, 19, 98, 115, 224, 79, 247, 255, 251,
0, 75, 49, 108, 157, 224, 4, 107, 104, 33, 96, 240, 2, 253, 15, 107, 173, 45, 0, 209, 248, 77, 44, 34, 32, 28, 40, 153,
2, 240, 2, 254, 42, 126, 34, 42, 0, 208, 16, 9, 211, 32, 15, 64, 16, 1, 27, 24, 27, 106, 113, 34, 1, 64, 154, 67, 145,
28, 10, 105, 169, 6, 9, 15, 201, 64, 153, 28, 11, 67, 19, 98, 115, 77, 28, 33, 32, 104, 43, 38, 2, 105, 152, 240, 3,
254, 41, 104, 43, 33, 32, 105, 152, 240, 2, 252, 192, 75, 30, 104, 42, 104, 27, 105, 145, 108, 91, 34, 255, 2, 18, 64,
26, 2, 16, 34, 255, 4, 18, 64, 26, 10, 18, 67, 2, 14, 24, 67, 2, 32, 224, 64, 3, 67, 51, 6, 24, 28, 19, 67, 3, 96, 11,
104, 43, 33, 32, 105, 152, 240, 3, 253, 232, 247, 255, 250, 220, 73, 10, 32, 1, 247, 255, 251, 2, 105, 33, 41, 0, 208,
48, 126, 99, 104, 224, 43, 0, 208, 42, 240, 2, 252, 175, 224, 41, 19, 112, 107, 84, 19, 112, 96, 60, 19, 112, 106, 244,
19, 112, 107, 72, 19, 114, 197, 0, 19, 112, 106, 252, 19, 112, 107, 64, 19, 112, 107, 20, 64, 64, 64, 0, 19, 112, 107,
68, 1, 0, 0, 128, 19, 112, 106, 248, 19, 112, 96, 56, 19, 112, 96, 194, 19, 112, 107, 16, 19, 112, 41, 229, 19, 112,
98, 156, 19, 112, 96, 240, 19, 112, 107, 80, 19, 112, 107, 4, 240, 2, 252, 138, 126, 35, 43, 0, 209, 3, 104, 96, 33,
8, 240, 2, 252, 125, 155, 1, 43, 0, 208, 0, 105, 103, 176, 5, 28, 56, 188, 240, 188, 2, 71, 8, 181, 48, 176, 137, 70,
108, 118, 33, 9, 201, 118, 97, 33, 128, 0, 137, 37, 0, 145, 7, 70, 105, 149, 0, 146, 4, 147, 2, 247, 255, 253, 246,
176, 9, 188, 48, 188, 2, 71, 8, 181, 240, 176, 139, 28, 6, 70, 104, 48, 70, 136, 4, 72, 43, 70, 156, 104, 0, 70, 107,
51, 66, 48, 248, 104, 0, 136, 27, 112, 66, 4, 27, 70, 98, 147, 1, 2, 19, 10, 18, 67, 19, 4, 26, 12, 19, 14, 18, 112,
1, 159, 18, 112, 130, 112, 195, 155, 1, 4, 36, 10, 26, 14, 27, 67, 19, 4, 27, 12, 37, 12, 26, 14, 27, 113, 3, 14, 36,
2, 43, 67, 35, 4, 27, 113, 66, 14, 26, 12, 27, 113, 195, 172, 2, 35, 0, 113, 130, 118, 35, 35, 64, 97, 227, 75, 21,
9, 201, 144, 2, 118, 97, 97, 37, 66, 159, 217, 22, 28, 40, 240, 2, 252, 52, 28, 42, 28, 57, 96, 160, 240, 3, 251, 237,
28, 33, 28, 48, 247, 255, 253, 171, 104, 164, 28, 6, 28, 33, 28, 56, 28, 42, 240, 3, 251, 226, 28, 32, 240, 2, 252,
63, 224, 5, 28, 48, 96, 167, 28, 33, 247, 255, 253, 155, 28, 6, 176, 11, 28, 48, 188, 240, 188, 2, 71, 8, 70, 192, 19,
112, 96, 60, 19, 136, 0, 0, 181, 0, 176, 133, 145, 0, 35, 0, 33, 2, 34, 1, 147, 1, 147, 2, 247, 255, 255, 148, 176,
5, 188, 2, 71, 8, 181, 0, 176, 133, 28, 19, 34, 0, 145, 0, 146, 1, 146, 2, 33, 1, 34, 11, 247, 255, 255, 134, 176, 5,
188, 2, 71, 8, 181, 0, 176, 133, 34, 0, 146, 0, 146, 1, 146, 2, 28, 11, 34, 9, 33, 0, 247, 255, 255, 120, 176, 5, 188,
2, 71, 8, 181, 112, 28, 4, 176, 132, 32, 1, 28, 14, 240, 2, 251, 224, 30, 5, 208, 18, 35, 0, 147, 0, 35, 1, 147, 1,
28, 32, 33, 128, 34, 8, 35, 0, 149, 2, 247, 255, 255, 97, 30, 4, 219, 1, 120, 43, 112, 51, 28, 40, 240, 2, 251, 234,
224, 1, 36, 4, 66, 100, 176, 4, 28, 32, 188, 112, 188, 2, 71, 8, 181, 16, 176, 132, 70, 108, 2, 18, 52, 27, 120, 36,
67, 19, 34, 0, 146, 0, 145, 2, 34, 6, 33, 128, 148, 1, 247, 255, 255, 67, 176, 4, 188, 16, 188, 2, 71, 8, 0, 0, 181,
240, 176, 137, 75, 65, 28, 2, 104, 30, 0, 129, 104, 179, 24, 9, 50, 16, 0, 201, 0, 146, 24, 154, 28, 11, 51, 88, 28,
7, 24, 240, 144, 5, 24, 113, 32, 0, 103, 8, 104, 81, 29, 21, 74, 56, 64, 10, 42, 1, 209, 99, 34, 4, 146, 4, 147, 7,
75, 54, 32, 10, 96, 43, 247, 254, 255, 156, 75, 52, 32, 100, 96, 43, 247, 254, 255, 151, 75, 51, 34, 128, 96, 43, 35,
250, 0, 219, 147, 0, 0, 82, 35, 0, 28, 40, 28, 41, 247, 255, 248, 15, 104, 42, 75, 45, 28, 4, 64, 19, 43, 5, 209, 50,
35, 192, 1, 27, 64, 26, 35, 128, 0, 219, 66, 154, 208, 43, 40, 0, 209, 43, 32, 100, 247, 254, 255, 121, 75, 38, 74,
38, 104, 24, 96, 26, 154, 7, 35, 22, 147, 1, 24, 179, 147, 2, 35, 128, 144, 6, 33, 128, 152, 5, 34, 6, 0, 91, 148, 0,
247, 255, 254, 231, 30, 4, 219, 12, 28, 123, 32, 0, 4, 27, 144, 0, 144, 1, 144, 2, 12, 27, 152, 5, 33, 0, 34, 5, 247,
255, 254, 217, 28, 4, 75, 21, 154, 6, 96, 26, 44, 0, 219, 2, 224, 8, 36, 1, 66, 100, 155, 4, 59, 1, 147, 4, 43, 0, 209,
169, 44, 0, 219, 10, 0, 187, 25, 219, 0, 219, 24, 246, 55, 1, 35, 0, 103, 243, 103, 55, 224, 1, 36, 1, 66, 100, 176,
9, 28, 32, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 96, 60, 0, 0, 32, 1, 0, 0, 24, 3, 0, 0, 25, 3, 0, 0, 16, 1, 0,
0, 32, 5, 19, 112, 96, 56, 0, 6, 26, 128, 181, 248, 76, 25, 28, 6, 104, 35, 104, 157, 35, 1, 96, 171, 247, 255, 255,
97, 30, 7, 218, 24, 104, 35, 33, 55, 104, 155, 28, 52, 104, 90, 32, 10, 64, 10, 96, 90, 52, 16, 247, 254, 255, 18, 0,
164, 75, 15, 25, 44, 96, 99, 32, 50, 247, 254, 255, 11, 75, 13, 32, 100, 96, 99, 247, 254, 255, 6, 75, 11, 96, 99, 75,
7, 32, 55, 104, 26, 104, 146, 104, 81, 64, 1, 96, 81, 104, 27, 34, 4, 104, 155, 28, 56, 96, 154, 188, 248, 188, 2, 71,
8, 70, 192, 19, 112, 96, 60, 0, 0, 24, 3, 0, 0, 25, 3, 0, 0, 16, 1, 181, 240, 176, 137, 75, 126, 34, 0, 104, 31, 0,
131, 24, 27, 0, 219, 28, 30, 147, 5, 54, 88, 24, 251, 28, 4, 25, 190, 103, 26, 32, 50, 247, 254, 254, 218, 37, 3, 150,
6, 72, 118, 247, 255, 251, 219, 32, 50, 247, 254, 254, 210, 35, 22, 147, 1, 155, 6, 34, 0, 147, 2, 35, 128, 146, 0,
28, 48, 33, 128, 34, 6, 0, 91, 247, 255, 254, 69, 40, 0, 218, 12, 72, 109, 247, 255, 251, 198, 32, 50, 247, 254, 254,
189, 61, 1, 32, 100, 247, 254, 254, 185, 45, 0, 209, 222, 224, 2, 154, 5, 24, 187, 224, 38, 28, 32, 247, 255, 249, 106,
75, 100, 66, 152, 209, 0, 224, 184, 32, 100, 247, 254, 254, 169, 72, 98, 247, 255, 251, 172, 35, 22, 147, 1, 155, 6,
34, 0, 147, 2, 35, 128, 146, 0, 28, 48, 33, 128, 34, 6, 0, 91, 247, 255, 254, 25, 40, 0, 218, 6, 72, 90, 53, 1, 247,
255, 251, 153, 45, 3, 209, 221, 224, 12, 0, 163, 25, 27, 0, 219, 24, 251, 110, 26, 75, 85, 66, 154, 209, 46, 28, 32,
247, 255, 249, 199, 76, 83, 224, 144, 28, 32, 247, 255, 249, 14, 32, 100, 247, 254, 254, 125, 28, 32, 247, 255, 249,
52, 74, 73, 66, 144, 209, 0, 224, 130, 32, 100, 247, 254, 254, 115, 72, 75, 247, 255, 251, 118, 35, 0, 154, 6, 147,
0, 35, 22, 147, 1, 35, 128, 146, 2, 28, 48, 33, 128, 34, 6, 0, 91, 247, 255, 253, 227, 40, 0, 218, 7, 72, 63, 61, 1,
247, 255, 251, 99, 45, 0, 209, 215, 76, 64, 224, 102, 72, 64, 247, 255, 251, 92, 28, 99, 147, 5, 4, 27, 12, 27, 147,
7, 0, 163, 25, 28, 0, 228, 37, 0, 25, 63, 32, 50, 247, 254, 254, 73, 72, 57, 28, 41, 247, 255, 251, 75, 35, 0, 147,
0, 147, 1, 147, 2, 28, 48, 33, 0, 34, 5, 155, 7, 247, 255, 253, 187, 30, 4, 218, 7, 76, 50, 28, 41, 72, 50, 27, 100,
247, 255, 251, 57, 53, 1, 224, 3, 72, 48, 28, 41, 247, 255, 251, 51, 155, 5, 34, 0, 103, 250, 103, 59, 44, 0, 218, 47,
33, 0, 28, 48, 247, 255, 254, 5, 32, 50, 247, 254, 254, 32, 72, 40, 247, 255, 251, 35, 35, 22, 147, 1, 155, 6, 34, 0,
147, 2, 35, 128, 146, 0, 28, 48, 33, 128, 34, 6, 0, 91, 247, 255, 253, 144, 30, 4, 218, 6, 72, 32, 247, 255, 251, 17,
34, 0, 103, 58, 76, 31, 224, 2, 72, 31, 247, 255, 251, 10, 53, 1, 44, 0, 218, 7, 15, 233, 34, 0, 35, 4, 66, 171, 65,
74, 6, 18, 42, 0, 209, 172, 44, 0, 219, 4, 72, 24, 247, 255, 250, 250, 224, 0, 76, 6, 176, 9, 28, 32, 188, 240, 188,
2, 71, 8, 70, 192, 19, 112, 96, 60, 19, 112, 97, 75, 19, 112, 97, 0, 255, 255, 251, 161, 19, 112, 97, 30, 19, 112, 97,
69, 149, 11, 32, 119, 255, 255, 251, 160, 19, 112, 97, 106, 255, 255, 247, 103, 19, 112, 97, 155, 19, 112, 97, 181,
255, 255, 224, 192, 19, 112, 97, 212, 19, 112, 97, 243, 19, 112, 98, 55, 19, 112, 98, 14, 255, 255, 247, 62, 19, 112,
98, 52, 19, 112, 98, 87, 181, 16, 75, 10, 34, 1, 104, 27, 28, 4, 104, 155, 96, 154, 247, 255, 248, 117, 40, 0, 219,
2, 28, 32, 247, 255, 254, 202, 75, 3, 34, 4, 104, 27, 104, 155, 96, 154, 188, 16, 188, 2, 71, 8, 19, 112, 96, 60, 181,
240, 176, 141, 144, 6, 32, 22, 28, 13, 240, 2, 249, 151, 30, 7, 209, 0, 224, 214, 32, 10, 247, 254, 253, 159, 35, 18,
147, 0, 152, 6, 28, 57, 34, 1, 35, 0, 247, 255, 253, 197, 40, 0, 218, 54, 72, 180, 247, 255, 250, 152, 76, 179, 104,
32, 247, 255, 255, 202, 28, 6, 32, 20, 247, 254, 253, 138, 75, 176, 104, 32, 104, 27, 0, 130, 104, 155, 51, 68, 24,
155, 104, 26, 46, 0, 219, 4, 75, 172, 64, 26, 75, 172, 66, 154, 208, 13, 247, 255, 254, 81, 32, 20, 247, 254, 253, 118,
75, 166, 104, 27, 104, 154, 75, 164, 50, 68, 104, 27, 0, 155, 24, 211, 104, 27, 32, 30, 247, 254, 253, 106, 35, 18,
147, 0, 152, 6, 28, 57, 34, 1, 35, 0, 247, 255, 253, 144, 30, 4, 218, 1, 72, 158, 224, 165, 28, 57, 34, 18, 28, 40,
240, 3, 249, 9, 28, 56, 240, 2, 249, 102, 120, 170, 120, 235, 2, 18, 67, 26, 4, 18, 10, 19, 14, 18, 67, 19, 4, 27, 12,
26, 112, 234, 14, 27, 122, 42, 112, 171, 122, 107, 2, 18, 67, 26, 4, 18, 10, 19, 14, 18, 67, 19, 4, 27, 12, 26, 114,
106, 14, 27, 122, 170, 114, 43, 122, 235, 2, 18, 67, 26, 4, 18, 10, 19, 14, 18, 67, 19, 4, 27, 12, 26, 114, 234, 14,
27, 123, 42, 114, 171, 123, 107, 2, 18, 67, 26, 4, 18, 10, 19, 14, 18, 67, 19, 4, 27, 12, 26, 14, 27, 115, 43, 124,
107, 115, 106, 0, 88, 24, 192, 0, 128, 24, 192, 240, 2, 249, 13, 14, 3, 116, 171, 12, 3, 116, 235, 10, 3, 117, 43, 117,
104, 40, 0, 209, 1, 72, 120, 224, 204, 124, 107, 33, 0, 0, 90, 24, 210, 0, 146, 24, 210, 240, 3, 248, 250, 33, 0, 145,
10, 145, 5, 28, 46, 225, 51, 32, 9, 240, 2, 248, 242, 30, 4, 208, 49, 154, 5, 28, 33, 6, 19, 14, 27, 147, 3, 35, 9,
147, 0, 34, 2, 155, 3, 152, 6, 247, 255, 253, 32, 124, 179, 124, 245, 6, 27, 4, 45, 67, 29, 125, 51, 28, 33, 2, 27,
67, 29, 125, 115, 34, 9, 67, 29, 155, 10, 24, 237, 28, 40, 240, 3, 248, 145, 28, 32, 240, 2, 248, 238, 120, 170, 120,
235, 2, 18, 67, 26, 4, 18, 10, 19, 14, 18, 67, 19, 4, 27, 12, 28, 14, 27, 112, 171, 112, 236, 28, 32, 240, 2, 248, 192,
30, 7, 209, 6, 28, 53, 72, 86, 36, 4, 247, 255, 249, 205, 66, 100, 225, 3, 120, 235, 152, 6, 147, 0, 28, 57, 34, 2,
155, 3, 247, 255, 252, 235, 40, 0, 218, 5, 28, 4, 72, 78, 28, 53, 247, 255, 249, 188, 224, 238, 120, 41, 145, 2, 121,
43, 0, 216, 24, 192, 0, 64, 240, 2, 248, 159, 14, 3, 114, 107, 12, 3, 114, 171, 10, 3, 114, 235, 115, 40, 40, 0, 209,
2, 28, 53, 72, 68, 224, 93, 155, 2, 154, 2, 26, 228, 25, 210, 146, 3, 148, 4, 121, 43, 33, 0, 0, 218, 24, 210, 0, 82,
240, 3, 248, 134, 33, 0, 145, 11, 145, 8, 224, 177, 122, 107, 122, 172, 6, 27, 4, 36, 67, 28, 122, 235, 154, 11, 2,
27, 67, 28, 123, 43, 153, 3, 67, 28, 24, 164, 28, 32, 34, 9, 240, 3, 248, 47, 120, 35, 147, 2, 121, 35, 0, 216, 26,
192, 240, 2, 248, 106, 14, 3, 115, 163, 12, 3, 115, 227, 10, 3, 116, 35, 116, 96, 40, 0, 209, 2, 28, 53, 72, 42, 224,
40, 153, 3, 155, 4, 28, 10, 153, 2, 24, 82, 153, 2, 146, 3, 26, 91, 147, 4, 121, 35, 33, 0, 0, 218, 26, 210, 240, 3,
248, 79, 152, 3, 153, 4, 247, 255, 248, 33, 35, 11, 144, 2, 70, 106, 92, 154, 115, 98, 155, 2, 43, 0, 208, 31, 28, 24,
240, 2, 248, 64, 14, 3, 114, 99, 12, 3, 114, 163, 10, 3, 114, 227, 115, 32, 40, 0, 209, 6, 72, 23, 28, 53, 36, 4, 247,
255, 249, 70, 66, 100, 224, 119, 153, 3, 154, 2, 240, 2, 255, 234, 153, 3, 155, 4, 28, 10, 153, 2, 24, 82, 153, 2, 146,
3, 26, 91, 147, 4, 34, 0, 146, 7, 146, 9, 224, 68, 70, 192, 19, 112, 98, 121, 19, 112, 107, 80, 19, 112, 96, 60, 0,
0, 49, 5, 0, 0, 16, 5, 19, 112, 98, 163, 19, 112, 98, 198, 19, 112, 98, 96, 19, 112, 98, 236, 19, 112, 99, 22, 19, 112,
99, 56, 19, 112, 99, 89, 123, 162, 123, 227, 6, 18, 4, 27, 67, 19, 124, 34, 153, 7, 2, 18, 67, 19, 124, 98, 67, 19,
24, 201, 145, 2, 28, 8, 34, 7, 153, 3, 240, 2, 255, 178, 154, 2, 153, 3, 120, 19, 24, 201, 145, 3, 153, 2, 121, 18,
121, 75, 2, 18, 67, 26, 4, 18, 10, 17, 14, 19, 67, 11, 4, 27, 153, 2, 12, 26, 14, 27, 113, 11, 113, 74, 154, 9, 155,
7, 50, 1, 51, 7, 146, 9, 147, 7, 121, 35, 153, 9, 66, 153, 211, 207, 154, 8, 155, 11, 50, 1, 51, 18, 146, 8, 147, 11,
121, 43, 153, 8, 66, 153, 210, 0, 231, 72, 28, 56, 240, 1, 255, 230, 154, 5, 155, 10, 50, 1, 51, 13, 146, 5, 147, 10,
39, 0, 124, 115, 153, 5, 66, 153, 210, 0, 230, 198, 28, 53, 36, 0, 47, 0, 208, 7, 28, 56, 240, 1, 255, 211, 44, 0, 208,
2, 28, 40, 247, 254, 255, 151, 176, 13, 28, 32, 188, 240, 188, 2, 71, 8, 70, 192, 181, 248, 28, 4, 38, 3, 39, 64, 224,
79, 104, 160, 240, 2, 255, 38, 10, 3, 64, 51, 28, 5, 43, 2, 208, 7, 107, 227, 108, 34, 105, 89, 24, 138, 0, 65, 12,
73, 26, 82, 97, 90, 108, 35, 43, 0, 208, 59, 66, 47, 208, 57, 75, 36, 120, 27, 43, 0, 208, 2, 72, 35, 247, 255, 248,
157, 6, 235, 213, 6, 75, 32, 120, 27, 43, 0, 208, 2, 72, 32, 247, 255, 248, 148, 7, 107, 213, 6, 75, 27, 120, 27, 43,
0, 208, 2, 72, 28, 247, 255, 248, 139, 6, 171, 213, 6, 75, 23, 120, 27, 43, 0, 208, 2, 72, 25, 247, 255, 248, 130, 7,
43, 213, 6, 75, 18, 120, 27, 43, 0, 208, 2, 72, 21, 247, 255, 248, 121, 75, 15, 120, 27, 43, 0, 208, 2, 72, 19, 247,
255, 248, 114, 75, 11, 120, 27, 43, 0, 208, 8, 72, 16, 247, 255, 248, 107, 224, 4, 107, 164, 44, 0, 209, 173, 32, 0,
224, 3, 107, 227, 32, 1, 66, 64, 97, 88, 75, 11, 34, 0, 104, 27, 100, 26, 188, 248, 188, 2, 71, 8, 19, 112, 106, 248,
19, 112, 99, 118, 19, 112, 99, 131, 19, 112, 99, 139, 19, 112, 99, 160, 19, 112, 99, 179, 19, 112, 99, 190, 19, 112,
105, 116, 19, 112, 96, 60, 181, 240, 176, 131, 28, 5, 35, 9, 7, 193, 213, 60, 75, 58, 120, 27, 43, 0, 208, 2, 72, 57,
247, 255, 248, 59, 75, 57, 104, 28, 44, 0, 208, 9, 107, 96, 33, 96, 240, 3, 248, 79, 107, 96, 33, 96, 240, 1, 254, 239,
107, 164, 231, 243, 76, 51, 104, 35, 43, 0, 208, 24, 108, 88, 33, 32, 240, 3, 248, 65, 104, 35, 33, 32, 108, 88, 240,
1, 254, 224, 104, 35, 34, 128, 4, 82, 97, 26, 74, 43, 108, 88, 104, 18, 33, 32, 107, 82, 97, 90, 240, 3, 248, 32, 104,
35, 105, 154, 75, 39, 96, 26, 75, 35, 104, 24, 247, 255, 255, 78, 35, 0, 40, 0, 208, 4, 74, 36, 104, 18, 100, 19, 35,
5, 66, 91, 7, 106, 213, 40, 75, 26, 120, 27, 43, 0, 208, 2, 72, 31, 247, 254, 255, 251, 33, 128, 1, 137, 79, 28, 78,
29, 35, 1, 34, 0, 145, 1, 104, 56, 104, 49, 104, 128, 0, 148, 48, 68, 25, 0, 70, 140, 104, 4, 69, 98, 209, 7, 32, 1,
66, 32, 209, 10, 75, 22, 96, 24, 35, 1, 66, 91, 224, 5, 73, 20, 64, 12, 44, 3, 209, 1, 153, 1, 96, 1, 50, 1, 42, 4,
209, 228, 43, 0, 208, 4, 34, 18, 66, 42, 208, 1, 35, 6, 66, 91, 176, 3, 28, 24, 188, 240, 188, 2, 71, 8, 70, 192, 19,
112, 106, 248, 19, 112, 99, 207, 19, 112, 107, 20, 19, 112, 106, 252, 19, 112, 107, 8, 19, 112, 107, 4, 19, 112, 96,
60, 19, 112, 99, 240, 19, 112, 107, 80, 19, 112, 107, 84, 0, 0, 32, 3, 181, 240, 176, 131, 147, 1, 70, 107, 51, 39,
120, 30, 28, 5, 30, 115, 6, 27, 14, 27, 145, 0, 28, 23, 43, 15, 216, 61, 28, 4, 52, 160, 104, 32, 40, 0, 208, 56, 33,
0, 34, 31, 240, 2, 254, 139, 104, 35, 74, 29, 96, 26, 28, 43, 51, 152, 104, 24, 240, 2, 254, 7, 104, 35, 96, 88, 28,
56, 240, 2, 254, 2, 104, 35, 70, 105, 96, 152, 29, 202, 120, 17, 104, 35, 70, 106, 115, 25, 28, 209, 104, 35, 120, 10,
115, 90, 104, 34, 35, 6, 46, 6, 217, 0, 35, 10, 28, 44, 115, 147, 52, 160, 104, 32, 153, 8, 28, 50, 48, 15, 240, 2,
254, 34, 28, 43, 51, 144, 104, 24, 123, 105, 104, 35, 34, 31, 247, 255, 249, 214, 40, 31, 208, 6, 40, 0, 219, 5, 72,
5, 224, 3, 32, 3, 66, 64, 224, 0, 32, 0, 176, 3, 188, 240, 188, 2, 71, 8, 85, 83, 66, 67, 255, 255, 216, 238, 181, 240,
28, 4, 176, 131, 52, 160, 28, 5, 145, 0, 28, 23, 33, 255, 34, 13, 104, 32, 240, 2, 254, 62, 28, 43, 51, 144, 104, 24,
123, 41, 104, 35, 34, 13, 247, 255, 249, 176, 40, 13, 208, 1, 40, 0, 218, 40, 40, 0, 219, 43, 28, 43, 51, 160, 104,
28, 104, 32, 240, 2, 253, 174, 144, 1, 104, 96, 240, 2, 253, 170, 28, 6, 104, 160, 240, 2, 253, 166, 74, 16, 153, 1,
123, 35, 66, 145, 209, 21, 47, 0, 208, 0, 96, 56, 154, 0, 42, 0, 208, 0, 112, 19, 53, 152, 104, 43, 66, 158, 209, 12,
28, 179, 4, 27, 12, 54, 12, 27, 4, 54, 67, 30, 96, 46, 32, 0, 224, 4, 72, 5, 224, 2, 72, 5, 224, 0, 72, 5, 176, 3, 188,
240, 188, 2, 71, 8, 83, 66, 83, 85, 255, 255, 216, 237, 255, 255, 216, 236, 255, 255, 216, 235, 181, 240, 176, 135,
74, 75, 75, 76, 120, 18, 28, 6, 104, 31, 42, 0, 208, 1, 73, 74, 224, 0, 73, 74, 96, 25, 28, 51, 51, 144, 104, 24, 75,
72, 104, 27, 104, 153, 105, 195, 49, 68, 0, 155, 24, 203, 104, 25, 35, 1, 66, 11, 209, 6, 74, 68, 36, 1, 96, 19, 75,
62, 66, 100, 96, 31, 224, 113, 75, 60, 42, 0, 208, 1, 74, 60, 224, 0, 74, 60, 96, 26, 75, 62, 120, 27, 43, 0, 208, 17,
136, 243, 34, 255, 147, 0, 33, 33, 35, 0, 147, 1, 147, 2, 247, 255, 249, 80, 28, 4, 28, 33, 72, 55, 247, 254, 254, 209,
32, 60, 247, 254, 249, 200, 224, 6, 33, 0, 247, 255, 249, 166, 32, 5, 247, 254, 249, 193, 36, 0, 75, 41, 120, 26, 75,
41, 42, 0, 208, 1, 74, 41, 224, 0, 74, 41, 28, 53, 96, 26, 53, 144, 44, 0, 218, 10, 32, 50, 247, 254, 249, 176, 104,
40, 33, 0, 247, 255, 249, 142, 32, 5, 247, 254, 249, 169, 224, 48, 123, 49, 104, 40, 247, 255, 249, 134, 28, 4, 32,
5, 247, 254, 249, 160, 72, 33, 28, 33, 247, 254, 254, 162, 44, 0, 219, 34, 123, 113, 104, 40, 247, 255, 249, 120, 28,
4, 32, 5, 247, 254, 249, 146, 72, 27, 28, 33, 247, 254, 254, 148, 44, 0, 219, 20, 32, 10, 247, 254, 249, 137, 70, 105,
49, 23, 104, 40, 247, 255, 249, 143, 28, 4, 28, 33, 72, 20, 247, 254, 254, 133, 44, 0, 219, 5, 72, 19, 247, 254, 254,
128, 75, 7, 96, 31, 224, 4, 75, 6, 34, 1, 96, 31, 75, 8, 96, 26, 176, 7, 28, 32, 188, 240, 188, 2, 71, 8, 70, 192, 19,
112, 1, 15, 19, 112, 96, 56, 0, 15, 66, 64, 0, 3, 13, 64, 19, 112, 96, 60, 19, 112, 107, 84, 19, 112, 1, 13, 19, 112,
100, 17, 19, 112, 100, 50, 19, 112, 100, 89, 19, 112, 100, 129, 19, 112, 100, 176, 181, 240, 176, 141, 146, 6, 70, 106,
50, 79, 120, 18, 28, 31, 70, 107, 51, 95, 146, 7, 70, 106, 120, 27, 50, 83, 120, 18, 6, 27, 22, 27, 146, 8, 70, 106,
50, 47, 147, 4, 35, 0, 112, 19, 74, 147, 77, 148, 28, 6, 145, 5, 147, 10, 96, 19, 147, 3, 36, 0, 28, 163, 43, 1, 216,
0, 225, 6, 44, 0, 208, 33, 28, 48, 33, 0, 247, 255, 255, 38, 30, 4, 219, 1, 32, 5, 224, 0, 32, 60, 247, 254, 249, 37,
75, 137, 104, 27, 104, 154, 75, 136, 50, 68, 104, 27, 0, 155, 24, 211, 104, 27, 44, 0, 218, 9, 154, 3, 50, 1, 146, 3,
42, 2, 221, 0, 224, 232, 32, 10, 247, 254, 249, 17, 224, 219, 35, 0, 147, 3, 155, 4, 154, 8, 59, 1, 6, 27, 22, 27, 147,
4, 42, 0, 208, 59, 104, 43, 74, 123, 147, 2, 120, 19, 43, 0, 208, 1, 75, 121, 224, 0, 75, 121, 96, 43, 154, 7, 155,
18, 146, 1, 147, 0, 28, 58, 35, 0, 28, 48, 153, 5, 247, 255, 254, 66, 75, 110, 154, 2, 28, 4, 96, 26, 28, 131, 43, 1,
216, 0, 224, 190, 40, 0, 218, 0, 224, 178, 155, 6, 34, 144, 25, 146, 28, 60, 147, 2, 146, 9, 224, 18, 155, 9, 123, 113,
104, 24, 28, 34, 155, 2, 247, 255, 248, 69, 28, 131, 43, 1, 216, 0, 224, 159, 40, 0, 219, 69, 66, 160, 209, 67, 154,
2, 26, 36, 24, 18, 146, 2, 44, 0, 209, 234, 224, 62, 104, 43, 74, 93, 147, 2, 120, 19, 43, 0, 208, 1, 75, 91, 224, 0,
75, 91, 96, 43, 154, 7, 155, 18, 146, 1, 147, 0, 28, 58, 35, 128, 28, 48, 153, 5, 247, 255, 254, 6, 75, 80, 154, 2,
28, 4, 96, 26, 40, 0, 218, 3, 72, 83, 28, 33, 247, 254, 253, 178, 28, 163, 43, 1, 217, 125, 44, 0, 218, 22, 224, 113,
28, 51, 51, 144, 104, 24, 123, 49, 28, 58, 155, 6, 247, 255, 248, 10, 30, 4, 218, 3, 72, 74, 28, 33, 247, 254, 253,
158, 28, 163, 43, 1, 217, 96, 44, 0, 219, 5, 66, 188, 208, 5, 224, 2, 47, 0, 209, 231, 224, 1, 76, 68, 224, 86, 75,
59, 74, 61, 104, 27, 147, 2, 120, 19, 43, 0, 208, 1, 75, 59, 224, 0, 75, 59, 74, 54, 70, 105, 96, 19, 28, 48, 49, 47,
170, 10, 247, 255, 254, 33, 30, 4, 218, 34, 72, 58, 28, 33, 247, 254, 253, 121, 28, 99, 209, 3, 75, 46, 154, 2, 96,
26, 224, 65, 28, 52, 52, 144, 104, 32, 123, 49, 247, 255, 248, 73, 123, 51, 32, 15, 104, 34, 64, 24, 9, 219, 1, 27,
106, 81, 24, 27, 32, 1, 64, 152, 67, 129, 98, 81, 70, 105, 28, 48, 49, 47, 170, 10, 247, 255, 253, 253, 28, 4, 75, 31,
154, 2, 96, 26, 28, 163, 43, 1, 217, 34, 155, 10, 43, 0, 208, 7, 75, 37, 104, 27, 43, 0, 208, 3, 70, 107, 34, 1, 51,
47, 112, 26, 44, 0, 219, 12, 75, 32, 36, 0, 104, 27, 43, 0, 208, 7, 70, 107, 51, 47, 120, 27, 43, 0, 208, 2, 76, 28,
224, 0, 28, 4, 155, 4, 43, 0, 221, 2, 44, 0, 218, 0, 230, 247, 34, 0, 44, 0, 218, 0, 34, 1, 75, 9, 96, 26, 154, 21,
42, 0, 208, 3, 70, 107, 51, 47, 120, 27, 112, 19, 155, 22, 43, 0, 208, 2, 155, 10, 154, 22, 96, 19, 176, 13, 28, 32,
188, 240, 188, 2, 71, 8, 19, 112, 107, 84, 19, 112, 96, 56, 19, 112, 96, 60, 19, 112, 107, 80, 19, 112, 1, 15, 0, 15,
66, 64, 0, 3, 13, 64, 19, 112, 100, 186, 19, 112, 100, 205, 255, 255, 216, 233, 19, 112, 100, 229, 19, 112, 107, 28,
255, 255, 216, 234, 181, 240, 28, 3, 176, 143, 51, 160, 145, 7, 104, 30, 33, 128, 70, 111, 1, 9, 55, 55, 37, 0, 172,
9, 24, 118, 144, 6, 112, 61, 28, 32, 33, 0, 34, 16, 240, 2, 251, 218, 46, 0, 208, 87, 35, 6, 147, 1, 35, 1, 147, 2,
35, 10, 147, 5, 153, 7, 35, 0, 152, 6, 34, 0, 149, 4, 148, 0, 151, 3, 247, 255, 254, 131, 28, 5, 28, 41, 72, 40, 247,
254, 252, 216, 28, 107, 208, 69, 45, 0, 219, 2, 120, 59, 43, 0, 208, 64, 153, 7, 171, 9, 34, 3, 112, 26, 1, 74, 112,
90, 34, 18, 113, 26, 34, 0, 113, 90, 28, 48, 33, 0, 34, 18, 240, 2, 251, 174, 75, 28, 53, 2, 209, 1, 74, 28, 224, 0,
74, 28, 96, 26, 171, 9, 147, 0, 35, 6, 147, 1, 35, 0, 147, 2, 147, 3, 147, 4, 35, 10, 147, 5, 153, 7, 152, 6, 28, 50,
35, 18, 247, 255, 254, 81, 28, 5, 28, 41, 72, 19, 247, 254, 252, 166, 45, 0, 219, 19, 120, 179, 33, 15, 70, 108, 64,
25, 52, 55, 72, 15, 112, 33, 247, 254, 252, 155, 120, 35, 59, 2, 6, 27, 14, 27, 43, 2, 217, 3, 224, 3, 37, 4, 66, 109,
224, 0, 77, 9, 176, 15, 28, 40, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 100, 244, 19, 112, 96, 56, 0, 38, 37, 160,
0, 152, 150, 128, 19, 112, 101, 21, 19, 112, 101, 52, 255, 255, 216, 239, 181, 240, 176, 147, 70, 106, 35, 0, 50, 71,
112, 19, 74, 197, 28, 4, 32, 16, 112, 16, 72, 196, 28, 34, 50, 152, 96, 16, 174, 12, 58, 8, 96, 17, 28, 8, 130, 115,
28, 49, 130, 179, 247, 255, 249, 179, 28, 5, 28, 41, 72, 190, 247, 254, 252, 96, 45, 0, 218, 0, 225, 195, 75, 188, 104,
27, 43, 0, 208, 37, 75, 187, 121, 50, 121, 153, 66, 145, 209, 23, 121, 217, 121, 114, 66, 145, 209, 19, 137, 25, 137,
50, 66, 145, 209, 15, 137, 89, 137, 114, 66, 145, 209, 11, 123, 25, 123, 178, 66, 145, 209, 7, 123, 89, 123, 242, 66,
145, 209, 3, 123, 154, 124, 51, 66, 154, 208, 8, 168, 12, 247, 254, 251, 12, 37, 1, 72, 171, 247, 254, 252, 53, 66,
109, 225, 167, 170, 12, 121, 17, 75, 167, 38, 0, 113, 153, 121, 81, 113, 217, 137, 17, 129, 25, 137, 81, 129, 89, 123,
145, 115, 25, 123, 209, 115, 89, 124, 18, 115, 154, 74, 161, 35, 128, 66, 91, 96, 19, 35, 0, 147, 10, 147, 5, 224, 221,
138, 111, 138, 171, 154, 10, 4, 63, 67, 31, 24, 191, 122, 58, 72, 155, 0, 82, 153, 5, 247, 254, 252, 14, 34, 156, 35,
0, 25, 18, 147, 9, 147, 6, 146, 11, 224, 191, 122, 123, 122, 189, 6, 27, 4, 45, 67, 29, 122, 251, 2, 27, 67, 29, 123,
59, 67, 29, 155, 9, 24, 237, 121, 107, 43, 8, 209, 115, 121, 235, 43, 80, 209, 112, 121, 43, 43, 1, 217, 109, 154, 11,
35, 1, 112, 19, 121, 169, 72, 137, 34, 1, 247, 254, 251, 234, 35, 0, 115, 102, 115, 38, 147, 8, 147, 7, 224, 49, 123,
170, 123, 235, 6, 18, 4, 27, 67, 19, 124, 42, 2, 18, 67, 19, 124, 106, 67, 19, 154, 8, 24, 155, 120, 218, 42, 2, 209,
28, 120, 154, 6, 17, 41, 0, 218, 11, 123, 33, 41, 0, 209, 8, 42, 0, 208, 6, 115, 34, 121, 25, 121, 91, 2, 9, 67, 25,
72, 119, 224, 10, 123, 97, 41, 0, 209, 9, 42, 0, 208, 7, 115, 98, 121, 25, 121, 91, 2, 9, 72, 114, 67, 25, 247, 254,
251, 184, 155, 7, 154, 8, 51, 1, 50, 7, 147, 7, 146, 8, 121, 43, 154, 7, 66, 154, 211, 201, 123, 33, 41, 0, 208, 93,
123, 98, 42, 0, 208, 90, 72, 105, 247, 254, 251, 165, 75, 97, 123, 34, 168, 12, 116, 26, 123, 98, 116, 90, 121, 122,
112, 34, 120, 170, 96, 98, 115, 218, 120, 235, 96, 163, 247, 254, 250, 105, 75, 91, 74, 97, 72, 97, 96, 26, 120, 33,
104, 162, 247, 254, 251, 142, 28, 35, 51, 144, 70, 105, 104, 24, 49, 71, 247, 254, 254, 140, 40, 0, 218, 89, 224, 85,
123, 170, 123, 235, 6, 18, 4, 27, 67, 19, 124, 42, 124, 104, 2, 18, 67, 19, 67, 24, 208, 1, 240, 1, 250, 129, 122, 106,
122, 171, 6, 18, 4, 27, 67, 19, 122, 234, 123, 40, 2, 18, 67, 19, 115, 174, 115, 238, 116, 46, 116, 110, 67, 24, 208,
1, 240, 1, 250, 112, 121, 107, 114, 110, 114, 174, 114, 238, 115, 46, 43, 9, 209, 4, 74, 72, 75, 63, 168, 12, 96, 26,
224, 39, 43, 8, 209, 10, 121, 235, 43, 80, 209, 7, 121, 43, 43, 1, 217, 4, 121, 171, 74, 66, 26, 211, 74, 56, 96, 19,
155, 6, 154, 9, 51, 1, 50, 18, 147, 6, 146, 9, 121, 59, 154, 6, 66, 154, 210, 0, 231, 58, 155, 5, 154, 10, 51, 1, 50,
13, 147, 5, 146, 10, 173, 12, 124, 107, 154, 5, 66, 154, 210, 0, 231, 27, 72, 53, 247, 254, 251, 51, 28, 40, 247, 254,
250, 3, 77, 49, 224, 148, 72, 50, 247, 254, 251, 43, 70, 107, 51, 71, 120, 25, 120, 34, 72, 48, 247, 254, 251, 36, 75,
34, 74, 47, 96, 26, 28, 35, 51, 144, 104, 24, 120, 33, 247, 254, 254, 18, 40, 0, 218, 2, 72, 43, 247, 254, 251, 22,
74, 42, 75, 27, 121, 225, 96, 26, 28, 35, 51, 144, 104, 24, 122, 226, 247, 254, 253, 245, 40, 0, 218, 2, 72, 37, 247,
254, 251, 7, 72, 37, 70, 109, 247, 254, 251, 3, 53, 70, 35, 0, 112, 43, 28, 35, 51, 144, 104, 24, 136, 227, 33, 161,
147, 0, 35, 1, 147, 1, 34, 254, 35, 0, 149, 2, 247, 254, 253, 109, 40, 0, 218, 56, 72, 27, 247, 254, 250, 238, 35, 8,
115, 163, 224, 58, 70, 192, 19, 112, 96, 64, 44, 13, 224, 1, 19, 112, 101, 86, 19, 112, 107, 56, 19, 112, 107, 36, 19,
112, 101, 128, 19, 112, 107, 0, 19, 112, 101, 166, 19, 112, 101, 205, 19, 112, 102, 4, 19, 112, 102, 18, 19, 112, 102,
33, 255, 255, 251, 79, 19, 112, 102, 102, 255, 255, 177, 224, 255, 255, 216, 240, 19, 112, 102, 53, 19, 112, 102, 148,
19, 112, 102, 189, 255, 255, 251, 78, 19, 112, 102, 222, 255, 255, 251, 77, 19, 112, 102, 252, 19, 112, 103, 43, 19,
112, 103, 102, 120, 41, 72, 24, 49, 1, 6, 9, 14, 9, 115, 161, 247, 254, 250, 176, 28, 37, 53, 160, 104, 43, 43, 0, 209,
7, 32, 129, 1, 64, 240, 1, 249, 147, 35, 31, 48, 31, 67, 152, 96, 40, 52, 160, 104, 35, 37, 0, 43, 0, 209, 4, 74, 12,
75, 13, 37, 4, 96, 26, 66, 109, 74, 12, 75, 12, 96, 26, 45, 0, 208, 5, 75, 8, 72, 11, 104, 25, 247, 254, 250, 143, 224,
2, 72, 9, 247, 254, 250, 139, 176, 19, 28, 40, 188, 240, 188, 2, 71, 8, 19, 112, 103, 141, 255, 255, 251, 75, 19, 112,
107, 0, 0, 15, 66, 64, 19, 112, 96, 56, 19, 112, 103, 164, 19, 112, 103, 198, 181, 8, 33, 0, 247, 255, 251, 104, 188,
8, 188, 2, 71, 8, 0, 0, 181, 240, 176, 139, 171, 8, 34, 18, 112, 26, 1, 74, 112, 90, 34, 0, 112, 154, 112, 218, 113,
90, 28, 15, 28, 2, 33, 36, 50, 160, 113, 25, 104, 20, 34, 128, 1, 18, 24, 164, 144, 7, 44, 0, 208, 42, 38, 0, 33, 0,
34, 36, 28, 32, 240, 2, 249, 63, 171, 8, 34, 6, 147, 0, 35, 10, 37, 0, 146, 1, 147, 5, 152, 7, 28, 57, 28, 34, 35, 36,
149, 2, 149, 3, 149, 4, 247, 255, 251, 233, 40, 0, 219, 7, 120, 35, 34, 31, 64, 19, 43, 5, 208, 6, 43, 7, 209, 8, 224,
3, 54, 1, 46, 2, 208, 9, 231, 220, 75, 6, 34, 1, 96, 26, 224, 4, 75, 4, 96, 29, 224, 1, 32, 4, 66, 64, 176, 11, 188,
240, 188, 2, 71, 8, 19, 112, 107, 12, 181, 112, 176, 136, 28, 22, 28, 29, 34, 37, 171, 7, 112, 26, 1, 74, 112, 90, 28,
2, 50, 160, 104, 20, 34, 128, 1, 18, 24, 164, 44, 0, 208, 42, 147, 0, 35, 2, 147, 1, 35, 0, 147, 2, 147, 3, 147, 4,
35, 10, 147, 5, 28, 34, 35, 8, 247, 255, 251, 174, 40, 0, 219, 29, 168, 6, 28, 33, 34, 4, 240, 2, 248, 171, 45, 0, 208,
1, 155, 6, 96, 43, 29, 33, 168, 6, 34, 4, 240, 2, 248, 162, 46, 0, 208, 1, 155, 6, 96, 51, 35, 128, 154, 6, 1, 27, 32,
0, 66, 154, 209, 5, 75, 4, 34, 1, 96, 26, 224, 1, 32, 4, 66, 64, 176, 8, 188, 112, 188, 2, 71, 8, 19, 112, 107, 12,
181, 240, 176, 131, 123, 131, 28, 15, 28, 5, 66, 187, 217, 72, 78, 40, 73, 40, 72, 41, 96, 49, 33, 0, 247, 254, 249,
212, 75, 39, 28, 40, 96, 51, 28, 57, 247, 255, 252, 204, 30, 4, 219, 53, 74, 33, 28, 57, 96, 50, 28, 40, 247, 255, 255,
86, 28, 4, 28, 33, 72, 32, 247, 254, 249, 193, 44, 0, 219, 40, 28, 43, 51, 160, 104, 26, 35, 128, 1, 27, 92, 211, 33,
31, 64, 25, 72, 27, 247, 254, 249, 180, 28, 59, 29, 62, 51, 20, 0, 182, 0, 155, 25, 170, 147, 1, 28, 57, 24, 235, 28,
40, 247, 255, 255, 130, 153, 1, 28, 4, 89, 75, 89, 114, 72, 18, 28, 33, 247, 254, 249, 160, 89, 114, 75, 17, 66, 154,
217, 3, 154, 1, 89, 83, 43, 9, 216, 1, 36, 33, 66, 100, 74, 6, 75, 5, 96, 26, 224, 1, 36, 3, 66, 100, 176, 3, 28, 32,
188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 96, 56, 0, 15, 66, 64, 19, 112, 103, 231, 1, 49, 45, 0, 19, 112, 104, 2,
19, 112, 104, 22, 19, 112, 104, 43, 0, 0, 1, 255, 181, 240, 176, 141, 175, 9, 37, 40, 112, 61, 1, 77, 112, 125, 14,
21, 112, 189, 70, 110, 12, 21, 36, 0, 112, 253, 113, 122, 10, 21, 54, 47, 10, 26, 112, 52, 113, 61, 113, 188, 113, 250,
114, 59, 114, 124, 123, 130, 66, 138, 217, 28, 29, 10, 0, 146, 88, 18, 146, 7, 42, 0, 208, 22, 77, 15, 34, 1, 96, 42,
154, 7, 151, 0, 67, 83, 34, 10, 146, 1, 34, 6, 146, 5, 154, 18, 148, 2, 150, 3, 148, 4, 247, 255, 250, 240, 96, 44,
40, 0, 221, 7, 120, 51, 43, 0, 209, 3, 224, 3, 32, 3, 66, 64, 224, 0, 72, 3, 176, 13, 188, 240, 188, 2, 71, 8, 70, 192,
19, 112, 107, 28, 255, 255, 216, 234, 181, 240, 176, 141, 147, 7, 1, 75, 175, 9, 37, 42, 70, 156, 112, 61, 35, 8, 70,
101, 67, 43, 112, 123, 14, 21, 155, 7, 112, 189, 70, 110, 12, 21, 36, 0, 112, 253, 113, 122, 10, 21, 54, 47, 10, 26,
112, 52, 113, 61, 113, 188, 113, 250, 114, 59, 114, 124, 123, 130, 66, 138, 217, 32, 29, 10, 0, 146, 88, 18, 70, 148,
69, 164, 208, 26, 77, 17, 35, 1, 96, 43, 155, 7, 151, 0, 70, 98, 67, 90, 70, 148, 34, 1, 146, 2, 34, 6, 146, 5, 39,
10, 154, 18, 70, 99, 151, 1, 150, 3, 148, 4, 247, 255, 250, 162, 96, 44, 40, 0, 221, 7, 120, 51, 43, 0, 209, 3, 224,
3, 32, 3, 66, 64, 224, 0, 72, 3, 176, 13, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 107, 28, 255, 255, 216, 234, 181,
240, 176, 135, 28, 28, 147, 2, 28, 11, 51, 4, 0, 155, 145, 3, 88, 25, 28, 6, 28, 11, 67, 99, 32, 128, 2, 64, 28, 23,
66, 131, 217, 2, 240, 2, 248, 151, 144, 2, 155, 3, 32, 1, 51, 4, 0, 155, 66, 64, 147, 5, 224, 28, 154, 2, 28, 37, 66,
148, 217, 0, 28, 21, 4, 43, 12, 27, 147, 4, 155, 12, 28, 48, 147, 0, 153, 3, 28, 58, 155, 4, 247, 255, 255, 67, 40,
0, 219, 12, 154, 4, 25, 127, 26, 164, 154, 5, 4, 36, 89, 147, 12, 36, 67, 93, 155, 12, 25, 91, 147, 12, 44, 0, 209,
224, 176, 7, 188, 240, 188, 2, 71, 8, 181, 240, 176, 135, 28, 28, 147, 2, 28, 11, 51, 4, 0, 155, 145, 3, 88, 25, 28,
6, 28, 11, 67, 99, 32, 128, 2, 64, 28, 23, 66, 131, 217, 2, 240, 2, 248, 89, 144, 2, 155, 3, 32, 1, 51, 4, 0, 155, 66,
64, 147, 5, 224, 28, 154, 2, 28, 37, 66, 148, 217, 0, 28, 21, 4, 43, 12, 27, 147, 4, 155, 12, 28, 48, 147, 0, 153, 3,
28, 58, 155, 4, 247, 255, 255, 73, 40, 0, 219, 12, 154, 4, 25, 127, 26, 164, 154, 5, 4, 36, 89, 147, 12, 36, 67, 93,
155, 12, 25, 91, 147, 12, 44, 0, 209, 224, 176, 7, 188, 240, 188, 2, 71, 8, 181, 240, 176, 139, 74, 135, 35, 0, 128,
19, 74, 135, 36, 0, 128, 19, 75, 134, 74, 135, 112, 28, 75, 135, 79, 135, 112, 28, 35, 120, 144, 8, 66, 91, 96, 19,
28, 56, 153, 8, 247, 255, 251, 218, 40, 0, 218, 0, 224, 241, 34, 1, 75, 129, 115, 186, 104, 25, 41, 0, 208, 74, 121,
91, 43, 0, 209, 3, 75, 126, 120, 27, 66, 26, 208, 29, 76, 122, 35, 0, 115, 163, 77, 124, 75, 124, 38, 1, 96, 43, 28,
35, 51, 144, 104, 24, 136, 227, 33, 161, 147, 0, 28, 35, 51, 14, 147, 2, 34, 254, 35, 0, 150, 1, 247, 254, 250, 171,
75, 117, 96, 43, 40, 0, 218, 1, 115, 166, 224, 188, 123, 163, 51, 1, 115, 163, 75, 108, 72, 113, 121, 29, 28, 41, 247,
254, 248, 34, 78, 104, 28, 41, 28, 48, 247, 255, 254, 59, 28, 4, 28, 33, 72, 108, 247, 254, 248, 24, 28, 163, 43, 1,
216, 9, 28, 48, 247, 255, 253, 154, 74, 94, 35, 121, 66, 91, 96, 19, 34, 0, 75, 91, 224, 61, 44, 0, 218, 0, 224, 153,
75, 88, 34, 1, 112, 26, 75, 89, 112, 29, 224, 139, 38, 1, 113, 92, 37, 0, 28, 60, 150, 6, 55, 144, 28, 40, 30, 67, 65,
152, 144, 9, 40, 0, 209, 5, 75, 84, 120, 27, 7, 217, 213, 1, 46, 0, 209, 41, 72, 87, 28, 41, 247, 253, 255, 236, 6,
43, 14, 27, 28, 25, 72, 76, 147, 5, 247, 255, 254, 3, 144, 7, 153, 7, 72, 80, 247, 253, 255, 224, 155, 7, 51, 2, 43,
1, 216, 16, 154, 9, 42, 0, 208, 13, 74, 73, 75, 70, 72, 67, 96, 26, 247, 255, 253, 91, 74, 63, 35, 121, 66, 91, 96,
19, 75, 60, 34, 0, 112, 26, 224, 105, 155, 7, 43, 0, 218, 59, 46, 0, 208, 52, 78, 61, 75, 62, 73, 66, 96, 51, 136, 227,
32, 0, 96, 8, 115, 160, 104, 56, 147, 0, 28, 35, 34, 1, 51, 14, 146, 1, 147, 2, 33, 161, 35, 0, 34, 254, 247, 254, 250,
44, 75, 53, 144, 5, 96, 51, 40, 0, 218, 5, 73, 55, 35, 1, 32, 0, 115, 163, 96, 8, 224, 5, 123, 163, 34, 1, 51, 1, 115,
163, 75, 42, 113, 90, 75, 40, 72, 49, 123, 155, 153, 5, 28, 26, 147, 6, 247, 253, 255, 153, 75, 38, 38, 0, 120, 27,
7, 216, 213, 3, 153, 5, 15, 206, 224, 0, 53, 1, 154, 6, 66, 149, 219, 144, 224, 29, 33, 23, 70, 104, 74, 29, 92, 8,
35, 1, 96, 19, 113, 16, 154, 8, 152, 8, 137, 17, 74, 19, 128, 17, 137, 65, 74, 19, 128, 17, 74, 19, 70, 105, 112, 19,
34, 23, 75, 19, 92, 81, 112, 25, 74, 23, 75, 21, 32, 0, 96, 26, 75, 14, 34, 0, 96, 26, 224, 14, 74, 12, 35, 122, 66,
91, 96, 19, 72, 12, 247, 255, 252, 239, 75, 8, 34, 0, 112, 26, 72, 20, 247, 253, 255, 97, 32, 3, 66, 64, 176, 11, 188,
240, 188, 2, 71, 8, 70, 192, 19, 112, 107, 24, 19, 112, 107, 32, 19, 112, 107, 60, 19, 112, 107, 0, 19, 112, 96, 64,
19, 114, 197, 128, 19, 112, 107, 36, 19, 112, 1, 14, 19, 112, 96, 56, 0, 152, 150, 128, 0, 15, 66, 64, 19, 112, 104,
98, 19, 112, 104, 128, 19, 112, 104, 103, 19, 112, 107, 84, 19, 112, 104, 157, 19, 112, 104, 198, 181, 8, 74, 10, 104,
19, 43, 0, 208, 13, 75, 9, 33, 16, 112, 25, 35, 0, 73, 8, 96, 19, 74, 8, 112, 11, 96, 19, 72, 7, 33, 0, 34, 20, 240,
1, 254, 17, 188, 8, 188, 1, 71, 0, 19, 112, 107, 56, 19, 112, 96, 64, 19, 112, 107, 60, 19, 112, 107, 84, 19, 112, 107,
36, 181, 240, 176, 135, 75, 120, 36, 0, 104, 29, 45, 0, 208, 0, 224, 229, 75, 118, 32, 0, 104, 27, 104, 155, 96, 157,
247, 253, 248, 99, 74, 116, 35, 100, 66, 91, 96, 19, 74, 115, 35, 1, 96, 19, 74, 114, 72, 115, 112, 21, 74, 115, 112,
19, 247, 253, 254, 251, 75, 114, 120, 27, 43, 1, 208, 4, 43, 2, 208, 6, 34, 0, 146, 4, 224, 6, 35, 1, 147, 4, 36, 1,
224, 2, 34, 1, 146, 4, 36, 0, 0, 167, 224, 176, 75, 99, 74, 105, 104, 29, 0, 163, 25, 27, 0, 219, 24, 235, 103, 92,
111, 27, 96, 20, 43, 0, 209, 54, 104, 171, 34, 1, 51, 68, 25, 219, 104, 27, 66, 26, 209, 2, 28, 32, 247, 253, 252, 223,
78, 88, 34, 1, 104, 51, 104, 155, 51, 68, 25, 219, 104, 27, 66, 26, 208, 35, 28, 32, 247, 254, 251, 253, 35, 140, 0,
219, 24, 192, 40, 1, 216, 4, 35, 100, 74, 80, 66, 91, 96, 19, 224, 130, 28, 32, 247, 254, 250, 140, 144, 3, 32, 20,
247, 253, 249, 176, 104, 51, 104, 155, 51, 68, 25, 219, 104, 26, 155, 3, 43, 0, 219, 4, 75, 77, 64, 26, 75, 77, 66,
154, 208, 2, 28, 32, 247, 254, 251, 220, 0, 160, 25, 0, 0, 192, 24, 43, 111, 27, 43, 0, 208, 100, 75, 64, 34, 1, 48,
88, 96, 26, 24, 40, 247, 255, 254, 44, 144, 3, 40, 0, 209, 87, 75, 56, 34, 1, 96, 26, 79, 65, 74, 57, 96, 16, 28, 56,
247, 252, 255, 230, 77, 52, 34, 4, 104, 43, 72, 62, 104, 155, 96, 154, 247, 253, 254, 132, 32, 100, 247, 253, 249, 123,
32, 128, 1, 0, 240, 0, 253, 105, 78, 57, 75, 57, 34, 1, 96, 51, 75, 57, 144, 4, 112, 26, 104, 43, 154, 3, 104, 155,
32, 0, 96, 154, 247, 252, 255, 201, 72, 53, 247, 253, 254, 108, 75, 52, 34, 0, 120, 25, 155, 4, 72, 51, 147, 0, 35,
1, 247, 255, 253, 123, 144, 5, 28, 56, 247, 252, 255, 185, 104, 43, 34, 4, 104, 155, 96, 154, 70, 107, 34, 15, 92, 210,
75, 40, 152, 4, 112, 26, 75, 43, 96, 51, 240, 0, 253, 91, 155, 5, 43, 0, 218, 7, 72, 40, 247, 253, 254, 75, 28, 32,
247, 253, 252, 132, 76, 38, 224, 27, 72, 38, 247, 253, 254, 67, 75, 38, 104, 27, 43, 0, 208, 20, 52, 2, 224, 18, 28,
32, 247, 253, 252, 118, 52, 1, 55, 4, 154, 4, 66, 148, 220, 0, 231, 74, 72, 18, 247, 252, 255, 139, 74, 7, 104, 19,
34, 4, 104, 155, 96, 154, 75, 5, 104, 28, 176, 7, 28, 32, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 107, 56, 19, 112,
96, 60, 19, 112, 107, 0, 19, 112, 107, 84, 19, 112, 107, 60, 19, 112, 104, 227, 19, 112, 1, 15, 19, 112, 1, 12, 19,
112, 107, 80, 0, 0, 57, 5, 0, 0, 16, 5, 19, 112, 17, 29, 19, 112, 105, 118, 19, 112, 96, 56, 0, 152, 150, 128, 19, 112,
106, 248, 19, 112, 105, 167, 19, 112, 96, 64, 19, 114, 197, 128, 0, 15, 66, 64, 19, 112, 105, 140, 255, 255, 251, 162,
19, 112, 105, 164, 19, 112, 107, 12, 181, 0, 30, 3, 208, 1, 34, 0, 96, 26, 74, 12, 32, 0, 120, 18, 42, 1, 209, 16, 74,
10, 120, 18, 42, 16, 208, 12, 43, 0, 208, 4, 50, 4, 73, 8, 0, 146, 88, 82, 96, 26, 75, 5, 120, 26, 75, 5, 50, 20, 0,
146, 88, 208, 188, 2, 71, 8, 70, 192, 19, 112, 107, 60, 19, 112, 96, 64, 19, 114, 197, 128, 181, 240, 176, 139, 75,
78, 104, 27, 43, 0, 209, 0, 224, 139, 75, 77, 34, 16, 112, 26, 75, 76, 120, 26, 75, 76, 42, 0, 208, 1, 74, 76, 224,
0, 74, 76, 78, 76, 96, 26, 172, 4, 35, 0, 28, 53, 130, 99, 130, 163, 53, 144, 28, 33, 104, 40, 247, 254, 251, 0, 75,
71, 121, 34, 121, 153, 66, 145, 209, 23, 121, 217, 121, 98, 66, 145, 209, 19, 137, 25, 137, 34, 66, 145, 209, 15, 137,
89, 137, 98, 66, 145, 209, 11, 123, 25, 123, 162, 66, 145, 209, 7, 123, 89, 123, 226, 66, 145, 209, 3, 123, 154, 124,
35, 66, 154, 208, 6, 168, 4, 247, 253, 252, 101, 72, 56, 247, 253, 253, 143, 224, 80, 28, 32, 247, 253, 252, 94, 74,
54, 75, 47, 104, 40, 96, 26, 120, 49, 247, 254, 248, 123, 40, 0, 219, 70, 104, 178, 42, 0, 208, 7, 6, 18, 104, 40, 121,
241, 14, 18, 247, 254, 248, 98, 40, 0, 219, 61, 76, 41, 35, 0, 115, 163, 77, 36, 75, 42, 39, 1, 96, 43, 28, 35, 51,
144, 104, 24, 136, 227, 33, 161, 147, 0, 28, 35, 51, 14, 147, 2, 34, 254, 35, 0, 151, 1, 247, 253, 255, 220, 75, 28,
96, 43, 40, 0, 218, 6, 115, 167, 28, 32, 33, 0, 247, 254, 254, 77, 72, 30, 224, 34, 123, 163, 78, 25, 51, 1, 115, 163,
75, 28, 28, 32, 96, 43, 121, 49, 247, 255, 248, 75, 75, 18, 96, 43, 40, 0, 219, 17, 121, 49, 28, 32, 247, 255, 250,
213, 40, 0, 219, 13, 121, 50, 75, 9, 112, 26, 75, 19, 112, 31, 224, 8, 72, 19, 224, 6, 72, 19, 224, 4, 72, 19, 224,
2, 72, 19, 224, 0, 72, 19, 176, 11, 188, 240, 188, 2, 71, 8, 19, 112, 107, 56, 19, 112, 96, 64, 19, 112, 1, 15, 19,
112, 96, 56, 0, 15, 66, 64, 0, 3, 13, 64, 19, 114, 197, 128, 19, 112, 107, 36, 19, 112, 101, 128, 0, 152, 150, 128,
255, 255, 252, 20, 1, 49, 45, 0, 19, 112, 107, 60, 255, 255, 252, 15, 255, 255, 252, 23, 255, 255, 252, 22, 255, 255,
252, 19, 255, 255, 252, 18, 181, 240, 176, 131, 75, 57, 76, 58, 120, 26, 38, 1, 30, 83, 65, 154, 75, 56, 96, 34, 104,
27, 43, 0, 208, 99, 75, 55, 0, 146, 104, 27, 104, 155, 28, 25, 49, 68, 24, 138, 104, 18, 66, 22, 208, 89, 34, 0, 32,
0, 96, 154, 247, 252, 254, 74, 104, 32, 247, 254, 248, 191, 30, 7, 218, 3, 104, 32, 247, 254, 248, 186, 28, 7, 32, 60,
247, 252, 255, 222, 77, 41, 72, 42, 104, 43, 28, 57, 104, 154, 75, 37, 50, 68, 104, 27, 38, 1, 0, 155, 24, 211, 104,
27, 28, 26, 147, 1, 247, 253, 252, 212, 76, 32, 35, 1, 96, 35, 47, 0, 219, 48, 155, 1, 74, 32, 64, 26, 75, 32, 66, 154,
209, 42, 74, 32, 35, 0, 112, 19, 34, 0, 96, 34, 247, 255, 254, 242, 74, 29, 75, 30, 96, 26, 40, 0, 219, 12, 74, 26,
35, 0, 112, 22, 96, 35, 72, 27, 247, 252, 254, 16, 104, 43, 34, 4, 104, 155, 38, 0, 96, 154, 224, 17, 28, 57, 72, 23,
96, 38, 247, 253, 252, 171, 75, 17, 34, 0, 112, 26, 32, 100, 247, 252, 255, 159, 72, 17, 247, 252, 253, 252, 104, 43,
34, 4, 104, 155, 96, 154, 32, 100, 247, 252, 255, 149, 176, 3, 28, 48, 188, 240, 188, 2, 71, 8, 19, 112, 1, 12, 19,
112, 107, 80, 19, 112, 107, 84, 19, 112, 96, 60, 19, 112, 105, 185, 0, 0, 49, 5, 0, 0, 16, 5, 19, 112, 107, 60, 0, 15,
66, 64, 19, 112, 96, 56, 19, 112, 17, 29, 19, 112, 105, 213, 181, 240, 176, 131, 75, 30, 34, 0, 104, 27, 146, 1, 43,
0, 208, 50, 247, 255, 255, 104, 75, 27, 104, 27, 43, 0, 209, 44, 75, 26, 120, 27, 43, 0, 208, 40, 77, 25, 79, 26, 76,
26, 78, 27, 96, 47, 121, 49, 28, 32, 247, 255, 249, 243, 40, 0, 219, 29, 96, 47, 121, 49, 28, 32, 28, 11, 29, 10, 51,
20, 0, 146, 0, 155, 25, 18, 25, 27, 247, 255, 250, 47, 40, 0, 219, 15, 75, 17, 104, 26, 42, 0, 208, 7, 121, 49, 35,
128, 49, 4, 0, 137, 89, 9, 1, 27, 66, 153, 209, 3, 28, 19, 30, 90, 65, 147, 147, 1, 152, 1, 176, 3, 188, 240, 188, 2,
71, 8, 19, 112, 107, 56, 19, 112, 107, 84, 19, 112, 107, 60, 19, 112, 96, 56, 0, 15, 66, 64, 19, 114, 197, 128, 19,
112, 107, 36, 19, 112, 107, 12, 181, 240, 176, 135, 75, 66, 144, 3, 104, 27, 146, 4, 43, 0, 209, 7, 75, 64, 104, 27,
43, 0, 208, 3, 0, 66, 75, 63, 8, 82, 96, 26, 75, 62, 104, 27, 43, 0, 208, 6, 75, 61, 104, 26, 42, 1, 221, 2, 34, 1,
96, 26, 224, 101, 4, 9, 12, 9, 79, 56, 38, 4, 36, 0, 145, 5, 247, 255, 254, 255, 30, 67, 65, 152, 104, 59, 66, 64, 64,
4, 43, 0, 208, 3, 74, 50, 104, 19, 43, 3, 208, 79, 44, 0, 219, 3, 75, 48, 120, 27, 43, 1, 208, 4, 75, 45, 34, 1, 36,
1, 96, 26, 66, 100, 75, 43, 104, 27, 43, 0, 209, 61, 75, 38, 104, 26, 75, 42, 42, 0, 208, 1, 74, 41, 224, 0, 74, 41,
96, 26, 28, 99, 208, 24, 32, 0, 247, 252, 253, 61, 77, 39, 34, 0, 104, 43, 72, 38, 104, 155, 96, 154, 154, 4, 75, 37,
120, 25, 155, 5, 146, 0, 154, 3, 247, 255, 250, 237, 28, 4, 72, 34, 247, 252, 253, 43, 104, 43, 34, 4, 104, 155, 96,
154, 74, 32, 75, 24, 96, 26, 44, 0, 218, 2, 75, 20, 34, 1, 96, 26, 75, 18, 104, 27, 43, 0, 208, 3, 75, 17, 104, 27,
43, 0, 209, 15, 75, 15, 104, 27, 43, 0, 209, 5, 75, 14, 120, 27, 43, 1, 209, 1, 44, 0, 218, 7, 62, 1, 46, 0, 209, 162,
67, 228, 15, 224, 224, 2, 32, 0, 224, 0, 32, 1, 176, 7, 188, 240, 188, 2, 71, 8, 19, 112, 106, 240, 19, 112, 107, 12,
19, 112, 106, 192, 19, 112, 106, 196, 19, 112, 107, 84, 19, 112, 107, 60, 19, 112, 96, 56, 0, 152, 150, 128, 0, 45,
198, 192, 19, 112, 96, 60, 19, 114, 197, 128, 19, 112, 96, 64, 19, 112, 17, 29, 0, 15, 66, 64, 181, 240, 176, 133, 75,
39, 28, 7, 104, 27, 28, 22, 32, 0, 43, 0, 209, 67, 4, 9, 12, 9, 36, 0, 145, 3, 247, 255, 254, 111, 40, 0, 208, 2, 44,
0, 219, 5, 224, 0, 36, 0, 74, 31, 120, 19, 43, 1, 208, 4, 75, 30, 34, 1, 36, 1, 96, 26, 66, 100, 75, 27, 104, 27, 43,
0, 209, 234, 73, 26, 74, 27, 96, 17, 28, 98, 208, 22, 77, 26, 32, 0, 104, 42, 104, 146, 96, 147, 247, 252, 252, 182,
75, 23, 28, 58, 120, 25, 72, 23, 155, 3, 150, 0, 247, 255, 250, 170, 28, 4, 72, 21, 247, 252, 252, 170, 104, 43, 34,
4, 104, 155, 96, 154, 74, 18, 75, 13, 96, 26, 44, 0, 218, 2, 75, 9, 34, 1, 96, 26, 75, 7, 104, 27, 43, 0, 209, 194,
44, 0, 219, 192, 32, 1, 176, 5, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 107, 12, 19, 112, 107, 60, 19, 112, 107,
84, 0, 45, 198, 192, 19, 112, 96, 56, 19, 112, 96, 60, 19, 112, 96, 64, 19, 114, 197, 128, 19, 112, 17, 29, 0, 15, 66,
64, 181, 240, 176, 137, 74, 95, 104, 19, 43, 0, 209, 6, 75, 94, 104, 27, 105, 153, 96, 17, 106, 26, 75, 93, 96, 26,
75, 92, 77, 90, 104, 28, 38, 0, 28, 55, 104, 43, 55, 8, 0, 191, 80, 252, 28, 32, 33, 0, 34, 96, 240, 1, 249, 245, 104,
43, 33, 96, 88, 248, 240, 0, 249, 214, 52, 127, 33, 31, 54, 1, 67, 140, 46, 8, 209, 234, 37, 8, 38, 31, 28, 32, 33,
0, 34, 96, 240, 1, 249, 227, 61, 1, 28, 32, 33, 96, 52, 127, 240, 0, 249, 195, 67, 180, 45, 0, 209, 241, 75, 72, 34,
255, 96, 28, 75, 68, 39, 128, 104, 29, 35, 255, 2, 18, 4, 27, 76, 69, 38, 0, 5, 255, 146, 2, 147, 3, 33, 0, 96, 37,
34, 96, 28, 40, 240, 1, 249, 198, 28, 40, 240, 0, 249, 152, 28, 50, 100, 104, 104, 35, 30, 81, 65, 138, 5, 210, 96,
90, 104, 35, 34, 0, 96, 154, 104, 35, 33, 31, 97, 159, 53, 127, 67, 141, 104, 34, 28, 40, 146, 5, 240, 0, 249, 132,
144, 6, 28, 40, 240, 0, 249, 128, 144, 1, 28, 40, 240, 0, 249, 124, 144, 7, 28, 40, 240, 0, 249, 120, 35, 255, 2, 27,
153, 2, 147, 4, 34, 255, 155, 1, 4, 18, 64, 11, 146, 1, 153, 3, 154, 7, 2, 27, 64, 10, 10, 18, 67, 19, 14, 0, 154, 6,
67, 3, 32, 224, 64, 16, 33, 2, 67, 8, 154, 5, 6, 0, 67, 3, 96, 19, 104, 34, 35, 128, 4, 91, 97, 19, 104, 34, 33, 96,
97, 83, 204, 1, 54, 1, 240, 0, 249, 100, 46, 6, 209, 175, 76, 22, 77, 26, 104, 32, 105, 110, 240, 0, 249, 75, 144, 2,
104, 32, 240, 0, 249, 71, 28, 7, 104, 32, 240, 0, 249, 67, 144, 3, 104, 32, 240, 0, 249, 63, 155, 4, 153, 1, 64, 31,
155, 3, 2, 63, 64, 11, 10, 27, 67, 31, 154, 2, 14, 3, 28, 56, 67, 24, 35, 224, 64, 19, 33, 2, 67, 11, 6, 27, 67, 24,
96, 48, 105, 104, 33, 96, 240, 0, 249, 57, 176, 9, 188, 240, 188, 1, 71, 0, 70, 192, 19, 112, 107, 76, 19, 112, 96,
60, 19, 112, 106, 236, 19, 112, 107, 8, 19, 114, 195, 160, 181, 248, 75, 16, 39, 128, 104, 28, 38, 0, 4, 127, 28, 32,
247, 252, 253, 241, 46, 3, 208, 15, 28, 37, 35, 31, 53, 127, 67, 157, 107, 104, 240, 1, 248, 182, 96, 103, 96, 32, 33,
96, 28, 32, 240, 0, 249, 18, 54, 1, 28, 44, 231, 234, 28, 32, 33, 96, 240, 0, 249, 11, 188, 248, 188, 1, 71, 0, 19,
112, 107, 8, 181, 240, 176, 131, 247, 255, 255, 12, 247, 255, 255, 214, 76, 65, 75, 66, 104, 34, 104, 24, 77, 65, 97,
144, 104, 89, 78, 65, 97, 209, 104, 154, 79, 64, 96, 42, 104, 218, 105, 27, 96, 50, 96, 59, 33, 96, 240, 0, 249, 1,
104, 35, 33, 0, 105, 154, 100, 211, 105, 154, 100, 145, 105, 155, 28, 24, 147, 1, 240, 0, 248, 209, 155, 1, 104, 34,
100, 88, 104, 59, 105, 145, 108, 91, 34, 255, 2, 18, 64, 26, 2, 16, 34, 255, 4, 18, 64, 26, 10, 18, 67, 2, 14, 24, 67,
2, 32, 224, 64, 3, 39, 2, 67, 59, 6, 24, 28, 19, 67, 3, 96, 11, 104, 35, 34, 128, 105, 153, 4, 18, 96, 74, 105, 154,
33, 0, 96, 145, 105, 153, 34, 128, 5, 210, 97, 138, 105, 153, 34, 128, 4, 82, 97, 10, 105, 153, 97, 74, 105, 152, 33,
96, 240, 0, 248, 179, 104, 35, 33, 96, 105, 216, 240, 0, 248, 194, 104, 35, 33, 0, 105, 218, 100, 211, 105, 218, 100,
145, 105, 223, 28, 56, 240, 0, 248, 147, 33, 96, 100, 120, 104, 40, 240, 0, 248, 179, 104, 47, 104, 35, 28, 56, 100,
251, 35, 0, 100, 187, 240, 0, 248, 134, 33, 96, 100, 120, 104, 40, 240, 0, 248, 146, 104, 48, 33, 96, 240, 0, 248, 162,
104, 53, 104, 35, 33, 0, 100, 235, 100, 169, 28, 40, 240, 0, 248, 117, 33, 96, 100, 104, 104, 48, 240, 0, 248, 129,
176, 3, 188, 240, 188, 1, 71, 0, 70, 192, 19, 112, 96, 60, 19, 114, 195, 160, 19, 112, 106, 244, 19, 112, 107, 72, 19,
112, 107, 68, 181, 248, 76, 35, 75, 35, 96, 35, 240, 0, 248, 74, 40, 0, 219, 58, 240, 0, 249, 117, 74, 32, 104, 131,
96, 32, 96, 26, 104, 32, 35, 1, 104, 130, 104, 17, 66, 11, 209, 252, 33, 252, 240, 0, 248, 91, 38, 128, 39, 128, 76,
23, 37, 0, 4, 118, 1, 127, 104, 35, 33, 4, 108, 219, 81, 94, 104, 35, 108, 219, 89, 88, 53, 4, 240, 0, 248, 75, 66,
189, 209, 243, 247, 255, 255, 65, 104, 35, 34, 2, 51, 84, 112, 26, 247, 252, 255, 185, 104, 35, 32, 0, 104, 154, 105,
155, 108, 91, 97, 147, 104, 35, 34, 4, 104, 155, 96, 154, 104, 35, 74, 8, 104, 155, 96, 26, 104, 35, 104, 155, 104,
27, 224, 1, 32, 1, 66, 64, 188, 248, 188, 2, 71, 8, 19, 112, 96, 60, 19, 114, 198, 36, 0, 1, 0, 32, 0, 1, 0, 33, 181,
8, 33, 224, 72, 4, 2, 9, 240, 1, 249, 66, 75, 3, 96, 24, 23, 192, 188, 8, 188, 2, 71, 8, 19, 112, 163, 128, 19, 112,
96, 68, 71, 112, 71, 112, 181, 16, 28, 4, 240, 1, 249, 62, 28, 32, 188, 16, 188, 2, 71, 8, 181, 16, 28, 4, 240, 1, 249,
54, 28, 32, 188, 16, 188, 2, 71, 8, 181, 16, 28, 4, 240, 1, 249, 46, 28, 32, 188, 16, 188, 2, 71, 8, 181, 8, 240, 1,
249, 71, 188, 8, 188, 1, 71, 0, 181, 8, 240, 1, 249, 65, 188, 8, 188, 1, 71, 0, 181, 8, 240, 1, 249, 59, 188, 8, 188,
1, 71, 0, 181, 8, 75, 12, 28, 1, 34, 32, 104, 24, 240, 1, 249, 45, 40, 0, 209, 13, 72, 9, 240, 1, 249, 4, 240, 0, 249,
63, 32, 200, 247, 252, 251, 253, 240, 0, 249, 68, 32, 200, 247, 252, 251, 248, 231, 244, 188, 8, 188, 2, 71, 8, 19,
112, 96, 68, 19, 112, 105, 237, 181, 8, 75, 4, 28, 1, 104, 24, 240, 1, 248, 216, 188, 8, 188, 1, 71, 0, 70, 192, 19,
112, 96, 68, 181, 248, 76, 13, 28, 15, 104, 33, 28, 30, 28, 24, 28, 21, 67, 81, 240, 1, 248, 228, 28, 56, 28, 41, 28,
50, 247, 255, 252, 173, 35, 1, 40, 0, 208, 5, 104, 33, 28, 48, 67, 105, 240, 1, 248, 247, 35, 0, 28, 24, 188, 248, 188,
2, 71, 8, 19, 114, 199, 32, 181, 16, 76, 11, 104, 32, 40, 0, 208, 3, 240, 0, 252, 39, 35, 0, 96, 35, 76, 8, 104, 35,
43, 0, 209, 3, 72, 7, 247, 251, 252, 132, 96, 32, 74, 6, 35, 1, 66, 91, 96, 19, 188, 16, 188, 1, 71, 0, 19, 112, 107,
96, 19, 112, 107, 88, 0, 0, 128, 32, 19, 112, 96, 24, 181, 56, 75, 14, 104, 24, 40, 0, 208, 1, 247, 251, 252, 139, 76,
12, 75, 10, 104, 32, 37, 0, 96, 29, 40, 0, 208, 2, 240, 0, 251, 254, 96, 37, 75, 8, 104, 24, 40, 0, 208, 1, 240, 0,
251, 91, 75, 5, 34, 0, 96, 26, 188, 56, 188, 1, 71, 0, 70, 192, 19, 112, 107, 88, 19, 112, 107, 96, 19, 112, 107, 92,
181, 240, 176, 135, 75, 37, 28, 7, 104, 24, 145, 5, 40, 0, 208, 1, 247, 251, 252, 100, 75, 33, 77, 34, 34, 0, 96, 26,
104, 43, 43, 0, 209, 23, 247, 255, 249, 93, 78, 31, 36, 0, 28, 48, 247, 255, 250, 124, 75, 29, 96, 24, 40, 0, 208, 43,
154, 5, 104, 51, 33, 0, 144, 0, 146, 1, 72, 26, 34, 0, 148, 2, 240, 0, 249, 238, 96, 40, 40, 0, 208, 30, 77, 23, 104,
44, 44, 0, 208, 11, 72, 22, 28, 57, 34, 6, 240, 0, 254, 210, 40, 0, 208, 19, 28, 32, 240, 0, 251, 179, 35, 0, 96, 43,
75, 11, 28, 57, 104, 24, 240, 0, 251, 54, 75, 12, 28, 4, 96, 24, 40, 0, 208, 4, 72, 11, 28, 57, 34, 6, 240, 0, 254,
234, 176, 7, 28, 32, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 107, 88, 19, 112, 107, 92, 19, 114, 199, 32, 19, 114,
199, 36, 19, 112, 72, 161, 19, 112, 107, 96, 19, 112, 96, 72, 181, 8, 28, 3, 28, 10, 32, 0, 28, 25, 35, 0, 240, 1, 248,
56, 188, 8, 188, 1, 71, 0, 181, 8, 32, 1, 33, 0, 34, 0, 35, 0, 240, 1, 248, 46, 188, 8, 188, 2, 71, 8, 181, 8, 32, 17,
33, 0, 34, 0, 35, 0, 240, 1, 248, 36, 188, 8, 188, 2, 71, 8, 181, 8, 32, 18, 33, 0, 34, 0, 35, 0, 240, 1, 248, 26, 188,
8, 188, 2, 71, 8, 181, 56, 28, 5, 28, 12, 30, 19, 221, 4, 32, 2, 28, 41, 28, 34, 240, 1, 248, 13, 188, 56, 188, 1, 71,
0, 181, 56, 28, 5, 28, 12, 30, 19, 221, 4, 32, 9, 28, 41, 28, 34, 240, 1, 248, 0, 188, 56, 188, 1, 71, 0, 181, 8, 28,
3, 28, 10, 32, 5, 28, 25, 35, 0, 240, 0, 255, 245, 188, 8, 188, 1, 71, 0, 181, 8, 28, 3, 28, 10, 32, 6, 28, 25, 35,
0, 240, 0, 255, 234, 188, 8, 188, 1, 71, 0, 181, 56, 28, 5, 28, 12, 28, 19, 28, 41, 28, 34, 32, 16, 240, 0, 255, 222,
188, 56, 188, 2, 71, 8, 181, 8, 32, 128, 33, 0, 34, 0, 35, 0, 240, 0, 255, 212, 188, 8, 188, 1, 71, 0, 181, 8, 32, 129,
33, 0, 34, 0, 35, 0, 240, 0, 255, 202, 188, 8, 188, 1, 71, 0, 181, 0, 35, 0, 224, 3, 51, 1, 6, 27, 14, 27, 8, 64, 40,
0, 209, 249, 30, 88, 6, 0, 14, 0, 188, 2, 71, 8, 0, 0, 181, 240, 176, 133, 144, 1, 32, 84, 145, 3, 146, 2, 28, 30, 159,
11, 247, 251, 251, 98, 28, 4, 30, 48, 209, 1, 32, 128, 0, 128, 247, 251, 251, 91, 28, 5, 32, 128, 2, 0, 97, 32, 247,
255, 255, 218, 75, 125, 117, 32, 97, 227, 154, 10, 75, 124, 96, 37, 96, 30, 11, 211, 67, 115, 97, 163, 155, 12, 98,
231, 43, 0, 208, 50, 33, 0, 28, 50, 28, 40, 240, 0, 254, 102, 35, 87, 112, 43, 35, 66, 112, 107, 35, 70, 112, 171, 35,
83, 112, 235, 28, 48, 247, 255, 255, 188, 114, 40, 159, 10, 73, 111, 14, 59, 113, 43, 12, 59, 113, 107, 10, 59, 113,
171, 113, 239, 105, 162, 35, 6, 66, 138, 217, 16, 73, 106, 35, 7, 66, 138, 217, 12, 73, 105, 35, 8, 66, 138, 217, 8,
73, 104, 35, 9, 66, 138, 217, 4, 75, 103, 66, 147, 65, 155, 66, 91, 51, 10, 125, 34, 24, 155, 114, 107, 224, 6, 28,
57, 152, 2, 34, 1, 28, 43, 159, 1, 240, 0, 248, 207, 120, 43, 120, 106, 6, 27, 4, 18, 67, 26, 120, 171, 2, 27, 67, 26,
120, 235, 67, 26, 75, 91, 66, 154, 208, 4, 72, 90, 240, 0, 255, 49, 72, 90, 224, 40, 75, 90, 104, 27, 66, 95, 65, 95,
46, 0, 208, 12, 47, 0, 208, 10, 28, 48, 247, 255, 255, 117, 122, 43, 66, 131, 208, 4, 72, 81, 240, 0, 255, 30, 72, 82,
224, 21, 154, 10, 42, 0, 208, 31, 47, 0, 208, 29, 121, 42, 121, 107, 6, 18, 4, 27, 67, 19, 121, 170, 159, 10, 2, 18,
67, 19, 121, 234, 67, 19, 66, 187, 208, 16, 72, 69, 240, 0, 255, 7, 72, 72, 240, 0, 255, 4, 72, 71, 240, 0, 255, 1,
28, 32, 247, 251, 250, 232, 28, 40, 247, 251, 250, 229, 36, 0, 224, 100, 122, 46, 39, 1, 28, 58, 64, 178, 96, 98, 122,
43, 28, 22, 147, 0, 114, 35, 121, 42, 121, 107, 6, 18, 4, 27, 67, 19, 121, 170, 121, 232, 2, 18, 67, 19, 67, 24, 105,
33, 96, 224, 240, 0, 254, 168, 67, 112, 97, 160, 122, 107, 125, 34, 64, 159, 98, 99, 26, 155, 105, 226, 64, 216, 64,
218, 4, 18, 12, 18, 4, 51, 12, 27, 133, 98, 50, 128, 4, 1, 133, 32, 0, 82, 30, 88, 24, 130, 66, 91, 64, 26, 155, 3,
28, 37, 53, 72, 99, 99, 12, 201, 155, 0, 98, 39, 128, 42, 26, 127, 154, 1, 64, 223, 99, 34, 100, 39, 154, 2, 159, 12,
99, 162, 47, 0, 209, 1, 100, 103, 224, 11, 30, 112, 24, 65, 66, 112, 64, 8, 247, 251, 250, 125, 141, 34, 100, 96, 8,
210, 33, 255, 240, 0, 253, 155, 28, 35, 51, 72, 136, 25, 108, 32, 122, 35, 56, 1, 65, 25, 240, 0, 254, 104, 4, 2, 104,
96, 12, 18, 28, 3, 59, 12, 135, 162, 66, 154, 217, 0, 135, 163, 247, 251, 250, 99, 35, 0, 100, 224, 101, 35, 176, 5,
28, 32, 188, 240, 188, 2, 71, 8, 70, 192, 0, 4, 96, 144, 19, 112, 107, 108, 0, 63, 255, 255, 0, 127, 255, 255, 0, 255,
255, 255, 1, 255, 255, 255, 3, 255, 255, 255, 87, 66, 70, 83, 19, 112, 106, 12, 19, 112, 106, 24, 19, 112, 107, 104,
19, 112, 106, 34, 19, 112, 106, 63, 19, 112, 105, 116, 71, 56, 70, 192, 181, 240, 176, 165, 144, 9, 28, 24, 146, 10,
147, 11, 145, 15, 247, 251, 250, 51, 35, 1, 74, 140, 77, 141, 66, 91, 96, 19, 104, 43, 28, 4, 43, 0, 209, 3, 152, 11,
247, 251, 250, 39, 96, 40, 75, 136, 152, 11, 33, 0, 96, 24, 34, 1, 152, 10, 28, 35, 157, 9, 240, 0, 249, 24, 40, 0,
208, 0, 224, 246, 35, 255, 0, 91, 92, 227, 43, 85, 209, 28, 51, 171, 51, 255, 92, 227, 43, 170, 209, 23, 28, 224, 73,
125, 34, 4, 240, 0, 253, 138, 40, 0, 208, 16, 77, 123, 28, 32, 48, 54, 28, 41, 34, 3, 240, 0, 253, 129, 40, 0, 208,
7, 28, 32, 48, 82, 28, 41, 34, 3, 240, 0, 253, 121, 40, 0, 209, 5, 168, 20, 33, 0, 34, 64, 240, 0, 253, 22, 224, 6,
28, 33, 49, 191, 49, 255, 168, 20, 34, 64, 240, 0, 252, 204, 175, 32, 151, 5, 32, 228, 39, 1, 66, 127, 0, 64, 38, 0,
173, 20, 144, 14, 151, 8, 122, 235, 122, 47, 122, 105, 122, 170, 147, 7, 120, 32, 120, 99, 6, 0, 4, 27, 67, 24, 120,
163, 2, 27, 67, 24, 120, 227, 67, 24, 75, 97, 66, 152, 208, 3, 121, 40, 40, 0, 209, 0, 224, 162, 2, 9, 4, 18, 67, 17,
67, 57, 159, 7, 6, 59, 67, 25, 145, 7, 121, 43, 43, 15, 209, 101, 33, 227, 32, 0, 0, 73, 159, 8, 144, 12, 35, 0, 145,
13, 149, 4, 154, 7, 152, 10, 24, 210, 146, 8, 28, 17, 28, 35, 34, 1, 157, 9, 240, 0, 248, 169, 40, 0, 208, 0, 224, 135,
72, 78, 153, 14, 92, 34, 92, 99, 2, 18, 4, 27, 67, 26, 77, 76, 155, 13, 152, 8, 92, 225, 93, 99, 67, 10, 6, 27, 67,
19, 24, 192, 35, 235, 144, 8, 0, 91, 92, 227, 152, 10, 147, 16, 75, 69, 153, 8, 92, 227, 34, 1, 147, 17, 35, 236, 0,
91, 92, 227, 157, 9, 147, 18, 75, 65, 92, 227, 147, 19, 28, 35, 240, 0, 248, 128, 40, 0, 209, 95, 120, 34, 120, 99,
6, 18, 4, 27, 67, 19, 120, 162, 73, 54, 2, 18, 67, 19, 120, 226, 67, 19, 66, 139, 209, 10, 154, 43, 66, 150, 209, 2,
144, 0, 155, 8, 224, 48, 152, 8, 66, 184, 208, 1, 54, 1, 28, 7, 153, 17, 157, 18, 2, 11, 4, 42, 152, 16, 153, 19, 67,
19, 67, 3, 6, 10, 67, 19, 208, 53, 154, 12, 50, 1, 146, 12, 42, 8, 209, 162, 224, 47, 152, 10, 153, 7, 34, 1, 28, 35,
159, 9, 240, 0, 248, 79, 40, 0, 209, 45, 120, 34, 120, 99, 6, 18, 4, 27, 67, 19, 120, 162, 73, 29, 2, 18, 67, 19, 120,
226, 67, 19, 66, 139, 209, 27, 154, 43, 66, 150, 209, 15, 155, 7, 144, 0, 157, 44, 147, 1, 152, 9, 153, 15, 154, 10,
155, 11, 149, 2, 247, 255, 253, 201, 28, 5, 28, 32, 247, 251, 249, 79, 224, 17, 159, 7, 152, 8, 66, 135, 208, 4, 54,
1, 151, 8, 224, 1, 157, 4, 151, 8, 153, 5, 66, 141, 208, 1, 53, 16, 231, 65, 28, 32, 247, 251, 249, 61, 37, 0, 176,
37, 28, 40, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 96, 80, 19, 112, 107, 100, 19, 112, 107, 108, 19, 112, 106, 91,
19, 112, 106, 96, 87, 66, 70, 83, 0, 0, 1, 199, 0, 0, 1, 201, 0, 0, 1, 215, 0, 0, 1, 217, 71, 40, 71, 56, 181, 16, 109,
3, 28, 4, 43, 0, 208, 9, 72, 13, 240, 0, 253, 46, 72, 12, 240, 0, 253, 43, 72, 12, 240, 0, 253, 40, 224, 13, 104, 0,
247, 251, 249, 14, 108, 224, 247, 251, 249, 11, 108, 96, 40, 0, 208, 1, 247, 251, 249, 6, 28, 32, 247, 251, 249, 3,
188, 16, 188, 1, 71, 0, 19, 112, 106, 12, 19, 112, 106, 100, 19, 112, 105, 116, 181, 240, 28, 3, 51, 72, 176, 131, 136,
26, 122, 3, 28, 5, 65, 26, 146, 1, 35, 1, 74, 48, 66, 91, 96, 19, 34, 0, 28, 14, 146, 0, 39, 0, 224, 79, 104, 43, 25,
219, 123, 27, 43, 0, 208, 68, 106, 233, 155, 0, 49, 1, 24, 201, 34, 1, 107, 168, 108, 235, 107, 44, 240, 0, 248, 83,
108, 233, 28, 48, 34, 6, 240, 0, 251, 106, 40, 0, 209, 51, 32, 12, 247, 251, 248, 177, 30, 6, 209, 9, 72, 32, 240, 0,
252, 224, 72, 31, 240, 0, 252, 221, 72, 31, 240, 0, 252, 218, 224, 46, 28, 43, 51, 72, 96, 53, 96, 183, 136, 24, 247,
251, 248, 158, 28, 3, 96, 112, 40, 0, 209, 12, 72, 21, 240, 0, 252, 203, 72, 21, 240, 0, 252, 200, 72, 20, 240, 0, 252,
197, 28, 48, 247, 251, 248, 172, 224, 21, 106, 233, 154, 0, 49, 1, 24, 137, 107, 168, 107, 44, 154, 1, 240, 0, 248,
28, 109, 43, 51, 1, 101, 43, 224, 9, 155, 0, 55, 1, 28, 26, 155, 1, 24, 210, 146, 0, 143, 171, 66, 159, 211, 172, 38,
0, 176, 3, 28, 48, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 96, 80, 19, 112, 106, 12, 19, 112, 106, 144, 19, 112,
105, 116, 71, 32, 70, 192, 181, 16, 104, 3, 28, 4, 109, 26, 58, 1, 101, 26, 104, 64, 247, 251, 248, 123, 28, 32, 247,
251, 248, 120, 188, 16, 188, 1, 71, 0, 0, 0, 181, 240, 176, 137, 104, 5, 147, 0, 106, 107, 146, 1, 28, 6, 30, 154, 28,
8, 64, 208, 4, 2, 12, 18, 104, 104, 146, 4, 70, 132, 152, 4, 104, 116, 48, 128, 0, 64, 90, 32, 122, 47, 106, 42, 144,
2, 36, 1, 40, 0, 209, 0, 224, 194, 58, 1, 64, 250, 27, 219, 146, 6, 63, 2, 28, 10, 64, 250, 147, 5, 155, 6, 28, 23,
70, 96, 64, 31, 8, 131, 59, 1, 28, 26, 64, 10, 146, 7, 209, 0, 224, 133, 155, 2, 152, 5, 106, 233, 64, 131, 24, 121,
147, 3, 24, 201, 75, 87, 104, 26, 108, 235, 66, 138, 209, 5, 74, 85, 28, 24, 104, 17, 74, 85, 104, 18, 224, 18, 107,
44, 107, 168, 34, 1, 240, 0, 248, 165, 30, 4, 208, 0, 224, 149, 106, 235, 152, 3, 73, 76, 24, 251, 24, 27, 96, 11, 75,
75, 108, 233, 104, 24, 75, 75, 104, 26, 240, 0, 250, 227, 154, 7, 104, 108, 0, 145, 155, 0, 26, 100, 66, 156, 217, 0,
28, 28, 108, 235, 152, 1, 24, 89, 28, 34, 240, 0, 250, 213, 152, 0, 153, 1, 27, 0, 25, 9, 144, 0, 145, 1, 55, 1, 40,
0, 208, 71, 154, 6, 66, 186, 210, 68, 155, 4, 104, 114, 51, 1, 4, 27, 12, 27, 147, 4, 51, 128, 0, 91, 90, 211, 36, 1,
147, 2, 39, 0, 43, 0, 209, 54, 224, 95, 122, 43, 152, 0, 64, 216, 106, 43, 25, 194, 144, 3, 66, 154, 217, 1, 27, 219,
147, 3, 154, 5, 106, 233, 155, 2, 24, 121, 64, 147, 24, 201, 107, 168, 107, 44, 154, 3, 155, 1, 240, 0, 248, 86, 40,
0, 209, 70, 122, 43, 152, 3, 153, 0, 64, 152, 154, 3, 26, 9, 28, 3, 145, 0, 24, 191, 41, 0, 208, 15, 152, 6, 66, 184,
210, 12, 154, 4, 104, 113, 50, 1, 4, 18, 12, 18, 146, 4, 50, 128, 0, 82, 90, 138, 146, 2, 42, 0, 208, 42, 39, 0, 153,
1, 24, 201, 145, 1, 104, 107, 154, 0, 66, 154, 210, 197, 36, 0, 42, 0, 208, 34, 155, 5, 158, 2, 106, 233, 64, 158, 24,
121, 107, 44, 107, 168, 25, 137, 108, 235, 34, 1, 240, 0, 248, 35, 30, 4, 209, 20, 106, 235, 108, 233, 24, 255, 75,
11, 25, 190, 96, 30, 75, 11, 104, 24, 75, 11, 104, 26, 240, 0, 250, 99, 108, 233, 152, 1, 154, 0, 240, 0, 250, 94, 224,
2, 36, 1, 224, 0, 28, 4, 176, 9, 28, 32, 188, 240, 188, 2, 71, 8, 70, 192, 19, 112, 96, 80, 19, 112, 107, 100, 19, 112,
107, 108, 71, 32, 70, 192, 239, 0, 0, 204, 225, 47, 255, 30, 225, 160, 0, 0, 225, 160, 0, 0, 230, 0, 0, 16, 225, 47,
255, 30, 230, 0, 0, 48, 225, 47, 255, 30, 230, 0, 0, 80, 225, 47, 255, 30, 230, 0, 0, 112, 225, 47, 255, 30, 230, 0,
0, 144, 225, 47, 255, 30, 230, 0, 0, 176, 225, 47, 255, 30, 230, 0, 0, 208, 225, 47, 255, 30, 230, 0, 0, 240, 225, 47,
255, 30, 230, 0, 1, 16, 225, 47, 255, 30, 230, 0, 1, 48, 225, 47, 255, 30, 230, 0, 1, 80, 225, 47, 255, 30, 230, 0,
1, 112, 225, 47, 255, 30, 230, 0, 1, 144, 225, 47, 255, 30, 230, 0, 1, 176, 225, 47, 255, 30, 230, 0, 1, 208, 225, 47,
255, 30, 230, 0, 1, 240, 225, 47, 255, 30, 230, 0, 2, 16, 225, 47, 255, 30, 230, 0, 2, 48, 225, 47, 255, 30, 230, 0,
2, 80, 225, 47, 255, 30, 230, 0, 2, 112, 225, 47, 255, 30, 230, 0, 2, 144, 225, 47, 255, 30, 230, 0, 2, 176, 225, 47,
255, 30, 230, 0, 2, 208, 225, 47, 255, 30, 230, 0, 2, 240, 225, 47, 255, 30, 230, 0, 3, 16, 225, 47, 255, 30, 230, 0,
3, 48, 225, 47, 255, 30, 230, 0, 3, 80, 225, 47, 255, 30, 230, 0, 3, 112, 225, 47, 255, 30, 230, 0, 3, 144, 225, 47,
255, 30, 230, 0, 3, 176, 225, 47, 255, 30, 230, 0, 3, 208, 225, 47, 255, 30, 230, 0, 3, 240, 225, 47, 255, 30, 230,
0, 4, 16, 225, 47, 255, 30, 230, 0, 4, 48, 225, 47, 255, 30, 230, 0, 4, 80, 225, 47, 255, 30, 230, 0, 4, 112, 225, 47,
255, 30, 230, 0, 4, 144, 225, 47, 255, 30, 230, 0, 4, 176, 225, 47, 255, 30, 230, 0, 4, 208, 225, 47, 255, 30, 230,
0, 4, 240, 225, 47, 255, 30, 230, 0, 5, 16, 225, 47, 255, 30, 230, 0, 5, 48, 225, 47, 255, 30, 230, 0, 5, 80, 225, 47,
255, 30, 230, 0, 6, 144, 225, 47, 255, 30, 230, 0, 7, 240, 225, 47, 255, 30, 230, 0, 8, 16, 225, 47, 255, 30, 230, 0,
10, 16, 225, 47, 255, 30, 226, 144, 16, 0, 227, 176, 0, 4, 239, 0, 0, 171, 225, 47, 255, 30, 225, 160, 0, 0, 225, 160,
0, 0, 180, 3, 70, 113, 8, 73, 0, 64, 0, 73, 90, 9, 0, 73, 68, 142, 188, 3, 71, 112, 226, 81, 32, 1, 1, 47, 255, 30,
58, 0, 0, 54, 225, 80, 0, 1, 154, 0, 0, 34, 225, 17, 0, 2, 10, 0, 0, 35, 227, 17, 2, 14, 1, 160, 17, 129, 3, 160, 48,
8, 19, 160, 48, 1, 227, 81, 2, 1, 49, 81, 0, 0, 49, 160, 18, 1, 49, 160, 50, 3, 58, 255, 255, 250, 227, 81, 1, 2, 49,
81, 0, 0, 49, 160, 16, 129, 49, 160, 48, 131, 58, 255, 255, 250, 227, 160, 32, 0, 225, 80, 0, 1, 32, 64, 0, 1, 33, 130,
32, 3, 225, 80, 0, 161, 32, 64, 0, 161, 33, 130, 32, 163, 225, 80, 1, 33, 32, 64, 1, 33, 33, 130, 33, 35, 225, 80, 1,
161, 32, 64, 1, 161, 33, 130, 33, 163, 227, 80, 0, 0, 17, 176, 50, 35, 17, 160, 18, 33, 26, 255, 255, 239, 225, 160,
0, 2, 225, 47, 255, 30, 3, 160, 0, 1, 19, 160, 0, 0, 225, 47, 255, 30, 227, 81, 8, 1, 33, 160, 24, 33, 35, 160, 32,
16, 51, 160, 32, 0, 227, 81, 12, 1, 33, 160, 20, 33, 34, 130, 32, 8, 227, 81, 0, 16, 33, 160, 18, 33, 34, 130, 32, 4,
227, 81, 0, 4, 130, 130, 32, 3, 144, 130, 32, 161, 225, 160, 2, 48, 225, 47, 255, 30, 225, 47, 255, 31, 225, 160, 0,
0, 227, 80, 0, 0, 19, 224, 0, 0, 234, 0, 1, 11, 227, 81, 0, 0, 10, 255, 255, 248, 233, 45, 64, 3, 235, 255, 255, 188,
232, 189, 64, 6, 224, 3, 0, 146, 224, 65, 16, 3, 225, 47, 255, 30, 227, 81, 0, 0, 10, 0, 0, 67, 224, 32, 192, 1, 66,
97, 16, 0, 226, 81, 32, 1, 10, 0, 0, 39, 225, 176, 48, 0, 66, 96, 48, 0, 225, 83, 0, 1, 154, 0, 0, 38, 225, 17, 0, 2,
10, 0, 0, 40, 227, 17, 2, 14, 1, 160, 17, 129, 3, 160, 32, 8, 19, 160, 32, 1, 227, 81, 2, 1, 49, 81, 0, 3, 49, 160,
18, 1, 49, 160, 34, 2, 58, 255, 255, 250, 227, 81, 1, 2, 49, 81, 0, 3, 49, 160, 16, 129, 49, 160, 32, 130, 58, 255,
255, 250, 227, 160, 0, 0, 225, 83, 0, 1, 32, 67, 48, 1, 33, 128, 0, 2, 225, 83, 0, 161, 32, 67, 48, 161, 33, 128, 0,
162, 225, 83, 1, 33, 32, 67, 49, 33, 33, 128, 1, 34, 225, 83, 1, 161, 32, 67, 49, 161, 33, 128, 1, 162, 227, 83, 0,
0, 17, 176, 34, 34, 17, 160, 18, 33, 26, 255, 255, 239, 227, 92, 0, 0, 66, 96, 0, 0, 225, 47, 255, 30, 225, 60, 0, 0,
66, 96, 0, 0, 225, 47, 255, 30, 51, 160, 0, 0, 1, 160, 15, 204, 3, 128, 0, 1, 225, 47, 255, 30, 227, 81, 8, 1, 33, 160,
24, 33, 35, 160, 32, 16, 51, 160, 32, 0, 227, 81, 12, 1, 33, 160, 20, 33, 34, 130, 32, 8, 227, 81, 0, 16, 33, 160, 18,
33, 34, 130, 32, 4, 227, 81, 0, 4, 130, 130, 32, 3, 144, 130, 32, 161, 227, 92, 0, 0, 225, 160, 2, 51, 66, 96, 0, 0,
225, 47, 255, 30, 225, 47, 255, 31, 225, 160, 0, 0, 227, 80, 0, 0, 195, 224, 1, 2, 179, 160, 1, 2, 234, 0, 0, 183, 227,
81, 0, 0, 10, 255, 255, 247, 233, 45, 64, 3, 235, 255, 255, 177, 232, 189, 64, 6, 224, 3, 0, 146, 224, 65, 16, 3, 225,
47, 255, 30, 71, 112, 70, 192, 33, 16, 6, 2, 14, 3, 65, 200, 67, 19, 6, 2, 14, 0, 67, 16, 65, 200, 67, 24, 71, 112,
70, 192, 181, 112, 28, 4, 28, 13, 42, 3, 217, 33, 28, 11, 67, 3, 7, 158, 208, 18, 120, 32, 120, 41, 66, 136, 209, 29,
58, 1, 35, 0, 224, 5, 52, 1, 51, 1, 120, 32, 92, 233, 66, 136, 209, 20, 66, 154, 209, 247, 32, 0, 188, 112, 188, 2,
71, 8, 28, 13, 28, 4, 201, 8, 200, 64, 66, 158, 209, 4, 58, 4, 28, 4, 28, 13, 42, 3, 216, 244, 32, 0, 42, 0, 209, 222,
231, 237, 26, 64, 231, 235, 70, 192, 181, 240, 28, 5, 28, 14, 28, 20, 42, 15, 217, 3, 28, 11, 67, 3, 7, 159, 208, 10,
44, 0, 208, 5, 35, 0, 92, 242, 84, 234, 51, 1, 66, 163, 209, 250, 188, 240, 188, 2, 71, 8, 28, 21, 28, 12, 28, 3, 104,
38, 96, 30, 104, 102, 96, 94, 104, 166, 96, 158, 104, 230, 61, 16, 96, 222, 52, 16, 51, 16, 45, 15, 216, 242, 58, 16,
9, 23, 28, 126, 1, 63, 1, 54, 27, 215, 25, 133, 28, 60, 25, 142, 47, 3, 217, 217, 28, 52, 28, 59, 28, 42, 204, 2, 59,
4, 194, 2, 43, 3, 216, 250, 63, 4, 8, 188, 28, 99, 0, 155, 0, 164, 24, 237, 24, 246, 27, 60, 231, 200, 70, 192, 181,
112, 28, 3, 7, 132, 208, 13, 42, 0, 208, 64, 6, 13, 58, 1, 14, 45, 36, 3, 224, 2, 42, 0, 208, 57, 58, 1, 112, 29, 51,
1, 66, 35, 209, 248, 42, 3, 217, 41, 37, 255, 64, 13, 2, 44, 67, 37, 4, 44, 28, 30, 67, 37, 42, 15, 217, 18, 28, 28,
28, 22, 62, 16, 96, 37, 96, 101, 96, 165, 96, 229, 52, 16, 46, 15, 216, 247, 58, 16, 9, 22, 54, 1, 1, 54, 25, 158, 35,
15, 64, 26, 42, 3, 217, 12, 28, 52, 28, 19, 59, 4, 196, 32, 43, 3, 216, 251, 58, 4, 8, 147, 51, 1, 0, 155, 24, 246,
35, 3, 64, 26, 28, 51, 42, 0, 208, 6, 6, 9, 14, 12, 33, 0, 84, 92, 49, 1, 66, 138, 209, 251, 188, 112, 188, 2, 71, 8,
120, 2, 120, 11, 48, 1, 49, 1, 42, 0, 208, 1, 66, 154, 208, 247, 26, 208, 71, 112, 35, 0, 92, 194, 51, 1, 42, 0, 209,
251, 30, 88, 71, 112, 70, 192, 181, 240, 28, 3, 32, 0, 42, 0, 208, 72, 28, 8, 67, 24, 36, 3, 30, 85, 64, 4, 209, 42,
28, 30, 28, 13, 42, 3, 217, 67, 104, 31, 104, 8, 66, 135, 209, 63, 58, 4, 28, 32, 42, 0, 208, 54, 72, 34, 24, 61, 67,
189, 79, 33, 28, 32, 66, 61, 209, 47, 29, 28, 29, 8, 224, 11, 204, 8, 200, 2, 66, 139, 209, 45, 58, 4, 42, 0, 208, 40,
77, 25, 25, 89, 67, 153, 66, 57, 209, 35, 28, 38, 28, 5, 42, 3, 216, 239, 28, 35, 28, 1, 42, 0, 208, 33, 30, 85, 120,
28, 120, 8, 66, 132, 209, 18, 32, 0, 45, 0, 208, 16, 44, 0, 208, 14, 61, 1, 34, 0, 224, 4, 66, 170, 208, 12, 50, 1,
44, 0, 208, 9, 24, 152, 120, 68, 24, 136, 120, 64, 66, 132, 208, 244, 26, 32, 188, 240, 188, 2, 71, 8, 32, 0, 231, 250,
28, 41, 28, 51, 30, 85, 231, 222, 120, 36, 120, 0, 26, 32, 231, 242, 70, 192, 254, 254, 254, 255, 128, 128, 128, 128,
0, 0, 0, 0, 71, 120, 70, 192, 234, 255, 254, 125, 71, 120, 70, 192, 234, 255, 254, 137, 71, 120, 70, 192, 234, 255,
254, 123, 71, 120, 70, 192, 234, 255, 254, 253, 71, 120, 70, 192, 234, 255, 233, 149, 71, 120, 70, 192, 234, 255, 254,
119, 71, 120, 70, 192, 234, 255, 254, 184, 71, 120, 70, 192, 234, 255, 254, 163, 71, 120, 70, 192, 234, 255, 233, 174,
229, 159, 192, 0, 225, 47, 255, 28, 19, 112, 87, 81, 71, 120, 70, 192, 234, 255, 254, 124, 71, 120, 70, 192, 234, 255,
254, 244, 71, 120, 70, 192, 234, 255, 255, 62, 71, 120, 70, 192, 234, 255, 254, 84, 71, 120, 70, 192, 234, 255, 254,
80, 71, 120, 70, 192, 234, 255, 254, 112, 71, 120, 70, 192, 234, 255, 254, 86, 71, 120, 70, 192, 234, 255, 254, 88,
71, 120, 70, 192, 234, 255, 233, 162, 71, 120, 70, 192, 234, 255, 254, 96, 71, 120, 70, 192, 234, 255, 254, 144, 71,
120, 70, 192, 234, 255, 233, 152, 71, 120, 70, 192, 234, 255, 254, 136, 71, 120, 70, 192, 234, 255, 254, 84, 71, 120,
70, 192, 234, 255, 233, 106, 71, 120, 70, 192, 234, 255, 254, 124, 71, 120, 70, 192, 234, 255, 254, 34, 71, 120, 70,
192, 234, 255, 254, 66, 71, 120, 70, 192, 234, 255, 233, 94, 71, 120, 70, 192, 234, 255, 254, 82, 71, 120, 70, 192,
234, 255, 254, 118, 71, 120, 70, 192, 234, 255, 254, 34, 0, 0, 0, 0, 73, 79, 83, 32, 109, 111, 100, 117, 108, 101, 0,
0, 255, 255, 255, 255, 1, 0, 0, 0, 0, 0, 0, 1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 31,
240, 4, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 15, 66, 64, 19, 114, 198, 36, 16,
0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 87, 66, 70, 83, 32, 110, 111, 116, 32, 101,
110, 111, 117, 103, 104, 32, 109, 101, 109, 111, 114, 121, 33, 10, 0, 47, 100, 101, 118, 47, 117, 115, 98, 49, 50, 51,
0, 47, 100, 101, 118, 47, 117, 115, 98, 49, 50, 51, 47, 79, 70, 70, 0, 102, 105, 114, 115, 116, 32, 114, 101, 97, 100,
32, 115, 101, 99, 116, 111, 114, 32, 40, 37, 105, 41, 32, 79, 75, 10, 0, 102, 105, 114, 115, 116, 32, 114, 101, 97,
100, 32, 115, 101, 99, 116, 111, 114, 32, 40, 37, 105, 41, 32, 69, 82, 82, 79, 82, 10, 0, 101, 104, 99, 105, 95, 105,
110, 116, 95, 119, 111, 114, 107, 105, 110, 103, 95, 99, 97, 108, 108, 98, 97, 99, 107, 95, 112, 97, 114, 116, 49, 44,
32, 116, 105, 109, 101, 111, 117, 116, 58, 32, 37, 117, 10, 0, 117, 114, 98, 32, 114, 101, 116, 118, 97, 108, 58, 32,
37, 105, 10, 0, 117, 110, 97, 98, 108, 101, 32, 116, 111, 32, 103, 101, 116, 32, 100, 101, 118, 105, 99, 101, 32, 100,
101, 115, 99, 46, 46, 46, 10, 0, 103, 101, 116, 116, 105, 110, 103, 32, 85, 83, 66, 95, 82, 69, 81, 95, 71, 69, 84,
68, 69, 83, 67, 82, 73, 80, 84, 79, 82, 32, 45, 32, 114, 101, 115, 101, 116, 10, 0, 101, 114, 114, 111, 114, 32, 103,
101, 116, 116, 105, 110, 103, 32, 85, 83, 66, 95, 82, 69, 81, 95, 71, 69, 84, 68, 69, 83, 67, 82, 73, 80, 84, 79, 82,
10, 0, 103, 101, 116, 116, 105, 110, 103, 32, 85, 83, 66, 95, 82, 69, 81, 95, 71, 69, 84, 68, 69, 83, 67, 82, 73, 80,
84, 79, 82, 32, 45, 32, 97, 100, 113, 117, 105, 114, 101, 32, 45, 32, 114, 101, 115, 101, 116, 10, 0, 85, 83, 66, 95,
82, 69, 81, 95, 71, 69, 84, 68, 69, 83, 67, 82, 73, 80, 84, 79, 82, 32, 111, 107, 10, 0, 116, 114, 121, 105, 110, 103,
32, 85, 83, 66, 95, 82, 69, 81, 95, 83, 69, 84, 65, 68, 68, 82, 69, 83, 83, 58, 32, 37, 100, 10, 0, 117, 110, 97, 98,
108, 101, 32, 116, 111, 32, 115, 101, 116, 32, 100, 101, 118, 105, 99, 101, 32, 97, 100, 100, 114, 58, 32, 37, 100,
10, 0, 85, 83, 66, 95, 82, 69, 81, 95, 83, 69, 84, 65, 68, 68, 82, 69, 83, 83, 32, 111, 107, 58, 32, 37, 100, 10, 0,
101, 114, 114, 111, 114, 32, 99, 104, 101, 99, 107, 105, 110, 103, 32, 85, 83, 66, 95, 82, 69, 81, 95, 71, 69, 84, 68,
69, 83, 67, 82, 73, 80, 84, 79, 82, 10, 0, 111, 107, 32, 99, 104, 101, 99, 107, 105, 110, 103, 32, 85, 83, 66, 95, 82,
69, 81, 95, 71, 69, 84, 68, 69, 83, 67, 82, 73, 80, 84, 79, 82, 10, 0, 105, 110, 105, 116, 32, 111, 107, 10, 0, 98,
117, 102, 102, 101, 114, 32, 61, 61, 32, 78, 85, 76, 76, 32, 40, 110, 111, 32, 109, 101, 109, 41, 10, 0, 95, 95, 117,
115, 98, 95, 103, 101, 116, 100, 101, 115, 99, 32, 101, 114, 114, 111, 114, 32, 85, 83, 66, 95, 68, 84, 95, 68, 69,
86, 73, 67, 69, 58, 32, 114, 101, 116, 114, 121, 10, 0, 95, 95, 117, 115, 98, 95, 103, 101, 116, 100, 101, 115, 99,
32, 101, 114, 114, 111, 114, 32, 85, 83, 66, 95, 68, 84, 95, 68, 69, 86, 73, 67, 69, 10, 0, 117, 100, 100, 45, 62, 99,
111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 115, 32, 61, 61, 32, 78, 85, 76, 76, 32, 40, 110, 111, 32,
109, 101, 109, 41, 10, 0, 95, 95, 117, 115, 98, 95, 103, 101, 116, 100, 101, 115, 99, 32, 101, 114, 114, 111, 114, 32,
85, 83, 66, 95, 68, 84, 95, 67, 79, 78, 70, 73, 71, 58, 32, 114, 101, 116, 114, 121, 10, 0, 117, 99, 100, 45, 62, 105,
110, 116, 101, 114, 102, 97, 99, 101, 115, 32, 61, 61, 32, 78, 85, 76, 76, 32, 40, 110, 111, 32, 109, 101, 109, 41,
10, 0, 117, 105, 100, 45, 62, 101, 110, 100, 112, 111, 105, 110, 116, 115, 32, 61, 61, 32, 78, 85, 76, 76, 32, 40, 110,
111, 32, 109, 101, 109, 41, 10, 0, 117, 105, 100, 45, 62, 101, 120, 116, 114, 97, 32, 61, 61, 32, 78, 85, 76, 76, 32,
40, 110, 111, 32, 109, 101, 109, 41, 10, 0, 10, 113, 116, 100, 32, 101, 114, 114, 111, 114, 33, 58, 0, 32, 66, 65, 66,
66, 76, 69, 0, 32, 32, 109, 105, 115, 115, 101, 100, 32, 109, 105, 99, 114, 111, 32, 102, 114, 97, 109, 101, 0, 32,
32, 100, 97, 116, 97, 98, 117, 102, 102, 101, 114, 32, 101, 114, 114, 111, 114, 0, 32, 119, 114, 111, 110, 103, 32,
97, 99, 107, 0, 32, 116, 111, 111, 32, 109, 97, 110, 121, 32, 101, 114, 114, 111, 114, 115, 0, 105, 110, 116, 101, 114,
114, 117, 112, 116, 95, 99, 97, 108, 108, 98, 97, 99, 107, 95, 104, 97, 110, 100, 32, 83, 84, 83, 95, 73, 78, 84, 10,
0, 105, 110, 116, 101, 114, 114, 117, 112, 116, 95, 99, 97, 108, 108, 98, 97, 99, 107, 95, 104, 97, 110, 100, 32, 83,
84, 83, 95, 80, 67, 68, 10, 0, 117, 115, 98, 115, 116, 111, 114, 97, 103, 101, 32, 114, 101, 115, 101, 116, 58, 32,
66, 85, 76, 75, 32, 82, 69, 83, 69, 84, 32, 37, 105, 10, 0, 117, 115, 98, 115, 116, 111, 114, 97, 103, 101, 32, 114,
101, 115, 101, 116, 58, 32, 99, 108, 101, 97, 114, 104, 97, 108, 116, 32, 105, 110, 32, 114, 101, 116, 32, 37, 105,
10, 0, 117, 115, 98, 115, 116, 111, 114, 97, 103, 101, 32, 114, 101, 115, 101, 116, 58, 32, 99, 108, 101, 97, 114, 104,
97, 108, 116, 32, 111, 117, 116, 32, 114, 101, 116, 32, 37, 105, 10, 0, 117, 115, 98, 115, 116, 111, 114, 97, 103, 101,
32, 114, 101, 115, 101, 116, 58, 32, 85, 83, 66, 95, 71, 101, 116, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105,
111, 110, 32, 114, 101, 116, 32, 37, 105, 10, 0, 114, 101, 115, 101, 116, 32, 111, 107, 10, 0, 95, 95, 115, 101, 110,
100, 95, 99, 98, 119, 32, 114, 101, 116, 32, 37, 105, 10, 0, 95, 95, 85, 83, 66, 95, 66, 108, 107, 77, 115, 103, 84,
105, 109, 101, 111, 117, 116, 32, 37, 105, 10, 0, 95, 95, 114, 101, 97, 100, 95, 99, 115, 119, 32, 37, 105, 10, 0, 32,
32, 32, 32, 83, 67, 83, 73, 95, 84, 69, 83, 84, 95, 85, 78, 73, 84, 95, 82, 69, 65, 68, 89, 32, 114, 101, 116, 32, 37,
105, 10, 0, 32, 32, 32, 32, 83, 67, 83, 73, 95, 82, 69, 81, 85, 69, 83, 84, 95, 83, 69, 78, 83, 69, 32, 114, 101, 116,
32, 37, 105, 10, 0, 32, 32, 32, 32, 83, 67, 83, 73, 95, 82, 69, 81, 85, 69, 83, 84, 95, 83, 69, 78, 83, 69, 32, 115,
116, 97, 116, 117, 115, 32, 37, 120, 10, 0, 85, 83, 66, 83, 116, 111, 114, 97, 103, 101, 95, 79, 112, 101, 110, 40,
41, 58, 32, 85, 83, 66, 95, 71, 101, 116, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 115, 32, 37, 105, 10, 0, 85,
83, 66, 83, 116, 111, 114, 97, 103, 101, 95, 79, 112, 101, 110, 40, 41, 58, 32, 100, 101, 118, 105, 99, 101, 32, 99,
104, 97, 110, 103, 101, 100, 33, 33, 33, 10, 0, 85, 83, 66, 83, 116, 111, 114, 97, 103, 101, 95, 79, 112, 101, 110,
40, 41, 58, 32, 117, 99, 100, 32, 37, 105, 32, 80, 111, 119, 101, 114, 32, 37, 105, 32, 109, 65, 10, 0, 85, 83, 66,
83, 116, 111, 114, 97, 103, 101, 95, 79, 112, 101, 110, 40, 41, 58, 32, 105, 110, 116, 101, 114, 102, 97, 99, 101, 32,
115, 117, 98, 99, 108, 97, 115, 115, 32, 37, 105, 32, 97, 116, 97, 95, 112, 114, 111, 116, 32, 37, 105, 32, 10, 0, 73,
110, 32, 80, 111, 105, 110, 116, 58, 32, 37, 105, 10, 0, 79, 117, 116, 32, 80, 111, 105, 110, 116, 58, 32, 37, 105,
10, 0, 101, 112, 95, 105, 110, 32, 37, 120, 32, 101, 112, 95, 111, 117, 116, 32, 37, 120, 10, 0, 85, 83, 66, 83, 116,
111, 114, 97, 103, 101, 95, 79, 112, 101, 110, 40, 41, 58, 32, 99, 97, 110, 110, 111, 116, 32, 102, 105, 110, 100, 32,
97, 110, 121, 32, 105, 110, 116, 101, 114, 102, 97, 99, 101, 33, 33, 33, 10, 0, 85, 83, 66, 83, 116, 111, 114, 97, 103,
101, 95, 79, 112, 101, 110, 40, 41, 58, 32, 99, 111, 110, 102, 58, 32, 37, 120, 32, 97, 108, 116, 73, 110, 116, 101,
114, 102, 97, 99, 101, 58, 32, 37, 120, 10, 0, 85, 83, 66, 95, 71, 101, 116, 67, 111, 110, 102, 105, 103, 117, 114,
97, 116, 105, 111, 110, 40, 41, 32, 69, 114, 114, 111, 114, 46, 32, 67, 111, 110, 116, 105, 110, 117, 101, 46, 10, 0,
65, 99, 116, 117, 97, 108, 32, 99, 111, 110, 102, 58, 32, 37, 120, 32, 32, 32, 110, 101, 120, 116, 32, 99, 111, 110,
102, 58, 32, 37, 120, 10, 0, 85, 83, 66, 95, 83, 101, 116, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111,
110, 40, 41, 32, 69, 114, 114, 111, 114, 10, 0, 85, 83, 66, 95, 83, 101, 116, 65, 108, 116, 101, 114, 110, 97, 116,
105, 118, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 40, 41, 32, 69, 114, 114, 111, 114, 46, 32, 67, 111, 110, 116,
105, 110, 117, 101, 10, 0, 85, 83, 66, 95, 83, 101, 116, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110,
40, 41, 32, 38, 32, 85, 83, 66, 95, 83, 101, 116, 65, 108, 116, 101, 114, 110, 97, 116, 105, 118, 101, 73, 110, 116,
101, 114, 102, 97, 99, 101, 40, 41, 32, 79, 75, 10, 0, 71, 101, 116, 95, 77, 97, 120, 95, 76, 117, 110, 40, 41, 58,
32, 101, 114, 114, 44, 32, 100, 101, 102, 97, 117, 108, 116, 32, 109, 97, 120, 95, 108, 117, 110, 61, 56, 10, 0, 71,
101, 116, 95, 77, 97, 120, 95, 76, 117, 110, 40, 41, 58, 32, 79, 75, 58, 32, 37, 105, 10, 0, 85, 83, 66, 83, 116, 111,
114, 97, 103, 101, 95, 79, 112, 101, 110, 40, 41, 58, 32, 116, 114, 121, 95, 115, 116, 97, 116, 117, 115, 32, 37, 105,
10, 0, 85, 83, 66, 83, 116, 111, 114, 97, 103, 101, 95, 79, 112, 101, 110, 40, 41, 58, 32, 79, 75, 44, 32, 114, 101,
116, 117, 114, 110, 32, 48, 10, 0, 32, 32, 32, 32, 115, 116, 97, 114, 116, 95, 115, 116, 111, 112, 32, 99, 109, 100,
32, 114, 101, 116, 32, 37, 105, 10, 0, 32, 32, 32, 32, 73, 110, 113, 117, 105, 114, 121, 32, 114, 101, 116, 32, 37,
105, 10, 0, 32, 32, 32, 32, 68, 101, 118, 105, 99, 101, 32, 84, 121, 112, 101, 58, 32, 37, 120, 10, 0, 32, 32, 32, 32,
82, 101, 97, 100, 67, 97, 112, 97, 99, 105, 116, 121, 32, 114, 101, 116, 32, 37, 105, 32, 32, 115, 101, 99, 116, 111,
114, 95, 115, 105, 122, 101, 58, 32, 37, 117, 32, 32, 115, 101, 99, 116, 111, 114, 115, 58, 32, 37, 117, 10, 0, 70,
97, 115, 116, 32, 85, 83, 66, 83, 116, 111, 114, 97, 103, 101, 95, 77, 111, 117, 110, 116, 76, 85, 78, 32, 37, 105,
35, 10, 0, 85, 83, 66, 83, 116, 111, 114, 97, 103, 101, 95, 77, 111, 117, 110, 116, 76, 85, 78, 58, 32, 114, 101, 116,
32, 37, 105, 10, 0, 85, 83, 66, 83, 84, 79, 82, 65, 71, 69, 95, 71, 69, 84, 95, 77, 65, 88, 95, 76, 85, 78, 32, 114,
101, 116, 32, 37, 105, 32, 109, 97, 120, 108, 117, 110, 32, 37, 105, 10, 0, 85, 83, 66, 83, 116, 111, 114, 97, 103,
101, 95, 77, 111, 117, 110, 116, 76, 85, 78, 32, 102, 97, 105, 108, 33, 33, 33, 10, 0, 10, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 10, 82, 111, 100, 114, 105, 101, 115, 32, 101, 104, 99,
109, 111, 100, 117, 108, 101, 32, 49, 46, 48, 10, 85, 83, 66, 83, 116, 111, 114, 97, 103, 101, 95, 73, 110, 105, 116,
40, 41, 10, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 10, 10, 0, 85, 83,
66, 83, 116, 111, 114, 97, 103, 101, 95, 73, 110, 105, 116, 40, 41, 32, 79, 107, 10, 0, 69, 114, 114, 111, 114, 32,
82, 101, 97, 100, 105, 110, 103, 32, 115, 101, 99, 116, 111, 114, 32, 48, 10, 0, 79, 75, 32, 82, 101, 97, 100, 105,
110, 103, 32, 115, 101, 99, 116, 111, 114, 32, 48, 10, 0, 85, 110, 112, 108, 117, 103, 58, 32, 114, 101, 115, 101, 116,
32, 37, 105, 32, 115, 116, 97, 116, 117, 115, 32, 37, 120, 10, 0, 102, 97, 115, 116, 95, 114, 101, 109, 111, 117, 110,
116, 32, 75, 79, 32, 114, 101, 116, 32, 37, 105, 10, 0, 85, 83, 66, 32, 65, 108, 108, 111, 99, 58, 32, 110, 111, 116,
32, 101, 110, 111, 117, 103, 104, 32, 109, 101, 109, 111, 114, 121, 33, 10, 0, 119, 98, 102, 115, 32, 101, 114, 114,
111, 114, 32, 0, 98, 97, 100, 32, 109, 97, 103, 105, 99, 0, 104, 100, 32, 115, 101, 99, 116, 111, 114, 32, 115, 105,
122, 101, 32, 100, 111, 101, 115, 110, 39, 116, 32, 109, 97, 116, 99, 104, 0, 104, 100, 32, 110, 117, 109, 32, 115,
101, 99, 116, 111, 114, 32, 100, 111, 101, 115, 110, 39, 116, 32, 109, 97, 116, 99, 104, 0, 78, 84, 70, 83, 0, 70, 65,
84, 0, 116, 114, 121, 105, 110, 103, 32, 116, 111, 32, 99, 108, 111, 115, 101, 32, 119, 98, 102, 115, 32, 119, 104,
105, 108, 101, 32, 100, 105, 115, 99, 115, 32, 115, 116, 105, 108, 108, 32, 111, 112, 101, 110, 0, 97, 108, 108, 111,
99, 97, 116, 105, 110, 103, 32, 109, 101, 109, 111, 114, 121, 0
};

3
bin/ehcmodule_5.h Normal file
View File

@ -0,0 +1,3 @@
#define size_ehcmodule_5 26234
extern unsigned char ehcmodule_5[26234];

View File

@ -1,14 +0,0 @@
#!/bin/bash
if [ ! -z "$1" ];
then
if [ ! -s source/buildtype.h ];
then
echo "#define $1" > source/buildtype.h
fi
else
if [[ ! -f source/buildtype.h || -s source/buildtype.h ]];
then
cp /dev/null source/buildtype.h
fi
fi

BIN
cios_installer.dol Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

339
cios_installer/COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,5 @@
make
pause

141
cios_installer/Makefile Normal file
View File

@ -0,0 +1,141 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := cios_installer
BUILD := build
SOURCES := .
DATA := data
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) $(DEBUG) $(ADD_DIP_PLUGIN)
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lwiiuse -lbte -lm -lfat -logc -ldb
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o)
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
upload:
$(DEVKITPPC)/bin/geckoupload $(TARGET).dol; nanokdp -d /dev/tty.usbserial-GECKUSB0
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
%.certs.o : %.certs
@echo $(notdir $<)
$(bin2o)
%.elf.o : %.elf
@echo $(notdir $<)
$(bin2o)
%.bin.o : %.bin
@echo $(notdir $<)
$(bin2o)
%.raw.o : %.raw
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

View File

@ -0,0 +1,288 @@
/* Copyright (C) 2008 Mega Man */
/* Based on Wii GameCube Homebrew Launcher */
/* Copyright (C) 2008 WiiGator */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <ctype.h>
#include <unistd.h>
#include "elf.h"
#include "add_dip_plugin.h"
#include "debug_printf.h"
#if 0
// disabled
// XXXXXXXXXXXXXXXXXXXXX
#include "dip_plugin_bin.h"
#define round_up(x,n) (-(-(x) & -(n)))
/** Binary is loaded to this address. */
#if IOS36
#define BIN_PATCH_ADDR 0x202080e0
#define EXTENDED_AREA_START 0x20200000
#define BSS_START 0x2020a000
#define BSS_SIZE 0x0002c000
#elif IOS38
#define BIN_PATCH_ADDR 0x20208200
#define EXTENDED_AREA_START 0x20208000
#define BSS_START 0x20209000
#define BSS_SIZE 0x0002c000
#else
#ifdef ADD_DIP_PLUGIN
#error "Hey! i need IOS36 or IOS38 defined!"
#else
// fake data to compile the code
#define BIN_PATCH_ADDR 0x202080e0
#define EXTENDED_AREA_START 0x20200000
#define BSS_START 0x2020a000
#define BSS_SIZE 0x0002c000
#endif
#endif
/** Start of ELF area which is extneded. */
/** Header for Wii ARM binaries. */
typedef struct
{
/** Size of this header. */
uint32_t headerSize;
/** Offset to ELF file. */
uint32_t offset;
/** Size of ELF file. */
uint32_t size;
/** Padded with zeroes. */
uint32_t resevered;
}
arm_binary_header_t;
typedef struct
{
uint32_t cmd;
uint32_t function_orig;
uint32_t function_patch;
}
jmp_table_patch_entry_t;
/**
* Copy program sections of ELF file to new ELF file;
* @param buffer Pointer to ELF file.
*/
static int copy_sections(uint8_t *buffer, uint8_t *out)
{
Elf32_Ehdr_t *file_header;
int pos = 0;
int i;
uint32_t outPos = 0;
/* 0x1000 should be enough to copy ELF header. */
memcpy(out, buffer, 0x1000);
/* Use output (copied) elf header. */
file_header = (Elf32_Ehdr_t *) & out[pos];
pos += sizeof(Elf32_Ehdr_t);
if (file_header->magic != ELFMAGIC)
{
debug_printf("Magic 0x%08x is wrong.\n", file_header->magic);
return -2;
}
outPos = pos + file_header->phnum * sizeof(Elf32_Phdr_t);
//debug_printf("data start = 0x%02x\n", outPos);
for (i = 0; i < file_header->phnum; i++)
{
Elf32_Phdr_t *program_header;
program_header = (Elf32_Phdr_t *) & out[pos];
pos += sizeof(Elf32_Phdr_t);
if ( (program_header->type == PT_LOAD)
&& (program_header->memsz != 0) )
{
unsigned char *src;
unsigned char *dst;
// Copy to physical address which can be accessed by loader.
src = buffer + program_header->offset;
if (program_header->offset != sizeof(Elf32_Ehdr_t))
{
program_header->offset = outPos;
}
else
{
/* Don't change offset for first section. */
outPos = program_header->offset;
}
dst = out + outPos;
if (program_header->vaddr == EXTENDED_AREA_START)
{
uint32_t origFileSize;
printf("Extended Area finded!!!!\n");
origFileSize = program_header->filesz;
program_header->filesz = program_header->memsz = BIN_PATCH_ADDR - EXTENDED_AREA_START + dip_plugin_bin_size;
memset(dst, 0, program_header->filesz);
if (origFileSize != 0)
{
memcpy(dst, src, origFileSize);
}
}
if (program_header->vaddr == BSS_START)
{
printf("BSS Start finded!!!!\n");
//debug_printf("Extending BSS.\n");
program_header->memsz += 0x1000; //BSS_SIZE;
}
/*debug_printf("VAddr: 0x%08x PAddr: 0x%08x Offset 0x%08x File Size 0x%08x Mem Size 0x%08x\n",
program_header->vaddr,
program_header->paddr,
program_header->offset,
program_header->filesz,
program_header->memsz);
*/
if (program_header->filesz != 0)
{
if (program_header->vaddr == EXTENDED_AREA_START)
{
//debug_printf("Adding dip plugin with binary data in existing ELF section.\n");
memcpy(dst + BIN_PATCH_ADDR - EXTENDED_AREA_START, dip_plugin_bin, dip_plugin_bin_size);
}
else
{
memcpy(dst, src, program_header->filesz);
}
outPos += program_header->filesz;
}
}
}
return 0;
}
/**
* Calculate required memory space.
* @param buffer Pointer to ELF file.
*/
static uint32_t calculate_new_size(uint8_t *buffer)
{
Elf32_Ehdr_t *file_header;
int pos = 0;
int i;
uint32_t maxSize = 0;
file_header = (Elf32_Ehdr_t *) & buffer[pos];
pos += sizeof(Elf32_Ehdr_t);
if (file_header->magic != ELFMAGIC)
{
debug_printf("Magic 0x%08x is wrong.\n", file_header->magic);
return 0;
}
for (i = 0; i < file_header->phnum; i++)
{
Elf32_Phdr_t *program_header;
program_header = (Elf32_Phdr_t *) & buffer[pos];
pos += sizeof(Elf32_Phdr_t);
if ( (program_header->type == PT_LOAD)
&& (program_header->memsz != 0) )
{
unsigned char *src;
/*debug_printf("VAddr: 0x%08x PAddr: 0x%08x Offset 0x%08x File Size 0x%08x Mem Size 0x%08x\n",
program_header->vaddr,
program_header->paddr,
program_header->offset,
program_header->filesz,
program_header->memsz);
*/
src = buffer + program_header->offset;
if (program_header->filesz != 0)
{
uint32_t size;
size = program_header->offset + program_header->filesz;
if (size > maxSize)
{
maxSize = size;
}
}
}
}
/* Real calculation after getting all information .*/
return maxSize + BIN_PATCH_ADDR - EXTENDED_AREA_START + dip_plugin_bin_size + sizeof(Elf32_Phdr_t);
}
int add_dip_plugin(uint8_t **buffer)
{
uint8_t *inElf = NULL;
uint8_t *outElf = NULL;
uint32_t outElfSize;
uint32_t content_size;
inElf = *buffer;
debug_printf("Adding DIP plugin\n");
outElfSize = calculate_new_size(inElf);
if (outElfSize <= 0)
{
debug_printf("add dip plugin Patching failed\n");
return -32;
}
content_size = round_up(outElfSize, 0x40);
outElf = malloc(content_size);
if (outElf == NULL)
{
debug_printf("Out of memory\n");
return -33;
}
/* Set default to 0. */
memset(outElf, 0, content_size);
debug_printf("\n");
if (copy_sections(inElf, outElf) < 0)
{
debug_printf("Failed to patch ELF.\n");
return -39;
}
*buffer = outElf;
free(inElf);
return outElfSize;
}
// XXXXXXXXXXXXXXXXXXXX
#endif

View File

@ -0,0 +1,8 @@
#ifndef _ADD_KERNEL_CODE_H_
#define _ADD_KERNEL_CODE_H_
#include "stdint.h"
int add_dip_plugin(uint8_t **buffer);
#endif

Binary file not shown.

Binary file not shown.

BIN
cios_installer/data/tmd.raw Normal file

Binary file not shown.

View File

@ -0,0 +1,7 @@
#ifndef _DEBUG_PRINTF_H_
#define _DEBUG_PRINTF_H_
void debug_printf(const char *fmt, ...);
void error_debug_printf(const char *fmt, ...);
#endif

57
cios_installer/elf.h Normal file
View File

@ -0,0 +1,57 @@
/* Copyright (C) 2008 Mega Man */
#ifndef __ELF_H_
#define __ELF_H_
#include "stdint.h"
/* File header */
typedef struct Elf32_Ehdr
{
uint32_t magic; /* Magic number */
unsigned char info[12]; /* other info */
uint16_t type; /* Object file type */
uint16_t machine; /* Architecture */
uint32_t version; /* Object file version */
uint32_t entry; /* Entry point virtual address */
uint32_t phoff; /* Program header table file offset */
uint32_t shoff; /* Section header table file offset */
uint32_t flags; /* Processor-specific flags */
uint16_t ehsize; /* ELF header size in bytes */
uint16_t phentsize; /* Program header table entry size */
uint16_t phnum; /* Program header table entry count */
uint16_t shentsize; /* Section header table entry size */
uint16_t shnum; /* Section header table entry count */
uint16_t shstrndx; /* Section header string table index */
} Elf32_Ehdr_t;
/* Conglomeration of the identification bytes, for easy testing as a word. */
#if 0
/** ELF magic for little endian. */
#define ELFMAGIC 0x464c457f
#else
/** ELF magic for big endian. */
#define ELFMAGIC 0x7f454c46
#endif
/* Program segment header. */
typedef struct Elf32_Phdr
{
uint32_t type; /* type */
uint32_t offset; /* file offset */
uint32_t vaddr; /* virtual address */
uint32_t paddr; /* physical address */
uint32_t filesz; /* size in file */
uint32_t memsz; /* size in memory */
uint32_t flags; /* flags */
uint32_t align; /* alignment */
} Elf32_Phdr_t;
/* Possible values for segment type. */
#define PT_LOAD 1 /* Loadable program segment */
/* Possible values for segment flags. */
#define PF_X 1 /* executable */
#define PF_W 2 /* writable */
#define PF_R 4 /* readable */
#endif /* __ELF_H_ */

397
cios_installer/http.c Normal file
View File

@ -0,0 +1,397 @@
/* http -- http convenience functions
Copyright (C) 2008 bushing
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <ogcsys.h>
#include <network.h>
#include <ogc/lwp_watchdog.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <fcntl.h>
void debug_printf(const char *fmt, ...);
#include "http.h"
char *http_host;
u16 http_port;
char *http_path;
u32 http_max_size;
http_res result;
u32 http_status;
u32 content_length;
u8 *http_data;
s32 tcp_socket (void) {
s32 s, res;
s = net_socket (PF_INET, SOCK_STREAM, 0);
if (s < 0) {
debug_printf ("net_socket failed: %d\n", s);
return s;
}
res = net_fcntl (s, F_GETFL, 0);
if (res < 0) {
debug_printf ("F_GETFL failed: %d\n", res);
net_close (s);
return res;
}
res = net_fcntl (s, F_SETFL, res | 4);
if (res < 0) {
debug_printf ("F_SETFL failed: %d\n", res);
net_close (s);
return res;
}
return s;
}
s32 tcp_connect (char *host, const u16 port) {
struct hostent *hp;
struct sockaddr_in sa;
s32 s, res;
s64 t;
hp = net_gethostbyname (host);
if (!hp || !(hp->h_addrtype == PF_INET)) {
debug_printf ("net_gethostbyname failed: %d\n", errno);
return errno;
}
s = tcp_socket ();
if (s < 0)
return s;
memset (&sa, 0, sizeof (struct sockaddr_in));
sa.sin_family= PF_INET;
sa.sin_len = sizeof (struct sockaddr_in);
sa.sin_port= htons (port);
memcpy ((char *) &sa.sin_addr, hp->h_addr_list[0], hp->h_length);
t = gettime ();
while (true) {
if (ticks_to_millisecs (diff_ticks (t, gettime ())) >
TCP_CONNECT_TIMEOUT) {
debug_printf ("tcp_connect timeout\n");
net_close (s);
return -ETIMEDOUT;
}
res = net_connect (s, (struct sockaddr *) &sa,
sizeof (struct sockaddr_in));
if (res < 0) {
if (res == -EISCONN)
break;
if (res == -EINPROGRESS || res == -EALREADY) {
usleep (20 * 1000);
continue;
}
debug_printf ("net_connect failed: %d\n", res);
net_close (s);
return res;
}
break;
}
return s;
}
char * tcp_readln (const s32 s, const u16 max_length, const u64 start_time, const u32 timeout) {
char *buf;
u16 c;
s32 res;
char *ret;
buf = (char *) malloc (max_length);
c = 0;
ret = NULL;
while (true) {
if (ticks_to_millisecs (diff_ticks (start_time, gettime ())) > timeout)
break;
res = net_read (s, &buf[c], 1);
if ((res == 0) || (res == -EAGAIN)) {
usleep (20 * 1000);
continue;
}
if (res < 0) {
debug_printf ("tcp_readln failed: %d\n", res);
break;
}
if ((c > 0) && (buf[c - 1] == '\r') && (buf[c] == '\n')) {
if (c == 1) {
ret = strdup ("");
break;
}
ret = strndup (buf, c - 1);
break;
}
c++;
if (c == max_length)
break;
}
free (buf);
return ret;
}
bool tcp_read (const s32 s, u8 **buffer, const u32 length) {
u8 *p;
u32 step, left, block, received;
s64 t;
s32 res;
step = 0;
p = *buffer;
left = length;
received = 0;
t = gettime ();
while (left) {
if (ticks_to_millisecs (diff_ticks (t, gettime ())) >
TCP_BLOCK_RECV_TIMEOUT) {
debug_printf ("tcp_read timeout\n");
break;
}
block = left;
if (block > (32*1024))
block = (32*1024);
res = net_read (s, p, block);
if ((res == 0) || (res == -EAGAIN)) {
usleep (20 * 1000);
continue;
}
if (res < 0) {
debug_printf ("net_read failed: %d\n", res);
break;
}
received += res;
left -= res;
p += res;
if ((received / TCP_BLOCK_SIZE) > step) {
t = gettime ();
step++;
}
}
return left == 0;
}
bool tcp_write (const s32 s, const u8 *buffer, const u32 length) {
const u8 *p;
u32 step, left, block, sent;
s64 t;
s32 res;
step = 0;
p = buffer;
left = length;
sent = 0;
t = gettime ();
while (left) {
if (ticks_to_millisecs (diff_ticks (t, gettime ())) >
TCP_BLOCK_SEND_TIMEOUT) {
debug_printf ("tcp_write timeout\n");
break;
}
block = left;
if (block > 2048)
block = 2048;
res = net_write (s, p, block);
if ((res == 0) || (res == -56)) {
usleep (20 * 1000);
continue;
}
if (res < 0) {
debug_printf ("net_write failed: %d\n", res);
break;
}
sent += res;
left -= res;
p += res;
if ((sent / TCP_BLOCK_SIZE) > step) {
t = gettime ();
step++;
}
}
return left == 0;
}
bool http_split_url (char **host, char **path, const char *url) {
const char *p;
char *c;
if (strncasecmp (url, "http://", 7))
return false;
p = url + 7;
c = strchr (p, '/');
if (c[0] == 0)
return false;
*host = strndup (p, c - p);
*path = strdup (c);
return true;
}
bool http_request (const char *url, const u32 max_size) {
int linecount;
if (!http_split_url(&http_host, &http_path, url)) return false;
http_port = 80;
http_max_size = max_size;
http_status = 404;
content_length = 0;
http_data = NULL;
int s = tcp_connect (http_host, http_port);
// debug_printf("tcp_connect(%s, %hu) = %d\n", http_host, http_port, s);
if (s < 0) {
result = HTTPR_ERR_CONNECT;
return false;
}
char *request = (char *) malloc (1024);
char *r = request;
r += sprintf (r, "GET %s HTTP/1.1\r\n", http_path);
r += sprintf (r, "Host: %s\r\n", http_host);
r += sprintf (r, "Cache-Control: no-cache\r\n\r\n");
// debug_printf("request = %s\n", request);
bool b = tcp_write (s, (u8 *) request, strlen (request));
// debug_printf("tcp_write returned %d\n", b);
free (request);
linecount = 0;
for (linecount=0; linecount < 32; linecount++) {
char *line = tcp_readln (s, 0xff, gettime(), HTTP_TIMEOUT);
// debug_printf("tcp_readln returned %p (%s)\n", line, line?line:"(null)");
if (!line) {
http_status = 404;
result = HTTPR_ERR_REQUEST;
break;
}
if (strlen (line) < 1) {
free (line);
line = NULL;
break;
}
sscanf (line, "HTTP/1.1 %u", &http_status);
sscanf (line, "Content-Length: %u", &content_length);
free (line);
line = NULL;
}
// debug_printf("content_length = %d, status = %d, linecount = %d\n", content_length, http_status, linecount);
if (linecount == 32 || !content_length) http_status = 404;
if (http_status != 200) {
result = HTTPR_ERR_STATUS;
net_close (s);
return false;
}
if (content_length > http_max_size) {
result = HTTPR_ERR_TOOBIG;
net_close (s);
return false;
}
http_data = (u8 *) malloc (content_length);
b = tcp_read (s, &http_data, content_length);
if (!b) {
free (http_data);
http_data = NULL;
result = HTTPR_ERR_RECEIVE;
net_close (s);
return false;
}
result = HTTPR_OK;
net_close (s);
return true;
}
bool http_get_result (u32 *_http_status, u8 **content, u32 *length) {
if (http_status) *_http_status = http_status;
if (result == HTTPR_OK) {
*content = http_data;
*length = content_length;
} else {
*content = NULL;
*length = 0;
}
free (http_host);
free (http_path);
return true;
}

32
cios_installer/http.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef _HTTP_H_
#define _HTTP_H_
#include <gctypes.h>
#define TCP_CONNECT_TIMEOUT 10000
#define TCP_BLOCK_SIZE (8 * 1024)
#define TCP_BLOCK_RECV_TIMEOUT 10000
#define TCP_BLOCK_SEND_TIMEOUT 10000
s32 tcp_socket (void);
s32 tcp_connect (char *host, const u16 port);
char * tcp_readln (const s32 s, const u16 max_length, const u64 start_time, const u32 timeout);
bool tcp_read (const s32 s, u8 **buffer, const u32 length);
bool tcp_write (const s32 s, const u8 *buffer, const u32 length);
#define HTTP_TIMEOUT 300000
typedef enum {
HTTPR_OK,
HTTPR_ERR_CONNECT,
HTTPR_ERR_REQUEST,
HTTPR_ERR_STATUS,
HTTPR_ERR_TOOBIG,
HTTPR_ERR_RECEIVE
} http_res;
bool http_request (const char *url, const u32 max_size);
bool http_get_result (u32 *http_status, u8 **content, u32 *length);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
// Basic I/O.
static inline u32 read32(u32 addr)
{
u32 x;
asm volatile("lwz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr));
return x;
}
static inline void write32(u32 addr, u32 x)
{
asm("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr));
}
// USB Gecko.
void usb_flush(int chn);
int usb_sendbuffer(int chn,const void *buffer,int size);
// Version string.
extern const char version[];
// Debug: blink the tray led.
static inline void blink(void)
{
write32(0x0d8000c0, read32(0x0d8000c0) ^ 0x20);
}
void debug_printf(const char *fmt, ...);
void hexdump(void *d, int len);
void aes_set_key(u8 *key);
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len);
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len);
#define TRACE(x) debug_printf("%s / %d: %d\n", __FUNCTION__, __LINE__, (x))
#define ISFS_ACCESS_READ 1
#define ISFS_ACCESS_WRITE 2

View File

@ -0,0 +1,60 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
//#define OH0_REPL
#ifdef OH0_REPL
#include "oh0_elf.h"
#endif
struct ios_module_replacement
{
char *name;
u8 *data;
u32 *size;
};
struct ios_module_replacement ios_repls[]={
#ifdef OH0_REPL
{"OH0",(u8*)oh0_elf,(u32*)&oh0_elf_size}
#endif
};
void debug_printf(const char *fmt, ...);
int replace_ios_modules(u8 **decrypted_buf, u32 *content_size)
{
int i,version;
u32 len;
u8*buf = *decrypted_buf;
char *ios_version_tag = "$IOSVersion:";
len = *content_size;
if (len == 64)
return 0;
version =0;
for (i=0; i<(len-64); i++)
if (!strncmp((char *)buf+i, ios_version_tag, 10)) {
version = i;
break;
}
for (i=0;i<sizeof(ios_repls)/sizeof(ios_repls[0]); i++){
struct ios_module_replacement *repl = &ios_repls[i];
if(!memcmp(buf+version+13,repl->name,strlen(repl->name)))
{
debug_printf("replaced %s\n",repl->name);
free(*decrypted_buf);
len = *repl->size;
len+=31;
len&=~31;
*decrypted_buf = malloc(len);
memcpy(*decrypted_buf,repl->data,len);
*content_size = len;
return 1;
}
}
return 0;
}

398
cios_installer/rijndael.c Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#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<nb;j++,m+=3)
{
fi[m]=(j+C1)%nb;
fi[m+1]=(j+C2)%nb;
fi[m+2]=(j+C3)%nb;
ri[m]=(nb+j-C1)%nb;
ri[m+1]=(nb+j-C2)%nb;
ri[m+2]=(nb+j-C3)%nb;
}
N=Nb*(Nr+1);
for (i=j=0;i<Nk;i++,j+=4)
{
CipherKey[i]=pack((u8 *)&key[j]);
}
for (i=0;i<Nk;i++) fkey[i]=CipherKey[i];
for (j=Nk,k=0;j<N;j+=Nk,k++)
{
fkey[j]=fkey[j-Nk]^SubByte(ROTL24(fkey[j-1]))^rco[k];
if (Nk<=6)
{
for (i=1;i<Nk && (i+j)<N;i++)
fkey[i+j]=fkey[i+j-Nk]^fkey[i+j-1];
}
else
{
for (i=1;i<4 &&(i+j)<N;i++)
fkey[i+j]=fkey[i+j-Nk]^fkey[i+j-1];
if ((j+4)<N) fkey[j+4]=fkey[j+4-Nk]^SubByte(fkey[j+3]);
for (i=5;i<Nk && (i+j)<N;i++)
fkey[i+j]=fkey[i+j-Nk]^fkey[i+j-1];
}
}
/* now for the expanded decrypt key in reverse order */
for (j=0;j<Nb;j++) rkey[j+N-Nb]=fkey[j];
for (i=Nb;i<N-Nb;i+=Nb)
{
k=N-Nb-i;
for (j=0;j<Nb;j++) rkey[k+j]=InvMixCol(fkey[i+j]);
}
for (j=N-Nb;j<N;j++) rkey[j-N+Nb]=fkey[j];
}
/* There is an obvious time/space trade-off possible here. *
* Instead of just one ftable[], I could have 4, the other *
* 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
void encrypt(char *buff)
{
int i,j,k,m;
u32 a[8],b[8],*x,*y,*t;
for (i=j=0;i<Nb;i++,j+=4)
{
a[i]=pack((u8 *)&buff[j]);
a[i]^=fkey[i];
}
k=Nb;
x=a; y=b;
/* State alternates between a and b */
for (i=1;i<Nr;i++)
{ /* Nr is number of rounds. May be odd. */
/* if Nb is fixed - unroll this next
loop and hard-code in the values of fi[] */
for (m=j=0;j<Nb;j++,m+=3)
{ /* deal with each 32-bit element of the State */
/* This is the time-critical bit */
y[j]=fkey[k++]^ftable[(u8)x[j]]^
ROTL8(ftable[(u8)(x[fi[m]]>>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<Nb;j++,m+=3)
{
y[j]=fkey[k++]^(u32)fbsub[(u8)x[j]]^
ROTL8((u32)fbsub[(u8)(x[fi[m]]>>8)])^
ROTL16((u32)fbsub[(u8)(x[fi[m+1]]>>16)])^
ROTL24((u32)fbsub[x[fi[m+2]]>>24]);
}
for (i=j=0;i<Nb;i++,j+=4)
{
unpack(y[i],(u8 *)&buff[j]);
x[i]=y[i]=0; /* clean up stack */
}
return;
}
void decrypt(char *buff)
{
int i,j,k,m;
u32 a[8],b[8],*x,*y,*t;
for (i=j=0;i<Nb;i++,j+=4)
{
a[i]=pack((u8 *)&buff[j]);
a[i]^=rkey[i];
}
k=Nb;
x=a; y=b;
/* State alternates between a and b */
for (i=1;i<Nr;i++)
{ /* Nr is number of rounds. May be odd. */
/* if Nb is fixed - unroll this next
loop and hard-code in the values of ri[] */
for (m=j=0;j<Nb;j++,m+=3)
{ /* This is the time-critical bit */
y[j]=rkey[k++]^rtable[(u8)x[j]]^
ROTL8(rtable[(u8)(x[ri[m]]>>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<Nb;j++,m+=3)
{
y[j]=rkey[k++]^(u32)rbsub[(u8)x[j]]^
ROTL8((u32)rbsub[(u8)(x[ri[m]]>>8)])^
ROTL16((u32)rbsub[(u8)(x[ri[m+1]]>>16)])^
ROTL24((u32)rbsub[x[ri[m+2]]>>24]);
}
for (i=j=0;i<Nb;i++,j+=4)
{
unpack(y[i],(u8 *)&buff[j]);
x[i]=y[i]=0; /* clean up stack */
}
return;
}
void aes_set_key(u8 *key) {
gentables();
gkey(4, 4,(void*) key);
}
// CBC mode decryption
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
u8 block[16];
unsigned int blockno = 0, i;
// debug_printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) {
unsigned int fraction;
if (blockno == (len / sizeof(block))) { // last block
fraction = len % sizeof(block);
if (fraction == 0) break;
memset((void *) block, 0, sizeof(block));
} else fraction = 16;
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
memcpy((void *) block, inbuf + blockno * sizeof(block), fraction);
decrypt((void *) block);
u8 *ctext_ptr;
if (blockno == 0) ctext_ptr = iv;
else ctext_ptr = inbuf + (blockno-1) * sizeof(block);
for(i=0; i < fraction; i++)
outbuf[blockno * sizeof(block) + i] =
ctext_ptr[i] ^ block[i];
// debug_printf("Block %d output: ", blockno);
// hexdump(outbuf + blockno*sizeof(block), 16);
}
}
// CBC mode encryption
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len) {
u8 block[16];
unsigned int blockno = 0, i;
// debug_printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) {
unsigned int fraction;
if (blockno == (len / sizeof(block))) { // last block
fraction = len % sizeof(block);
if (fraction == 0) break;
memset((void *) block, 0, sizeof(block));
} else fraction = 16;
// debug_printf("block %d: fraction = %d\n", blockno, fraction);
memcpy(block, inbuf + blockno * sizeof(block), fraction);
for(i=0; i < fraction; i++)
block[i] = inbuf[blockno * sizeof(block) + i] ^ iv[i];
encrypt((void *) block);
memcpy(iv, block, sizeof(block));
memcpy(outbuf + blockno * sizeof(block), block, sizeof(block));
// debug_printf("Block %d output: ", blockno);
// hexdump(outbuf + blockno*sizeof(block), 16);
}
}

View File

@ -0,0 +1,78 @@
// Copyright 2010 Joseph Jordan <joe.ftpii@psychlaw.com.au>
// This code is licensed to you under the terms of the GNU GPL, version 2;
// see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
// Some modifications taken from dop-mii. Credits to them
#include <gccore.h>
#include <ogc/machine/processor.h>
#include <string.h>
#include <stdio.h>
#include "runtime_ios_patch.h"
#define MEM_REG_BASE 0xd8b4000
#define MEM_PROT (MEM_REG_BASE + 0x20a)
static void disable_memory_protection() {
write32(MEM_PROT, read32(MEM_PROT) & 0x0000FFFF);
}
static u32 apply_patch(char *name, const u8 *old, u32 old_size, const u8 *patch, u32 patch_size, u32 patch_offset) {
u8 *ptr = (u8 *)0x93400000;
u32 found = 0;
u8 *location = NULL;
while ((u32)ptr < (0x94000000 - patch_size)) {
if (!memcmp(ptr, old, old_size)) {
found++;
location = ptr + patch_offset;
u8 *start = location;
u32 i;
for (i = 0; i < patch_size; i++) {
*location++ = patch[i];
}
DCFlushRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64);
ICInvalidateRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64);
}
ptr++;
}
if (found) {
printf("\b..");
} else {
printf("\b!.");
}
return found;
}
static const u8 di_readlimit_old[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0A, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x7E, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08
};
static const u8 di_readlimit_patch[] = { 0x7e, 0xd4 };
const u8 isfs_permissions_old[] = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 };
const u8 isfs_permissions_patch[] = { 0x42, 0x8B, 0xE0, 0x01, 0x25, 0x66 };
static const u8 setuid_old[] = { 0xD1, 0x2A, 0x1C, 0x39 };
static const u8 setuid_patch[] = { 0x46, 0xC0 };
const u8 es_identify_old[] = { 0x28, 0x03, 0xD1, 0x23 };
const u8 es_identify_patch[] = { 0x00, 0x00 };
const u8 hash_old[] = { 0x20, 0x07, 0x23, 0xA2 };
const u8 hash_patch[] = { 0x00 };
const u8 new_hash_old[] = { 0x20, 0x07, 0x4B, 0x0B };
u32 IOSPATCH_Apply() {
printf("\n\n");
u32 count = 0;
if (HAVE_AHBPROT) {
disable_memory_protection();
count += apply_patch("di_readlimit", di_readlimit_old, sizeof(di_readlimit_old), di_readlimit_patch, sizeof(di_readlimit_patch), 12);
count += apply_patch("isfs_permissions", isfs_permissions_old, sizeof(isfs_permissions_old), isfs_permissions_patch, sizeof(isfs_permissions_patch), 0);
count += apply_patch("es_setuid", setuid_old, sizeof(setuid_old), setuid_patch, sizeof(setuid_patch), 0);
count += apply_patch("es_identify", es_identify_old, sizeof(es_identify_old), es_identify_patch, sizeof(es_identify_patch), 2);
count += apply_patch("hash_check", hash_old, sizeof(hash_old), hash_patch, sizeof(hash_patch), 1);
count += apply_patch("new_hash_check", new_hash_old, sizeof(new_hash_old), hash_patch, sizeof(hash_patch), 1);
}
return count;
}

View File

@ -0,0 +1,14 @@
// Copyright 2010 Joseph Jordan <joe.ftpii@psychlaw.com.au>
// This code is licensed to you under the terms of the GNU GPL, version 2;
// see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#ifndef __RUNTIMEIOSPATCH_H
#define __RUNTIMEIOSPATCH_H
#include <gccore.h>
#define HAVE_AHBPROT ((*(vu32*)0xcd800064 == 0xFFFFFFFF) ? 1 : 0)
u32 IOSPATCH_Apply();
#endif

172
cios_installer/sha1.c Normal file
View File

@ -0,0 +1,172 @@
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
#define SHA1HANDSOFF
#include <stdio.h>
#include <string.h>
#include "sha1.h"
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifdef LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
{
unsigned long a, b, c, d, e;
typedef union {
unsigned char c[64];
unsigned long l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
static unsigned char workspace[64];
block = (CHAR64LONG16*)workspace;
memcpy(block, buffer, 64);
#else
block = (CHAR64LONG16*)buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context */
void SHA1Init(SHA1_CTX* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
{
unsigned int i, j;
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
{
unsigned long i, j;
unsigned char finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
SHA1Update(context, (unsigned char *)"\200", 1);
while ((context->count[0] & 504) != 448) {
SHA1Update(context, (unsigned char *)"\0", 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++) {
digest[i] = (unsigned char)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
/* Wipe variables */
i = j = 0;
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(&finalcount, 0, 8);
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
SHA1Transform(context->state, context->buffer);
#endif
}
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
SHA1_CTX ctx;
SHA1Init(&ctx);
SHA1Update(&ctx, ptr, size);
SHA1Final(outbuf, &ctx);
}

12
cios_installer/sha1.h Normal file
View File

@ -0,0 +1,12 @@
typedef struct {
unsigned long state[5];
unsigned long count[2];
unsigned char buffer[64];
} SHA1_CTX;
void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
void SHA1Init(SHA1_CTX* context);
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf);

View File

@ -0,0 +1,114 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <stdarg.h>
#include <ctype.h>
#include <unistd.h>
#include <network.h>
#include <sys/errno.h>
#include <wiiuse/wpad.h>
#include "patchmii_core.h"
#include "sha1.h"
#include "debug.h"
#include "http.h"
//#include "haxx_certs.h"
#include <fat.h>
//#include "ehc_elf.h"
#include "mload_elf.h"
//#define ADD_EHC
#define ADD_HAXX // active this if you want to play with starlet without installing 50 times an hour
//#define REMOVE_OH0
u32 save_nus_object (u16 index, u8 *buf, u32 size);
/* add module inside the tmd
take care of alignement.
*/
extern int INPUT_TITLEID_L;
void tmd_add_module(tmd *p_tmd,const u8 *elf, u32 elf_size)
{
int ncid;
int i,found=0;
tmd_content *p_cr = (tmd_content *)TMD_CONTENTS(p_tmd);
sha1 hash;
int content_size = (elf_size+31)&~31;
u8 *buf = memalign(32,content_size);
int index = p_tmd->num_contents;
memset((void *) buf,0,content_size);
memcpy((void *) buf,elf,elf_size);
ncid = 10;
while(!found){
found = 1;
ncid++;
for (i=0;i<p_tmd->num_contents;i++) {
if(p_cr[i].cid == ncid){ found = 0;break;}
}
}
debug_printf("found a free cid: %x\n",ncid);
p_cr[index].cid = ncid;
p_cr[index].type = 0x0001; // shared is 0x8001
p_cr[index].size = content_size;
p_cr[index].index = index;
//calc sha
SHA1(buf, content_size, hash);
memcpy(p_cr[index].hash, hash, sizeof hash);
p_tmd->num_contents++;
save_nus_object(ncid, buf, content_size);
}
int add_custom_modules(tmd *p_tmd)
{
tmd_content tmp;
int tmd_dirty=0;
tmd_content *p_cr = (tmd_content *)TMD_CONTENTS(p_tmd);
#ifdef REMOVE_OH0 // remove oh0 module
{
int i;
debug_printf("removing cid %d\n",p_cr[2].cid);
memmove(&p_cr[2],&p_cr[3],p_tmd->num_contents*sizeof(tmd_content)-2);
p_tmd->num_contents--;
for (i=0;i<p_tmd->num_contents;i++)
p_cr[i].index = i;
tmd_dirty = 1;
}
#endif
#ifdef ADD_EHC
/* add ehc module. We need it installed before OH0 and OH1, because IOS loads it in the order of the tmd.
for some reason, we cant shift all indexes or the IOS_Reload will crashed without saying anything.
*/
debug_printf("adding EHC module\n");
tmd_add_module(p_tmd,ehc_elf,ehc_elf_size);
tmp = p_cr[3]; // inverse ehc and oh0 place in tmd
p_cr[3] = p_cr[p_tmd->num_contents-1];
p_cr[p_tmd->num_contents-1] = tmp;
tmd_dirty = 1;
#endif
#ifdef ADD_HAXX
/*add haxx module. We need it installed before OH0 and OH1, because IOS loads it in the order of the tmd.
for some reason, we cant shift all indexes or the IOS_Reload will crashed without saying anything.
*/
debug_printf("adding haxx module\n");
tmd_add_module(p_tmd,mload_elf,mload_elf_size);
tmp = p_cr[3-(INPUT_TITLEID_L==57)]; // inverse ehc and oh0 place in tmd
p_cr[3-(INPUT_TITLEID_L==57)] = p_cr[p_tmd->num_contents-1];
p_cr[p_tmd->num_contents-1] = tmp;
tmd_dirty = 1;
#endif
return tmd_dirty;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,3 @@
---- port = Matches (2 in 2 files) ----
Ehci.c (c:\devkitpro\soft\uloader_v2.6\cios_mload\tinyehci): dev->port = i;
Ehci1.c (c:\devkitpro\soft\uloader_v2.6\cios_mload\tinyehci): dev->port = i;

4
ehcmodule/MakeIt.bat Normal file
View File

@ -0,0 +1,4 @@
make
pause

144
ehcmodule/Makefile Normal file
View File

@ -0,0 +1,144 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source ../libcios/source ../wii_wbfs
DATA := data
INCLUDES := include ../tinyehci ../libcios/include ../wii_wbfs
SCRIPTDIR := scripts
BIN := bin
STRIPIOS := ../stripios/stripios.exe
LIBS :=
LIBDIRS :=
export IOS_MODULE=ehc
CFLAGS+=-D$(IOS_MODULE) $(DEBUG)
#---------------------------------------------------------------------------------
# the prefix on the compiler executables
#---------------------------------------------------------------------------------
#$(DEVKITARM)/bin/
PREFIX := $(DEVKITARM)/bin/arm-eabi-
CC := $(PREFIX)gcc
CXX := $(PREFIX)g++
AR := $(PREFIX)ar
OBJCOPY := $(PREFIX)objcopy
LD := $(PREFIX)g++
AS := $(PREFIX)g++
#---------------------------------------------------------------------------------
# linker script
#---------------------------------------------------------------------------------
LINKSCRIPT := $(ROOT)/$(SCRIPTDIR)/link.ld
SPECS := $(ROOT)/$(SCRIPTDIR)/nostart.specs
ifeq ($(BUILDING),$(emptystring))
export ROOT := $(CURDIR)
all:
@[ -d $(BUILD) ] || mkdir -p $(BUILD)
@$(MAKE) -C $(BUILD) --no-print-directory -f $(CURDIR)/Makefile BUILDING=all
clean:
@echo clean ...
@rm -fr $(BUILD) $(BIN)/*.elf
else
TARGET := $(notdir $(ROOT))
STRIPIOS := $(ROOT)/$(STRIPIOS)
#----------------------------------------------------
# MS Visual Studio Style Fix:
#----------------------------------------------------
#STYLEFIX = 2>&1 | sed -e 's/\([a-zA-Z\.]\+\):\([0-9]\+\):\([0-9]\+:\)\?\(.\+\)/\1(\2):\4/' -e 's/undefined/error: undefined/'
STYLEFIX ?=
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
OUTPUT := $(ROOT)/$(BIN)/$(TARGET)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(ROOT)/$(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(ROOT)/$(dir)/*.*)))
OFILES := $(addsuffix _bin.o,$(BINFILES)) \
$(CPPFILES:.cpp=_cpp.o) $(CFILES:.c=_c.o) \
$(sFILES:.s=_s.o) $(SFILES:.S=_S.o)
DEPENDS := $(OFILES:.o=.d)
VPATH = $(foreach dir,$(SOURCES),$(ROOT)/$(dir))
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
INCLUDE := $(foreach dir,$(INCLUDES),-I$(ROOT)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(ROOT)/$(BUILD)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ARCH = -mcpu=arm9tdmi -mtune=arm9tdmi -mthumb -mthumb-interwork -mbig-endian
CFLAGS += $(ARCH) $(INCLUDE) -fno-strict-aliasing -Wall -Os -fomit-frame-pointer -ffast-math -fverbose-asm -Wpointer-arith -Winline -Wundef -g -ffunction-sections -fdata-sections -fno-exceptions
CFLAGS += -Wstrict-prototypes
AFLAGS = $(ARCH) -x assembler-with-cpp
LDFLAGS = $(ARCH) -specs=$(SPECS) -T$(LINKSCRIPT) $(LIBPATHS) $(LIBS) -Wl,--gc-sections -Wl,-static -Wl,-Map,$(TARGET).map -nostartfiles
$(OUTPUT).elf: $(TARGET).elf
@echo stripping $(notdir $@)
@$(STRIPIOS) $< $@
%.elf: $(OFILES)
@echo linking $(notdir $@)
@$(LD) -o $@ $(OFILES) $(LDFLAGS) $(STYLEFIX)
%_cpp.o : %.cpp
@echo $(notdir $<)
@$(CXX) -MMD -MF $*_cpp.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
%_c.o : %.c
@echo $(notdir $<)
@$(CC) -MMD -MF $*_c.d $(CFLAGS) -c $< -o$@ $(STYLEFIX)
%_s.o : %.s
@echo $(notdir $<)
@$(AS) -MMD -MF $*_s.d $(AFLAGS) -c $< -o$@ $(STYLEFIX)
%_bin.o : %.bin
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
define bin2o
@echo -e "\t.section .rodata\n\t.align 4\n\t.global $(*)\n\t.global $(*)_end\n$(*):\n\t.incbin \"$(subst /,\\\\\\\\,$(shell echo $< | sed 's=/==;s=/=:/='))\"\n$(*)_end:\n" > $@.s
@$(CC) $(ASFLAGS) $(AFLAGS) -c $@.s -o $@
@rm -rf $@.s
endef
endif

13
ehcmodule/bin/convert.bat Normal file
View File

@ -0,0 +1,13 @@
del *.c
del *.h
filetochar ehcmodule.elf ehcmodule_5 -h -align 32
del C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.c
del C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.h
copy ehcmodule_5.c C:\devkitPro\soft\usbloader\source\mload\modules\
copy ehcmodule_5.h C:\devkitPro\soft\usbloader\source\mload\modules\
touch C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.c
touch C:\devkitPro\soft\usbloader\source\mload\modules\ehcmodule_5.h

BIN
ehcmodule/bin/ehcmodule.elf Normal file

Binary file not shown.

BIN
ehcmodule/bin/ehcmodule.rar Normal file

Binary file not shown.

View File

@ -1,3 +1,3 @@
#define size_ehcmodule_5 25776
extern unsigned char ehcmodule_5[25776];
#define size_ehcmodule_5 25776
extern unsigned char ehcmodule_5[25776];

Binary file not shown.

View File

@ -0,0 +1,30 @@
#ifndef LIBWBFS_OS_H
#define LIBWBFS_OS_H
// libwbfs_os.h for ehc module env
#include "syscalls.h"
#include "ehci_types.h"
#include "ehci.h"
void *WBFS_Alloc(int size);
void WBFS_Free(void *ptr);
void my_sprint(char *cad, char *s);
#define wbfs_fatal(x) do{os_puts("wbfs panic ");os_puts(x);os_puts("\n"); while(1) ehci_msleep(100);}while(0)
#define wbfs_error(x) do{os_puts("wbfs error ");os_puts(x);;os_puts("\n");}while(0)
#define wbfs_malloc(x) WBFS_Alloc(x)
#define wbfs_free(x) WBFS_Free(x)
#define wbfs_ioalloc(x) WBFS_Alloc(x)
#define wbfs_iofree(x) WBFS_Free(x)
#define wbfs_ntohl(x) (x)
#define wbfs_htonl(x) (x)
#define wbfs_ntohs(x) (x)
#define wbfs_htons(x) (x)
#include <string.h>
#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

View File

@ -0,0 +1,9 @@
#define swab32(x) ((u32)( \
(((u32)(x) & (u32)0x000000ffUL) << 24) | \
(((u32)(x) & (u32)0x0000ff00UL) << 8) | \
(((u32)(x) & (u32)0x00ff0000UL) >> 8) | \
(((u32)(x) & (u32)0xff000000UL) >> 24)))
#define swab16(x) ((u16)( \
(((u16)(x) & (u16)0x00ffU) << 8) | \
(((u16)(x) & (u16)0xff00U) >> 8)))

8
ehcmodule/m.bat Normal file
View File

@ -0,0 +1,8 @@
make
if not %errorlevel% == 0 goto end
@echo off
cd bin
call convert.bat
cd ..
:end

50
ehcmodule/scripts/link.ld Normal file
View File

@ -0,0 +1,50 @@
OUTPUT_FORMAT("elf32-bigarm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
/*
Change exe start and ram start as needed for the custom IOS module.
Current settings are for the EHC module from IOS 31. actually this is free space in this IOS
*/
MEMORY {
ios_info_table : ORIGIN = 0x0, LENGTH = 0x4000
exe(rwx) : ORIGIN = 0x13700000, LENGTH = 0x6000
ram(rw) : ORIGIN = 0x13706000, LENGTH = 0x2A000 /* END 0x13730000 */
}
__exe_start_virt__ = 0x13700000;
__exe_start_phys__ = 0x13700000;
__ram_start_virt__ = 0x13706000;
__ram_start_phys__ = 0x13706000;
__ios_info_table_start = 0x0;
SECTIONS
{
.debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .note.arm.ident 0 : { KEEP (*(.note.arm.ident)) }
.ios_info_table __ios_info_table_start : { . = .; KEEP (*(.ios_info_table)) } > ios_info_table
.init __exe_start_virt__ : AT (__exe_start_phys__) { . = .; KEEP (*(.init)) } > exe
.text ALIGN (0x20) : {
*(.text*)
*(.gnu.warning)
*(.gnu.linkonce.t.*)
*(.init)
*(.glue_7)
*(.glue_7t) } > exe
.data __ram_start_virt__ : AT (__ram_start_phys__) { KEEP( *(.ios_data) ) *(.data*) *(.data1) *(.gnu.linkonce.d.*) . = ALIGN (4); __CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.); __DTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.dtors*))) __DTOR_END__ = ABSOLUTE (.); *(.dynamic) *(.sdata*) *(.gnu.linkonce.s.*) . = ALIGN (4); *(.2ram.*) } > ram
.fini : { . = .; *(.fini) } > ram
.rodata ALIGN (0x4) : {
. = .;
*(.rodata*)
*(.gnu.linkonce.r.*) } > ram
.rodata1 ALIGN (0x4) : { . = .; *(.rodata1) } > ram
.fixup ALIGN (0x4) : { . = .; *(.fixup) } > ram
.gcc_except_table ALIGN (0x4) : { . = .; *(.gcc_except_table) } > ram
.got ALIGN (0x4) : { *(.got.plt) *(.got) } > ram
.bss ALIGN (0x20) : { *(.scommon) *(.dynsbss) *(.sbss*) *(.gnu.linkonce.sb.*) *(.dynbss) *(.bss*) *(.gnu.linkonce.b.*) *(COMMON) KEEP( *(.ios_bss) ) } > ram
. = ALIGN(4);
}

View File

@ -0,0 +1,2 @@
*startfile:
crti%O%s crtbegin%O%s

249
ehcmodule/source/crt0.s Normal file
View File

@ -0,0 +1,249 @@
/*
Custom IOS module for Wii.
Copyright (C) 2008 neimod.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
.section ".init"
.global _start
.align 4
.arm
/*******************************************************************************
*
* crt0.s - IOS module startup code
*
*******************************************************************************
*
*
* v1.0 - 26 July 2008 - initial release by neimod
* v1.1 - 5 September 2008 - prepared for public release
*
*/
.EQU ios_thread_arg, 4
.EQU ios_thread_priority, 0x78 //0x48
.EQU ios_thread_stacksize, 0x3000
_start:
/* Execute main program */
mov r0, #0 @ int argc
mov r1, #0 @ char *argv[]
ldr r3, =main
bx r3
.align 4
.code 32
.global direct_syscall
direct_syscall:
ldr r12, =syscall_base
ldr r12, [r12]
nop
ldr r12, [r12,r11,lsl#2]
nop
bx r12
.align 4
.code 32
.global direct_os_sync_before_read
direct_os_sync_before_read:
mov r11, #0x3f
b direct_syscall
.align 4
.code 32
.global direct_os_sync_after_write
direct_os_sync_after_write:
mov r11, #0x40
b direct_syscall
.global ic_invalidate
ic_invalidate:
mov r0, #0
mcr p15, 0, r0, c7, c5, 0
bx lr
// bypass to interrupt vector
.align 4
.code 32
.global interrupt_vector
interrupt_vector:
tst r8, #0x10
beq int_cont1
bic r8, r8, #0x10 // disable next EHCI treatment
mov r2, #0x10
str r2, [r7]
nop
mov r2, sp
nop
ldr sp, =_interrupt_stack
nop
stmfd sp!, {r1-r12,lr}
nop
bl _ehci_vector_
ldmfd sp!, {r1-r12,lr}
nop
mov sp, r2
tst r0, #0x1
beq int_cont1
nop
mov r0,#4
bl int_send_device_message
int_cont1:
tst r8, #0x1
beq patch2_timer_cont
// int timer
.global patch1_timer
patch1_timer:
ldr pc, =0xFFFF1E80
nop
.global patch2_timer_cont
patch2_timer_cont:
ldr pc, =0xFFFF1E9C
nop
.global int_send_device_message
int_send_device_message:
ldr pc, =0xFFFF1D44
nop
_ehci_vector_:
ldr r2,=ehci_vector
bx r2
.align 4
.code 32
.global read_access_perm
read_access_perm:
mrc p15, 0, r0,c3,c0
bx lr
.align 4
.code 32
.global write_access_perm
write_access_perm:
mcr p15, 0, r0,c3,c0
bx lr
.align 4
/*******************************************************************************
*
* DRIVER CONFIGURATION AREA
*
*******************************************************************************
*/
.string "EHC_CFG"
.long 0x12340001
.global initial_port
initial_port:
.byte 0x0
.global use_reset_bulk
use_reset_bulk:
.byte 0x0
/* force_flags 1 ->force GetMaxLun, 2-> force SetConfiguration */
.global force_flags
force_flags:
.byte 0x0
.global use_alternative_timeout
use_alternative_timeout:
.byte 0x0
.align
.pool
/*******************************************************************************
* IOS data section
*
* Basically, this is required for the program header not to be messed up
* The program header will only be generated correctly if there is "something"
* in the ram segment, this makes sure of that by placing a silly string there.
*******************************************************************************
*/
.section ".ios_data" ,"aw",%progbits
.ascii "IOS module"
/*******************************************************************************
* IOS bss section
*
* This contains the module's thread stack
*******************************************************************************
*/
.section ".ios_bss", "a", %nobits
.global ios_thread_stack_start
ios_thread_stack_start:
.space ios_thread_stacksize
.global ios_thread_stack /* stack decrements from high address.. */
ios_thread_stack:
.space 0x200
_interrupt_stack:
.section ".ios_info_table","ax",%progbits
/*******************************************************************************
* IOS info table section
*
* This contains the module's loader information
* The stripios tool will find this, and package it nicely for the IOS system
*******************************************************************************
*/
.global ios_info_table
ios_info_table:
.long 0x0
.long 0x28 @ numentries * 0x28
.long 0x6
.long 0xB
.long ios_thread_arg @ passed to thread entry func, maybe module id
.long 0x9
.long _start
.long 0x7D
.long ios_thread_priority
.long 0x7E
.long ios_thread_stacksize
.long 0x7F
.long ios_thread_stack
.pool
.end

885
ehcmodule/source/ehc_loop.c Normal file
View File

@ -0,0 +1,885 @@
/*
Custom IOS module for Wii.
OH0 message loop
Copyright (C) 2009 kwiirk.
Copyright (C) 2008 neimod.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*******************************************************************************
*
* oh0_loop.c - IOS module main code
* even if we are "ehc" driver, we still pretend to be "oh0"
* and implement "standard" ios oh0 usb api
*
*******************************************************************************
*
*/
#include <stdio.h>
#include <string.h>
#include "syscalls.h"
#include "ehci_types.h"
#include "ehci.h"
#include "utils.h"
#include "libwbfs.h"
#include "ehci_interrupt.h"
#undef ehci_writel
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
void ehci_usleep(int usec);
void ehci_msleep(int msec);
int ehci_release_externals_usb_ports(void);
void off_callback_hand(u32 flags);
int disable_ehc=0;
#undef NULL
#define NULL ((void *)0)
#define IOS_OPEN 0x01
#define IOS_CLOSE 0x02
#define IOS_IOCTL 0x06
#define IOS_IOCTLV 0x07
#define USB_IOCTL_CTRLMSG 0
#define USB_IOCTL_BLKMSG 1
#define USB_IOCTL_INTRMSG 2
#define USB_IOCTL_SUSPENDDEV 5
#define USB_IOCTL_RESUMEDEV 6
#define USB_IOCTL_GETDEVLIST 12
#define USB_IOCTL_DEVREMOVALHOOK 26
#define USB_IOCTL_DEVINSERTHOOK 27
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
#define USB_IOCTL_UMS_UMOUNT (UMS_BASE+0x10)
#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
#define USB_IOCTL_UMS_TESTMODE (UMS_BASE+0x81)
#define USB_IOCTL_UMS_OFF (UMS_BASE+0x82)
#define USB_IOCTL_SET_PORT (UMS_BASE+0x83)
#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
#define USB_IOCTL_WBFS_READ_DIRECT_DISC (WBFS_BASE+0x3)
#define USB_IOCTL_WBFS_STS_DISC (WBFS_BASE+0x4)
//#define USB_IOCTL_WBFS_SPEED_LIMIT (WBFS_BASE+0x80)
void USBStorage_Umount(void);
//#define DEVICE "/dev/usb/ehc"
#define DEVICE "/dev/usb123"
int verbose = 0;
#define ioctlv_u8(a) (*((u8*)(a).data))
#define ioctlv_u16(a) (*((u16*)(a).data))
#define ioctlv_u32(a) (*((u32*)(a).data))
#define ioctlv_len(a) (a).len
#define ioctlv_voidp(a) (a).data
wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition);
int USBStorage_DVD_Test(void);
#define WATCHDOG_TIMER 1000*1000*10
int test_mode=0;
char *parse_hex(char *base,int *val)
{
int v = 0,done=0;
char *ptr = base,c;
while(!done)
{
c = *ptr++;
if(c >= '0' && c <= '9')
v = v << 4 | (c-'0');
else if(c >= 'a' && c <= 'f')
v = v << 4 | (10+c-'a');
else if(c >= 'A' && c <= 'F')
v = v << 4 | (10+c-'A');
else
done = 1;
}
if(ptr==base+1)//only incremented once
return 0; //we did not found any hex numbers
*val = v;
return ptr-1;
}
/*
int parse_and_open_device(char *devname,int fd)
{
char *ptr = devname;
int vid,pid;
if (! (ptr = parse_hex(ptr,&vid)))
return -6;
if ( *ptr != '/' )
return -6;
ptr++;// skip /
if (! (ptr = parse_hex(ptr,&pid)))
return -6;
if ( *ptr != '\0' )
return -6;
return ehci_open_device(vid,pid,fd);
}
*/
int DVD_speed_limit=0; // ingame it can fix x6 speed
int watchdog_enable=1;
// special ingame
int wbfs_disc_read2(wbfs_disc_t*d,u32 offset, u8 *data, u32 len);
// heap space for WBFS and queue
extern int heaphandle;
void msleep(int msec);
u8 mem_sector[4096] __attribute__ ((aligned (32)));
void *WBFS_Alloc(int size)
{
void * ret = 0;
// ret= os_heap_alloc(heaphandle, size);
ret= os_heap_alloc_aligned(heaphandle, size, 32);
if(ret==0)
{debug_printf("WBFS not enough memory! need %d\n",size);
os_puts("WBFS not enough memory!\n");
while(1) {swi_mload_led_on();ehci_msleep(200);swi_mload_led_off();ehci_msleep(200);}
}
return ret;
}
void WBFS_Free(void *ptr)
{
return os_heap_free(heaphandle, ptr);
}
extern u8 *disc_buff;
u32 last_disc_lba=0;
u32 current_disc_lba=0xffffffff;
void wbfs_perform_disc(void);
// CISO mem area
int ciso_lba=-1;
int ciso_size=0;
u32 table_lba[2048];
u8 mem_index[2048] __attribute__ ((aligned (32)));
// offset -> disc_offset in words
// data -> buffer
// len -> len to read in bytes
int WBFS_direct_disc_read(u32 offset, u8 *data, u32 len)
{
int r=true;
u32 lba;
u32 len2=len;
u8* data2=data;
u32 sec_size;
int l;
u8 *buff;
os_sync_after_write(data2, len2);
if(!disc_buff) return 0x8000;
last_disc_lba= USBStorage_Get_Capacity(&sec_size);
if(last_disc_lba==0 || sec_size!=2048)
{
current_disc_lba=0xffffffff;
return 0x8000;
}
if(ciso_lba>=0 && ciso_lba!=0x7fffffff && current_disc_lba==0xffffffff)
{
u32 lba_glob;
current_disc_lba=0xffffffff;
while(1)
{
lba_glob=ciso_lba+16;
buff=(u8 *) (((u32)disc_buff+31) & ~31); // 32 bytes aligment
r=USBStorage_Read_Sectors(ciso_lba, 16, buff); // read 16 cached sectors
if(!r) return 0x8000;
if((buff[0]=='C' && buff[1]=='I' && buff[2]=='S' && buff[3]=='O')) ciso_lba=0x7fffffff;
else
{
if(ciso_lba!=0) {ciso_lba=0;continue;}
ciso_lba=-1;
}
break;
}
ciso_size=(((u32)buff[4])+(((u32)buff[5])<<8)+(((u32)buff[6])<<16)+(((u32)buff[7])<<24))/2048;
memset(mem_index,0,2048);
if(ciso_lba==0x7fffffff)
for(l=0;l<16384;l++)
{
if((l & 7)==0) table_lba[l>>3]=lba_glob;
if(buff[8+l])
{
mem_index[l>>3]|=1<<(l & 7);
lba_glob+=ciso_size;
}
}
}
buff=(u8 *) (((u32)disc_buff+31) & ~31); // 32 bytes aligment
while(len>0)
{
lba=offset>>9; // offset to LBA (sector have 512 words)
if((lba & ~15)!=current_disc_lba)
{
u32 read_lba;
current_disc_lba=(lba & ~15);
read_lba=current_disc_lba;
if(ciso_lba==0x7fffffff)
{
u32 temp=current_disc_lba/ciso_size;
read_lba=table_lba[temp>>3];
for(l=0;l<(temp & 7);l++) if((mem_index[temp>>3]>>l) & 1) read_lba+=ciso_size;
read_lba+=current_disc_lba & (ciso_size-1);
}
l=(last_disc_lba-read_lba/*current_disc_lba*/);if(l>16) l=16;
if(l<16) memset(buff,0,0x8000);
if(l>0)
{
r=USBStorage_Read_Sectors(/*current_disc_lba*/read_lba, l, buff); // read 16 cached sectors
if(!r) break;
}
}
l=0x8000-((offset & 8191)<<2); // get max size in the cache relative to offset
if(l>len) l=len;
memcpy(data, &buff[((offset & 8191)<<2)], l);
os_sync_after_write(data, l);
data+=l;
len-=l;
offset+=l>>2;
}
if(!r) return 0x8000;
os_sync_before_read(data2, len2);
return 0;
}
extern int unplug_device;
int unplug_procedure(void);
extern int is_watchdog_read_sector;
extern u32 n_sec,sec_size;
u32 last_sector=0;
void direct_os_sync_before_read(void* ptr, int size);
void direct_os_sync_after_write(void* ptr, int size);
u32 read_access_perm(void);
void write_access_perm(u32 flags);
/******************************************************************************************************************************************************/
// dev/di ioctl os_message_queue_receive
/******************************************************************************************************************************************************/
int swi_di_queue(u32 cmd, ipcmessage *message)
{
u32 perm;
perm=read_access_perm();
write_access_perm(0xffffffff);
message->ioctl.command=cmd;
*((u32 *) message->ioctl.buffer_in)=cmd<<24;
direct_os_sync_after_write(&message->ioctl.command,4);
direct_os_sync_after_write(message->ioctl.buffer_in,4);
write_access_perm(perm);
return 0;
}
int my_di_os_message_queue_receive(int queuehandle, ipcmessage ** message,int flag)
{
int ret,ret2;
ret= os_message_queue_receive(queuehandle, (void*) message, flag);
if(ret==0 && message && *message)
{
if((*message)->command==IOS_IOCTL)
{
switch((*message)->ioctl.command)
{
case 0x7a:
ret2=swi_mload_call_func((void *) swi_di_queue, (void *) 0x15, (void *) (*message));
break;
case 0x88:
ret2=swi_mload_call_func((void *) swi_di_queue, (void *) 0x14, (void *) (*message));
break;
}
}
}
return ret;
}
/******************************************************************************************************************************************************/
// ehcmodule swi service
/******************************************************************************************************************************************************/
void release_wbfs_mem(void);
int swi_ehcmodule(u32 cmd, u32 param1, u32 param2, u32 param3)
{
s32 ret=-666;
switch(cmd)
{
case 0: // get mem alloc handle (139264 bytes heap)
ret=heaphandle;
break;
case 1: // obtain release_wbfs_mem() function to be sure you have free memory
ret=(int) release_wbfs_mem;
break;
case 2:
ret=0;disable_ehc=1; // disable ehcmodule device for direct access operations
break;
case 16: // get USBStorage_Read_Sectors() for direct operations (remember you disable_ehc must be 1)
ret= (int) USBStorage_Read_Sectors;
break;
case 17:
ret= (int) USBStorage_Write_Sectors;
break;
}
return ret;
}
int ehc_loop(void)
{
ipcmessage* message;
int timer2_id=-1;
extern char initial_port;
int init_mode=initial_port;
static bool first_read=true;
char port;
extern int ums_init_done[2];
extern u32 current_port;
int must_read_sectors=0;
void* queuespace = os_heap_alloc(heaphandle, 0x80);
int queuehandle = os_message_queue_create(queuespace, 32);
init_thread_ehci();
os_thread_set_priority(os_get_thread_id(), /*os_thread_get_priority()-1*/0x78);
os_device_register(DEVICE, queuehandle);
timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0);
int ums_mode = 0;
// int already_discovered = 0;
wbfs_disc_t *d = 0;
int usb_lock=0;
int watch_time_on=1;
// register SWI function (0xcd)
swi_mload_add_handler(0xcd, swi_ehcmodule);
while(1)
{
int result = 1;
int ack = 1;
volatile int ret;
// Wait for message to arrive
ret=os_message_queue_receive(queuehandle, (void*)&message, 0);
if(ret) continue;
// timer message WATCHDOG
//if((int) message==0x555) continue;
if(watch_time_on)
os_stop_timer(timer2_id); // stops watchdog timer
watch_time_on=0;
is_watchdog_read_sector=0;
if((int) message==0x0)
{
if(test_mode && !disable_ehc)
watchdog_enable=0; // test mode blocks watchdog
if(must_read_sectors && watchdog_enable && !disable_ehc)
{
int n,r;
if(unplug_device)
{
for(n=0;n<3;n++)
if(!unplug_procedure()) break;
}
if(unplug_device==0)
{
if(sec_size!=0 && sec_size<=4096)
{
extern int is_dvd[2];
is_watchdog_read_sector=1;
r=USBStorage_Read_Sectors(last_sector, 1, mem_sector);
is_watchdog_read_sector=0;
if(r!=0 && !is_dvd[current_port])
last_sector+=0x1000000/sec_size; // steps of 16MB
if(last_sector>=n_sec) last_sector=0;
}
}
if(!disable_ehc)
{
watch_time_on=1;
os_restart_timer(timer2_id, WATCHDOG_TIMER);
}
}
continue;
}
//print_hex_dump_bytes("msg",0, message,sizeof(*message));
switch( message->command )
{
case IOS_OPEN:
{
//debug_printf("%s try open %sfor fd %d\n",DEVICE,message->open.device,message->open.resultfd);
// Checking device name
if (0 == strcmp(message->open.device, DEVICE))
{
result = message->open.resultfd;
}
else
if (0 == strcmp(message->open.device, DEVICE"/OFF"))
{
result = message->open.resultfd;
disable_ehc=1;
must_read_sectors=0;
watchdog_enable=0;
ehci_int_passive_callback(off_callback_hand);
ehci_writel (STS_PCD, &ehci->regs->intr_enable);
ehci_release_externals_usb_ports();
//swi_mload_led_on();
}
/*else if (!ums_mode && 0 == memcmp(message->open.device, DEVICE"/", sizeof(DEVICE)) && !disable_ehc)
result = parse_and_open_device(message->open.device+sizeof(DEVICE),message->open.resultfd);
*/
else
result = -6;
}
break;
case IOS_CLOSE:
{
//debug_printf("close fd %d\n",message->fd);
//USBStorage_Umount();
//ehci_release_externals_usb_ports();
if(ums_mode == message->fd)
ums_mode = 0;
else
ehci_close_devices();
result = 0;
}
break;
case IOS_IOCTL:
{
break;
}
case IOS_IOCTLV:
{
ioctlv *vec = message->ioctlv.vector;
void *dev =NULL;
int i,in = message->ioctlv.num_in,io= message->ioctlv.num_io;
if( 0==(message->ioctl.command>>24) && !ums_mode)
dev = ehci_fd_to_dev(message->fd);
os_sync_before_read( vec, (in+io)*sizeof(ioctlv));
for(i=0;i<in+io;i++){
os_sync_before_read( vec[i].data, vec[i].len);
//print_hex_dump_bytes("vec",0, vec[i].data,vec[i].len);
}
if(disable_ehc)
{
result=-1;
}
else
switch( message->ioctl.command )
{
case USB_IOCTL_CTRLMSG:
//debug_printf("ctrl message%x\n",dev);
if(!dev)result= -6;
else
result = ehci_control_message(dev,ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
swab16(ioctlv_u16(vec[2])),swab16(ioctlv_u16(vec[3])),
swab16(ioctlv_u16(vec[4])),ioctlv_voidp(vec[6]));
break;
case USB_IOCTL_BLKMSG:
//debug_printf("bulk message\n");
if(!dev)result= -6;
else
result = ehci_bulk_message(dev,ioctlv_u8(vec[0]),ioctlv_u16(vec[1]),
ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_INTRMSG:
debug_printf("intr message\n");
case USB_IOCTL_SUSPENDDEV:
case USB_IOCTL_RESUMEDEV:
debug_printf("or resume/suspend message\n");
result = 0;//-1;// not supported
break;
case USB_IOCTL_GETDEVLIST:
debug_printf("get dev list\n");
//if(dev)result= -6;
//else
result = ehci_get_device_list(ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
ioctlv_voidp(vec[2]),ioctlv_voidp(vec[3]));
break;
case USB_IOCTL_DEVREMOVALHOOK:
case USB_IOCTL_DEVINSERTHOOK:
debug_printf("removal/insert hook\n");
ack = 0; // dont reply to those, as we dont detect anything
break;
case USB_IOCTL_UMS_INIT:
must_read_sectors=0;
result = USBStorage_Init(init_mode);
if(result>=0 && result <3)
{
if(result==0 || result==2)
current_port = 0;
else
current_port = 1;
}
//result=-os_thread_get_priority();
if(result>=0) {must_read_sectors=1;watchdog_enable=1;}
ums_mode = message->fd;
break;
case USB_IOCTL_UMS_UMOUNT:
must_read_sectors=0;
watchdog_enable=0;
USBStorage_Umount();
result =0;
break;
case USB_IOCTL_UMS_TESTMODE:
test_mode=ioctlv_u32(vec[0]);
result =0;
break;
case USB_IOCTL_SET_PORT:
result =0;
port=ioctlv_u32(vec[0]);
init_mode=port;
//if(ums_init_done==0) init_mode=port;
//else
{
if(port==0 || port==1) current_port=port;
result = current_port;
}
break;
case USB_IOCTL_UMS_OFF:
{
disable_ehc=1;
must_read_sectors=0;
watchdog_enable=0;
ehci_int_passive_callback(off_callback_hand);
ehci_writel (STS_PCD, &ehci->regs->intr_enable);
ehci_release_externals_usb_ports();
result =0;
}
case USB_IOCTL_UMS_GET_CAPACITY:
n_sec = USBStorage_Get_Capacity(&sec_size);
if(ioctlv_voidp(vec[0]))
{
*((u32 *) ioctlv_voidp(vec[0]))= sec_size;
}
result =n_sec ;
break;
case USB_IOCTL_UMS_READ_SECTORS:
#ifdef VIGILANTE
enable_button=1;
#endif
if(watchdog_enable && timer2_id!=-1)
{
os_stop_timer(timer2_id); // stops the timeout timer
os_destroy_timer(timer2_id);
timer2_id=-1;
}
result = USBStorage_Read_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
if(first_read)
{
void s_printf(char *format,...);
//#define s_printf(a...)
first_read=false;
if(result>0)
s_printf("first read sector (%i) OK\n",ioctlv_u32(vec[0]));
else
s_printf("first read sector (%i) ERROR\n",ioctlv_u32(vec[0]));
}
if(watchdog_enable && timer2_id==-1)timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0);
break;
case USB_IOCTL_UMS_WRITE_SECTORS:
#ifdef VIGILANTE
enable_button=1;
#endif
result = USBStorage_Write_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_UMS_READ_STRESS:
// result = USBStorage_Read_Stress(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_UMS_SET_VERBOSE:
verbose = !verbose;
result = 0;
break;
/*case USB_IOCTL_WBFS_SPEED_LIMIT:
DVD_speed_limit=ioctlv_u32(vec[0]);
break;*/
case USB_IOCTL_UMS_WATCHDOG:
watchdog_enable=ioctlv_u32(vec[0]);
break;
case USB_IOCTL_WBFS_OPEN_DISC:
ums_mode = message->fd;
u8 *discid;
int partition=0;
#ifdef VIGILANTE
enable_button=1;
#endif
discid=ioctlv_voidp(vec[0]);
if(discid[0]=='_' && discid[1]=='D' && discid[2]=='V' && discid[3]=='D')
{
result = 0;watchdog_enable=1;
ciso_lba=0;
if(vec[1].len==4)
{
memcpy(&partition, ioctlv_voidp(vec[1]), 4);
ciso_lba=partition;
}
//ciso_lba=265;
wbfs_perform_disc();
}
else
{
if(vec[1].len==4) memcpy(&partition, ioctlv_voidp(vec[1]), 4);
d = wbfs_init_with_partition(discid, partition);
if(!d)
result = -1;
else
{result = 0;watchdog_enable=1;}
}
must_read_sectors=1;
break;
case USB_IOCTL_WBFS_STS_DISC:
result=USBStorage_DVD_Test();
if(result==0) current_disc_lba=0xffffffff; // test fail
break;
case USB_IOCTL_WBFS_READ_DIRECT_DISC: // used to read USB DVD
usb_lock=1;
watchdog_enable=1;
if(watchdog_enable && timer2_id!=-1)
{
os_stop_timer(timer2_id); // stops the timeout timer
os_destroy_timer(timer2_id);
timer2_id=-1;
}
result = WBFS_direct_disc_read(ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1]));
if(watchdog_enable)timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0);
usb_lock=0;
break;
case USB_IOCTL_WBFS_READ_DISC:
/*if (verbose)
debug_printf("r%x %x\n",ioctlv_u32(vec[0]),ioctlv_u32(vec[1]));
else
debug_printf("r%x %x\r",ioctlv_u32(vec[0]),ioctlv_u32(vec[1]));
*/
if(!d /*|| usb_lock*/)
result = -1;
else
{
usb_lock=1;
//os_stop_timer(timer2_id);
if(watchdog_enable && timer2_id!=-1)
{
os_stop_timer(timer2_id); // stops the timeout timer
os_destroy_timer(timer2_id);
timer2_id=-1;
}
result = wbfs_disc_read(d,ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1]));
if(watchdog_enable)timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x0);
usb_lock=0;
if(result){
//debug_printf("wbfs failed! %d\n",result);
//result = 0x7800; // wii games shows unrecoverable error..
result = 0;//0x8000;
}
//result=0;
}
break;
}
for(i=in;i<in+io;i++){
//print_hex_dump_bytes("iovec",0, vec[i].data,vec[i].len>0x20?0x20:vec[i].len);
os_sync_after_write( vec[i].data, vec[i].len);
}
break;
}
default:
result = -1;
//ack = 0;
break;
}
if(watchdog_enable)
{
watch_time_on=1;
os_restart_timer(timer2_id, WATCHDOG_TIMER);
}
// Acknowledge message
if (ack)
os_message_queue_ack( (void*)message, result );
}
return 0;
}

View File

@ -0,0 +1,498 @@
/*
Custom IOS module for Wii.
OH0 message loop
Copyright (C) 2009 kwiirk.
Copyright (C) 2008 neimod.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*******************************************************************************
*
* oh0_loop.c - IOS module main code
* even if we are "ehc" driver, we still pretend to be "oh0"
* and implement "standard" ios oh0 usb api
*
*******************************************************************************
*
*/
#include <stdio.h>
#include <string.h>
#include "syscalls.h"
#include "ehci_types.h"
#include "ehci.h"
#include "utils.h"
#include "libwbfs.h"
void ehci_usleep(int usec);
void ehci_msleep(int msec);
#undef NULL
#define NULL ((void *)0)
#define IOS_OPEN 0x01
#define IOS_CLOSE 0x02
#define IOS_IOCTL 0x06
#define IOS_IOCTLV 0x07
#define USB_IOCTL_CTRLMSG 0
#define USB_IOCTL_BLKMSG 1
#define USB_IOCTL_INTRMSG 2
#define USB_IOCTL_SUSPENDDEV 5
#define USB_IOCTL_RESUMEDEV 6
#define USB_IOCTL_GETDEVLIST 12
#define USB_IOCTL_DEVREMOVALHOOK 26
#define USB_IOCTL_DEVINSERTHOOK 27
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
#define USB_IOCTL_UMS_UMOUNT (UMS_BASE+0x10)
#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
//#define USB_IOCTL_WBFS_SPEED_LIMIT (WBFS_BASE+0x80)
void USBStorage_Umount(void);
//#define DEVICE "/dev/usb/ehc"
#define DEVICE "/dev/usb2"
int verbose = 0;
#define ioctlv_u8(a) (*((u8*)(a).data))
#define ioctlv_u16(a) (*((u16*)(a).data))
#define ioctlv_u32(a) (*((u32*)(a).data))
#define ioctlv_voidp(a) (a).data
wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition);
#define WATCHDOG_TIMER 1000*1000*4
char *parse_hex(char *base,int *val)
{
int v = 0,done=0;
char *ptr = base,c;
while(!done)
{
c = *ptr++;
if(c >= '0' && c <= '9')
v = v << 4 | (c-'0');
else if(c >= 'a' && c <= 'f')
v = v << 4 | (10+c-'a');
else if(c >= 'A' && c <= 'F')
v = v << 4 | (10+c-'A');
else
done = 1;
}
if(ptr==base+1)//only incremented once
return 0; //we did not found any hex numbers
*val = v;
return ptr-1;
}
int parse_and_open_device(char *devname,int fd)
{
char *ptr = devname;
int vid,pid;
if (! (ptr = parse_hex(ptr,&vid)))
return -6;
if ( *ptr != '/' )
return -6;
ptr++;// skip /
if (! (ptr = parse_hex(ptr,&pid)))
return -6;
if ( *ptr != '\0' )
return -6;
return ehci_open_device(vid,pid,fd);
}
int DVD_speed_limit=0; // ingame it can fix x6 speed
int watchdog_enable=1;
// special ingame
int wbfs_disc_read2(wbfs_disc_t*d,u32 offset, u8 *data, u32 len);
// heap space for WBFS and queue
extern int heaphandle;
void msleep(int msec);
u8 mem_sector[2048] __attribute__ ((aligned (32)));
void *WBFS_Alloc(int size)
{
void * ret = 0;
ret= os_heap_alloc(heaphandle, size);
if(ret==0)
{debug_printf("WBFS not enough memory! need %d\n",size);
my_sprint("WBFS not enough memory!", NULL);
while(1) ehci_msleep(100);
}
return ret;
}
void WBFS_Free(void *ptr)
{
return os_heap_free(heaphandle, ptr);
}
void my_sprint(char *cad, char *s)
{
int n=strlen(cad);
int m=0;
int fd;
os_sync_after_write(cad, n);
if(s) {m=strlen(s);os_sync_after_write(s, m);}
fd=os_open("/dev/fat/log", 1);
if(fd<0) return;
os_write(fd, cad, n);
if(s)
os_write(fd, s, m);
os_close(fd);
}
#if 0
char my_log[256];
void my_dump(char *cad, char *dat, int len)
{
int n,m;
int fd;
fd=ios_open("/dev/fat/log", 1);
if(fd<0) return;
n=0;
while(*cad) {my_log[n]=*cad++;n++;}
my_log[n]='\n';n++;
for(m=0;m<len;m++)
{
if(n>=253) {ios_write(fd, my_log, n);n=0;}
my_log[n]=((*dat>>8) & 0xf)+48;if(my_log[n]>'9') my_log[n]+=7; n++;
my_log[n]=((*dat) & 0xf)+48;if(my_log[n]>'9') my_log[n]+=7; n++;
my_log[n]=((m & 15)!=15) ? ' ' : '\n'; n++;
dat++;
}
if(n>0)
{
os_sync_after_write((void *) cad, n);
os_write(fd, my_log, n);
}
ios_close(fd);
}
#endif
extern int unplug_device;
int unplug_procedure(void);
int ehc_loop(void)
{
ipcmessage* message;
int timer2_id=-1;
int last_sector=0;
int must_read_sectors=0;
my_sprint("ehc loop entry", NULL);
void* queuespace = os_heap_alloc(heaphandle, 0x40);
int queuehandle = os_message_queue_create(queuespace, 16);
os_device_register(DEVICE, queuehandle);
timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x666);
int ums_mode = 0;
int already_discovered = 0;
wbfs_disc_t *d = 0;
int usb_lock=0;
int watch_time_on=1;
while(1)
{
int result = 1;
int ack = 1;
// Wait for message to arrive
os_message_queue_receive(queuehandle, (void*)&message, 0);
// timer message WATCHDOG
if((int) message==0x555) continue;
if(watch_time_on)
os_stop_timer(timer2_id); // stops watchdog timer
watch_time_on=0;
if((int) message==0x666)
{
if(must_read_sectors && watchdog_enable)
{
int n,m;
unplug_procedure();
if(unplug_device==0 && !usb_lock)
{
n=USBStorage_Get_Capacity((void *) &m);
if(m!=0 && m<2048) // only support sector size minor to 2048
{
USBStorage_Read_Sectors(last_sector, 1, mem_sector);
last_sector+=0x1000000/m; // steps of 16MB
if(last_sector>n) last_sector=0;
}
}
watch_time_on=1;
os_restart_timer(timer2_id, WATCHDOG_TIMER);
}
continue;
}
//print_hex_dump_bytes("msg",0, message,sizeof(*message));
switch( message->command )
{
case IOS_OPEN:
{
//debug_printf("%s try open %sfor fd %d\n",DEVICE,message->open.device,message->open.resultfd);
// Checking device name
if (0 == strcmp(message->open.device, DEVICE))
{
result = message->open.resultfd;
if(!already_discovered)
ehci_discover();
already_discovered=1;
}
else if (!ums_mode && 0 == memcmp(message->open.device, DEVICE"/", sizeof(DEVICE)))
result = parse_and_open_device(message->open.device+sizeof(DEVICE),message->open.resultfd);
else
result = -6;
}
break;
case IOS_CLOSE:
{
//debug_printf("close fd %d\n",message->fd);
if(ums_mode == message->fd)
ums_mode = 0;
else
ehci_close_device(ehci_fd_to_dev(message->fd));
// do nothing
result = 0;
}
break;
case IOS_IOCTL:
{
break;
}
case IOS_IOCTLV:
{
ioctlv *vec = message->ioctlv.vector;
void *dev =NULL;
int i,in = message->ioctlv.num_in,io= message->ioctlv.num_io;
if( 0==(message->ioctl.command>>24) && !ums_mode)
dev = ehci_fd_to_dev(message->fd);
os_sync_before_read( vec, (in+io)*sizeof(ioctlv));
for(i=0;i<in+io;i++){
os_sync_before_read( vec[i].data, vec[i].len);
//print_hex_dump_bytes("vec",0, vec[i].data,vec[i].len);
}
switch( message->ioctl.command )
{
case USB_IOCTL_CTRLMSG:
//debug_printf("ctrl message%x\n",dev);
if(!dev)result= -6;
else
result = ehci_control_message(dev,ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
swab16(ioctlv_u16(vec[2])),swab16(ioctlv_u16(vec[3])),
swab16(ioctlv_u16(vec[4])),ioctlv_voidp(vec[6]));
break;
case USB_IOCTL_BLKMSG:
//debug_printf("bulk message\n");
if(!dev)result= -6;
else
result = ehci_bulk_message(dev,ioctlv_u8(vec[0]),ioctlv_u16(vec[1]),
ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_INTRMSG:
debug_printf("intr message\n");
case USB_IOCTL_SUSPENDDEV:
case USB_IOCTL_RESUMEDEV:
debug_printf("or resume/suspend message\n");
result = 0;//-1;// not supported
break;
case USB_IOCTL_GETDEVLIST:
debug_printf("get dev list\n");
if(dev)result= -6;
else
result = ehci_get_device_list(ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
ioctlv_voidp(vec[2]),ioctlv_voidp(vec[3]));
break;
case USB_IOCTL_DEVREMOVALHOOK:
case USB_IOCTL_DEVINSERTHOOK:
debug_printf("removal/insert hook\n");
ack = 0; // dont reply to those, as we dont detect anything
break;
case USB_IOCTL_UMS_INIT:
must_read_sectors=0;
result = USBStorage_Init();
//result=-os_thread_get_priority();
if(result>=0) {must_read_sectors=1;watchdog_enable=1;}
ums_mode = message->fd;
if(result>=0) my_sprint("UMS Init", NULL); else my_sprint("UMS fail", NULL);
break;
case USB_IOCTL_UMS_UMOUNT:
must_read_sectors=0;
watchdog_enable=0;
USBStorage_Umount();
result =0;
break;
case USB_IOCTL_UMS_GET_CAPACITY:
result = USBStorage_Get_Capacity(ioctlv_voidp(vec[0]));
break;
case USB_IOCTL_UMS_READ_SECTORS:
if (verbose)
debug_printf("%p read sector %d %d %p\n",&vec[0],ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
result = USBStorage_Read_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
//udelay(ioctlv_u32(vec[1])*125);
if(result) break;
break;
case USB_IOCTL_UMS_WRITE_SECTORS:
result = USBStorage_Write_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_UMS_READ_STRESS:
result = USBStorage_Read_Stress(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_UMS_SET_VERBOSE:
verbose = !verbose;
result = 0;
break;
/*case USB_IOCTL_WBFS_SPEED_LIMIT:
DVD_speed_limit=ioctlv_u32(vec[0]);
break;*/
case USB_IOCTL_UMS_WATCHDOG:
watchdog_enable=ioctlv_u32(vec[0]);
break;
case USB_IOCTL_WBFS_OPEN_DISC:
ums_mode = message->fd;
int partition=0;
// if (verbose)
debug_printf("ehc:use disc %s\n",ioctlv_voidp(vec[0]));
if(vec[1].len==4) memcpy(&partition, ioctlv_voidp(vec[1]), 4);
d = wbfs_init_with_partition(ioctlv_voidp(vec[0]), partition);
if(!d)
result = -1;
else
{result = 0;watchdog_enable=1;}
my_sprint("WBFS Open()", NULL);
must_read_sectors=1;
break;
case USB_IOCTL_WBFS_READ_DISC:
if (verbose)
debug_printf("r%x %x\n",ioctlv_u32(vec[0]),ioctlv_u32(vec[1]));
else
debug_printf("r%x %x\r",ioctlv_u32(vec[0]),ioctlv_u32(vec[1]));
if(!d || usb_lock)
result = -1;
else
{
usb_lock=1;
//os_stop_timer(timer2_id);
result = wbfs_disc_read2(d,ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1]));
usb_lock=0;
/* if(result){
debug_printf("wbfs failed! %d\n",result);
//result = 0x7800; // wii games shows unrecoverable error..
result = 0x8000;
}*/
result=0;
}
break;
}
for(i=in;i<in+io;i++){
//print_hex_dump_bytes("iovec",0, vec[i].data,vec[i].len>0x20?0x20:vec[i].len);
os_sync_after_write( vec[i].data, vec[i].len);
}
break;
}
default:
result = -1;
//ack = 0;
break;
}
if(watchdog_enable)
{watch_time_on=1;
os_restart_timer(timer2_id, WATCHDOG_TIMER);
}
//debug_printf("return %d\n",result);
// Acknowledge message
if (ack)
os_message_queue_ack( (void*)message, result );
}
return 0;
}

View File

@ -0,0 +1,522 @@
/*
Custom IOS module for Wii.
OH0 message loop
Copyright (C) 2009 kwiirk.
Copyright (C) 2008 neimod.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*******************************************************************************
*
* oh0_loop.c - IOS module main code
* even if we are "ehc" driver, we still pretend to be "oh0"
* and implement "standard" ios oh0 usb api
*
*******************************************************************************
*
*/
#include <stdio.h>
#include <string.h>
#include "syscalls.h"
#include "ehci_types.h"
#include "ehci.h"
#include "utils.h"
#include "libwbfs.h"
void ehci_usleep(int usec);
void ehci_msleep(int msec);
#undef NULL
#define NULL ((void *)0)
#define IOS_OPEN 0x01
#define IOS_CLOSE 0x02
#define IOS_IOCTL 0x06
#define IOS_IOCTLV 0x07
#define USB_IOCTL_CTRLMSG 0
#define USB_IOCTL_BLKMSG 1
#define USB_IOCTL_INTRMSG 2
#define USB_IOCTL_SUSPENDDEV 5
#define USB_IOCTL_RESUMEDEV 6
#define USB_IOCTL_GETDEVLIST 12
#define USB_IOCTL_DEVREMOVALHOOK 26
#define USB_IOCTL_DEVINSERTHOOK 27
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
#define USB_IOCTL_UMS_IS_INSERTED (UMS_BASE+0x7)
#define USB_IOCTL_UMS_UMOUNT (UMS_BASE+0x10)
#define USB_IOCTL_UMS_START (UMS_BASE+0x11)
#define USB_IOCTL_UMS_STOP (UMS_BASE+0x12)
#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
s32 USBStorage_Umount(void);
s32 USBStorage_Start(void);
s32 USBStorage_Stop(void);
//#define DEVICE "/dev/usb/ehc"
#define DEVICE "/dev/usb2"
int verbose = 0;
#define ioctlv_u8(a) (*((u8*)(a).data))
#define ioctlv_u16(a) (*((u16*)(a).data))
#define ioctlv_u32(a) (*((u32*)(a).data))
#define ioctlv_voidp(a) (a).data
wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition);
#define WATCHDOG_TIMER 1000*1000*5
char *parse_hex(char *base,int *val)
{
int v = 0,done=0;
char *ptr = base,c;
while(!done)
{
c = *ptr++;
if(c >= '0' && c <= '9')
v = v << 4 | (c-'0');
else if(c >= 'a' && c <= 'f')
v = v << 4 | (10+c-'a');
else if(c >= 'A' && c <= 'F')
v = v << 4 | (10+c-'A');
else
done = 1;
}
if(ptr==base+1)//only incremented once
return 0; //we did not found any hex numbers
*val = v;
return ptr-1;
}
int parse_and_open_device(char *devname,int fd)
{
char *ptr = devname;
int vid,pid;
if (! (ptr = parse_hex(ptr,&vid)))
return -6;
if ( *ptr != '/' )
return -6;
ptr++;// skip /
if (! (ptr = parse_hex(ptr,&pid)))
return -6;
if ( *ptr != '\0' )
return -6;
return ehci_open_device(vid,pid,fd);
}
int DVD_speed_limit=0; // ingame it can fix x6 speed
int watchdog_enable=0;
// special ingame
int wbfs_disc_read2(wbfs_disc_t*d,u32 offset, u8 *data, u32 len);
// heap space for WBFS and queue
extern int heaphandle;
void msleep(int msec);
u8 mem_sector[2048] __attribute__ ((aligned (32)));
void *WBFS_Alloc(int size)
{
void * ret = 0;
ret= os_heap_alloc(heaphandle, size);
if(ret==0)
{debug_printf("WBFS not enough memory! need %d\n",size);
my_sprint("WBFS not enough memory!", NULL);
while(1) ehci_msleep(100);
}
return ret;
}
void WBFS_Free(void *ptr)
{
return os_heap_free(heaphandle, ptr);
}
void my_sprint(char *cad, char *s)
{
#if 0
int n=strlen(cad);
int m=0;
int fd;
os_sync_after_write(cad, n);
if(s) {m=strlen(s);os_sync_after_write(s, m);}
fd=os_open("/dev/fat/log", 1);
if(fd<0) return;
os_write(fd, cad, n);
if(s)
os_write(fd, s, m);
os_close(fd);
#endif
}
#if 0
char my_log[256];
void my_dump(char *cad, char *dat, int len)
{
int n,m;
int fd;
fd=ios_open("/dev/fat/log", 1);
if(fd<0) return;
n=0;
while(*cad) {my_log[n]=*cad++;n++;}
my_log[n]='\n';n++;
for(m=0;m<len;m++)
{
if(n>=253) {ios_write(fd, my_log, n);n=0;}
my_log[n]=((*dat>>8) & 0xf)+48;if(my_log[n]>'9') my_log[n]+=7; n++;
my_log[n]=((*dat) & 0xf)+48;if(my_log[n]>'9') my_log[n]+=7; n++;
my_log[n]=((m & 15)!=15) ? ' ' : '\n'; n++;
dat++;
}
if(n>0)
{
ios_sync_after_write((void *) cad, n);
ios_write(fd, my_log, n);
}
ios_close(fd);
}
#endif
/*
void my_sprint2(char *cad)
{
int n=strlen(cad);
int fd;
os_sync_after_write(cad, n);
fd=os_open("/dev/fat/log", 1);
if(fd<0) return;
os_write(fd, cad, n);
os_close(fd);
}*/
//#ifdef HOMEBREW
extern bool first_access;
//#endif
int ehc_loop(void)
{
ipcmessage* message;
int timer2_id=-1;
//my_sprint2("ehc loop entry");
// my_sprint("ehc loop entry", NULL);
void* queuespace = os_heap_alloc(heaphandle, 0x40);
int queuehandle = os_message_queue_create(queuespace, 32);
timer2_id=os_create_timer(WATCHDOG_TIMER, WATCHDOG_TIMER, queuehandle, 0x666);
int ums_mode = 0;
int already_discovered = 0;
wbfs_disc_t *d = 0;
int usb_lock=0;
int cnt_timer=0;
// wbfs_disc_t *d = 0;
// int usb_lock=0;
int watch_time_on=1;
os_device_register(DEVICE, queuehandle);
while(1)
{
int result = 1;
int ack = 1;
// Wait for message to arrive
os_message_queue_receive(queuehandle, (void*)&message, 0);
os_stop_timer(timer2_id); // stops watchdog timer
// timer message WATCHDOG
if((int) message==0x555) continue;
if(watch_time_on)
os_stop_timer(timer2_id); // stops watchdog timer
watch_time_on=0;
if((int) message==0x666)
{
cnt_timer++;
if(cnt_timer<6) //every 30 secs
{
watch_time_on=1;
os_restart_timer(timer2_id, WATCHDOG_TIMER);
}
else
{
cnt_timer=0;
first_access=true;
watchdog_enable=0;
}
continue;
}
//print_hex_dump_bytes("msg",0, message,sizeof(*message));
switch( message->command )
{
case IOS_OPEN:
{
#ifdef HOMEBREW
if (0 == strcmp(message->open.device, DEVICE))
result = message->open.resultfd;
else
result = -6;
#else
// Checking device name
if (0 == strcmp(message->open.device, DEVICE))
{
result = message->open.resultfd;
if(!already_discovered)
ehci_discover();
already_discovered=1;
}
else if (!ums_mode && 0 == memcmp(message->open.device, DEVICE"/", sizeof(DEVICE)))
result = parse_and_open_device(message->open.device+sizeof(DEVICE),message->open.resultfd);
else
result = -6;
#endif
}
break;
case IOS_CLOSE:
{
#ifndef HOMEBREW
//debug_printf("close fd %d\n",message->fd);
if(ums_mode == message->fd)
ums_mode = 0;
else
ehci_close_device(ehci_fd_to_dev(message->fd));
#endif
// do nothing
result = 0;
}
break;
case IOS_IOCTL:
{
break;
}
case IOS_IOCTLV:
{
ioctlv *vec = message->ioctlv.vector;
void *dev =NULL;
int i,in = message->ioctlv.num_in,io= message->ioctlv.num_io;
#ifdef HOMEBREW
if( 0==(message->ioctl.command>>24))
dev = ehci_fd_to_dev(message->fd);
#else
if( 0==(message->ioctl.command>>24) && !ums_mode)
dev = ehci_fd_to_dev(message->fd);
#endif
os_sync_before_read( vec, (in+io)*sizeof(ioctlv));
for(i=0;i<in+io;i++){
os_sync_before_read( vec[i].data, vec[i].len);
//print_hex_dump_bytes("vec",0, vec[i].data,vec[i].len);
}
switch( message->ioctl.command )
{
case USB_IOCTL_CTRLMSG:
//debug_printf("ctrl message%x\n",dev);
if(!dev)result= -6;
else
result = ehci_control_message(dev,ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
swab16(ioctlv_u16(vec[2])),swab16(ioctlv_u16(vec[3])),
swab16(ioctlv_u16(vec[4])),ioctlv_voidp(vec[6]));
break;
case USB_IOCTL_BLKMSG:
//debug_printf("bulk message\n");
if(!dev)result= -6;
else
result = ehci_bulk_message(dev,ioctlv_u8(vec[0]),ioctlv_u16(vec[1]),
ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_INTRMSG:
debug_printf("intr message\n");
case USB_IOCTL_SUSPENDDEV:
case USB_IOCTL_RESUMEDEV:
debug_printf("or resume/suspend message\n");
result = 0;//-1;// not supported
break;
case USB_IOCTL_GETDEVLIST:
debug_printf("get dev list\n");
if(dev)result= -6;
else
result = ehci_get_device_list(ioctlv_u8(vec[0]),ioctlv_u8(vec[1]),
ioctlv_voidp(vec[2]),ioctlv_voidp(vec[3]));
break;
case USB_IOCTL_DEVREMOVALHOOK:
case USB_IOCTL_DEVINSERTHOOK:
debug_printf("removal/insert hook\n");
ack = 0; // dont reply to those, as we dont detect anything
break;
case USB_IOCTL_UMS_INIT:
result = USBStorage_Init();
if(result>=0) watchdog_enable=1;
#ifndef HOMEBREW
ums_mode = message->fd;
//if(result>=0) my_sprint("UMS Init", NULL); else my_sprint("UMS fail", NULL);
#endif
break;
case USB_IOCTL_UMS_UMOUNT:
watchdog_enable=0;
result = USBStorage_Umount();
break;
case USB_IOCTL_UMS_START:
result = USBStorage_Start();
break;
case USB_IOCTL_UMS_STOP:
result = USBStorage_Stop();
break;
case USB_IOCTL_UMS_GET_CAPACITY:
result = USBStorage_Get_Capacity(ioctlv_voidp(vec[0]));
break;
case USB_IOCTL_UMS_READ_SECTORS:
os_stop_timer(timer2_id);
result = USBStorage_Read_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
cnt_timer=0;
watchdog_enable=1;
break;
case USB_IOCTL_UMS_WRITE_SECTORS:
os_stop_timer(timer2_id);
result = USBStorage_Write_Sectors(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
cnt_timer=0;
watchdog_enable=1;
break;
case USB_IOCTL_UMS_READ_STRESS:
result = USBStorage_Read_Stress(ioctlv_u32(vec[0]),ioctlv_u32(vec[1]), ioctlv_voidp(vec[2]));
break;
case USB_IOCTL_UMS_SET_VERBOSE:
verbose = !verbose;
result = 0;
break;
case USB_IOCTL_UMS_IS_INSERTED:
result = ehci_is_inserted();
break;
/*case USB_IOCTL_WBFS_SPEED_LIMIT:
DVD_speed_limit=ioctlv_u32(vec[0]);
break;*/
case USB_IOCTL_UMS_WATCHDOG:
watchdog_enable=ioctlv_u32(vec[0]);
break;
case USB_IOCTL_WBFS_OPEN_DISC:
ums_mode = message->fd;
int partition=0;
// if (verbose)
debug_printf("ehc:use disc %s\n",ioctlv_voidp(vec[0]));
if(vec[1].len==4) memcpy(&partition, ioctlv_voidp(vec[1]), 4);
d = wbfs_init_with_partition(ioctlv_voidp(vec[0]), partition);
if(!d)
result = -1;
else
{result = 0;watchdog_enable=1;}
my_sprint("WBFS Open()", NULL);
cnt_timer=0;
break;
case USB_IOCTL_WBFS_READ_DISC:
if(!d || usb_lock)
result = -1;
else
{
usb_lock=1;
//os_stop_timer(timer2_id);
result = wbfs_disc_read2(d,ioctlv_u32(vec[0]),ioctlv_voidp(vec[2]),ioctlv_u32(vec[1]));
usb_lock=0;
cnt_timer=0;
/* if(result){
debug_printf("wbfs failed! %d\n",result);
//result = 0x7800; // wii games shows unrecoverable error..
result = 0x8000;
}*/
result=0;
}
break;
}
for(i=in;i<in+io;i++){
//print_hex_dump_bytes("iovec",0, vec[i].data,vec[i].len>0x20?0x20:vec[i].len);
os_sync_after_write( vec[i].data, vec[i].len);
}
break;
}
default:
// os_message_queue_send(queuehandle, (void*)message, 0);
result = -1;
//ack = 0;
break;
}
if(watchdog_enable)
{
watch_time_on=1;
os_restart_timer(timer2_id, WATCHDOG_TIMER);
}
//debug_printf("return %d\n",result);
// Acknowledge message
if (ack)
os_message_queue_ack( (void*)message, result );
}
return 0;
}

View File

@ -0,0 +1,188 @@
#include "ehci_interrupt.h"
#include "swi_mload.h"
#define ehci_readl(a) (*((volatile u32*)(a)))
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
#define get_timer() (*(((volatile u32*)0x0D800010)))
void enable_EHCI_IRQ(void)
{
*((volatile u32 *) 0x0d0400cc)|=1<<15;
}
void disable_EHCI_IRQ(void)
{
*((volatile u32 *) 0x0d0400cc) &=~(1<<15);
}
#if 0
void enable_OHCI0_IRQ(void)
{
*((volatile u32 *) 0x0d0400cc)|=1<<11;
}
void disable_OHCI0_IRQ(void)
{
*((volatile u32 *) 0x0d0400cc) &=~(1<<11);
}
void enable_OHCI1_IRQ(void)
{
*((volatile u32 *) 0x0d0400cc)|=1<<12;
}
void disable_OHCI1_IRQ(void)
{
*((volatile u32 *) 0x0d0400cc) &=~(1<<12);
}
#endif
int ehci1_queuehandle=-1;
void init_thread_ehci(void)
{
disable_EHCI_IRQ();
ehci1_queuehandle= os_message_queue_create( USB_Alloc(4*32)/*os_heap_alloc(heaphandle, 4*32)*/, 32);
os_unregister_event_handler(DEV_EHCI);
os_register_event_handler(DEV_EHCI, ehci1_queuehandle, 0); // register interrupt event handler
enable_EHCI_IRQ();
os_software_IRQ(DEV_EHCI);
}
static int (*working_callback)(u32 flags)= NULL;
static void (*passive_callback)(u32 flags)= NULL;
static int private_timer_id=-1;
static int remote_message=0;
void ehci_int_working_callback_part1( int (*callback)(u32 flags), u32 timeout)
{
private_timer_id=os_create_timer(timeout, timeout*10, ehci1_queuehandle, 1);
swi_mload_set_register(0x0d800038,(1<<DEV_EHCI)); // clear interrupt flag
swi_mload_clr_register(0x0d80003c,(1<<DEV_EHCI)); // unmask interrupt flag
working_callback=callback;
ehci_writel (INTR_MASK, &ehci->regs->intr_enable);
os_software_IRQ(DEV_EHCI); // enable and mask interrupt flag
}
int ehci_int_working_callback_part2(void)
{
static int message=0;
message=-ETIMEDOUT;
os_message_queue_receive(ehci1_queuehandle, (void*)&message, 0); // waits for interrupt or timeout
ehci_writel (0, &ehci->regs->intr_enable); // disable interrupts flags
working_callback=NULL; // disable callback
os_stop_timer(private_timer_id); // stops the timeout timer
os_destroy_timer(private_timer_id);
private_timer_id=-1;
if(message==0) // build message response
{
message=remote_message;
}
else message=-ETIMEDOUT;
os_software_IRQ(DEV_EHCI); // enable and mask interrupt flag
return message;
}
void ehci_int_passive_callback( void (*callback)(u32 flags))
{
passive_callback=callback;
working_callback=NULL;
}
void int_send_device_message(int device);
int ehci_vector(void)
{
int ret=0;
u32 flags;
int message=1;
*((volatile u32 *)0x0d80003c ) &= ~(1<<DEV_EHCI); // disable EHCI interrupt
flags=ehci_readl (&ehci->regs->status);
if(working_callback)
{
message= working_callback(flags);
if(((int)message)<=0)
{
working_callback=NULL;
remote_message=message;
int_send_device_message(DEV_EHCI);
//ret=1;
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
}
else
{
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
//temp=ehci_readl( &ehci->regs->command);
*((volatile u32 *)0x0d80003c ) |= 1<<DEV_EHCI;
*((volatile u32 *)0x0d800038 ) |= 1<<DEV_EHCI;
}
}
else
if(passive_callback)
{
passive_callback(flags);
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
*((volatile u32 *)0x0d80003c ) |= 1<<DEV_EHCI;
*((volatile u32 *)0x0d800038 ) |= 1<<DEV_EHCI;
//ret=1; // remote int_send_device_message
}
else
{
ehci_writel (flags & INTR_MASK, &ehci->regs->status);
*((volatile u32 *)0x0d80003c ) |= 1<<DEV_EHCI;
*((volatile u32 *)0x0d800038 ) |= 1<<DEV_EHCI;
//ret=1; // remote int_send_device_message
}
// ret==1: send message to EHCI queue
return ret;
}

View File

@ -0,0 +1,28 @@
#ifndef _EHCI_INTERRUPT_H_
#define _EHCI_INTERRUPT_H_
#include "syscalls.h"
#include "ehci_types.h"
#include "ehci.h"
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
extern int heaphandle;
void enable_EHCI(void);
void disable_EHCI(void);
void enable_OHCI1(void);
void disable_OHCI1(void);
void init_thread_ehci(void);
void ehci_int_passive_callback( void (*callback)(u32 flags));
void ehci_int_working_callback_part1(int (*callback)(u32 flags), u32 timeout);
int ehci_int_working_callback_part2(void);
#endif

291
ehcmodule/source/main.c Normal file
View File

@ -0,0 +1,291 @@
/*
Custom IOS module for Wii.
Copyright (C) 2008 neimod.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*******************************************************************************
*
* main.c - IOS module main code
*
*******************************************************************************
*
*
* v1.0 - 26 July 2008 - initial release by neimod
* v1.1 - 5 September 2008 - prepared for public release
*
*/
#include <stdio.h>
#include <string.h>
#include "syscalls.h"
#include "swi_mload.h"
int tiny_ehci_init(void);
//int ehc_loop(void);
u8 heap_space2[0xe000] __attribute__ ((aligned (32)));
/* USB timer */
int timer1_queuehandle=-1;
int timer1_id=-1;
void ehci_usleep(u32 time)
{
static u32 message;
//int n;
//os_message_queue_send(timer1_queuehandle, 0x555, 0);
//os_restart_timer(timer1_id, time);
timer1_id=os_create_timer(time, 1000*1000*10, timer1_queuehandle, 0x0);
os_message_queue_receive(timer1_queuehandle,(void *) &message, 0);
os_stop_timer(timer1_id);
os_destroy_timer(timer1_id);
}
void ehci_msleep(int msec)
{
ehci_usleep(((u32) msec)*1000);
}
#define get_timer() (*(((volatile u32*)0x0D800010)))
void ehci_udelay(int usec)
{
u32 tmr,temp;
u32 time_usec;
tmr = get_timer();
time_usec=2*usec;
while (1) {temp=get_timer()-tmr;if(((int) temp)<0) tmr = get_timer(); if(((int)temp) > time_usec) break;}
}
void ehci_mdelay(int msec)//@todo not really sleeping..
{
u32 tmr,temp;
u32 time_usec;
tmr = get_timer();
time_usec=2048*msec;
while (1) {temp=get_timer()-tmr;if(((int) temp)<0) tmr = get_timer(); if(((int)temp) > time_usec) break;}
}
int ehc_loop(void);
int heaphandle=-1;
unsigned int heapspace[0x5000/*0x8800*/] __attribute__ ((aligned (32)));
void interrupt_vector(void);
void patch1_timer(void);
void patch2_timer_cont(void);
void int_send_device_message(u32);
void direct_os_sync_before_read(void* ptr, int size);
void direct_os_sync_after_write(void* ptr, int size);
void ic_invalidate(void);
static u32 vector[2]={ 0xE51FF004, 0}; // ldr pc,=addr
u32 syscall_base;
int my_di_os_message_queue_receive(int queuehandle, ipcmessage ** message,int flag);
u32 read_access_perm(void);
void write_access_perm(u32 flags);
static void di_patch(u32 addr1, u32 addr2)
{
u32 perm;
perm=read_access_perm();
write_access_perm(0xffffffff);
if(*((u32 *) addr2)==0xE6000170) // detect an unused syscall in dev/di to store the entry
{
vector[1]= ((u32) my_di_os_message_queue_receive) | 1;
memcpy((void *) addr2, vector, 8);
direct_os_sync_after_write((void *) addr2, 8);
*((u32 *) addr1)= 0xEA000000 | (((addr2-addr1)/4-2) & 0xFFFFFF); // change the jump
direct_os_sync_after_write((void *) addr1, 4);
}
write_access_perm(perm);
}
int copy_int_vect(u32 ios, u32 none)
{
ic_invalidate();
switch(ios)
{
case 36:
// WARNING!!!: IOS 36 ins not recommended because it fails using the ehcmodule some times
vector[1]= (u32) interrupt_vector;
memcpy((void *) 0xFFFF1E78, vector,8); // fix interrupt jump
direct_os_sync_after_write((void *) 0xFFFF1E78, 8);
break;
case 37:
// patch for DI (IOS37 v3869) os_message_queue_receive() syscalls
di_patch(0x20205DE8, 0x2020408c);
vector[1]= (u32) 0xFFFF1F70;
memcpy((void *) patch1_timer, vector,8); // patch1 -> timer
direct_os_sync_after_write((void *) patch1_timer, 8);
vector[1]= (u32) 0xFFFF1F8C;
memcpy((void *) patch2_timer_cont, vector,8); // patch2-> next interrupt case
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
vector[1]= (u32) 0xFFFF1E34;
memcpy((void *) int_send_device_message, vector,8); // patch3 ->send device message
direct_os_sync_after_write((void *) int_send_device_message, 8);
vector[1]= (u32) interrupt_vector;
memcpy((void *) 0xFFFF1F68, vector,8); // fix interrupt jump
direct_os_sync_after_write((void *) 0xFFFF1F68, 8);
break;
case 38:
// patch for DI (IOS38 v3867) os_message_queue_receive() syscalls
di_patch(0x20205B14, 0x20203E6C);
vector[1]= (u32) 0xFFFF1EB0;
memcpy((void *) patch1_timer, vector, 8); // patch1 -> timer
direct_os_sync_after_write((void *) patch1_timer, 8);
vector[1]= (u32) 0xFFFF1ECC;
memcpy((void *) patch2_timer_cont, vector, 8); // patch2-> next interrupt case
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
vector[1]= (u32) 0xFFFF1D74;
memcpy((void *) int_send_device_message, vector, 8); // patch3 ->send device message
direct_os_sync_after_write((void *) int_send_device_message, 8);
vector[1]= (u32) interrupt_vector;
memcpy((void *) 0xFFFF1EA8, vector,8);
direct_os_sync_after_write((void *) 0xFFFF1EA8, 8);
break;
case 57:
// patch for DI (IOS57 v5661) os_message_queue_receive() syscalls
di_patch(0x20205E84, 0x20203F60);
vector[1]= (u32) 0xFFFF2130;
memcpy((void *) patch1_timer, vector,8); // patch1 -> timer
direct_os_sync_after_write((void *) patch1_timer, 8);
vector[1]= (u32) 0xFFFF214C;
memcpy((void *) patch2_timer_cont, vector,8); // patch2-> next interrupt case
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
vector[1]= (u32) 0xFFFF1FF4;
memcpy((void *) int_send_device_message, vector,8); // patch3 ->send device message
direct_os_sync_after_write((void *) int_send_device_message, 8);
vector[1]= (u32) interrupt_vector;
memcpy((void *) 0xFFFF2128, vector,8); // fix interrupt jump
direct_os_sync_after_write((void *) 0xFFFF2128, 8);
break;
case 60:
// patch for DI (IOS60 v6174) os_message_queue_receive() syscalls
di_patch(0x20205D94, 0x20203F60);
vector[1]= (u32) 0xFFFF2130;
memcpy((void *) patch1_timer, vector,8); // patch1 -> timer
direct_os_sync_after_write((void *) patch1_timer, 8);
vector[1]= (u32) 0xFFFF214C;
memcpy((void *) patch2_timer_cont, vector,8); // patch2-> next interrupt case
direct_os_sync_after_write((void *) patch2_timer_cont, 8);
vector[1]= (u32) 0xFFFF1FF4;
memcpy((void *) int_send_device_message, vector,8); // patch3 ->send device message
direct_os_sync_after_write((void *) int_send_device_message, 8);
vector[1]= (u32) interrupt_vector;
memcpy((void *) 0xFFFF2128, vector,8); // fix interrupt jump
direct_os_sync_after_write((void *) 0xFFFF2128, 8);
break;
}
//*((volatile u32 *)0x0d8000c0) |=0x20;
return 0;
}
extern char initial_port;
extern u32 current_port;
int main(void)
{
current_port=initial_port;
// changes IOS vector interrupt to crt0.s routine
//swi_mload_led_on();
syscall_base=swi_mload_get_syscall_base();
os_sync_after_write((void *) &syscall_base, 4);
swi_mload_call_func((void *) copy_int_vect, (void *) swi_mload_get_ios_base(), NULL);
heaphandle = os_heap_create(heapspace, sizeof(heapspace));
void* timer1_queuespace = os_heap_alloc(heaphandle, 0x80);
timer1_queuehandle = os_message_queue_create(timer1_queuespace, 32);
if(tiny_ehci_init()<0) return -1;
ehc_loop();
return 0;
}

View File

@ -0,0 +1,367 @@
/*
EHCI glue. A bit hacky for the moment. needs cleaning..
Copyright (C) 2008 kwiirk.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <setjmp.h>
#include "syscalls.h"
#include "ehci_types.h"
#include "utils.h"
#include "ehci_interrupt.h"
#include "swi_mload.h"
#define static
#define inline extern
#define readl(a) (*((volatile u32*)(a)))
#define writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
#define ehci_dbg(a...) debug_printf(a)
#define printk(a...) debug_printf(a)
#define get_timer() (*(((volatile u32*)0x0D800010)))
void BUG(void)
{
debug_printf("bug\n");
// stack_trace();
// while(1);
}
#define BUG_ON(a) if(a)BUG()
void ehci_usleep(int usec);
void ehci_msleep(int msec);
/*
void udelay(int usec)
{
u32 tmr,temp;
u32 time_usec;
tmr = get_timer();
time_usec=2*usec;
while (1) {temp=get_timer()-tmr;if(temp > time_usec) break;}
}
void msleep(int msec)//@todo not really sleeping..
{
u32 tmr,temp;
u32 time_usec;
tmr = get_timer();
time_usec=2048*msec;
while (1) {temp=get_timer()-tmr;if(temp > time_usec) break;}
}
*/
extern u32 __exe_start_virt__;
extern u32 __ram_start_virt__;
extern u32 ios_thread_stack;
#define cpu_to_le32(a) swab32(a)
#define le32_to_cpu(a) swab32(a)
#define cpu_to_le16(a) swab16(a)
#define le16_to_cpu(a) swab16(a)
#define cpu_to_be32(a) (a)
#define be32_to_cpu(a) (a)
void print_hex_dump_bytes(char *header,int prefix,u8 *buf,int len)
{
int i;
if (len>0x100)len=0x100;
debug_printf("%s %08X\n",header,(u32)buf);
for (i=0;i<len;i++){
debug_printf("%02x ",buf[i]);
if((i&0xf) == 0xf)
debug_printf("\n");
}
debug_printf("\n");
}
#define DUMP_PREFIX_OFFSET 1
#include "ehci.h"
#define ehci_readl(a) ((*((volatile u32*)(a))))
//#define ehci_writel(e,v,a) do{msleep(40);debug_printf("writel %08X %08X\n",a,v);*((volatile u32*)(a))=(v);}while(0)
#define ehci_writel(v,a) do{*((volatile u32*)(a))=(v);}while(0)
struct ehci_hcd _ehci;
struct ehci_hcd *ehci = &_ehci;
#include "ehci.c"
int usb_os_init(void);
#define MLOAD_GET_EHCI_DATA 0x4D4C44A0
#if 1
int system_cmd(int cmd)
{
return 0;
}
#endif
static struct ehci_qtd *qtd_dummy_first=NULL ;
static struct ehci_qtd * qtd_header=NULL;
static struct ehci_qh * qh_header=NULL;
//void *global_buffer=NULL;
struct ehci_qh * qh_pointer[64];
extern struct ehci_qh *in_qh;
extern struct ehci_qh *out_qh;
extern struct ehci_qh *dummy_qh;
inline dma_addr_t get_qtd_dummy(void)
{
return qtd_dummy_first->qtd_dma;
}
void init_qh_and_qtd(void)
{
int n;
struct ehci_qtd * qtd;
struct ehci_qh * qh;
if(!qh_header)
{
//u32 mem = (u32) USB_Alloc(4096*3);
//mem=(mem+4095) & ~4095;
qh_header= (struct ehci_qh *) ehci->async;//mem;
qtd_header= (struct ehci_qtd *) ehci->qtds[0];
}
qtd=qtd_header;//= (struct ehci_qtd *) (((u32)qh_header)+4096);
for(n=0;n<EHCI_MAX_QTD;n++)
{
ehci->qtds[n]=qtd;
memset((void *) ehci->qtds[n], 0, sizeof(struct ehci_qtd));
ehci_dma_map_bidir((void *) ehci->qtds[n],sizeof(struct ehci_qtd));
qtd=(struct ehci_qtd *) (((((u32) qtd)+sizeof(struct ehci_qtd)+31) & ~31));
}
for(n=0;n<EHCI_MAX_QTD;n++)
{
memset((void *) qtd, 0, sizeof(struct ehci_qtd));
ehci_dma_map_bidir((void *) qtd,sizeof(struct ehci_qtd));
qtd=(struct ehci_qtd *) (((((u32) qtd)+sizeof(struct ehci_qtd)+31) & ~31));
}
qtd_dummy_first=qtd;
qh=qh_header;
for(n=0;n<6;n++)
{
qh_pointer[n]=qh;
memset((void *) qh_pointer[n], 0, sizeof(struct ehci_qh));
qh->qh_dma = ehci_virt_to_dma(qh);
qh_pointer[n]->hw_info1 = cpu_to_hc32((QH_HEAD*(n!=0)));
qh_pointer[n]->hw_info2 = cpu_to_hc32(0);
qh_pointer[n]->hw_token = cpu_to_hc32( QTD_STS_HALT);
qh=(struct ehci_qh *) (((((u32) qh)+sizeof(struct ehci_qh)+31) & ~31));
qh_pointer[n]->hw_next = QH_NEXT( ehci_virt_to_dma(qh));
qh_pointer[n]->hw_qtd_next =EHCI_LIST_END();
qh_pointer[n]->hw_alt_next = EHCI_LIST_END();
ehci_dma_map_bidir((void *) qh_pointer[n],sizeof(struct ehci_qh));
}
n--;
qh_pointer[n]->hw_next = QH_NEXT( ehci_virt_to_dma(qh_header));
ehci_dma_map_bidir((void *) qh_pointer[n],sizeof(struct ehci_qh));
}
void create_qtd_dummy(void)
{
int n;
struct ehci_qtd * qtd, *qtd_next;
qtd=qtd_dummy_first;
for(n=0;;n++)
{
qtd_next=(struct ehci_qtd *) (((((u32) qtd)+sizeof(struct ehci_qtd)+31) & ~31));
ehci_qtd_init(qtd);
//qtd_fill( qtd, 0, 0, QTD_STS_HALT, 0);
if(n<3)
{
qtd->hw_next= QTD_NEXT(qtd_next->qtd_dma);
qtd->hw_alt_next= EHCI_LIST_END(); //QTD_NEXT(qtd_next->qtd_dma);
ehci_dma_map_bidir((void *) qtd,sizeof(struct ehci_qtd));
}
else
{
ehci_dma_map_bidir(qtd,sizeof(struct ehci_qtd));
break;
}
qtd=qtd_next;
}
}
/*
int hola(void *i, void *o)
{
int n;
for(n=0;n<10;n++)
{
*((volatile u32 *)0x0d8000c0) ^=0x20;
ehci_mdelay(50);
}
}
*/
void reinit_ehci_headers(void)
{
init_qh_and_qtd();
create_qtd_dummy();
ehci->async= qh_pointer[0];
ehci->asyncqh= qh_pointer[1];
in_qh=qh_pointer[2];
out_qh=qh_pointer[3];
dummy_qh=qh_pointer[4];
ehci_dma_unmap_bidir((dma_addr_t) ehci->async,sizeof(struct ehci_qh));
ehci->async->ehci = ehci;
ehci->async->qtd_head = NULL;
ehci->async->qh_dma = ehci_virt_to_dma(ehci->async);
ehci->async->hw_next = QH_NEXT(dummy_qh->qh_dma/* ehci->async->qh_dma*/);
ehci->async->hw_info1 = cpu_to_hc32( QH_HEAD);
ehci->async->hw_info2 = cpu_to_hc32( 0);
ehci->async->hw_token = cpu_to_hc32( QTD_STS_HALT);
ehci->async->hw_qtd_next =EHCI_LIST_END();
ehci->async->hw_alt_next =EHCI_LIST_END(); //QTD_NEXT(get_qtd_dummy());
ehci_dma_map_bidir(ehci->async,sizeof(struct ehci_qh));
ehci_dma_unmap_bidir((dma_addr_t)ehci->asyncqh,sizeof(struct ehci_qh));
ehci->asyncqh->ehci = ehci;
ehci->asyncqh->qtd_head = NULL;
ehci->asyncqh->qh_dma = ehci_virt_to_dma(ehci->asyncqh);
ehci_dma_unmap_bidir((dma_addr_t)in_qh,sizeof(struct ehci_qh));
in_qh->ehci = ehci;
in_qh->qtd_head = NULL;
in_qh->qh_dma = ehci_virt_to_dma(in_qh);
ehci_dma_map_bidir(in_qh,sizeof(struct ehci_qh));
ehci_dma_unmap_bidir((dma_addr_t)out_qh,sizeof(struct ehci_qh));
out_qh->ehci = ehci;
out_qh->qtd_head = NULL;
out_qh->qh_dma = ehci_virt_to_dma(out_qh);
ehci_dma_map_bidir(out_qh,sizeof(struct ehci_qh));
}
int tiny_ehci_init(void)
{
int i;
ehci = &_ehci;
if(usb_os_init()<0)
return -1;
if(1)
{ // From Hermes: ohci mem is readed from dev/mload: (ehci init is from here)
/* int fd;
fd = os_open("/dev/mload",1);
if(fd<0) return -1;
ehci= (struct ehci_hcd *) os_ioctlv(fd, MLOAD_GET_EHCI_DATA ,0,0,0);
os_close(fd);
*/
ehci=swi_mload_EHCI_data();
// stops EHCI
ehci_writel( 0x00010020 , &ehci->regs->command);
do
{
if(!(ehci_readl( &ehci->regs->command) & 1))break;
} while(1);
ehci_dma_map_bidir(ehci,sizeof(struct ehci_hcd));
for (i = 0; i < DEFAULT_I_TDPS; i++)
{
ehci->periodic [i] = EHCI_LIST_END();
ehci_dma_map_bidir((void *) ehci->periodic [i],4);
}
reinit_ehci_headers();
//////////////////////////////////////////////////////////////////////////////////////////////
/* WARNING: This ignore the port 1 (external) and 2,3 (internals) for USB 2.0 operations */
/* from cIOS mload 1.6 port 1 is forced to USB 1.1. Only port 0 can work as USB 2.0 */
ehci->num_port=2;
ehci_release_ports();
//ehci_writel( 0x00080021, &ehci->regs->command);
//ehci_writel(0, &ehci->regs->frame_list);
ehci_writel(ehci->async->qh_dma, &ehci->regs->async_next);
ehci_writel (/*INTR_MASK*/STS_PCD, &ehci->regs->intr_enable);
#define t125us (1)
ehci_writel( (t125us<<16) | 0x0021 , &ehci->regs->command);
ehci_readl( &ehci->regs->command);
//swi_mload_led_on();
//swi_mload_call_func(hola,NULL,NULL);
/////////////////////////////////////////////////////////////////////////////////////////////
}
return 0;
}

90
ehcmodule/source/ums.c Normal file
View File

@ -0,0 +1,90 @@
#ifndef HOMEBREW
#include "syscalls.h"
#include "ios_usbstorage.h"
#include <stdarg.h>
#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)
static int fd;
static u32 sector_size;
static u32 num_sector;
static int heap;
/* */
void ums_init(void)
{
ioctlv *vec;
u32 *p_sector_size;
fd = os_open("/dev/usb2", 1);
if (fd < 0)
{
debug_printf("unable to open /dev/usb2 %d\n", fd);
return ;
}
os_ioctlv(fd, USB_IOCTL_UMS_INIT, 0, 0, 0);
heap = os_heap_create((void*)0x13898000, 0x8000);
vec = os_heap_alloc(heap, sizeof(ioctlv));
p_sector_size = os_heap_alloc(heap, sizeof(u32));
vec[0].data = p_sector_size;
vec[0].len = 4;
num_sector = os_ioctlv(fd, USB_IOCTL_UMS_GET_CAPACITY, 0, 1, vec);
sector_size = *p_sector_size;
debug_printf("found device %d %d: %dkB\n", sector_size, num_sector, sector_size*(num_sector / 1024));
os_heap_free(heap, vec);
os_heap_free(heap, p_sector_size);
}
void *ums_alloc(int size)
{
return os_heap_alloc(heap, size);
}
void ums_free(void *ptr)
{
os_heap_free(heap, ptr);
}
s32 ums_read_sectors(u32 sector, u32 numSectors, void *buffer)
{
ioctlv *vec;
u32 *p_sector;
u32 *p_nsector;
s32 ret;
vec = os_heap_alloc(heap, sizeof(ioctlv) * 3);
p_sector = os_heap_alloc(heap, sizeof(u32));
p_nsector = os_heap_alloc(heap, sizeof(u32));
*p_nsector = numSectors;
*p_sector = sector;
vec[0].data = p_sector;
vec[0].len = 4;
vec[1].data = p_nsector;
vec[1].len = 4;
vec[2].data = buffer;
vec[2].len = sector_size * numSectors;
ret = os_ioctlv(fd, USB_IOCTL_UMS_READ_SECTORS, 2, 1, vec);
// no need to flush cache, this is done by ehc..
os_heap_free(heap, vec);
os_heap_free(heap, p_sector);
os_heap_free(heap, p_nsector);
return ret;
}
void ums_close(void)
{
os_close(fd);
os_heap_destroy(heap);
fd = -1;
heap = -1;
}
#endif

90
ehcmodule/source/usb_os.c Normal file
View File

@ -0,0 +1,90 @@
#include "syscalls.h"
#include <string.h>
#include "ehci_types.h"
#include "usb.h"
#include "ehci.h"
static int heap=-1;
void ehci_usleep(int usec);
void ehci_msleep(int msec);
extern u8 heap_space2[0xe000];
int usb_os_init(void)
{
heap = os_heap_create(heap_space2, 0xe000);
//heap = os_heap_create((void*)0x13890000, 0x8000);
if(heap<0)
{
return -1;
}
return 0;
}
void read_cache_data(char *in, int len)
{
int n;
char t;
for(n=0;n<len;n++) t=*in++;
}
dma_addr_t ehci_virt_to_dma(void *a)
{
return (dma_addr_t)a;
}
dma_addr_t ehci_dma_map_to(void *buf,size_t len)
{
os_sync_after_write(buf, len);
return (dma_addr_t)buf;
}
dma_addr_t ehci_dma_map_from(void *buf,size_t len)
{
os_sync_after_write(buf, len);
return (dma_addr_t)buf;
}
dma_addr_t ehci_dma_map_bidir(void *buf,size_t len)
{
//debug_printf("sync_after_write %p %x\n",buf,len);
os_sync_after_write(buf, len);
return (dma_addr_t)buf;
}
void ehci_dma_unmap_to(dma_addr_t buf,size_t len)
{
os_sync_before_read((void*)buf, len);
read_cache_data((void *) buf, len);
}
void ehci_dma_unmap_from(dma_addr_t buf,size_t len)
{
os_sync_before_read((void*)buf, len);
read_cache_data((void *) buf, len);
}
void ehci_dma_unmap_bidir(dma_addr_t buf,size_t len)
{
os_sync_before_read((void*)buf, len);
read_cache_data((void *) buf, len);
}
void *USB_Alloc(int size)
{
void * ret = 0;
ret= os_heap_alloc_aligned(heap, size, 32);
// ret= os_heap_alloc(heap, size);
if(ret==0)
{
os_puts("USB Alloc: not enough memory!\n");
while(1) {swi_mload_led_on();ehci_msleep(200);swi_mload_led_off();ehci_msleep(200);}
}
return ret;
}
void USB_Free(void *ptr)
{
return os_heap_free(heap, ptr);
}

View File

@ -0,0 +1,132 @@
/*
Custom IOS module for Wii.
wbfs glue
Copyright (C) 2009 kwiirk.
Copyright (C) 2008 neimod.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*******************************************************************************
*
* oh0_loop.c - IOS module main code
* even if we are "ehc" driver, we still pretend to be "oh0"
* and implement "standard" ios oh0 usb api
*
*******************************************************************************
*
*/
#include <stdio.h>
#include <string.h>
#include "syscalls.h"
#include "libwbfs.h"
u32 n_sec,sec_size;
/*static*/ int read_sector(void *ign,u32 lba,u32 count,void*buf)
{
int ret;
os_sync_after_write(buf, count*sec_size);
/* do
{*/
ret = USBStorage_Read_Sectors(lba,count, buf);
/*}*/
if(!ret) return 1;
os_sync_before_read(buf, count*sec_size);
return 0;
}
static wbfs_disc_t *wbfs_disc=NULL;
u8 *disc_buff=NULL;
extern u32 current_disc_lba;
void wbfs_perform_disc(void)
{
if(wbfs_disc)
{
wbfs_close_disc(wbfs_disc);wbfs_disc=NULL;
}
if(!disc_buff) {disc_buff=WBFS_Alloc(0x8020);}
current_disc_lba=0xffffffff;
}
static wbfs_t *p=NULL;
void release_wbfs_mem(void)
{
if(disc_buff) WBFS_Free(disc_buff);disc_buff=NULL;
if(wbfs_disc)
{
wbfs_close_disc(wbfs_disc);wbfs_disc=NULL;
}
if(p)
wbfs_close(p);p= NULL;
}
wbfs_disc_t * wbfs_init_with_partition(u8*discid, int partition)
{
static u8 old_discid[6]="";
if(disc_buff) WBFS_Free(disc_buff);disc_buff=NULL;
// opens the hd only is is not opened
if(!p)
{
extern u32 current_port;
USBStorage_Init(current_port);
n_sec = USBStorage_Get_Capacity(&sec_size);
//debug_printf("hd found n_sec:%x sec_size %x\n",n_sec,sec_size);
if (n_sec==0)
return NULL; //no hd
p = wbfs_open_hd(read_sector, 0, 0, sec_size, n_sec,partition, 0);
if(!p) // no partition
return NULL;
}
// close previously disc opened except if discid is equal
if(wbfs_disc)
{
if(!memcmp(old_discid,discid,6)) return wbfs_disc;
wbfs_close_disc(wbfs_disc);wbfs_disc=NULL;
}
// open the disc
wbfs_disc=wbfs_open_disc(p, discid);
if(wbfs_disc) memcpy(old_discid,discid,6);
return wbfs_disc;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
<pd><ViewState><e p="gui" x="true"></e><e p="gui\source" x="false"></e></ViewState></pd>

View File

@ -0,0 +1,10 @@
#ifndef IOS_USBSTORAGE_H
#define IOS_USBSTORAGE_H
#include "syscalls.h"
void ums_init(void);
s32 ums_read_sectors(u32 sector, u32 numSectors, void *buffer);
void ums_close(void);
void *ums_alloc(int size);
void ums_free(void *ptr);
#endif

92
libcios/include/starlet.h Normal file
View File

@ -0,0 +1,92 @@
#ifndef STARLET_H
#define STARLET_H
// info from wiibrew.org
// IRQS (32 bits registers)
/*
IRQ Description
0 Starlet Timer
1 NAND Interface
2 AES Engine
3 SHA-1 Engine
4 USB Host Controller (EHCI)
5 USB Host Controller (OHCI0)
6 USB Host Controller (OHCI1)
7 SD Host Controller
8 802.11 Wireless
9 Unknown
10 Hollywood GPIOs (Broadway)
11 Hollywood GPIOs (Starlet)
12-16 Unknown
17 Reset button
18-29 Unknown
30 IPC (Broadway)
31 IPC (Starlet)
*/
#define HW_PPCIRQFLAG 0x0d800030 // Broadway IRQ Flags (write 1 to clear)
#define HW_PPCIRQMASK 0x0d800034 // Broadway IRQ Mask (write 1 to set)
#define HW_ARMIRQFLAG 0x0d800038 // Starlet IRQ Flags (write 1 to clear)
#define HW_ARMIRQMASK 0x0d80003c // Starlet IRQ Mask (write 1 to set)
// GPIOS (32 bits registers)
/*
Bit Direction Connection Description
0 IN POWER Power button input (pulse width limited; will not detect a held-down state).
1 OUT SHUTDOWN Output high to turn system off (Power LED = red).
2 OUT FAN Fan power, active high.
3 OUT DC_DC DC/DC converter power, active high (powers the Broadway?[check]). When off, also triggers the Yellow power LED.
4 OUT DI_SPIN DI spinup disable. If clear, the drive attempts to spin up a disc when reset (if there is one in the drive). If set, the drive ignores a present disc when reset.
5 OUT SLOT_LED Blue disc slot LED, active high.
6 IN EJECT_BTN Eject button (pulse width limited). Button press will also trigger the drive directly.
7 IN SLOT_IN Disc slot optical detector. High if disc in drive, disc being inserted, or disc still in slot after eject.
8 OUT SENSOR_BAR Sensor bar, active high.
9 OUT DO_EJECT Pulse high to trigger a DI eject from software.
10 OUT EEP_CS SEEPROM Chip Select.
11 OUT EEP_CLK SEEPROM Clock.
12 OUT EEP_MOSI Data to SEEPROM.
13 IN EEP_MISO Data from SEEPROM.
14 OUT AVE_SCL A/V Encoder I²C Clock.
15 I/O AVE_SDA A/V Encoder I²C Data (has an external pull-up, so you should only drive it low).
16 OUT DEBUG0 Debug Testpoint TP221.
17 OUT DEBUG1 Debug Testpoint TP222.
18 OUT DEBUG2 Debug Testpoint TP223.
19 OUT DEBUG3 Debug Testpoint TP224.
20 OUT DEBUG4 Debug Testpoint TP225.
21 OUT DEBUG5 Debug Testpoint TP226.
22 OUT DEBUG6 Debug Testpoint TP219.
23 OUT DEBUG7 Debug Testpoint TP220.
*/
#define HW_GPIOB_OUT 0x0d8000c0 // GPIO Outputs (Broadway access)
#define HW_GPIOB_DIR 0x0d8000c4 // GPIO Direction (Broadway access)
#define HW_GPIOB_IN 0x0d8000c8 // GPIO Inputs (Broadway access)
#define HW_GPIOB_INTLVL 0x0d8000cc // GPIO Interrupt Levels (Broadway access)
#define HW_GPIOB_INTFLAG 0x0d8000d0 // GPIO Interrupt Flags (Broadway access)
#define HW_GPIOB_INTMASK 0x0d8000d4 // GPIO Interrupt Masks (Broadway access)
#define HW_GPIOB_INMIR 0x0d8000d8 // GPIO Input Mirror (Broadway access)
#define HW_GPIO_ENABLE 0x0d8000dc // GPIO Enable (Starlet only)
#define HW_GPIO_OUT 0x0d8000e0 // GPIO Outputs (Starlet only)
#define HW_GPIO_DIR 0x0d8000e4 // GPIO Direction (Starlet only)
#define HW_GPIO_IN 0x0d8000e8 // GPIO Inputs (Starlet only)
#define HW_GPIO_INTLVL 0x0d8000ec // GPIO Interrupt Levels (Starlet only)
#define HW_GPIO_INTFLAG 0x0d8000f0 // GPIO Interrupt Flags (Starlet only)
#define HW_GPIO_INTMASK 0x0d8000f4 // GPIO Interrupt Masks (Starlet only)
#define HW_GPIO_INMIR 0x0d8000f8 // GPIO Input Mirror (Starlet only)
#define HW_GPIO_OWNER 0x0d8000fc // GPIO Owner Select (Starlet only)
// TIMER (32 bits registers)
#define HW_TIMER 0x0d800010 // Timer counter
#define HW_ALARM 0x0d800014 // Alarm value
#endif

233
libcios/include/swi_mload.h Normal file
View File

@ -0,0 +1,233 @@
/* SWI service from dev/mload (c) 2009 Hermes / www.elotrolado.net */
#ifndef IOS_SWI_MLOAD_H
#define IOS_SWI_MLOAD_H
#include "types.h"
#include "starlet.h"
/* NOTE: stack for SWI services is 0x900 bytes */
/* WARNING: Interrupt are disabled in SWI functions and you cannot call syscalls */
/***************************************************************************************************************************************************/
/*
swi_mload_add_handler: add a new service handler for SWI
svc_code: for example 0xab for svc 0xab
func: function for the new SWI service
return: none
*/
void swi_mload_add_handler(u8 svc_code, int (*func) (u32 arg0, u32 arg1, u32 arg2, u32 arg3));
/***************************************************************************************************************************************************/
/*
swi_mload_EHCI_data: gets the EHCI struct from dev/mload
return: the struct pointer
*/
void * swi_mload_EHCI_data(void);
/***************************************************************************************************************************************************/
/*
swi_mload_get_syscall_base: gets the syscall base address to call directly
return: the address
*/
u32 swi_mload_get_syscall_base(void);
/***************************************************************************************************************************************************/
/*
swi_mload_get_ios_base: gets the ios base (FFS, ES, IOSP) used to create this cIOS
return: the IOS base version
*/
u32 swi_mload_get_ios_base(void);
/***************************************************************************************************************************************************/
/*
swi_mload_memcpy: memcpy from supervisor mode
dst: destination address
src: source address
len: datas to move
return: none
*/
void swi_mload_memcpy(void * dst, void * src, int len);
/***************************************************************************************************************************************************/
/*
swi_mload_memcpy_from_uncached: memcpy from supervisor mode. Copies from uncached source RAM to cached RAM
dst: destination address
src: source address uncached
len: datas to move
return: none
*/
void swi_mload_memcpy_from_uncached(void * dst, void * src, int len);
/***************************************************************************************************************************************************/
/*
swi_mload_get_register: function thinking to read 32 bits registers from supervisor mode
addr: register address
return: value
*/
u32 swi_mload_get_register(u32 addr);
/***************************************************************************************************************************************************/
/*
swi_mload_put_register: function thinking to write 32 bits registers from supervisor mode
addr: register address
val: new value for register
return: none
*/
void swi_mload_put_register(u32 addr, u32 val);
/***************************************************************************************************************************************************/
/*
swi_mload_set_register: function thinking to set bits to 1 (with OR) in 32 bits registers from supervisor mode
addr: register address
val: bits to set must be 1 (operation reg|=val)
return: none
*/
void swi_mload_set_register(u32 addr, u32 val);
/***************************************************************************************************************************************************/
/*
swi_mload_clr_register: function thinking to clear bits to 0 (with AND) in 32 bits registers from supervisor mode
addr: register address
val: bits to clear must be 1 (operation register &=~value)
return: none
*/
void swi_mload_clr_register(u32 addr, u32 val);
/***************************************************************************************************************************************************/
/*
swi_mload_call_func: call to one function in Supervisor Mode
in: pointer to data in (received as argument 0 in the function)
out: pointer to data out (received as argument 0 in the function)
return: result from the function
*/
int swi_mload_call_func(int (*func) (void *in, void *out), void *in, void *out);
/***************************************************************************************************************************************************/
/*
swi_mload_led_on: frontal LED ON
return: none
*/
void swi_mload_led_on(void);
/***************************************************************************************************************************************************/
/*
swi_mload_led_off: frontal LED OFF
return: none
*/
void swi_mload_led_off(void);
/***************************************************************************************************************************************************/
/*
swi_mload_led_blink: frontal LED Blinking (note: it use a XOR function, so must call some times for blinking :P). It is thinking to see some activity...
return: none
*/
void swi_mload_led_blink(void);
/***************************************************************************************************************************************************/
/*
swi_mload_os_software_IRQ_func: function to call from os_software_IRQ(9) in system mode
system_mode_func: function address
return: none
*/
void swi_mload_os_software_IRQ9_func( int (*system_mode_func)(void));
/***************************************************************************************************************************************************/
/*
swi_mload_log_func: control the log buffer for os_puts()
mode: 0-> return log buffer 1-> clear log buffer 2-> set a new log buffer
buffer_log: new buffer log address (only with mode==2)
maxsize_log: max size for log (only with mode==2)
return: current buffer_log (by default 4KB) the string finish with '\0' code
*/
void * swi_mload_log_func(u32 mode, void *buffer_log, int maxsize_log);
/***************************************************************************************************************************************************/
#endif

115
libcios/include/syscalls.h Normal file
View File

@ -0,0 +1,115 @@
#ifndef IOS_SYSCALLS_H
#define IOS_SYSCALLS_H
#include "types.h"
typedef struct _ioctlv
{
void *data;
unsigned long len;
} ioctlv;
typedef struct ipcmessage
{
unsigned int command; // 0
unsigned int result; // 4
unsigned int fd; // 8
union
{
struct
{
char *device; // 12
unsigned int mode; // 16
unsigned int resultfd; // 20
} open;
struct
{
void *data;
unsigned int length;
} read, write;
struct
{
int offset;
int origin;
} seek;
struct
{
unsigned int command;
unsigned int *buffer_in;
unsigned int length_in;
unsigned int *buffer_io;
unsigned int length_io;
} ioctl;
struct
{
unsigned int command;
unsigned int num_in;
unsigned int num_io;
ioctlv *vector;
} ioctlv;
};
} __attribute__((packed)) ipcmessage;
// NOTE: I think "autostart" is a flag to indicate an internal (child thread) or external thread
int os_thread_create( unsigned int (*entry)(void* arg), void* arg, void* stack, unsigned int stacksize, unsigned int priority, int autostart);
void os_thread_set_priority(int id, unsigned int priority);
int os_thread_get_priority(void);
int os_get_thread_id(void);
int os_get_parent_thread_id(void);
int os_thread_continue(int id);
int os_thread_stop(int id);
int os_message_queue_create(void* ptr, unsigned int max_entries);
int os_message_queue_receive(int queue, unsigned int* message, unsigned int flags);
int os_message_queue_send(int queue, unsigned int message, int flags);
int os_message_queue_send_now(int queue, unsigned int message, int flags);
void os_message_queue_ack(void* message, int result);
int os_heap_create(void* ptr, int size);
int os_heap_destroy(int heap);
void* os_heap_alloc(int heap, unsigned int size);
void* os_heap_alloc_aligned(int heap, int size, int align);
void os_heap_free(int heap, void* ptr);
int os_device_register(const char* devicename, int queuehandle);
void os_sync_before_read(void* ptr, int size);
void os_sync_after_write(void* ptr, int size);
void os_syscall_50(unsigned int unknown);
int os_open(char* device, int mode);
int os_close(int fd);
int os_read(int fd, void *d, int len);
int os_write(int fd, void *s, int len);
int os_seek(int fd, int offset, int mode);
int os_ioctlv(int fd, int request, int in, int out, ioctlv *vector);
int os_ioctl(int fd, int request, void *in, int bytes_in, void *out, int bytes_out);
// timer control
int os_create_timer(int time_us, int repeat_time_us, int message_queue, int message); // return the timer_id
int os_destroy_timer(int time_id);
int os_stop_timer(int timer_id);
int os_restart_timer(int timer_id, int time_us); // restart one stopped timer
int os_timer_now(int time_id);
#define DEV_EHCI 4
int os_register_event_handler(int device, int queue, int message);
int os_unregister_event_handler(int device);
int os_software_IRQ(int dev);
void os_puts(char *str); // to create log in dev/mload
#ifdef DEBUG
void debug_printf(const char *fmt, ...);
void hexdump(void *d, int len);
#else
#define debug_printf(a...) do{}while(0)
#endif
#endif // IOS_SYSCALLS_H

144
libcios/include/types.h Normal file
View File

@ -0,0 +1,144 @@
#ifndef __GCTYPES_H__
#define __GCTYPES_H__
/*! \file gctypes.h
\brief Data type definitions
*/
typedef signed char int8_t ;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*+----------------------------------------------------------------------------------------------+*/
typedef unsigned char u8; ///< 8bit unsigned integer
typedef unsigned short u16; ///< 16bit unsigned integer
typedef unsigned int u32; ///< 32bit unsigned integer
typedef unsigned long long u64; ///< 64bit unsigned integer
/*+----------------------------------------------------------------------------------------------+*/
typedef signed char s8; ///< 8bit signed integer
typedef signed short s16; ///< 16bit signed integer
typedef signed int s32; ///< 32bit signed integer
typedef signed long long s64; ///< 64bit signed integer
/*+----------------------------------------------------------------------------------------------+*/
typedef volatile unsigned char vu8; ///< 8bit unsigned volatile integer
typedef volatile unsigned short vu16; ///< 16bit unsigned volatile integer
typedef volatile unsigned int vu32; ///< 32bit unsigned volatile integer
typedef volatile unsigned long long vu64; ///< 64bit unsigned volatile integer
/*+----------------------------------------------------------------------------------------------+*/
typedef volatile signed char vs8; ///< 8bit signed volatile integer
typedef volatile signed short vs16; ///< 16bit signed volatile integer
typedef volatile signed int vs32; ///< 32bit signed volatile integer
typedef volatile signed long long vs64; ///< 64bit signed volatile integer
/*+----------------------------------------------------------------------------------------------+*/
// fixed point math typedefs
typedef s16 sfp16; ///< 1:7:8 fixed point
typedef s32 sfp32; ///< 1:19:8 fixed point
typedef u16 ufp16; ///< 8:8 fixed point
typedef u32 ufp32; ///< 24:8 fixed point
/*+----------------------------------------------------------------------------------------------+*/
typedef float f32;
typedef double f64;
/*+----------------------------------------------------------------------------------------------+*/
typedef volatile float vf32;
typedef volatile double vf64;
/*+----------------------------------------------------------------------------------------------+*/
// bool is a standard type in cplusplus, but not in c.
#ifndef __cplusplus
/** C++ compatible bool for C
*/
typedef u8 bool;
enum { false, true };
#endif
typedef unsigned int BOOL;
/*+----------------------------------------------------------------------------------------------+*/
// alias type typedefs
#define FIXED s32 ///< Alias type for sfp32
/*+----------------------------------------------------------------------------------------------+*/
// boolean defines
#ifndef boolean
#define boolean u8
#endif
/*+----------------------------------------------------------------------------------------------+*/
#ifndef TRUE
#define TRUE 1 ///< True
#endif
/*+----------------------------------------------------------------------------------------------+*/
#ifndef FALSE
#define FALSE 0 ///< False
#endif
/*+----------------------------------------------------------------------------------------------+*/
#ifndef NULL
#define NULL 0 ///< Pointer to 0
#endif
/*+----------------------------------------------------------------------------------------------+*/
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 3412
#endif /* LITTLE_ENDIAN */
/*+----------------------------------------------------------------------------------------------+*/
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 1234
#endif /* BIGE_ENDIAN */
/*+----------------------------------------------------------------------------------------------+*/
#ifndef BYTE_ORDER
#define BYTE_ORDER BIG_ENDIAN
#endif /* BYTE_ORDER */
/*+----------------------------------------------------------------------------------------------+*/
//! argv structure
/*! \struct __argv
structure used to set up argc/argv
*/
struct __argv {
int argvMagic; //!< argv magic number, set to 0x5f617267 ('_arg') if valid
char *commandLine; //!< base address of command line, set of null terminated strings
int length;//!< total length of command line
int argc;
char **argv;
char **endARGV;
};
//! Default location for the system argv structure.
extern struct __argv *__system_argv;
// argv struct magic number
#define ARGV_MAGIC 0x5f617267
typedef uint32_t sec_t;
/* Attributes */
#ifndef ATTRIBUTE_ALIGN
# define ATTRIBUTE_ALIGN(v) __attribute__((aligned(v)))
#endif
#ifndef ATTRIBUTE_PACKED
# define ATTRIBUTE_PACKED __attribute__((packed))
#endif
/* Stack align */
#define STACK_ALIGN(type, name, cnt, alignment) \
u8 _al__##name[((sizeof(type)*(cnt)) + (alignment) + (((sizeof(type)*(cnt))%(alignment)) > 0 ? ((alignment) - ((sizeof(type)*(cnt))%(alignment))) : 0))]; \
type *name = (type*)(((u32)(_al__##name)) + ((alignment) - (((u32)(_al__##name))&((alignment)-1))))
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* TYPES_H */
/* END OF FILE */

140
libcios/source/printf.c Normal file
View File

@ -0,0 +1,140 @@
#include "syscalls.h"
#include <stdarg.h>
/**
@brief simple printf like function that write its output to os_puts
@param format the format string, followed by format arguments.
supported formatters are '%X' '%0*X' '% *X' '%d' '%u'
this may not be perfectly compliant with ANSI-C printf, but its suffisant for common debugging..
*/
#ifdef DEBUG
void debug_printf(const char *format, ...)
{
static const char HEX[] = "0123456789ABCDEF";
static const char hex[] = "0123456789abcdef";
const char *hexp = HEX;
int val,i;
unsigned int u_val, u_val_inv, base;
unsigned char c;
va_list list;
int zeros = 0,chars;
int spaces = 0;
char buffer[1024],*ptr;
va_start (list, format);
ptr = buffer;
for (;;) {
c = *format++;
while(c != '%' && c != '\0') // Until '%' or '\0'
{
*ptr++ = c;
c = *format++;
}
if(c == '\0')
{
*ptr++ = c;
va_end (list);
os_puts(buffer);
return ;
}
hexp = HEX;
CONTINUE_FORMAT:
switch (c = *format++) {
case '0': c = *format++;
if(c >= '1' && c <= '9')
{
zeros = c - '0';
goto CONTINUE_FORMAT;
}
else
format--;
break;
case ' ': c = *format++;
if(c >= '1' && c <= '9')
{
spaces = c - '0';
goto CONTINUE_FORMAT;
}
else
format--;
break;
case 'c': c = va_arg(list,int);
case '%':
*ptr++ = c;
continue;
case 's':
if(ptr!=buffer){
*ptr=0;
os_puts(buffer);
}
os_puts(va_arg(list,char*));
ptr=buffer;
break;
case '\0':
default: format--; continue; // will write it at next loop..
case 'u':
case 'd': base = 10; goto CONVERT_THIS;
case 'p': zeros = 8;case 'x' : hexp = hex;
case 'X':base = 16;
CONVERT_THIS:
val = va_arg(list,int);
if (c == 'd') {
if (val < 0) {
val = - val;
c = '-';
*ptr++ = c;
}
}
u_val = val;
u_val_inv = 0;
chars = 0;
while(u_val){u_val_inv*= base;u_val_inv += u_val %base;u_val/=base; chars++;}
if(chars == 0)chars++;
if(zeros){
for(i=zeros - chars;i>0;i--)
*ptr++ = '0';
}
if(spaces)
{
for(i=spaces - chars;i>0;i--)
*ptr++ = ' ';
}
do {
c = u_val_inv % base;
*ptr++ = hexp[c];
u_val_inv /= base;
chars --;
} while (chars>0);
zeros = 0;
spaces = 0;
}
}
}
char ascii(char s) {
if(s < 0x20) return '.';
if(s > 0x7E) return '.';
return s;
}
void hexdump(void *d, int len) {
u8 *data;
int i, off;
data = (u8*)d;
for (off=0; off<len; off += 16) {
debug_printf("%08x ",off);
for(i=0; i<16; i++)
if((i+off)>=len) debug_printf(" ");
else debug_printf("%02x ",data[off+i]);
debug_printf(" ");
for(i=0; i<16; i++)
if((i+off)>=len) debug_printf(" ");
else debug_printf("%c",ascii(data[off+i]));
debug_printf("\n");
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More