mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-15 16:05:10 +01:00
Push r1235 in internal update menu and window's installer.
Added used libraries to /branches/libs/ You need to "make" and "make install" both libsicksaxis and libupc to compile USBLoaderGX r1235+
This commit is contained in:
parent
da71bf99dc
commit
0cd2573062
131
libruntimeiospatch/API
Normal file
131
libruntimeiospatch/API
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
******
|
41
libruntimeiospatch/CHANGES
Normal file
41
libruntimeiospatch/CHANGES
Normal file
@ -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()
|
153
libruntimeiospatch/Makefile
Normal file
153
libruntimeiospatch/Makefile
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPPC)/wii_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := 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
|
||||||
|
#---------------------------------------------------------------------------------
|
21
libruntimeiospatch/README
Normal file
21
libruntimeiospatch/README
Normal file
@ -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 <libruntimeiospatch.h> // Code
|
||||||
|
LIBS := -lruntimeiospatch // Makefile
|
||||||
|
|
||||||
|
=== API ===
|
||||||
|
|
||||||
|
see File "API"
|
||||||
|
|
||||||
|
= Thanks =
|
||||||
|
- libOGC devs
|
||||||
|
- Team Twizzers
|
||||||
|
- damysterman
|
||||||
|
- anyone I forgot to mention here
|
188
libruntimeiospatch/source/runtimeiospatch.c
Normal file
188
libruntimeiospatch/source/runtimeiospatch.c
Normal file
@ -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 <joe.ftpii@psychlaw.com.au>
|
||||||
|
// Copyright (C) 2012-2013 damysteryman
|
||||||
|
// Copyright (C) 2012-2013 Christopher Bratusek <nano@tuxfamily.org>
|
||||||
|
// Copyright (C) 2013 DarkMatterCore
|
||||||
|
// Copyright (C) 2014 megazig
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <ogc/machine/processor.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
}
|
147
libruntimeiospatch/source/runtimeiospatch.h
Normal file
147
libruntimeiospatch/source/runtimeiospatch.h
Normal file
@ -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 <joe.ftpii@psychlaw.com.au>
|
||||||
|
// Copyright (C) 2012-2013 damysteryman
|
||||||
|
// Copyright (C) 2012-2013 Christopher Bratusek <nano@tuxfamily.org>
|
||||||
|
// 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
|
28
libsicksaxis/Makefile
Normal file
28
libsicksaxis/Makefile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>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)
|
135
libsicksaxis/sicksaxis-wrapper.c
Normal file
135
libsicksaxis/sicksaxis-wrapper.c
Normal file
@ -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 <sicksaxis.h>
|
||||||
|
#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;
|
||||||
|
}
|
74
libsicksaxis/sicksaxis-wrapper.h
Normal file
74
libsicksaxis/sicksaxis-wrapper.h
Normal file
@ -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 <gctypes.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
|
||||||
|
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
|
346
libsicksaxis/sicksaxis.c
Normal file
346
libsicksaxis/sicksaxis.c
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
#include "sicksaxis.h"
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
143
libsicksaxis/sicksaxis.h
Normal file
143
libsicksaxis/sicksaxis.h
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#ifndef _SICKSAXIS_H_
|
||||||
|
#define _SICKSAXIS_H_
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
98
libwupc/Makefile
Normal file
98
libwupc/Makefile
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPPC)/wii_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := 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
|
||||||
|
#---------------------------------------------------------------------------------
|
59
libwupc/include/wupc/wupc.h
Normal file
59
libwupc/include/wupc/wupc.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
#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
|
80
libwupc/libwupc_r3_mod1 (JoostinOnline).patch
Normal file
80
libwupc/libwupc_r3_mod1 (JoostinOnline).patch
Normal file
@ -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 <wupc/wupc.h> 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 <wiiuse/wpad.h>
|
||||||
|
--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 <wupc/wupc.h> 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 <wiiuse/wpad.h>
|
||||||
|
+-The Battery Status goes from 0 (critical) to 4 (full)
|
||||||
|
+
|
||||||
|
Have Fun!
|
||||||
|
\ No newline at end of file
|
76
libwupc/libwupc_r3_mod2 (Cyan).patch
Normal file
76
libwupc/libwupc_r3_mod2 (Cyan).patch
Normal file
@ -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:
|
282
libwupc/source/wupc.c
Normal file
282
libwupc/source/wupc.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* WiiU Pro Controller Documentation from TeHaxor69 */
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <ogc/machine/processor.h>
|
||||||
|
#include <wiiuse/wiiuse.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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<<i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 WUPC_ButtonsUp(u8 chan)
|
||||||
|
{
|
||||||
|
if(chan >= 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;
|
||||||
|
}
|
24
libwupc/source/wupc_structs.h
Normal file
24
libwupc/source/wupc_structs.h
Normal file
@ -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
|
23
libwupc/usage.txt
Normal file
23
libwupc/usage.txt
Normal file
@ -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 <wupc/wupc.h> 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 <wiiuse/wpad.h>
|
||||||
|
-The Battery Status goes from 0 (critical) to 4 (full)
|
||||||
|
|
||||||
|
Have Fun!
|
Loading…
Reference in New Issue
Block a user