Using the newest controller_patcher

- Code clean up
- main.c and function_hook.c are now cpp files
- added a splash screen
This commit is contained in:
Maschell 2016-08-03 22:47:09 +02:00
parent 273cd36ba0
commit ebe55f9457
35 changed files with 433 additions and 4336 deletions

3
.gitignore vendored
View File

@ -46,4 +46,5 @@ Network Trash Folder
Temporary Items
.apdisk
/build/*
/build/*
hidtopad.cbp

View File

@ -34,7 +34,6 @@ BUILD_DBG := $(TARGET)_dbg
SOURCES := src \
src/dynamic_libs \
src/controller_patcher \
src/fs \
src/game \
src/kernel \
src/patcher \

View File

@ -1,45 +1,53 @@
#HID to VPAD#
This is a little tool that let you use a hid device instead of the WiiU Gamepad. <br />
Currently its very experimental and result in random crashes at exiting an application or attach/detach a device.<br />
Currently its experimental and result in random crashes at exiting an application or attaching/detaching a device.<br />
It's based on the [controller_patcher](https://github.com/Maschell/controller_patcher) engine.
##Usage##
Start the .elf with the homebrew launcher. The system menu will be loaded and you can use your device. You can attach and detach devices at any time, but maybe it will result in a random crash.
Place the config files into the following folder:
```
sd:/wiiu/controller
```
##Supported devices##
The official GC Adapter, PS3/PS4 Pad, Mouse, Keyboard and a few other devices are currenty supported, check out the controller_patcher repository for the full list(https://github.com/Maschell/controller_patcher), also 99% of the logic is this reposistory.
The official GC Adapter, PS3/PS4 Pad, Mouse, Keyboard have built in support. Other devices can be added when a valid config file in provided.
Check out the [controller_patcher](https://github.com/Maschell/controller_patcher) repository for more details.
You can find deep information for creating own config files, the default mapping, in the [controller patcher wiki](https://github.com/Maschell/controller_patcher/wiki)
#### GC-Adapter: ####
You can plug in the controller in any port, if mutiple pads are connected only one pad is used.<br />
Mapping is the same as gc-to-vpad by FIX94. To quoute him:<br />
"It just works like you would expect for the most part except for Z, holding down Z will switch L to gamepad L, R to gamepad R and start to gamepad minus. This is done for convenience purposes."<br />
Default button mapping:
- [Mouse](https://github.com/Maschell/controller_patcher/wiki/3.-Mouses#default-configuration)
- [Keyboard](https://github.com/Maschell/controller_patcher/wiki/4.-Keyboards#default-configuration)
- [GameCube](https://github.com/Maschell/controller_patcher/wiki/5.a-Controller-%7C-Configurate-the-GameCube-controller#default-button-mapping)
- [Dualshock 3](https://github.com/Maschell/controller_patcher/wiki/5.b-Controller-%7C-Configurate-the-Dualshock-3-controller#default-button-mapping)
- [Dualshock 4](https://github.com/Maschell/controller_patcher/wiki/5.c-Controller-%7C-Configurate-the-Dualshock-4-controller#default-button-mapping)
####Playstation 3/4 pad:####
Works as aspected, button layout is the same as on the gamepad (Circle is A, Cross is B etc.)<br />
Rumble is currently not working.<br />
#FAQ
### I'm getting this annoying screen at the beginning
Just press A to skip it.
####Mouse support:####
Currently mice are supported in two different modes. Pressing F1 on a connected keyboard will change the mode<br />
- Touch mode (Touchscreen emulation) (default)<br />
- Aim mode (Right stick emulation) (Left click is ZR, left click R)<br />
### What about XBOX controller
The Xbox controller are no HID devices. Its not possible to use them with this method.
####Keyboard mapping:####
LStick = WSAD <br />
DPad = Arrowkeys<br />
A = E<br />
B = Q<br />
X = Space<br />
Y(Z) = R<br />
Plus = Enter<br />
Minus = Minus (Numpad)<br />
L = V<br />
R = B<br />
ZL = Shift<br />
ZR = N<br />
### Is my controller supported?
Take a look at this [repo](https://github.com/Maschell/controller_patcher_configs)
####Building####
### Can I really use my Mouse and Keyboard
Yes. Just plug in you mouse and keyboard. The mouse has 2 mode, switch between them with "F1" on the keyboard.
### ???
Do you have an other question? First take a look at:
- the [controller_patcher repo](https://github.com/Maschell/controller_patcher)
- the thread on [gbatemp](http://gbatemp.net/threads/hid-to-vpad.424127/)
- the [wiki](https://github.com/Maschell/controller_patcher/wiki)
If you don't find an anwser, please open an issue.
#Building#
In order to build this application, you need the custom liboGC and portlibs modified/created by dimok. You can find them on the loadiine_gx2 repo (https://github.com/dimok789/loadiine_gx2/releases/tag/v0.2). Simply put the files in your devkit folder and run the Makefile of HID to VPAD.
##Credits##
#Credits#
A big thanks goes out to <b>dimok</b> for creating the HBL, the dynamic libs and every stuff he made. The "environment" of this app is copied from ddd, turned out to be a "hello world" with useful extra stuff.
Also huge thanks to <b>FIX94</b> who initally created his gc-to-vpad. Helped me a lot! Thanks!
And of course big thanks to everyone who has helped me testing! (dimok, dibas, EclipseSin,FunThomas,n1ghty etc.)

View File

@ -2,8 +2,8 @@
<app version="1">
<name>HID to VPAD</name>
<coder>Maschell</coder>
<version>0.2e</version>
<release_date>20160512000000</release_date>
<version>0.9</version>
<release_date>20160803224500</release_date>
<short_description>USB HID to gamepad input</short_description>
<long_description>Emulate Wii U gamepad input using various USB HID devices. </long_description>
</app>

View File

@ -1,67 +0,0 @@
#ifndef FS_DEFS_H
#define FS_DEFS_H
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* FS defines and types */
#define FS_MAX_LOCALPATH_SIZE 511
#define FS_MAX_MOUNTPATH_SIZE 128
#define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE)
#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE
#define FS_STATUS_OK 0
#define FS_RET_UNSUPPORTED_CMD 0x0400
#define FS_RET_NO_ERROR 0x0000
#define FS_RET_ALL_ERROR (unsigned int)(-1)
#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000
/* max length of file/dir name */
#define FS_MAX_ENTNAME_SIZE 256
#define FS_SOURCETYPE_EXTERNAL 0
#define FS_SOURCETYPE_HFIO 1
#define FS_SOURCETYPE_HFIO 1
#define FS_STATUS_OK 0
#define FS_STATUS_EXISTS -5
#define FS_STATUS_STORAGE_FULL -12
#define FS_STATUS_JOURNAL_FULL -13
#define FS_MOUNT_SOURCE_SIZE 0x300
#define FS_CLIENT_SIZE 0x1700
#define FS_CMD_BLOCK_SIZE 0xA80
typedef struct
{
uint32_t flag;
uint32_t permission;
uint32_t owner_id;
uint32_t group_id;
uint32_t size;
uint32_t alloc_size;
uint64_t quota_size;
uint32_t ent_id;
uint64_t ctime;
uint64_t mtime;
uint8_t attributes[48];
} __attribute__((packed)) FSStat;
typedef struct
{
FSStat stat;
char name[FS_MAX_ENTNAME_SIZE];
} FSDirEntry;
#ifdef __cplusplus
}
#endif
#endif /* FS_DEFS_H */

View File

@ -2,7 +2,7 @@
#define __KERNEL_DEFS_H_
#include "types.h"
#include "fs_defs.h"
#include "dynamic_libs/fs_functions.h"
#ifdef __cplusplus
extern "C" {

@ -1 +1 @@
Subproject commit d1f6f4a6744cab1057f81404a9ac7d4efcd27831
Subproject commit 0f6d2945fc65b2939dbede096508bd9e59c8adb9

@ -1 +1 @@
Subproject commit 2524defead2add843056ab234a8cc4364a7af175
Subproject commit 4f6bb467c315e33b01847011a350088de5b1173b

View File

@ -1,182 +0,0 @@
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include "common/fs_defs.h"
#include "dynamic_libs/fs_functions.h"
int MountFS(void *pClient, void *pCmd, char **mount_path)
{
int result = -1;
void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE);
if(!mountSrc)
return -3;
char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE);
if(!mountPath) {
free(mountSrc);
return -4;
}
memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE);
memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE);
// Mount sdcard
if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0)
{
result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
if((result == 0) && mount_path) {
*mount_path = (char*)malloc(strlen(mountPath) + 1);
if(*mount_path)
strcpy(*mount_path, mountPath);
}
}
free(mountPath);
free(mountSrc);
return result;
}
int UmountFS(void *pClient, void *pCmd, const char *mountPath)
{
int result = -1;
result = FSUnmount(pClient, pCmd, mountPath, -1);
return result;
}
int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size)
{
//! always initialze input
*inbuffer = NULL;
if(size)
*size = 0;
int iFd = open(filepath, O_RDONLY);
if (iFd < 0)
return -1;
u32 filesize = lseek(iFd, 0, SEEK_END);
lseek(iFd, 0, SEEK_SET);
u8 *buffer = (u8 *) malloc(filesize);
if (buffer == NULL)
{
close(iFd);
return -2;
}
u32 blocksize = 0x4000;
u32 done = 0;
int readBytes = 0;
while(done < filesize)
{
if(done + blocksize > filesize) {
blocksize = filesize - done;
}
readBytes = read(iFd, buffer + done, blocksize);
if(readBytes <= 0)
break;
done += readBytes;
}
close(iFd);
if (done != filesize)
{
free(buffer);
return -3;
}
*inbuffer = buffer;
//! sign is optional input
if(size)
*size = filesize;
return filesize;
}
int CheckFile(const char * filepath)
{
if(!filepath)
return 0;
struct stat filestat;
char dirnoslash[strlen(filepath)+2];
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
while(dirnoslash[strlen(dirnoslash)-1] == '/')
dirnoslash[strlen(dirnoslash)-1] = '\0';
char * notRoot = strrchr(dirnoslash, '/');
if(!notRoot)
{
strcat(dirnoslash, "/");
}
if (stat(dirnoslash, &filestat) == 0)
return 1;
return 0;
}
int CreateSubfolder(const char * fullpath)
{
if(!fullpath)
return 0;
int result = 0;
char dirnoslash[strlen(fullpath)+1];
strcpy(dirnoslash, fullpath);
int pos = strlen(dirnoslash)-1;
while(dirnoslash[pos] == '/')
{
dirnoslash[pos] = '\0';
pos--;
}
if(CheckFile(dirnoslash))
{
return 1;
}
else
{
char parentpath[strlen(dirnoslash)+2];
strcpy(parentpath, dirnoslash);
char * ptr = strrchr(parentpath, '/');
if(!ptr)
{
//!Device root directory (must be with '/')
strcat(parentpath, "/");
struct stat filestat;
if (stat(parentpath, &filestat) == 0)
return 1;
return 0;
}
ptr++;
ptr[0] = '\0';
result = CreateSubfolder(parentpath);
}
if(!result)
return 0;
if (mkdir(dirnoslash, 0777) == -1)
{
return 0;
}
return 1;
}

View File

@ -1,23 +0,0 @@
#ifndef __FS_UTILS_H_
#define __FS_UTILS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <gctypes.h>
int MountFS(void *pClient, void *pCmd, char **mount_path);
int UmountFS(void *pClient, void *pCmd, const char *mountPath);
int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size);
//! todo: C++ class
int CreateSubfolder(const char * fullpath);
int CheckFile(const char * filepath);
#ifdef __cplusplus
}
#endif
#endif // __FS_UTILS_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +0,0 @@
/***************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef __SD_FAT_DEVOPTAB_H_
#define __SD_FAT_DEVOPTAB_H_
#ifdef __cplusplus
extern "C" {
#endif
int mount_sd_fat(const char *path);
int unmount_sd_fat(const char *path);
#ifdef __cplusplus
}
#endif
#endif // __SD_FAT_DEVOPTAB_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
*
* 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 _MEMORY_AREA_TABLE_H_
#define _MEMORY_AREA_TABLE_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Struct used to organize empty memory areas */
typedef struct _s_mem_area
{
unsigned int address;
unsigned int size;
struct _s_mem_area* next;
} s_mem_area;
void memoryInitAreaTable();
s_mem_area * memoryGetAreaTable(void);
#ifdef __cplusplus
}
#endif
#endif // _MEMORY_AREA_TABLE_H_

View File

@ -1,210 +0,0 @@
#include <string.h>
#include "rpx_rpl_table.h"
#include "kernel/kernel_functions.h"
#include "common/common.h"
//! static container holding our retain data
static unsigned char ucRpxData[0xffff];
static int iRpxRplCount = 0;
void rpxRplTableInit(void)
{
s_rpx_rpl *pRpxData = (s_rpx_rpl*)ucRpxData;
//! initialize the RPL/RPX table first entry to zero + 1 byte for name zero termination
//! just in case no RPL/RPX are found, though it wont boot then anyway
memset(pRpxData, 0, sizeof(s_rpx_rpl) + 1);
iRpxRplCount = 0;
}
s_rpx_rpl * rpxRplTableAddEntry(const char *name, int offset, int size, int is_rpx, int entry_index, s_mem_area* area)
{
// fill rpx/rpl entry
s_rpx_rpl * rpx_rpl_data = (s_rpx_rpl *)(ucRpxData);
// get to last entry
while(rpx_rpl_data->next) {
rpx_rpl_data = rpx_rpl_data->next;
}
// setup next entry on the previous one (only if it is not the first entry)
if(entry_index > 0) {
rpx_rpl_data->next = (s_rpx_rpl *)( ((u32)rpx_rpl_data) + sizeof(s_rpx_rpl) + strlen(rpx_rpl_data->name) + 1 );
rpx_rpl_data = rpx_rpl_data->next;
}
// setup current entry
rpx_rpl_data->area = area;
rpx_rpl_data->size = size;
rpx_rpl_data->offset = offset;
rpx_rpl_data->is_rpx = is_rpx;
rpx_rpl_data->next = 0;
strcpy(rpx_rpl_data->name, name);
iRpxRplCount++;
return rpx_rpl_data;
}
s_rpx_rpl* rpxRplTableGet(void)
{
return (s_rpx_rpl*)ucRpxData;
}
int rpxRplTableGetCount(void)
{
return iRpxRplCount;
}
s_mem_area *rpxRplTableGetNextFreeMemArea(u32 * mem_area_addr_start, u32 * mem_area_addr_end, u32 * mem_area_offset)
{
s_mem_area * mem_area = memoryGetAreaTable();
s_rpx_rpl *rpl_struct = rpxRplTableGet();
while(rpl_struct != 0)
{
// check if this entry was loaded into memory
if(rpl_struct->size == 0) {
// see if we find entries behind this one that was pre-loaded
rpl_struct = rpl_struct->next;
// entry was not loaded into memory -> skip it
continue;
}
// this entry has been loaded to memory, remember it's area
mem_area = rpl_struct->area;
int rpl_size = rpl_struct->size;
int rpl_offset = rpl_struct->offset;
// find the end of the entry and switch between areas if needed
while(mem_area && (u32)(rpl_offset + rpl_size) >= mem_area->size)
{
rpl_size -= mem_area->size - rpl_offset;
rpl_offset = 0;
mem_area = mem_area->next;
}
if(!mem_area)
return NULL;
// set new start, end and memory area offset
*mem_area_addr_start = mem_area->address;
*mem_area_addr_end = mem_area->address + mem_area->size;
*mem_area_offset = rpl_offset + rpl_size;
// see if we find entries behind this one that was pre-loaded
rpl_struct = rpl_struct->next;
}
return mem_area;
}
int rpxRplCopyDataToMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, const u8 *data, u32 dataSize)
{
s_mem_area *mem_area = rpx_rpl_struct->area;
u32 mem_area_addr_start = mem_area->address;
u32 mem_area_addr_end = mem_area_addr_start + mem_area->size;
u32 mem_area_offset = rpx_rpl_struct->offset;
// add to offset
mem_area_offset += fileOffset;
// skip position to the end of the fill
while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >=
{
// subtract what was in the offset left from last memory block
mem_area_offset = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end;
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area_addr_start + mem_area->size;
}
// copy to memory
u32 copiedBytes = 0;
while(copiedBytes < dataSize)
{
u32 blockSize = dataSize - copiedBytes;
u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset;
if((mem_area_addr_dest + blockSize) > mem_area_addr_end)
blockSize = mem_area_addr_end - mem_area_addr_dest;
if(blockSize == 0)
{
// Set next memory area
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area->address + mem_area->size;
mem_area_offset = 0;
continue;
}
SC0x25_KernelCopyData(mem_area_addr_dest, (u32)&data[copiedBytes], blockSize);
mem_area_offset += blockSize;
copiedBytes += blockSize;
}
return copiedBytes;
}
int rpxRplCopyDataFromMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, u8 *data, u32 dataSize)
{
s_mem_area *mem_area = rpx_rpl_struct->area;
u32 mem_area_addr_start = mem_area->address;
u32 mem_area_addr_end = mem_area_addr_start + mem_area->size;
u32 mem_area_offset = rpx_rpl_struct->offset;
if(fileOffset > rpx_rpl_struct->size)
return 0;
if((fileOffset + dataSize) > rpx_rpl_struct->size)
dataSize = rpx_rpl_struct->size - fileOffset;
// add to offset
mem_area_offset += fileOffset;
// skip position to the end of the fill
while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >=
{
// subtract what was in the offset left from last memory block
mem_area_offset = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end;
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area_addr_start + mem_area->size;
}
// copy to memory
u32 copiedBytes = 0;
while(copiedBytes < dataSize)
{
u32 blockSize = dataSize - copiedBytes;
u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset;
if((mem_area_addr_dest + blockSize) > mem_area_addr_end)
blockSize = mem_area_addr_end - mem_area_addr_dest;
if(blockSize == 0)
{
// Set next memory area
mem_area = mem_area->next;
if(!mem_area)
return 0;
mem_area_addr_start = mem_area->address;
mem_area_addr_end = mem_area->address + mem_area->size;
mem_area_offset = 0;
continue;
}
SC0x25_KernelCopyData((u32)&data[copiedBytes], mem_area_addr_dest, blockSize);
mem_area_offset += blockSize;
copiedBytes += blockSize;
}
return copiedBytes;
}

View File

@ -1,37 +0,0 @@
#ifndef __RPX_ARRAY_H_
#define __RPX_ARRAY_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <gctypes.h>
#include "common/common.h"
#include "memory_area_table.h"
/* Struct used to organize rpx/rpl data in memory */
typedef struct _s_rpx_rpl
{
struct _s_rpx_rpl* next;
s_mem_area* area;
unsigned int offset;
unsigned int size;
unsigned char is_rpx;
char name[0];
} s_rpx_rpl;
void rpxRplTableInit(void);
s_rpx_rpl* rpxRplTableAddEntry(const char *name, int offset, int size, int is_rpx, int entry_index, s_mem_area* area);
s_rpx_rpl* rpxRplTableGet(void);
int rpxRplTableGetCount(void);
s_mem_area *rpxRplTableGetNextFreeMemArea(u32 * mem_area_addr_start, u32 * mem_area_addr_end, u32 * mem_area_offset);
int rpxRplCopyDataToMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, const u8 *data, u32 dataSize);
int rpxRplCopyDataFromMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, u8 *data, u32 dataSize);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -3,7 +3,6 @@
#include "common/kernel_defs.h"
#include "kernel/kernel_functions.h"
#include "kernel/syscalls.h"
#include "start.h"
/* our retain data */
ReducedCosAppXmlInfo cosAppXmlInfoStruct __attribute__((section(".data")));
@ -41,9 +40,6 @@ void my_PrepareTitle(CosAppXmlInfo *xmlKernelInfo)
cosAppXmlInfoStruct.exception_stack2_size = xmlKernelInfo->exception_stack2_size;
cosAppXmlInfoStruct.sdk_version = xmlKernelInfo->sdk_version;
cosAppXmlInfoStruct.title_version = xmlKernelInfo->title_version;
// on title switch reset the dumper
Reset();
}
void SetupKernelCallback(void)

View File

@ -1,3 +1,4 @@
# Created by dimok
# This stuff may need a change in different kernel versions
# This is only needed when launched directly through browser and not SD card.

View File

@ -1,3 +1,4 @@
# Created by dimok
# Syscalls for kernel that we use
.globl SC0x36_KernelReadDBATs

View File

@ -1,4 +1,4 @@
OUTPUT(ddd.elf);
OUTPUT(hidtovpad.elf);
/* Tell linker where our application entry is so the garbage collect can work correct */
ENTRY(__entry_menu);

View File

@ -1,70 +0,0 @@
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/gx2_functions.h"
#include "dynamic_libs/syshid_functions.h"
#include "dynamic_libs/vpad_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "dynamic_libs/sys_functions.h"
#include "system/memory.h"
#include "utils/logger.h"
#include "common/common.h"
#include "game/rpx_rpl_table.h"
#include "game/memory_area_table.h"
#include "start.h"
#include "patcher/function_hooks.h"
#include "patcher/cpp_to_c_util.h"
#include "kernel/kernel_functions.h"
#include "system/exception_handler.h"
#include "controller_patcher/controller_patcher.h"
/* Entry point */
int Menu_Main(void)
{
//!*******************************************************************
//! Initialize function pointers *
//!*******************************************************************
//! do OS (for acquire) and sockets first so we got logging
InitOSFunctionPointers();
InitSocketFunctionPointers();
InitGX2FunctionPointers();
InitSysFunctionPointers();
draw_Cursor_destroy();
log_init("192.168.0.181");
SetupKernelCallback();
log_printf("Started %s\n", cosAppXmlInfoStruct.rpx_name);
//!*******************************************************************
//! Initialize HID Config *
//!*******************************************************************
init_config_controller();
PatchMethodHooks();
if(strlen(cosAppXmlInfoStruct.rpx_name) > 0 && strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) != 0)
{
return EXIT_RELAUNCH_ON_LOAD;
}
if(strlen(cosAppXmlInfoStruct.rpx_name) <= 0){ // First boot back to SysMenu
SYSLaunchMenu();
return EXIT_RELAUNCH_ON_LOAD;
}
draw_Cursor_destroy();
RestoreInstructions();
deinit_config_controller();
log_deinit();
return EXIT_SUCCESS;
}

161
src/main.cpp Normal file
View File

@ -0,0 +1,161 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include "main.h"
#include "version.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/gx2_functions.h"
#include "dynamic_libs/syshid_functions.h"
#include "dynamic_libs/vpad_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "dynamic_libs/sys_functions.h"
#include "controller_patcher/controller_patcher.h"
#include "controller_patcher/config_reader.h"
#include "controller_patcher/cp_retain_vars.h"
#include "patcher/function_hooks.h"
#include "kernel/kernel_functions.h"
#include "video/CursorDrawer.h"
#include "utils/logger.h"
#define PRINT_TEXT1(x, y, str) { OSScreenPutFontEx(1, x, y, str); OSScreenPutFontEx(0, x, y, str); }
#define PRINT_TEXT2(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(0, x, y, msg);OSScreenPutFontEx(1, x, y, msg); }
/* Entry point */
extern "C" int Menu_Main(void)
{
//!*******************************************************************
//! Initialize function pointers *
//!*******************************************************************
//! do OS (for acquire) and sockets first so we got logging
InitOSFunctionPointers();
InitSocketFunctionPointers();
InitGX2FunctionPointers();
InitSysFunctionPointers();
InitVPadFunctionPointers();
SetupKernelCallback();
log_init("192.168.0.181");
//Reset everything when were going back to the Mii Maker
if(strlen(cosAppXmlInfoStruct.rpx_name) > 0 && strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) == 0){
log_print("Returing to the Homebrew Launcher!\n");
deInit();
return EXIT_SUCCESS;
}
//Otherwise apply the patches!!!
log_printf("HID to VPAD %s - %s %s - by Maschell\n\n",APP_VERION,__DATE__,__TIME__);
//!*******************************************************************
//! Initialize HID Config *
//!*******************************************************************
log_print("Initializing the controller data\n");
init_config_controller();
log_print("Initializing the data for button remapping\n");
init_button_remapping();
if(gConfig_done == HID_INIT_DONE){
log_print("Reading config files from SD Card\n");
ConfigReader::getInstance(); //doing the magic automatically
ConfigReader::destroyInstance();
log_print("Done with reading config files from SD Card\n");
gConfig_done = HID_SDCARD_READ;
}
//!*******************************************************************
//! Patching functions *
//!*******************************************************************
log_print("Patching functions\n");
PatchMethodHooks();
if(strlen(cosAppXmlInfoStruct.rpx_name) > 0 && strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) != 0)
{
return EXIT_RELAUNCH_ON_LOAD;
}
if(strlen(cosAppXmlInfoStruct.rpx_name) <= 0){ // First boot back to SysMenu
SplashScreen(15);
SYSLaunchMenu();
return EXIT_RELAUNCH_ON_LOAD;
}
deInit();
return EXIT_SUCCESS;
}
void deInit(){
CursorDrawer::destroyInstance();
RestoreInstructions();
deinit_config_controller();
log_deinit();
}
void SplashScreen(int time){
// Prepare screen
int screen_buf0_size = 0;
// Init screen and screen buffers
OSScreenInit();
screen_buf0_size = OSScreenGetBufferSizeEx(0);
OSScreenSetBufferEx(0, (void *)0xF4000000);
OSScreenSetBufferEx(1, (void *)(0xF4000000 + screen_buf0_size));
OSScreenEnableEx(0, 1);
OSScreenEnableEx(1, 1);
// Clear screens
OSScreenClearBufferEx(0, 0);
OSScreenClearBufferEx(1, 0);
// Flip buffers
OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1);
char* msg = (char*) malloc(80);
PRINT_TEXT2(0,0, "HID to VPAD %s - %s %s - by Maschell",APP_VERION,__DATE__,__TIME__);
int readFiles = 0;//ConfigReader::getNumberOfLoadedFiles();
int i = 2;
PRINT_TEXT1(0,i, " - Reading SD Card."); i++;
if(readFiles > 0){
PRINT_TEXT2(0,i, " - Loaded %d valid config files",readFiles); i++;
}else{
PRINT_TEXT1(0,i, " - No valid config files found."); i++;
PRINT_TEXT1(0,i, " - Starting with default values"); i++;
}
PRINT_TEXT1(0,i, " - Applied functions patches"); i++;i++;
PRINT_TEXT2(0,i, "Wait %d seconds or press A to return to the system menu",time); i++;
PRINT_TEXT1(0,9, "Support for new gamepads can be added through config files"); i++;
PRINT_TEXT1(0,11, "Download new configs here: ");
PRINT_TEXT1(0,12, "https://github.com/Maschell/controller_patcher_configs");
//13
PRINT_TEXT1(0,14, "Support:");
PRINT_TEXT1(0,15, "github : https://github.com/Maschell/hid_to_vpad");
PRINT_TEXT1(0,16, " https://github.com/Maschell/controller_patcher");
PRINT_TEXT1(0,17, "gbatemp.net: http://gbatemp.net/threads/hid-to-vpad.424127/");
OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1);
VPADData vpad_data;
int error;
int tickswait = time * 1000*1000;
int times = 1000;
int sleepingtime = tickswait / 1000;
i=0;
while(i<times){
VPADRead(0, &vpad_data, 1, &error);
if(vpad_data.btns_h & VPAD_BUTTON_A){
i = times;
}
i++;
usleep(sleepingtime);
}
free(msg);
}

View File

@ -11,6 +11,8 @@ extern "C" {
//! C wrapper for our C++ functions
int Menu_Main(void);
void SplashScreen(int time);
void deInit(void);
#ifdef __cplusplus
}

View File

@ -1,59 +0,0 @@
#include "cpp_to_c_util.h"
#include <string.h>
#include "common/common.h"
#include "video/shaders/ColorShader.h"
u8 gCursorInitDone __attribute__((section(".data"))) = 0;
static u8 * cursor_colorVtxs = NULL;
void init_cursor(){
if(!gCursorInitDone){
if(!cursor_colorVtxs){
cursor_colorVtxs = (u8*)memalign(0x40, sizeof(u8) * 16);
if(cursor_colorVtxs == NULL) return;
}
memset(cursor_colorVtxs,0xFF,16*sizeof(u8));
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, cursor_colorVtxs, 16 * sizeof(u8));
gCursorInitDone = 1;
}
}
void draw_Cursor_at(f32 x, f32 y) {
init_cursor();
if(cursor_colorVtxs == NULL) return;
f32 widthScaleFactor = 1.0f / (f32)1280;
f32 heightScaleFactor = 1.0f / (f32)720;
int width = 20;
glm::vec3 positionOffsets = glm::vec3(0.0f);
positionOffsets[0] = (x-((1280)/2)+(width/2)) * widthScaleFactor * 2.0f;
positionOffsets[1] = -(y-((720)/2)+(width/2)) * heightScaleFactor * 2.0f;
glm::vec3 scale(width*widthScaleFactor,width*heightScaleFactor,1.0f);
ColorShader::instance()->setShaders();
ColorShader::instance()->setAttributeBuffer(cursor_colorVtxs, NULL, 4);
ColorShader::instance()->setAngle(0);
ColorShader::instance()->setOffset(positionOffsets);
ColorShader::instance()->setScale(scale);
ColorShader::instance()->setColorIntensity(glm::vec4(1.0f));
ColorShader::instance()->draw(GX2_PRIMITIVE_QUADS, 4);
}
void draw_Cursor_destroy() {
//! destroy shaders
ColorShader::destroyInstance();
if(cursor_colorVtxs){
free(cursor_colorVtxs);
cursor_colorVtxs = NULL;
}
gCursorInitDone = 0;
}

View File

@ -1,12 +0,0 @@
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
#include "../dynamic_libs/gx2_types.h"
EXTERNC void draw_Cursor_at(f32 x, f32 y);
EXTERNC void draw_Cursor_destroy();
#undef EXTERNC

View File

@ -1,11 +1,26 @@
/****************************************************************************
* Copyright (C) 2016 Maschell
*
* 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/>.
****************************************************************************/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "common/common.h"
#include "common/fs_defs.h"
#include "common/loader_defs.h"
#include <gctypes.h>
#include "function_hooks.h"
#include "controller_patcher/cp_retain_vars.h"
#include "game/rpx_rpl_table.h"
#include "dynamic_libs/aoc_functions.h"
#include "dynamic_libs/ax_functions.h"
#include "dynamic_libs/fs_functions.h"
@ -18,13 +33,8 @@
#include "dynamic_libs/acp_functions.h"
#include "dynamic_libs/syshid_functions.h"
#include "kernel/kernel_functions.h"
#include "system/exception_handler.h"
#include "function_hooks.h"
#include "fs/fs_utils.h"
#include "utils/logger.h"
#include "system/memory.h"
#include "cpp_to_c_util.h"
#include "video/CursorDrawer.h"
#define LIB_CODE_RW_BASE_OFFSET 0xC1000000
#define CODE_RW_BASE_OFFSET 0x00000000
@ -37,26 +47,27 @@
res my_ ## name(__VA_ARGS__)
DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target){
if(gHIDCurrentDevice & HID_LIST_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) {
draw_Cursor_at(gHID_Mouse.pad_data[0].data[0].X, gHID_Mouse.pad_data[0].data[0].Y);
if(gHIDCurrentDevice & gHID_LIST_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) {
CursorDrawer::draw(gHID_Mouse.pad_data[0].data[0].X, gHID_Mouse.pad_data[0].data[0].Y);
}
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
}
DECL(void, _Exit, void){
draw_Cursor_destroy();
CursorDrawer::destroyInstance();
real__Exit();
}
DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {
int result = real_VPADRead(chan, buffer, buffer_size, error);
if(gHIDAttached){
setControllerDataFromHID(buffer,gHIDCurrentDevice);
setControllerDataFromHID(buffer,HID_ALL_CONNECTED_DEVICES);
}
if(gButtonRemappingConfigDone){
buttonRemapping(buffer);
if (HID_DEBUG) printButtons(buffer);
}
//log_printf("%08X %08X %08X\n",buffer->btns_h,buffer->btns_r,buffer->btns_d);
return result;
}
@ -89,7 +100,7 @@ volatile unsigned int dynamic_method_calls[sizeof(method_hooks) / sizeof(struct
/*
*Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic.
* "normal" functions should be patch with the normal patcher.
* "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok.
*/
void PatchMethodHooks(void)
{
@ -104,12 +115,13 @@ void PatchMethodHooks(void)
u32 flush_len = 4*instr_len;
for(int i = 0; i < method_hooks_count; i++)
{
log_printf("Patching %s ...",method_hooks[i].functionName);
if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){
if(isDynamicFunction((u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr))){
log_printf("The function %s is a dynamic function. Please fix that <3\n", method_hooks[i].functionName);
log_printf(" The function %s is a dynamic function. Please fix that <3 ... ", method_hooks[i].functionName);
method_hooks[i].functionType = DYNAMIC_FUNCTION;
}else{
log_printf("Skipping %s, its already patched\n", method_hooks[i].functionName);
log_printf(" skipped. Its already patched\n", method_hooks[i].functionName);
space += instr_len;
continue;
}
@ -122,7 +134,7 @@ void PatchMethodHooks(void)
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
if(!real_addr){
log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
log_printf("Error. OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
space += instr_len;
continue;
}
@ -131,7 +143,7 @@ void PatchMethodHooks(void)
physical = (u32)OSEffectiveToPhysical((void*)real_addr);
if(!physical){
log_printf("Something is wrong with the physical address\n");
log_printf("Error. Something is wrong with the physical address\n");
space += instr_len;
continue;
}
@ -159,7 +171,7 @@ void PatchMethodHooks(void)
method_hooks[i].realAddr = real_addr;
method_hooks[i].restoreInstruction = *(volatile unsigned int*)(physical);
}else{
log_printf("Can't save %s for restoring!\n", method_hooks[i].functionName);
log_printf("Error. Can't save %s for restoring!\n", method_hooks[i].functionName);
}
//adding jump to real function
@ -194,6 +206,8 @@ void PatchMethodHooks(void)
KernelRestoreDBATs(&my_dbat_table);
method_hooks[i].alreadyPatched = 1;
log_printf("done!\n");
}
log_print("Done with patching all functions!\n");
}
@ -208,33 +222,34 @@ void RestoreInstructions(void)
int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t);
for(int i = 0; i < method_hooks_count; i++)
{
log_printf("Restoring %s ...",method_hooks[i].functionName);
if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0){
log_printf("I dont have the information for the restore =( skip\n");
log_printf("Error. I dont have the information for the restore =( skip\n");
continue;
}
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
if(!real_addr){
log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
//log_printf("Error. OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
continue;
}
u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr);
if(!physical){
log_printf("Something is wrong with the physical address\n");
log_printf("Error. Something is wrong with the physical address\n");
continue;
}
if(isDynamicFunction(physical)){
log_printf("Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName);
log_printf("Error. Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName);
}else{
KernelSetDBATs(&table);
*(volatile unsigned int *)(LIB_CODE_RW_BASE_OFFSET + method_hooks[i].realAddr) = method_hooks[i].restoreInstruction;
DCFlushRange((void*)(LIB_CODE_RW_BASE_OFFSET + method_hooks[i].realAddr), 4);
ICInvalidateRange((void*)method_hooks[i].realAddr, 4);
log_printf("Restored %s\n",method_hooks[i].functionName);
log_printf(" done\n");
KernelRestoreDBATs(&table);
}
method_hooks[i].alreadyPatched = 0; // In case a
@ -255,72 +270,72 @@ unsigned int GetAddressOfFunction(const char * functionName,unsigned int library
unsigned int rpl_handle = 0;
if(library == LIB_CORE_INIT){
log_printf("FindExport of %s! From LIB_CORE_INIT\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_CORE_INIT\n", functionName);
if(coreinit_handle == 0){log_print("LIB_CORE_INIT not aquired\n"); return 0;}
rpl_handle = coreinit_handle;
}
else if(library == LIB_NSYSNET){
log_printf("FindExport of %s! From LIB_NSYSNET\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_NSYSNET\n", functionName);
if(nsysnet_handle == 0){log_print("LIB_NSYSNET not aquired\n"); return 0;}
rpl_handle = nsysnet_handle;
}
else if(library == LIB_GX2){
log_printf("FindExport of %s! From LIB_GX2\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_GX2\n", functionName);
if(gx2_handle == 0){log_print("LIB_GX2 not aquired\n"); return 0;}
rpl_handle = gx2_handle;
}
else if(library == LIB_AOC){
log_printf("FindExport of %s! From LIB_AOC\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_AOC\n", functionName);
if(aoc_handle == 0){log_print("LIB_AOC not aquired\n"); return 0;}
rpl_handle = aoc_handle;
}
else if(library == LIB_AX){
log_printf("FindExport of %s! From LIB_AX\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_AX\n", functionName);
if(sound_handle == 0){log_print("LIB_AX not aquired\n"); return 0;}
rpl_handle = sound_handle;
}
else if(library == LIB_FS){
log_printf("FindExport of %s! From LIB_FS\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_FS\n", functionName);
if(coreinit_handle == 0){log_print("LIB_FS not aquired\n"); return 0;}
rpl_handle = coreinit_handle;
}
else if(library == LIB_OS){
log_printf("FindExport of %s! From LIB_OS\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_OS\n", functionName);
if(coreinit_handle == 0){log_print("LIB_OS not aquired\n"); return 0;}
rpl_handle = coreinit_handle;
}
else if(library == LIB_PADSCORE){
log_printf("FindExport of %s! From LIB_PADSCORE\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_PADSCORE\n", functionName);
if(padscore_handle == 0){log_print("LIB_PADSCORE not aquired\n"); return 0;}
rpl_handle = padscore_handle;
}
else if(library == LIB_SOCKET){
log_printf("FindExport of %s! From LIB_SOCKET\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_SOCKET\n", functionName);
if(nsysnet_handle == 0){log_print("LIB_SOCKET not aquired\n"); return 0;}
rpl_handle = nsysnet_handle;
}
else if(library == LIB_SYS){
log_printf("FindExport of %s! From LIB_SYS\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_SYS\n", functionName);
if(sysapp_handle == 0){log_print("LIB_SYS not aquired\n"); return 0;}
rpl_handle = sysapp_handle;
}
else if(library == LIB_VPAD){
log_printf("FindExport of %s! From LIB_VPAD\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_VPAD\n", functionName);
if(vpad_handle == 0){log_print("LIB_VPAD not aquired\n"); return 0;}
rpl_handle = vpad_handle;
}
else if(library == LIB_NN_ACP){
log_printf("FindExport of %s! From LIB_NN_ACP\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_NN_ACP\n", functionName);
if(acp_handle == 0){log_print("LIB_NN_ACP not aquired\n"); return 0;}
rpl_handle = acp_handle;
}
else if(library == LIB_SYSHID){
log_printf("FindExport of %s! From LIB_SYSHID\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_SYSHID\n", functionName);
if(syshid_handle == 0){log_print("LIB_SYSHID not aquired\n"); return 0;}
rpl_handle = syshid_handle;
}
else if(library == LIB_VPADBASE){
log_printf("FindExport of %s! From LIB_VPADBASE\n", functionName);
if(DEBUG_LOG_DYN)log_printf("FindExport of %s! From LIB_VPADBASE\n", functionName);
if(vpadbase_handle == 0){log_print("LIB_VPADBASE not aquired\n"); return 0;}
rpl_handle = vpadbase_handle;
}

View File

@ -1,38 +1,31 @@
/****************************************************************************
* Copyright (C) 2016 Maschell
*
* 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 _FUNCTION_HOOKS_H_
#define _FUNCTION_HOOKS_H_
#include "dynamic_libs/syshid_functions.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations */
#define MAX_CLIENT 32
struct bss_t {
int global_sock;
int socket_fs[MAX_CLIENT];
void *pClient_fs[MAX_CLIENT];
volatile int lock;
char mount_base[255];
char save_base[255];
void* file_replacer;
char update_path[50];
char save_dir_common[7];
char save_dir_user[9];
};
#define bss_ptr (*(struct bss_t **)0x100000e4)
#define bss (*bss_ptr)
void PatchMethodHooks(void);
void RestoreInstructions(void);
unsigned int GetAddressOfFunction(const char * functionName,unsigned int library);
int isDynamicFunction(unsigned int physicalAddress);
void PatchSDK(void);
#ifdef __cplusplus
}

View File

@ -1,24 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "common/kernel_defs.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/fs_functions.h"
#include "dynamic_libs/aoc_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "dynamic_libs/sys_functions.h"
#include "game/rpx_rpl_table.h"
#include "game/memory_area_table.h"
#include "utils/net.h"
#include "start.h"
void StartFunction()
{
}
void Reset(void)
{
}

View File

@ -1,18 +0,0 @@
#ifndef _DISCDUMPER_H_
#define _DISCDUMPER_H_
#ifdef __cplusplus
extern "C" {
#endif
void StartFunction(void);
void Reset(void);
void SetServerIp(u32 ip);
u32 GetServerIp(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -3,7 +3,6 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "common/common.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "logger.h"

View File

@ -1,636 +0,0 @@
#include <string.h>
#include <malloc.h>
#include "common/common.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "net.h"
#define CHECK_ERROR(cond) if (cond) { goto error; }
#include <string.h>
#include <malloc.h>
#include "common/common.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "net.h"
static volatile int iLock = 0;
#define CHECK_ERROR(cond) if (cond) { goto error; }
void cafiine_connect(int *psock,u32 server_ip) {
struct sockaddr_in addr;
int sock, ret;
socket_lib_init();
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CHECK_ERROR(sock == -1);
addr.sin_family = AF_INET;
addr.sin_port = 7332;
addr.sin_addr.s_addr = server_ip;
ret = connect(sock, (void *)&addr, sizeof(addr));
CHECK_ERROR(ret < 0);
ret = cafiine_handshake(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_NORMAL);
*psock = sock;
return;
error:
if (sock != -1)
socketclose(sock);
*psock = -1;
return;
}
void cafiine_disconnect(int sock) {
CHECK_ERROR(sock == -1);
socketclose(sock);
error:
return;
}
int cafiine_handshake(int sock) {
int ret;
unsigned char buffer[16];
u64 title_id = OSGetTitleID();
memcpy(buffer, &title_id, 16);
ret = sendwait(sock, buffer, sizeof(buffer));
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
return ret;
error:
return ret;
}
int getMode(int sock,int * result)
{
int ret = 0;
CHECK_ERROR(sock == -1);
// create and send buffer with : [cmd id][fd][size][buffer data ...]
{
ret = sendbyte(sock, BYTE_G_MODE);
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
if(ret == BYTE_MODE_D) *result = BYTE_MODE_D;
if(ret == BYTE_MODE_I) *result = BYTE_MODE_I;
ret = 1;
}
error:
return ret;
}
int cafiine_fsetpos(int sock, int *result, int fd, int set) {
CHECK_ERROR(sock == -1);
int ret;
char buffer[1 + 8];
buffer[0] = BYTE_SETPOS;
*(int *)(buffer + 1) = fd;
*(int *)(buffer + 5) = set;
ret = sendwait(sock, buffer, 1 + 8);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_NORMAL);
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
return 0;
error:
return -1;
}
int cafiine_send_handle(int sock, const char *path, int handle)
{
CHECK_ERROR(sock == -1);
// create and send buffer with : [cmd id][handle][path length][path data ...]
{
int ret;
int len_path = 0;
while (path[len_path++]);
char buffer[1 + 4 + 4 + len_path];
buffer[0] = BYTE_HANDLE;
*(int *)(buffer + 1) = handle;
*(int *)(buffer + 5) = len_path;
for (ret = 0; ret < len_path; ret++)
buffer[9 + ret] = path[ret];
// send buffer, wait for reply
ret = sendwait(sock, buffer, 1 + 4 + 4 + len_path);
CHECK_ERROR(ret < 0);
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_SPECIAL);
if(ret == BYTE_REQUEST){
ret = 1;
}else{
ret = 2;
}
// wait reply
int special_ret = recvbyte(sock);
CHECK_ERROR(special_ret < 0);
CHECK_ERROR(special_ret != BYTE_SPECIAL);
return ret;
}
error:
return -1;
}
int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle) {
int final_result = -1;
CHECK_ERROR(sock == -1);
int ret;
int len_path = 0;
while (path[len_path++]);
int len_mode = 0;
while (mode[len_mode++]);
//
{
char buffer[1 + 8 + len_path + len_mode];
buffer[0] = BYTE_OPEN;
*(int *)(buffer + 1) = len_path;
*(int *)(buffer + 5) = len_mode;
for (ret = 0; ret < len_path; ret++)
buffer[9 + ret] = path[ret];
for (ret = 0; ret < len_mode; ret++)
buffer[9 + len_path + ret] = mode[ret];
ret = sendwait(sock, buffer, 1 + 8 + len_path + len_mode);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_NORMAL);
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
ret = recvwait(sock, handle, 4);
CHECK_ERROR(ret < 0);
}
final_result = 0;
error:
return final_result;
}
void cafiine_send_file(int sock, char *file, int size, int fd) {
CHECK_ERROR(sock == -1);
int ret;
// create and send buffer with : [cmd id][fd][size][buffer data ...]
{
char buffer[1 + 4 + 4 + size];
buffer[0] = BYTE_DUMP;
*(int *)(buffer + 1) = fd;
*(int *)(buffer + 5) = size;
for (ret = 0; ret < size; ret++)
buffer[9 + ret] = file[ret];
// send buffer, wait for reply
ret = sendwait(sock, buffer, 1 + 4 + 4 + size);
CHECK_ERROR(ret < 0);
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret != BYTE_SPECIAL);
}
error:
return;
}
int cafiine_fread(int sock, int *result, void *ptr, int size, int fd) {
CHECK_ERROR(sock == -1);
int ret;
char buffer[1 + 8];
buffer[0] = BYTE_READ;
*(int *)(buffer + 1) = size;
*(int *)(buffer + 5) = fd;
ret = sendwait(sock, buffer, 1 + 8);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret == BYTE_NORMAL);
int sz;
ret = recvwait(sock, &sz, 4);
CHECK_ERROR(ret < 0);
ret = recvwaitlen(sock, ptr, sz);
*result = sz - ret;
ret = sendbyte(sock, BYTE_OK);
CHECK_ERROR(ret < 0);
return 0;
error:
return -1;
}
int cafiine_fclose(int sock, int *result, int fd,int dumpclose) {
CHECK_ERROR(sock == -1);
int ret;
char buffer[1 + 4];
buffer[0] = BYTE_CLOSE;
if(dumpclose)buffer[0] = BYTE_CLOSE_DUMP;
*(int *)(buffer + 1) = fd;
ret = sendwait(sock, buffer, 1 + 4);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret == BYTE_NORMAL);
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
return 0;
error:
return -1;
}
int saviine_start_injection(int sock, long persistentID,int * mask){
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
char buffer[1+4];
buffer[0] = BYTE_INJECTSTART;
*(long *)(buffer + 1) = persistentID;
ret = sendwait(sock, buffer, 1 + 4);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
ret = recvwait(sock, mask, 4);
CHECK_ERROR(ret < 0);
CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
result = 1;
}
error:
return result;
}
int saviine_end_injection(int sock){
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
ret = sendbyte(sock, BYTE_INJECTEND);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_OK);
result = 1;
}
error:
return result;
}
int saviine_start_dump(int sock, long persistentID,int * mask){
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
char buffer[1+4];
buffer[0] = BYTE_DUMPSTART;
*(long *)(buffer + 1) = persistentID;
ret = sendwait(sock, buffer, 1 + 4);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
ret = recvwait(sock, mask, 4);
CHECK_ERROR(ret < 0);
CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
result = 1;
}
error:
return result;
}
int saviine_end_dump(int sock){
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
ret = sendbyte(sock, BYTE_DUMPEND);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_OK);
result = 1;
}
error:
return result;
}
int saviine_readdir(int sock, char * path,char * resultname, int * resulttype, int * filesize){
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
// create and send buffer with : [cmd id][len_path][path][filesize]
{
int size = 0;
while (path[size++]);
char buffer[1+4+size];
buffer[0] = BYTE_READ_DIR;
*(int *)(buffer + 1) = size;
for (ret = 0; ret < size; ret++)
buffer[5 + ret] = path[ret];
// send buffer, wait for reply
ret = sendwait(sock, buffer, 1+4+size);
CHECK_ERROR(ret < 0);
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret != BYTE_OK);
ret = recvbyte(sock);
CHECK_ERROR(ret != BYTE_FILE && ret != BYTE_FOLDER);
*resulttype = ret;
size = 0;
ret = recvwait(sock, &size, 4);
CHECK_ERROR(ret < 0);
ret = recvwait(sock, resultname, size+1);
CHECK_ERROR(ret < 0);
size = 0;
ret = recvwait(sock, &size, 4);
CHECK_ERROR(ret < 0);
*filesize = size;
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
result = 1;
}
error:
return result;
}
void cafiine_send_ping(int sock, int val1, int val2) {
int ret;
char buffer[1 + 4 + 4];
buffer[0] = BYTE_PING;
*(int *)(buffer + 1) = val1;
*(int *)(buffer + 5) = val2;
ret = sendwait(sock, buffer, 1 + 4 + 4);
CHECK_ERROR(ret < 0);
error:
return;
}
int recvwaitlen(int sock, void *buffer, int len) {
int ret;
while (len > 0) {
ret = recv(sock, buffer, len, 0);
CHECK_ERROR(ret < 0);
len -= ret;
buffer += ret;
}
return 0;
error:
return len;
}
int recvbyte(int sock) {
unsigned char buffer[1];
int ret;
ret = recvwait(sock, buffer, 1);
if (ret < 0) return ret;
return buffer[0];
}
void log_string(int sock, const char* str, char flag_byte) {
if(sock == -1) {
return;
}
int i;
int len_str = 0;
while (str[len_str++]);
//
{
char buffer[1 + 4 + len_str];
buffer[0] = flag_byte;
*(int *)(buffer + 1) = len_str;
for (i = 0; i < len_str; i++)
buffer[5 + i] = str[i];
buffer[5 + i] = 0;
sendwait(sock, buffer, 1 + 4 + len_str);
}
}
int sendbyte(int sock, unsigned char byte) {
unsigned char buffer[1];
buffer[0] = byte;
return sendwait(sock, buffer, 1);
}
int sendwait(int sock, const void *buffer, int len)
{
while (iLock)
usleep(5000);
iLock = 1;
int ret;
while (len > 0) {
ret = send(sock, buffer, len, 0);
CHECK_ERROR(ret <= 0);
len -= ret;
buffer += ret;
}
iLock = 0;
return 0;
error:
iLock = 0;
return ret;
}
int recvwait(int sock, void *buffer, int len)
{
while (iLock)
usleep(5000);
iLock = 1;
int ret;
int received = 0;
while (len > 0)
{
ret = recv(sock, buffer, len, 0);
if(ret > 0)
{
len -= ret;
buffer += ret;
received += ret;
}
else
{
received = ret < 0 ? ret : -1;
break;
}
}
iLock = 0;
return received;
}
/*
s32 create_server(void) {
socket_lib_init();
s32 server = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (server < 0)
return -1;
u32 enable = 1;
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
struct sockaddr_in bindAddress;
memset(&bindAddress, 0, sizeof(bindAddress));
bindAddress.sin_family = AF_INET;
bindAddress.sin_port = 7333;
bindAddress.sin_addr.s_addr = INADDR_ANY;
s32 ret;
if ((ret = bind(server, (struct sockaddr *)&bindAddress, sizeof(bindAddress))) < 0) {
socketclose(server);
return ret;
}
if ((ret = listen(server, 3)) < 0) {
socketclose(server);
return ret;
}
return server;
}
s32 accept_client(s32 server)
{
struct sockaddr addr;
s32 addrlen = sizeof(addr);
return accept(server, &addr, &addrlen);
}
*/
int server_connect(int *psock, unsigned int server_ip)
{
struct sockaddr_in addr;
int sock, ret;
// No ip means that we don't have any server running, so no logs
if (server_ip == 0) {
*psock = -1;
return 0;
}
socket_lib_init();
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock < 0)
return sock;
addr.sin_family = AF_INET;
addr.sin_port = 7333;
addr.sin_addr.s_addr = server_ip;
ret = connect(sock, (void *)&addr, sizeof(addr));
if(ret < 0)
{
socketclose(sock);
return -1;
}
int enable = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, sizeof(enable));
*psock = sock;
iLock = 0;
return 0;
}

View File

@ -1,64 +0,0 @@
#ifndef NETWORK_H_
#define NETWORK_H_
#define BYTE_NORMAL 0xff
#define BYTE_SPECIAL 0xfe
#define BYTE_OPEN 0x00
#define BYTE_READ 0x01
#define BYTE_CLOSE 0x02
#define BYTE_OK 0x03
#define BYTE_SETPOS 0x04
#define BYTE_STATFILE 0x05
#define BYTE_EOF 0x06
#define BYTE_GETPOS 0x07
#define BYTE_REQUEST 0x08
#define BYTE_REQUEST_SLOW 0x09
#define BYTE_HANDLE 0x0A
#define BYTE_DUMP 0x0B
#define BYTE_PING 0x0C
#define BYTE_G_MODE 0x0D
#define BYTE_MODE_D 0x0E
#define BYTE_MODE_I 0x0F
#define BYTE_CLOSE_DUMP 0x10
#define BYTE_LOG_STR 0xfb
#define BYTE_FILE 0xC0
#define BYTE_FOLDER 0xC1
#define BYTE_READ_DIR 0xCC
#define BYTE_INJECTSTART 0x40
#define BYTE_INJECTEND 0x41
#define BYTE_DUMPSTART 0x42
#define BYTE_DUMPEND 0x43
#define BYTE_END 0xfd
#define MASK_NORMAL 0x8000
#define MASK_USER 0x0100
#define MASK_COMMON 0x0200
#define MASK_COMMON_CLEAN 0x0400
void cafiine_connect(int *psock,u32 ip);
void cafiine_disconnect(int sock);
int cafiine_handshake(int sock);
int getMode(int sock,int * result);
int cafiine_fsetpos(int sock, int *result, int fd, int set);
int cafiine_send_handle(int sock, const char *path, int handle);
int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle);
void cafiine_send_file(int sock, char *file, int size, int fd);
int cafiine_fread(int sock, int *result, void *ptr, int size, int fd);
int cafiine_fclose(int sock, int *result, int fd,int dumpclose);
int saviine_start_injection(int sock, long persistentID,int * mask);
int saviine_end_injection(int sock);
int saviine_start_dump(int sock, long persistentID,int * mask);
int saviine_end_dump(int sock);
int saviine_readdir(int sock, char * path,char * resultname, int * resulttype, int * filesize);
void cafiine_send_ping(int sock, int val1, int val2);
int recvwaitlen(int sock, void *buffer, int len);
int recvbyte(int sock);
void log_string(int sock, const char* str, char flag_byte);
int sendbyte(int sock, unsigned char byte);
int server_connect(int *psock, unsigned int server_ip);
int recvwait(int sock, void *buffer, int len);
int sendwait(int sock, const void *buffer, int len);
#endif

5
src/version.h Normal file
View File

@ -0,0 +1,5 @@
#define MAJOR_VERION "0"
#define MINOR_VERSION "9"
#define EXTRA_VERSION " "
#define APP_VERION "v" MAJOR_VERION "." MINOR_VERSION EXTRA_VERSION

View File

@ -0,0 +1,80 @@
/****************************************************************************
* Copyright (C) 2016 Maschell
*
* 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/>.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dynamic_libs/gx2_functions.h"
#include "video/shaders/ColorShader.h"
#include "CursorDrawer.h"
CursorDrawer *CursorDrawer::instance = NULL;
CursorDrawer::CursorDrawer()
{
init_colorVtxs();
}
CursorDrawer::~CursorDrawer()
{
//! destroy shaders
ColorShader::destroyInstance();
if(this->colorVtxs){
free(this->colorVtxs);
this->colorVtxs = NULL;
}
}
void CursorDrawer::init_colorVtxs(){
if(!this->colorVtxs){
this->colorVtxs = (u8*)memalign(0x40, sizeof(u8) * 16);
if(this->colorVtxs == NULL) return;
}
memset(this->colorVtxs,0xFF,16*sizeof(u8));
GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, this->colorVtxs, 16 * sizeof(u8));
}
// Could be improved. It be more generic.
void CursorDrawer::draw_Cursor(f32 x,f32 y)
{
if(this->colorVtxs == NULL){
init_colorVtxs();
return;
}
f32 widthScaleFactor = 1.0f / (f32)1280;
f32 heightScaleFactor = 1.0f / (f32)720;
int width = 20;
glm::vec3 positionOffsets = glm::vec3(0.0f);
positionOffsets[0] = (x-((1280)/2)+(width/2)) * widthScaleFactor * 2.0f;
positionOffsets[1] = -(y-((720)/2)+(width/2)) * heightScaleFactor * 2.0f;
glm::vec3 scale(width*widthScaleFactor,width*heightScaleFactor,1.0f);
ColorShader::instance()->setShaders();
ColorShader::instance()->setAttributeBuffer(this->colorVtxs, NULL, 4);
ColorShader::instance()->setAngle(0);
ColorShader::instance()->setOffset(positionOffsets);
ColorShader::instance()->setScale(scale);
ColorShader::instance()->setColorIntensity(glm::vec4(1.0f));
ColorShader::instance()->draw(GX2_PRIMITIVE_QUADS, 4);
}

64
src/video/CursorDrawer.h Normal file
View File

@ -0,0 +1,64 @@
/****************************************************************************
* Copyright (C) 2016 Maschell
*
* 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 _CursorDrawer_H_
#define _CursorDrawer_H_
#include <string>
#include <stdio.h>
#include <gctypes.h>
#include <gctypes.h>
#include "dynamic_libs/gx2_types.h"
class CursorDrawer
{
public:
static CursorDrawer *getInstance() {
if(!instance)
instance = new CursorDrawer();
return instance;
}
static void destroyInstance() {
if(instance){
delete instance;
instance = NULL;
}
}
static void draw(f32 x, f32 y)
{
CursorDrawer * cur_instance = getInstance();
if(cur_instance == NULL) return;
cur_instance->draw_Cursor(x,y);
}
private:
//!Constructor
CursorDrawer();
//!Destructor
~CursorDrawer();
static CursorDrawer *instance;
void draw_Cursor(f32 x, f32 y);
void init_colorVtxs();
u8 * colorVtxs = NULL;
};
#endif