diff --git a/libruntimeiospatch/API b/libruntimeiospatch/API new file mode 100644 index 00000000..a4f5074c --- /dev/null +++ b/libruntimeiospatch/API @@ -0,0 +1,131 @@ +libruntimeiospatch function overview +==================================== + +>>>>>>>> libruntimeiospatch 1.3: <<<<<<<< + +===================== =================== +=== ERROR_AHBPROT === === ERROR_PATCH === +===================== =================== + +Use those to catch occuring errors + +****** +if (IosPatch_AHBPROT(false) == ERROR_AHBPROT) + printf("AHBPROT is still enabled!"); + +if (IosPatch_RUNTIME(true, false, false, false) == ERROR_PATCH) + printf("Patching IOS failed!"); + +======================== +=== AHBPROT_DISABLED === +======================== + +Returns true when HW_AHBPROT access can be applied + +****** +If(AHBPROT_DISABLED) { + do_something +} else { + do_something_else +} +****** + +=================================== +=== LIB_RUNTIMEIOSPATCH_VERSION === +=================================== + +Stores printable version of libruntimeiospatch. + +>>>>>>>> libruntimeiospatch 1.1: <<<<<<<< + +===================== +=== IosPatch_FULL === +===================== + +This function combines IosPatch_AHBPROT + IOS_ReloadIOS + IosPatch_RUNTIME + +>> Flags: [bool]wii (whether to apply Wii patches) + [bool]sciifii (whether to apply extra Sciifii patches) + [bool]vwii (whether to apply extra vWii patches) + [bool]verbose (whether to print messages on-screen) + [int]ios (which IOS to reload into) + +>> Return: +-5: no HW_AHBPROT access +-7: patching HW_AHBPROT access failed +>0: success (return equals to number of applied patches) + +****** +If(AHBPROT_DISABLED) { + IosPatch_FULL(true, false, false, false, 58); +} +****** + +>>>>>>>> libruntimeiospatch 1.0: <<<<<<<< + +======================== +=== IosPatch_AHBPROT === +======================== + +This function can be used to keep HW_AHBPROT access when going to reload IOS + +>> Flags: [bool]verbose (whether to print messages on-screen) + +>> Return: +-5: no HW_AHBPROT access +-7: patching HW_AHBPROT access failed +>0: success + +****** +if(AHBPROT_DISABLED) { + s32 ret; + ret = IosPatch_AHBPROT(false); + if (ret) { + IOS_ReloadIOS(36); + } else { + printf("IosPatch_AHBPROT failed."); + } +} +****** + +======================== +=== IosPatch_RUNTIME === +======================== + +This function applies patches on current IOS + +>> Flags: [bool]wii (whether to apply Wii patches) + [bool]sciifii (whether to apply extra Sciifii patches) + [bool]vwii (whether to apply extra vWii patches) + [bool]verbose (whether to print messages on-screen) + +>> Return: +-5: no HW_AHBPROT access +>0: success (return equals to number of applied patches) + +<< Patchsets: +Wii: + * DI Readlimit + * ISFS Permissions + * ES SetUID + * ES SetIdentify + * Hash Check (aka Trucha) + * New Hash Check (aka New Trucha) + +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 + + +****** +If(AHBPROT_DISABLED) { + IosPatch_RUNTIME(true, false, false, false); +} +****** diff --git a/libruntimeiospatch/CHANGES b/libruntimeiospatch/CHANGES new file mode 100644 index 00000000..4c6defbc --- /dev/null +++ b/libruntimeiospatch/CHANGES @@ -0,0 +1,41 @@ +1.5.1: +* code clean-up (JoostinOnline) +* add typedef for s32 (JoostinOnline) +* misc minor changes (JoostinOnline) + +1.5: +* add ISFS_SetAttr() patches. (megazig) + Forces the ISFS_SetAttr() function to continue instead of + returning -102 when you're trying to change the UID/GID of a file. + +1.4: +* fix value for hash_old (spotted by DarkMatterCore) + +1.3: thanks to JoostinOnline/damysteryman +* replaced HAVE_ABHPROT by AHBPROT_DISABLED (now public) +* removed (now) redundant have_ahbprot() +* store version in #LIB_RUNTIMEIOSPATCH_VERSION +* removed (now) redundant get_libruntimeiospatch_version() +* minor code clean-ups +* changed some unsigned ints to signed +* added license header to runtimeiospatch.[ch] +* new vWii patches by damysteryman (fixes installation of hidden channels) +* updated API + +1.2: +[NEW] get_libruntimeiospatch_version() +[MOD] IosPatch_AHBPROT() - return code re-work +[MOD] IosPatch_RUNTIME() - return code re-work +[MOD] IosPatch_FULL() - retun code re-work +[MOD] API doc file updated +[NEW] CHANGES doc file + +1.1: +[NEW] IosPatch_FULL() +[MOD] IosPatch_AHBPROT() - proper return work +[NEW] API doc file + +1.0: initial release +[NEW] have_ahbprot() +[NEW] IosPatch_AHBPROT() +[NEW] IosPatch_RUNTIME() diff --git a/libruntimeiospatch/Makefile b/libruntimeiospatch/Makefile new file mode 100644 index 00000000..6f4c6bef --- /dev/null +++ b/libruntimeiospatch/Makefile @@ -0,0 +1,153 @@ +#--------------------------------------------------------------------------------- +# 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 := runtimeiospatch +BUILD := build +SOURCES := source +DATA := data +INCLUDES := $(DEVKITPRO)/libogc + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -save-temps -g -O2 -Wall $(MACHDEP) $(INCLUDE) +CXXFLAGS = $(CFLAGS) +ASFLAGS = $(INCLUDE) -D_LANGUAGE_ASSEMBLY + +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map +ARFLAGS = rcs + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(DEVKITPRO)/libogc + +#--------------------------------------------------------------------------------- +# 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),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBOGC_INC) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) + @rm -f lib$(TARGET).a +#--------------------------------------------------------------------------------- +run: + wiiload $(OUTPUT).dol + +#--------------------------------------------------------------------------------- + +install: + @echo Installing ... + @mkdir -p $(LIBOGC_INC)/$(TARGET) + @install -v -m 644 lib$(TARGET).a $(LIBOGC_LIB) + @install -v -m 644 source/$(TARGET).h $(LIBOGC_INC)/$(TARGET) +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).a: $(OFILES) + + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .bin extension +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + $(bin2o) + + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +# This rule will create a library with all the object files +#--------------------------------------------------------------------------------- +%.a: + @echo Archiving ... lib$(notdir $@) + @$(AR) $(ARFLAGS) ../lib$(notdir $@) $^ + @echo $(TARGET) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/libruntimeiospatch/README b/libruntimeiospatch/README new file mode 100644 index 00000000..ee4e75a4 --- /dev/null +++ b/libruntimeiospatch/README @@ -0,0 +1,21 @@ +=== libruntimeiospatch === + +a library providing necessary functions for patching IOS at runtime using HW_AHBPROT. +It is distributed under the terms of the GNU General Public License v2 + +=== Including === + +include the library as + +#include // Code +LIBS := -lruntimeiospatch // Makefile + +=== API === + +see File "API" + += Thanks = +- libOGC devs +- Team Twizzers +- damysterman +- anyone I forgot to mention here diff --git a/libruntimeiospatch/source/runtimeiospatch.c b/libruntimeiospatch/source/runtimeiospatch.c new file mode 100644 index 00000000..66650576 --- /dev/null +++ b/libruntimeiospatch/source/runtimeiospatch.c @@ -0,0 +1,188 @@ +// 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-2013 Christopher Bratusek +// Copyright (C) 2013 DarkMatterCore +// Copyright (C) 2014 megazig + +#include +#include +#include +#include + +#include "runtimeiospatch.h" + +#define MEM_REG_BASE 0xd8b4000 +#define MEM_PROT (MEM_REG_BASE + 0x20a) + + +static inline void disable_memory_protection(void) { + write32(MEM_PROT, read32(MEM_PROT) & 0x0000FFFF); +} + +static const u8 di_readlimit_old[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 +}; +static const u8 di_readlimit_patch[] = { 0x7e, 0xd4 }; + +static const u8 isfs_permissions_old[] = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 }; +static const u8 isfs_permissions_patch[] = { 0x42, 0x8B, 0xE0, 0x01, 0x25, 0x66 }; +static const u8 setuid_old[] = { 0xD1, 0x2A, 0x1C, 0x39 }; +static const u8 setuid_patch[] = { 0x46, 0xC0 }; +static const u8 es_identify_old[] = { 0x28, 0x03, 0xD1, 0x23 }; +static const u8 es_identify_patch[] = { 0x00, 0x00 }; +static const u8 hash_old[] = { 0x20, 0x07, 0x23, 0xA2 }; +static const u8 hash_patch[] = { 0x00 }; +static const u8 new_hash_old[] = { 0x20, 0x07, 0x4B, 0x0B }; +static const u8 addticket_vers_check[] = { 0xD2, 0x01, 0x4E, 0x56 }; +static const u8 addticket_patch[] = { 0xE0 }; +static const u8 es_set_ahbprot_old[] = { 0x68, 0x5B, 0x22, 0xEC, 0x00, 0x52, 0x18, 0x9B, 0x68, 0x1B, 0x46, 0x98, 0x07, 0xDB }; +static const u8 es_set_ahbprot_patch[] = { 0x01 }; + +//Following patches added to iospatch.c by damysteryman, taken from sciifii v5 +static const u8 MEM2_prot_old[] = { 0xB5, 0x00, 0x4B, 0x09, 0x22, 0x01, 0x80, 0x1A, 0x22, 0xF0 }; +static const u8 MEM2_prot_patch[] = { 0xB5, 0x00, 0x4B, 0x09, 0x22, 0x00, 0x80, 0x1A, 0x22, 0xF0 }; +static const u8 ES_OpenTitleContent1_old[] = { 0x9D, 0x05, 0x42, 0x9D, 0xD0, 0x03 }; +static const u8 ES_OpenTitleContent1_patch[] = { 0x9D, 0x05, 0x42, 0x9D, 0xE0, 0x03 }; +static const u8 ES_OpenTitleContent2_old[] = { 0xD4, 0x01, 0x4C, 0x36, 0xE0, 0x3B }; +static const u8 ES_OpenTitleContent2_patch[] = { 0xE0, 0x01, 0x4C, 0x36, 0xE0, 0x3B }; +static const u8 ES_ReadContent_old[] = { 0xFC, 0x0F, 0xB5, 0x30, 0x1C, 0x14, 0x1C, 0x1D, 0x4B, + 0x0E, 0x68, 0x9B, 0x2B, 0x00, 0xD0, 0x03, 0x29, 0x00, 0xDB, 0x01, + 0x29, 0x0F, 0xDD, 0x01 }; +static const u8 ES_ReadContent_patch[] = { 0xFC, 0x0F, 0xB5, 0x30, 0x1C, 0x14, 0x1C, 0x1D, 0x4B, + 0x0E, 0x68, 0x9B, 0x2B, 0x00, 0x46, 0xC0, 0x29, 0x00, 0x46, 0xC0, + 0x29, 0x0F, 0xE0, 0x01 }; +static const u8 ES_CloseContent_old[] = { 0xB5, 0x10, 0x4B, 0x10, 0x68, 0x9B, 0x2B, 0x00, 0xD0, + 0x03, 0x29, 0x00, 0xDB, 0x01, 0x29, 0x0F, 0xDD, 0x01 }; +static const u8 ES_CloseContent_patch[] = { 0xB5, 0x10, 0x4B, 0x10, 0x68, 0x9B, 0x2B, 0x00, 0x46, + 0xC0, 0x29, 0x00, 0x46, 0xC0, 0x29, 0x0F, 0xE0, 0x01 }; +static const u8 ES_TitleVersionCheck_old[] = { 0xD2, 0x01, 0x4E, 0x56 }; +static const u8 ES_TitleVersionCheck_patch[] = { 0xE0, 0x01, 0x4E, 0x56 }; +static const u8 ES_TitleDeleteCheck_old[] = { 0xD8, 0x00, 0x4A, 0x04 }; +static const u8 ES_TitleDeleteCheck_patch[] = { 0xE0, 0x00, 0x4A, 0x04 }; + + +//Following set of patches made by damysteryman for use with Wii U's vWii +static const u8 Kill_AntiSysTitleInstallv3_pt1_old[] = { 0x68, 0x1A, 0x2A, 0x01, 0xD0, 0x05 }; // Make sure that the pt1 +static const u8 Kill_AntiSysTitleInstallv3_pt1_patch[] = { 0x68, 0x1A, 0x2A, 0x01, 0x46, 0xC0 }; // patch is applied twice. -dmm +static const u8 Kill_AntiSysTitleInstallv3_pt2_old[] = { 0xD0, 0x02, 0x33, 0x06, 0x42, 0x9A, 0xD1, 0x01 }; // Make sure that the pt2 patch +static const u8 Kill_AntiSysTitleInstallv3_pt2_patch[] = { 0x46, 0xC0, 0x33, 0x06, 0x42, 0x9A, 0xE0, 0x01 }; // is also applied twice. -dmm +static const u8 Kill_AntiSysTitleInstallv3_pt3_old[] = { 0x68, 0xFB, 0x2B, 0x00, 0xDB, 0x01 }; +static const u8 Kill_AntiSysTitleInstallv3_pt3_patch[] = { 0x68, 0xFB, 0x2B, 0x00, 0xDB, 0x10 }; + +static const u8 isfs_setattr_pt1_old[] = { 0x42, 0xAB, 0xD0, 0x02, 0x20, 0x66 }; +static const u8 isfs_setattr_pt1_patch[] = { 0x42, 0xAB, 0xE0, 0x02, 0x20, 0x66 }; +static const u8 isfs_setattr_pt2_old[] = { 0x2D, 0x00, 0xD0, 0x02, 0x20, 0x66 }; +static const u8 isfs_setattr_pt2_patch[] = { 0x2D, 0x00, 0xE0, 0x02, 0x20, 0x66 }; + +static u8 apply_patch(const char *name, const u8 *old, u32 old_size, const u8 *patch, size_t patch_size, u32 patch_offset, bool verbose) { + u8 *ptr_start = (u8*)*((u32*)0x80003134), *ptr_end = (u8*)0x94000000; + u8 found = 0; + if(verbose) + printf(" Patching %-30s", name); + u8 *location = NULL; + while (ptr_start < (ptr_end - patch_size)) { + if (!memcmp(ptr_start, old, old_size)) { + found++; + location = ptr_start + patch_offset; + u8 *start = location; + u32 i; + for (i = 0; i < patch_size; i++) { + *location++ = patch[i]; + } + DCFlushRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64); + ICInvalidateRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64); + } + ptr_start++; + } + if(verbose){ + if (found) + printf(" patched\n"); + else + printf(" not patched\n"); + } + return found; +} + +s32 IosPatch_AHBPROT(bool verbose) { + if (AHBPROT_DISABLED) { + disable_memory_protection(); + s32 ret = apply_patch("es_set_ahbprot", es_set_ahbprot_old, sizeof(es_set_ahbprot_old), es_set_ahbprot_patch, sizeof(es_set_ahbprot_patch), 25, verbose); + if (ret) + return ret; + else + return ERROR_PATCH; + } + return ERROR_AHBPROT; +} + +s32 IosPatch_RUNTIME(bool wii, bool sciifii, bool vwii, bool verbose) { + s32 count = 0; + + if (AHBPROT_DISABLED) { + disable_memory_protection(); + if(wii) + { + if(verbose) printf(">> Applying standard Wii patches:\n"); + count += apply_patch("di_readlimit", di_readlimit_old, sizeof(di_readlimit_old), di_readlimit_patch, sizeof(di_readlimit_patch), 12, verbose); + count += apply_patch("isfs_permissions", isfs_permissions_old, sizeof(isfs_permissions_old), isfs_permissions_patch, sizeof(isfs_permissions_patch), 0, verbose); + count += apply_patch("es_setuid", setuid_old, sizeof(setuid_old), setuid_patch, sizeof(setuid_patch), 0, verbose); + count += apply_patch("es_identify", es_identify_old, sizeof(es_identify_old), es_identify_patch, sizeof(es_identify_patch), 2, verbose); + count += apply_patch("hash_check", hash_old, sizeof(hash_old), hash_patch, sizeof(hash_patch), 1, verbose); + count += apply_patch("new_hash_check", new_hash_old, sizeof(new_hash_old), hash_patch, sizeof(hash_patch), 1, verbose); + count += apply_patch("isfs_setattr_pt1", isfs_setattr_pt1_old, sizeof(isfs_setattr_pt1_old), isfs_setattr_pt1_patch, sizeof(isfs_setattr_pt1_patch), 0, verbose); + count += apply_patch("isfs_setattr_pt2", isfs_setattr_pt2_old, sizeof(isfs_setattr_pt2_old), isfs_setattr_pt2_patch, sizeof(isfs_setattr_pt2_patch), 0, verbose); + } + if(sciifii) + { + if(verbose) printf(">> Applying Sciifii patches:\n"); + count += apply_patch("MEM2_prot", MEM2_prot_old, sizeof(MEM2_prot_old), MEM2_prot_patch, sizeof(MEM2_prot_patch), 0, verbose); + count += apply_patch("ES_OpenTitleContent1", ES_OpenTitleContent1_old, sizeof(ES_OpenTitleContent1_old), ES_OpenTitleContent1_patch, sizeof(ES_OpenTitleContent1_patch), 0, verbose); + count += apply_patch("ES_OpenTitleContent2", ES_OpenTitleContent2_old, sizeof(ES_OpenTitleContent2_old), ES_OpenTitleContent2_patch, sizeof(ES_OpenTitleContent2_patch), 0, verbose); + count += apply_patch("ES_ReadContent_prot", ES_ReadContent_old, sizeof(ES_ReadContent_old), ES_ReadContent_patch, sizeof(ES_ReadContent_patch), 0, verbose); + count += apply_patch("ES_CloseContent", ES_CloseContent_old, sizeof(ES_CloseContent_old), ES_CloseContent_patch, sizeof(ES_CloseContent_patch), 0, verbose); + count += apply_patch("ES_TitleVersionCheck", ES_TitleVersionCheck_old, sizeof(ES_TitleVersionCheck_old), ES_TitleVersionCheck_patch, sizeof(ES_TitleVersionCheck_patch), 0, verbose); + count += apply_patch("ES_TitleDeleteCheck", ES_TitleDeleteCheck_old, sizeof(ES_TitleDeleteCheck_old), ES_TitleDeleteCheck_patch, sizeof(ES_TitleDeleteCheck_patch), 0, verbose); + } + if(vwii) + { + if(verbose) printf(">> Applying vWii patches:\n"); + count += apply_patch("Kill_AntiSysTitleInstallv3_pt1", Kill_AntiSysTitleInstallv3_pt1_old, sizeof(Kill_AntiSysTitleInstallv3_pt1_old), Kill_AntiSysTitleInstallv3_pt1_patch, sizeof(Kill_AntiSysTitleInstallv3_pt1_patch), 0, verbose); + count += apply_patch("Kill_AntiSysTitleInstallv3_pt2", Kill_AntiSysTitleInstallv3_pt2_old, sizeof(Kill_AntiSysTitleInstallv3_pt2_old), Kill_AntiSysTitleInstallv3_pt2_patch, sizeof(Kill_AntiSysTitleInstallv3_pt2_patch), 0, verbose); + count += apply_patch("Kill_AntiSysTitleInstallv3_pt3", Kill_AntiSysTitleInstallv3_pt3_old, sizeof(Kill_AntiSysTitleInstallv3_pt3_old), Kill_AntiSysTitleInstallv3_pt3_patch, sizeof(Kill_AntiSysTitleInstallv3_pt3_patch), 0, verbose); + } + return count; + } + return ERROR_AHBPROT; +} + +s32 IosPatch_FULL(bool wii, bool sciifii, bool vwii, bool verbose, int IOS) { + s32 ret = 0; + s32 xret = 0; + + if (AHBPROT_DISABLED) + ret = IosPatch_AHBPROT(verbose); + else + return ERROR_AHBPROT; + + if (ret) { + IOS_ReloadIOS(IOS); + xret = IosPatch_RUNTIME(wii, sciifii, vwii, verbose); + } else { + xret = ERROR_PATCH; + } + + return xret; + +} diff --git a/libruntimeiospatch/source/runtimeiospatch.h b/libruntimeiospatch/source/runtimeiospatch.h new file mode 100644 index 00000000..0c212dd4 --- /dev/null +++ b/libruntimeiospatch/source/runtimeiospatch.h @@ -0,0 +1,147 @@ +// 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-2013 Christopher Bratusek +// Copyright (C) 2013 DarkMatterCore +// Copyright (C) 2014 megazig + +#ifndef __RUNTIMEIOSPATCH_H__ +#define __RUNTIMEIOSPATCH_H__ + +/** + * Version information for Libruntimeiospatch. + */ +#define LIB_RUNTIMEIOSPATCH_VERSION "1.5.1" + +//============================================================================== +// 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 */ + +//============================================================================== +// Extra standard declarations +//============================================================================== +typedef signed int s32; +//============================================================================== + +//============================================================================== +// Patchsets: +//============================================================================== +/* +Wii: + * DI Readlimit + * ISFS Permissions + * ES SetUID + * ES SetIdentify + * Hash Check (aka Trucha) + * New Hash Check (aka New Trucha) + +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/libsicksaxis/Makefile b/libsicksaxis/Makefile new file mode 100644 index 00000000..cd20f0d9 --- /dev/null +++ b/libsicksaxis/Makefile @@ -0,0 +1,28 @@ +.SUFFIXES: + +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + + +TARGET := libsicksaxis.a +CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(LIBOGC_INC) + + +all: sicksaxis.o + powerpc-eabi-ar rcs $(TARGET) -c sicksaxis.o + @echo "Type 'make install' to install" + +sicksaxis.o: + powerpc-eabi-gcc $(CFLAGS) -c sicksaxis.c + +install: all + @echo install ... + cp $(TARGET) $(LIBOGC_LIB) + cp sicksaxis.h $(LIBOGC_INC) + +clean: + @echo clean ... + @rm -fr sicksaxis.o $(TARGET) diff --git a/libsicksaxis/sicksaxis-wrapper.c b/libsicksaxis/sicksaxis-wrapper.c new file mode 100644 index 00000000..87c85dd6 --- /dev/null +++ b/libsicksaxis/sicksaxis-wrapper.c @@ -0,0 +1,135 @@ +/* +// A simple wrapper for libsicksaxis, to make it resemble WPAD/PAD more closely. +// Written by daxtsu/thedax. I'm releasing this code into the public domain, so do whatever you want with it. +// +// 2015-01 Cyan +// Added Buttons state Up and Held. +// +*/ +#include +#include "sicksaxis-wrapper.h" + +static DS3 first; +static bool psPressed = false; + +static unsigned int ButtonsUp; +static unsigned int ButtonsDown; +static unsigned int ButtonsHeld; + +bool DS3_Init() +{ + USB_Initialize(); + + if (ss_init() < 0) + { + return false; + } + + ss_initialize(&first); + + return true; +} + +void DS3_Rumble() +{ + if (first.connected && psPressed) + { + ss_set_rumble(&first, 2, 255, 2, 255); + } +} + +void DS3_Cleanup() +{ + psPressed = false; + ss_close(&first); + USB_Deinitialize(); +} + +unsigned int DS3_ButtonsDown() +{ + if (!ss_is_connected(&first) || !psPressed) + return 0; + + DS3 *controller; + controller = &first; + + unsigned int pressed = 0; + + pressed |= controller->pad.buttons.PS ? DS3_BUTTON_PS : 0; + pressed |= controller->pad.buttons.start ? DS3_BUTTON_START : 0; + pressed |= controller->pad.buttons.select ? DS3_BUTTON_SELECT : 0; + pressed |= controller->pad.buttons.triangle ? DS3_BUTTON_TRIANGLE : 0; + pressed |= controller->pad.buttons.circle ? DS3_BUTTON_CIRCLE : 0; + pressed |= controller->pad.buttons.cross ? DS3_BUTTON_CROSS : 0; + pressed |= controller->pad.buttons.square ? DS3_BUTTON_SQUARE : 0; + pressed |= controller->pad.buttons.up ? DS3_BUTTON_UP : 0; + pressed |= controller->pad.buttons.right ? DS3_BUTTON_RIGHT : 0; + pressed |= controller->pad.buttons.down ? DS3_BUTTON_DOWN : 0; + pressed |= controller->pad.buttons.left ? DS3_BUTTON_LEFT : 0; + pressed |= controller->pad.buttons.L1 ? DS3_BUTTON_L1 : 0; + pressed |= controller->pad.buttons.L2 ? DS3_BUTTON_L2 : 0; +// pressed |= controller->pad.buttons.L3 ? DS3_BUTTON_L3 : 0; + pressed |= controller->pad.buttons.R1 ? DS3_BUTTON_R1 : 0; + pressed |= controller->pad.buttons.R2 ? DS3_BUTTON_R2 : 0; +// pressed |= controller->pad.buttons.R3 ? DS3_BUTTON_R3 : 0; + + ButtonsUp = ButtonsHeld & ~pressed; + ButtonsDown = ~ButtonsHeld & pressed; + ButtonsHeld = pressed; + + return ButtonsDown; +} + +unsigned int DS3_ButtonsHeld() +{ + return ButtonsHeld; +} + +unsigned int DS3_ButtonsUp() +{ + return ButtonsUp; +} + +bool DS3_Connected() +{ + return first.connected > 0 && psPressed; +} + +void DS3_ScanPads() +{ + if (!ss_is_connected(&first)) + { + psPressed = false; + ss_initialize(&first); + if (ss_open(&first) > 0) + { + ss_start_reading(&first); + ss_set_led(&first, 0); + } + } + else if (first.pad.buttons.PS && !psPressed) + { + psPressed = true; + ss_set_led(&first, 1); + } +} + +int DS3_StickX() +{ + return psPressed? first.pad.left_analog.x - 128 : 0; +} + +int DS3_SubStickX() +{ + return psPressed? first.pad.right_analog.x - 128 : 0; +} + +int DS3_StickY() +{ + return psPressed? 127 - first.pad.left_analog.y : 0; +} + +int DS3_SubStickY() +{ + return psPressed? 127 - first.pad.right_analog.y : 0; +} diff --git a/libsicksaxis/sicksaxis-wrapper.h b/libsicksaxis/sicksaxis-wrapper.h new file mode 100644 index 00000000..f159e26c --- /dev/null +++ b/libsicksaxis/sicksaxis-wrapper.h @@ -0,0 +1,74 @@ +// A simple wrapper for libsicksaxis, to make it resemble WPAD/PAD more closely. +// Written by daxtsu/thedax. I'm releasing this code into the public domain, so do whatever you want with it. + +#ifndef _DS3WRAPPER_H_ +#define _DS3WRAPPER_H_ + +#include +#include + +struct ss_device; + +enum +{ +// DS3_BUTTON_PS = 1, +// DS3_BUTTON_START = 2, +// DS3_BUTTON_SELECT = 4, +// DS3_BUTTON_TRIANGLE = 8, +// DS3_BUTTON_CIRCLE = 16, +// DS3_BUTTON_CROSS = 32, +// DS3_BUTTON_SQUARE = 64, +// DS3_BUTTON_UP = 128, +// DS3_BUTTON_RIGHT = 256, +// DS3_BUTTON_DOWN = 512, +// DS3_BUTTON_LEFT = 1024, +// DS3_BUTTON_L1 = 2048, +// DS3_BUTTON_L2 = 4096, +// DS3_BUTTON_L3 = 8192, +// DS3_BUTTON_R1 = 16384, +// DS3_BUTTON_R2 = 32768, +// DS3_BUTTON_R3 = 65536, + + // Classic Controller mapping + DS3_BUTTON_PS = WPAD_CLASSIC_BUTTON_HOME, + DS3_BUTTON_START = WPAD_CLASSIC_BUTTON_PLUS, + DS3_BUTTON_SELECT = WPAD_CLASSIC_BUTTON_MINUS, + DS3_BUTTON_TRIANGLE = WPAD_CLASSIC_BUTTON_X, + DS3_BUTTON_CIRCLE = WPAD_CLASSIC_BUTTON_A, + DS3_BUTTON_CROSS = WPAD_CLASSIC_BUTTON_B, + DS3_BUTTON_SQUARE = WPAD_CLASSIC_BUTTON_Y, + DS3_BUTTON_UP = WPAD_CLASSIC_BUTTON_UP, + DS3_BUTTON_RIGHT = WPAD_CLASSIC_BUTTON_RIGHT, + DS3_BUTTON_DOWN = WPAD_CLASSIC_BUTTON_DOWN, + DS3_BUTTON_LEFT = WPAD_CLASSIC_BUTTON_LEFT, + DS3_BUTTON_L1 = WPAD_CLASSIC_BUTTON_FULL_L, + DS3_BUTTON_L2 = WPAD_CLASSIC_BUTTON_ZL, +// DS3_BUTTON_L3 = + DS3_BUTTON_R1 = WPAD_CLASSIC_BUTTON_FULL_R, + DS3_BUTTON_R2 = WPAD_CLASSIC_BUTTON_ZR, +// DS3_BUTTON_R3 = +}; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct ss_device DS3; +bool DS3_Init(); +void DS3_Rumble(); +void DS3_Cleanup(); +u32 DS3_ButtonsDown(); +u32 DS3_ButtonsHeld(); +u32 DS3_ButtonsUp(); +bool DS3_Connected(); +void DS3_ScanPads(); +int DS3_StickX(); +int DS3_SubStickX(); +int DS3_StickY(); +int DS3_SubStickY(); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/libsicksaxis/sicksaxis.c b/libsicksaxis/sicksaxis.c new file mode 100644 index 00000000..d57b9c07 --- /dev/null +++ b/libsicksaxis/sicksaxis.c @@ -0,0 +1,346 @@ +#include "sicksaxis.h" +#include +#include +#include + +static uint8_t ATTRIBUTE_ALIGN(32) _ss_attributes_payload[] = +{ + 0x52, + 0x00, 0x00, 0x00, 0x00, //Rumble + 0xff, 0x80, //Gyro + 0x00, 0x00, + 0x00, //* LED_1 = 0x02, LED_2 = 0x04, ... */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_4 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_3 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_2 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_1 */ +}; + +static const uint8_t _ss_led_pattern[] = {0x0, 0x02, 0x04, 0x08, 0x10, 0x12, 0x14, 0x18}; + +static int _ss_heap_id = -1; +static int _ss_inited = 0; +static int _ss_dev_number = 1; +static int _ss_dev_id_list[SS_MAX_DEV] = {0}; + +static int _ss_dev_id_list_exists(int id); +static int _ss_dev_id_list_add(int id); +static int _ss_dev_id_list_remove(int id); +static int _ss_removal_cb(int result, void *usrdata); +static int _ss_read_cb(int result, void *usrdata); +static int _ss_operational_cb(int result, void *usrdata); +static int _ss_read(struct ss_device *dev); +static int _ss_set_operational(struct ss_device *dev); +static int _ss_build_attributes_payload(struct ss_device *dev); +static int _ss_send_attributes_payload(struct ss_device *dev); + +int ss_init() +{ + if (!_ss_inited) { + _ss_heap_id = iosCreateHeap(SS_HEAP_SIZE); + _ss_inited = 1; + } + return 1; +} + + +int ss_initialize(struct ss_device *dev) +{ + dev->device_id = -1; + dev->fd = -1; + dev->connected = 0; + dev->enabled = 0; + dev->reading = 0; + dev->removal_callback = NULL; + dev->removal_usrdata = NULL; + dev->read_callback = NULL; + dev->read_usrdata = NULL; + memset(&dev->pad, 0x0, sizeof(struct SS_GAMEPAD)); + memset(&dev->attributes, 0x0, sizeof(struct SS_ATTRIBUTES)); + return 1; +} + +int ss_open(struct ss_device *dev) +{ + if (!_ss_inited) return -1; + if (dev->connected) ss_close(dev); + + usb_device_entry dev_entry[8]; + unsigned char dev_count; + if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_HID, &dev_count) < 0) { + return -2; + } + + int i; + for (i = 0; i < dev_count; ++i) { + + if ((dev_entry[i].vid == SS_VENDOR_ID) && (dev_entry[i].pid == SS_PRODUCT_ID)) { + + if (!_ss_dev_id_list_exists(dev_entry[i].device_id)) { + if (USB_OpenDevice(dev_entry[i].device_id, SS_VENDOR_ID, SS_PRODUCT_ID, &dev->fd) < 0) { + return -3; + } + + dev->device_id = dev_entry[i].device_id; + dev->connected = 1; + dev->enabled = 0; + dev->reading = 0; + + _ss_set_operational(dev); + ss_set_led(dev, _ss_dev_number); + + _ss_dev_id_list_add(dev_entry[i].device_id); + _ss_dev_number++; + + USB_DeviceRemovalNotifyAsync(dev->fd, &_ss_removal_cb, dev); + return 1; + } + } + } + return -4; +} + +int ss_close(struct ss_device *dev) +{ + if (dev && dev->fd > 0) { + USB_CloseDevice(&dev->fd); + } + return 1; +} + +int ss_is_connected(struct ss_device *dev) +{ + return dev->connected; +} + +int ss_set_read_cb(struct ss_device *dev,ss_usb_callback cb, void *usrdata) +{ + dev->read_callback = cb; + dev->read_usrdata = usrdata; + return 1; +} + +int ss_set_removal_cb(struct ss_device *dev, ss_usb_callback cb, void *usrdata) +{ + dev->removal_callback = cb; + dev->removal_usrdata = usrdata; + return 1; +} + +int ss_start_reading(struct ss_device *dev) +{ + if (dev) { + dev->reading = 1; + if (dev->enabled) { + _ss_read(dev); + } + return 1; + } + return 0; +} + + +int ss_stop_reading(struct ss_device *dev) +{ + if (dev) { + dev->reading = 0; + return 1; + } + return 0; +} + +static int _ss_build_attributes_payload(struct ss_device *dev) +{ + _ss_attributes_payload[1] = dev->attributes.rumble.duration_right; + _ss_attributes_payload[2] = dev->attributes.rumble.power_right; + _ss_attributes_payload[3] = dev->attributes.rumble.duration_left; + _ss_attributes_payload[4] = dev->attributes.rumble.power_left; + _ss_attributes_payload[9] = _ss_led_pattern[dev->attributes.led]; + return 1; +} + +static int _ss_send_attributes_payload(struct ss_device *dev) +{ + if (!dev->connected) return 0; + _ss_build_attributes_payload(dev); + return USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_SET, + USB_REQ_SETREPORT, + (USB_REPTYPE_OUTPUT<<8) | 0x01, + 0x0, + sizeof(_ss_attributes_payload), + _ss_attributes_payload, + NULL, NULL); +} + +inline int ss_set_led(struct ss_device *dev, int led) +{ + dev->attributes.led = led; + return _ss_send_attributes_payload(dev); +} + +inline int ss_set_rumble(struct ss_device *dev, uint8_t duration_right, uint8_t power_right, uint8_t duration_left, uint8_t power_left) +{ + dev->attributes.rumble.duration_right = duration_right; + dev->attributes.rumble.power_right = power_right; + dev->attributes.rumble.duration_left = duration_left; + dev->attributes.rumble.power_left = power_left; + return _ss_send_attributes_payload(dev); +} + +int ss_get_bd_address(struct ss_device *dev, uint8_t *mac) +{ + uint8_t ATTRIBUTE_ALIGN(32) msg[17]; + int ret = USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf2, + 0, + sizeof(msg), + msg, + NULL, NULL); + + mac[0] = msg[4]; + mac[1] = msg[5]; + mac[2] = msg[6]; + mac[3] = msg[7]; + mac[4] = msg[8]; + mac[5] = msg[9]; + return ret; +} + +int ss_get_mac(struct ss_device *dev, uint8_t *mac) +{ + uint8_t ATTRIBUTE_ALIGN(32) msg[8]; + int ret = USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf5, + 0, + sizeof(msg), + msg, + NULL, NULL); + + mac[0] = msg[2]; + mac[1] = msg[3]; + mac[2] = msg[4]; + mac[3] = msg[5]; + mac[4] = msg[6]; + mac[5] = msg[7]; + return ret; +} + +int ss_set_mac(struct ss_device *dev, const uint8_t *mac) +{ + uint8_t ATTRIBUTE_ALIGN(32) msg[] = {0x01, 0x00, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]}; + int ret = USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_SET, + USB_REQ_SETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf5, + 0, + sizeof(msg), + msg, + NULL, NULL); + return ret; +} + + +static int _ss_read(struct ss_device *dev) +{ + return USB_WriteCtrlMsgAsync( + dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_INPUT<<8) | 0x01, + 0x0, + SS_PAYLOAD_SIZE, + &dev->pad, + &_ss_read_cb, + dev); +} + +static int _ss_removal_cb(int result, void *usrdata) +{ + struct ss_device *dev = (struct ss_device*)usrdata; + if (dev->device_id > 0) { + _ss_dev_id_list_remove(dev->device_id); + _ss_dev_number--; + if (dev->removal_callback) + dev->removal_callback(dev->removal_usrdata); + ss_initialize(dev); + return 1; + } + return 0; +} + +static int _ss_set_operational(struct ss_device *dev) +{ + uint8_t ATTRIBUTE_ALIGN(32) buf[17]; + return USB_WriteCtrlMsgAsync( + dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf2, + 0x0, + 17, + buf, + &_ss_operational_cb, + dev); +} + +static int _ss_read_cb(int result, void *usrdata) +{ + if (usrdata) { + struct ss_device *dev = (struct ss_device*)usrdata; + if (dev->reading) { + _ss_read(dev); + if (dev->read_callback) + dev->read_callback(dev->read_usrdata); + } + } + return 1; +} + +static int _ss_operational_cb(int result, void *usrdata) +{ + struct ss_device *dev = (struct ss_device*)usrdata; + dev->enabled = 1; + if (dev->reading) { + _ss_read(dev); + } + return 1; +} + + +static int _ss_dev_id_list_exists(int id) +{ + int i; + for (i = 0; i < SS_MAX_DEV; ++i) { + if (_ss_dev_id_list[i] == id) return 1; + } + return 0; +} + +static int _ss_dev_id_list_add(int id) +{ + int i; + for (i = 0; i < SS_MAX_DEV; ++i) { + if (_ss_dev_id_list[i] == 0) { + _ss_dev_id_list[i] = id; + return 1; + } + } + return 0; +} + +static int _ss_dev_id_list_remove(int id) +{ + int i; + for (i = 0; i < SS_MAX_DEV; ++i) { + if (_ss_dev_id_list[i] == id) { + _ss_dev_id_list[i] = 0; + return 1; + } + } + return 0; +} diff --git a/libsicksaxis/sicksaxis.h b/libsicksaxis/sicksaxis.h new file mode 100644 index 00000000..c514aed5 --- /dev/null +++ b/libsicksaxis/sicksaxis.h @@ -0,0 +1,143 @@ +#ifndef _SICKSAXIS_H_ +#define _SICKSAXIS_H_ + +#include + + +#define SS_HEAP_SIZE 4096 +#define SS_MAX_DEV 8 +#define SS_VENDOR_ID 0x054C +#define SS_PRODUCT_ID 0x0268 +#define SS_PAYLOAD_SIZE 49 + +struct SS_BUTTONS +{ + uint8_t left : 1; + uint8_t down : 1; + uint8_t right : 1; + uint8_t up : 1; + uint8_t start : 1; + uint8_t R3 : 1; + uint8_t L3 : 1; + uint8_t select : 1; + + uint8_t square : 1; + uint8_t cross : 1; + uint8_t circle : 1; + uint8_t triangle : 1; + uint8_t R1 : 1; + uint8_t L1 : 1; + uint8_t R2 : 1; + uint8_t L2 : 1; + + uint8_t not_used : 7; + uint8_t PS : 1; +}; + +struct SS_ANALOG +{ + uint8_t x; + uint8_t y; +}; + +struct SS_DPAD_SENSITIVE +{ + uint8_t up; + uint8_t right; + uint8_t down; + uint8_t left; +}; + +struct SS_SHOULDER_SENSITIVE +{ + uint8_t L2; + uint8_t R2; + uint8_t L1; + uint8_t R1; +}; + +struct SS_BUTTON_SENSITIVE +{ + uint8_t triangle; + uint8_t circle; + uint8_t cross; + uint8_t square; +}; + +struct SS_MOTION +{ + uint16_t acc_x; + uint16_t acc_y; + uint16_t acc_z; + uint16_t z_gyro; +}; + +struct SS_GAMEPAD +{ + uint8_t hid_data; + uint8_t unk0; + struct SS_BUTTONS buttons; + uint8_t unk1; + struct SS_ANALOG left_analog; + struct SS_ANALOG right_analog; + uint32_t unk2; + struct SS_DPAD_SENSITIVE dpad_sens; + struct SS_SHOULDER_SENSITIVE shoulder_sens; + struct SS_BUTTON_SENSITIVE button_sens; + uint16_t unk3; + uint8_t unk4; + uint8_t status; + uint8_t power_rating; + uint8_t comm_status; + uint32_t unk5; + uint32_t unk6; + uint8_t unk7; + struct SS_MOTION motion; +}__attribute__((packed)); + +struct SS_ATTRIBUTE_RUMBLE +{ + uint8_t duration_right; + uint8_t power_right; + uint8_t duration_left; + uint8_t power_left; +}; + +struct SS_ATTRIBUTES +{ + struct SS_ATTRIBUTE_RUMBLE rumble; + int led; +}; + +typedef void (*ss_usb_callback)(void *usrdata); + +struct ss_device { + struct SS_GAMEPAD pad; + struct SS_ATTRIBUTES attributes; + int device_id, fd; + int connected, enabled, reading; + ss_usb_callback read_callback; + ss_usb_callback removal_callback; + void *read_usrdata, *removal_usrdata; +}__attribute__((aligned(32))); + + +int ss_init(); +int ss_initialize(struct ss_device *dev); +int ss_open(struct ss_device *dev); +int ss_close(struct ss_device *dev); +int ss_is_connected(struct ss_device *dev); + +int ss_set_read_cb(struct ss_device *dev, ss_usb_callback cb, void *usrdata); +int ss_set_removal_cb(struct ss_device *dev, ss_usb_callback cb, void *usrdata); + +int ss_start_reading(struct ss_device *dev); +int ss_stop_reading(struct ss_device *dev); +int ss_set_led(struct ss_device *dev, int led); +int ss_set_rumble(struct ss_device *dev, uint8_t duration_right, uint8_t power_right, uint8_t duration_left, uint8_t power_left); +int ss_get_bd_address(struct ss_device *dev, uint8_t *mac); +int ss_get_paired_mac(struct ss_device *dev, uint8_t *mac); +int ss_set_paired_mac(struct ss_device *dev, const uint8_t *mac); + + +#endif diff --git a/libwupc/Makefile b/libwupc/Makefile new file mode 100644 index 00000000..6728c868 --- /dev/null +++ b/libwupc/Makefile @@ -0,0 +1,98 @@ +#--------------------------------------------------------------------------------- +# 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 := libwupc +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include +INCDIR := $(LIBOGC_INC)/wupc/ +INCFILE := include/wupc/wupc +LIBFILE := lib/$(TARGET) +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CFLAGS = -g -O2 -Wall -Wextra $(MACHDEP) $(INCLUDE) + +#--------------------------------------------------------------------------------- +# 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)/lib/$(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 +#--------------------------------------------------------------------------------- +export CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +#--------------------------------------------------------------------------------- +export OFILES := $(CFILES:.c=.o) +export LD := $(CC) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(LIBOGC_INC) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).a + +#--------------------------------------------------------------------------------- + +install: + @echo Installing ... + @mkdir -p $(INCDIR) + @install -v -m 644 $(LIBFILE).a $(LIBOGC_LIB) + @install -v -m 644 $(INCFILE).h $(INCDIR) +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).a: $(OFILES) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/libwupc/include/wupc/wupc.h b/libwupc/include/wupc/wupc.h new file mode 100644 index 00000000..a337b395 --- /dev/null +++ b/libwupc/include/wupc/wupc.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * Copyright (C) 2014 FIX94 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#ifndef _WUPC_H_ +#define _WUPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct WUPCData { + s16 xAxisL; + s16 xAxisR; + s16 yAxisL; + s16 yAxisR; + u32 button; + u8 battery; + u8 extra; +}; + +#define WUPC_EXTRA_BUTTON_RSTICK 0x01 +#define WUPC_EXTRA_BUTTON_LSTICK 0x02 + +#define WUPC_EXTRA_CHARGING 0x04 +#define WUPC_EXTRA_USBCONNECTED 0x08 + +void WUPC_Init(); +void WUPC_Disconnect(u8 chan); +void WUPC_Shutdown(); +struct WUPCData *WUPC_Data(u8 chan); +void WUPC_Rumble(u8 chan, bool rumble); +u32 WUPC_UpdateButtonStats(); +u32 WUPC_ButtonsUp(u8 chan); +u32 WUPC_ButtonsDown(u8 chan); +u32 WUPC_ButtonsHeld(u8 chan); +s16 WUPC_lStickX(u8 chan); +s16 WUPC_lStickY(u8 chan); +s16 WUPC_rStickX(u8 chan); +s16 WUPC_rStickY(u8 chan); +u8 WUPC_extra(u8 chan); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libwupc/libwupc_r3_mod1 (JoostinOnline).patch b/libwupc/libwupc_r3_mod1 (JoostinOnline).patch new file mode 100644 index 00000000..0dd3258d --- /dev/null +++ b/libwupc/libwupc_r3_mod1 (JoostinOnline).patch @@ -0,0 +1,80 @@ +Index: Makefile +=================================================================== +--- Makefile (revision 3) ++++ Makefile (working copy) +@@ -20,7 +20,9 @@ + SOURCES := source + DATA := data + INCLUDES := include +- ++INCDIR := $(LIBOGC_INC)/wupc/ ++INCFILE := include/wupc/wupc ++LIBFILE := lib/$(TARGET) + #--------------------------------------------------------------------------------- + # options for code generation + #--------------------------------------------------------------------------------- +@@ -72,7 +74,13 @@ + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).a + ++#--------------------------------------------------------------------------------- + ++install: ++ @echo Installing ... ++ @mkdir -p $(INCDIR) ++ @install -v -m 644 $(LIBFILE).a $(LIBOGC_LIB) ++ @install -v -m 644 $(INCFILE).h $(INCDIR) + #--------------------------------------------------------------------------------- + else + +Index: usage.txt +=================================================================== +--- usage.txt (revision 3) ++++ usage.txt (working copy) +@@ -1,23 +1,23 @@ +-libwupc - A WiiU Pro Controller Library for Wii Homebrew Applications by FIX94 +-WiiU Pro Controller Documentation from TeHaxor69 +- +-1. Copy the "lib" and "include" folder into your "portlibs" folder +- +-2. Make these modifications to your Makefile: +--add "-lwupc" right behind "-lwiiuse" to your LIBS +--add ",-wrap,wiiuse_register" to your LDFLAGS +- +-3. Modify your code like this: +--make sure to include in all files you use WUPC calls +--call "WUPC_Init" before "WPAD_Init" +--call "WUPC_Shutdown" before "WPAD_Shutdown" +--either use the separate calls or use WUPC_Data at the same place you would normally use the WPAD calls for your data handling +--if you use ButtonsUp, ButtonsUp and/or ButtonsHeld, make sure to call "WUPC_UpdateButtonStats" before "WPAD_ScanPads", +-if you dont use any of these you can ignore "WUPC_UpdateButtonStats" +- +-Notes: +--The X and Y-Axis are going from about -1024 to +1024, make sure you adjust your calculations to that +--The Buttons are using the same layout as the classic controller buttons, use the "WPAD_CLASSIC_BUTTON_" definitions in +--The Battery Status goes from 0 (critical) to 4 (full) +- ++libwupc - A WiiU Pro Controller Library for Wii Homebrew Applications by FIX94 ++WiiU Pro Controller Documentation from TeHaxor69 ++ ++1. Copy the "lib" and "include" folder into your "portlibs" folder ++ ++2. Make these modifications to your Makefile: ++-add "-lwupc" right after "-lwiiuse" to your LIBS ++-add ",-wrap,wiiuse_register" to your LDFLAGS ++ ++3. Modify your code like this: ++-make sure to include in all files you use WUPC calls ++-call "WUPC_Init" before "WPAD_Init" ++-call "WUPC_Shutdown" before "WPAD_Shutdown" ++-either use the separate calls or use WUPC_Data at the same place you would normally use the WPAD calls for your data handling ++-if you use ButtonsUp, ButtonsUp and/or ButtonsHeld, make sure to call "WUPC_UpdateButtonStats" before "WPAD_ScanPads", ++if you dont use any of these you can ignore "WUPC_UpdateButtonStats" ++ ++Notes: ++-The X and Y-Axis are going from about -1024 to +1024, make sure you adjust your calculations to that ++-The Buttons are using the same layout as the classic controller buttons, use the "WPAD_CLASSIC_BUTTON_" definitions in ++-The Battery Status goes from 0 (critical) to 4 (full) ++ + Have Fun! +\ No newline at end of file diff --git a/libwupc/libwupc_r3_mod2 (Cyan).patch b/libwupc/libwupc_r3_mod2 (Cyan).patch new file mode 100644 index 00000000..33fea6dc --- /dev/null +++ b/libwupc/libwupc_r3_mod2 (Cyan).patch @@ -0,0 +1,76 @@ +Index: include/wupc/wupc.h +=================================================================== +--- include/wupc/wupc.h (revision 3) ++++ include/wupc/wupc.h (working copy) +@@ -50,6 +50,7 @@ + s16 WUPC_lStickY(u8 chan); + s16 WUPC_rStickX(u8 chan); + s16 WUPC_rStickY(u8 chan); ++u8 WUPC_extra(u8 chan); + + #ifdef __cplusplus + } +Index: Makefile +=================================================================== +--- Makefile (revision 3) ++++ Makefile (working copy) +@@ -20,7 +20,9 @@ + SOURCES := source + DATA := data + INCLUDES := include +- ++INCDIR := $(LIBOGC_INC)/wupc/ ++INCFILE := include/wupc/wupc ++LIBFILE := lib/$(TARGET) + #--------------------------------------------------------------------------------- + # options for code generation + #--------------------------------------------------------------------------------- +@@ -72,7 +74,13 @@ + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).a + ++#--------------------------------------------------------------------------------- + ++install: ++ @echo Installing ... ++ @mkdir -p $(INCDIR) ++ @install -v -m 644 $(LIBFILE).a $(LIBOGC_LIB) ++ @install -v -m 644 $(INCFILE).h $(INCDIR) + #--------------------------------------------------------------------------------- + else + +Index: source/wupc.c +=================================================================== +--- source/wupc.c (revision 3) ++++ source/wupc.c (working copy) +@@ -230,7 +230,7 @@ + { + if(__WUPC_Connected[i] == NULL) + return ret; +- newstate = __WUPC_PadData[i].button; ++ newstate = __WUPC_PadData[i].button | (__WUPC_PadData[i].extra & WUPC_EXTRA_BUTTON_RSTICK) | (__WUPC_PadData[i].extra & WUPC_EXTRA_BUTTON_LSTICK); + oldstate = __WUPC_PadButtons[i].state; + __WUPC_PadButtons[i].state = newstate; + __WUPC_PadButtons[i].up = oldstate & ~newstate; +@@ -275,3 +275,8 @@ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadData[chan].yAxisR; + } ++u8 WUPC_extra(u8 chan) ++{ ++ if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; ++ return __WUPC_PadData[chan].extra; ++} +Index: usage.txt +=================================================================== +--- usage.txt (revision 3) ++++ usage.txt (working copy) +@@ -4,7 +4,7 @@ + 1. Copy the "lib" and "include" folder into your "portlibs" folder + + 2. Make these modifications to your Makefile: +--add "-lwupc" right behind "-lwiiuse" to your LIBS ++-add "-lwupc" right after "-lwiiuse" to your LIBS + -add ",-wrap,wiiuse_register" to your LDFLAGS + + 3. Modify your code like this: diff --git a/libwupc/source/wupc.c b/libwupc/source/wupc.c new file mode 100644 index 00000000..02212bb3 --- /dev/null +++ b/libwupc/source/wupc.c @@ -0,0 +1,282 @@ +/**************************************************************************** + * Copyright (C) 2014 FIX94 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +/* WiiU Pro Controller Documentation from TeHaxor69 */ + +#include +#include +#include +#include +#include +#include "wupc_structs.h" +#include "wupc/wupc.h" + +extern __typeof(wiiuse_register) __real_wiiuse_register; + +static vu32 __WUPC_ChannelsUsed = 0; + +static conf_pads __WUPC_Devices; +static struct WUPCStat *__WUPC_Connected[4]; +static struct WUPCStat __WUPC_Status[CONF_PAD_MAX_REGISTERED]; +static struct WUPCData __WUPC_PadData[4]; +static struct WUPCButtons __WUPC_PadButtons[4]; + +static u32 __WUPC_Inited = 0; + +static const u8 __WUPC_LEDState[] = { 0x10, 0x20, 0x40, 0x80 }; + +#define CHAN_MAX 4 + +#define TRANSFER_CALIBRATE 0 +#define TRANSFER_DONE 1 + +static void __WUPC_SetLED(struct bte_pcb *sock, u32 state) +{ + u8 buf[2]; + buf[0] = 0x11; + buf[1] = __WUPC_LEDState[state]; + bte_senddata(sock,buf,2); +} +static s32 __WUPC_HandleData(void *arg,void *buffer,u16 len) +{ + struct WUPCStat *stat = (struct WUPCStat*)arg; + u32 chan = stat->channel; + + if(*(u8*)buffer == 0x3D && len == 22) + { + if(stat->transferstate == TRANSFER_CALIBRATE) + { + stat->xAxisLmid = bswap16(*(u16*)(((u8*)buffer)+1)); + stat->xAxisRmid = bswap16(*(u16*)(((u8*)buffer)+3)); + stat->yAxisLmid = bswap16(*(u16*)(((u8*)buffer)+5)); + stat->yAxisRmid = bswap16(*(u16*)(((u8*)buffer)+7)); + stat->transferstate = TRANSFER_DONE; + } + __WUPC_PadData[chan].xAxisL = bswap16(*(u16*)(((u8*)buffer)+1)) - stat->xAxisLmid; + __WUPC_PadData[chan].xAxisR = bswap16(*(u16*)(((u8*)buffer)+3)) - stat->xAxisRmid; + __WUPC_PadData[chan].yAxisL = bswap16(*(u16*)(((u8*)buffer)+5)) - stat->yAxisLmid; + __WUPC_PadData[chan].yAxisR = bswap16(*(u16*)(((u8*)buffer)+7)) - stat->yAxisRmid; + __WUPC_PadData[chan].button = ~(*(u16*)(((u8*)buffer)+9)) << 16; + u8 extradata = ~(*(((u8*)buffer)+11)); + __WUPC_PadData[chan].battery = (extradata >> 4) & 0x7; + __WUPC_PadData[chan].extra = extradata & 0xF; + } + return ERR_OK; +} + +static s32 __WUPC_HandleConnect(void *arg,struct bte_pcb *pcb,u8 err) +{ + struct WUPCStat *stat = (struct WUPCStat*)arg; + + if(__WUPC_ChannelsUsed >= CHAN_MAX) + { + bte_disconnect(pcb); + return err; + } + + stat->channel = __WUPC_ChannelsUsed; + stat->rumble = 0; + + __WUPC_SetLED(pcb, __WUPC_ChannelsUsed); + + u8 buf[3]; + buf[0] = 0x12; + buf[1] = 0x00; + buf[2] = 0x3D; + bte_senddata(pcb,buf,3); + stat->transferstate = TRANSFER_CALIBRATE; + + __WUPC_Connected[__WUPC_ChannelsUsed] = stat; + __WUPC_ChannelsUsed++; + return err; +} + +static s32 __WUPC_HandleDisconnect(void *arg,struct bte_pcb *pcb __attribute__((unused)),u8 err) +{ + struct WUPCStat *stat = (struct WUPCStat*)arg; + if(__WUPC_ChannelsUsed) __WUPC_ChannelsUsed--; + + u32 i; + for(i = stat->channel; i < 3; ++i) + __WUPC_Connected[i] = __WUPC_Connected[i+1]; + __WUPC_Connected[3] = NULL; + + for(i = 0; i < CONF_PAD_MAX_REGISTERED; ++i) + { + if(__WUPC_Status[i].channel > stat->channel && __WUPC_Status[i].channel != CHAN_MAX) + { + __WUPC_Status[i].channel--; + __WUPC_SetLED(__WUPC_Status[i].sock, __WUPC_Status[i].channel); + } + } + stat->channel = CHAN_MAX; + return err; +} + +int __WUPC_RegisterPad(struct WUPCStat *stat, struct bd_addr *_bdaddr) +{ + stat->channel = CHAN_MAX; + stat->bdaddr = *_bdaddr; + + if(stat->sock == NULL) + { + stat->sock = bte_new(); + if(stat->sock == NULL) + return ERR_OK; + } + + bte_arg(stat->sock, stat); + bte_received(stat->sock, __WUPC_HandleData); + bte_disconnected(stat->sock, __WUPC_HandleDisconnect); + + bte_registerdeviceasync(stat->sock, _bdaddr, __WUPC_HandleConnect); + + return ERR_OK; +} + +int __wrap_wiiuse_register(struct wiimote_listen_t *wml, struct bd_addr *bdaddr, struct wiimote_t *(*assign_cb)(struct bd_addr *bdaddr)) +{ + if(__WUPC_Inited) + { + u8 got_addr[] = { bdaddr->addr[5], bdaddr->addr[4], bdaddr->addr[3], bdaddr->addr[2], bdaddr->addr[1], bdaddr->addr[0] }; + u32 i; + for(i = 0; i < __WUPC_Devices.num_registered; ++i) + { + if(strstr(__WUPC_Devices.registered[i].name, "-UC") != NULL) + { + u8 *cur_bdaddr = __WUPC_Devices.registered[i].bdaddr; + if(memcmp(cur_bdaddr, got_addr, 6) == 0) + return __WUPC_RegisterPad(&__WUPC_Status[i], bdaddr); + } + } + } + return __real_wiiuse_register(wml,bdaddr,assign_cb); +} + +void WUPC_Init() +{ + if(__WUPC_Inited == 1) + return; + if(CONF_GetPadDevices(&__WUPC_Devices) < 0) + return; + + u32 i; + for(i = 0; i < CHAN_MAX; ++i) + __WUPC_Connected[i] = NULL; + + for(i = 0; i < CONF_PAD_MAX_REGISTERED; ++i) + __WUPC_Status[i].channel = CHAN_MAX; + + __WUPC_ChannelsUsed = 0; + __WUPC_Inited = 1; +} + +void WUPC_Disconnect(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return; + bte_disconnect(__WUPC_Connected[chan]->sock); +} + +void WUPC_Shutdown() +{ + if(__WUPC_Inited == 0) + return; + + __WUPC_Inited = 0; + + u32 i; + for(i = 0; i < CONF_PAD_MAX_REGISTERED; ++i) + { + if(__WUPC_Status[i].channel != CHAN_MAX) + bte_disconnect(__WUPC_Status[i].sock); + } +} + +struct WUPCData *WUPC_Data(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return NULL; + return &__WUPC_PadData[chan]; +} + +void WUPC_Rumble(u8 chan, bool rumble) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return; + + u8 buf[2]; + buf[0] = 0x11; + buf[1] = __WUPC_LEDState[chan] | rumble; + bte_senddata(__WUPC_Connected[chan]->sock,buf,2); +} + +u32 WUPC_UpdateButtonStats() +{ + u32 newstate, oldstate; + u32 i, ret = 0; + for(i = 0; i < CHAN_MAX; ++i) + { + if(__WUPC_Connected[i] == NULL) + return ret; + newstate = __WUPC_PadData[i].button | (__WUPC_PadData[i].extra & WUPC_EXTRA_BUTTON_RSTICK) | (__WUPC_PadData[i].extra & WUPC_EXTRA_BUTTON_LSTICK); + oldstate = __WUPC_PadButtons[i].state; + __WUPC_PadButtons[i].state = newstate; + __WUPC_PadButtons[i].up = oldstate & ~newstate; + __WUPC_PadButtons[i].down = newstate & (newstate ^ oldstate); + ret |= (1<= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadButtons[chan].up; +} +u32 WUPC_ButtonsDown(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadButtons[chan].down; +} +u32 WUPC_ButtonsHeld(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadButtons[chan].state; +} +s16 WUPC_lStickX(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadData[chan].xAxisL; +} +s16 WUPC_lStickY(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadData[chan].yAxisL; +} +s16 WUPC_rStickX(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadData[chan].xAxisR; +} +s16 WUPC_rStickY(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadData[chan].yAxisR; +} +u8 WUPC_extra(u8 chan) +{ + if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadData[chan].extra; +} diff --git a/libwupc/source/wupc_structs.h b/libwupc/source/wupc_structs.h new file mode 100644 index 00000000..9f7857fa --- /dev/null +++ b/libwupc/source/wupc_structs.h @@ -0,0 +1,24 @@ + +#ifndef _WUPC_STRUCTS_H_ +#define _WUPC_STRUCTS_H_ + +struct WUPCStat { + u32 connected; + u32 transferstate; + u32 channel; + u32 rumble; + s16 xAxisLmid; + s16 xAxisRmid; + s16 yAxisLmid; + s16 yAxisRmid; + struct bte_pcb *sock; + struct bd_addr bdaddr; +}; + +struct WUPCButtons { + u32 up; + u32 down; + u32 state; +}; + +#endif diff --git a/libwupc/usage.txt b/libwupc/usage.txt new file mode 100644 index 00000000..3ddf642f --- /dev/null +++ b/libwupc/usage.txt @@ -0,0 +1,23 @@ +libwupc - A WiiU Pro Controller Library for Wii Homebrew Applications by FIX94 +WiiU Pro Controller Documentation from TeHaxor69 + +1. Copy the "lib" and "include" folder into your "portlibs" folder + +2. Make these modifications to your Makefile: +-add "-lwupc" right after "-lwiiuse" to your LIBS +-add ",-wrap,wiiuse_register" to your LDFLAGS + +3. Modify your code like this: +-make sure to include in all files you use WUPC calls +-call "WUPC_Init" before "WPAD_Init" +-call "WUPC_Shutdown" before "WPAD_Shutdown" +-either use the separate calls or use WUPC_Data at the same place you would normally use the WPAD calls for your data handling +-if you use ButtonsUp, ButtonsUp and/or ButtonsHeld, make sure to call "WUPC_UpdateButtonStats" before "WPAD_ScanPads", +if you dont use any of these you can ignore "WUPC_UpdateButtonStats" + +Notes: +-The X and Y-Axis are going from about -1024 to +1024, make sure you adjust your calculations to that +-The Buttons are using the same layout as the classic controller buttons, use the "WPAD_CLASSIC_BUTTON_" definitions in +-The Battery Status goes from 0 (critical) to 4 (full) + +Have Fun! \ No newline at end of file