diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f7adc5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build +/.vscode \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..186e391 --- /dev/null +++ b/Makefile @@ -0,0 +1,151 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := boot +BUILD := build +SOURCES := source +DATA := data +INCLUDES := + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) +CXXFLAGS = $(CFLAGS) + +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lwiiuse -lbte -logc -lm -lruntimeiospatch + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBOGC_INC) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +run: + wiiload $(TARGET).dol + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .jpg extension +#--------------------------------------------------------------------------------- +%.wad.o : %.wad +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + $(bin2o) + +%.certs.o : %.certs + @echo $(notdir $<) + $(bin2o) + +%.dat.o : %.dat + @echo $(notdir $<) + $(bin2o) + +%.tmd.o : %.tmd + @echo $(notdir $<) + $(bin2o) + +%.tik.o : %.tik + @echo $(notdir $<) + $(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/data/certs.dat b/data/certs.dat new file mode 100644 index 0000000..2184107 Binary files /dev/null and b/data/certs.dat differ diff --git a/data/haxx.certs b/data/haxx.certs new file mode 100644 index 0000000..32dd50c Binary files /dev/null and b/data/haxx.certs differ diff --git a/source/detect_settings.c b/source/detect_settings.c new file mode 100644 index 0000000..9b65f33 --- /dev/null +++ b/source/detect_settings.c @@ -0,0 +1,286 @@ +/*------------------------------------------------------------- + +detect_settings.c -- detects various system settings + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#include +#include +#include + +#include "id.h" +#include "wiibasics.h" +#include "detect_settings.h" + +u16 get_installed_title_version(u64 title) { + s32 ret, fd; + static char filepath[256] ATTRIBUTE_ALIGN(32); + + // Check to see if title exists + if (ES_GetDataDir(title, filepath) >= 0 ) { + u32 tmd_size; + static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); + + ret = ES_GetStoredTMDSize(title, &tmd_size); + if (ret < 0){ + // If we fail to use the ES function, try reading manually + // This is a workaround added since some IOS (like 21) don't like our + // call to ES_GetStoredTMDSize + + //printf("Error! ES_GetStoredTMDSize: %d\n", ret); + + sprintf(filepath, "/title/%08lx/%08lx/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title)); + + ret = ISFS_Open(filepath, ISFS_OPEN_READ); + if (ret <= 0) + { + printf("Error! ISFS_Open (ret = %ld)\n", ret); + return 0; + } + + fd = ret; + + ret = ISFS_Seek(fd, 0x1dc, 0); + if (ret < 0) + { + printf("Error! ISFS_Seek (ret = %ld)\n", ret); + return 0; + } + + ret = ISFS_Read(fd,tmd_buf,2); + if (ret < 0) + { + printf("Error! ISFS_Read (ret = %ld)\n", ret); + return 0; + } + + ret = ISFS_Close(fd); + if (ret < 0) + { + printf("Error! ISFS_Close (ret = %ld)\n", ret); + return 0; + } + + return be16(tmd_buf); + + } else { + // Normal versions of IOS won't have a problem, so we do things the "right" way. + + // Some of this code adapted from bushing's title_lister.c + signed_blob *s_tmd = (signed_blob *)tmd_buf; + ret = ES_GetStoredTMD(title, s_tmd, tmd_size); + if (ret < 0){ + printf("Error! ES_GetStoredTMD: %ld\n", ret); + return -1; + } + tmd *t = SIGNATURE_PAYLOAD(s_tmd); + return t->title_version; + } + + } + return 0; +} + +u64 get_title_ios(u64 title) { + s32 ret, fd; + static char filepath[256] ATTRIBUTE_ALIGN(32); + + // Check to see if title exists + if (ES_GetDataDir(title, filepath) >= 0 ) { + u32 tmd_size; + static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); + + ret = ES_GetStoredTMDSize(title, &tmd_size); + if (ret < 0){ + // If we fail to use the ES function, try reading manually + // This is a workaround added since some IOS (like 21) don't like our + // call to ES_GetStoredTMDSize + + //printf("Error! ES_GetStoredTMDSize: %d\n", ret); + + sprintf(filepath, "/title/%08lx/%08lx/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title)); + + ret = ISFS_Open(filepath, ISFS_OPEN_READ); + if (ret <= 0) + { + printf("Error! ISFS_Open (ret = %ld)\n", ret); + return 0; + } + + fd = ret; + + ret = ISFS_Seek(fd, 0x184, 0); + if (ret < 0) + { + printf("Error! ISFS_Seek (ret = %ld)\n", ret); + return 0; + } + + ret = ISFS_Read(fd,tmd_buf,8); + if (ret < 0) + { + printf("Error! ISFS_Read (ret = %ld)\n", ret); + return 0; + } + + ret = ISFS_Close(fd); + if (ret < 0) + { + printf("Error! ISFS_Close (ret = %ld)\n", ret); + return 0; + } + + return be64(tmd_buf); + + } else { + // Normal versions of IOS won't have a problem, so we do things the "right" way. + + // Some of this code adapted from bushing's title_lister.c + signed_blob *s_tmd = (signed_blob *)tmd_buf; + ret = ES_GetStoredTMD(title, s_tmd, tmd_size); + if (ret < 0){ + printf("Error! ES_GetStoredTMD: %ld\n", ret); + return -1; + } + tmd *t = SIGNATURE_PAYLOAD(s_tmd); + return t->sys_version; + } + + } + return 0; +} + +/* Get Sysmenu Region identifies the region of the system menu (not your Wii) + by looking into it's resource content file for region information. */ +char get_sysmenu_region(void) +{ + s32 ret, cfd; + static u8 fbuffer[0x500] ATTRIBUTE_ALIGN(32); + static tikview viewdata[0x10] ATTRIBUTE_ALIGN(32); + u32 views; + static u64 tid ATTRIBUTE_ALIGN(32) = TITLE_ID(1,2); + u8 region, match[] = "FINAL"; + + + /*ret = ES_SetUID(TITLE_ID(1,2)); + if (ret){ + printf("Error! ES_GetSetUID %d\n", ret); + wait_anyKey(); + return 0; + } + + ret = ES_GetTitleID(&tid); + if (ret){ + printf("Error! ES_GetTitleID %d\n", ret); + wait_anyKey(); + return 0; + } + if (tid != TITLE_ID(1,2)){ + printf("Error! Not System Menu! %016llx\n", tid); + wait_anyKey(); + return 0; + } + ret = ES_OpenContent(1); + if (ret < 0) + { + printf("Error! ES_OpenContent (ret = %d)\n", ret); + wait_anyKey(); + return 0; + }*/ + + ret = ES_GetNumTicketViews(tid, &views); + if (ret < 0) { + printf(" Error! ES_GetNumTickets (ret = %ld)\n", ret); + wait_anyKey(); + return ret; + } + + if (!views) { + printf(" No tickets found!\n"); + wait_anyKey(); + return 0; + } else if (views > 16) { + printf(" Too many ticket views! (views = %ld)\n", views); + wait_anyKey(); + return 0; + } + + ret = ES_GetTicketViews(tid, viewdata, 1); + if (ret < 0) + { + printf("Error! ES_OpenTitleContent (ret = %ld)\n", ret); + wait_anyKey(); + return 0; + } + + ret = ES_OpenTitleContent(tid, viewdata, 1); + if (ret < 0) + { + printf("Error! ES_OpenTitleContent (ret = %ld)\n", ret); + wait_anyKey(); + return 0; + } + + cfd = ret; + region = 0; + while (!region){ + int i; + ret = ES_ReadContent(cfd,fbuffer,0x500); + if (ret < 0) + { + printf("Error! ES_ReadContent (ret = %ld)\n", ret); + wait_anyKey(); + return 0; + } + + for(i=0;i<0x500;i++) { + if (fbuffer[i] == 'F'){ + if (!memcmp(&fbuffer[i], match, 6)){ + region = fbuffer[i+6]; + break; + } + } + } + + } + ret = ES_CloseContent(cfd); + if (ret < 0) + { + printf("Error! ES_CloseContent (ret = %ld)\n", ret); + wait_anyKey(); + return 0; + } + + switch (region){ + case 'U': + case 'E': + case 'J': + return region; + break; + default: + return -1; + break; + } +} diff --git a/source/detect_settings.h b/source/detect_settings.h new file mode 100644 index 0000000..eaeda93 --- /dev/null +++ b/source/detect_settings.h @@ -0,0 +1,41 @@ +/*------------------------------------------------------------- + +detect_settings.h -- detects various system settings + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#ifndef __SYSMENU_DETECT_H_ +#define __SYSMENU_DETECT_H_ + +//Get the title version of a given title +u16 get_installed_title_version(u64 title); + +//Get the IOS version of a given title +u64 get_title_ios(u64 title); + +//Get the region that the System menu is currently using +char get_sysmenu_region(void); + +#endif diff --git a/source/gecko.c b/source/gecko.c new file mode 100644 index 0000000..ae49ffd --- /dev/null +++ b/source/gecko.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include +#include +#include +#include //for mkdir + +//#include "fat2.h" +//#include "install.h" + + +/* init-globals */ +static bool geckoinit = false; +char DirPath[64] = "Fat:/debug"; +char SavePath[128]; +int ret = 0; +int vasprintf(char **, const char *, va_list); + +//#ifndef NO_DEBUG +#include + +void gprintf(const char *format, ...) +{ + if (!geckoinit) + return; + + char * tmp = NULL; + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + usb_sendbuffer(1, tmp, strlen(tmp)); + } + va_end(va); + + if(tmp) + free(tmp); +} + +bool InitGecko() +{ + u32 geckoattached = usb_isgeckoalive(EXI_CHANNEL_1); + if (geckoattached) + { + usb_flush(EXI_CHANNEL_1); + geckoinit = true; + return true; + } + + return false; +} +void gecko_log(const char *format, ...) { + //ret = Fat_MakeDir(DirPath); + //void *f = NULL; + gprintf("\n\n Fat Make Dir ret[%i] \n\n", ret); + + if (!geckoinit) + return; + + char * tmp = NULL; + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + sprintf(SavePath, "%s/debug.log", DirPath); + //f = &tmp; + //Fat_SaveFilelog(SavePath, f, strlen(tmp)); + // usb_sendbuffer(1, tmp, strlen(tmp)); + } + va_end(va); + //if(tmp) + // free(tmp); + tmp = NULL; + //f = NULL; +} + +char ascii2(char s) +{ + if (s < 0x20) return '.'; + if (s > 0x7E) return '.'; + return s; +} + +void hexdump2(void *d, int len) +{ + u8 *data; + int i, off; + data = (u8*) d; + + gprintf("\n 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF"); + gprintf("\n==== =============================================== ================\n"); + + for (off = 0; off < len; off += 16) + { + gprintf("%04x ", off); + for (i = 0; i < 16; i++) + if ((i + off) >= len) + gprintf(" "); + else gprintf("%02x ", data[off + i]); + + gprintf(" "); + for (i = 0; i < 16; i++) + if ((i + off) >= len) + gprintf(" "); + else gprintf("%c", ascii2(data[off + i])); + gprintf("\n"); + } +} + +static ssize_t __out_write(struct _reent *r, int fd, const char *ptr, size_t len) +{ + if(geckoinit && ptr) + { + usb_sendbuffer(1, ptr, len); + } + return len; +} + +static const devoptab_t gecko_out = { + "stdout", // device name + 0, // size of file structure + NULL, // device open + NULL, // device close + __out_write, // device write + NULL, // device read + NULL, // device seek + NULL, // device fstat + NULL, // device stat + NULL, // device link + NULL, // device unlink + NULL, // device chdir + NULL, // device rename + NULL, // device mkdir + 0, // dirStateSize + NULL, // device diropen_r + NULL, // device dirreset_r + NULL, // device dirnext_r + NULL, // device dirclose_r + NULL, // device statvfs_r + NULL, // device ftruncate_r + NULL, // device fsync_r + NULL, // device deviceData + NULL, // device chmod_r + NULL, // device fchmod_r +}; + +void USBGeckoOutput() +{ + devoptab_list[STD_OUT] = &gecko_out; + devoptab_list[STD_ERR] = &gecko_out; +} + +//#endif /* NO_DEBUG */ diff --git a/source/gecko.h b/source/gecko.h new file mode 100644 index 0000000..afe4935 --- /dev/null +++ b/source/gecko.h @@ -0,0 +1,30 @@ + +#ifndef _GECKO_H_ +#define _GECKO_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + char ascii2(char s); + +//#ifndef NO_DEBUG + //use this just like printf(); + void gprintf(const char *str, ...); + bool InitGecko(); + void hexdump2(void *d, int len); + void USBGeckoOutput(); + void gecko_log(const char *str, ...); +//#else +//#define gprintf(...) +//#define InitGecko() false +//#define hexdump( x, y ) +//#endif /* NO_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/id.c b/source/id.c new file mode 100644 index 0000000..d3ae1b3 --- /dev/null +++ b/source/id.c @@ -0,0 +1,232 @@ +/*------------------------------------------------------------- + +id.c -- ES Identification code + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "wiibasics.h" +#include "id.h" +#include "gecko.h" +#include "sha1.h" +#include "certs_dat.h" + + + +/* Debug functions adapted from libogc's es.c */ +//#define DEBUG_ES +//#define DEBUG_IDENT +#define ISALIGNED(x) ((((u32)x)&0x1F)==0) + +static u8 su_tmd[0x208] ATTRIBUTE_ALIGN(32); +static u8 su_tik[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(32); +int su_id_filled = 0; + +#ifdef DEBUG_IDENT +s32 __sanity_check_certlist(const signed_blob *certs, u32 certsize) +{ + int count = 0; + signed_blob *end; + + if(!certs || !certsize) return 0; + + end = (signed_blob*)(((u8*)certs) + certsize); + while(certs != end) { +#ifdef DEBUG_ES + printf("Checking certificate at %p\n",certs); +#endif + certs = ES_NextCert(certs); + if(!certs) return 0; + count++; + } +#ifdef DEBUG_ES + printf("Num of certificates: %d\n",count); +#endif + return count; +} +#endif +void zero_sig(signed_blob *sig) { + u8 *sig_ptr = (u8 *)sig; + memset(sig_ptr + 4, 0, SIGNATURE_SIZE(sig)-4); +} + +void brute_tmd(tmd *p_tmd) { + u16 fill; + for(fill=0; fill<65535; fill++) { + p_tmd->fill3=fill; + sha1 hash; + // debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash); + SHA1((u8 *)p_tmd, TMD_SIZE(p_tmd), hash);; + + if (hash[0]==0) { + // debug_printf("setting fill3 to %04hx\n", fill); + return; + } + } + printf("Unable to fix tmd :(\n"); + exit(4); +} + +void brute_tik(tik *p_tik) { + u16 fill; + for(fill=0; fill<65535; fill++) { + p_tik->padding=fill; + sha1 hash; + // debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash); + SHA1((u8 *)p_tik, sizeof(tik), hash); + + if (hash[0]==0) return; + } + printf("Unable to fix tik :(\n"); + exit(5); +} + +void forge_tmd(signed_blob *s_tmd) { +// debug_printf("forging tmd sig"); + zero_sig(s_tmd); + brute_tmd(SIGNATURE_PAYLOAD(s_tmd)); +} + +void forge_tik(signed_blob *s_tik) { +// debug_printf("forging tik sig"); + zero_sig(s_tik); + brute_tik(SIGNATURE_PAYLOAD(s_tik)); +} + + +void Make_SUID(void) { + signed_blob *s_tmd, *s_tik; + tmd *p_tmd; + tik *p_tik; + + memset(su_tmd, 0, sizeof su_tmd); + memset(su_tik, 0, sizeof su_tik); + s_tmd = (signed_blob*)&su_tmd[0]; + s_tik = (signed_blob*)&su_tik[0]; + *s_tmd = *s_tik = 0x10001; + p_tmd = (tmd*)SIGNATURE_PAYLOAD(s_tmd); + p_tik = (tik*)SIGNATURE_PAYLOAD(s_tik); + + + strcpy(p_tmd->issuer, "Root-CA00000001-CP00000004"); + p_tmd->title_id = TITLE_ID(1,2); + + p_tmd->num_contents = 1; + + forge_tmd(s_tmd); + + strcpy(p_tik->issuer, "Root-CA00000001-XS00000003"); + p_tik->ticketid = 0x000038A45236EE5FLL; + p_tik->titleid = TITLE_ID(1,2); + + memset(p_tik->cidx_mask, 0xFF, 0x20); + forge_tik(s_tik); + + su_id_filled = 1; + +} + +s32 Identify(const u8 *certs, u32 certs_size, const u8 *idtmd, u32 idtmd_size, const u8 *idticket, u32 idticket_size) { + s32 ret; + u32 keyid = 0; + ret = ES_Identify((signed_blob*)certs, certs_size, (signed_blob*)idtmd, idtmd_size, (signed_blob*)idticket, idticket_size, &keyid); + if (ret < 0){ + switch(ret){ + case ES_EINVAL: + printf("Error! ES_Identify (ret = %ld;) Data invalid!\n", ret); + break; + case ES_EALIGN: + printf("Error! ES_Identify (ret = %ld;) Data not aligned!\n", ret); + break; + case ES_ENOTINIT: + printf("Error! ES_Identify (ret = %ld;) ES not initialized!\n", ret); + break; + case ES_ENOMEM: + printf("Error! ES_Identify (ret = %ld;) No memory!\n", ret); + break; + default: + printf("Error! ES_Identify (ret = %ld)\n", ret); + break; + } +#ifdef DEBUG_IDENT + printf("\tTicket: %u Std: %u Max: %u\n", idticket_size, STD_SIGNED_TIK_SIZE, MAX_SIGNED_TMD_SIZE); + printf("\tTMD invalid? %d %d %d Tik invalid? %d %d\n", !(signed_blob*)idtmd, !idtmd_size, !IS_VALID_SIGNATURE((signed_blob*)idtmd), !(signed_blob*)idticket, !IS_VALID_SIGNATURE((signed_blob*)idticket)); + printf("\tCerts: Sane? %d\n", __sanity_check_certlist((signed_blob*)certs, certs_size)); + if (!ISALIGNED(certs)) printf("\tCertificate data is not aligned!\n"); + if (!ISALIGNED(idtmd)) printf("\tTMD data is not aligned!\n"); + if (!ISALIGNED(idticket)) printf("\tTicket data is not aligned!\n"); +#endif + } + else + printf("OK!\n"); + return ret; +} + + +s32 Identify_SU(void) { + if (!su_id_filled) + Make_SUID(); + + gprintf("\nIdentifying as SU..."); + fflush(stdout); + return Identify(certs_dat, certs_dat_size, su_tmd, sizeof su_tmd, su_tik, sizeof su_tik); +} + +s32 Identify_SysMenu(void) { + s32 ret; + u32 sysmenu_tmd_size, sysmenu_ticket_size; + //static u8 certs[0xA00] ATTRIBUTE_ALIGN(32); + static u8 sysmenu_tmd[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); + static u8 sysmenu_ticket[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(32); + + /*printf("\nPulling Certs..."); + ret = ISFS_ReadFileToArray ("/sys/certs.sys", certs, 0xA00, &certs_size); + if (ret < 0) { + printf("\tReading Certs failed!\n"); + return -1; + }*/ + + printf("\nPulling Sysmenu TMD..."); + ret = ISFS_ReadFileToArray ("/title/00000001/00000002/content/title.tmd", sysmenu_tmd, MAX_SIGNED_TMD_SIZE, &sysmenu_tmd_size); + if (ret < 0) { + printf("\tReading TMD failed!\n"); + return -1; + } + + printf("\nPulling Sysmenu Ticket..."); + ret = ISFS_ReadFileToArray ("/ticket/00000001/00000002.tik", sysmenu_ticket, STD_SIGNED_TIK_SIZE, &sysmenu_ticket_size); + if (ret < 0) { + printf("\tReading TMD failed!\n"); + return -1; + } + + printf("\nIdentifying as SysMenu..."); + fflush(stdout); + return Identify(certs_dat, certs_dat_size, sysmenu_tmd, sysmenu_tmd_size, sysmenu_ticket, sysmenu_ticket_size); +} diff --git a/source/id.h b/source/id.h new file mode 100644 index 0000000..5081009 --- /dev/null +++ b/source/id.h @@ -0,0 +1,38 @@ +/*------------------------------------------------------------- + +id.h -- ES Identification code + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#ifndef _ID_H_ +#define _ID_H_ + +// Identify as the "super user" +s32 Identify_SU(void); + +// Identify as the system menu +s32 Identify_SysMenu(void); + +#endif diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..13cc1d6 --- /dev/null +++ b/source/main.c @@ -0,0 +1,405 @@ +/*------------------------------------------------------------- + +regionchange.c -- Region Changing application + +Copyright (C) 2008 tona + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wiibasics.h" +#include "runtimeiospatch.h" +#include "sysconf.h" +#include "id.h" +#include "detect_settings.h" +#include "gecko.h" + +#define ITEMS 11 +#define SADR_LENGTH 0x1007 + 1 +#define WARNING_SIGN "\x1b[30;1m\x1b[43;1m/!\\\x1b[37;1m\x1b[40m" +#define maxdata 256 + +u32 selected = 0; +char page_contents[ITEMS][64]; + +int lang, area, game, video, region, country, countrystr, eula; +u8 sadr[SADR_LENGTH]; + +char languages[][ITEMS] = {"Japanese ", "English ", "German ", "French ", "Spanish ", "Italian ", "Dutch "}; +char areas[][ITEMS] = {"Japan ", "USA ", "Europe ", "Australia", "Brazil ", "Taiwan ", "China ", "Korea ", "Hong Kong", "Asia ", "Latin Am.", "S. Africa"}; +char regions[][ITEMS] = {"Japan ", "USA ", "Europe ", "Korea "}; +char vmodes[][ITEMS] = {"NTSC ", "PAL ", "MPAL "}; +char eulas[][ITEMS] = {"Unread ", "Read "}; + +void draw_credits() { + ClearScreen(); + PrintBanner(); + Console_SetPosition(3, 0); + printf("\t\t\t\tCREDITS:\n\n\n"); + printf("\tOriginal Program:\n"); + printf("\t- Tona\n"); + printf("\n\tOthers in Original Credits: \n"); + printf("\t- Bushing, svpe, Marcan, Waninkoko, Crediar, \n"); + printf("\t- ChipD, Sorak05, serlex, pcg, callmebob, and dieforit .\n"); + printf("\n\tARC ModMii Edition: \n"); + printf("\t- Scooby74029(FakeCoder) - Coding \n"); + printf("\t- Xflak - testing, overall help \n"); + printf("\t- To Many Coders To Thank For The Great Code I Used ..... \n"); + printf("\n"); + Console_SetPosition(26,0); + ClearLine(); + Console_SetPosition(26, 20); + printf("Press Any Button To Return ..... "); +} +void Draw_Disclaimer() { + ClearScreen(); + PrintBanner(); + printf("\n\t This software comes supplied with absolutely no warranty.\n"); + printf("\t\t\t\tUse this software at your own risk.\n"); + + printf("\n\n\n\t\t\t\t" WARNING_SIGN " IMPORTANT BRICK INFORMATION " WARNING_SIGN "\n\n"); + printf("\n\tSemi Bricks are caused by the Console Area setting not matching\n"); + printf("\tyour System Menu region. A semi-brick in itself is not terribly\n"); + printf("\tharmful, but it can easily deteriorate into a full brick--there\n"); + printf("\tare multiple simple triggers to do so.\n"); + printf("\n\n\n\tIn order to practice proper safety when using this application, \n"); + printf("\tplease make sure that your Console Area and System Menu region \n"); + printf("\tare congruent before rebooting your system. A warning will be\n"); + printf("\tdisplayed if they are not in agreement.\n"); + + sleep(5); + printf("\n\n\n\n\t\t\t\t[A] Continue [Home] Exit\n"); + wait_key(WPAD_BUTTON_A); +} +void handleError(const char* string, int errorval){ + printf("Unexpected Error: %s Value: %d\n", string, errorval); + printf("Press any key to quit\n"); + wait_anyKey(); + exit(0); +} + +void getSettings(void){ + int ret; + lang = SYSCONF_GetLanguage(); + area = SYSCONF_GetArea(); + game = SYSCONF_GetRegion(); + video = SYSCONF_GetVideo(); + eula = SYSCONF_GetEULA(); + if (lang < 0 || area < 0 || game < 0 || video < 0 || (eula != SYSCONF_ENOENT && eula < 0)){ + printf("Error getting settings! %d, %d, %d, %d, %d\n", lang, area, game, video, eula); + wait_anyKey(); + exit(1); + } + + if (SYSCONF_GetLength("IPL.SADR") != SADR_LENGTH) handleError("IPL.SADR Length Incorrect", SYSCONF_GetLength("IPL.SADR")); + ret = SYSCONF_Get("IPL.SADR", sadr, SADR_LENGTH); + if (ret < 0 ) handleError("SYSCONF_Get IPL.SADR", ret); + country = sadr[0]; + gprintf("\n\ncountry[%i] \n\n", country); + +} + +void saveSettings(void){ + Console_SetPosition(24, 0); + int ret = 0; + if (lang != SYSCONF_GetLanguage()) ret = SYSCONF_SetLanguage(lang); + if (ret) handleError("SYSCONF_SetLanguage", ret); + if (area != SYSCONF_GetArea()) ret = SYSCONF_SetArea(area); + if (ret) handleError("SYSCONF_SetArea", ret); + if(game != SYSCONF_GetRegion()) ret = SYSCONF_SetRegion(game); + if (ret) handleError("SYSCONF_SetRegion", ret); + if (video != SYSCONF_GetVideo()) ret = SYSCONF_SetVideo(video); + if (ret) handleError("SYSCONF_SetVideo", ret); + if (eula != SYSCONF_GetEULA()) ret = SYSCONF_SetEULA(eula); + if (ret) handleError("SYSCONF_SetEULA", ret); + + if (country != sadr[0]){ + memset(sadr, 0, SADR_LENGTH); + sadr[0] = country; + ret = SYSCONF_Set("IPL.SADR", sadr, SADR_LENGTH); + if (ret) handleError("SYSCONF_Set IPL.SADR", ret); + } + //wait_anyKey(); + printf("Saving..."); + ret = SYSCONF_SaveChanges(); + if (ret < 0) handleError("SYSCONF_SaveChanges", ret); + else printf("OK!\n"); + printf("Press any key to continue ....."); + wait_anyKey(); +} + +void updateSelected(int delta){ + if (selected + delta >= ITEMS || selected + delta < 0) return; + + if (delta != 0){ + // Remove the cursor from the last selected item + page_contents[selected][1] = ' '; + page_contents[selected][45] = ' '; + page_contents[selected][57] = ' '; + // Set new cursor location + selected += delta; + } + + // Add the cursor to the now-selected item + page_contents[selected][1] = '>'; + page_contents[selected][45] = '<'; + page_contents[selected][57] = '>'; +} + +void updatePage(void){ + + sprintf(page_contents[0], " %-40s %10s \n", "Language Setting:", languages[lang]); + sprintf(page_contents[1], " %-40s %10s \n", "Console Area Setting:", areas[area]); + sprintf(page_contents[2], " %-40s %10s \n", "Game Region Setting:", regions[game]); + sprintf(page_contents[3], " %-40s %10s \n", "Console Video Mode:", vmodes[video]); + sprintf(page_contents[4], " %-40s %10d \n", "Shop Country Code:", country); + sprintf(page_contents[5], " %-40s %10s \n", "Services EULA:", (eula == SYSCONF_ENOENT)?"Disabled":eulas[eula]); + sprintf(page_contents[6], " %-40s %10s \n", "Revert Settings", "Revert "); + sprintf(page_contents[7], " %-40s %10s \n", "Save Settings", "Save "); + sprintf(page_contents[8], " %-40s %10s \n", "Auto Fix Settings ", "Fix "); + sprintf(page_contents[9], " %-40s %10s \n", "Exit to the Homebrew Channel", "Exit "); + sprintf(page_contents[10], " %-40s %10s \n", "Reboot to System Menu", "Reboot "); + + updateSelected(0); +} +char AREAtoSysMenuRegion(int area){ + // Data based on my own tests with AREA/Sysmenu + switch (area){ + case 0: + case 5: + case 6: + return 'J'; + case 1: + case 4: + case 7: + case 8: + case 9: + case 10: + case 11: + return 'U'; + case 2: + case 3: + return 'E'; + default: + return 0; + } +} + +//--------------------------------------------------------------------------------- +int main(int argc, char **argv) { +//--------------------------------------------------------------------------------- + int ret = 0, i; + u16 sysmenu_version; + char sysmenu_region; + bool needbreak = false; + u32 buttons; + Current_Ios = 0; + + ret = IOS_ReloadIOS(236); + if(ret != 0) { + ret = IOS_ReloadIOS(249); + if(ret != 0) { + IosPatch_FULL(true, true, false, false, 58); + } + } + basicInit(); + + miscInit(); + if(InitGecko()) + USBGeckoOutput(); + Current_Ios = IOS_GetVersion(); + gprintf("\n\ncurrent_ios [%i] \n\n", Current_Ios); + + sysmenu_version = get_installed_title_version(TITLE_ID(1,2)); + sysmenu_region = get_sysmenu_region(); + gprintf("\n\nsysmenu_version[%u] sysmenu_region[%c] \n\n", sysmenu_version, sysmenu_region); + gprintf("Init SYSCONF..."); + ret = SYSCONF_Init(); + if (ret < 0) handleError("SYSCONF_Init", ret); + else gprintf("OK!\n"); + + getSettings(); + region = game; + Draw_Disclaimer(); + updatePage(); + + while(1) { + + PrintBanner(); + printf("\n------------------------------------------------------------------------"); + printf("Edit Region Settings"); + if (sysmenu_region != 0 && sysmenu_region != AREAtoSysMenuRegion(area)) + printf(" " WARNING_SIGN " \x1b[41;1mWARNING: AREA/SysMenu MISMATCH!\x1b[40m " WARNING_SIGN); + printf("\n------------------------------------------------------------------------"); + for (i = 0; i < 4; i++) + printf(page_contents[i]); + + printf("\t Country Codes: \t1[JPN] 49[USA] 110[UK] 136[KOR]\n"); + + for (i = i; i < 8; i++) + printf(page_contents[i]); + printf("------------------------------------------------------------------------"); + printf("Auto Fix\n"); + printf("------------------------------------------------------------------------"); + for (i = i; i < 9; i++) + printf(page_contents[i]); + printf("------------------------------------------------------------------------"); + printf("Exiting Options\n"); + printf("------------------------------------------------------------------------"); + for (i = i; i < ITEMS; i++) + printf(page_contents[i]); + printf("------------------------------------------------------------------------"); + Console_SetPosition(26, 0); + printf("Change Selection: [%s%s %s%s]\t\t\t\t\t\tSelect: [A]\tCredits: [1]", LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW); + buttons = wait_anyKey(); + gprintf("\n\nselected [%i] \n\n", selected); + if (buttons & WPAD_BUTTON_DOWN) + updateSelected(1); + + if (buttons & WPAD_BUTTON_UP) + updateSelected(-1); + + if (buttons & WPAD_BUTTON_LEFT){ + switch(selected){ + case 0: + if (--lang < 0) lang = 6; + break; + case 1: + if (--area < 0) area = 11; + break; + case 2: + if (--game < 0) game = 3; + break; + case 3: + if (--video < 0) video = 2; + break; + case 4: + if (country == 1) country = 136; + else if (country == 49) country = 1; + else if (country == 110) country = 49; + else if (country == 136) country = 110; + if (eula >= 0) eula = 0; + break; + case 5: + if (eula >= 0) eula = !eula; + break; + } + } + + if (buttons & WPAD_BUTTON_RIGHT){ + switch(selected){ + case 0: + if (++lang == 7) lang = 0; + break; + case 1: + if (++area == 12) area = 0; + break; + case 2: + if (++game == 4) game = 0; + break; + case 3: + if (++video == 3) video = 0; + break; + case 4: + if (country == 1) country = 49; + else if (country == 49) country = 110; + else if (country == 110) country = 136; + else if (country == 136) country = 1; + if (eula >= 0) eula = 0; + break; + case 5: + if (eula >= 0) eula = !eula; + break; + } + } + + if (buttons & WPAD_BUTTON_A){ + switch(selected){ + case 6: + getSettings(); + break; + case 7: + saveSettings(); + break; + case 8: + if(sysmenu_region == 85) { // usa + lang = 1; + area = 1; + game = 1; + video = 0; + country = 49; + } + else if(sysmenu_region == 74) { // jpn + lang = 0; + area = 0; + game = 0; + video = 0; + country = 1; + } + else if(sysmenu_region == 69) { // EUR/PAL + lang = 1; + area = 2; + game = 2; + video = 1; + country = 110; + } + // ============== to do add korean system menu's region ============================ + // ======================================= ================================== + saveSettings(); + break; + case 9: + needbreak = true; + break; + case 10: + STM_RebootSystem(); + break; + } + } + + if (buttons & WPAD_BUTTON_B) { + selected = 9; + } + if (buttons & WPAD_BUTTON_1) { + draw_credits(); + wait_anyKey(); + } + updatePage(); + if(needbreak) + break; + } + + Console_SetPosition(26,30); + Console_SetColors(BLACK, 0, GREEN, 0); + printf("Exiting"); + miscDeInit(); + + exit(0); +} diff --git a/source/runtimeiospatch.h b/source/runtimeiospatch.h new file mode 100644 index 0000000..4bcdfbc --- /dev/null +++ b/source/runtimeiospatch.h @@ -0,0 +1,143 @@ +// 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.0. + +// 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 2.0 for more details. + +// Copyright (C) 2010 Joseph Jordan +// Copyright (C) 2012-2013 damysteryman +// Copyright (C) 2012-2015 Christopher Bratusek +// Copyright (C) 2013 DarkMatterCore +// Copyright (C) 2014 megazig +// Copyright (C) 2015 FIX94 + +#ifndef __RUNTIMEIOSPATCH_H__ +#define __RUNTIMEIOSPATCH_H__ + +/** + * Version information for Libruntimeiospatch. + */ +#define LIB_RUNTIMEIOSPATCH_VERSION "1.5.4" + +//============================================================================== +// HW_RVL header +//============================================================================== +#if defined(HW_RVL) /* defined(HW_RVL) */ + +/** + *Returns true when HW_AHBPROT access can be applied + */ +#define AHBPROT_DISABLED (*(vu32*)0xcd800064 == 0xFFFFFFFF) + +//============================================================================== +// Error code definitions: +//============================================================================== +#define ERROR_AHBPROT -5 +#define ERROR_PATCH -7 + +//============================================================================== +// C++ header +//============================================================================== +#ifdef __cplusplus +extern "C" { +#endif +/* __cplusplus */ + +//============================================================================== +// Patchsets: +//============================================================================== +/* +Wii: + * DI Readlimit + * ISFS Permissions + * ES SetUID + * ES SetIdentify + * Hash Check (aka Trucha) + * New Hash Check (aka New Trucha) + * SSL patches + +Sciifii: + * MEM2 Prot + * ES OpenTitleContent 1 & 2 + * ES ReadContent Prot + * ES CloseContent + * ES TitleVersionCheck + * ES TitleDeleteCheck + +vWii: + * Kill Anti-SystemTitle-Install 1, 2, 3, 4 & 5 +*/ + + +//============================================================================== +// Functions: +//============================================================================== + +/** + * This function can be used to keep HW_AHBPROT access when going to reload IOS + * @param verbose Flag determing whether or not to print messages on-screen + * @example + * if(AHBPROT_DISABLED) { + * s32 ret; + * ret = IosPatch_AHBPROT(false); + * if (ret) { + * IOS_ReloadIOS(36); + * } else { + * printf("IosPatch_AHBPROT failed."); + * } + * } + * @return Signed 32bit integer representing code + * > 0 : Success - return equals to number of applied patches + * ERROR_AHBPROT : Error - No HW_AHBPROT access + */ +s32 IosPatch_AHBPROT(bool verbose); + + +/** + * This function applies patches on current IOS + * @see Patchsets + * @param wii Flag determing whether or not to apply Wii patches. + * @param sciifii Flag determing whether or not to apply extra Sciifii patches. + * @param vwii Flag determing whether or not to apply extra vWii patches. + * @param verbose Flag determing whether or not to print messages on-screen. + * @example if(AHBPROT_DISABLED) IosPatch_FULL(true, false, false, false); + * @return Signed 32bit integer representing code + * > 0 : Success - return equals to number of applied patches + * ERROR_AHBPROT : Error - No HW_AHBPROT access + * ERROR_PATCH : Error - Patching HW_AHBPROT access failed + */ +s32 IosPatch_RUNTIME(bool wii, bool sciifii, bool vwii, bool verbose); + + +/** + * This function combines IosPatch_AHBPROT + IOS_ReloadIOS + IosPatch_RUNTIME + * @see Patchsets + * @param wii Flag determing whether or not to apply Wii patches. + * @param sciifii Flag determing whether or not to apply extra Sciifii patches. + * @param vwii Flag determing whether or not to apply extra vWii patches. + * @param verbose Flag determing whether or not to print messages on-screen. + * @param IOS Which IOS to reload into. + * @example if(AHBPROT_DISABLED) IosPatch_FULL(true, false, false, false, 58); + * @return Signed 32bit integer representing code + * > 0 : Success - return equals to number of applied patches + * ERROR_AHBPROT : Error - No HW_AHBPROT access + * ERROR_PATCH : Error - Patching HW_AHBPROT access failed + */ +s32 IosPatch_FULL(bool wii, bool sciifii, bool vwii, bool verbose, int IOS); + +//============================================================================== +// C++ footer +//============================================================================== +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +//============================================================================== +// HW_RVL footer +//============================================================================== +#endif /* defined(HW_RVL) */ + +#endif diff --git a/source/sha1.c b/source/sha1.c new file mode 100644 index 0000000..83a533a --- /dev/null +++ b/source/sha1.c @@ -0,0 +1,172 @@ +/* +SHA-1 in C +By Steve Reid +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 +#include +#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); +} + diff --git a/source/sha1.h b/source/sha1.h new file mode 100644 index 0000000..757af1c --- /dev/null +++ b/source/sha1.h @@ -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); diff --git a/source/sysconf.c b/source/sysconf.c new file mode 100644 index 0000000..3e5709e --- /dev/null +++ b/source/sysconf.c @@ -0,0 +1,1032 @@ +/*------------------------------------------------------------- + +sysconf.c -- SYSCONF & setting.txt support + +Copyright (C) 2008 tona + +Original conf.c portions written by and Copright (C) 2008 +Hector Martin (marcan) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#if defined(HW_RVL) + +#include +#include +#include +#include +#include +#include + +#include "sysconf.h" + +#define DEBUG_SYSCONF + +#ifdef DEBUG_SYSCONF +#include "wiibasics.h" +#endif + +static int __sysconf_inited = 0; +static int __sysconf_buffer_txt_decrypted = 0; +static u8 __sysconf_buffer[0x4000] ATTRIBUTE_ALIGN(32); +static char __sysconf_txt_buffer[0x101] ATTRIBUTE_ALIGN(32); +static int __sysconf_buffer_updated = 0; +static int __sysconf_txt_buffer_updated = 0; + +static const char __sysconf_file[] ATTRIBUTE_ALIGN(32) = "/shared2/sys/SYSCONF"; +//static const char __sysconf_txt_file[] ATTRIBUTE_ALIGN(32) = "/title/00000001/00000002/data/setting.txt"; +static const char __sysconf_txt_file[] ATTRIBUTE_ALIGN(32) = "/title/00000001/00000002/data/setting.txt"; + +int __SYSCONF_EndOfTextOffset(void){ + int i; + int offset = 0; + + for (i = 0; i < 0x100; i++) + if (!memcmp(__sysconf_txt_buffer+i, "\r\n", 2)) + offset = i; + + offset += 2; + return offset; +} + +void __SYSCONF_DecryptEncryptTextBuffer(void) +{ + u32 key = 0x73B5DBFA; + int i; + char *end = (char*)__sysconf_txt_buffer; + + if (__sysconf_buffer_txt_decrypted) + end += __SYSCONF_EndOfTextOffset(); + + for(i=0; i<0x100; i++) { + __sysconf_txt_buffer[i] ^= key & 0xff; + key = (key<<1) | (key>>31); + } + + __sysconf_buffer_txt_decrypted = !__sysconf_buffer_txt_decrypted; + + if (__sysconf_buffer_txt_decrypted) + end += __SYSCONF_EndOfTextOffset(); + + + memset(end, 0, (__sysconf_txt_buffer+0x100)-end); + +} + +#ifdef DEBUG_SYSCONF + +void SYSCONF_DumpBuffer(void){ + if(!__sysconf_inited) return; + hex_print_array16(__sysconf_buffer, 0x4000); +} + +void SYSCONF_DumpTxtBuffer(void){ + if(!__sysconf_inited) return; + hex_print_array16((u8*)__sysconf_txt_buffer, 0x101); +} + +void SYSCONF_DumpEncryptedTxtBuffer(void){ + if(!__sysconf_inited) return; + int was = __sysconf_buffer_txt_decrypted; + if (__sysconf_buffer_txt_decrypted) + __SYSCONF_DecryptEncryptTextBuffer(); + hex_print_array16((u8*)__sysconf_txt_buffer, 0x101); + if (was) + __SYSCONF_DecryptEncryptTextBuffer(); +} + + +void SYSCONF_PrintAllSettings(void){ + if(!__sysconf_inited) return; + u16 i, count; + u16 *offset; + char temp[33], typestring[20]; + u8 nlen; + offset = (u16*)&__sysconf_buffer[6]; + count = *((u16*)(&__sysconf_buffer[4])); + printf("Total: %u settings.\n", count); + for (i = 0; i < count; i++) { + nlen = (__sysconf_buffer[*offset] & 0x0F)+1; + memcpy(temp, &__sysconf_buffer[(*offset)+1], nlen); + temp[nlen] = 0; + switch(__sysconf_buffer[*offset] >> 5){ + case 1: + sprintf(typestring, "BIGARRAY[0x%X]", *((u16*)&__sysconf_buffer[(*offset)+nlen+1]) + 1); + break; + case 2: + sprintf(typestring, "SMALLARRAY[0x%X]", __sysconf_buffer[(*offset)+nlen+1] + 1); + break; + case 3: + strcpy(typestring, "BYTE"); + break; + case 4: + strcpy(typestring, "SHORT"); + break; + case 5: + strcpy(typestring, "LONG"); + break; + case 7: + strcpy(typestring, "BOOL"); + break; + default: + sprintf(typestring, "Unknown %u", __sysconf_buffer[*offset] >> 5); + } + printf("%3u. 0x%04X: %-10s Type: %s\n", i+1, *offset, temp, typestring); + offset++; + } + +} +#endif /* DEBUG_SYSCONF */ + +s32 SYSCONF_Init(void) +{ + int fd; + int ret; + + if(__sysconf_inited) return 0; + + fd = IOS_Open(__sysconf_file,1); + if(fd < 0) return fd; + + memset(__sysconf_buffer,0,0x4000); + memset(__sysconf_txt_buffer,0,0x101); + + ret = IOS_Read(fd, __sysconf_buffer, 0x4000); + IOS_Close(fd); + if(ret != 0x4000) return SYSCONF_EBADFILE; + + fd = IOS_Open(__sysconf_txt_file,1); + if(fd < 0) return fd; + + ret = IOS_Read(fd, __sysconf_txt_buffer, 0x100); + IOS_Close(fd); + if(ret != 0x100) return SYSCONF_EBADFILE; + + if(memcmp(__sysconf_buffer, "SCv0", 4)) return SYSCONF_EBADFILE; + + __SYSCONF_DecryptEncryptTextBuffer(); + + __sysconf_inited = 1; + return 0; +} + +int __SYSCONF_WriteTxtBuffer(void) +{ + u64 tid; + int ret, fd; + + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + if (!__sysconf_txt_buffer_updated) return 0; + + ret = ES_GetTitleID(&tid); + if (ret < 0) return ret; + + if (tid != 0x100000002LL) return SYSCONF_EPERMS; + + if (__sysconf_buffer_txt_decrypted) + __SYSCONF_DecryptEncryptTextBuffer(); + + ret = ISFS_SetAttr(__sysconf_txt_file, 0x1000, 1, 0, 3, 3, 3); + if (ret < 0) return ret; + + fd = IOS_Open(__sysconf_txt_file, 2); + if(fd < 0) return fd; + + ret = IOS_Write(fd, __sysconf_txt_buffer, 0x100); + IOS_Close(fd); + if(ret != 0x100) return SYSCONF_EBADWRITE; + + ret = ISFS_SetAttr(__sysconf_txt_file, 0x1000, 1, 0, 1, 1, 1); + if (ret < 0) return ret; + + __sysconf_buffer_updated = 0; + + return 0; + +} + +int __SYSCONF_WriteBuffer(void) +{ + int ret, fd; + + if (!__sysconf_inited) return SYSCONF_ENOTINIT; + + if (!__sysconf_buffer_updated) return 0; + + fd = IOS_Open(__sysconf_file,2); + if(fd < 0) return fd; + + + ret = IOS_Write(fd, __sysconf_buffer, 0x4000); + IOS_Close(fd); + if(ret != 0x4000) return SYSCONF_EBADFILE; + + __sysconf_buffer_updated = 0; + return 0; +} + +s32 SYSCONF_SaveChanges(void) +{ + s32 ret; + if (!__sysconf_inited) return SYSCONF_ENOTINIT; + ret = __SYSCONF_WriteBuffer(); + if (ret < 0) + return ret; + + ret = __SYSCONF_WriteTxtBuffer(); + if (ret < 0) + return ret; + + return SYSCONF_ERR_OK; +} + +int __SYSCONF_ShiftTxt(char *start, s32 delta) +{ + char *end; + char temp[0x100]; + + if (!__sysconf_buffer_txt_decrypted) + __SYSCONF_DecryptEncryptTextBuffer(); + + end = strchr((char*)__sysconf_txt_buffer, 0); + if (end == NULL || end > __sysconf_txt_buffer+0x100) return SYSCONF_EBADFILE; + + if (start < __sysconf_txt_buffer || start >= end) + return SYSCONF_EBADVALUE; + + memcpy(temp, start, end-start); + memcpy(start+delta, temp, end-start); + //free (temp); + *(end+delta) = 0; + return 0; + +} + +int __SYSCONF_GetTxt(const char *name, char *buf, int length) +{ + char *line = __sysconf_txt_buffer; + char *delim, *end; + int slen; + int nlen = strlen(name); + + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + if (!__sysconf_buffer_txt_decrypted) + __SYSCONF_DecryptEncryptTextBuffer(); + + while(line < (__sysconf_txt_buffer+0x100) ) { + delim = strchr(line, '='); + if(delim && ((delim - line) == nlen) && !memcmp(name, line, nlen)) { + delim++; + end = strchr(line, '\r'); + if(end) { + slen = end - delim; + if(slen < length) { + memcpy(buf, delim, slen); + buf[slen] = 0; + return slen; + } else { + //printf("Should be %u is %u", slen, length); + return SYSCONF_ETOOBIG; + } + } + } + + // skip to line end + while(line < (__sysconf_txt_buffer+0x100) && *line++ != '\n'); + } + return SYSCONF_ENOENT; +} + +/* This function should NOT be used, and was only added for emergency recovery at one point */ +int __SYSCONF_AddTxt(const char *name, const char *value) +{ + char *newline; + char *temp; + char endline[10]; + u32 length; + + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + newline = strchr((char*)__sysconf_txt_buffer, 0); + if (newline == NULL || newline > __sysconf_txt_buffer+0x100) return SYSCONF_EBADFILE; + + + newline--; + while (*--newline == '\r'); + newline++; + + strcpy(endline, newline); + + newline += strlen(endline); + + length = strlen(name)+strlen(value)+strlen(endline)+1; + + if (newline+length < __sysconf_txt_buffer+0x100){ + temp = malloc(length+1); + sprintf(temp, "%s=%s%s", name, value, endline); + strcpy(newline, temp); + } else { + printf("Not worth it!"); + return SYSCONF_EBADFILE; + } + + return 0; +} + +int __SYSCONF_SetTxt(const char *name, const char *value) +{ + char *line = __sysconf_txt_buffer; + char *delim, *end; + int slen; + int nlen = strlen(name); + int vlen = strlen(value); + + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + if (!__sysconf_buffer_txt_decrypted) + __SYSCONF_DecryptEncryptTextBuffer(); + + while(line < (__sysconf_txt_buffer+0x100) ) { + delim = strchr(line, '='); + if(delim && ((delim - line) == nlen) && !memcmp(name, line, nlen)) { + delim++; + end = strchr(line, '\r'); + if(end) { + slen = end - delim; + if(slen == vlen) { + //printf("vlen: %u slen: %u\n", vlen, slen); + memcpy(delim, value, vlen); + __sysconf_txt_buffer_updated = 1; + return 0; + } else if(vlen && (vlen < slen || + (strchr(end, '\n') + (vlen-slen)) < __sysconf_txt_buffer+0x100)){ + //printf("vlen: %u slen: %u\n", vlen, slen); + if (__SYSCONF_ShiftTxt(end, vlen-slen)) return -1; + memcpy(delim, value, vlen); + __sysconf_txt_buffer_updated = 1; + return 0; + } else { + return SYSCONF_EBADVALUE; + } + } + } + + // skip to line end + while(line < (__sysconf_txt_buffer+0x100) && *line++ != '\n'); + } + + return SYSCONF_ENOENT; +} + + + +u8 *__SYSCONF_Find(const char *name) +{ + u16 count; + u16 *offset; + int nlen = strlen(name); + count = *((u16*)(&__sysconf_buffer[4])); + offset = (u16*)&__sysconf_buffer[6]; + + while(count--) { + if((nlen == ((__sysconf_buffer[*offset]&0x0F)+1)) && !memcmp(name, &__sysconf_buffer[*offset+1], nlen)) + return &__sysconf_buffer[*offset]; + offset++; + } + return NULL; +} + +s32 SYSCONF_GetLength(const char *name) +{ + u8 *entry; + + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + entry = __SYSCONF_Find(name); + if(!entry) return SYSCONF_ENOENT; + + switch(*entry>>5) { + case 1: + return *((u16*)&entry[strlen(name)+1]) + 1; + case 2: + return entry[strlen(name)+1] + 1; + case 3: + return 1; + case 4: + return 2; + case 5: + return 4; + case 7: + return 1; + default: + return SYSCONF_ENOTIMPL; + } +} + +s32 SYSCONF_GetType(const char *name) +{ + u8 *entry; + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + entry = __SYSCONF_Find(name); + if(!entry) return SYSCONF_ENOENT; + + return *entry>>5; +} + +s32 SYSCONF_Get(const char *name, void *buffer, u32 length) +{ + u8 *entry; + s32 len; + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + entry = __SYSCONF_Find(name); + if(!entry) return SYSCONF_ENOENT; + + len = SYSCONF_GetLength(name); + if(len<0) return len; + if(len>length) return SYSCONF_ETOOBIG; + + switch(*entry>>5) { + case SYSCONF_BIGARRAY: + memcpy(buffer, &entry[strlen(name)+3], len); + break; + case SYSCONF_SMALLARRAY: + memcpy(buffer, &entry[strlen(name)+2], len); + break; + case SYSCONF_BYTE: + case SYSCONF_SHORT: + case SYSCONF_LONG: + case SYSCONF_BOOL: + memset(buffer, 0, length); + memcpy(buffer, &entry[strlen(name)+1], len); + break; + default: + return SYSCONF_ENOTIMPL; + } + return len; +} + +s32 SYSCONF_Set(const char *name, const void *value, u32 length) +{ + u8 *entry; + s32 len; + if(!__sysconf_inited) return SYSCONF_ENOTINIT; + + entry = __SYSCONF_Find(name); + if(!entry) return SYSCONF_ENOENT; + + len = SYSCONF_GetLength(name); + if(len<0) return len; + if(length!=len) return SYSCONF_EBADVALUE; + + switch(*entry>>5) { + case SYSCONF_BIGARRAY: + memcpy(&entry[strlen(name)+3], value, len); + break; + case SYSCONF_SMALLARRAY: + memcpy(&entry[strlen(name)+2], value, len); + break; + case SYSCONF_BYTE: + case SYSCONF_SHORT: + case SYSCONF_LONG: + case SYSCONF_BOOL: + //memset(buffer, 0, length); + memcpy(&entry[strlen(name)+1], value, len); + break; + default: + return SYSCONF_ENOTIMPL; + } + __sysconf_buffer_updated = 1; + return 0; +} + +s32 SYSCONF_GetShutdownMode(void) +{ + u8 idlesysconf[2] = {0,0}; + int res; + + res = SYSCONF_Get("IPL.IDL", idlesysconf, 2); + if(res<0) return res; + if(res!=2) return SYSCONF_EBADVALUE; + return idlesysconf[0]; +} + +s32 SYSCONF_GetIdleLedMode(void) +{ + int res; + u8 idlesysconf[2] = {0,0}; + res = SYSCONF_Get("IPL.IDL", idlesysconf, 2); + if(res<0) return res; + if(res!=2) return SYSCONF_EBADVALUE; + return idlesysconf[1]; +} + +s32 SYSCONF_GetProgressiveScan(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("IPL.PGS", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetEuRGB60(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("IPL.E60", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetIRSensitivity(void) +{ + int res; + u32 val = 0; + res = SYSCONF_Get("BT.SENS", &val, 4); + if(res<0) return res; + if(res!=4) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetSensorBarPosition(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("BT.BAR", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetPadSpeakerVolume(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("BT.SPKV", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetPadMotorMode(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("BT.MOT", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetSoundMode(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("IPL.SND", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetLanguage(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("IPL.LNG", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetCounterBias(u32 *bias) +{ + int res; + res = SYSCONF_Get("IPL.CB", bias, 4); + if(res<0) return res; + if(res!=4) return SYSCONF_EBADVALUE; + return SYSCONF_ERR_OK; +} + +s32 SYSCONF_GetScreenSaverMode(void) +{ + int res; + u8 val = 0; + res = SYSCONF_Get("IPL.SSV", &val, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetDisplayOffsetH(s8 *offset) +{ + int res; + res = SYSCONF_Get("IPL.DH", offset, 1); + if(res<0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return 0; +} + +s32 SYSCONF_GetPadDevices(sysconf_pad_device *devs, int count) +{ + int res; + u8 buf[0x461]; + + res = SYSCONF_Get("BT.DINF", buf, 0x461); + if(res < 0) return res; + if((res < 1) || (buf[0] > 0x10)) return SYSCONF_EBADVALUE; + + if(count && devs) { + memset(devs,0,count*sizeof(sysconf_pad_device)); + if(count < buf[0]) + memcpy(devs,&buf[1],count*sizeof(sysconf_pad_device)); + else + memcpy(devs,&buf[1],buf[0]*sizeof(sysconf_pad_device)); + } + + res = buf[0]; + return res; +} + +s32 SYSCONF_GetNickName(u8 *nickname) +{ + int i, res; + u16 buf[11]; + + res = SYSCONF_Get("IPL.NIK", buf, 0x16); + if(res < 0) return res; + if((res != 0x16) || (!buf[0])) return SYSCONF_EBADVALUE; + + for(i=0; i<10; i++) + nickname[i] = buf[i]; + nickname[10] = 0; + + return res; +} + +s32 SYSCONF_GetAspectRatio(void) +{ + int res; + u8 val = 0; + + res = SYSCONF_Get("IPL.AR", &val, 1); + if(res < 0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetEULA(void) +{ + int res; + u8 val = 0; + + res = SYSCONF_Get("IPL.EULA", &val, 1); + if(res < 0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetParentalPassword(s8 *password) +{ + int res; + u8 buf[0x4A]; + + res = SYSCONF_Get("IPL.PC", buf, 0x4A); + if(res < 0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + + memcpy(password, buf+3, 4); + password[4] = 0; + + return res; +} + +s32 SYSCONF_GetParentalAnswer(s8 *answer) +{ + int res; + u8 buf[0x4A]; + + res = SYSCONF_Get("IPL.PC", buf, 0x4A); + if(res < 0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + + memcpy(answer, buf+8, 32); + answer[32] = 0; + + return res; +} + +s32 SYSCONF_GetWiiConnect24(void) +{ + int res; + u32 val = 0; + + res = SYSCONF_Get("NET.WCFG", &val, 4); + if(res < 0) return res; + if(res!=4) return SYSCONF_EBADVALUE; + return val; +} + +s32 SYSCONF_GetRegion(void) +{ + int res; + char buf[3]; + + res = __SYSCONF_GetTxt("GAME", buf, 3); + if(res < 0) return res; + if(!strcmp(buf, "JP")) return SYSCONF_REGION_JP; + if(!strcmp(buf, "US")) return SYSCONF_REGION_US; + if(!strcmp(buf, "EU")) return SYSCONF_REGION_EU; + return SYSCONF_EBADVALUE; +} + +s32 SYSCONF_GetArea(void) +{ + int res; + char buf[4]; + + res = __SYSCONF_GetTxt("AREA", buf, 4); + if(res < 0) return res; + if(!strcmp(buf, "JPN")) return SYSCONF_AREA_JPN; + if(!strcmp(buf, "USA")) return SYSCONF_AREA_USA; + if(!strcmp(buf, "EUR")) return SYSCONF_AREA_EUR; + if(!strcmp(buf, "AUS")) return SYSCONF_AREA_AUS; + if(!strcmp(buf, "BRA")) return SYSCONF_AREA_BRA; + if(!strcmp(buf, "TWN")) return SYSCONF_AREA_TWN; + if(!strcmp(buf, "ROC")) return SYSCONF_AREA_ROC; + if(!strcmp(buf, "KOR")) return SYSCONF_AREA_KOR; + if(!strcmp(buf, "HKG")) return SYSCONF_AREA_HKG; + if(!strcmp(buf, "ASI")) return SYSCONF_AREA_ASI; + if(!strcmp(buf, "LTN")) return SYSCONF_AREA_LTN; + if(!strcmp(buf, "SAF")) return SYSCONF_AREA_SAF; + return SYSCONF_EBADVALUE; +} + +s32 SYSCONF_GetVideo(void) +{ + int res; + char buf[5]; + + res = __SYSCONF_GetTxt("VIDEO", buf, 5); + if(res < 0) return res; + if(!strcmp(buf, "NTSC")) return SYSCONF_VIDEO_NTSC; + if(!strcmp(buf, "PAL")) return SYSCONF_VIDEO_PAL; + if(!strcmp(buf, "MPAL")) return SYSCONF_VIDEO_MPAL; + return SYSCONF_EBADVALUE; +} + +s32 SYSCONF_SetShutdownMode(u8 value) +{ + u8 idlesysconf[2] = {0,0}; + int res; + res = SYSCONF_Get("IPL.IDL", idlesysconf, 2); + if(res<0) return res; + if(res!=2) return SYSCONF_EBADVALUE; + + idlesysconf[0] = value; + + return SYSCONF_Set("IPL.IDL", idlesysconf, 2); +} + +s32 SYSCONF_SetIdleLedMode(u8 value) +{ + u8 idlesysconf[2] = {0,0}; + int res; + res = SYSCONF_Get("IPL.IDL", idlesysconf, 2); + if(res<0) return res; + if(res!=2) return SYSCONF_EBADVALUE; + + idlesysconf[1] = value; + + return SYSCONF_Set("IPL.IDL", idlesysconf, 2); +} + + +s32 SYSCONF_SetProgressiveScan(u8 value) +{ + return SYSCONF_Set("IPL.PGS", &value, 1); +} + +s32 SYSCONF_SetEuRGB60(u8 value) +{ + return SYSCONF_Set("IPL.E60", &value, 1); +} + + +s32 SYSCONF_SetIRSensitivity(u32 value) +{ + return SYSCONF_Set("BT.SENS", &value, 4); +} + +s32 SYSCONF_SetSensorBarPosition(u8 value) +{ + return SYSCONF_Set("BT.BAR", &value, 1); +} + +s32 SYSCONF_SetPadSpeakerVolume(u8 value) +{ + return SYSCONF_Set("BT.SPKV", &value, 1); +} + +s32 SYSCONF_SetPadMotorMode(u8 value) +{ + return SYSCONF_Set("BT.MOT", &value, 1); +} + +s32 SYSCONF_SetSoundMode(u8 value) +{ + return SYSCONF_Set("IPL.SND", &value, 1); +} + +s32 SYSCONF_SetLanguage(u8 value) +{ + return SYSCONF_Set("IPL.LNG", &value, 1); +} + +s32 SYSCONF_SetCounterBias(u32 bias) +{ + return SYSCONF_Set("IPL.CB", &bias, 4); +} + +s32 SYSCONF_SetScreenSaverMode(u8 value) +{ + return SYSCONF_Set("IPL.SSV", &value, 1); +} + +s32 SYSCONF_SetDisplayOffsetH(s8 offset) +{ + return SYSCONF_Set("IPL.DH", &offset, 1); +} + +s32 SYSCONF_SetPadDevices(const sysconf_pad_device *devs, u8 count) +{ + u8 buf[0x461] = {0}; + + if(count > 0x10) return SYSCONF_EBADVALUE; + buf[0] = count; + + if(devs) + memcpy(&buf[1],devs,count*sizeof(sysconf_pad_device)); + + return SYSCONF_Set("BT.DINF", buf, 0x461); +} + +s32 SYSCONF_SetNickName(const u8 *nickname, u16 length) +{ + int i; + u16 buf[11] = {0}; + if (length >10) return SYSCONF_EBADVALUE; + + for(i=0; i 1) return SYSCONF_EBADVALUE; + return SYSCONF_Set("IPL.EULA", &value, 1); +} + +s32 SYSCONF_SetParentalPassword(const s8 *password, u32 length) +{ + int res; + u8 buf[0x4A] = {0}; + if (length != 4) return SYSCONF_EBADVALUE; + + res = SYSCONF_Get("IPL.PC", buf, 0x4A); + if(res < 0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + + memcpy(buf+3, password, 4); + + return SYSCONF_Set("IPL.PC", buf, 0x4A); +} + +s32 SYSCONF_SetParentalAnswer(const s8 *answer, u32 length) +{ + int res; + u8 buf[0x4A] = {0}; + if (length != 32) return SYSCONF_EBADVALUE; + + res = SYSCONF_Get("IPL.PC", buf, 0x4A); + if(res < 0) return res; + if(res!=1) return SYSCONF_EBADVALUE; + + memcpy(buf+8, answer, length); + + return SYSCONF_Set("IPL.PC", buf, 0x4A); +} + +s32 SYSCONF_SetWiiConnect24(u32 value) +{ + return SYSCONF_Set("NET.WCFG", &value, 4); +} + +s32 SYSCONF_SetRegion(s32 value) +{ + switch(value){ + case SYSCONF_REGION_JP: + return __SYSCONF_SetTxt("GAME", "JP"); + case SYSCONF_REGION_US: + return __SYSCONF_SetTxt("GAME", "US"); + case SYSCONF_REGION_EU: + return __SYSCONF_SetTxt("GAME", "EU"); + default: + return SYSCONF_EBADVALUE; + } +} + +s32 SYSCONF_SetArea(s32 value) +{ + switch(value){ + case SYSCONF_AREA_JPN: + return __SYSCONF_SetTxt("AREA", "JPN"); + break; + case SYSCONF_AREA_USA: + return __SYSCONF_SetTxt("AREA", "USA"); + break; + case SYSCONF_AREA_EUR: + return __SYSCONF_SetTxt("AREA", "EUR"); + break; + case SYSCONF_AREA_AUS: + return __SYSCONF_SetTxt("AREA", "AUS"); + break; + case SYSCONF_AREA_BRA: + return __SYSCONF_SetTxt("AREA", "BRA"); + break; + case SYSCONF_AREA_TWN: + return __SYSCONF_SetTxt("AREA", "TWN"); + break; + case SYSCONF_AREA_ROC: + return __SYSCONF_SetTxt("AREA", "ROC"); + break; + case SYSCONF_AREA_KOR: + return __SYSCONF_SetTxt("AREA", "KOR"); + break; + case SYSCONF_AREA_HKG: + return __SYSCONF_SetTxt("AREA", "HKG"); + break; + case SYSCONF_AREA_ASI: + return __SYSCONF_SetTxt("AREA", "ASI"); + break; + case SYSCONF_AREA_LTN: + return __SYSCONF_SetTxt("AREA", "LTN"); + break; + case SYSCONF_AREA_SAF: + return __SYSCONF_SetTxt("AREA", "SAF"); + break; + default: + return SYSCONF_EBADVALUE; + } +} + +s32 SYSCONF_SetVideo(s32 value) +{ + switch(value){ + case SYSCONF_VIDEO_NTSC: + return __SYSCONF_SetTxt("VIDEO", "NTSC"); + break; + case SYSCONF_VIDEO_PAL: + return __SYSCONF_SetTxt("VIDEO", "PAL"); + break; + case SYSCONF_VIDEO_MPAL: + return __SYSCONF_SetTxt("VIDEO", "MPAL"); + break; + default: + return SYSCONF_EBADVALUE; + } +} + +#endif diff --git a/source/sysconf.h b/source/sysconf.h new file mode 100644 index 0000000..64401b6 --- /dev/null +++ b/source/sysconf.h @@ -0,0 +1,212 @@ +/*------------------------------------------------------------- + +sysconf.h -- SYSCONF & setting.txt support + +Copyright (C) 2008 tona + +Original conf.c portions written by and Copright (C) 2008 +Hector Martin (marcan) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#ifndef __SYSCONF_H__ +#define __SYSCONF_H__ + +#if defined(HW_RVL) + +#include +#include + +#define SYSCONF_EBADFILE -0x6001 +#define SYSCONF_ENOENT -0x6002 +#define SYSCONF_ETOOBIG -0x6003 +#define SYSCONF_ENOTINIT -0x6004 +#define SYSCONF_ENOTIMPL -0x6005 +#define SYSCONF_EBADVALUE -0x6006 +#define SYSCONF_ENOMEM -0x6007 +#define SYSCONF_EPERMS -0x6008 +#define SYSCONF_EBADWRITE -0x6009 +#define SYSCONF_ERR_OK 0 + +//#define DEBUG_SYSCONF + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +enum { + SYSCONF_BIGARRAY = 1, + SYSCONF_SMALLARRAY, + SYSCONF_BYTE, + SYSCONF_SHORT, + SYSCONF_LONG, + SYSCONF_BOOL = 7 +}; + +enum { + SYSCONF_VIDEO_NTSC = 0, + SYSCONF_VIDEO_PAL, + SYSCONF_VIDEO_MPAL +}; + +enum { + SYSCONF_REGION_JP = 0, + SYSCONF_REGION_US, + SYSCONF_REGION_EU +}; + +enum { + SYSCONF_AREA_JPN = 0, + SYSCONF_AREA_USA, + SYSCONF_AREA_EUR, + SYSCONF_AREA_AUS, + SYSCONF_AREA_BRA, + SYSCONF_AREA_TWN, + SYSCONF_AREA_ROC, + SYSCONF_AREA_KOR, + SYSCONF_AREA_HKG, + SYSCONF_AREA_ASI, + SYSCONF_AREA_LTN, + SYSCONF_AREA_SAF +}; + +enum { + SYSCONF_SHUTDOWN_STANDBY = 0, + SYSCONF_SHUTDOWN_IDLE +}; + +enum { + SYSCONF_LED_OFF = 0, + SYSCONF_LED_DIM, + SYSCONF_LED_BRIGHT +}; + +enum { + SYSCONF_SOUND_MONO = 0, + SYSCONF_SOUND_STEREO, + SYSCONF_SOUND_SURROUND +}; + +enum { + SYSCONF_LANG_JAPANESE = 0, + SYSCONF_LANG_ENGLISH, + SYSCONF_LANG_GERMAN, + SYSCONF_LANG_FRENCH, + SYSCONF_LANG_SPANISH, + SYSCONF_LANG_ITALIAN, + SYSCONF_LANG_DUTCH +}; + +enum { + SYSCONF_ASPECT_4_3 = 0, + SYSCONF_ASPECT_16_9 +}; + +enum { + SYSCONF_SENSORBAR_BOTTOM = 0, + SYSCONF_SENSORBAR_TOP +}; + +typedef struct _sysconf_pad_device sysconf_pad_device; + +struct _sysconf_pad_device { + u8 bdaddr[6]; + char name[0x40]; +} ATTRIBUTE_PACKED; + +#ifdef DEBUG_SYSCONF +void SYSCONF_DumpBuffer(void); +void SYSCONF_DumpTxtBuffer(void); +void SYSCONF_DumpEncryptedTxtBuffer(void); +void SYSCONF_PrintAllSettings(void); +#endif /* DEBUG_SYSCONF */ + +s32 SYSCONF_Init(void); +/* SYSCONF configuation */ +s32 SYSCONF_GetLength(const char *name); +s32 SYSCONF_GetType(const char *name); +s32 SYSCONF_Get(const char *name, void *buffer, u32 length); +s32 SYSCONF_GetShutdownMode(void); +s32 SYSCONF_GetIdleLedMode(void); +s32 SYSCONF_GetProgressiveScan(void); +s32 SYSCONF_GetEuRGB60(void); +s32 SYSCONF_GetIRSensitivity(void); +s32 SYSCONF_GetSensorBarPosition(void); +s32 SYSCONF_GetPadSpeakerVolume(void); +s32 SYSCONF_GetPadMotorMode(void); +s32 SYSCONF_GetSoundMode(void); +s32 SYSCONF_GetLanguage(void); +s32 SYSCONF_GetCounterBias(u32 *bias); +s32 SYSCONF_GetScreenSaverMode(void); +s32 SYSCONF_GetDisplayOffsetH(s8 *offset); +s32 SYSCONF_GetPadDevices(sysconf_pad_device *devs, int count); +s32 SYSCONF_GetNickName(u8 *nickname); +s32 SYSCONF_GetAspectRatio(void); +s32 SYSCONF_GetEULA(void); +s32 SYSCONF_GetParentalPassword(s8 *password); +s32 SYSCONF_GetParentalAnswer(s8 *answer); +s32 SYSCONF_GetWiiConnect24(void); +/* setting.txt configuration */ +s32 SYSCONF_GetRegion(void); +s32 SYSCONF_GetArea(void); +s32 SYSCONF_GetVideo(void); + + +/* Set functions */ +s32 SYSCONF_SaveChanges(void); +s32 SYSCONF_Set(const char *name, const void *value, u32 length); + + +s32 SYSCONF_SetShutdownMode(u8 value); +s32 SYSCONF_SetIdleLedMode(u8 value); +s32 SYSCONF_SetProgressiveScan(u8 value); +s32 SYSCONF_SetEuRGB60(u8 value); +s32 SYSCONF_SetIRSensitivity(u32 value); +s32 SYSCONF_SetSensorBarPosition(u8 value); +s32 SYSCONF_SetPadSpeakerVolume(u8 value); +s32 SYSCONF_SetPadMotorMode(u8 value); +s32 SYSCONF_SetSoundMode(u8 value); +s32 SYSCONF_SetLanguage(u8 value); + +s32 SYSCONF_SetCounterBias(u32 bias); +s32 SYSCONF_SetScreenSaverMode(u8 value); +s32 SYSCONF_SetDisplayOffsetH(s8 offset); +s32 SYSCONF_SetPadDevices(const sysconf_pad_device *devs, u8 count); +s32 SYSCONF_SetNickName(const u8 *nickname, u16 length); +s32 SYSCONF_SetAspectRatio(u8 value); +s32 SYSCONF_SetEULA(u8 value); +s32 SYSCONF_SetParentalPassword(const s8 *password, u32 length); +s32 SYSCONF_SetParentalAnswer(const s8 *answer, u32 length); +s32 SYSCONF_SetWiiConnect24(u32 value); + +s32 SYSCONF_SetRegion(s32 value); +s32 SYSCONF_SetArea(s32 value); +s32 SYSCONF_SetVideo(s32 value); + + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif + +#endif diff --git a/source/wiibasics.c b/source/wiibasics.c new file mode 100644 index 0000000..51238e6 --- /dev/null +++ b/source/wiibasics.c @@ -0,0 +1,533 @@ +/*------------------------------------------------------------- + +wiibasics.c -- basic Wii initialization and functions + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include "wiibasics.h" +#include "id.h" +#include "gecko.h" + +#define MAX_WIIMOTES 4 + + +static void *xfb = NULL; +static GXRModeObj *rmode = NULL; +int ConsoleRows; +int ConsoleCols; +u16 be16(const u8 *p) +{ + return (p[0] << 8) | p[1]; +} + +u32 be32(const u8 *p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; +} + +u64 be64(const u8 *p) +{ + return ((u64)be32(p) << 32) | be32(p + 4); +} + +u32 getTitleIDUID(u64 titleID){ + s32 ret, i; + static u8 uid_buffer[0x1000] ATTRIBUTE_ALIGN(32); + u32 size; + ret = ISFS_ReadFileToArray("/sys/uid.sys", uid_buffer, 0x1000, &size); + if (ret < 0) + return 0; + + for(i = 0; i < size; i+=12) + if (be64(&uid_buffer[i]) == titleID) + return be32(&uid_buffer[i+8]); + + return 0; +} + +u64 getUIDTitleID(u32 uid){ + s32 ret, i; + static u8 uid_buffer[0x1000] ATTRIBUTE_ALIGN(32); + u32 size; + ret = ISFS_ReadFileToArray("/sys/uid.sys", uid_buffer, 0x1000, &size); + if (ret < 0) + return 0; + + for(i = 8; i < size; i+=12) + if (be32(&uid_buffer[i]) == uid) + return be64(&uid_buffer[i-8]); + return 0; +} + + +/* Basic init taken pretty directly from the libOGC examples */ +void basicInit(void) +{ + // Initialise the video system + VIDEO_Init(); + + // Obtain the preferred video mode from the system + // This will correspond to the settings in the Wii menu + rmode = VIDEO_GetPreferredMode(NULL); + + //rmode->viWidth = 678; + //rmode->viXOrigin = (VI_MAX_WIDTH_PAL - 678)/2; + + GX_AdjustForOverscan(rmode, rmode, 32, 24); + + // Allocate memory for the display in the uncached region + xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + + + // Initialise the console, required for printf + console_init(xfb,0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); + + + // Set up the video registers with the chosen mode + VIDEO_Configure(rmode); + + // Tell the video hardware where our display memory is + VIDEO_SetNextFramebuffer(xfb); + + // Make the display visible + VIDEO_SetBlack(FALSE); + + // Flush the video register changes to the hardware + VIDEO_Flush(); + + // Wait for Video setup to complete + VIDEO_WaitVSync(); + if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); + + + + + // The console understands VT terminal escape codes + // This positions the cursor on row 2, column 0 + // we can use variables for this with format codes too + // e.g. printf ("\x1b[%d;%dH", row, column ); + //printf("\x1b[2;0H"); + CON_GetMetrics(&ConsoleCols, &ConsoleRows); +} + +void ClearScreen() { + /* Clear console */ + printf("\x1b[2J"); + fflush(stdout); +} +void ClearLine() { + printf("\r\x1b[2K\r"); + fflush(stdout); +} +void PrintCenter(char *text, int width) { + int textLen = strlen(text); + int leftPad = (width - textLen) / 2; + int rightPad = (width - textLen) - leftPad; + printf("%*s%s%*s", leftPad, " ", text, rightPad, " "); +} +void Console_SetFgColor(u8 color, u8 bold) { + printf("\x1b[%u;%dm", color + 30, bold); +} +void Console_SetBgColor(u8 color, u8 bold) { + printf("\x1b[%u;%dm", color + 40, bold); +} +void Console_SetColors(u8 bgColor, u8 bgBold, u8 fgColor, u8 fgBold) { + Console_SetBgColor(bgColor, bgBold); + Console_SetFgColor(fgColor, fgBold); +} +void Console_SetPosition(u8 row, u8 column) { + // The console understands VT terminal escape codes + // This positions the cursor on row 2, column 0 + // we can use variables for this with format codes too + // e.g. printf ("\x1b[%d;%dH", row, column ); + printf("\x1b[%u;%uH", row, column); +} +void PrintBanner() { + ClearScreen(); + Console_SetColors(GREEN, 0, WHITE, 2); + char text[ConsoleCols]; + snprintf(text, sizeof(text), "Any Region Changer ModMii Edition %.1lf.%i IOS: %i", ARCME_VERSION, ARCME_REV, Current_Ios); + PrintCenter(text, ConsoleCols); + Console_SetColors(BLACK, 0, WHITE, 2); +} +void miscInit(void) +{ + int ret; + + // This function initialises the attached controllers + WPAD_Init(); + + Identify_SU(); + + gprintf("Initializing Filesystem driver..."); + fflush(stdout); + + ret = ISFS_Initialize(); + if (ret < 0) { + gprintf("\nError! ISFS_Initialize (ret = %d)\n", ret); + wait_anyKey(); + exit(0); + } else { + gprintf("OK!\n"); + } + + //IdentSysMenu(); +} + +void IdentSysMenu(void){ + int ret; + Identify_SysMenu(); + + ret = ES_SetUID(TITLE_ID(1, 2)); + if (ret < 0){ + printf("SetUID fail %d", ret); + wait_anyKey(); + exit(1); + } + + printf("Initializing Filesystem driver..."); + fflush(stdout); + + ISFS_Deinitialize(); + ret = ISFS_Initialize(); + if (ret < 0) { + printf("\nError! ISFS_Initialize (ret = %d)\n", ret); + wait_anyKey(); + exit(1); + } else { + printf("OK!\n"); + } +} + +void miscDeInit(void) +{ + fflush(stdout); + ISFS_Deinitialize(); +} + +u32 getButtons(void) +{ + WPAD_ScanPads(); + return WPAD_ButtonsDown(0); +} + +u32 wait_anyKey(void) { + u32 pressed; + while(!(pressed = getButtons())) { + VIDEO_WaitVSync(); + } + if (pressed & WPAD_BUTTON_HOME) { + Console_SetPosition(26,0); + ClearLine(); + Console_SetPosition(26,30); + Console_SetColors(BLACK, 0, GREEN, 0); + printf("Exiting"); + exit(0); + } + return pressed; +} + +u32 wait_key(u32 button) { + u32 pressed; + do { + VIDEO_WaitVSync(); + pressed = getButtons(); + if (pressed & WPAD_BUTTON_HOME) { + Console_SetPosition(26,0); + ClearLine(); + Console_SetPosition(26,30); + Console_SetColors(BLACK, 0, GREEN, 0); + printf("Exiting"); + exit(0); + } + } while(!(pressed & button)); + + return pressed; +} + +char charASCII(u8 c) { + if (c < 0x20 || c > 0x7E) + return '.'; + else + return (char)c; +} + +void hex_print_array16(const u8 *array, u32 size){ + u32 offset = 0; + u32 page_size = 0x100; + char line[17]; + line[16] = 0; + if (size > page_size) + printf("Page 1 of %lu", (size / page_size)+1); + while (offset < size){ + if (!(offset % 16)) printf("\n0x%08lX: ", offset); + + printf("%02X", array[offset]); + + line[offset % 16] = charASCII(array[offset]); + + if (!(++offset % 2)) + printf(" "); + + if (!(offset % 16)) + printf(line); + + if (!(offset % page_size) && offset < size){ + u32 pressed; + printf("\n\tPress a key for next page or B for finish\n"); + pressed = wait_anyKey(); + if (pressed & WPAD_BUTTON_HOME) + exit(1); + else if (pressed & WPAD_BUTTON_B) + return; + } + } +} + +bool yes_or_no(void){ + bool yes = 0; + u32 buttons = 0; + + do { + yes = buttons & WPAD_BUTTON_LEFT; + if(yes) + printf("\r\x1b[K <\x1b[30m\x1b[47;1m Yes \x1b[37;1m\x1b[40m> No "); + else + printf("\r\x1b[K Yes <\x1b[30m\x1b[47;1m No \x1b[37;1m\x1b[40m> "); + } while ((buttons = wait_key(WPAD_BUTTON_A | WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT)) + && (!(buttons & WPAD_BUTTON_A))); + printf("\n"); + return yes; +} + +/* Reads a file from ISFS to an array in memory */ +s32 ISFS_ReadFileToArray (const char *filepath, u8 *filearray, u32 max_size, u32 *file_size) { + s32 ret, fd; + static fstats filestats ATTRIBUTE_ALIGN(32); + + *file_size = 0; + ret = ISFS_Open(filepath, ISFS_OPEN_READ); + if (ret <= 0) + { + printf("Error! ISFS_Open (ret = %ld)\n", ret); + return -1; + } + + fd = ret; + + ret = ISFS_GetFileStats(fd, &filestats); + if (ret < 0) + { + printf("Error! ISFS_GetFileStats (ret = %ld)\n", ret); + return -1; + } + + *file_size = filestats.file_length; + + if (*file_size > max_size) + { + printf("File is too large! Size: %lu Max: %lu", *file_size, max_size); + return -1; + } + + ret = ISFS_Read(fd, filearray, *file_size); + *file_size = ret; + if (ret < 0) + { + printf("Error! ISFS_Read (ret = %ld)\n", ret); + return -1; + } + else if (ret != filestats.file_length) + { + printf("Error! ISFS_Read Only read: %ld\n", ret); + return -1; + } + + ret = ISFS_Close(fd); + if (ret < 0) + { + printf("Error! ISFS_Close (ret = %ld)\n", ret); + return -1; + } + return 0; +} + +/* Writes from an array in memory to a file with ISFS */ +s32 ISFS_WriteFileFromArray (const char *filepath, const u8 *filearray, u32 array_size, u32 ownerID, u16 groupID, u8 attr, u8 own_perm, u8 group_perm, u8 other_perm){ + s32 ret, fd = 0, out; + u64 currentTid; + u32 realownid; + u16 realgroupid; + u8 realattr, realownperm, realgroupperm, realotherperm; + static fstats filestats ATTRIBUTE_ALIGN(32); + + out = 0; + + ret = ISFS_Open(filepath, ISFS_OPEN_WRITE); + if (ret == -102){ + + printf("\tMaking file writable...\n"); + ret = ISFS_SetAttr(filepath, ownerID, groupID, attr, 3, 3, 3); + if (ret < 0) + { + printf("Error! ISFS_SetAttr (ret = %ld)\n", ret); + out = -1; + goto cleanup; + } + + return ISFS_WriteFileFromArray(filepath, filearray, array_size, ownerID, groupID, attr, own_perm, group_perm, other_perm); + + } else if (ret == -106){ + + printf("\tCreating file...\n"); + ret = ISFS_CreateFile(filepath, attr, 3, 3, 3); + if (ret < 0){ + printf("Error! ISFS_CreateFile (ret = %ld)\n", ret); + out = -1; + goto cleanup; + } + + return ISFS_WriteFileFromArray(filepath, filearray, array_size, ownerID, groupID, attr, own_perm, group_perm, other_perm); + + } else if (ret <= 0) { + printf("Error! ISFS_Open WRITE (ret = %ld)\n", ret); + out = -1; + goto cleanup; + } + + fd = ret; + + ret = ISFS_Seek(fd, 0, 0); + if (ret < 0) { + printf("Error! ISFS_Seek (ret = %ld)\n", ret); + out = -1; + goto cleanup; + } + + ret = ISFS_Write(fd, filearray, array_size); + if (ret < 0) + { + printf("Error! ISFS_Write (ret = %ld)\n", ret); + out = -1; + goto cleanup; + } + + if (ret != array_size) + { + printf("Filesize is wrong! Wrote:%lu Expect:%lu", filestats.file_length, array_size); + out = -1; + } + + ret = ISFS_Close(fd); + if (ret < 0) + { + printf("Error! ISFS_Close (ret = %ld)\n", ret); + return -1; + } + fd = 0; + + /* + ret = ISFS_Open(filepath, ISFS_OPEN_READ); + if (ret <= 0) { + printf("Error! ISFS_Open READ (ret = %d)\n", ret); + out = -1; + goto cleanup; + } + fd = ret; + + ret = ISFS_GetFileStats(fd, &filestats); + if (ret < 0) + { + printf("Error! ISFS_GetFileStats (ret = %d)\n", ret); + out = -1; + goto cleanup; + } + + ret = ISFS_Close(fd); + if (ret < 0) + { + printf("Error! ISFS_Close (ret = %d)\n", ret); + return -1; + } + fd = 0; + */ + ret = ISFS_GetAttr(filepath, &realownid, &realgroupid, &realattr, &realownperm, &realgroupperm, &realotherperm); + if (ret < 0) + { + printf("Error! ISFS_GetAttr (ret = %ld)\n", ret); + out = -1; + } + + if (realownid != ownerID){ + ret = ES_GetTitleID(¤tTid); + if (ret){ + printf("Fail GetTitleID %ld", ret); + if(wait_key(WPAD_BUTTON_A | WPAD_BUTTON_B) & WPAD_BUTTON_B) + goto cleanup; + } + ret = ES_SetUID(getUIDTitleID(ownerID)); + if (ret){ + printf("Couldn't set OwnerID, using current owner ID\n"); + if(wait_key(WPAD_BUTTON_A | WPAD_BUTTON_B) & WPAD_BUTTON_B) + goto cleanup; + ownerID = realownid; + } + } + + ret = ISFS_SetAttr(filepath, ownerID, groupID, attr, own_perm, group_perm, other_perm); + if (ret < 0) + { + printf("Error! ISFS_SetAttr (ret = %ld)\n", ret); + out = -1; + goto cleanup; + } + + if (realownid != ownerID){ + ret = ES_SetUID(currentTid); + if (ret){ + printf("Fail SetUID %ld", ret); + if(wait_key(WPAD_BUTTON_A | WPAD_BUTTON_B) & WPAD_BUTTON_B) + goto cleanup; + } + } + + cleanup: + if (fd) { + ret = ISFS_Close(fd); + if (ret < 0) + { + printf("Error! ISFS_Close (ret = %ld)\n", ret); + return -1; + } + } + return out; + +} diff --git a/source/wiibasics.h b/source/wiibasics.h new file mode 100644 index 0000000..64064b5 --- /dev/null +++ b/source/wiibasics.h @@ -0,0 +1,104 @@ +/*------------------------------------------------------------- + +wiibasics.h -- basic Wii initialization and functions + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#ifndef _WII_BASICS_H_ +#define _WII_BASICS_H_ + + +// Turn upper and lower into a full title ID +#define TITLE_ID(x,y) (((u64)(x) << 32) | (y)) +// Get upper or lower half of a title ID +#define TITLE_UPPER(x) ((u32)((x) >> 32)) +// Turn upper and lower into a full title ID +#define TITLE_LOWER(x) ((u32)(x)) +#define BLACK 0 +#define RED 1 +#define GREEN 2 +#define YELLOW 3 +#define BLUE 4 +#define MAGENTA 5 +#define CYAN 6 +#define WHITE 7 + +#define BOLD_NONE 0 +#define BOLD_NORMAL 1 +#define BOLD_FAINT 2 + +#define UP_ARROW "\x1E" +#define DOWN_ARROW "\x1F" +#define LEFT_ARROW "\x11" +#define RIGHT_ARROW "\x10" + +#define ARCME_VERSION 1.0 +#define ARCME_REV 5 + +int Current_Ios; + +// be functions from segher's wii.git +u16 be16(const u8 *p); +u32 be32(const u8 *p); +u64 be64(const u8 *p); +u64 be34(const u8 *p); + +// Do basic Wii init: Video, console, WPAD +void basicInit(void); + +// Do our custom init: Identify and initialized ISFS driver +void miscInit(void); + +void IdentSysMenu(void); + +// Clean up after ourselves (Deinit ISFS) +void miscDeInit(void); + +// Scan the pads and return buttons +u32 getButtons(void); + +u32 wait_anyKey(void); + +u32 wait_key(u32 button); + +void hex_print_array16(const u8 *array, u32 size); + +/* Reads a file from ISFS to an array in memory */ +s32 ISFS_ReadFileToArray (const char *filepath, u8 *filearray, u32 max_size, u32 *file_size); + +/* Writes from an array in memory to a file with ISFS */ +s32 ISFS_WriteFileFromArray (const char *filepath, const u8 *filearray, u32 array_size, u32 ownerID, u16 groupID, u8 attr, u8 own_perm, u8 group_perm, u8 other_perm); + +bool yes_or_no(); +void ClearScreen(); +void ClearLine(); +void PrintCenter(char *, int); +void Console_SetFgColor(u8, u8); +void Console_SetBgColor(u8, u8); +void Console_SetColors(u8, u8, u8, u8); +void Console_SetPosition(u8, u8); +void PrintBanner(); + +#endif