mirror of
https://github.com/wiiu-env/WiiUPluginSystem.git
synced 2024-12-23 16:42:00 +01:00
Formatting, added bash script for installing/updating the dependencies (based on the travis script)
This commit is contained in:
parent
0e60a9bb48
commit
6ca382bf6e
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,6 +4,7 @@ loader/*.elf
|
||||
example_plugin/bin/*
|
||||
example_plugin/build/*
|
||||
example_plugin_pic/*
|
||||
portlib_repos/*
|
||||
plugins/*/bin/*
|
||||
plugins/*/build/*
|
||||
plugins/*/*.cbp
|
||||
@ -17,3 +18,4 @@ release/*
|
||||
*.nam
|
||||
*.til
|
||||
*.layout
|
||||
wups.cbp
|
||||
|
21
installupdateportlibs.sh
Normal file
21
installupdateportlibs.sh
Normal file
@ -0,0 +1,21 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
7z x -y ./loader/libs/portlibs.zip -o${DEVKITPRO}
|
||||
mkdir portlib_repos
|
||||
cd portlib_repos
|
||||
((git clone https://github.com/Maschell/dynamic_libs.git -b lib && (7z x -y ./dynamic_libs/libs/portlibs.zip -o${DEVKITPRO})) || (cd dynamic_libs && git pull))
|
||||
(git clone https://github.com/dimok789/libiosuhax.git || (cd libiosuhax && git pull))
|
||||
(git clone https://github.com/aliaspider/libfat.git || (cd libfat && git pull))
|
||||
(git clone https://github.com/Maschell/libntfs-wiiu.git || (cd libntfs-wiiu && git pull))
|
||||
(git clone https://github.com/Maschell/libutils.git || (cd libutils && git pull))
|
||||
((git clone https://github.com/Maschell/libgui.git && (7z x -y ./libgui/libs/portlibs.zip -o${DEVKITPRO})) || (cd libgui && git pull))
|
||||
(git clone https://github.com/Maschell/fs_wrapper.git || (cd fs_wrapper && git pull))
|
||||
(git clone https://github.com/Maschell/controller_patcher.git || (cd controller_patcher && git pull))
|
||||
(cd dynamic_libs && ((make -j8 | grep -c "built ... ") && make install && echo "installed" ) || (echo "no need for make install" && make))
|
||||
(cd libiosuhax && make -j8 && make install)
|
||||
(cd libfat && make wiiu-release && make wiiu-install)
|
||||
(cd libntfs-wiiu && make wiiu-install)
|
||||
(cd libutils && ((make -j8 | grep -c "built ... ") && make install && echo "installed" ) || (echo "no need for make install" && make))
|
||||
(cd libgui && ((make -j8 | grep -c "built ... ") && make install) || echo "no need for make install")
|
||||
(cd fs_wrapper && ((make -j8 | grep -c "built ... ") && make install && echo "installed" ) || (echo "no need for make install" && make))
|
||||
(cd controller_patcher && ((make -j8 | grep -c "built ... ") && make install && echo "installed" ) || (echo "no need for make install" && make))
|
@ -22,21 +22,21 @@
|
||||
#include <dynamic_libs/vpad_functions.h>
|
||||
#include <dynamic_libs/padscore_functions.h>
|
||||
#include <dynamic_libs/proc_ui_functions.h>
|
||||
#include <utils/logger.h>
|
||||
|
||||
#include <fs/FSUtils.h>
|
||||
#include <fs/sd_fat_devoptab.h>
|
||||
#include <utils/logger.h>
|
||||
#include <utils/utils.h>
|
||||
#include <utils/function_patcher.h>
|
||||
#include <system/exception_handler.h>
|
||||
#include <system/memory.h>
|
||||
#include <kernel/kernel_utils.h>
|
||||
|
||||
|
||||
#include "common/retain_vars.h"
|
||||
#include "common/common.h"
|
||||
#include "plugin/PluginLoader.h"
|
||||
#include "plugin/PluginInformation.h"
|
||||
|
||||
#include <utils/function_patcher.h>
|
||||
|
||||
#include <wups.h>
|
||||
#include <iosuhax.h>
|
||||
|
@ -20,12 +20,4 @@
|
||||
#define SCREEN_WIDTH 1280
|
||||
#define SCREEN_HEIGHT 720
|
||||
|
||||
#define CONTENT_WIDTH (1280 - 260)
|
||||
|
||||
#define CONTENT_EXPANDABLE_FRAME_HEADER_HEIGHT 60
|
||||
|
||||
|
||||
#define MENU_LIST_WIDTH 260
|
||||
#define MENU_LIST_ELEMENT_HEIGHT 70
|
||||
|
||||
#endif
|
||||
|
@ -9,11 +9,9 @@
|
||||
#include <gui/sigslot.h>
|
||||
#include <gui/Gui.h>
|
||||
|
||||
class TcpReceiver : public CThread
|
||||
{
|
||||
class TcpReceiver : public CThread {
|
||||
public:
|
||||
enum eLoadResults
|
||||
{
|
||||
enum eLoadResults {
|
||||
SUCCESS = 0,
|
||||
INVALID_INPUT = -1,
|
||||
FILE_OPEN_FAILURE = -2,
|
||||
|
@ -30,8 +30,7 @@ static int *pretend_root_hub = (int*)0xF5003ABC;
|
||||
static int *ayylmao = (int*)0xF4500000;
|
||||
//!-------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
u32 size;
|
||||
u8 data[0];
|
||||
} payload_info_t;
|
||||
@ -47,273 +46,272 @@ typedef struct
|
||||
|
||||
/* ROP CHAIN STARTS HERE (0x1015BD78) */
|
||||
static const unsigned int final_chain[] = {
|
||||
0x101236f3, // 0x00 POP {R1-R7,PC}
|
||||
0x0, // 0x04 arg
|
||||
0x0812974C, // 0x08 stackptr CMP R3, #1; STREQ R1, [R12]; BX LR
|
||||
0x68, // 0x0C stacksize
|
||||
0x10101638, // 0x10
|
||||
0x0, // 0x14
|
||||
0x0, // 0x18
|
||||
0x0, // 0x1C
|
||||
0x1010388C, // 0x20 CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x24
|
||||
0x0, // 0x28
|
||||
0x1012CFEC, // 0x2C MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x30
|
||||
0x0, // 0x34
|
||||
IOS_CREATETHREAD, // 0x38
|
||||
0x1, // 0x3C
|
||||
0x2, // 0x40
|
||||
0x10123a9f, // 0x44 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x00, // 0x48 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE92D4010, // 0x4C value: PUSH {R4,LR}
|
||||
0x0, // 0x50
|
||||
0x10123a8b, // 0x54 POP {R3,R4,PC}
|
||||
0x1, // 0x58 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x5C
|
||||
0x1010CD18, // 0x60 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x64
|
||||
0x0, // 0x68
|
||||
0x1012EE64, // 0x6C set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x70
|
||||
0x0, // 0x74
|
||||
0x10123a9f, // 0x78 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x04, // 0x7C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE1A04000, // 0x80 value: MOV R4, R0
|
||||
0x0, // 0x84
|
||||
0x10123a8b, // 0x88 POP {R3,R4,PC}
|
||||
0x1, // 0x8C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x90
|
||||
0x1010CD18, // 0x94 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x98
|
||||
0x0, // 0x9C
|
||||
0x1012EE64, // 0xA0 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0xA4
|
||||
0x0, // 0xA8
|
||||
0x10123a9f, // 0xAC POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x08, // 0xB0 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE3E00000, // 0xB4 value: MOV R0, #0xFFFFFFFF
|
||||
0x0, // 0xB8
|
||||
0x10123a8b, // 0xBC POP {R3,R4,PC}
|
||||
0x1, // 0xC0 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0xC4
|
||||
0x1010CD18, // 0xC8 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0xCC
|
||||
0x0, // 0xD0
|
||||
0x1012EE64, // 0xD4 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0xD8
|
||||
0x0, // 0xDC
|
||||
0x10123a9f, // 0xE0 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x0C, // 0xE4 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xEE030F10, // 0xE8 value: MCR P15, #0, R0, C3, C0, #0 (set dacr to R0)
|
||||
0x0, // 0xEC
|
||||
0x10123a8b, // 0xF0 POP {R3,R4,PC}
|
||||
0x1, // 0xF4 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0xF8
|
||||
0x1010CD18, // 0xFC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x100
|
||||
0x0, // 0x104
|
||||
0x1012EE64, // 0x108 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x10C
|
||||
0x0, // 0x110
|
||||
0x10123a9f, // 0x114 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x10, // 0x118 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE1A00004, // 0x11C value: MOV R0, R4
|
||||
0x0, // 0x120
|
||||
0x10123a8b, // 0x124 POP {R3,R4,PC}
|
||||
0x1, // 0x128 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x12C
|
||||
0x1010CD18, // 0x130 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x134
|
||||
0x0, // 0x138
|
||||
0x1012EE64, // 0x13C set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x140
|
||||
0x0, // 0x144
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x14, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE12FFF33, // 0x150 value: BLX R3 KERNEL_MEMCPY
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x18, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0x00000000, // 0x150 value: NOP
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x1C, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xEE17FF7A, // 0x150 value: clean_loop: MRC p15, 0, r15, c7, c10, 3
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x20, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0x1AFFFFFD, // 0x150 value: BNE clean_loop
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x24, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xEE070F9A, // 0x150 value: MCR p15, 0, R0, c7, c10, 4
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x17C POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x28, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE1A03004, // 0x184 value: MOV R3, R4
|
||||
0x0, // 0x188
|
||||
0x10123a8b, // 0x18C POP {R3,R4,PC}
|
||||
0x1, // 0x190 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x194
|
||||
0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x19C
|
||||
0x0, // 0x1A0
|
||||
0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x1A8
|
||||
0x0, // 0x1AC
|
||||
0x10123a9f, // 0x17C POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x2C, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE8BD4010, // 0x184 value: POP {R4,LR}
|
||||
0x0, // 0x188
|
||||
0x10123a8b, // 0x18C POP {R3,R4,PC}
|
||||
0x1, // 0x190 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x194
|
||||
0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x19C
|
||||
0x0, // 0x1A0
|
||||
0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x1A8
|
||||
0x0, // 0x1AC
|
||||
0x10123a9f, // 0x1B0 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x30, // 0x1B4 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE12FFF13, // 0x1B8 value: BX R3 our code :-)
|
||||
0x0, // 0x1BC
|
||||
0x10123a8b, // 0x1C0 POP {R3,R4,PC}
|
||||
0x1, // 0x1C4 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x1C8
|
||||
0x1010CD18, // 0x1CC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x1D0
|
||||
0x0, // 0x1D4
|
||||
0x1012EE64, // 0x1D8 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x1DC
|
||||
0x0, // 0x1E0
|
||||
0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL, // 0x1DC start of syscall IOS_GetUpTime64
|
||||
0x4001, // 0x1E0 on > 0x4000 it flushes all data caches
|
||||
0x0, // 0x1E0
|
||||
0x1012ED4C, // 0x1E4 IOS_FlushDCache(void *ptr, unsigned int len)
|
||||
0x0, // 0x1DC
|
||||
0x0, // 0x1E0
|
||||
0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC}
|
||||
ARM_CODE_BASE, // 0x1E8 our code destination address
|
||||
0x0, // 0x1EC
|
||||
0x0, // 0x1F0
|
||||
0x101063db, // 0x1F4 POP {R1,R2,R5,PC}
|
||||
0x0, // 0x1F8
|
||||
sizeof(ios_kernel_bin), // 0x1FC our code size
|
||||
0x0, // 0x200
|
||||
0x10123983, // 0x204 POP {R1,R3,R4,R6,PC}
|
||||
0x00140000, // 0x208 our code source location
|
||||
0x08131D04, // 0x20C KERNEL_MEMCPY address
|
||||
0x0, // 0x210
|
||||
0x0, // 0x214
|
||||
0x1012EBB4, // 0x218 IOS_GetUpTime64 (privileged stack pivot)
|
||||
0x0,
|
||||
0x0,
|
||||
0x101312D0,
|
||||
0x101236f3, // 0x00 POP {R1-R7,PC}
|
||||
0x0, // 0x04 arg
|
||||
0x0812974C, // 0x08 stackptr CMP R3, #1; STREQ R1, [R12]; BX LR
|
||||
0x68, // 0x0C stacksize
|
||||
0x10101638, // 0x10
|
||||
0x0, // 0x14
|
||||
0x0, // 0x18
|
||||
0x0, // 0x1C
|
||||
0x1010388C, // 0x20 CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x24
|
||||
0x0, // 0x28
|
||||
0x1012CFEC, // 0x2C MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x30
|
||||
0x0, // 0x34
|
||||
IOS_CREATETHREAD, // 0x38
|
||||
0x1, // 0x3C
|
||||
0x2, // 0x40
|
||||
0x10123a9f, // 0x44 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x00, // 0x48 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE92D4010, // 0x4C value: PUSH {R4,LR}
|
||||
0x0, // 0x50
|
||||
0x10123a8b, // 0x54 POP {R3,R4,PC}
|
||||
0x1, // 0x58 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x5C
|
||||
0x1010CD18, // 0x60 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x64
|
||||
0x0, // 0x68
|
||||
0x1012EE64, // 0x6C set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x70
|
||||
0x0, // 0x74
|
||||
0x10123a9f, // 0x78 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x04, // 0x7C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE1A04000, // 0x80 value: MOV R4, R0
|
||||
0x0, // 0x84
|
||||
0x10123a8b, // 0x88 POP {R3,R4,PC}
|
||||
0x1, // 0x8C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x90
|
||||
0x1010CD18, // 0x94 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x98
|
||||
0x0, // 0x9C
|
||||
0x1012EE64, // 0xA0 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0xA4
|
||||
0x0, // 0xA8
|
||||
0x10123a9f, // 0xAC POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x08, // 0xB0 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE3E00000, // 0xB4 value: MOV R0, #0xFFFFFFFF
|
||||
0x0, // 0xB8
|
||||
0x10123a8b, // 0xBC POP {R3,R4,PC}
|
||||
0x1, // 0xC0 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0xC4
|
||||
0x1010CD18, // 0xC8 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0xCC
|
||||
0x0, // 0xD0
|
||||
0x1012EE64, // 0xD4 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0xD8
|
||||
0x0, // 0xDC
|
||||
0x10123a9f, // 0xE0 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x0C, // 0xE4 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xEE030F10, // 0xE8 value: MCR P15, #0, R0, C3, C0, #0 (set dacr to R0)
|
||||
0x0, // 0xEC
|
||||
0x10123a8b, // 0xF0 POP {R3,R4,PC}
|
||||
0x1, // 0xF4 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0xF8
|
||||
0x1010CD18, // 0xFC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x100
|
||||
0x0, // 0x104
|
||||
0x1012EE64, // 0x108 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x10C
|
||||
0x0, // 0x110
|
||||
0x10123a9f, // 0x114 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x10, // 0x118 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE1A00004, // 0x11C value: MOV R0, R4
|
||||
0x0, // 0x120
|
||||
0x10123a8b, // 0x124 POP {R3,R4,PC}
|
||||
0x1, // 0x128 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x12C
|
||||
0x1010CD18, // 0x130 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x134
|
||||
0x0, // 0x138
|
||||
0x1012EE64, // 0x13C set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x140
|
||||
0x0, // 0x144
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x14, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE12FFF33, // 0x150 value: BLX R3 KERNEL_MEMCPY
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x18, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0x00000000, // 0x150 value: NOP
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x1C, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xEE17FF7A, // 0x150 value: clean_loop: MRC p15, 0, r15, c7, c10, 3
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x20, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0x1AFFFFFD, // 0x150 value: BNE clean_loop
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x24, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xEE070F9A, // 0x150 value: MCR p15, 0, R0, c7, c10, 4
|
||||
0x0, // 0x154
|
||||
0x10123a8b, // 0x158 POP {R3,R4,PC}
|
||||
0x1, // 0x15C R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x160
|
||||
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x168
|
||||
0x0, // 0x16C
|
||||
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x174
|
||||
0x0, // 0x178
|
||||
0x10123a9f, // 0x17C POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x28, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE1A03004, // 0x184 value: MOV R3, R4
|
||||
0x0, // 0x188
|
||||
0x10123a8b, // 0x18C POP {R3,R4,PC}
|
||||
0x1, // 0x190 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x194
|
||||
0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x19C
|
||||
0x0, // 0x1A0
|
||||
0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x1A8
|
||||
0x0, // 0x1AC
|
||||
0x10123a9f, // 0x17C POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x2C, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE8BD4010, // 0x184 value: POP {R4,LR}
|
||||
0x0, // 0x188
|
||||
0x10123a8b, // 0x18C POP {R3,R4,PC}
|
||||
0x1, // 0x190 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x194
|
||||
0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x19C
|
||||
0x0, // 0x1A0
|
||||
0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x1A8
|
||||
0x0, // 0x1AC
|
||||
0x10123a9f, // 0x1B0 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL + 0x30, // 0x1B4 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
|
||||
0xE12FFF13, // 0x1B8 value: BX R3 our code :-)
|
||||
0x0, // 0x1BC
|
||||
0x10123a8b, // 0x1C0 POP {R3,R4,PC}
|
||||
0x1, // 0x1C4 R3 must be 1 for the arbitrary write
|
||||
0x0, // 0x1C8
|
||||
0x1010CD18, // 0x1CC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x1D0
|
||||
0x0, // 0x1D4
|
||||
0x1012EE64, // 0x1D8 set_panic_behavior (arbitrary write)
|
||||
0x0, // 0x1DC
|
||||
0x0, // 0x1E0
|
||||
0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC}
|
||||
REPLACE_SYSCALL, // 0x1DC start of syscall IOS_GetUpTime64
|
||||
0x4001, // 0x1E0 on > 0x4000 it flushes all data caches
|
||||
0x0, // 0x1E0
|
||||
0x1012ED4C, // 0x1E4 IOS_FlushDCache(void *ptr, unsigned int len)
|
||||
0x0, // 0x1DC
|
||||
0x0, // 0x1E0
|
||||
0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC}
|
||||
ARM_CODE_BASE, // 0x1E8 our code destination address
|
||||
0x0, // 0x1EC
|
||||
0x0, // 0x1F0
|
||||
0x101063db, // 0x1F4 POP {R1,R2,R5,PC}
|
||||
0x0, // 0x1F8
|
||||
sizeof(ios_kernel_bin), // 0x1FC our code size
|
||||
0x0, // 0x200
|
||||
0x10123983, // 0x204 POP {R1,R3,R4,R6,PC}
|
||||
0x00140000, // 0x208 our code source location
|
||||
0x08131D04, // 0x20C KERNEL_MEMCPY address
|
||||
0x0, // 0x210
|
||||
0x0, // 0x214
|
||||
0x1012EBB4, // 0x218 IOS_GetUpTime64 (privileged stack pivot)
|
||||
0x0,
|
||||
0x0,
|
||||
0x101312D0,
|
||||
};
|
||||
|
||||
static const int second_chain[] = {
|
||||
0x10123a9f, // 0x00 POP {R0,R1,R4,PC}
|
||||
CHAIN_START + 0x14 + 0x4 + 0x20 - 0xF000, // 0x04 destination
|
||||
0x0, // 0x08
|
||||
0x0, // 0x0C
|
||||
0x101063db, // 0x10 POP {R1,R2,R5,PC}
|
||||
0x00130000, // 0x14 source
|
||||
sizeof(final_chain), // 0x18 length
|
||||
0x0, // 0x1C
|
||||
0x10106D4C, // 0x20 BL MEMCPY; MOV R0, #0; LDMFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x24
|
||||
0x0, // 0x28
|
||||
0x101236f3, // 0x2C POP {R1-R7,PC}
|
||||
0x0, // 0x30 arg
|
||||
0x101001DC, // 0x34 stackptr
|
||||
0x68, // 0x38 stacksize
|
||||
0x10101634, // 0x3C proc: ADD SP, SP, #8; LDMFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x40
|
||||
0x0, // 0x44
|
||||
0x0, // 0x48
|
||||
0x1010388C, // 0x4C CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x50
|
||||
0x0, // 0x54
|
||||
0x1012CFEC, // 0x58 MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x5C
|
||||
0x0, // 0x60
|
||||
IOS_CREATETHREAD, // 0x64
|
||||
0x1, // 0x68 priority
|
||||
0x2, // 0x6C flags
|
||||
0x0, // 0x70
|
||||
0x0, // 0x74
|
||||
0x101063db, // 0x78 POP {R1,R2,R5,PC}
|
||||
0x0, // 0x7C
|
||||
-(0x240 + 0x18 + 0xF000), // 0x80 stack offset
|
||||
0x0, // 0x84
|
||||
0x101141C0, // 0x88 MOV R0, R9; ADD SP, SP, #0xC; LDMFD SP!, {R4-R11,PC}
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x00110000 - 0x44, // 0x8C
|
||||
0x00110010, // 0x90
|
||||
0x0, // 0x94
|
||||
0x0, // 0x98
|
||||
0x0, // 0x9C
|
||||
0x0, // 0xA0
|
||||
0x0, // 0xA4
|
||||
0x4, // 0xA8 R11 must equal 4 in order to pivot the stack
|
||||
0x101088F4, // STR R0, [R4,#0x44]; MOVEQ R0, R5; STRNE R3, [R5]; LDMFD SP!, {R4,R5,PC}
|
||||
0x0,
|
||||
0x0,
|
||||
0x1012EA68, // 0xAC stack pivot
|
||||
0x10123a9f, // 0x00 POP {R0,R1,R4,PC}
|
||||
CHAIN_START + 0x14 + 0x4 + 0x20 - 0xF000, // 0x04 destination
|
||||
0x0, // 0x08
|
||||
0x0, // 0x0C
|
||||
0x101063db, // 0x10 POP {R1,R2,R5,PC}
|
||||
0x00130000, // 0x14 source
|
||||
sizeof(final_chain), // 0x18 length
|
||||
0x0, // 0x1C
|
||||
0x10106D4C, // 0x20 BL MEMCPY; MOV R0, #0; LDMFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x24
|
||||
0x0, // 0x28
|
||||
0x101236f3, // 0x2C POP {R1-R7,PC}
|
||||
0x0, // 0x30 arg
|
||||
0x101001DC, // 0x34 stackptr
|
||||
0x68, // 0x38 stacksize
|
||||
0x10101634, // 0x3C proc: ADD SP, SP, #8; LDMFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x40
|
||||
0x0, // 0x44
|
||||
0x0, // 0x48
|
||||
0x1010388C, // 0x4C CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC}
|
||||
0x0, // 0x50
|
||||
0x0, // 0x54
|
||||
0x1012CFEC, // 0x58 MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC}
|
||||
0x0, // 0x5C
|
||||
0x0, // 0x60
|
||||
IOS_CREATETHREAD, // 0x64
|
||||
0x1, // 0x68 priority
|
||||
0x2, // 0x6C flags
|
||||
0x0, // 0x70
|
||||
0x0, // 0x74
|
||||
0x101063db, // 0x78 POP {R1,R2,R5,PC}
|
||||
0x0, // 0x7C
|
||||
-(0x240 + 0x18 + 0xF000), // 0x80 stack offset
|
||||
0x0, // 0x84
|
||||
0x101141C0, // 0x88 MOV R0, R9; ADD SP, SP, #0xC; LDMFD SP!, {R4-R11,PC}
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x00110000 - 0x44, // 0x8C
|
||||
0x00110010, // 0x90
|
||||
0x0, // 0x94
|
||||
0x0, // 0x98
|
||||
0x0, // 0x9C
|
||||
0x0, // 0xA0
|
||||
0x0, // 0xA4
|
||||
0x4, // 0xA8 R11 must equal 4 in order to pivot the stack
|
||||
0x101088F4, // STR R0, [R4,#0x44]; MOVEQ R0, R5; STRNE R3, [R5]; LDMFD SP!, {R4,R5,PC}
|
||||
0x0,
|
||||
0x0,
|
||||
0x1012EA68, // 0xAC stack pivot
|
||||
};
|
||||
|
||||
static void uhs_exploit_init(int dev_uhs_0_handle, cfw_config_t * config)
|
||||
{
|
||||
static void uhs_exploit_init(int dev_uhs_0_handle, cfw_config_t * config) {
|
||||
ayylmao[5] = 1;
|
||||
ayylmao[8] = 0x500000;
|
||||
|
||||
@ -375,20 +373,19 @@ static void uhs_exploit_init(int dev_uhs_0_handle, cfw_config_t * config)
|
||||
DCStoreRange((void*)0xF4148000, ((u32)payloads) - 0xF4148000);
|
||||
}
|
||||
|
||||
static int uhs_write32(int dev_uhs_0_handle, int arm_addr, int val)
|
||||
{
|
||||
ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes
|
||||
DCStoreRange(ayylmao, 521 * 4); //! Make CPU fetch new data (with updated adress)
|
||||
OSSleepTicks(0x200000); //! Improves stability
|
||||
int request_buffer[] = { -(0xBEA2C), val }; //! -(0xBEA2C) gets IOS_USB to read from the middle of MEM1
|
||||
int output_buffer[32];
|
||||
return IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer));
|
||||
static int uhs_write32(int dev_uhs_0_handle, int arm_addr, int val) {
|
||||
ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes
|
||||
DCStoreRange(ayylmao, 521 * 4); //! Make CPU fetch new data (with updated adress)
|
||||
OSSleepTicks(0x200000); //! Improves stability
|
||||
int request_buffer[] = { -(0xBEA2C), val }; //! -(0xBEA2C) gets IOS_USB to read from the middle of MEM1
|
||||
int output_buffer[32];
|
||||
return IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer));
|
||||
}
|
||||
|
||||
int ExecuteIOSExploit(cfw_config_t * config){
|
||||
int ExecuteIOSExploit(cfw_config_t * config) {
|
||||
DEBUG_FUNCTION_LINE("Running ExecuteIOSExploit\n");
|
||||
int iosuhaxFd = IOS_Open("/dev/iosuhax", 0);
|
||||
if(iosuhaxFd >= 0){
|
||||
if(iosuhaxFd >= 0) {
|
||||
int dummy = 0;
|
||||
|
||||
IOS_Ioctl(iosuhaxFd, 0x03, &dummy, sizeof(dummy), &dummy, sizeof(dummy));
|
||||
@ -401,7 +398,7 @@ int ExecuteIOSExploit(cfw_config_t * config){
|
||||
|
||||
//! execute exploit
|
||||
int dev_uhs_0_handle = IOS_Open("/dev/uhs/0", 0);
|
||||
if(dev_uhs_0_handle < 0){
|
||||
if(dev_uhs_0_handle < 0) {
|
||||
DEBUG_FUNCTION_LINE("Failed to open \"/dev/uhs/0\"\n");
|
||||
return dev_uhs_0_handle;
|
||||
}
|
||||
@ -418,7 +415,7 @@ int ExecuteIOSExploit(cfw_config_t * config){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExecuteIOSExploitWithDefaultConfig(){
|
||||
void ExecuteIOSExploitWithDefaultConfig() {
|
||||
cfw_config_t config;
|
||||
config.viewMode = 0;
|
||||
config.directLaunch = 0;
|
||||
|
@ -7,7 +7,7 @@ extern "C" {
|
||||
|
||||
#include <wups.h>
|
||||
|
||||
struct buffer_store{
|
||||
struct buffer_store {
|
||||
void * buffer;
|
||||
s32 buffer_size;
|
||||
s32 mode;
|
||||
|
@ -21,33 +21,33 @@
|
||||
#include <wups.h>
|
||||
#include <string>
|
||||
|
||||
class FunctionData{
|
||||
class FunctionData {
|
||||
|
||||
public:
|
||||
FunctionData(const char * name, wups_loader_library_type_t library, void * target, void * call_addr){
|
||||
FunctionData(const char * name, wups_loader_library_type_t library, void * target, void * call_addr) {
|
||||
this->name = name;
|
||||
this->library = library;
|
||||
this->replaceAddr = target;
|
||||
this->replaceCall = call_addr;
|
||||
}
|
||||
|
||||
~FunctionData(){
|
||||
~FunctionData() {
|
||||
|
||||
}
|
||||
|
||||
std::string getName(){
|
||||
std::string getName() {
|
||||
return this->name;
|
||||
}
|
||||
|
||||
wups_loader_library_type_t getLibrary(){
|
||||
wups_loader_library_type_t getLibrary() {
|
||||
return this->library;
|
||||
}
|
||||
|
||||
void * getReplaceAddress(){
|
||||
void * getReplaceAddress() {
|
||||
return replaceAddr;
|
||||
}
|
||||
|
||||
void * getReplaceCall(){
|
||||
void * getReplaceCall() {
|
||||
return replaceCall;
|
||||
}
|
||||
|
||||
|
@ -397,7 +397,7 @@ void PluginLoader::copyPluginDataIntoGlobalStruct(std::vector<PluginData *> plug
|
||||
replacement_data_function_t * function_data = &plugin_data->functions[j];
|
||||
FunctionData * cur_function = function_data_list[j];
|
||||
|
||||
if(strlen(cur_function->getName().c_str()) > MAXIMUM_FUNCTION_NAME_LENGTH-1){
|
||||
if(strlen(cur_function->getName().c_str()) > MAXIMUM_FUNCTION_NAME_LENGTH-1) {
|
||||
DEBUG_FUNCTION_LINE("Couldn not add function \"%s\" for plugin \"%s\" function name is too long.\n",cur_function->getName().c_str(),plugin_data->plugin_name);
|
||||
continue;
|
||||
}
|
||||
|
@ -7,91 +7,91 @@
|
||||
#include <dirent.h>
|
||||
#include <wups.h>
|
||||
|
||||
static void * new_open_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_close_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_write_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_read_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_lseek_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_stat_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_fstat_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_opendir_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_closedir_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_readdir_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_mkdir_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_open_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_close_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_write_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_read_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_lseek_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_stat_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_fstat_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_opendir_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_closedir_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_readdir_ptr __attribute__((section(".data"))) = NULL;
|
||||
static void * new_mkdir_ptr __attribute__((section(".data"))) = NULL;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void WUPS_InitFS(wups_loader_init_fs_args_t args){
|
||||
new_open_ptr = (void*) args.open_repl;
|
||||
new_close_ptr = (void*) args.close_repl;
|
||||
new_write_ptr = (void*) args.write_repl;
|
||||
new_read_ptr = (void*) args.read_repl;
|
||||
new_lseek_ptr = (void*) args.lseek_repl;
|
||||
new_stat_ptr = (void*) args.stat_repl;
|
||||
new_fstat_ptr = (void*) args.fstat_repl;
|
||||
new_opendir_ptr = (void*) args.opendir_repl;
|
||||
new_closedir_ptr = (void*) args.closedir_repl;
|
||||
new_readdir_ptr = (void*) args.readdir_repl;
|
||||
new_mkdir_ptr = (void*) args.mkdir_repl;
|
||||
}
|
||||
extern "C" {
|
||||
#endif
|
||||
void WUPS_InitFS(wups_loader_init_fs_args_t args) {
|
||||
new_open_ptr = (void*) args.open_repl;
|
||||
new_close_ptr = (void*) args.close_repl;
|
||||
new_write_ptr = (void*) args.write_repl;
|
||||
new_read_ptr = (void*) args.read_repl;
|
||||
new_lseek_ptr = (void*) args.lseek_repl;
|
||||
new_stat_ptr = (void*) args.stat_repl;
|
||||
new_fstat_ptr = (void*) args.fstat_repl;
|
||||
new_opendir_ptr = (void*) args.opendir_repl;
|
||||
new_closedir_ptr = (void*) args.closedir_repl;
|
||||
new_readdir_ptr = (void*) args.readdir_repl;
|
||||
new_mkdir_ptr = (void*) args.mkdir_repl;
|
||||
}
|
||||
|
||||
int __real_open(const char *pathname, int flags);
|
||||
int __wrap_open(const char *pathname, int flags) {
|
||||
if(new_open_ptr == NULL) return __real_open(pathname,flags);
|
||||
return ( (int (*)(const char *,int))((unsigned int*)new_open_ptr) )(pathname,flags);
|
||||
}
|
||||
int __real_close(int fd);
|
||||
int __wrap_close(int fd) {
|
||||
if(new_close_ptr == NULL) return __real_close(fd);
|
||||
return ( (int (*)(int))((unsigned int*)new_close_ptr) )(fd);
|
||||
}
|
||||
ssize_t __real_write(int fd, const void *buf, size_t count);
|
||||
ssize_t __wrap_write(int fd, const void *buf, size_t count) {
|
||||
if(new_write_ptr == NULL) return __real_write(fd,buf,count);
|
||||
return ( (ssize_t (*)(int, const void *, size_t))((unsigned int*)new_write_ptr) )(fd,buf,count);
|
||||
}
|
||||
ssize_t __real_read(int fd, const void *buf, size_t count);
|
||||
ssize_t __wrap_read(int fd, const void *buf, size_t count) {
|
||||
if(new_read_ptr == NULL) return __real_read(fd,buf,count);
|
||||
return ( (ssize_t (*)(int, const void *, size_t))((unsigned int*)new_read_ptr) )(fd,buf,count);
|
||||
}
|
||||
off_t __real_lseek(int fd, off_t offset, int whence);
|
||||
off_t __wrap_lseek(int fd, off_t offset, int whence) {
|
||||
if(new_lseek_ptr == NULL) return __real_lseek(fd, offset, whence);
|
||||
return ( (off_t (*)(int, off_t, int))((unsigned int*)new_lseek_ptr) )(fd, offset, whence);
|
||||
}
|
||||
int __real_stat(const char *pathname, struct stat *statbuf);
|
||||
int __wrap_stat(const char *pathname, struct stat *statbuf) {
|
||||
if(new_stat_ptr == NULL) return __real_stat(pathname,statbuf);
|
||||
return ( (int (*)(const char *, struct stat *))((unsigned int*)new_stat_ptr) )(pathname,statbuf);
|
||||
}
|
||||
int __real_fstat(int fd, struct stat *statbuf);
|
||||
int __wrap_fstat(int fd, struct stat *statbuf) {
|
||||
if(new_fstat_ptr == NULL) return __real_fstat(fd,statbuf);
|
||||
return ( (int (*)(int, struct stat *))((unsigned int*)new_fstat_ptr) )(fd,statbuf);
|
||||
}
|
||||
DIR* __real_opendir(const char * arg);
|
||||
DIR* __wrap_opendir(const char * arg) {
|
||||
if(new_opendir_ptr == NULL) return __real_opendir(arg);
|
||||
return ( (DIR* (*)(const char *))((unsigned int*)new_opendir_ptr) )(arg);
|
||||
}
|
||||
int __real_closedir(DIR *dirp);
|
||||
int __wrap_closedir(DIR *dirp) {
|
||||
if(new_closedir_ptr == NULL) return __real_closedir(dirp);
|
||||
return ( (int (*)(DIR *))((unsigned int*)new_closedir_ptr) )(dirp);
|
||||
}
|
||||
struct dirent * __real_readdir(DIR *dirp);
|
||||
struct dirent * __wrap_readdir(DIR *dirp) {
|
||||
if(new_readdir_ptr == NULL) return __real_readdir(dirp);
|
||||
return ( (struct dirent * (*)(DIR *))((unsigned int*)new_readdir_ptr) )(dirp);
|
||||
}
|
||||
int __real_mkdir(const char *path, mode_t mode);
|
||||
int __wrap_mkdir(const char *path, mode_t mode) {
|
||||
if(new_mkdir_ptr == NULL) return __real_mkdir(path, mode);
|
||||
return ( (int (*)(const char *, mode_t))((unsigned int*) new_mkdir_ptr) )(path, mode);
|
||||
}
|
||||
|
||||
int __real_open(const char *pathname, int flags);
|
||||
int __wrap_open(const char *pathname, int flags){
|
||||
if(new_open_ptr == NULL) return __real_open(pathname,flags);
|
||||
return ( (int (*)(const char *,int))((unsigned int*)new_open_ptr) )(pathname,flags);
|
||||
}
|
||||
int __real_close(int fd);
|
||||
int __wrap_close(int fd){
|
||||
if(new_close_ptr == NULL) return __real_close(fd);
|
||||
return ( (int (*)(int))((unsigned int*)new_close_ptr) )(fd);
|
||||
}
|
||||
ssize_t __real_write(int fd, const void *buf, size_t count);
|
||||
ssize_t __wrap_write(int fd, const void *buf, size_t count){
|
||||
if(new_write_ptr == NULL) return __real_write(fd,buf,count);
|
||||
return ( (ssize_t (*)(int, const void *, size_t))((unsigned int*)new_write_ptr) )(fd,buf,count);
|
||||
}
|
||||
ssize_t __real_read(int fd, const void *buf, size_t count);
|
||||
ssize_t __wrap_read(int fd, const void *buf, size_t count){
|
||||
if(new_read_ptr == NULL) return __real_read(fd,buf,count);
|
||||
return ( (ssize_t (*)(int, const void *, size_t))((unsigned int*)new_read_ptr) )(fd,buf,count);
|
||||
}
|
||||
off_t __real_lseek(int fd, off_t offset, int whence);
|
||||
off_t __wrap_lseek(int fd, off_t offset, int whence){
|
||||
if(new_lseek_ptr == NULL) return __real_lseek(fd, offset, whence);
|
||||
return ( (off_t (*)(int, off_t, int))((unsigned int*)new_lseek_ptr) )(fd, offset, whence);
|
||||
}
|
||||
int __real_stat(const char *pathname, struct stat *statbuf);
|
||||
int __wrap_stat(const char *pathname, struct stat *statbuf){
|
||||
if(new_stat_ptr == NULL) return __real_stat(pathname,statbuf);
|
||||
return ( (int (*)(const char *, struct stat *))((unsigned int*)new_stat_ptr) )(pathname,statbuf);
|
||||
}
|
||||
int __real_fstat(int fd, struct stat *statbuf);
|
||||
int __wrap_fstat(int fd, struct stat *statbuf){
|
||||
if(new_fstat_ptr == NULL) return __real_fstat(fd,statbuf);
|
||||
return ( (int (*)(int, struct stat *))((unsigned int*)new_fstat_ptr) )(fd,statbuf);
|
||||
}
|
||||
DIR* __real_opendir(const char * arg);
|
||||
DIR* __wrap_opendir(const char * arg){
|
||||
if(new_opendir_ptr == NULL) return __real_opendir(arg);
|
||||
return ( (DIR* (*)(const char *))((unsigned int*)new_opendir_ptr) )(arg);
|
||||
}
|
||||
int __real_closedir(DIR *dirp);
|
||||
int __wrap_closedir(DIR *dirp){
|
||||
if(new_closedir_ptr == NULL) return __real_closedir(dirp);
|
||||
return ( (int (*)(DIR *))((unsigned int*)new_closedir_ptr) )(dirp);
|
||||
}
|
||||
struct dirent * __real_readdir(DIR *dirp);
|
||||
struct dirent * __wrap_readdir(DIR *dirp){
|
||||
if(new_readdir_ptr == NULL) return __real_readdir(dirp);
|
||||
return ( (struct dirent * (*)(DIR *))((unsigned int*)new_readdir_ptr) )(dirp);
|
||||
}
|
||||
int __real_mkdir(const char *path, mode_t mode);
|
||||
int __wrap_mkdir(const char *path, mode_t mode){
|
||||
if(new_mkdir_ptr == NULL) return __real_mkdir(path, mode);
|
||||
return ( (int (*)(const char *, mode_t))((unsigned int*) new_mkdir_ptr) )(path, mode);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
110
src/overlay.c
110
src/overlay.c
@ -15,61 +15,67 @@
|
||||
static void * overlayfunction_ptr __attribute__((section(".data"))) = NULL;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void WUPS_InitOverlay(wups_loader_init_overlay_args_t args){
|
||||
InitOSFunctionPointers();
|
||||
overlayfunction_ptr = (void*) args.overlayfunction_ptr;
|
||||
}
|
||||
|
||||
void WUPS_Overlay_PrintTextOnScreen(wups_overlay_options_type_t screen, int x,int y, const char * msg, ...){
|
||||
if(screen == WUPS_OVERLAY_NONE){ return; }
|
||||
|
||||
char * tmp = NULL;
|
||||
extern "C" {
|
||||
#endif
|
||||
void WUPS_InitOverlay(wups_loader_init_overlay_args_t args) {
|
||||
InitOSFunctionPointers();
|
||||
overlayfunction_ptr = (void*) args.overlayfunction_ptr;
|
||||
}
|
||||
|
||||
va_list va;
|
||||
va_start(va, msg);
|
||||
if((vasprintf(&tmp, msg, va) >= 0) && tmp){
|
||||
if(screen != WUPS_OVERLAY_DRC_ONLY){ // Draw TV if it's not DRC exclusive.
|
||||
OSScreenPutFontEx(0, x, y, tmp);
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_TV_ONLY){ // Draw DRC if it's not TV exclusive.
|
||||
OSScreenPutFontEx(1, x, y, tmp);
|
||||
}
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
if(tmp){
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void WUPS_Overlay_OSScreenClear(wups_overlay_options_type_t screen){
|
||||
if(screen == WUPS_OVERLAY_NONE){ return; }
|
||||
if(screen != WUPS_OVERLAY_DRC_ONLY){ // Clear TV if it's not DRC exclusive.
|
||||
OSScreenClearBufferEx(0, 0);
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_TV_ONLY){ // Clear DRC if it's not TV exclusive.
|
||||
OSScreenClearBufferEx(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void WUPS_Overlay_FlipBuffers(wups_overlay_options_type_t screen){
|
||||
if(screen == WUPS_OVERLAY_NONE){ return; }
|
||||
if(screen != WUPS_OVERLAY_DRC_ONLY){ // Flip TV buffer if it's not DRC exclusive.
|
||||
OSScreenFlipBuffersEx(0);
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_TV_ONLY){ // Flip DRC buffer if it's not TV exclusive.
|
||||
OSScreenFlipBuffersEx(1);
|
||||
}
|
||||
void WUPS_Overlay_PrintTextOnScreen(wups_overlay_options_type_t screen, int x,int y, const char * msg, ...) {
|
||||
if(screen == WUPS_OVERLAY_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
void WUPS_OpenOverlay(wups_overlay_options_type_t screen, overlay_callback callback){
|
||||
if(overlayfunction_ptr != NULL){
|
||||
( (void (*)(wups_overlay_options_type_t, overlay_callback))((unsigned int*)overlayfunction_ptr) )(screen,callback);
|
||||
char * tmp = NULL;
|
||||
|
||||
va_list va;
|
||||
va_start(va, msg);
|
||||
if((vasprintf(&tmp, msg, va) >= 0) && tmp) {
|
||||
if(screen != WUPS_OVERLAY_DRC_ONLY) { // Draw TV if it's not DRC exclusive.
|
||||
OSScreenPutFontEx(0, x, y, tmp);
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_TV_ONLY) { // Draw DRC if it's not TV exclusive.
|
||||
OSScreenPutFontEx(1, x, y, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(va);
|
||||
|
||||
if(tmp) {
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void WUPS_Overlay_OSScreenClear(wups_overlay_options_type_t screen) {
|
||||
if(screen == WUPS_OVERLAY_NONE) {
|
||||
return;
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_DRC_ONLY) { // Clear TV if it's not DRC exclusive.
|
||||
OSScreenClearBufferEx(0, 0);
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_TV_ONLY) { // Clear DRC if it's not TV exclusive.
|
||||
OSScreenClearBufferEx(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void WUPS_Overlay_FlipBuffers(wups_overlay_options_type_t screen) {
|
||||
if(screen == WUPS_OVERLAY_NONE) {
|
||||
return;
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_DRC_ONLY) { // Flip TV buffer if it's not DRC exclusive.
|
||||
OSScreenFlipBuffersEx(0);
|
||||
}
|
||||
if(screen != WUPS_OVERLAY_TV_ONLY) { // Flip DRC buffer if it's not TV exclusive.
|
||||
OSScreenFlipBuffersEx(1);
|
||||
}
|
||||
}
|
||||
|
||||
void WUPS_OpenOverlay(wups_overlay_options_type_t screen, overlay_callback callback) {
|
||||
if(overlayfunction_ptr != NULL) {
|
||||
( (void (*)(wups_overlay_options_type_t, overlay_callback))((unsigned int*)overlayfunction_ptr) )(screen,callback);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* based on blsug.h
|
||||
* by Alex Chadwick
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2014, Alex Chadwick
|
||||
* Modified by Maschell, 2018
|
||||
*
|
||||
@ -99,7 +99,8 @@ typedef enum wups_loader_library_type_t {
|
||||
WUPS_LOADER_LIBRARY_VPAD,
|
||||
WUPS_LOADER_LIBRARY_VPADBASE,
|
||||
WUPS_LOADER_LIBRARY_ZLIB125,
|
||||
} wups_loader_library_type_t;
|
||||
}
|
||||
wups_loader_library_type_t;
|
||||
|
||||
typedef enum wups_loader_entry_type_t {
|
||||
WUPS_LOADER_ENTRY_FUNCTION,
|
||||
@ -109,13 +110,13 @@ typedef enum wups_loader_entry_type_t {
|
||||
|
||||
typedef struct wups_loader_entry_t {
|
||||
wups_loader_entry_type_t type;
|
||||
struct {
|
||||
const char *name; /* Name of the function that will be replaced */
|
||||
const wups_loader_library_type_t library; /**/
|
||||
const char *my_function_name; /* Function name of your own, new function (my_XXX) */
|
||||
const void *target; /* Address of our own, new function (my_XXX)*/
|
||||
const void *call_addr; /* Address for calling the real function.(real_XXX) */
|
||||
} _function;
|
||||
struct {
|
||||
const char *name; /* Name of the function that will be replaced */
|
||||
const wups_loader_library_type_t library; /**/
|
||||
const char *my_function_name; /* Function name of your own, new function (my_XXX) */
|
||||
const void *target; /* Address of our own, new function (my_XXX)*/
|
||||
const void *call_addr; /* Address for calling the real function.(real_XXX) */
|
||||
} _function;
|
||||
} wups_loader_entry_t;
|
||||
|
||||
#define WUPS_MUST_REPLACE(x, lib, function_name) WUPS_MUST_REPLACE_EX(real_ ## x, lib, my_ ## x, function_name);
|
||||
@ -133,7 +134,7 @@ typedef struct wups_loader_entry_t {
|
||||
.call_addr = (const void*)&(original_func) \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define DECL_FUNCTION(res, name, ...) \
|
||||
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \
|
||||
res my_ ## name(__VA_ARGS__)
|
||||
@ -142,4 +143,4 @@ typedef struct wups_loader_entry_t {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WUPS_FUNCTION_PATCHING_DEF_H_ */
|
||||
#endif /* WUPS_FUNCTION_PATCHING_DEF_H_ */
|
||||
|
@ -14,7 +14,7 @@
|
||||
* 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 WUPS_HOOKS_DEF_H_
|
||||
#define WUPS_HOOKS_DEF_H_
|
||||
|
||||
@ -31,19 +31,19 @@ extern "C" {
|
||||
.type = type_def, \
|
||||
.target = (const void*)&(original_func) \
|
||||
}
|
||||
|
||||
|
||||
typedef enum wups_loader_hook_type_t {
|
||||
WUPS_LOADER_HOOK_INIT_FS, /* Only for internal usage */
|
||||
WUPS_LOADER_HOOK_INIT_OVERLAY, /* Only for internal usage */
|
||||
|
||||
WUPS_LOADER_HOOK_INIT_OVERLAY, /* Only for internal usage */
|
||||
|
||||
WUPS_LOADER_HOOK_INIT_PLUGIN, /* Called when exiting the plugin loader */
|
||||
WUPS_LOADER_HOOK_DEINIT_PLUGIN, /* Called when re-entering the plugin loader */
|
||||
WUPS_LOADER_HOOK_DEINIT_PLUGIN, /* Called when re-entering the plugin loader */
|
||||
WUPS_LOADER_HOOK_STARTING_APPLICATION, /* Called when an application gets started */
|
||||
WUPS_LOADER_HOOK_FUNCTIONS_PATCHED, /* Called when the functions where patched */
|
||||
WUPS_LOADER_HOOK_ENDING_APPLICATION, /* Called when an application ends */
|
||||
WUPS_LOADER_HOOK_VSYNC, /* Called when an application calls GX2WaitForVsync (most times each frame) */
|
||||
WUPS_LOADER_HOOK_APP_STATUS_CHANGED, /* Called when the app status changes (foreground, background, closing) */
|
||||
|
||||
|
||||
} wups_loader_hook_type_t;
|
||||
|
||||
typedef struct wups_loader_hook_t {
|
||||
@ -57,7 +57,7 @@ typedef enum wups_loader_app_status_t {
|
||||
WUPS_APP_STATUS_CLOSED, /* App is going to be closed */
|
||||
WUPS_APP_STATUS_UNKNOWN, /* Unknown status _should_ never happen.*/
|
||||
} wups_loader_app_status_t;
|
||||
|
||||
|
||||
typedef struct wups_loader_init_overlay_args_t {
|
||||
const void * overlayfunction_ptr;
|
||||
} wups_loader_init_overlay_args_t;
|
||||
@ -78,8 +78,8 @@ typedef struct wups_loader_init_fs_args_t {
|
||||
|
||||
|
||||
typedef struct wups_loader_app_started_args_t {
|
||||
bool sd_mounted;
|
||||
bool usb_mounted;
|
||||
bool sd_mounted;
|
||||
bool usb_mounted;
|
||||
} wups_loader_app_started_args_t;
|
||||
|
||||
|
||||
@ -89,7 +89,7 @@ typedef struct wups_loader_app_started_args_t {
|
||||
void init_fs(wups_loader_init_fs_args_t args){ \
|
||||
WUPS_InitFS(args);\
|
||||
}
|
||||
|
||||
|
||||
#define WUPS_ALLOW_OVERLAY() \
|
||||
void init_overlay(wups_loader_init_overlay_args_t);\
|
||||
WUPS_HOOK_EX(WUPS_LOADER_HOOK_INIT_OVERLAY,init_overlay); \
|
||||
@ -101,17 +101,17 @@ typedef struct wups_loader_app_started_args_t {
|
||||
void init_plugin(void);\
|
||||
WUPS_HOOK_EX(WUPS_LOADER_HOOK_INIT_PLUGIN,init_plugin); \
|
||||
void init_plugin()
|
||||
|
||||
|
||||
#define DEINITIALIZE_PLUGIN() \
|
||||
void deinit_plugin(void);\
|
||||
WUPS_HOOK_EX(WUPS_LOADER_HOOK_DEINIT_PLUGIN,deinit_plugin); \
|
||||
void deinit_plugin()
|
||||
|
||||
|
||||
#define ON_APPLICATION_START(myargs) \
|
||||
void on_app_starting(wups_loader_app_started_args_t);\
|
||||
WUPS_HOOK_EX(WUPS_LOADER_HOOK_STARTING_APPLICATION,on_app_starting); \
|
||||
void on_app_starting(wups_loader_app_started_args_t myargs)
|
||||
|
||||
void on_app_starting(wups_loader_app_started_args_t myargs)
|
||||
|
||||
#define ON_FUNCTIONS_PATCHED() \
|
||||
void on_functions_patched();\
|
||||
WUPS_HOOK_EX(WUPS_LOADER_HOOK_FUNCTIONS_PATCHED,on_functions_patched); \
|
||||
@ -126,7 +126,7 @@ typedef struct wups_loader_app_started_args_t {
|
||||
void on_vsync(void);\
|
||||
WUPS_HOOK_EX(WUPS_LOADER_HOOK_VSYNC,on_vsync); \
|
||||
void on_vsync(void)
|
||||
|
||||
|
||||
#define ON_APP_STATUS_CHANGED(status) \
|
||||
void on_app_status_changed(wups_loader_app_status_t);\
|
||||
WUPS_HOOK_EX(WUPS_LOADER_HOOK_APP_STATUS_CHANGED,on_app_status_changed); \
|
||||
@ -136,4 +136,4 @@ typedef struct wups_loader_app_started_args_t {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WUPS_WUPS_H_ */
|
||||
#endif /* WUPS_WUPS_H_ */
|
||||
|
@ -30,7 +30,8 @@ typedef enum wups_overlay_options_type_t {
|
||||
WUPS_OVERLAY_TV_ONLY, /* Tries to display only on tv screen */
|
||||
WUPS_OVERLAY_DRC_AND_TV, /* Tries to display on both screens. Prioritizes the TV screen if memory is low. */
|
||||
WUPS_OVERLAY_DRC_AND_TV_WITH_DRC_PRIO /* Tries to display on both screens. But if memory is low, prioritize the DRC screen.*/
|
||||
} wups_overlay_options_type_t;
|
||||
}
|
||||
wups_overlay_options_type_t;
|
||||
|
||||
typedef void (*overlay_callback)(wups_overlay_options_type_t);
|
||||
|
||||
@ -55,4 +56,4 @@ void WUPS_OpenOverlay(wups_overlay_options_type_t screen, overlay_callback callb
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WUPS_WUPS_H_ */
|
||||
#endif /* WUPS_WUPS_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user