├── .gitignore ├── meta ├── icon.png └── meta.xml ├── meta_lite ├── icon.png └── meta.xml ├── src ├── common │ ├── types.h │ ├── os_defs.h │ ├── loader_defs.h │ ├── fs_defs.h │ ├── common.h │ └── kernel_defs.h ├── gecko │ ├── pygecko.h │ └── pygecko.c ├── system │ ├── exception_handler.h │ ├── memory.h │ ├── exception_handler.c │ └── memory.c ├── main.h ├── kernel │ ├── kernel_functions.h │ ├── syscalls_asm.S │ ├── syscalls.h │ ├── kernel_functions.c │ ├── kernel_hooks.S │ └── syscalls.c ├── patcher │ ├── proc_ui_function_patcher.h │ ├── vpad_function_patcher.h │ ├── video_swapping_function_patcher.h │ ├── voice_swapping_function_patcher.h │ ├── gambit_functions.h │ ├── cafiine_function_patcher.h │ ├── proc_ui_function_patcher.cpp │ ├── video_swapping_function_patcher.cpp │ ├── vpad_function_patcher.cpp │ ├── voice_swapping_function_patcher.cpp │ ├── gambit_functions.c │ └── cafiine_function_patcher.cpp ├── entry.c ├── utils │ ├── logger.h │ ├── voice_info.hpp │ ├── logger.c │ ├── function_patcher.h │ ├── voice_swapper.hpp │ └── function_patcher.cpp ├── retain_vars.h ├── link.ld ├── retain_vars.c ├── cafiine │ ├── cafiine.h │ ├── cafiine.c │ └── 550.h └── main.c ├── .gitmodules ├── README.md ├── Makefile └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directory 2 | build/ 3 | 4 | # ELF files 5 | *.elf 6 | -------------------------------------------------------------------------------- /meta/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OatmealDome/SwapDRC/HEAD/meta/icon.png -------------------------------------------------------------------------------- /meta_lite/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OatmealDome/SwapDRC/HEAD/meta_lite/icon.png -------------------------------------------------------------------------------- /src/common/types.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_H 2 | #define TYPES_H 3 | 4 | #include 5 | 6 | #endif /* TYPES_H */ 7 | 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/dynamic_libs"] 2 | path = src/dynamic_libs 3 | url = https://github.com/Maschell/dynamic_libs 4 | -------------------------------------------------------------------------------- /src/gecko/pygecko.h: -------------------------------------------------------------------------------- 1 | #ifndef _PYGECKO_H_ 2 | #define _PYGECKO_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void start_pygecko(void); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* _PYGECKO_H_ */ 15 | -------------------------------------------------------------------------------- /src/system/exception_handler.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXCEPTION_HANDLER_H_ 2 | #define __EXCEPTION_HANDLER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void setup_os_exceptions(void); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H_ 2 | #define _MAIN_H_ 3 | 4 | /* Main */ 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | //! C wrapper for our C++ functions 10 | int Menu_Main(void); 11 | int isInMiiMakerHBL(); 12 | int isInSplatoon(); 13 | void ApplyPatches(); 14 | void RestorePatches(); 15 | void deInit(); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/kernel/kernel_functions.h: -------------------------------------------------------------------------------- 1 | #ifndef __KERNEL_FUNCTIONS_H_ 2 | #define __KERNEL_FUNCTIONS_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "common/kernel_defs.h" 9 | #include "syscalls.h" 10 | 11 | void SetupKernelCallback(void); 12 | 13 | extern ReducedCosAppXmlInfo cosAppXmlInfoStruct; 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif // __KERNEL_FUNCTIONS_H_ 20 | -------------------------------------------------------------------------------- /src/kernel/syscalls_asm.S: -------------------------------------------------------------------------------- 1 | # Created by dimok 2 | # Syscalls for kernel that we use 3 | 4 | .globl SC0x36_KernelReadDBATs 5 | SC0x36_KernelReadDBATs: 6 | li r0, 0x3600 7 | sc 8 | blr 9 | 10 | .globl SC0x37_KernelWriteDBATs 11 | SC0x37_KernelWriteDBATs: 12 | li r0, 0x3700 13 | sc 14 | blr 15 | 16 | .globl SC0x25_KernelCopyData 17 | SC0x25_KernelCopyData: 18 | li r0, 0x2500 19 | sc 20 | blr 21 | -------------------------------------------------------------------------------- /src/patcher/proc_ui_function_patcher.h: -------------------------------------------------------------------------------- 1 | #ifndef _PROC_UI_FUNCTION_PATCHER_H 2 | #define _PROC_UI_FUNCTION_PATCHER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "utils/function_patcher.h" 9 | 10 | extern hooks_magic_t method_hooks_proc_ui[]; 11 | extern u32 method_hooks_size_proc_ui; 12 | extern volatile unsigned int method_calls_proc_ui[]; 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif /* _PROC_UI_FUNCTION_PATCHER_H */ 19 | -------------------------------------------------------------------------------- /src/patcher/vpad_function_patcher.h: -------------------------------------------------------------------------------- 1 | #ifndef _VPAD_FUNCTION_PATCHER_H 2 | #define _VPAD_FUNCTION_PATCHER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "utils/function_patcher.h" 9 | 10 | void drcSwap(); 11 | 12 | extern hooks_magic_t method_hooks_vpad[]; 13 | extern u32 method_hooks_size_vpad; 14 | extern volatile unsigned int method_calls_vpad[]; 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif /* _VPAD_FUNCTION_PATCHER_H */ 21 | -------------------------------------------------------------------------------- /src/entry.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include "retain_vars.h" 3 | 4 | int __entry_menu(int argc, char **argv){ 5 | if(gAppStatus == 2){ 6 | return EXIT_RELAUNCH_ON_LOAD; 7 | } 8 | gAppStatus = 0; 9 | //! ******************************************************************* 10 | //! * Jump to our application * 11 | //! ******************************************************************* 12 | return Menu_Main(); 13 | } 14 | -------------------------------------------------------------------------------- /src/patcher/video_swapping_function_patcher.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIDEO_SWAPPING_FUNCTION_PATCHER_H 2 | #define _VIDEO_SWAPPING_FUNCTION_PATCHER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "utils/function_patcher.h" 9 | 10 | extern hooks_magic_t method_hooks_video_swapping[]; 11 | extern u32 method_hooks_size_video_swapping; 12 | extern volatile unsigned int method_calls_video_swapping[]; 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif /* _VIDEO_SWAPPING_FUNCTION_PATCHER_H */ 19 | -------------------------------------------------------------------------------- /src/utils/logger.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGGER_H_ 2 | #define __LOGGER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //#define DEBUG_LOGGER 1 9 | 10 | #ifdef DEBUG_LOGGER 11 | void log_init(const char * ip); 12 | void log_deinit(void); 13 | void log_print(const char *str); 14 | void log_printf(const char *format, ...); 15 | #else 16 | #define log_init(x) 17 | #define log_deinit() 18 | #define log_print(x) 19 | #define log_printf(x, ...) 20 | #endif 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/patcher/voice_swapping_function_patcher.h: -------------------------------------------------------------------------------- 1 | #ifndef _VOICE_SWAPPING_FUNCTION_PATCHER_H 2 | #define _VOICE_SWAPPING_FUNCTION_PATCHER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "utils/function_patcher.h" 9 | 10 | void swapVoices(); 11 | 12 | extern hooks_magic_t method_hooks_voice_swapping[]; 13 | extern u32 method_hooks_size_voice_swapping; 14 | extern volatile unsigned int method_calls_voice_swapping[]; 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif /* _VOICE_SWAPPING_FUNCTION_PATCHER_H */ 21 | -------------------------------------------------------------------------------- /src/patcher/gambit_functions.h: -------------------------------------------------------------------------------- 1 | #ifndef _GAMBIT_FUNCTIONS_H_ 2 | #define _GAMBIT_FUNCTIONS_H_ 3 | 4 | #include "dynamic_libs/vpad_functions.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef enum GambitDPAD 11 | { 12 | D_NEUTRAL, 13 | D_LEFT, 14 | D_UP, 15 | D_RIGHT, 16 | D_DOWN 17 | } GambitDPAD; 18 | 19 | extern void gambitDRC(void); 20 | extern void gambitJump(VPADData *buffer); 21 | extern void gambitTouch(VPADTPData *screen); 22 | extern void gambitPatches(VPADData *buffer); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif /* _GAMBIT_FUNCTIONS_H_ */ 29 | -------------------------------------------------------------------------------- /src/common/os_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef __OS_DEFS_H_ 2 | #define __OS_DEFS_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct _OsSpecifics 9 | { 10 | unsigned int addr_OSDynLoad_Acquire; 11 | unsigned int addr_OSDynLoad_FindExport; 12 | unsigned int addr_OSTitle_main_entry; 13 | 14 | unsigned int addr_KernSyscallTbl1; 15 | unsigned int addr_KernSyscallTbl2; 16 | unsigned int addr_KernSyscallTbl3; 17 | unsigned int addr_KernSyscallTbl4; 18 | unsigned int addr_KernSyscallTbl5; 19 | } OsSpecifics; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif // __OS_DEFS_H_ 26 | -------------------------------------------------------------------------------- /src/patcher/cafiine_function_patcher.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAFIINE_FUNCTION_PATCHER_H 2 | #define _CAFIINE_FUNCTION_PATCHER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "utils/function_patcher.h" 9 | #include "cafiine/cafiine.h" 10 | 11 | struct fs_patcher_utils { 12 | int socket_fsa[MAX_CLIENT]; 13 | void *pClient_fs[MAX_CLIENT]; 14 | int socket_fs[MAX_CLIENT]; 15 | volatile int lock; 16 | }; 17 | 18 | extern hooks_magic_t method_hooks_cafiine[]; 19 | extern u32 method_hooks_size_cafiine; 20 | extern volatile unsigned int method_calls_cafiine[]; 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* _CAFIINE_FUNCTION_PATCHER_H */ 27 | -------------------------------------------------------------------------------- /src/kernel/syscalls.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __SYSCALLS_H_ 3 | #define __SYSCALLS_H_ 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #include 10 | #include "common/kernel_defs.h" 11 | 12 | void KernelSetupSyscalls(void); 13 | void KernelRestoreInstructions(void); 14 | 15 | void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len); 16 | void SC0x36_KernelReadDBATs(bat_table_t * table); 17 | void SC0x37_KernelWriteDBATs(bat_table_t * table); 18 | 19 | uint32_t __attribute__ ((noinline)) kern_read(const void *addr); 20 | void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif // __KERNEL_FUNCTIONS_H_ 27 | -------------------------------------------------------------------------------- /meta_lite/meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SwapDRC Lite 4 | OatmealDome and Yahya14 5 | https://gbatemp.net/threads/swap-drc-for-tv-only-wii-u-games.478026/#post-7458492 6 | 1.3.2 7 | 201707190000000 8 | Switch TV display onto the gamepad 9 | Switch Display, Audio, and Gamepad Sensor Bar: 10 | - Press the TV button. 11 | 12 | Switch on/off Gamepad LCD: 13 | - Press and hold R-Stick for 3-6 seconds. 14 | 15 | Special thanks to: Maschell, dimok, NWPlayer123, Brienj, and BKOOL999. 16 | 17 | tool 18 | 19 | -------------------------------------------------------------------------------- /meta/meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SwapDRC 4 | OatmealDome and Yahya14 5 | https://gbatemp.net/threads/swap-drc-for-tv-only-wii-u-games.478026/#post-7458492 6 | 1.3.2 7 | 201707190000000 8 | Switch TV display onto the gamepad 9 | This tool installs SwapDRC, Padcon, TCPGecko and/or Cafiine into system memory. 10 | 11 | Switch the TV and gamepad display and the DRC sensor bar by holding the L shoulder button and then press MINUS. Pressing the TV button also works. 12 | 13 | Special thanks to: Maschell, dimok, NWPlayer123, Brienj, and BKOOL999. 14 | 15 | tool 16 | 17 | -------------------------------------------------------------------------------- /src/retain_vars.h: -------------------------------------------------------------------------------- 1 | #ifndef _RETAIN_VARS_H_ 2 | #define _RETAIN_VARS_H_ 3 | 4 | //for pre-compiling the app 5 | #define LITE 0 // 0 = default, 1 = lite version (no tcpgecko and cafiine) 6 | 7 | 8 | #include "common/types.h" 9 | #include "utils/voice_info.hpp" 10 | #include "patcher/cafiine_function_patcher.h" 11 | 12 | extern struct fs_patcher_utils fspatchervars __attribute__((section(".data"))); 13 | 14 | extern int isSplatoon; 15 | extern int drcMode; 16 | extern uint32_t gAppStatus; 17 | extern int gCoolDown; 18 | extern int gLCDDelay; 19 | extern s32 gLCDMode; 20 | 21 | extern uint32_t cafiine_addr; 22 | 23 | // AX 24 | extern VoiceInfo gVoiceInfos[VOICE_INFO_MAX]; 25 | 26 | // for Splatoon 27 | extern u8 gSwapForce; 28 | 29 | extern uint32_t* gamemode; 30 | extern uint32_t* inkstrikeEq; 31 | extern uint32_t* spTimer; 32 | 33 | extern uint32_t incrementVal; 34 | extern uint32_t* incrementPtr; 35 | extern uint32_t* PCtrlPtr; 36 | 37 | #endif // _RETAIN_VARS_H_ 38 | -------------------------------------------------------------------------------- /src/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT(ddd.elf); 2 | 3 | /* Tell linker where our application entry is so the garbage collect can work correct */ 4 | ENTRY(__entry_menu); 5 | 6 | SECTIONS { 7 | . = 0x00802000; 8 | .text : { 9 | *(.kernel_code*); 10 | *(.text*); 11 | /* Tell linker to not garbage collect this section as it is not referenced anywhere */ 12 | KEEP(*(.kernel_code*)); 13 | } 14 | .rodata : { 15 | *(.rodata*); 16 | } 17 | .data : { 18 | *(.data*); 19 | 20 | __sdata_start = .; 21 | *(.sdata*); 22 | __sdata_end = .; 23 | 24 | __sdata2_start = .; 25 | *(.sdata2*); 26 | __sdata2_end = .; 27 | } 28 | .bss : { 29 | __bss_start = .; 30 | *(.bss*); 31 | *(.sbss*); 32 | *(COMMON); 33 | __bss_end = .; 34 | } 35 | __CODE_END = .; 36 | 37 | /DISCARD/ : { 38 | *(*); 39 | } 40 | } 41 | 42 | /******************************************************** FS ********************************************************/ 43 | /* coreinit.rpl difference in addresses 0xFE3C00 */ 44 | -------------------------------------------------------------------------------- /src/common/loader_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOADER_DEFS_H_ 2 | #define __LOADER_DEFS_H_ 3 | 4 | #include "types.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // struct holding the globals of the loader (there are actually more but we don't need others) 11 | typedef struct _loader_globals_t 12 | { 13 | int sgIsLoadingBuffer; 14 | int sgFileType; 15 | int sgProcId; 16 | int sgGotBytes; 17 | int sgFileOffset; 18 | int sgBufferNumber; 19 | int sgBounceError; 20 | char sgLoadName[0x1000]; 21 | } __attribute__((packed)) loader_globals_t; 22 | 23 | typedef struct _loader_globals_550_t 24 | { 25 | int sgFinishedLoadingBuffer; 26 | int sgFileType; 27 | int sgProcId; 28 | int sgGotBytes; 29 | int sgTotalBytes; 30 | int sgFileOffset; 31 | int sgBufferNumber; 32 | int sgBounceError; 33 | char sgLoadName[0x1000]; 34 | } __attribute__((packed)) loader_globals_550_t; 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #endif // __LOADER_DEFS_H_ 41 | -------------------------------------------------------------------------------- /src/patcher/proc_ui_function_patcher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "proc_ui_function_patcher.h" 5 | #include "utils/logger.h" 6 | #include "retain_vars.h" 7 | 8 | //PROCUI FUNCTIONS 9 | DECL(u32, ProcUIProcessMessages, u32 u) { 10 | u32 res = real_ProcUIProcessMessages(u); 11 | if(res != gAppStatus){ 12 | log_printf("App status changed from %d to %d \n",gAppStatus,res); 13 | gAppStatus = res; 14 | } 15 | return res; 16 | } 17 | 18 | hooks_magic_t method_hooks_proc_ui[] __attribute__((section(".data"))) = { 19 | MAKE_MAGIC(ProcUIProcessMessages, LIB_PROC_UI, DYNAMIC_FUNCTION), 20 | }; 21 | u32 method_hooks_size_proc_ui __attribute__((section(".data"))) = sizeof(method_hooks_proc_ui) / sizeof(hooks_magic_t); 22 | 23 | //! buffer to store our instructions needed for our replacements 24 | volatile unsigned int method_calls_proc_ui[sizeof(method_hooks_proc_ui) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data"))); 25 | -------------------------------------------------------------------------------- /src/retain_vars.c: -------------------------------------------------------------------------------- 1 | #include "common/types.h" 2 | #include "retain_vars.h" 3 | #include "patcher/cafiine_function_patcher.h" 4 | 5 | int isSplatoon __attribute__((section(".data"))) = 0; 6 | int drcMode __attribute__((section(".data"))) = 0; 7 | uint32_t gAppStatus __attribute__((section(".data"))) = 0; 8 | int gCoolDown __attribute__((section(".data"))) = 0; 9 | int gLCDDelay __attribute__((section(".data"))) = 0; 10 | s32 gLCDMode __attribute__((section(".data"))) = 0xFF; 11 | 12 | uint32_t cafiine_addr __attribute__((section(".data"))) = 0; 13 | VoiceInfo gVoiceInfos[VOICE_INFO_MAX] __attribute__((section(".data"))); 14 | struct fs_patcher_utils fspatchervars __attribute__((section(".data"))); 15 | 16 | // for Splatoon 17 | u8 gSwapForce __attribute__((section(".data"))) = 0; 18 | uint32_t* gamemode __attribute__((section(".data"))) = (uint32_t*)0; 19 | uint32_t* inkstrikeEq __attribute__((section(".data"))) = (uint32_t*)0x10000000; 20 | uint32_t* spTimer __attribute__((section(".data"))) = (uint32_t*)0x10000000; 21 | 22 | uint32_t incrementVal __attribute__((section(".data"))) = (uint32_t)0; 23 | uint32_t* incrementPtr __attribute__((section(".data"))) = (uint32_t*)0x10000000; 24 | uint32_t* PCtrlPtr __attribute__((section(".data"))) = (uint32_t*)0x10000000; 25 | -------------------------------------------------------------------------------- /src/utils/voice_info.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2017 Maschell 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ****************************************************************************/ 17 | #ifndef _VOICE_INFO_H_ 18 | #define _VOICE_INFO_H_ 19 | #include 20 | 21 | #define VOICE_INFO_MAX 100 22 | 23 | typedef struct _VoiceInfo { 24 | void* voice; /**< Pointer to the voice */ 25 | u32 mixTV[24]; /**< Mix to the TV */ 26 | u32 mixDRC[24]; /**< Mix of the DRC */ 27 | } VoiceInfo; 28 | 29 | #endif //_VOICE_INFO_H_ 30 | -------------------------------------------------------------------------------- /src/cafiine/cafiine.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAFIINE_H_ 2 | #define _CAFIINE_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define MAX_CLIENT 32 9 | 10 | #define CHECK_ERROR(cond) if (cond) { goto error; } 11 | 12 | #define MASK_FD 0x0fff00ff 13 | 14 | #define BYTE_NORMAL 0xff 15 | #define BYTE_SPECIAL 0xfe 16 | #define BYTE_OPEN 0x00 17 | #define BYTE_READ 0x01 18 | #define BYTE_CLOSE 0x02 19 | #define BYTE_OK 0x03 20 | #define BYTE_SETPOS 0x04 21 | #define BYTE_STATFILE 0x05 22 | #define BYTE_EOF 0x06 23 | #define BYTE_GETPOS 0x07 24 | 25 | void cafiine_connect(void *pClient, int clientId, int isFSA); 26 | void cafiine_disconnect(void *pClient, int clientId, int isFSA); 27 | int cafiine_handshake(int sock); 28 | int cafiine_fopen(void* pClient, int clientId, int *result, const char *path, const char *mode, int *handle, int isFSA); 29 | int cafiine_fread(void* pClient, int *result, void *buffer, int size, int count, int fd); 30 | int cafiine_fclose(void* pClient, int *result, int fd); 31 | int cafiine_fsetpos(void* pClient, int *result, int fd, int set); 32 | int cafiine_fgetpos(void* pClient, int *result, int fd, int *pos); 33 | int cafiine_fstat(void* pClient, int *result, int fd, void *ptr); 34 | int cafiine_feof(void* pClient, int *result, int fd); 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #endif // _CAFIINE_H_ 41 | -------------------------------------------------------------------------------- /src/system/memory.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 Dimok 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ****************************************************************************/ 17 | #ifndef __MEMORY_H_ 18 | #define __MEMORY_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include 25 | 26 | void memoryInitialize(void); 27 | void memoryRelease(void); 28 | 29 | void * MEM2_alloc(u32 size, u32 align); 30 | void MEM2_free(void *ptr); 31 | 32 | void * MEM1_alloc(u32 size, u32 align); 33 | void MEM1_free(void *ptr); 34 | 35 | void * MEMBucket_alloc(u32 size, u32 align); 36 | void MEMBucket_free(void *ptr); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif // __MEMORY_H_ 43 | -------------------------------------------------------------------------------- /src/patcher/video_swapping_function_patcher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "video_swapping_function_patcher.h" 5 | #include "utils/logger.h" 6 | #include "retain_vars.h" 7 | 8 | // GX2 FUNCTIONS 9 | DECL(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, s32 scan_target) { 10 | // GX2 destinations: 11 | // 0x1 = TV 12 | // 0x4 = 1st GamePad 13 | 14 | // drcMode values: 15 | // 0x0 = normal 16 | // 0x1 = swap 17 | 18 | // check drc swap and force the drcMode to default when inkstrike is activated 19 | if (drcMode == 0 || gSwapForce || gAppStatus == 2) { 20 | real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); 21 | } 22 | else { 23 | switch (scan_target) 24 | { 25 | case 0x1: 26 | real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x4); 27 | break; 28 | case 0x4: 29 | real_GX2CopyColorBufferToScanBuffer(colorBuffer, 0x1); 30 | break; 31 | } 32 | } 33 | } 34 | 35 | hooks_magic_t method_hooks_video_swapping[] __attribute__((section(".data"))) = { 36 | MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION), 37 | }; 38 | u32 method_hooks_size_video_swapping __attribute__((section(".data"))) = sizeof(method_hooks_video_swapping) / sizeof(hooks_magic_t); 39 | 40 | //! buffer to store our instructions needed for our replacements 41 | volatile unsigned int method_calls_video_swapping[sizeof(method_hooks_video_swapping) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data"))); 42 | -------------------------------------------------------------------------------- /src/common/fs_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_DEFS_H 2 | #define FS_DEFS_H 3 | 4 | #include "types.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | 11 | /* FS defines and types */ 12 | #define FS_MAX_LOCALPATH_SIZE 511 13 | #define FS_MAX_MOUNTPATH_SIZE 128 14 | #define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE) 15 | #define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE 16 | 17 | #define FS_STATUS_OK 0 18 | #define FS_RET_UNSUPPORTED_CMD 0x0400 19 | #define FS_RET_NO_ERROR 0x0000 20 | #define FS_RET_ALL_ERROR (unsigned int)(-1) 21 | 22 | #define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 23 | 24 | /* max length of file/dir name */ 25 | #define FS_MAX_ENTNAME_SIZE 256 26 | 27 | #define FS_SOURCETYPE_EXTERNAL 0 28 | #define FS_SOURCETYPE_HFIO 1 29 | #define FS_SOURCETYPE_HFIO 1 30 | 31 | #define FS_STATUS_OK 0 32 | #define FS_STATUS_EXISTS -5 33 | #define FS_STATUS_STORAGE_FULL -12 34 | #define FS_STATUS_JOURNAL_FULL -13 35 | 36 | #define FS_MOUNT_SOURCE_SIZE 0x300 37 | #define FS_CLIENT_SIZE 0x1700 38 | #define FS_CMD_BLOCK_SIZE 0xA80 39 | 40 | typedef struct 41 | { 42 | uint32_t flag; 43 | uint32_t permission; 44 | uint32_t owner_id; 45 | uint32_t group_id; 46 | uint32_t size; 47 | uint32_t alloc_size; 48 | uint64_t quota_size; 49 | uint32_t ent_id; 50 | uint64_t ctime; 51 | uint64_t mtime; 52 | uint8_t attributes[48]; 53 | } __attribute__((packed)) FSStat; 54 | 55 | typedef struct 56 | { 57 | FSStat stat; 58 | char name[FS_MAX_ENTNAME_SIZE]; 59 | } FSDirEntry; 60 | 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* FS_DEFS_H */ 67 | 68 | -------------------------------------------------------------------------------- /src/utils/logger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common/common.h" 7 | #include "dynamic_libs/os_functions.h" 8 | #include "dynamic_libs/socket_functions.h" 9 | #include "logger.h" 10 | 11 | #ifdef DEBUG_LOGGER 12 | static int log_socket = -1; 13 | static volatile int log_lock = 0; 14 | 15 | 16 | void log_init(const char * ipString) 17 | { 18 | log_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 19 | if (log_socket < 0) 20 | return; 21 | 22 | struct sockaddr_in connect_addr; 23 | memset(&connect_addr, 0, sizeof(connect_addr)); 24 | connect_addr.sin_family = AF_INET; 25 | connect_addr.sin_port = 4405; 26 | inet_aton(ipString, &connect_addr.sin_addr); 27 | 28 | if(connect(log_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0) 29 | { 30 | socketclose(log_socket); 31 | log_socket = -1; 32 | } 33 | } 34 | 35 | void log_deinit(void) 36 | { 37 | if(log_socket >= 0) 38 | { 39 | socketclose(log_socket); 40 | log_socket = -1; 41 | } 42 | } 43 | 44 | void log_print(const char *str) 45 | { 46 | // socket is always 0 initially as it is in the BSS 47 | if(log_socket < 0) { 48 | return; 49 | } 50 | 51 | while(log_lock) 52 | os_usleep(1000); 53 | log_lock = 1; 54 | 55 | int len = strlen(str); 56 | int ret; 57 | while (len > 0) { 58 | int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet 59 | ret = send(log_socket, str, block, 0); 60 | if(ret < 0) 61 | break; 62 | 63 | len -= ret; 64 | str += ret; 65 | } 66 | 67 | log_lock = 0; 68 | } 69 | 70 | void log_printf(const char *format, ...) 71 | { 72 | if(log_socket < 0) { 73 | return; 74 | } 75 | 76 | char * tmp = NULL; 77 | 78 | va_list va; 79 | va_start(va, format); 80 | if((vasprintf(&tmp, format, va) >= 0) && tmp) 81 | { 82 | log_print(tmp); 83 | } 84 | va_end(va); 85 | 86 | if(tmp) 87 | free(tmp); 88 | } 89 | #endif 90 | -------------------------------------------------------------------------------- /src/common/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "os_defs.h" 9 | 10 | #define CAFE_OS_SD_PATH "/vol/external01" 11 | #define SD_PATH "sd:" 12 | #define WIIU_PATH "/wiiu" 13 | 14 | /* Macros for libs */ 15 | #define LIB_CORE_INIT 0 16 | #define LIB_NSYSNET 1 17 | #define LIB_GX2 2 18 | #define LIB_AOC 3 19 | #define LIB_AX 4 20 | #define LIB_FS 5 21 | #define LIB_OS 6 22 | #define LIB_PADSCORE 7 23 | #define LIB_SOCKET 8 24 | #define LIB_SYS 9 25 | #define LIB_VPAD 10 26 | #define LIB_NN_ACP 11 27 | #define LIB_SYSHID 12 28 | #define LIB_VPADBASE 13 29 | #define LIB_AX_OLD 14 30 | #define LIB_PROC_UI 15 31 | 32 | // functions types 33 | #define STATIC_FUNCTION 0 34 | #define DYNAMIC_FUNCTION 1 35 | 36 | // none dynamic libs 37 | #define LIB_LOADER 0x1001 38 | 39 | #ifndef MEM_BASE 40 | #define MEM_BASE (0x00800000) 41 | #endif 42 | 43 | #define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00)) 44 | #define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04)) 45 | #define MAIN_ENTRY_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00)) 46 | #define OS_FIRMWARE (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x04)) 47 | 48 | #define OS_SPECIFICS ((OsSpecifics*)(MEM_BASE + 0x1500)) 49 | 50 | #ifndef EXIT_SUCCESS 51 | #define EXIT_SUCCESS 0 52 | #endif 53 | #define EXIT_HBL_EXIT 0xFFFFFFFE 54 | #define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD 55 | 56 | #define RESTORE_INSTR_MAGIC 0xC001C0DE 57 | #define RESTORE_INSTR_ADDR ((restore_instructions_t*)(MEM_BASE + 0x1600)) 58 | 59 | typedef struct _restore_instructions_t { 60 | unsigned int magic; 61 | unsigned int instr_count; 62 | struct { 63 | unsigned int addr; 64 | unsigned int instr; 65 | } data[0]; 66 | } restore_instructions_t; 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif /* COMMON_H */ 73 | 74 | -------------------------------------------------------------------------------- /src/kernel/kernel_functions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "common/common.h" 3 | #include "common/kernel_defs.h" 4 | #include "kernel/kernel_functions.h" 5 | #include "kernel/syscalls.h" 6 | 7 | /* our retain data */ 8 | ReducedCosAppXmlInfo cosAppXmlInfoStruct __attribute__((section(".data"))); 9 | /* 10 | * This function is a kernel hook function. It is called directly from kernel code at position 0xFFF18558. 11 | */ 12 | void my_PrepareTitle(CosAppXmlInfo *xmlKernelInfo) 13 | { 14 | /** 15 | * DBAT for access to our data region is setup at this point for the 0xC0000000 area. 16 | */ 17 | 18 | //! Copy all data from the XML info 19 | strncpy(cosAppXmlInfoStruct.rpx_name, xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE); 20 | 21 | cosAppXmlInfoStruct.version_cos_xml = xmlKernelInfo->version_cos_xml; 22 | cosAppXmlInfoStruct.os_version = xmlKernelInfo->os_version; 23 | cosAppXmlInfoStruct.title_id = xmlKernelInfo->title_id; 24 | cosAppXmlInfoStruct.app_type = xmlKernelInfo->app_type; 25 | cosAppXmlInfoStruct.cmdFlags = xmlKernelInfo->cmdFlags; 26 | cosAppXmlInfoStruct.max_size = xmlKernelInfo->max_size; 27 | cosAppXmlInfoStruct.avail_size = xmlKernelInfo->avail_size; 28 | cosAppXmlInfoStruct.codegen_size = xmlKernelInfo->codegen_size; 29 | cosAppXmlInfoStruct.codegen_core = xmlKernelInfo->codegen_core; 30 | cosAppXmlInfoStruct.max_codesize = xmlKernelInfo->max_codesize; 31 | cosAppXmlInfoStruct.overlay_arena = xmlKernelInfo->overlay_arena; 32 | cosAppXmlInfoStruct.default_stack0_size = xmlKernelInfo->default_stack0_size; 33 | cosAppXmlInfoStruct.default_stack1_size = xmlKernelInfo->default_stack1_size; 34 | cosAppXmlInfoStruct.default_stack2_size = xmlKernelInfo->default_stack2_size; 35 | cosAppXmlInfoStruct.default_redzone0_size = xmlKernelInfo->default_redzone0_size; 36 | cosAppXmlInfoStruct.default_redzone1_size = xmlKernelInfo->default_redzone1_size; 37 | cosAppXmlInfoStruct.default_redzone2_size = xmlKernelInfo->default_redzone2_size; 38 | cosAppXmlInfoStruct.exception_stack0_size = xmlKernelInfo->exception_stack0_size; 39 | cosAppXmlInfoStruct.exception_stack1_size = xmlKernelInfo->exception_stack1_size; 40 | cosAppXmlInfoStruct.exception_stack2_size = xmlKernelInfo->exception_stack2_size; 41 | cosAppXmlInfoStruct.sdk_version = xmlKernelInfo->sdk_version; 42 | cosAppXmlInfoStruct.title_version = xmlKernelInfo->title_version; 43 | } 44 | 45 | void SetupKernelCallback(void) 46 | { 47 | KernelSetupSyscalls(); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/utils/function_patcher.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2016 Maschell 3 | * With code from chadderz and dimok 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | ****************************************************************************/ 18 | 19 | #ifndef _FUNCTION_HOOKS_H_ 20 | #define _FUNCTION_HOOKS_H_ 21 | 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | #include 28 | #include "common/common.h" 29 | #include "dynamic_libs/aoc_functions.h" 30 | #include "dynamic_libs/ax_functions.h" 31 | #include "dynamic_libs/fs_functions.h" 32 | #include "dynamic_libs/gx2_functions.h" 33 | #include "dynamic_libs/os_functions.h" 34 | #include "dynamic_libs/padscore_functions.h" 35 | #include "dynamic_libs/socket_functions.h" 36 | #include "dynamic_libs/sys_functions.h" 37 | #include "dynamic_libs/vpad_functions.h" 38 | #include "dynamic_libs/acp_functions.h" 39 | #include "dynamic_libs/syshid_functions.h" 40 | #include "dynamic_libs/proc_ui_functions.h" 41 | 42 | //Orignal code by Chadderz. 43 | #define DECL(res, name, ...) \ 44 | res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \ 45 | res my_ ## name(__VA_ARGS__) 46 | 47 | #define FUNCTION_PATCHER_METHOD_STORE_SIZE 7 48 | 49 | typedef struct { 50 | const unsigned int replaceAddr; 51 | const unsigned int replaceCall; 52 | const unsigned int library; 53 | const char functionName[50]; 54 | unsigned int realAddr; 55 | unsigned int restoreInstruction; 56 | unsigned char functionType; 57 | unsigned char alreadyPatched; 58 | } hooks_magic_t; 59 | 60 | void PatchInvidualMethodHooks(hooks_magic_t hook_information[],int hook_information_size, volatile unsigned int dynamic_method_calls[]); 61 | void RestoreInvidualInstructions(hooks_magic_t hook_information[],int hook_information_size); 62 | unsigned int GetAddressOfFunction(const char * functionName,unsigned int library); 63 | int isDynamicFunction(unsigned int physicalAddress); 64 | 65 | //Orignal code by Chadderz. 66 | #define MAKE_MAGIC(x, lib,functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x,0,0,functionType,0} 67 | #define MAKE_MAGIC_NAME(x,y, lib,functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # y,0,0,functionType,0} 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | #endif /* _FS_H */ 74 | -------------------------------------------------------------------------------- /src/patcher/vpad_function_patcher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "vpad_function_patcher.h" 5 | #include "voice_swapping_function_patcher.h" 6 | #include "gambit_functions.h" 7 | #include "utils/logger.h" 8 | #include "retain_vars.h" 9 | 10 | //VPAD FUNCTIONS 11 | DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) { 12 | int result = real_VPADRead(chan, buffer, buffer_size, error); 13 | if(result <= 0) return result; 14 | 15 | #if !LITE 16 | // switch on L and SELECT 17 | if ((buffer[0].btns_h & (VPAD_BUTTON_MINUS | VPAD_BUTTON_L)) == (VPAD_BUTTON_MINUS | VPAD_BUTTON_L) && 18 | gAppStatus != 2) { 19 | if (buffer->btns_d & (VPAD_BUTTON_MINUS | VPAD_BUTTON_L)) { 20 | drcSwap(); 21 | } 22 | } 23 | #endif 24 | 25 | // switch on TV button 26 | if (buffer[0].btns_h & VPAD_BUTTON_TV && (gCoolDown == 0 && gAppStatus != 2)) { 27 | gCoolDown = 0x1F; 28 | drcSwap(); 29 | } 30 | else if (gCoolDown > 0) { 31 | gCoolDown--; 32 | } 33 | 34 | // switch on/off gamepad screen 35 | if (buffer[0].btns_d & VPAD_BUTTON_STICK_R && gLCDMode != 0xFF) { 36 | VPADSetLcdMode(0, gLCDMode = 0xFF); // Turn it on 37 | } 38 | else if (buffer[0].btns_h & VPAD_BUTTON_STICK_R) { 39 | if (gLCDDelay == 0xB0) { 40 | if (gLCDMode != 1) { 41 | VPADSetLcdMode(0, gLCDMode = 1); // Turn it off 42 | } 43 | else { 44 | VPADSetLcdMode(0, gLCDMode = 0xFF); // Turn it on 45 | } 46 | 47 | // reset delay 48 | gLCDDelay = 0; 49 | } 50 | gLCDDelay++; 51 | } 52 | else { 53 | gLCDDelay = 0; 54 | } 55 | 56 | 57 | // patches splatoon enhanced controls 58 | if (isSplatoon) { 59 | gambitPatches(buffer); 60 | gambitDRC(); 61 | } 62 | 63 | return result; 64 | } 65 | 66 | DECL(void, VPADGetTPCalibratedPoint, int chan, VPADTPData *screen, VPADTPData *raw) { 67 | real_VPADGetTPCalibratedPoint(chan, screen, raw); 68 | 69 | if (isSplatoon) { 70 | // handles modified touch input for super jumps 71 | gambitTouch(screen); 72 | } 73 | } 74 | 75 | DECL(void, VPADSetSensorBar, s32 chan, bool on){ 76 | real_VPADSetSensorBar(chan, on); 77 | } 78 | 79 | void drcSwap() { 80 | log_printf("Swapping Screens!\n"); 81 | // swap drc modes 82 | drcMode = !drcMode; 83 | 84 | // swap audio 85 | swapVoices(); 86 | 87 | // enable/disable sensor bar 88 | real_VPADSetSensorBar(0, drcMode); 89 | } 90 | 91 | hooks_magic_t method_hooks_vpad[] __attribute__((section(".data"))) = { 92 | MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION), 93 | MAKE_MAGIC(VPADGetTPCalibratedPoint, LIB_VPAD, STATIC_FUNCTION), 94 | MAKE_MAGIC(VPADSetSensorBar, LIB_VPAD, STATIC_FUNCTION), 95 | }; 96 | u32 method_hooks_size_vpad __attribute__((section(".data"))) = sizeof(method_hooks_vpad) / sizeof(hooks_magic_t); 97 | 98 | //! buffer to store our instructions needed for our replacements 99 | volatile unsigned int method_calls_vpad[sizeof(method_hooks_vpad) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data"))); 100 | -------------------------------------------------------------------------------- /src/utils/voice_swapper.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2017 Maschell 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ****************************************************************************/ 17 | #ifndef _VOICE_SWAPPER_H_ 18 | #define _VOICE_SWAPPER_H_ 19 | #define VOICE_SWAP_LOG 0 20 | #include "voice_info.hpp" 21 | #include "retain_vars.h" 22 | 23 | #include "utils/logger.h" 24 | 25 | #include "dynamic_libs/os_functions.h" 26 | #include 27 | #include 28 | 29 | class VoiceSwapper{ 30 | 31 | public: 32 | static void acquireVoice(void * voice){ 33 | for(int i = 0;i 2 | #include 3 | #include 4 | #include "voice_swapping_function_patcher.h" 5 | #include "utils/voice_swapper.hpp" 6 | #include "utils/logger.h" 7 | #include "retain_vars.h" 8 | 9 | DECL(s32, AXSetVoiceDeviceMixOld, void *v, s32 device, u32 id, void *mix){ 10 | if (drcMode) device = (device == 1) ? 0 : 1; 11 | if(VOICE_SWAP_LOG == 1){log_printf("AXSetVoiceDeviceMixOld voice: %08X device: %d, mix: %08X\n",v,device,mix);} 12 | VoiceSwapper::setMix(v,device,mix); 13 | return real_AXSetVoiceDeviceMixOld(v,device,id,mix); 14 | } 15 | 16 | DECL(s32, AXSetVoiceDeviceMix, void *v, s32 device, u32 id, void *mix){ 17 | if (drcMode) device = (device == 1) ? 0 : 1; 18 | if(VOICE_SWAP_LOG == 1){log_printf("AXSetVoiceDeviceMix voice: %08X device: %d, mix: %08X\n",v,device,mix);} 19 | VoiceSwapper::setMix(v,device,mix); 20 | return real_AXSetVoiceDeviceMix(v,device,id,mix); 21 | } 22 | 23 | DECL(void *, AXAcquireVoiceExOld, u32 prio, void * callback, u32 arg){ 24 | void * result = real_AXAcquireVoiceExOld(prio,callback,arg); 25 | if(VOICE_SWAP_LOG == 1){log_printf("AXAcquireVoiceExOld result: %08X \n",result);} 26 | VoiceSwapper::acquireVoice(result); 27 | return result; 28 | } 29 | 30 | DECL(void *, AXAcquireVoiceEx, u32 prio, void * callback, u32 arg){ 31 | void * result = real_AXAcquireVoiceEx(prio,callback,arg); 32 | if(VOICE_SWAP_LOG == 1){log_printf("AXAcquireVoiceEx result: %08X \n",result);} 33 | VoiceSwapper::acquireVoice(result); 34 | return result; 35 | } 36 | 37 | DECL(void, AXFreeVoiceOld, void *v){ 38 | if(VOICE_SWAP_LOG == 1){log_printf("AXFreeVoiceOld v: %08X \n",v);} 39 | VoiceSwapper::freeVoice(v); 40 | real_AXFreeVoiceOld(v); 41 | } 42 | 43 | DECL(void, AXFreeVoice, void *v){ 44 | if(VOICE_SWAP_LOG == 1){log_printf("AXFreeVoice v: %08X \n",v);} 45 | VoiceSwapper::freeVoice(v); 46 | real_AXFreeVoice(v); 47 | } 48 | 49 | /** 50 | We do this here because we need the real_ addresses. Not clean code, but the easiest way to do it :> 51 | **/ 52 | void swapVoices(){ 53 | VoiceSwapper::swapAll(); 54 | for(int i = 0;i 2 | #include 3 | #include "dynamic_libs/vpad_functions.h" 4 | #include "patcher/vpad_function_patcher.h" 5 | #include "retain_vars.h" 6 | #include "utils/logger.h" 7 | #include "gambit_functions.h" 8 | 9 | uint32_t* ptr = (uint32_t*)0x106E46E8; 10 | uint32_t* ptr2 = (uint32_t*)0x106E4DA8; 11 | bool AButton = 0; 12 | int touchVal = 0; 13 | 14 | void gambitDRC() 15 | { 16 | if (*inkstrikeEq == 2 && *spTimer != 0) 17 | gSwapForce = 1; 18 | else if (AButton) 19 | gSwapForce = 1; 20 | else 21 | gSwapForce = 0; 22 | } 23 | 24 | void gambitTouch(VPADTPData *screen) 25 | { 26 | switch (touchVal) 27 | { 28 | case D_LEFT: 29 | screen->x = 1080; 30 | screen->y = 130; 31 | screen->touched = 1; 32 | screen->invalid = 0; 33 | break; 34 | case D_UP: 35 | screen->x = 1080; 36 | screen->y = 290; 37 | screen->touched = 1; 38 | screen->invalid = 0; 39 | break; 40 | case D_RIGHT: 41 | screen->x = 1080; 42 | screen->y = 450; 43 | screen->touched = 1; 44 | screen->invalid = 0; 45 | break; 46 | case D_DOWN: 47 | screen->x = 1170; 48 | screen->y = 625; 49 | screen->touched = 1; 50 | screen->invalid = 0; 51 | break; 52 | case D_NEUTRAL: 53 | // disable touchscreen input if the TV is on the DRC for Splatoon enhanced controls 54 | if ((drcMode == 0 || gSwapForce)) {} 55 | else if (gAppStatus != 2) 56 | { 57 | screen->touched = 0; 58 | } 59 | break; 60 | } 61 | } 62 | 63 | void gambitPatches(VPADData *buffer) 64 | { 65 | // prevents the game from crashing 66 | if (*ptr < 0x1C000000) 67 | { 68 | inkstrikeEq = (uint32_t*)0x10000000; 69 | spTimer = (uint32_t*)0x10000000; 70 | incrementPtr = (uint32_t*)0x10000000; 71 | PCtrlPtr = (uint32_t*)0x10000000; 72 | } 73 | else 74 | { 75 | // define pointers 76 | if (gamemode == (uint32_t*)0) 77 | { 78 | uint32_t firstBase = *(uint32_t*)0x106A3BA0; 79 | if (firstBase > 0x10000000 && firstBase < 0x11000000) 80 | { 81 | uint32_t secondBase = *(uint32_t*)(firstBase + 0xD074); 82 | if (secondBase > 0x12000000 && secondBase < 0x14000000) 83 | { 84 | gamemode = (uint32_t*)(secondBase + 0x238); 85 | } 86 | } 87 | } 88 | 89 | inkstrikeEq = (uint32_t*)(*ptr + 0x80); 90 | spTimer = (uint32_t*)(*ptr + 0x808); 91 | incrementPtr = (uint32_t*)(*ptr + 0x150); 92 | PCtrlPtr = (uint32_t*)(*ptr + 0x798); 93 | 94 | // check if in-game menu is up 95 | if (*ptr2 > 0x1C000000) 96 | { 97 | // switch if B is pressed 98 | if (buffer->btns_d & VPAD_BUTTON_B && (gAppStatus != 2) && *incrementPtr != incrementVal && *PCtrlPtr < 0x01000000) 99 | { 100 | drcSwap(); 101 | } 102 | 103 | // force temporary default swap in a match 104 | if (buffer->btns_h & VPAD_BUTTON_A) 105 | { 106 | if (*gamemode != 0xFFFFFFFF) 107 | { 108 | AButton = true; 109 | 110 | // super jumping with D-Pad 111 | if (buffer->btns_h & VPAD_BUTTON_LEFT) 112 | { 113 | touchVal = D_LEFT; 114 | } 115 | else if (buffer->btns_h & VPAD_BUTTON_UP) 116 | { 117 | touchVal = D_UP; 118 | } 119 | else if (buffer->btns_h & VPAD_BUTTON_RIGHT) 120 | { 121 | touchVal = D_RIGHT; 122 | } 123 | else if (buffer->btns_h & VPAD_BUTTON_DOWN) 124 | { 125 | touchVal = D_DOWN; 126 | } 127 | else 128 | { 129 | touchVal = D_NEUTRAL; 130 | } 131 | } 132 | } 133 | else 134 | { 135 | AButton = false; 136 | touchVal = D_NEUTRAL; 137 | } 138 | 139 | // reset increment value 140 | incrementVal = *incrementPtr; 141 | 142 | } 143 | else 144 | { 145 | AButton = false; 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/kernel/kernel_hooks.S: -------------------------------------------------------------------------------- 1 | # Created by dimok 2 | # This stuff may need a change in different kernel versions 3 | # This is only needed when launched directly through browser and not SD card. 4 | 5 | .section ".kernel_code" 6 | .globl SaveAndResetDataBATs_And_SRs_hook 7 | SaveAndResetDataBATs_And_SRs_hook: 8 | # setup CTR to the position we need to return to 9 | mflr r5 10 | mtctr r5 11 | # set link register to its original value 12 | mtlr r7 13 | # setup us a nice DBAT for our code data with same region as our code 14 | mfspr r5, 560 15 | mtspr 570, r5 16 | mfspr r5, 561 17 | mtspr 571, r5 18 | # restore the original kernel instructions that we replaced 19 | lwz r5, 0x34(r3) 20 | lwz r6, 0x38(r3) 21 | lwz r7, 0x3C(r3) 22 | lwz r8, 0x40(r3) 23 | lwz r9, 0x44(r3) 24 | lwz r10, 0x48(r3) 25 | lwz r11, 0x4C(r3) 26 | lwz r3, 0x50(r3) 27 | isync 28 | mtsr 7, r5 29 | # jump back to the position in kernel after our patch (from LR) 30 | bctr 31 | 32 | .extern my_PrepareTitle 33 | .globl my_PrepareTitle_hook 34 | my_PrepareTitle_hook: 35 | # store all registers on stack to avoid issues with the call to C functions 36 | stwu r1, -0x90(r1) 37 | # registers for our own usage 38 | # only need r31 and rest is from tests before, just leaving it for later tests 39 | stw r28, 0x20(r1) 40 | stw r29, 0x24(r1) 41 | stw r30, 0x28(r1) 42 | stw r31, 0x2C(r1) 43 | 44 | stw r3, 0x30(r1) 45 | stw r4, 0x34(r1) 46 | stw r5, 0x38(r1) 47 | stw r6, 0x3C(r1) 48 | stw r7, 0x40(r1) 49 | stw r8, 0x44(r1) 50 | stw r9, 0x48(r1) 51 | stw r10, 0x4C(r1) 52 | stw r11, 0x50(r1) 53 | stw r12, 0x54(r1) 54 | stw r13, 0x58(r1) 55 | stw r14, 0x5C(r1) 56 | stw r15, 0x60(r1) 57 | stw r16, 0x64(r1) 58 | stw r17, 0x68(r1) 59 | stw r18, 0x6C(r1) 60 | stw r19, 0x70(r1) 61 | stw r20, 0x74(r1) 62 | stw r21, 0x78(r1) 63 | stw r22, 0x7C(r1) 64 | 65 | # save original DBAT registers 66 | mfdbatu r28, 0 67 | mfdbatl r29, 0 68 | 69 | # setup access to our data memory range 70 | lis r3, 0xC000 71 | ori r3, r3, 0x1FFF 72 | mtdbatu 0, r3 73 | lis r3, 0x3000 74 | ori r3, r3, 0x0012 75 | mtdbatl 0, r3 76 | 77 | # memory barrier 78 | eieio 79 | isync 80 | 81 | # save the LR from where we came 82 | mflr r31 83 | 84 | # the cos.xml/app.xml structure is at the location 0x68 of r11 85 | # there are actually many places that can be hooked for it 86 | # e.g. 0xFFF16130 and r27 points to this structure 87 | addi r3, r11, 0x68 88 | 89 | bl my_PrepareTitle 90 | 91 | # restore original DBAT registers 92 | mtdbatu 0, r28 93 | mtdbatl 0, r29 94 | 95 | # memory barrier 96 | eieio 97 | isync 98 | 99 | # setup LR to jump back to kernel code 100 | mtlr r31 101 | 102 | # restore all original values of registers from stack 103 | lwz r28, 0x20(r1) 104 | lwz r29, 0x24(r1) 105 | lwz r30, 0x28(r1) 106 | lwz r31, 0x2C(r1) 107 | 108 | lwz r3, 0x30(r1) 109 | lwz r4, 0x34(r1) 110 | lwz r5, 0x38(r1) 111 | lwz r6, 0x3C(r1) 112 | lwz r7, 0x40(r1) 113 | lwz r8, 0x44(r1) 114 | lwz r9, 0x48(r1) 115 | lwz r10, 0x4C(r1) 116 | lwz r11, 0x50(r1) 117 | lwz r12, 0x54(r1) 118 | lwz r13, 0x58(r1) 119 | lwz r14, 0x5C(r1) 120 | lwz r15, 0x60(r1) 121 | lwz r16, 0x64(r1) 122 | lwz r17, 0x68(r1) 123 | lwz r18, 0x6C(r1) 124 | lwz r19, 0x70(r1) 125 | lwz r20, 0x74(r1) 126 | lwz r21, 0x78(r1) 127 | lwz r22, 0x7C(r1) 128 | 129 | # restore the stack 130 | addi r1, r1, 0x90 131 | 132 | # restore original instruction that we replaced in the kernel 133 | clrlwi r7, r12, 0 134 | 135 | # jump back 136 | blr 137 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwapDRC for TV-Only Wii U Games 2 | 3 | Introducing SwapDRC, a homebrew application that allows you to play TV-only Wii U games on your GamePad screen. 4 | 5 | SwapDRC works by switching the display buffers for the TV and the GamePad with a press of a button. This app also includes the TCPGecko and Cafiine installers for other mods or hacks. The GamePad sensor bar can also be turned on when the TV display is on the GamePad screen, so playing with Wiimotes with just the GamePad is possible. 6 | 7 | Update v1.1: Audio swapping support is now available! 8 | 9 | ## Instructions 10 | #### Switch Display, Audio, and Gamepad Sensor Bar: 11 | + Press L and Minus together. 12 | + Press the TV button. 13 | 14 | #### Switch on/off Gamepad LCD: 15 | + Press and hold R-Stick for 3 seconds. 16 | 17 | #### Splatoon's Enhanced Controls: 18 | + Press **B** to switch screens except in-game menus. 19 | + Hold **A** + **D-Pad** in any direction to super jump to a teammate or the spawn point during a match. 20 | 21 | ## Requirements 22 | 23 | * An SD card 24 | * The Homebrew Launcher ([Haxchi](https://gbatemp.net/threads/haxchi-v2-0-a-persistent-wiiu-hack.451071/) or [Loadiine.ovh](http://loadiine.ovh) method) 25 | * A Wii U (on firmware version 5.5.1, 5.5.2 and lower versions aren't tested but may work) 26 | * (Optional) A cafiine server (examples: [the original by Chadderz and MrRean](https://github.com/MrRean/Cafiine-410-551/blob/master/server/cafiine_server.exe), [MusicRandomizer](https://github.com/OatmealDome/SplatoonUtilities/blob/master/MusicRandomizer/README.md), [Ray's custom server](https://github.com/Syroot/CafiineServer), and more) 27 | * (Optional) Your Wii U's IP for TCPGecko or your computer's local IP for Cafiine ([Windows](http://www.nirsoft.net/utils/wnetwatcher.zip), [macOS](http://osxdaily.com/2010/11/21/find-ip-address-mac/)) 28 | * For Splatoon's enhanced controls: ver 2.10.0 - 2.12.0 29 | 30 | 31 | ## Tutorial 32 | 33 | ### Video tutorial: 34 | 35 | (coming soon) 36 | 37 | ### Text tutorial: 38 | 39 | 1. Download the Homebrew Launcher v1.4 from [**here**](https://github.com/dimok789/homebrew_launcher/releases), and the swapdrc.elf application from [**here**](https://github.com/OatmealDome/geckiine_drc_swap/releases). 40 | 41 | 2. Unzip both apps and then drag them into your SD Card. Make sure both directories are at: 42 | 43 | * SD:/wiiu/apps/homebrew_launcher/homebrew_launcher.elf 44 | * SD:/wiiu/apps/swapdrc/swapdrc.elf 45 | 46 | 3. Safely remove the SD card and insert it into your Wii U, then launch the Homebrew Launcher from the [Loadiine.ovh](http://loadiine.ovh) website in your Wii U browser. If you have the [Haxchi](https://gbatemp.net/threads/haxchi-v2-0-a-persistent-wiiu-hack.451071/) Homebrew Launcher, that works too. 47 | 48 | 4. Launch SwapDRC, then press **A** to install SwapDRC with TCPGecko, or press **Y** to install SwapDRC with TCPGecko + Cafiine (a cafiine server on your computer is required) 49 | 50 | 5. You're done! You can now switch displays anywhere (but not in the settings menu, as it re-launches the entire System Menu). 51 | 52 | # FAQ 53 | 54 | ### What's TCPGecko and Cafiine? 55 | 56 | TCPGecko is a mod that allows you to use a TCPGecko editor to modify the ram through a TCP connection. 57 | A perfect example for this is the program Splathax, which lets you modify gear in your Splatoon 58 | inventory. 59 | 60 | Cafiine is another mod that lets you replace game files with modified ones for the game to load. A 61 | perfect example for this is the popular use of model and skin edits for Smash Bros for Wii U. Unlike the 62 | "Install TCPGecko only" option, Cafiine requires you to have a server running on your computer at all 63 | times. Don't use this if you don't want to use game file mods and have the computer running all the time. 64 | 65 | ### Can I get you banned playing online with SwapDRC in any game? 66 | 67 | Swapping displays doesn't modify the games directly but through CafeOS instead. Therefore, it is 100% 68 | safe. However, you can still get banned with TCPGecko and/or Caffine mods if you don't use them properly. 69 | 70 | ### r u a l33t hax0r? 71 | 72 | YeS I Am. 73 | (...I'm joking this question isn't real) 74 | 75 | 76 | # Credits 77 | 78 | ### Creators: 79 | 80 | + OatmealDome 81 | + Yahya14 82 | 83 | ### Special thanks: 84 | 85 | + Maschell for development contribution and the audio swap 86 | + Dimok for function_hooks and the pygecko server 87 | + Brienj for the IP selector and initial UI 88 | + /u/MachMatic for the banner background 89 | + BKOOL999 for feedback & testing the SwapDRC app 90 | -------------------------------------------------------------------------------- /src/patcher/cafiine_function_patcher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "cafiine_function_patcher.h" 5 | #include "utils/logger.h" 6 | #include "cafiine/cafiine.h" 7 | #include "retain_vars.h" 8 | 9 | DECL(int, FSAAddClient, void *r3) { 10 | int res = real_FSAAddClient(r3); 11 | if(gAppStatus == 2) return res; 12 | 13 | if (res < MAX_CLIENT && res >= 0) { 14 | cafiine_connect((void*)0, res, 1); 15 | } 16 | 17 | return res; 18 | } 19 | 20 | DECL(int, FSADelClient, int client) { 21 | if(gAppStatus == 2) return real_FSADelClient(client); 22 | if (client < MAX_CLIENT && client >= 0) { 23 | cafiine_disconnect((void*)0, client, 1); 24 | } 25 | 26 | return real_FSADelClient(client); 27 | } 28 | 29 | DECL(int, FSAOpenFile, int client, const char *path, const char *mode, int *handle) { 30 | if(gAppStatus == 2) return real_FSAOpenFile(client, path, mode, handle); 31 | if (client < MAX_CLIENT && client >= 0) { 32 | int ret; 33 | if (cafiine_fopen((void*)0, client, &ret, path, mode, handle, 1) == 0) 34 | return ret; 35 | } 36 | 37 | return real_FSAOpenFile(client, path, mode, handle); 38 | } 39 | 40 | 41 | DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) { 42 | int res = real_FSAddClientEx(r3, r4, r5); 43 | if(gAppStatus == 2) return res; 44 | 45 | if (res >= 0) { 46 | cafiine_connect(r3, 0, 0); 47 | } 48 | 49 | return res; 50 | } 51 | 52 | DECL(int, FSDelClient, void *pClient) { 53 | if(gAppStatus == 2) return real_FSDelClient(pClient); 54 | cafiine_disconnect(pClient, 0, 0); 55 | 56 | return real_FSDelClient(pClient); 57 | } 58 | 59 | DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error) { 60 | if(gAppStatus == 2) return real_FSOpenFile(pClient, pCmd, path, mode, handle, error); 61 | int ret; 62 | if (cafiine_fopen(pClient, 0, &ret, path, mode, handle, 0) == 0) { 63 | return ret; 64 | } 65 | 66 | return real_FSOpenFile(pClient, pCmd, path, mode, handle, error); 67 | } 68 | 69 | DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int error) { 70 | if(gAppStatus == 2) return real_FSReadFile(pClient, pCmd, buffer, size, count, fd, flag, error); 71 | if ((fd & MASK_FD) == MASK_FD) { 72 | int ret; 73 | if (cafiine_fread(pClient, &ret, buffer, size, count, fd) == 0) { 74 | return ret; 75 | } 76 | } 77 | 78 | return real_FSReadFile(pClient, pCmd, buffer, size, count, fd, flag, error); 79 | } 80 | 81 | DECL(int, FSReadFileWithPos, void *pClient, void *pCmd, void *buffer, int size, int count, int pos, int fd, int flag, int error) { 82 | if(gAppStatus == 2) return real_FSReadFileWithPos(pClient, pCmd, buffer, size, count, pos, fd, flag, error); 83 | if ((fd & MASK_FD) == MASK_FD) { 84 | int ret; 85 | if (cafiine_fsetpos(pClient, &ret, fd, pos) == 0) { 86 | if (cafiine_fread(pClient, &ret, buffer, size, count, fd) == 0) { 87 | return ret; 88 | } 89 | } 90 | } 91 | 92 | return real_FSReadFileWithPos(pClient, pCmd, buffer, size, count, pos, fd, flag, error); 93 | } 94 | 95 | DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int error) { 96 | if(gAppStatus == 2) return real_FSCloseFile(pClient, pCmd, fd, error); 97 | if ((fd & MASK_FD) == MASK_FD) { 98 | int ret; 99 | if (cafiine_fclose(pClient, &ret, fd) == 0) { 100 | return ret; 101 | } 102 | } 103 | 104 | return real_FSCloseFile(pClient, pCmd, fd, error); 105 | } 106 | 107 | DECL(int, FSSetPosFile, void *pClient, void *pCmd, int fd, int pos, int error) { 108 | if(gAppStatus == 2) return real_FSSetPosFile(pClient, pCmd, fd, pos, error); 109 | if ((fd & MASK_FD) == MASK_FD) { 110 | int ret; 111 | if (cafiine_fsetpos(pClient, &ret, fd, pos) == 0) { 112 | return ret; 113 | } 114 | 115 | } 116 | 117 | return real_FSSetPosFile(pClient, pCmd, fd, pos, error); 118 | } 119 | 120 | DECL(int, FSGetPosFile, void *pClient, void *pCmd, int fd, int *pos, int error) { 121 | if(gAppStatus == 2) return real_FSGetPosFile(pClient, pCmd, fd, pos, error); 122 | if ((fd & MASK_FD) == MASK_FD) { 123 | int ret; 124 | if (cafiine_fgetpos(pClient, &ret, fd, pos) == 0) { 125 | return ret; 126 | } 127 | } 128 | 129 | return real_FSGetPosFile(pClient, pCmd, fd, pos, error); 130 | } 131 | 132 | DECL(int, FSGetStatFile, void *pClient, void *pCmd, int fd, void *buffer, int error) { 133 | if(gAppStatus == 2) return real_FSGetStatFile(pClient, pCmd, fd, buffer, error); 134 | if ((fd & MASK_FD) == MASK_FD) { 135 | int ret; 136 | if (cafiine_fstat(pClient, &ret, fd, buffer) == 0) { 137 | return ret; 138 | } 139 | } 140 | 141 | return real_FSGetStatFile(pClient, pCmd, fd, buffer, error); 142 | } 143 | 144 | DECL(int, FSIsEof, void *pClient, void *pCmd, int fd, int error) { 145 | if(gAppStatus == 2) return real_FSIsEof(pClient, pCmd, fd, error); 146 | if ((fd & MASK_FD) == MASK_FD) { 147 | int ret; 148 | if (cafiine_feof(pClient, &ret, fd) == 0) { 149 | return ret; 150 | } 151 | } 152 | 153 | return real_FSIsEof(pClient, pCmd, fd, error); 154 | } 155 | 156 | hooks_magic_t method_hooks_cafiine[] __attribute__((section(".data"))) = { 157 | MAKE_MAGIC(FSAAddClient, LIB_FS, STATIC_FUNCTION), 158 | MAKE_MAGIC(FSADelClient, LIB_FS, STATIC_FUNCTION), 159 | MAKE_MAGIC(FSAOpenFile, LIB_FS, STATIC_FUNCTION), 160 | MAKE_MAGIC(FSAddClientEx, LIB_FS, STATIC_FUNCTION), 161 | MAKE_MAGIC(FSDelClient, LIB_FS, STATIC_FUNCTION), 162 | MAKE_MAGIC(FSOpenFile, LIB_FS, STATIC_FUNCTION), 163 | MAKE_MAGIC(FSCloseFile, LIB_FS, STATIC_FUNCTION), 164 | MAKE_MAGIC(FSReadFile, LIB_FS, STATIC_FUNCTION), 165 | MAKE_MAGIC(FSReadFileWithPos, LIB_FS, STATIC_FUNCTION), 166 | MAKE_MAGIC(FSSetPosFile, LIB_FS, STATIC_FUNCTION), 167 | MAKE_MAGIC(FSGetStatFile, LIB_FS, STATIC_FUNCTION), 168 | MAKE_MAGIC(FSIsEof, LIB_FS, STATIC_FUNCTION), 169 | }; 170 | u32 method_hooks_size_cafiine __attribute__((section(".data"))) = sizeof(method_hooks_cafiine) / sizeof(hooks_magic_t); 171 | 172 | //! buffer to store our instructions needed for our replacements 173 | volatile unsigned int method_calls_cafiine[sizeof(method_hooks_cafiine) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data"))); 174 | -------------------------------------------------------------------------------- /src/system/exception_handler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dynamic_libs/os_functions.h" 3 | #include "utils/logger.h" 4 | #include "exception_handler.h" 5 | 6 | #define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES 4 7 | 8 | #define OS_EXCEPTION_DSI 2 9 | #define OS_EXCEPTION_ISI 3 10 | #define OS_EXCEPTION_PROGRAM 6 11 | 12 | /* Exceptions */ 13 | typedef struct OSContext 14 | { 15 | /* OSContext identifier */ 16 | uint32_t tag1; 17 | uint32_t tag2; 18 | 19 | /* GPRs */ 20 | uint32_t gpr[32]; 21 | 22 | /* Special registers */ 23 | uint32_t cr; 24 | uint32_t lr; 25 | uint32_t ctr; 26 | uint32_t xer; 27 | 28 | /* Initial PC and MSR */ 29 | uint32_t srr0; 30 | uint32_t srr1; 31 | 32 | /* Only valid during DSI exception */ 33 | uint32_t exception_specific0; 34 | uint32_t exception_specific1; 35 | 36 | /* There is actually a lot more here but we don't need the rest*/ 37 | } OSContext; 38 | 39 | #define CPU_STACK_TRACE_DEPTH 10 40 | #define __stringify(rn) #rn 41 | 42 | #define mfspr(_rn) \ 43 | ({ register uint32_t _rval = 0; \ 44 | asm volatile("mfspr %0," __stringify(_rn) \ 45 | : "=r" (_rval));\ 46 | _rval; \ 47 | }) 48 | 49 | typedef struct _framerec { 50 | struct _framerec *up; 51 | void *lr; 52 | } frame_rec, *frame_rec_t; 53 | 54 | static const char *exception_names[] = { 55 | "DSI", 56 | "ISI", 57 | "PROGRAM" 58 | }; 59 | 60 | static const char exception_print_formats[18][45] = { 61 | "Exception type %s occurred!\n", // 0 62 | "GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1 63 | "GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2 64 | "GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3 65 | "GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4 66 | "GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5 67 | "GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6 68 | "GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7 69 | "GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8 70 | "LR %08X SRR0 %08x SRR1 %08x\n", // 9 71 | "DAR %08X DSISR %08X\n", // 10 72 | "\nSTACK DUMP:", // 11 73 | " --> ", // 12 74 | " -->\n", // 13 75 | "\n", // 14 76 | "%p", // 15 77 | "\nCODE DUMP:\n", // 16 78 | "%p: %08X %08X %08X %08X\n", // 17 79 | }; 80 | 81 | static unsigned char exception_cb(void * c, unsigned char exception_type) { 82 | char buf[850]; 83 | int pos = 0; 84 | 85 | OSContext *context = (OSContext *) c; 86 | /* 87 | * This part is mostly from libogc. Thanks to the devs over there. 88 | */ 89 | pos += sprintf(buf + pos, exception_print_formats[0], exception_names[exception_type]); 90 | pos += sprintf(buf + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], context->gpr[16], context->gpr[24]); 91 | pos += sprintf(buf + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], context->gpr[17], context->gpr[25]); 92 | pos += sprintf(buf + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], context->gpr[18], context->gpr[26]); 93 | pos += sprintf(buf + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], context->gpr[19], context->gpr[27]); 94 | pos += sprintf(buf + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], context->gpr[20], context->gpr[28]); 95 | pos += sprintf(buf + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], context->gpr[21], context->gpr[29]); 96 | pos += sprintf(buf + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], context->gpr[22], context->gpr[30]); 97 | pos += sprintf(buf + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], context->gpr[23], context->gpr[31]); 98 | pos += sprintf(buf + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1); 99 | 100 | //if(exception_type == OS_EXCEPTION_DSI) { 101 | pos += sprintf(buf + pos, exception_print_formats[10], context->exception_specific1, context->exception_specific0); // this freezes 102 | //} 103 | 104 | void *pc = (void*)context->srr0; 105 | void *lr = (void*)context->lr; 106 | void *r1 = (void*)context->gpr[1]; 107 | register uint32_t i = 0; 108 | register frame_rec_t l,p = (frame_rec_t)lr; 109 | 110 | l = p; 111 | p = r1; 112 | if(!p) 113 | asm volatile("mr %0,%%r1" : "=r"(p)); 114 | 115 | pos += sprintf(buf + pos, exception_print_formats[11]); 116 | 117 | for(i = 0; i < CPU_STACK_TRACE_DEPTH-1 && p->up; p = p->up, i++) { 118 | if(i % 4) 119 | pos += sprintf(buf + pos, exception_print_formats[12]); 120 | else { 121 | if(i > 0) 122 | pos += sprintf(buf + pos, exception_print_formats[13]); 123 | else 124 | pos += sprintf(buf + pos, exception_print_formats[14]); 125 | } 126 | 127 | switch(i) { 128 | case 0: 129 | if(pc) 130 | pos += sprintf(buf + pos, exception_print_formats[15],pc); 131 | break; 132 | case 1: 133 | if(!l) 134 | l = (frame_rec_t)mfspr(8); 135 | pos += sprintf(buf + pos, exception_print_formats[15],(void*)l); 136 | break; 137 | default: 138 | pos += sprintf(buf + pos, exception_print_formats[15],(void*)(p->up->lr)); 139 | break; 140 | } 141 | } 142 | 143 | //if(exception_type == OS_EXCEPTION_DSI) { 144 | uint32_t *pAdd = (uint32_t*)context->srr0; 145 | pos += sprintf(buf + pos, exception_print_formats[16]); 146 | // TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen 147 | for (i = 0; i < 8; i += 4) 148 | pos += sprintf(buf + pos, exception_print_formats[17], &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]); 149 | //} 150 | log_print(buf); 151 | OSFatal(buf); 152 | return 1; 153 | } 154 | 155 | static unsigned char dsi_exception_cb(void * context) { 156 | return exception_cb(context, 0); 157 | } 158 | static unsigned char isi_exception_cb(void * context) { 159 | return exception_cb(context, 1); 160 | } 161 | static unsigned char program_exception_cb(void * context) { 162 | return exception_cb(context, 2); 163 | } 164 | 165 | void setup_os_exceptions(void) { 166 | OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb); 167 | OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb); 168 | OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb); 169 | } 170 | -------------------------------------------------------------------------------- /src/system/memory.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 Dimok 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ****************************************************************************/ 17 | #include 18 | #include 19 | #include "dynamic_libs/os_functions.h" 20 | #include "common/common.h" 21 | #include "memory.h" 22 | 23 | #define MEMORY_ARENA_1 0 24 | #define MEMORY_ARENA_2 1 25 | #define MEMORY_ARENA_3 2 26 | #define MEMORY_ARENA_4 3 27 | #define MEMORY_ARENA_5 4 28 | #define MEMORY_ARENA_6 5 29 | #define MEMORY_ARENA_7 6 30 | #define MEMORY_ARENA_8 7 31 | #define MEMORY_ARENA_FG_BUCKET 8 32 | 33 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 34 | //! Memory functions 35 | //! This is the only place where those are needed so lets keep them more or less private 36 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 37 | extern u32 * pMEMAllocFromDefaultHeapEx; 38 | extern u32 * pMEMAllocFromDefaultHeap; 39 | extern u32 * pMEMFreeToDefaultHeap; 40 | 41 | extern s32 (* MEMGetBaseHeapHandle)(s32 mem_arena); 42 | extern u32 (* MEMGetAllocatableSizeForFrmHeapEx)(s32 heap, s32 align); 43 | extern void *(* MEMAllocFromFrmHeapEx)(s32 heap, u32 size, s32 align); 44 | extern void (* MEMFreeToFrmHeap)(s32 heap, s32 mode); 45 | extern void *(* MEMAllocFromExpHeapEx)(s32 heap, u32 size, s32 align); 46 | extern s32 (* MEMCreateExpHeapEx)(void* address, u32 size, unsigned short flags); 47 | extern void *(* MEMDestroyExpHeap)(s32 heap); 48 | extern void (* MEMFreeToExpHeap)(s32 heap, void* ptr); 49 | 50 | static s32 mem1_heap = -1; 51 | static s32 bucket_heap = -1; 52 | 53 | void memoryInitialize(void) 54 | { 55 | s32 mem1_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_1); 56 | u32 mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4); 57 | void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4); 58 | if(mem1_memory) 59 | mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0); 60 | 61 | s32 bucket_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET); 62 | u32 bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4); 63 | void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4); 64 | if(bucket_memory) 65 | bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0); 66 | } 67 | 68 | void memoryRelease(void) 69 | { 70 | MEMDestroyExpHeap(mem1_heap); 71 | MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3); 72 | mem1_heap = -1; 73 | 74 | MEMDestroyExpHeap(bucket_heap); 75 | MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3); 76 | bucket_heap = -1; 77 | } 78 | 79 | //!------------------------------------------------------------------------------------------- 80 | //! wraps 81 | //!------------------------------------------------------------------------------------------- 82 | void *__wrap_malloc(size_t size) 83 | { 84 | // pointer to a function resolve 85 | return ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size); 86 | } 87 | 88 | void *__wrap_memalign(size_t align, size_t size) 89 | { 90 | if (align < 4) 91 | align = 4; 92 | 93 | // pointer to a function resolve 94 | return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, align); 95 | } 96 | 97 | void __wrap_free(void *p) 98 | { 99 | // pointer to a function resolve 100 | if(p != 0) 101 | ((void (*)(void *))(*pMEMFreeToDefaultHeap))(p); 102 | } 103 | 104 | void *__wrap_calloc(size_t n, size_t size) 105 | { 106 | void *p = __wrap_malloc(n * size); 107 | if (p != 0) { 108 | memset(p, 0, n * size); 109 | } 110 | return p; 111 | } 112 | 113 | size_t __wrap_malloc_usable_size(void *p) 114 | { 115 | //! TODO: this is totally wrong and needs to be addressed 116 | return 0x7FFFFFFF; 117 | } 118 | 119 | void *__wrap_realloc(void *p, size_t size) 120 | { 121 | void *new_ptr = __wrap_malloc(size); 122 | if (new_ptr != 0) 123 | { 124 | memcpy(new_ptr, p, __wrap_malloc_usable_size(p) < size ? __wrap_malloc_usable_size(p) : size); 125 | __wrap_free(p); 126 | } 127 | return new_ptr; 128 | } 129 | 130 | //!------------------------------------------------------------------------------------------- 131 | //! reent versions 132 | //!------------------------------------------------------------------------------------------- 133 | void *__wrap__malloc_r(struct _reent *r, size_t size) 134 | { 135 | return __wrap_malloc(size); 136 | } 137 | 138 | void *__wrap__calloc_r(struct _reent *r, size_t n, size_t size) 139 | { 140 | return __wrap_calloc(n, size); 141 | } 142 | 143 | void *__wrap__memalign_r(struct _reent *r, size_t align, size_t size) 144 | { 145 | return __wrap_memalign(align, size); 146 | } 147 | 148 | void __wrap__free_r(struct _reent *r, void *p) 149 | { 150 | __wrap_free(p); 151 | } 152 | 153 | size_t __wrap__malloc_usable_size_r(struct _reent *r, void *p) 154 | { 155 | return __wrap_malloc_usable_size(p); 156 | } 157 | 158 | void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) 159 | { 160 | return __wrap_realloc(p, size); 161 | } 162 | 163 | //!------------------------------------------------------------------------------------------- 164 | //! some wrappers 165 | //!------------------------------------------------------------------------------------------- 166 | void * MEM2_alloc(u32 size, u32 align) 167 | { 168 | return __wrap_memalign(align, size); 169 | } 170 | 171 | void MEM2_free(void *ptr) 172 | { 173 | __wrap_free(ptr); 174 | } 175 | 176 | void * MEM1_alloc(u32 size, u32 align) 177 | { 178 | if (align < 4) 179 | align = 4; 180 | return MEMAllocFromExpHeapEx(mem1_heap, size, align); 181 | } 182 | 183 | void MEM1_free(void *ptr) 184 | { 185 | MEMFreeToExpHeap(mem1_heap, ptr); 186 | } 187 | 188 | void * MEMBucket_alloc(u32 size, u32 align) 189 | { 190 | if (align < 4) 191 | align = 4; 192 | return MEMAllocFromExpHeapEx(bucket_heap, size, align); 193 | } 194 | 195 | void MEMBucket_free(void *ptr) 196 | { 197 | MEMFreeToExpHeap(bucket_heap, ptr); 198 | } 199 | -------------------------------------------------------------------------------- /src/common/kernel_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef __KERNEL_DEFS_H_ 2 | #define __KERNEL_DEFS_H_ 3 | 4 | #include "types.h" 5 | #include "fs_defs.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | // original structure in the kernel that is originally 0x1270 long 12 | typedef struct 13 | { 14 | uint32_t version_cos_xml; // version tag from cos.xml 15 | uint64_t os_version; // os_version from app.xml 16 | uint64_t title_id; // title_id tag from app.xml 17 | uint32_t app_type; // app_type tag from app.xml 18 | uint32_t cmdFlags; // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure) 19 | char rpx_name[0x1000]; // rpx name from cos.xml 20 | uint32_t unknown2; // 0x050B8304 in mii maker and system menu (looks a bit like permissions complex that got masked!?) 21 | uint32_t unknown3[63]; // those were all zeros, but its probably connected with unknown2 22 | uint32_t max_size; // max_size in cos.xml which defines the maximum amount of memory reserved for the app 23 | uint32_t avail_size; // avail_size or codegen_size in cos.xml (seems to mostly be 0?) 24 | uint32_t codegen_size; // codegen_size or avail_size in cos.xml (seems to mostly be 0?) 25 | uint32_t codegen_core; // codegen_core in cos.xml (seems to mostly be 1?) 26 | uint32_t max_codesize; // max_codesize in cos.xml 27 | uint32_t overlay_arena; // overlay_arena in cos.xml 28 | uint32_t unknown4[59]; // all zeros it seems 29 | uint32_t default_stack0_size; // not sure because always 0 but very likely 30 | uint32_t default_stack1_size; // not sure because always 0 but very likely 31 | uint32_t default_stack2_size; // not sure because always 0 but very likely 32 | uint32_t default_redzone0_size; // not sure because always 0 but very likely 33 | uint32_t default_redzone1_size; // not sure because always 0 but very likely 34 | uint32_t default_redzone2_size; // not sure because always 0 but very likely 35 | uint32_t exception_stack0_size; // from cos.xml, 0x1000 on mii maker 36 | uint32_t exception_stack1_size; // from cos.xml, 0x1000 on mii maker 37 | uint32_t exception_stack2_size; // from cos.xml, 0x1000 on mii maker 38 | uint32_t sdk_version; // from app.xml, 20909 (0x51AD) on mii maker 39 | uint32_t title_version; // from app.xml, 0x32 on mii maker 40 | /* 41 | // --------------------------------------------------------------------------------------------------------------------------------------------- 42 | // the next part might be changing from title to title?! I don't think its important but nice to know maybe.... 43 | // --------------------------------------------------------------------------------------------------------------------------------------------- 44 | char mlc[4]; // string "mlc" on mii maker and sysmenu 45 | uint32_t unknown5[7]; // all zeros on mii maker and sysmenu 46 | uint32_t unknown6_one; // 0x01 on mii maker and sysmenu 47 | // --------------------------------------------------------------------------------------------------------------------------------------------- 48 | char ACP[4]; // string "ACP" on mii maker and sysmenu 49 | uint32_t unknown7[15]; // all zeros on mii maker and sysmenu 50 | uint32_t unknown8_5; // 0x05 on mii maker and sysmenu 51 | uint32_t unknown9_zero; // 0x00 on mii maker and sysmenu 52 | uint32_t unknown10_ptr; // 0xFF23DD0C pointer on mii maker and sysmenu 53 | // --------------------------------------------------------------------------------------------------------------------------------------------- 54 | char UVD[4]; // string "UVD" on mii maker and sysmenu 55 | uint32_t unknown11[15]; // all zeros on mii maker and sysmenu 56 | uint32_t unknown12_5; // 0x05 on mii maker and sysmenu 57 | uint32_t unknown13_zero; // 0x00 on mii maker and sysmenu 58 | uint32_t unknown14_ptr; // 0xFF23EFC8 pointer on mii maker and sysmenu 59 | // --------------------------------------------------------------------------------------------------------------------------------------------- 60 | char SND[4]; // string "SND" on mii maker and sysmenu 61 | uint32_t unknown15[15]; // all zeros on mii maker and sysmenu 62 | uint32_t unknown16_5; // 0x05 on mii maker and sysmenu 63 | uint32_t unknown17_zero; // 0x00 on mii maker and sysmenu 64 | uint32_t unknown18_ptr; // 0xFF23F014 pointer on mii maker and sysmenu 65 | // --------------------------------------------------------------------------------------------------------------------------------------------- 66 | uint32_t unknown19; // 0x02 on miimaker, 0x0F on system menu 67 | */ 68 | // after that only zeros follow 69 | } __attribute__((packed)) CosAppXmlInfo; 70 | 71 | 72 | // original structure in the kernel that is originally 0x1270 long 73 | typedef struct 74 | { 75 | uint64_t title_id; // title_id tag from app.xml 76 | uint64_t unknown1; 77 | uint64_t osversion; 78 | uint64_t unknown2; 79 | uint64_t common_save_size; 80 | uint64_t account_save_size; 81 | uint64_t unknown4; 82 | uint64_t unknown5; 83 | uint64_t unknown6; // companycode? 84 | uint64_t unknown7; 85 | char unknown8[6]; 86 | char product_code[22]; 87 | char unknown9[44]; 88 | char content_platform[3]; 89 | } __attribute__((packed)) MetaXmlInfo; 90 | 91 | // Our own cos/app.xml struct which uses only uses as much memory as really needed, since many things are just zeros in the above structure 92 | // This structure is only 0x64 bytes long + RPX name length (dynamic up to 0x1000 theoretically) 93 | typedef struct 94 | { 95 | uint32_t version_cos_xml; // version tag from cos.xml 96 | uint64_t os_version; // os_version from app.xml 97 | uint64_t title_id; // title_id tag from app.xml 98 | uint32_t app_type; // app_type tag from app.xml 99 | uint32_t cmdFlags; // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure) 100 | uint32_t max_size; // max_size in cos.xml which defines the maximum amount of memory reserved for the app 101 | uint32_t avail_size; // avail_size or codegen_size in cos.xml (seems to mostly be 0?) 102 | uint32_t codegen_size; // codegen_size or avail_size in cos.xml (seems to mostly be 0?) 103 | uint32_t codegen_core; // codegen_core in cos.xml (seems to mostly be 1?) 104 | uint32_t max_codesize; // max_codesize in cos.xml 105 | uint32_t overlay_arena; // overlay_arena in cos.xml 106 | uint32_t default_stack0_size; // not sure because always 0 but very likely 107 | uint32_t default_stack1_size; // not sure because always 0 but very likely 108 | uint32_t default_stack2_size; // not sure because always 0 but very likely 109 | uint32_t default_redzone0_size; // not sure because always 0 but very likely 110 | uint32_t default_redzone1_size; // not sure because always 0 but very likely 111 | uint32_t default_redzone2_size; // not sure because always 0 but very likely 112 | uint32_t exception_stack0_size; // from cos.xml, 0x1000 on mii maker 113 | uint32_t exception_stack1_size; // from cos.xml, 0x1000 on mii maker 114 | uint32_t exception_stack2_size; // from cos.xml, 0x1000 on mii maker 115 | uint32_t sdk_version; // from app.xml, 20909 (0x51AD) on mii maker 116 | uint32_t title_version; // from app.xml, 0x32 on mii maker 117 | char rpx_name[FS_MAX_ENTNAME_SIZE]; // rpx name from cos.xml, length 256 as it can't get bigger from FS anyway 118 | } __attribute__((packed)) ReducedCosAppXmlInfo; 119 | 120 | typedef struct _bat_t 121 | { 122 | u32 h; 123 | u32 l; 124 | } bat_t; 125 | 126 | typedef struct _bat_table_t 127 | { 128 | bat_t bat[8]; 129 | } bat_table_t; 130 | 131 | #ifdef __cplusplus 132 | } 133 | #endif 134 | 135 | #endif // __KERNEL_DEFS_H_ 136 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(DEVKITPPC)),) 7 | $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") 8 | endif 9 | ifeq ($(strip $(DEVKITPRO)),) 10 | $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") 11 | endif 12 | export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) 13 | export LIBOGC_INC := $(DEVKITPRO)/libogc/include 14 | export LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii 15 | export PORTLIBS := $(DEVKITPRO)/portlibs/ppc 16 | 17 | PREFIX := powerpc-eabi- 18 | 19 | export AS := $(PREFIX)as 20 | export CC := $(PREFIX)gcc 21 | export CXX := $(PREFIX)g++ 22 | export AR := $(PREFIX)ar 23 | export OBJCOPY := $(PREFIX)objcopy 24 | 25 | #--------------------------------------------------------------------------------- 26 | # TARGET is the name of the output 27 | # BUILD is the directory where object files & intermediate files will be placed 28 | # SOURCES is a list of directories containing source code 29 | # INCLUDES is a list of directories containing extra header files 30 | #--------------------------------------------------------------------------------- 31 | TARGET := swapdrc 32 | BUILD := build 33 | BUILD_DBG := $(TARGET)_dbg 34 | SOURCES := src \ 35 | src/dynamic_libs \ 36 | src/fs \ 37 | src/game \ 38 | src/kernel \ 39 | src/patcher \ 40 | src/common \ 41 | src/system \ 42 | src/utils \ 43 | src/cafiine \ 44 | src/gecko 45 | DATA := 46 | 47 | INCLUDES := src 48 | 49 | #--------------------------------------------------------------------------------- 50 | # options for code generation 51 | #--------------------------------------------------------------------------------- 52 | CFLAGS := -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ 53 | -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) 54 | CXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ 55 | -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) 56 | ASFLAGS := -mregnames 57 | LDFLAGS := -nostartfiles -Wl,-Map,$(notdir $@).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r,-wrap,valloc,-wrap,_valloc_r,-wrap,_pvalloc_r,--gc-sections 58 | 59 | #--------------------------------------------------------------------------------- 60 | Q := @ 61 | MAKEFLAGS += --no-print-directory 62 | #--------------------------------------------------------------------------------- 63 | # any extra libraries we wish to link with the project 64 | #--------------------------------------------------------------------------------- 65 | LIBS := 66 | 67 | #--------------------------------------------------------------------------------- 68 | # list of directories containing libraries, this must be the top level containing 69 | # include and lib 70 | #--------------------------------------------------------------------------------- 71 | LIBDIRS := $(CURDIR) \ 72 | $(DEVKITPPC)/lib \ 73 | $(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 74 | 75 | 76 | #--------------------------------------------------------------------------------- 77 | # no real need to edit anything past this point unless you need to add additional 78 | # rules for different file extensions 79 | #--------------------------------------------------------------------------------- 80 | ifneq ($(BUILD),$(notdir $(CURDIR))) 81 | #--------------------------------------------------------------------------------- 82 | export PROJECTDIR := $(CURDIR) 83 | export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) 84 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 85 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 86 | export DEPSDIR := $(CURDIR)/$(BUILD) 87 | 88 | #--------------------------------------------------------------------------------- 89 | # automatically build a list of object files for our project 90 | #--------------------------------------------------------------------------------- 91 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 92 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 93 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 94 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 95 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 96 | TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf))) 97 | PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) 98 | 99 | #--------------------------------------------------------------------------------- 100 | # use CXX for linking C++ projects, CC for standard C 101 | #--------------------------------------------------------------------------------- 102 | ifeq ($(strip $(CPPFILES)),) 103 | export LD := $(CC) 104 | else 105 | export LD := $(CXX) 106 | endif 107 | 108 | export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 109 | $(sFILES:.s=.o) $(SFILES:.S=.o) \ 110 | $(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES)) 111 | 112 | #--------------------------------------------------------------------------------- 113 | # build a list of include paths 114 | #--------------------------------------------------------------------------------- 115 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 116 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 117 | -I$(CURDIR)/$(BUILD) -I$(LIBOGC_INC) \ 118 | -I$(PORTLIBS)/include -I$(PORTLIBS)/include/freetype2 119 | 120 | #--------------------------------------------------------------------------------- 121 | # build a list of library paths 122 | #--------------------------------------------------------------------------------- 123 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 124 | -L$(LIBOGC_LIB) -L$(PORTLIBS)/lib 125 | 126 | export OUTPUT := $(CURDIR)/$(TARGET) 127 | .PHONY: $(BUILD) clean install 128 | 129 | #--------------------------------------------------------------------------------- 130 | $(BUILD): 131 | @[ -d $@ ] || mkdir -p $@ 132 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 133 | 134 | #--------------------------------------------------------------------------------- 135 | clean: 136 | @echo clean ... 137 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf 138 | 139 | #--------------------------------------------------------------------------------- 140 | else 141 | 142 | DEPENDS := $(OFILES:.o=.d) 143 | 144 | #--------------------------------------------------------------------------------- 145 | # main targets 146 | #--------------------------------------------------------------------------------- 147 | $(OUTPUT).elf: $(OFILES) 148 | 149 | #--------------------------------------------------------------------------------- 150 | # This rule links in binary data with the .jpg extension 151 | #--------------------------------------------------------------------------------- 152 | %.elf: link.ld $(OFILES) 153 | @echo "linking ... $(TARGET).elf" 154 | $(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf $(LIBPATHS) $(LIBS) 155 | $(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@ 156 | 157 | ../data/loader.bin: 158 | $(MAKE) -C ../loader clean 159 | $(MAKE) -C ../loader 160 | #--------------------------------------------------------------------------------- 161 | %.a: 162 | #--------------------------------------------------------------------------------- 163 | @echo $(notdir $@) 164 | @rm -f $@ 165 | @$(AR) -rc $@ $^ 166 | 167 | #--------------------------------------------------------------------------------- 168 | %.o: %.cpp 169 | @echo $(notdir $<) 170 | @$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) 171 | 172 | #--------------------------------------------------------------------------------- 173 | %.o: %.c 174 | @echo $(notdir $<) 175 | @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER) 176 | 177 | #--------------------------------------------------------------------------------- 178 | %.o: %.S 179 | @echo $(notdir $<) 180 | @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER) 181 | 182 | #--------------------------------------------------------------------------------- 183 | %.png.o : %.png 184 | @echo $(notdir $<) 185 | @bin2s -a 32 $< | $(AS) -o $(@) 186 | 187 | #--------------------------------------------------------------------------------- 188 | %.jpg.o : %.jpg 189 | @echo $(notdir $<) 190 | @bin2s -a 32 $< | $(AS) -o $(@) 191 | 192 | #--------------------------------------------------------------------------------- 193 | %.ttf.o : %.ttf 194 | @echo $(notdir $<) 195 | @bin2s -a 32 $< | $(AS) -o $(@) 196 | 197 | #--------------------------------------------------------------------------------- 198 | %.bin.o : %.bin 199 | @echo $(notdir $<) 200 | @bin2s -a 32 $< | $(AS) -o $(@) 201 | 202 | #--------------------------------------------------------------------------------- 203 | %.wav.o : %.wav 204 | @echo $(notdir $<) 205 | @bin2s -a 32 $< | $(AS) -o $(@) 206 | 207 | #--------------------------------------------------------------------------------- 208 | %.mp3.o : %.mp3 209 | @echo $(notdir $<) 210 | @bin2s -a 32 $< | $(AS) -o $(@) 211 | 212 | #--------------------------------------------------------------------------------- 213 | %.ogg.o : %.ogg 214 | @echo $(notdir $<) 215 | @bin2s -a 32 $< | $(AS) -o $(@) 216 | 217 | -include $(DEPENDS) 218 | 219 | #--------------------------------------------------------------------------------- 220 | endif 221 | #--------------------------------------------------------------------------------- 222 | -------------------------------------------------------------------------------- /src/cafiine/cafiine.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "main.h" 4 | #include "cafiine.h" 5 | #include "dynamic_libs/os_functions.h" 6 | #include "dynamic_libs/gx2_functions.h" 7 | #include "dynamic_libs/socket_functions.h" 8 | #include "kernel/kernel_functions.h" 9 | #include "common/common.h" 10 | #include "utils/logger.h" 11 | #include "retain_vars.h" 12 | 13 | static int recvwait(int sock, void *buffer, int len) { 14 | int ret; 15 | while (len > 0) { 16 | ret = recv(sock, buffer, len, 0); 17 | CHECK_ERROR(ret < 0); 18 | len -= ret; 19 | buffer += ret; 20 | } 21 | return 0; 22 | error: 23 | return ret; 24 | } 25 | 26 | static int recvbyte(int sock) { 27 | unsigned char buffer[1]; 28 | int ret; 29 | 30 | ret = recvwait(sock, buffer, 1); 31 | if (ret < 0) return ret; 32 | return buffer[0]; 33 | } 34 | 35 | static int sendwait(int sock, const void *buffer, int len) { 36 | int ret; 37 | while (len > 0) { 38 | ret = send(sock, buffer, len, 0); 39 | CHECK_ERROR(ret < 0); 40 | len -= ret; 41 | buffer += ret; 42 | } 43 | return 0; 44 | error: 45 | return ret; 46 | } 47 | 48 | static int sendbyte(int sock, unsigned char byte) { 49 | unsigned char buffer[1]; 50 | 51 | buffer[0] = byte; 52 | return sendwait(sock, buffer, 1); 53 | } 54 | 55 | static int client_num_alloc(void *pClient) { 56 | int i; 57 | 58 | for (i = 0; i < MAX_CLIENT; i++) 59 | if (fspatchervars.pClient_fs[i] == 0) { 60 | fspatchervars.pClient_fs[i] = pClient; 61 | return i; 62 | } 63 | return -1; 64 | } 65 | static void client_num_free(int client) { 66 | fspatchervars.pClient_fs[client] = 0; 67 | } 68 | 69 | static int client_num(void *pClient) { 70 | int i; 71 | 72 | for (i = 0; i < MAX_CLIENT; i++) 73 | if (fspatchervars.pClient_fs[i] == pClient) 74 | return i; 75 | 76 | return -1; 77 | } 78 | 79 | void cafiine_connect(void *pClient, int clientId, int isFSA) { 80 | struct sockaddr_in addr; 81 | int sock, ret; 82 | 83 | int client = (isFSA == 1) ? clientId : client_num_alloc(pClient); 84 | 85 | socket_lib_init(); 86 | 87 | sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 88 | CHECK_ERROR(sock == -1); 89 | 90 | addr.sin_family = AF_INET; 91 | addr.sin_port = 7332; 92 | addr.sin_addr.s_addr = cafiine_addr;; 93 | 94 | ret = connect(sock, (void *)&addr, sizeof(addr)); 95 | CHECK_ERROR(ret < 0); 96 | ret = cafiine_handshake(sock); 97 | CHECK_ERROR(ret < 0); 98 | CHECK_ERROR(ret == BYTE_NORMAL); 99 | 100 | if (isFSA == 1) 101 | fspatchervars.socket_fsa[client] = sock; 102 | else 103 | fspatchervars.socket_fs[client] = sock; 104 | 105 | 106 | return; 107 | error: 108 | if (sock != -1) 109 | socketclose(sock); 110 | fspatchervars.socket_fs[client] = -1; 111 | } 112 | 113 | 114 | void cafiine_disconnect(void *pClient, int clientId, int isFSA) { 115 | int sock; 116 | if (isFSA == 1) 117 | sock = fspatchervars.socket_fsa[clientId]; 118 | else 119 | sock = fspatchervars.socket_fs[client_num(pClient)]; 120 | 121 | CHECK_ERROR(sock == -1); 122 | socketclose(sock); 123 | 124 | client_num_free(clientId); 125 | error: 126 | return; 127 | } 128 | 129 | int cafiine_handshake(int sock) { 130 | int ret; 131 | unsigned char buffer[16]; 132 | 133 | void* title_id = (void*)0x0; 134 | if (OS_FIRMWARE == 550) { 135 | title_id = (void*)0x10013C10; 136 | } else if (OS_FIRMWARE < 550 && OS_FIRMWARE >= 532) { 137 | title_id = (void*)0x100136D0; 138 | } else if (OS_FIRMWARE < 532 && OS_FIRMWARE >= 500) { 139 | title_id = (void*)0x10013010; 140 | } else if (OS_FIRMWARE == 410) { 141 | title_id = (void*)0x1000ECB0; 142 | } else { 143 | OSFatal("Sorry, this firmware version is unsupported."); 144 | } 145 | 146 | memcpy(buffer, title_id, 16); 147 | 148 | ret = sendwait(sock, buffer, sizeof(buffer)); 149 | CHECK_ERROR(ret < 0); 150 | ret = recvbyte(sock); 151 | CHECK_ERROR(ret < 0); 152 | return ret; 153 | error: 154 | return ret; 155 | } 156 | 157 | int cafiine_fopen(void* pClient, int clientId, int *result, const char *path, const char *mode, int *handle, int isFSA) { 158 | while (fspatchervars.lock) GX2WaitForVsync(); 159 | 160 | fspatchervars.lock = 1; 161 | 162 | int sock; 163 | if (isFSA == 1) 164 | sock = fspatchervars.socket_fsa[clientId]; 165 | else 166 | sock = fspatchervars.socket_fs[client_num(pClient)]; 167 | 168 | CHECK_ERROR(sock == -1); 169 | 170 | int ret; 171 | ret = sendbyte(sock, BYTE_OPEN); 172 | CHECK_ERROR(ret < 0); 173 | 174 | int len_path = 0; 175 | while (path[len_path++]); 176 | int len_mode = 0; 177 | while (mode[len_mode++]); 178 | 179 | { 180 | char buffer[8 + len_path + len_mode]; 181 | *(int *)(buffer) = len_path; 182 | *(int *)(buffer + 4) = len_mode; 183 | for (ret = 0; ret < len_path; ret++) 184 | buffer[8 + ret] = path[ret]; 185 | for (ret = 0; ret < len_mode; ret++) 186 | buffer[8 + len_path + ret] = mode[ret]; 187 | 188 | ret = sendwait(sock, buffer, 8 + len_path + len_mode); 189 | } 190 | CHECK_ERROR(ret < 0); 191 | ret = recvbyte(sock); 192 | CHECK_ERROR(ret < 0); 193 | CHECK_ERROR(ret == BYTE_NORMAL); 194 | ret = recvwait(sock, result, 4); 195 | CHECK_ERROR(ret < 0); 196 | ret = recvwait(sock, handle, 4); 197 | CHECK_ERROR(ret < 0); 198 | 199 | fspatchervars.lock = 0; 200 | return 0; 201 | error: 202 | fspatchervars.lock = 0; 203 | return -1; 204 | } 205 | 206 | int cafiine_fread(void* pClient, int *result, void *ptr, int size, int count, int fd) { 207 | while (fspatchervars.lock) GX2WaitForVsync(); 208 | fspatchervars.lock = 1; 209 | 210 | int sock = fspatchervars.socket_fs[client_num(pClient)]; 211 | 212 | CHECK_ERROR(sock == -1); 213 | 214 | int ret; 215 | char buffer[1 + 12]; 216 | buffer[0] = BYTE_READ; 217 | *(int *)(buffer + 1) = size; 218 | *(int *)(buffer + 5) = count; 219 | *(int *)(buffer + 9) = fd; 220 | ret = sendwait(sock, buffer, 1 + 12); 221 | CHECK_ERROR(ret < 0); 222 | ret = recvbyte(sock); 223 | CHECK_ERROR(ret < 0); 224 | CHECK_ERROR(ret == BYTE_NORMAL); 225 | ret = recvwait(sock, result, 4); 226 | CHECK_ERROR(ret < 0); 227 | int sz; 228 | ret = recvwait(sock, &sz, 4); 229 | CHECK_ERROR(ret < 0); 230 | ret = recvwait(sock, ptr, sz); 231 | CHECK_ERROR(ret < 0); 232 | ret = sendbyte(sock, BYTE_OK); 233 | CHECK_ERROR(ret < 0); 234 | 235 | fspatchervars.lock = 0; 236 | return 0; 237 | error: 238 | fspatchervars.lock = 0; 239 | return -1; 240 | } 241 | 242 | int cafiine_fclose(void* pClient, int *result, int fd) { 243 | while (fspatchervars.lock) GX2WaitForVsync(); 244 | fspatchervars.lock = 1; 245 | 246 | int sock = fspatchervars.socket_fs[client_num(pClient)]; 247 | 248 | CHECK_ERROR(sock == -1); 249 | 250 | int ret; 251 | char buffer[1 + 4]; 252 | buffer[0] = BYTE_CLOSE; 253 | *(int *)(buffer + 1) = fd; 254 | ret = sendwait(sock, buffer, 1 + 4); 255 | CHECK_ERROR(ret < 0); 256 | ret = recvbyte(sock); 257 | CHECK_ERROR(ret < 0); 258 | CHECK_ERROR(ret == BYTE_NORMAL); 259 | ret = recvwait(sock, result, 4); 260 | CHECK_ERROR(ret < 0); 261 | 262 | fspatchervars.lock = 0; 263 | return 0; 264 | error: 265 | fspatchervars.lock = 0; 266 | return -1; 267 | } 268 | 269 | int cafiine_fsetpos(void *pClient, int *result, int fd, int set) { 270 | while (fspatchervars.lock) GX2WaitForVsync(); 271 | fspatchervars.lock = 1; 272 | 273 | int sock = fspatchervars.socket_fs[client_num(pClient)]; 274 | 275 | CHECK_ERROR(sock == -1); 276 | 277 | int ret; 278 | char buffer[1 + 8]; 279 | buffer[0] = BYTE_SETPOS; 280 | *(int *)(buffer + 1) = fd; 281 | *(int *)(buffer + 5) = set; 282 | ret = sendwait(sock, buffer, 1 + 8); 283 | CHECK_ERROR(ret < 0); 284 | ret = recvbyte(sock); 285 | CHECK_ERROR(ret < 0); 286 | CHECK_ERROR(ret == BYTE_NORMAL); 287 | ret = recvwait(sock, result, 4); 288 | CHECK_ERROR(ret < 0); 289 | 290 | fspatchervars.lock = 0; 291 | return 0; 292 | error: 293 | fspatchervars.lock = 0; 294 | return -1; 295 | } 296 | 297 | int cafiine_fgetpos(void* pClient, int *result, int fd, int *pos) { 298 | while (fspatchervars.lock) GX2WaitForVsync(); 299 | fspatchervars.lock = 1; 300 | 301 | int sock = fspatchervars.socket_fs[client_num(pClient)]; 302 | 303 | CHECK_ERROR(sock == -1); 304 | 305 | int ret; 306 | char buffer[1 + 4]; 307 | buffer[0] = BYTE_GETPOS; 308 | *(int *)(buffer + 1) = fd; 309 | ret = sendwait(sock, buffer, 1 + 4); 310 | CHECK_ERROR(ret < 0); 311 | ret = recvbyte(sock); 312 | CHECK_ERROR(ret < 0); 313 | CHECK_ERROR(ret == BYTE_NORMAL); 314 | ret = recvwait(sock, result, 4); 315 | CHECK_ERROR(ret < 0); 316 | ret = recvwait(sock, pos, 4); 317 | CHECK_ERROR(ret < 0); 318 | 319 | fspatchervars.lock = 0; 320 | return 0; 321 | error: 322 | fspatchervars.lock = 0; 323 | return -1; 324 | } 325 | 326 | int cafiine_fstat(void* pClient, int *result, int fd, void *ptr) { 327 | while (fspatchervars.lock) GX2WaitForVsync(); 328 | fspatchervars.lock = 1; 329 | 330 | int sock = fspatchervars.socket_fs[client_num(pClient)]; 331 | 332 | CHECK_ERROR(sock == -1); 333 | 334 | int ret; 335 | char buffer[1 + 4]; 336 | buffer[0] = BYTE_STATFILE; 337 | *(int *)(buffer + 1) = fd; 338 | ret = sendwait(sock, buffer, 1 + 4); 339 | CHECK_ERROR(ret < 0); 340 | ret = recvbyte(sock); 341 | CHECK_ERROR(ret < 0); 342 | CHECK_ERROR(ret == BYTE_NORMAL); 343 | ret = recvwait(sock, result, 4); 344 | CHECK_ERROR(ret < 0); 345 | int sz; 346 | ret = recvwait(sock, &sz, 4); 347 | CHECK_ERROR(ret < 0); 348 | if (ptr) { 349 | ret = recvwait(sock, ptr, sz); 350 | CHECK_ERROR(ret < 0); 351 | } 352 | 353 | fspatchervars.lock = 0; 354 | return 0; 355 | error: 356 | fspatchervars.lock = 0; 357 | return -1; 358 | } 359 | 360 | int cafiine_feof(void* pClient, int *result, int fd) { 361 | while (fspatchervars.lock) GX2WaitForVsync(); 362 | fspatchervars.lock = 1; 363 | 364 | int sock = fspatchervars.socket_fs[client_num(pClient)]; 365 | 366 | CHECK_ERROR(sock == -1); 367 | 368 | int ret; 369 | char buffer[1 + 4]; 370 | buffer[0] = BYTE_EOF; 371 | *(int *)(buffer + 1) = fd; 372 | ret = sendwait(sock, buffer, 1 + 4); 373 | CHECK_ERROR(ret < 0); 374 | ret = recvbyte(sock); 375 | CHECK_ERROR(ret < 0); 376 | CHECK_ERROR(ret == BYTE_NORMAL); 377 | ret = recvwait(sock, result, 4); 378 | CHECK_ERROR(ret < 0); 379 | 380 | fspatchervars.lock = 0; 381 | return 0; 382 | error: 383 | fspatchervars.lock = 0; 384 | return -1; 385 | } 386 | -------------------------------------------------------------------------------- /src/kernel/syscalls.c: -------------------------------------------------------------------------------- 1 | #include "common/os_defs.h" 2 | #include "common/kernel_defs.h" 3 | #include "common/common.h" 4 | #include "dynamic_libs/os_functions.h" 5 | #include "syscalls.h" 6 | 7 | extern void my_PrepareTitle_hook(void); 8 | 9 | static unsigned int origPrepareTitleInstr __attribute__((section(".data"))) = 0; 10 | 11 | static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len) 12 | { 13 | /* 14 | * Setup a DBAT access with cache inhibited to write through and read directly from memory 15 | */ 16 | unsigned int dbatu0, dbatl0, dbatu1, dbatl1; 17 | // save the original DBAT value 18 | asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); 19 | asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); 20 | asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); 21 | asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); 22 | 23 | unsigned int target_dbatu0 = 0; 24 | unsigned int target_dbatl0 = 0; 25 | unsigned int target_dbatu1 = 0; 26 | unsigned int target_dbatl1 = 0; 27 | 28 | unsigned char *dst_p = (unsigned char*)addr; 29 | unsigned char *src_p = (unsigned char*)src; 30 | 31 | // we only need DBAT modification for addresses out of our own DBAT range 32 | // as our own DBAT is available everywhere for user and supervisor 33 | // since our own DBAT is on DBAT5 position we don't collide here 34 | if(addr < 0x00800000 || addr >= 0x01000000) 35 | { 36 | target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F; 37 | target_dbatl0 = (addr & 0xFFF00000) | 0x32; 38 | asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); 39 | asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); 40 | dst_p = (unsigned char*)((addr & 0xFFFFFF) | 0xC0000000); 41 | } 42 | if(src < 0x00800000 || src >= 0x01000000) 43 | { 44 | target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F; 45 | target_dbatl1 = (src & 0xFFF00000) | 0x32; 46 | 47 | asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); 48 | asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); 49 | src_p = (unsigned char*)((src & 0xFFFFFF) | 0xB0000000); 50 | } 51 | 52 | asm volatile("eieio; isync"); 53 | 54 | unsigned int i; 55 | for(i = 0; i < len; i++) 56 | { 57 | // if we are on the edge to next chunk 58 | if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000))) 59 | { 60 | target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F; 61 | target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32; 62 | dst_p = (unsigned char*)(((addr + i) & 0xFFFFFF) | 0xC0000000); 63 | 64 | asm volatile("eieio; isync"); 65 | asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); 66 | asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); 67 | asm volatile("eieio; isync"); 68 | } 69 | if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000))) 70 | { 71 | target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F; 72 | target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32; 73 | src_p = (unsigned char*)(((src + i) & 0xFFFFFF) | 0xB0000000); 74 | 75 | asm volatile("eieio; isync"); 76 | asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); 77 | asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); 78 | asm volatile("eieio; isync"); 79 | } 80 | 81 | *dst_p = *src_p; 82 | 83 | ++dst_p; 84 | ++src_p; 85 | } 86 | 87 | /* 88 | * Restore original DBAT value 89 | */ 90 | asm volatile("eieio; isync"); 91 | asm volatile("mtdbatu 0, %0" : : "r" (dbatu0)); 92 | asm volatile("mtdbatl 0, %0" : : "r" (dbatl0)); 93 | asm volatile("mtdbatu 1, %0" : : "r" (dbatu1)); 94 | asm volatile("mtdbatl 1, %0" : : "r" (dbatl1)); 95 | asm volatile("eieio; isync"); 96 | } 97 | 98 | static void KernelReadDBATs(bat_table_t * table) 99 | { 100 | u32 i = 0; 101 | 102 | asm volatile("eieio; isync"); 103 | 104 | asm volatile("mfspr %0, 536" : "=r" (table->bat[i].h)); 105 | asm volatile("mfspr %0, 537" : "=r" (table->bat[i].l)); 106 | i++; 107 | asm volatile("mfspr %0, 538" : "=r" (table->bat[i].h)); 108 | asm volatile("mfspr %0, 539" : "=r" (table->bat[i].l)); 109 | i++; 110 | asm volatile("mfspr %0, 540" : "=r" (table->bat[i].h)); 111 | asm volatile("mfspr %0, 541" : "=r" (table->bat[i].l)); 112 | i++; 113 | asm volatile("mfspr %0, 542" : "=r" (table->bat[i].h)); 114 | asm volatile("mfspr %0, 543" : "=r" (table->bat[i].l)); 115 | i++; 116 | 117 | asm volatile("mfspr %0, 568" : "=r" (table->bat[i].h)); 118 | asm volatile("mfspr %0, 569" : "=r" (table->bat[i].l)); 119 | i++; 120 | asm volatile("mfspr %0, 570" : "=r" (table->bat[i].h)); 121 | asm volatile("mfspr %0, 571" : "=r" (table->bat[i].l)); 122 | i++; 123 | asm volatile("mfspr %0, 572" : "=r" (table->bat[i].h)); 124 | asm volatile("mfspr %0, 573" : "=r" (table->bat[i].l)); 125 | i++; 126 | asm volatile("mfspr %0, 574" : "=r" (table->bat[i].h)); 127 | asm volatile("mfspr %0, 575" : "=r" (table->bat[i].l)); 128 | } 129 | 130 | static void KernelWriteDBATs(bat_table_t * table) 131 | { 132 | u32 i = 0; 133 | 134 | asm volatile("eieio; isync"); 135 | 136 | asm volatile("mtspr 536, %0" : : "r" (table->bat[i].h)); 137 | asm volatile("mtspr 537, %0" : : "r" (table->bat[i].l)); 138 | i++; 139 | asm volatile("mtspr 538, %0" : : "r" (table->bat[i].h)); 140 | asm volatile("mtspr 539, %0" : : "r" (table->bat[i].l)); 141 | i++; 142 | asm volatile("mtspr 540, %0" : : "r" (table->bat[i].h)); 143 | asm volatile("mtspr 541, %0" : : "r" (table->bat[i].l)); 144 | i++; 145 | asm volatile("mtspr 542, %0" : : "r" (table->bat[i].h)); 146 | asm volatile("mtspr 543, %0" : : "r" (table->bat[i].l)); 147 | i++; 148 | 149 | asm volatile("mtspr 568, %0" : : "r" (table->bat[i].h)); 150 | asm volatile("mtspr 569, %0" : : "r" (table->bat[i].l)); 151 | i++; 152 | asm volatile("mtspr 570, %0" : : "r" (table->bat[i].h)); 153 | asm volatile("mtspr 571, %0" : : "r" (table->bat[i].l)); 154 | i++; 155 | asm volatile("mtspr 572, %0" : : "r" (table->bat[i].h)); 156 | asm volatile("mtspr 573, %0" : : "r" (table->bat[i].l)); 157 | i++; 158 | asm volatile("mtspr 574, %0" : : "r" (table->bat[i].h)); 159 | asm volatile("mtspr 575, %0" : : "r" (table->bat[i].l)); 160 | 161 | asm volatile("eieio; isync"); 162 | } 163 | 164 | /* Read a 32-bit word with kernel permissions */ 165 | uint32_t __attribute__ ((noinline)) kern_read(const void *addr) 166 | { 167 | uint32_t result; 168 | asm volatile ( 169 | "li 3,1\n" 170 | "li 4,0\n" 171 | "li 5,0\n" 172 | "li 6,0\n" 173 | "li 7,0\n" 174 | "lis 8,1\n" 175 | "mr 9,%1\n" 176 | "li 0,0x3400\n" 177 | "mr %0,1\n" 178 | "sc\n" 179 | "nop\n" 180 | "mr 1,%0\n" 181 | "mr %0,3\n" 182 | : "=r"(result) 183 | : "b"(addr) 184 | : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", 185 | "11", "12" 186 | ); 187 | 188 | return result; 189 | } 190 | 191 | /* Write a 32-bit word with kernel permissions */ 192 | void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) 193 | { 194 | asm volatile ( 195 | "li 3,1\n" 196 | "li 4,0\n" 197 | "mr 5,%1\n" 198 | "li 6,0\n" 199 | "li 7,0\n" 200 | "lis 8,1\n" 201 | "mr 9,%0\n" 202 | "mr %1,1\n" 203 | "li 0,0x3500\n" 204 | "sc\n" 205 | "nop\n" 206 | "mr 1,%1\n" 207 | : 208 | : "r"(addr), "r"(value) 209 | : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", 210 | "11", "12" 211 | ); 212 | } 213 | 214 | void KernelSetupSyscalls(void) 215 | { 216 | //! assign 1 so that this variable gets into the retained .data section 217 | static uint8_t ucSyscallsSetupRequired = 1; 218 | if(!ucSyscallsSetupRequired) 219 | return; 220 | 221 | ucSyscallsSetupRequired = 0; 222 | 223 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x36 * 4)), (unsigned int)KernelReadDBATs); 224 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x36 * 4)), (unsigned int)KernelReadDBATs); 225 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x36 * 4)), (unsigned int)KernelReadDBATs); 226 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x36 * 4)), (unsigned int)KernelReadDBATs); 227 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x36 * 4)), (unsigned int)KernelReadDBATs); 228 | 229 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); 230 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); 231 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); 232 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); 233 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); 234 | 235 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int)KernelCopyData); 236 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int)KernelCopyData); 237 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int)KernelCopyData); 238 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int)KernelCopyData); 239 | kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int)KernelCopyData); 240 | 241 | //! write our hook to the 242 | u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003; 243 | DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook)); 244 | 245 | SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4); 246 | SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4); 247 | } 248 | 249 | 250 | void KernelRestoreInstructions(void) 251 | { 252 | if(origPrepareTitleInstr != 0) 253 | SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&origPrepareTitleInstr, 4); 254 | } 255 | -------------------------------------------------------------------------------- /src/gecko/pygecko.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common/common.h" 4 | #include "dynamic_libs/os_functions.h" 5 | #include "dynamic_libs/socket_functions.h" 6 | #include "dynamic_libs/gx2_functions.h" 7 | #include "kernel/syscalls.h" 8 | 9 | struct pygecko_bss_t { 10 | int error, line; 11 | void* thread; 12 | unsigned char stack[0x8000]; 13 | }; 14 | 15 | #define CHECK_ERROR(cond) if (cond) { bss->line = __LINE__; goto error; } 16 | #define errno (*__gh_errno_ptr()) 17 | #define EWOULDBLOCK 6 18 | 19 | static int recvwait(struct pygecko_bss_t *bss, int sock, void *buffer, int len) { 20 | int ret; 21 | while (len > 0) { 22 | ret = recv(sock, buffer, len, 0); 23 | CHECK_ERROR(ret < 0); 24 | len -= ret; 25 | buffer += ret; 26 | } 27 | return 0; 28 | error: 29 | bss->error = ret; 30 | return ret; 31 | } 32 | 33 | static int recvbyte(struct pygecko_bss_t *bss, int sock) { 34 | unsigned char buffer[1]; 35 | int ret; 36 | 37 | ret = recvwait(bss, sock, buffer, 1); 38 | if (ret < 0) return ret; 39 | return buffer[0]; 40 | } 41 | 42 | static int checkbyte(struct pygecko_bss_t *bss, int sock) { 43 | unsigned char buffer[1]; 44 | int ret; 45 | 46 | ret = recv(sock, buffer, 1, MSG_DONTWAIT); 47 | if (ret < 0) return ret; 48 | if (ret == 0) return -1; 49 | return buffer[0]; 50 | } 51 | 52 | static int sendwait(struct pygecko_bss_t *bss, int sock, const void *buffer, int len) { 53 | int ret; 54 | while (len > 0) { 55 | ret = send(sock, buffer, len, 0); 56 | CHECK_ERROR(ret < 0); 57 | len -= ret; 58 | buffer += ret; 59 | } 60 | return 0; 61 | error: 62 | bss->error = ret; 63 | return ret; 64 | } 65 | 66 | static int sendbyte(struct pygecko_bss_t *bss, int sock, unsigned char byte) { 67 | unsigned char buffer[1]; 68 | 69 | buffer[0] = byte; 70 | return sendwait(bss, sock, buffer, 1); 71 | } 72 | 73 | static int rungecko(struct pygecko_bss_t *bss, int clientfd) { 74 | int ret; 75 | unsigned char buffer[0x401]; 76 | 77 | while (1) { 78 | ret = checkbyte(bss, clientfd); 79 | 80 | if (ret < 0) { 81 | CHECK_ERROR(errno != EWOULDBLOCK); 82 | GX2WaitForVsync(); 83 | continue; 84 | } 85 | 86 | switch (ret) { 87 | case 0x01: { /* cmd_poke08 */ 88 | char *ptr; 89 | ret = recvwait(bss, clientfd, buffer, 8); 90 | CHECK_ERROR(ret < 0); 91 | 92 | ptr = ((char **)buffer)[0]; 93 | *ptr = buffer[7]; 94 | DCFlushRange(ptr, 1); 95 | break; 96 | } 97 | case 0x02: { /* cmd_poke16 */ 98 | short *ptr; 99 | ret = recvwait(bss, clientfd, buffer, 8); 100 | CHECK_ERROR(ret < 0); 101 | 102 | ptr = ((short **)buffer)[0]; 103 | *ptr = ((short *)buffer)[3]; 104 | DCFlushRange(ptr, 2); 105 | break; 106 | } 107 | case 0x03: { /* cmd_pokemem */ 108 | int *ptr; 109 | ret = recvwait(bss, clientfd, buffer, 8); 110 | CHECK_ERROR(ret < 0); 111 | 112 | ptr = ((int **)buffer)[0]; 113 | *ptr = ((int *)buffer)[1]; 114 | DCFlushRange(ptr, 4); 115 | break; 116 | } 117 | case 0x04: { /* cmd_readmem */ 118 | const unsigned char *ptr, *end; 119 | ret = recvwait(bss, clientfd, buffer, 8); 120 | CHECK_ERROR(ret < 0); 121 | ptr = ((const unsigned char **)buffer)[0]; 122 | end = ((const unsigned char **)buffer)[1]; 123 | 124 | while (ptr != end) { 125 | int len, i; 126 | 127 | len = end - ptr; 128 | if (len > 0x400) 129 | len = 0x400; 130 | for (i = 0; i < len; i++) 131 | if (ptr[i] != 0) break; 132 | 133 | if (i == len) { // all zero! 134 | ret = sendbyte(bss, clientfd, 0xb0); 135 | CHECK_ERROR(ret < 0); 136 | } else { 137 | memcpy(buffer + 1, ptr, len); 138 | buffer[0] = 0xbd; 139 | ret = sendwait(bss, clientfd, buffer, len + 1); 140 | CHECK_ERROR(ret < 0); 141 | } 142 | 143 | ret = checkbyte(bss, clientfd); 144 | if (ret == 0xcc) /* GCFAIL */ 145 | goto next_cmd; 146 | ptr += len; 147 | } 148 | break; 149 | } 150 | case 0x0b: { /* cmd_writekern */ 151 | void *ptr, * value; 152 | ret = recvwait(bss, clientfd, buffer, 8); 153 | CHECK_ERROR(ret < 0); 154 | 155 | ptr = ((void **)buffer)[0]; 156 | value = ((void **)buffer)[1]; 157 | 158 | kern_write(ptr, (uint32_t)value); 159 | break; 160 | } 161 | case 0x0c: { /* cmd_readkern */ 162 | void *ptr, *value; 163 | ret = recvwait(bss, clientfd, buffer, 4); 164 | CHECK_ERROR(ret < 0); 165 | 166 | ptr = ((void **)buffer)[0]; 167 | 168 | value = (void*)kern_read(ptr); 169 | 170 | *(void **)buffer = value; 171 | sendwait(bss, clientfd, buffer, 4); 172 | break; 173 | } 174 | case 0x41: { /* cmd_upload */ 175 | unsigned char *ptr, *end, *dst; 176 | ret = recvwait(bss, clientfd, buffer, 8); 177 | CHECK_ERROR(ret < 0); 178 | ptr = ((unsigned char **)buffer)[0]; 179 | end = ((unsigned char **)buffer)[1]; 180 | 181 | while (ptr != end) { 182 | int len; 183 | 184 | len = end - ptr; 185 | if (len > 0x400) 186 | len = 0x400; 187 | if ((int)ptr >= 0x10000000 && (int)ptr <= 0x50000000) { 188 | dst = ptr; 189 | } else { 190 | dst = buffer; 191 | } 192 | ret = recvwait(bss, clientfd, dst, len); 193 | CHECK_ERROR(ret < 0); 194 | if (dst == buffer) { 195 | memcpy(ptr, buffer, len); 196 | } 197 | 198 | ptr += len; 199 | } 200 | 201 | sendbyte(bss, clientfd, 0xaa); /* GCACK */ 202 | break; 203 | } 204 | case 0x50: { /* cmd_status */ 205 | ret = sendbyte(bss, clientfd, 1); /* running */ 206 | CHECK_ERROR(ret < 0); 207 | break; 208 | } 209 | case 0x70: { /* cmd_rpc */ 210 | long long (*fun)(int, int, int, int, int, int, int, int); 211 | int r3, r4, r5, r6, r7, r8, r9, r10; 212 | long long result; 213 | 214 | ret = recvwait(bss, clientfd, buffer, 4 + 8 * 4); 215 | CHECK_ERROR(ret < 0); 216 | 217 | fun = ((void **)buffer)[0]; 218 | r3 = ((int *)buffer)[1]; 219 | r4 = ((int *)buffer)[2]; 220 | r5 = ((int *)buffer)[3]; 221 | r6 = ((int *)buffer)[4]; 222 | r7 = ((int *)buffer)[5]; 223 | r8 = ((int *)buffer)[6]; 224 | r9 = ((int *)buffer)[7]; 225 | r10 = ((int *)buffer)[8]; 226 | 227 | result = fun(r3, r4, r5, r6, r7, r8, r9, r10); 228 | 229 | ((long long *)buffer)[0] = result; 230 | ret = sendwait(bss, clientfd, buffer, 8); 231 | CHECK_ERROR(ret < 0); 232 | break; 233 | } 234 | case 0x71: { /* cmd_getsymbol */ 235 | int size = recvbyte(bss, clientfd); 236 | CHECK_ERROR(size < 0); 237 | ret = recvwait(bss, clientfd, buffer, size); 238 | CHECK_ERROR(ret < 0); 239 | 240 | /* Identify the RPL name and symbol name */ 241 | char *rplname = (char*) &((int*)buffer)[2]; 242 | char *symname = (char*) (&buffer[0] + ((int*)buffer)[1]); 243 | 244 | /* Get the symbol and store it in the buffer */ 245 | unsigned int module_handle, function_address; 246 | OSDynLoad_Acquire(rplname, &module_handle); 247 | 248 | char data = recvbyte(bss, clientfd); 249 | OSDynLoad_FindExport(module_handle, data, symname, &function_address); 250 | 251 | ((int*)buffer)[0] = (int)function_address; 252 | ret = sendwait(bss, clientfd, buffer, 4); 253 | CHECK_ERROR(ret < 0); 254 | break; 255 | } 256 | case 0x72: { /* cmd_search32 */ 257 | ret = recvwait(bss, clientfd, buffer, 12); 258 | CHECK_ERROR(ret < 0); 259 | int addr = ((int *) buffer)[0]; 260 | int val = ((int *) buffer)[1]; 261 | int size = ((int *) buffer)[2]; 262 | int i; 263 | int resaddr = 0; 264 | for(i = addr; i < (addr+size); i+=4) 265 | { 266 | if(*(int*)i == val) 267 | { 268 | resaddr = i; 269 | break; 270 | } 271 | } 272 | ((int *)buffer)[0] = resaddr; 273 | ret = sendwait(bss, clientfd, buffer, 4); 274 | CHECK_ERROR(ret < 0); 275 | break; 276 | } 277 | case 0x80: { /* cmd_rpc_big */ 278 | long long (*fun)(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); 279 | int r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18; 280 | long long result; 281 | 282 | ret = recvwait(bss, clientfd, buffer, 4 + 16 * 4); 283 | CHECK_ERROR(ret < 0); 284 | 285 | fun = ((void **)buffer)[0]; 286 | r3 = ((int *)buffer)[1]; 287 | r4 = ((int *)buffer)[2]; 288 | r5 = ((int *)buffer)[3]; 289 | r6 = ((int *)buffer)[4]; 290 | r7 = ((int *)buffer)[5]; 291 | r8 = ((int *)buffer)[6]; 292 | r9 = ((int *)buffer)[7]; 293 | r10 = ((int *)buffer)[8]; 294 | r11 = ((int *)buffer)[9]; 295 | r12 = ((int *)buffer)[10]; 296 | r13 = ((int *)buffer)[11]; 297 | r14 = ((int *)buffer)[12]; 298 | r15 = ((int *)buffer)[13]; 299 | r16 = ((int *)buffer)[14]; 300 | r17 = ((int *)buffer)[15]; 301 | r18 = ((int *)buffer)[16]; 302 | 303 | result = fun(r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18); 304 | 305 | ((long long *)buffer)[0] = result; 306 | ret = sendwait(bss, clientfd, buffer, 8); 307 | CHECK_ERROR(ret < 0); 308 | break; 309 | } 310 | case 0x99: { /* cmd_version */ 311 | ret = sendbyte(bss, clientfd, 0x82); /* WiiU */ 312 | CHECK_ERROR(ret < 0); 313 | break; 314 | } 315 | case 0x9A: { /* cmd_os_version */ 316 | ((int *)buffer)[0] = (int)OS_FIRMWARE; 317 | ret = sendwait(bss, clientfd, buffer, 4); 318 | CHECK_ERROR(ret < 0); 319 | break; 320 | } 321 | case 0xcc: { /* GCFAIL */ 322 | break; 323 | } 324 | default: 325 | ret = -1; 326 | CHECK_ERROR(0); 327 | break; 328 | } 329 | next_cmd: 330 | continue; 331 | } 332 | return 0; 333 | error: 334 | bss->error = ret; 335 | return 0; 336 | } 337 | 338 | static int pygecko_main(int argc, void *argv) { 339 | int sockfd = -1, clientfd = -1, ret, len; 340 | struct sockaddr_in addr; 341 | struct pygecko_bss_t *bss = argv; 342 | 343 | socket_lib_init(); 344 | 345 | while (1) { 346 | addr.sin_family = AF_INET; 347 | addr.sin_port = 7331; 348 | addr.sin_addr.s_addr = 0; 349 | 350 | sockfd = ret = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 351 | CHECK_ERROR(ret == -1); 352 | int enable = 1; 353 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); 354 | ret = bind(sockfd, (void *)&addr, 16); 355 | CHECK_ERROR(ret < 0); 356 | ret = listen(sockfd, 1); 357 | CHECK_ERROR(ret < 0); 358 | 359 | while(1) 360 | { 361 | len = 16; 362 | clientfd = ret = accept(sockfd, (void *)&addr, &len); 363 | CHECK_ERROR(ret == -1); 364 | rungecko(bss, clientfd); 365 | socketclose(clientfd); 366 | clientfd = -1; 367 | } 368 | continue; 369 | error: 370 | if (clientfd != -1) 371 | socketclose(clientfd); 372 | if (sockfd != -1) 373 | socketclose(sockfd); 374 | clientfd = -1; 375 | sockfd = -1; 376 | bss->error = ret; 377 | os_usleep(100000); 378 | } 379 | return 0; 380 | } 381 | 382 | void start_pygecko(void) 383 | { 384 | struct pygecko_bss_t *bss; 385 | 386 | bss = memalign(0x40, sizeof(struct pygecko_bss_t)); 387 | if (bss == 0) 388 | return; 389 | memset(bss, 0, sizeof(struct pygecko_bss_t)); 390 | 391 | if(OSCreateThread(&bss->thread, pygecko_main, 1, bss, (u32)bss->stack + sizeof(bss->stack), sizeof(bss->stack), 0, 0x1C) == 1) 392 | { 393 | OSResumeThread(&bss->thread); 394 | } 395 | else 396 | { 397 | free(bss); 398 | } 399 | } 400 | -------------------------------------------------------------------------------- /src/utils/function_patcher.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2016 Maschell 3 | * With code from chadderz and dimok 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | ****************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "function_patcher.h" 26 | #include "utils/logger.h" 27 | #include "common/kernel_defs.h" 28 | #include "kernel/kernel_functions.h" 29 | 30 | #define LIB_CODE_RW_BASE_OFFSET 0xC1000000 31 | #define CODE_RW_BASE_OFFSET 0x00000000 32 | #define DEBUG_LOG_DYN 0 33 | 34 | 35 | /* 36 | * Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic. 37 | * "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok. Orignal code by Chadderz. 38 | */ 39 | void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int hook_information_size, volatile unsigned int dynamic_method_calls[]) 40 | { 41 | log_printf("Patching %d given functions\n",hook_information_size); 42 | /* Patch branches to it. */ 43 | volatile unsigned int *space = &dynamic_method_calls[0]; 44 | 45 | int method_hooks_count = hook_information_size; 46 | 47 | u32 skip_instr = 1; 48 | u32 my_instr_len = 6; 49 | u32 instr_len = my_instr_len + skip_instr; 50 | u32 flush_len = 4*instr_len; 51 | for(int i = 0; i < method_hooks_count; i++) 52 | { 53 | log_printf("Patching %s ...",method_hooks[i].functionName); 54 | if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){ 55 | if(isDynamicFunction((u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr))){ 56 | log_printf("The function %s is a dynamic function. Please fix that <3\n", method_hooks[i].functionName); 57 | method_hooks[i].functionType = DYNAMIC_FUNCTION; 58 | }else{ 59 | log_printf("Skipping %s, its already patched\n", method_hooks[i].functionName); 60 | space += instr_len; 61 | continue; 62 | } 63 | } 64 | 65 | u32 physical = 0; 66 | unsigned int repl_addr = (unsigned int)method_hooks[i].replaceAddr; 67 | unsigned int call_addr = (unsigned int)method_hooks[i].replaceCall; 68 | 69 | unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library); 70 | 71 | if(!real_addr){ 72 | log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName); 73 | space += instr_len; 74 | continue; 75 | } 76 | 77 | if(DEBUG_LOG_DYN){log_printf("%s is located at %08X!\n", method_hooks[i].functionName,real_addr);} 78 | 79 | physical = (u32)OSEffectiveToPhysical((void*)real_addr); 80 | if(!physical){ 81 | log_printf("Error. Something is wrong with the physical address\n"); 82 | space += instr_len; 83 | continue; 84 | } 85 | 86 | if(DEBUG_LOG_DYN){log_printf("%s physical is located at %08X!\n", method_hooks[i].functionName,physical);} 87 | 88 | *(volatile unsigned int *)(call_addr) = (unsigned int)(space) - CODE_RW_BASE_OFFSET; 89 | 90 | 91 | SC0x25_KernelCopyData((u32)space, physical, 4); 92 | space++; 93 | 94 | //Only works if skip_instr == 1 95 | if(skip_instr == 1){ 96 | // fill the restore instruction section 97 | method_hooks[i].realAddr = real_addr; 98 | method_hooks[i].restoreInstruction = *(space-1); 99 | if(DEBUG_LOG_DYN){log_printf("method_hooks[i].realAddr = %08X!\n", method_hooks[i].realAddr);} 100 | if(DEBUG_LOG_DYN){log_printf("method_hooks[i].restoreInstruction = %08X!\n",method_hooks[i].restoreInstruction) ;} 101 | } 102 | else{ 103 | log_printf("Error. Can't save %s for restoring!\n", method_hooks[i].functionName); 104 | } 105 | 106 | //adding jump to real function thx @ dimok for the assembler code 107 | /* 108 | 90 61 ff e0 stw r3,-32(r1) 109 | 3c 60 12 34 lis r3,4660 110 | 60 63 56 78 ori r3,r3,22136 111 | 7c 69 03 a6 mtctr r3 112 | 80 61 ff e0 lwz r3,-32(r1) 113 | 4e 80 04 20 bctr*/ 114 | *space = 0x9061FFE0; 115 | space++; 116 | *space = 0x3C600000 | (((real_addr + (skip_instr * 4)) >> 16) & 0x0000FFFF); // lis r3, real_addr@h 117 | space++; 118 | *space = 0x60630000 | ((real_addr + (skip_instr * 4)) & 0x0000ffff); // ori r3, r3, real_addr@l 119 | space++; 120 | *space = 0x7C6903A6; // mtctr r3 121 | space++; 122 | *space = 0x8061FFE0; // lwz r3,-32(r1) 123 | space++; 124 | *space = 0x4E800420; // bctr 125 | space++; 126 | DCFlushRange((void*)(space - instr_len), flush_len); 127 | ICInvalidateRange((unsigned char*)(space - instr_len), flush_len); 128 | 129 | //setting jump back 130 | unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc); 131 | DCFlushRange(&replace_instr, 4); 132 | 133 | SC0x25_KernelCopyData(physical, (u32)OSEffectiveToPhysical(&replace_instr), 4); 134 | ICInvalidateRange((void*)(real_addr), 4); 135 | 136 | method_hooks[i].alreadyPatched = 1; 137 | log_printf("done!\n"); 138 | 139 | } 140 | log_print("Done with patching given functions!\n"); 141 | } 142 | 143 | /* ****************************************************************** */ 144 | /* RESTORE ORIGINAL INSTRUCTIONS */ 145 | /* ****************************************************************** */ 146 | void RestoreInvidualInstructions(hooks_magic_t method_hooks[],int hook_information_size) 147 | { 148 | log_printf("Restoring given functions!\n"); 149 | int method_hooks_count = hook_information_size; 150 | for(int i = 0; i < method_hooks_count; i++) 151 | { 152 | log_printf("Restoring %s... ",method_hooks[i].functionName); 153 | if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0){ 154 | log_printf("I dont have the information for the restore =( skip\n"); 155 | continue; 156 | } 157 | 158 | unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library); 159 | 160 | if(!real_addr){ 161 | log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName); 162 | continue; 163 | } 164 | 165 | u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr); 166 | if(!physical){ 167 | log_printf("Something is wrong with the physical address\n"); 168 | continue; 169 | } 170 | 171 | if(isDynamicFunction(physical)) 172 | { 173 | log_printf("Its a dynamic function. We don't need to restore it!\n",method_hooks[i].functionName); 174 | } 175 | else 176 | { 177 | physical = (u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr); //When its an static function, we need to use the old location 178 | if(DEBUG_LOG_DYN){log_printf("Restoring %08X to %08X\n",(u32)method_hooks[i].restoreInstruction,physical);} 179 | SC0x25_KernelCopyData(physical,(u32)&method_hooks[i].restoreInstruction , 4); 180 | if(DEBUG_LOG_DYN){log_printf("ICInvalidateRange %08X\n",(void*)method_hooks[i].realAddr);} 181 | ICInvalidateRange((void*)method_hooks[i].realAddr, 4); 182 | log_printf("done\n"); 183 | } 184 | method_hooks[i].alreadyPatched = 0; // In case a 185 | } 186 | 187 | log_print("Done with restoring given functions!\n"); 188 | } 189 | 190 | int isDynamicFunction(unsigned int physicalAddress){ 191 | if((physicalAddress & 0x80000000) == 0x80000000){ 192 | return 1; 193 | } 194 | return 0; 195 | } 196 | 197 | unsigned int GetAddressOfFunction(const char * functionName,unsigned int library){ 198 | unsigned int real_addr = 0; 199 | 200 | if(strcmp(functionName, "OSDynLoad_Acquire") == 0) 201 | { 202 | memcpy(&real_addr, &OSDynLoad_Acquire, 4); 203 | return real_addr; 204 | } 205 | else if(strcmp(functionName, "LiWaitOneChunk") == 0) 206 | { 207 | real_addr = (unsigned int)addr_LiWaitOneChunk; 208 | return real_addr; 209 | } 210 | else if(strcmp(functionName, "LiBounceOneChunk") == 0) 211 | { 212 | //! not required on firmwares above 3.1.0 213 | if(OS_FIRMWARE >= 400) 214 | return 0; 215 | 216 | unsigned int addr_LiBounceOneChunk = 0x010003A0; 217 | real_addr = (unsigned int)addr_LiBounceOneChunk; 218 | return real_addr; 219 | } 220 | 221 | unsigned int rpl_handle = 0; 222 | if(library == LIB_CORE_INIT){ 223 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_CORE_INIT\n", functionName);} 224 | if(coreinit_handle == 0){log_print("LIB_CORE_INIT not acquired\n"); return 0;} 225 | rpl_handle = coreinit_handle; 226 | } 227 | else if(library == LIB_NSYSNET){ 228 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_NSYSNET\n", functionName);} 229 | if(nsysnet_handle == 0){log_print("LIB_NSYSNET not acquired\n"); return 0;} 230 | rpl_handle = nsysnet_handle; 231 | } 232 | else if(library == LIB_GX2){ 233 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_GX2\n", functionName);} 234 | if(gx2_handle == 0){log_print("LIB_GX2 not acquired\n"); return 0;} 235 | rpl_handle = gx2_handle; 236 | } 237 | else if(library == LIB_AOC){ 238 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_AOC\n", functionName);} 239 | if(aoc_handle == 0){log_print("LIB_AOC not acquired\n"); return 0;} 240 | rpl_handle = aoc_handle; 241 | } 242 | else if(library == LIB_AX){ 243 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_AX\n", functionName);} 244 | if(sound_handle == 0){log_print("LIB_AX not acquired\n"); return 0;} 245 | rpl_handle = sound_handle; 246 | } 247 | else if(library == LIB_AX_OLD){ 248 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_AX_OLD\n", functionName);} 249 | if(sound_handle_old == 0){log_print("LIB_AX_OLD not acquired\n"); return 0;} 250 | rpl_handle = sound_handle_old; 251 | } 252 | else if(library == LIB_FS){ 253 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_FS\n", functionName);} 254 | if(coreinit_handle == 0){log_print("LIB_FS not acquired\n"); return 0;} 255 | rpl_handle = coreinit_handle; 256 | } 257 | else if(library == LIB_OS){ 258 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_OS\n", functionName);} 259 | if(coreinit_handle == 0){log_print("LIB_OS not acquired\n"); return 0;} 260 | rpl_handle = coreinit_handle; 261 | } 262 | else if(library == LIB_PADSCORE){ 263 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_PADSCORE\n", functionName);} 264 | if(padscore_handle == 0){log_print("LIB_PADSCORE not acquired\n"); return 0;} 265 | rpl_handle = padscore_handle; 266 | } 267 | else if(library == LIB_SOCKET){ 268 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_SOCKET\n", functionName);} 269 | if(nsysnet_handle == 0){log_print("LIB_SOCKET not acquired\n"); return 0;} 270 | rpl_handle = nsysnet_handle; 271 | } 272 | else if(library == LIB_SYS){ 273 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_SYS\n", functionName);} 274 | if(sysapp_handle == 0){log_print("LIB_SYS not acquired\n"); return 0;} 275 | rpl_handle = sysapp_handle; 276 | } 277 | else if(library == LIB_VPAD){ 278 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_VPAD\n", functionName);} 279 | if(vpad_handle == 0){log_print("LIB_VPAD not acquired\n"); return 0;} 280 | rpl_handle = vpad_handle; 281 | } 282 | else if(library == LIB_NN_ACP){ 283 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_NN_ACP\n", functionName);} 284 | if(acp_handle == 0){log_print("LIB_NN_ACP not acquired\n"); return 0;} 285 | rpl_handle = acp_handle; 286 | } 287 | else if(library == LIB_SYSHID){ 288 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_SYSHID\n", functionName);} 289 | if(syshid_handle == 0){log_print("LIB_SYSHID not acquired\n"); return 0;} 290 | rpl_handle = syshid_handle; 291 | } 292 | else if(library == LIB_VPADBASE){ 293 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_VPADBASE\n", functionName);} 294 | if(vpadbase_handle == 0){log_print("LIB_VPADBASE not acquired\n"); return 0;} 295 | rpl_handle = vpadbase_handle; 296 | } 297 | else if(library == LIB_PROC_UI){ 298 | if(DEBUG_LOG_DYN){log_printf("FindExport of %s! From LIB_PROC_UI\n", functionName);} 299 | if(proc_ui_handle == 0){log_print("LIB_PROC_UI not acquired\n"); return 0;} 300 | rpl_handle = proc_ui_handle; 301 | } 302 | 303 | if(!rpl_handle){ 304 | log_printf("Failed to find the RPL handle for %s\n", functionName); 305 | return 0; 306 | } 307 | 308 | OSDynLoad_FindExport(rpl_handle, 0, functionName, &real_addr); 309 | 310 | if(!real_addr){ 311 | log_printf("OSDynLoad_FindExport failed for %s\n", functionName); 312 | return 0; 313 | } 314 | 315 | if((library == LIB_NN_ACP) && (u32)(*(volatile unsigned int*)(real_addr) & 0x48000002) == 0x48000000) 316 | { 317 | unsigned int address_diff = (u32)(*(volatile unsigned int*)(real_addr) & 0x03FFFFFC); 318 | if((address_diff & 0x03000000) == 0x03000000) { 319 | address_diff |= 0xFC000000; 320 | } 321 | real_addr += (int)address_diff; 322 | if((u32)(*(volatile unsigned int*)(real_addr) & 0x48000002) == 0x48000000){ 323 | return 0; 324 | } 325 | } 326 | 327 | return real_addr; 328 | } 329 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "main.h" 7 | #include "dynamic_libs/os_functions.h" 8 | #include "dynamic_libs/gx2_functions.h" 9 | #include "dynamic_libs/ax_functions.h" 10 | #include "dynamic_libs/socket_functions.h" 11 | #include "dynamic_libs/sys_functions.h" 12 | #include "dynamic_libs/fs_functions.h" 13 | #include "dynamic_libs/vpad_functions.h" 14 | #include "dynamic_libs/proc_ui_functions.h" 15 | #include "utils/logger.h" 16 | #include "system/memory.h" 17 | #include "common/common.h" 18 | #include "patcher/cafiine_function_patcher.h" 19 | #include "patcher/voice_swapping_function_patcher.h" 20 | #include "patcher/video_swapping_function_patcher.h" 21 | #include "patcher/vpad_function_patcher.h" 22 | #include "patcher/proc_ui_function_patcher.h" 23 | #include "kernel/kernel_functions.h" 24 | #include "gecko/pygecko.h" 25 | #include "cafiine/cafiine.h" 26 | #include "retain_vars.h" 27 | 28 | #define PRINT_TEXT1(x, y, str) { OSScreenPutFontEx(1, x, y, str); } 29 | #define PRINT_TEXT2(x, y, ...) { snprintf(msg, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, msg); OSScreenPutFontEx(1, x, y, msg); } 30 | #define PRINT_TEXT3(x, y, _fmt, ...) { __os_snprintf(msg, 80, _fmt, __VA_ARGS__); OSScreenPutFontEx(1, x, y, msg); } 31 | 32 | #define BUILD "1.3.2" 33 | 34 | u8 isFirstBoot __attribute__((section(".data"))) = 1; 35 | 36 | /* IP union */ 37 | typedef union u_serv_ip 38 | { 39 | uint8_t digit[4]; 40 | uint32_t full; 41 | } u_serv_ip; 42 | 43 | void gambitBootScreen() 44 | { 45 | memoryInitialize(); 46 | // Init screen and screen buffers 47 | OSScreenInit(); 48 | int screen_buf0_size = OSScreenGetBufferSizeEx(0); 49 | int screen_buf1_size = OSScreenGetBufferSizeEx(1); 50 | unsigned char *screenBuffer = MEM1_alloc(screen_buf0_size + screen_buf1_size, 0x100); 51 | char msg[80]; 52 | 53 | OSScreenSetBufferEx(0, screenBuffer); 54 | OSScreenSetBufferEx(1, (screenBuffer + screen_buf0_size)); 55 | 56 | OSScreenEnableEx(0, 1); 57 | OSScreenEnableEx(1, 1); 58 | 59 | PRINT_TEXT2(0, 1, "Splatoon detected! Enhancing swap controls..."); 60 | PRINT_TEXT2(2, 4, "Tips:"); 61 | PRINT_TEXT2(2, 6, "Press B to swap displays except in-game menus."); 62 | PRINT_TEXT2(2, 7, "Hold A + D-PAD to super jump to a teammate in a match."); 63 | 64 | PRINT_TEXT2(10, 10, " Teammate 2"); 65 | PRINT_TEXT2(10, 11, " _ "); 66 | PRINT_TEXT2(10, 12, " _| |_"); 67 | PRINT_TEXT2(10, 13, "Teammate 1 |_ _| Teammate 3"); 68 | PRINT_TEXT2(10, 14, " |_|"); 69 | PRINT_TEXT2(10, 16, " Spawn Point"); 70 | 71 | PRINT_TEXT2(50, 9, " ____________"); 72 | PRINT_TEXT2(50, 10, "| Teammate 1 |"); 73 | PRINT_TEXT2(50, 10, " ____________"); 74 | PRINT_TEXT2(50, 11, " ____________"); 75 | PRINT_TEXT2(50, 12, "| Teammate 2 |"); 76 | PRINT_TEXT2(50, 12, " ____________"); 77 | PRINT_TEXT2(50, 13, " ____________"); 78 | PRINT_TEXT2(50, 14, "| Teammate 3 |"); 79 | PRINT_TEXT2(50, 14, " ____________"); 80 | PRINT_TEXT2(55, 15, " _______"); 81 | PRINT_TEXT2(55, 16, "| Spawn |"); 82 | PRINT_TEXT2(55, 17, "| Point |"); 83 | PRINT_TEXT2(55, 17, " _______"); 84 | 85 | OSScreenFlipBuffersEx(0); 86 | OSScreenFlipBuffersEx(1); 87 | 88 | os_sleep(1); 89 | MEM1_free(screenBuffer); 90 | screenBuffer = NULL; 91 | 92 | memoryRelease(); 93 | } 94 | 95 | /* Entry point */ 96 | int Menu_Main() 97 | { 98 | //!******************************************************************* 99 | //! Initialize function pointers * 100 | //!******************************************************************* 101 | //! do OS (for acquire) and sockets first so we got logging 102 | InitOSFunctionPointers(); 103 | InitSocketFunctionPointers(); 104 | InitGX2FunctionPointers(); 105 | InitSysFunctionPointers(); 106 | InitVPadFunctionPointers(); 107 | InitAXFunctionPointers(); 108 | InitProcUIFunctionPointers(); 109 | #if !LITE 110 | InitFSFunctionPointers(); 111 | #endif 112 | 113 | 114 | log_init("192.168.2.18"); 115 | 116 | SetupKernelCallback(); 117 | 118 | log_printf("SWAP DRC started\n"); 119 | 120 | memset(gVoiceInfos, 0, sizeof(gVoiceInfos)); 121 | memset(&fspatchervars,0,sizeof(fspatchervars)); 122 | 123 | //Reset everything when were going back to the Mii Maker 124 | if(!isFirstBoot && isInMiiMakerHBL()){ 125 | log_printf("Returing to the Homebrew Launcher!\n"); 126 | isFirstBoot = 0; 127 | deInit(); 128 | return EXIT_SUCCESS; 129 | } 130 | 131 | ApplyPatches(); 132 | 133 | #if !LITE 134 | log_printf("Starting the TCPGecko server.\n"); 135 | start_pygecko(); 136 | #endif 137 | 138 | if(!isInMiiMakerHBL()){ //Starting the application 139 | // Check for Splatoon (Gambit) 140 | if (isInSplatoon()) 141 | { 142 | log_printf("Splatoon enhanced swapping enabled.\n"); 143 | gambitBootScreen(); 144 | isSplatoon = 1; 145 | } 146 | else { 147 | log_printf("Splatoon enhanced swapping disabled.\n"); 148 | isSplatoon = 0; 149 | } 150 | 151 | return EXIT_RELAUNCH_ON_LOAD; 152 | } 153 | 154 | log_printf("Not in Mii Maker\n"); 155 | 156 | if(isFirstBoot){ // First boot back to SysMenu 157 | memoryInitialize(); 158 | 159 | VPADInit(); 160 | 161 | // Init screen and screen buffers 162 | OSScreenInit(); 163 | int screen_buf0_size = OSScreenGetBufferSizeEx(0); 164 | int screen_buf1_size = OSScreenGetBufferSizeEx(1); 165 | unsigned char *screenBuffer = MEM1_alloc(screen_buf0_size + screen_buf1_size, 0x100); 166 | char msg[80]; 167 | 168 | OSScreenSetBufferEx(0, screenBuffer); 169 | OSScreenSetBufferEx(1, (screenBuffer + screen_buf0_size)); 170 | 171 | OSScreenEnableEx(0, 1); 172 | OSScreenEnableEx(1, 1); 173 | 174 | #if LITE 175 | OSScreenClearBufferEx(0, 0); 176 | OSScreenClearBufferEx(1, 0); 177 | 178 | PRINT_TEXT2(0, 1, "SwapDRC Lite is now ready..."); 179 | PRINT_TEXT2(0, 3, "Tip: Swap screens with the TV button."); 180 | 181 | OSScreenFlipBuffersEx(0); 182 | OSScreenFlipBuffersEx(1); 183 | os_sleep(2); 184 | 185 | MEM1_free(screenBuffer); 186 | screenBuffer = NULL; 187 | 188 | memoryRelease(); 189 | 190 | isFirstBoot = 0; 191 | SYSLaunchMenu(); 192 | 193 | #else // LITE 194 | 195 | // Render IP selector and check for buttons 196 | u_serv_ip ip; 197 | ip.full = ((192 << 24) | (168 << 16) | (2 << 8) | (18 << 0)); 198 | VPADData vpad_data; 199 | s32 error; 200 | int delay = 0; 201 | int gui_mode = 0; 202 | int success = 0; // for exiting the menu with the home button 203 | int sel_ip = 3; 204 | 205 | while (1) 206 | { 207 | // Refresh TV and GamePad screen 208 | OSScreenFlipBuffersEx(0); 209 | OSScreenFlipBuffersEx(1); 210 | OSScreenClearBufferEx(0, 0); 211 | OSScreenClearBufferEx(1, 0); 212 | 213 | // Read vpad 214 | VPADRead(0, &vpad_data, 1, &error); 215 | 216 | // Title 217 | PRINT_TEXT2(21, 1, "-- SwapDRC %s --", BUILD); 218 | 219 | if (gui_mode == 0) // IP selector 220 | { 221 | PRINT_TEXT2(0, 4, " IP : %3d.%3d.%3d.%3d", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]); 222 | PRINT_TEXT2(0, 6, "Use the D-Pad to enter in your computer's IP address for Cafiine."); 223 | PRINT_TEXT2(0, 8, "Press A to install with TCPGecko."); 224 | PRINT_TEXT2(0, 9, "Press Y to install with TCPGecko + Cafiine. (needs server running)"); 225 | PRINT_TEXT2(0, 11, "Press B to view quick guide."); 226 | PRINT_TEXT2(0, 12, "Press X for credits."); 227 | PRINT_TEXT2(0, 15, "Press Home to exit."); 228 | 229 | 230 | PRINT_TEXT2(8 + 4 * sel_ip, 3, "vvv"); 231 | 232 | } 233 | else if (gui_mode == 1) // Credits 234 | { 235 | PRINT_TEXT2(0, 3, "Creators:"); 236 | PRINT_TEXT2(2, 5, "* OatmealDome and Yahya14"); 237 | PRINT_TEXT2(0, 7, "Special Thanks:"); 238 | PRINT_TEXT2(2, 9, "* Maschell for development contribution and the audio swap"); 239 | PRINT_TEXT2(2, 10, "* Dimok, Chadderz, etc for function_hooks and pygecko"); 240 | PRINT_TEXT2(2, 11, "* brienj for the IP selector and initial UI"); 241 | PRINT_TEXT2(2, 12, "* /u/MachMatic for the banner background"); 242 | PRINT_TEXT2(2, 13, "* BKOOL999 for testing the SwapDRC app"); 243 | PRINT_TEXT2(0, 15, "Press B to return to the menu."); 244 | } 245 | 246 | else if (gui_mode == 2) // Guide 247 | { 248 | PRINT_TEXT2(0, 3, "Switch Display, Audio, and Gamepad Sensor Bar:"); 249 | PRINT_TEXT2(2, 4, "* Press L and Minus together."); 250 | PRINT_TEXT2(2, 5, "* Press the TV button."); 251 | PRINT_TEXT2(0, 7, "Switch on/off Gamepad LCD:"); 252 | PRINT_TEXT2(2, 8, "* Press and hold R-Stick for 3-6 seconds."); 253 | PRINT_TEXT2(0, 10, "Splatoon's Enhanced Controls:"); 254 | PRINT_TEXT2(2, 11, "* Press B to swap displays except in-game menus."); 255 | PRINT_TEXT2(2, 12, "* Hold A + D-PAD to super jump to a teammate in a match."); 256 | 257 | PRINT_TEXT2(0, 15, "Press B to return to the menu."); 258 | } 259 | 260 | if ((vpad_data.btns_h & VPAD_BUTTON_A) && gui_mode == 0) 261 | { 262 | // Set wait message 263 | OSScreenClearBufferEx(1, 0); 264 | OSScreenClearBufferEx(0, 0); 265 | PRINT_TEXT2(42, 17, "Installing TCPGecko..."); 266 | ip.full = 0; 267 | OSScreenFlipBuffersEx(1); 268 | break; 269 | } 270 | else if ((vpad_data.btns_h & VPAD_BUTTON_Y) && gui_mode == 0) 271 | { 272 | // Set wait message 273 | OSScreenClearBufferEx(1, 0); 274 | OSScreenClearBufferEx(0, 0); 275 | PRINT_TEXT2(42, 17, "Installing geckiine..."); 276 | OSScreenFlipBuffersEx(1); 277 | break; 278 | } 279 | else if (vpad_data.btns_h & VPAD_BUTTON_X) 280 | { 281 | if (--delay <= 0) 282 | { 283 | // Swap GUI mode 284 | gui_mode = (gui_mode == 0) ? 1 : 0; 285 | delay = 100; 286 | } 287 | } 288 | else if (vpad_data.btns_h & VPAD_BUTTON_B) 289 | { 290 | if (--delay <= 0) 291 | { 292 | // Swap GUI mode 293 | gui_mode = (gui_mode == 0) ? 2 : 0; 294 | delay = 100; 295 | } 296 | } 297 | else if ((vpad_data.btns_h & VPAD_BUTTON_LEFT) && gui_mode == 0) 298 | { 299 | if (--delay <= 0) 300 | { 301 | if (sel_ip == 0) 302 | sel_ip = 3; 303 | else 304 | sel_ip--; 305 | 306 | delay = 8; 307 | } 308 | } 309 | else if ((vpad_data.btns_h & VPAD_BUTTON_RIGHT) && gui_mode == 0) 310 | { 311 | if (--delay <= 0) 312 | { 313 | sel_ip++; 314 | sel_ip = sel_ip % 4; 315 | delay = 8; 316 | } 317 | } 318 | else if ((vpad_data.btns_d & VPAD_BUTTON_UP) && gui_mode == 0) // add large delay at first 1/2 319 | { 320 | if (--delay <= 0) 321 | { 322 | ip.digit[sel_ip]++; 323 | delay = 10; 324 | } 325 | } 326 | else if ((vpad_data.btns_h & VPAD_BUTTON_UP) && gui_mode == 0) // then it gets shorter when holding it 2/2 327 | { 328 | if (--delay <= 0) 329 | { 330 | ip.digit[sel_ip]++; 331 | delay = 2; 332 | } 333 | } 334 | else if ((vpad_data.btns_d & VPAD_BUTTON_DOWN) && gui_mode == 0) 335 | { 336 | if (--delay <= 0) 337 | { 338 | ip.digit[sel_ip]--; 339 | delay = 10; 340 | } 341 | } 342 | else if ((vpad_data.btns_h & VPAD_BUTTON_DOWN) && gui_mode == 0) 343 | { 344 | if (--delay <= 0) 345 | { 346 | ip.digit[sel_ip]--; 347 | delay = 2; 348 | } 349 | } 350 | else if ((vpad_data.btns_h & VPAD_BUTTON_HOME) && gui_mode == 0) 351 | { 352 | success = -1; 353 | break; 354 | } 355 | else 356 | { 357 | delay = 0; 358 | } 359 | } 360 | 361 | MEM1_free(screenBuffer); 362 | screenBuffer = NULL; 363 | 364 | memoryRelease(); 365 | 366 | //return to HBV 367 | if (success == -1) 368 | { 369 | RestorePatches(); 370 | return EXIT_SUCCESS; 371 | } 372 | 373 | cafiine_addr = ip.full; 374 | 375 | log_printf("Returning to application.\n"); 376 | log_printf("De-initializing logging.\n"); 377 | log_deinit(); 378 | 379 | isFirstBoot = 0; 380 | SYSLaunchMenu(); 381 | #endif 382 | } 383 | return EXIT_RELAUNCH_ON_LOAD; 384 | } 385 | 386 | /* 387 | Patching all the functions!!! 388 | */ 389 | void ApplyPatches(){ 390 | #if !LITE 391 | PatchInvidualMethodHooks(method_hooks_cafiine, method_hooks_size_cafiine, method_calls_cafiine); 392 | #endif 393 | PatchInvidualMethodHooks(method_hooks_voice_swapping, method_hooks_size_voice_swapping, method_calls_voice_swapping); 394 | PatchInvidualMethodHooks(method_hooks_video_swapping, method_hooks_size_video_swapping, method_calls_video_swapping); 395 | PatchInvidualMethodHooks(method_hooks_vpad, method_hooks_size_vpad, method_calls_vpad); 396 | PatchInvidualMethodHooks(method_hooks_proc_ui, method_hooks_size_proc_ui, method_calls_proc_ui); 397 | } 398 | 399 | /* 400 | Restoring everything!! 401 | */ 402 | 403 | void RestorePatches(){ 404 | RestoreInvidualInstructions(method_hooks_cafiine, method_hooks_size_cafiine); 405 | RestoreInvidualInstructions(method_hooks_voice_swapping, method_hooks_size_voice_swapping); 406 | RestoreInvidualInstructions(method_hooks_video_swapping, method_hooks_size_video_swapping); 407 | RestoreInvidualInstructions(method_hooks_vpad, method_hooks_size_vpad); 408 | RestoreInvidualInstructions(method_hooks_proc_ui, method_hooks_size_proc_ui); 409 | KernelRestoreInstructions(); 410 | } 411 | 412 | void deInit(){ 413 | RestorePatches(); 414 | log_deinit(); 415 | } 416 | 417 | int isInSplatoon(){ 418 | if (OSGetTitleID != 0 && ( 419 | OSGetTitleID() == 0x0005000010176a00 || // splatoon eur 420 | OSGetTitleID() == 0x0005000010176900 || // splatoon usa 421 | OSGetTitleID() == 0x0005000010162b00)){ // splatoon jpn 422 | return 1; 423 | } 424 | return 0; 425 | } 426 | 427 | int isInMiiMakerHBL(){ 428 | if (OSGetTitleID != 0 && ( 429 | OSGetTitleID() == 0x000500101004A200 || // mii maker eur 430 | OSGetTitleID() == 0x000500101004A100 || // mii maker usa 431 | OSGetTitleID() == 0x000500101004A000 || // mii maker jpn 432 | OSGetTitleID() == 0x0005000013374842)) 433 | { 434 | return 1; 435 | } 436 | return 0; 437 | } 438 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /src/cafiine/550.h: -------------------------------------------------------------------------------- 1 | static const unsigned char cafiine_magic_bin[] = { 2 | 0x01, 0x06, 0x12, 0xf4, 0x01, 0x1d, 0xd8, 0xdc, 0x01, 0x1d, 0xe4, 0xf4, 3 | 0x01, 0x06, 0x13, 0xbc, 0x01, 0x1d, 0xd8, 0xbc, 0x01, 0x1d, 0xe4, 0xec, 4 | 0x01, 0x06, 0x5e, 0xb4, 0x01, 0x1d, 0xd9, 0xfc, 0x01, 0x1d, 0xe4, 0xfc, 5 | 0x01, 0x06, 0x14, 0xec, 0x01, 0x1d, 0xdb, 0x1c, 0x01, 0x1d, 0xe5, 0x04, 6 | 0x01, 0x06, 0x2c, 0x40, 0x01, 0x1d, 0xdc, 0x2c, 0x01, 0x1d, 0xe5, 0x0c, 7 | 0x01, 0x06, 0x8e, 0x10, 0x01, 0x1d, 0xd9, 0x6c, 0x01, 0x1d, 0xe4, 0xf8, 8 | 0x01, 0x06, 0x8f, 0x80, 0x01, 0x1d, 0xd8, 0xcc, 0x01, 0x1d, 0xe4, 0xf0, 9 | 0x01, 0x06, 0x90, 0x44, 0x01, 0x1d, 0xda, 0x64, 0x01, 0x1d, 0xe5, 0x00, 10 | 0x01, 0x06, 0x94, 0x50, 0x01, 0x1d, 0xdb, 0x80, 0x01, 0x1d, 0xe5, 0x08, 11 | 0x01, 0x06, 0xf9, 0xc4, 0x01, 0x1d, 0xdc, 0xe4, 0x01, 0x1d, 0xe5, 0x10, 12 | 0x01, 0x06, 0xfa, 0xd0, 0x01, 0x1d, 0xe1, 0x54, 0x01, 0x1d, 0xe5, 0x20, 13 | 0x01, 0x06, 0xfb, 0x50, 0x01, 0x1d, 0xdd, 0xd4, 0x01, 0x1d, 0xe5, 0x14, 14 | 0x01, 0x06, 0xfb, 0xdc, 0x01, 0x1d, 0xde, 0xfc, 0x01, 0x1d, 0xe5, 0x18, 15 | 0x01, 0x06, 0xff, 0x08, 0x01, 0x1d, 0xe2, 0x30, 0x01, 0x1d, 0xe5, 0x24, 16 | 0x01, 0x06, 0xff, 0x78, 0x01, 0x1d, 0xe0, 0x64, 0x01, 0x1d, 0xe5, 0x1c, 17 | 0x01, 0x06, 0xff, 0xe8, 0x01, 0x1d, 0xe3, 0x20, 0x01, 0x1d, 0xe5, 0x28, 18 | 0x01, 0x07, 0x00, 0x58, 0x01, 0x1d, 0xe4, 0x10, 0x01, 0x1d, 0xe5, 0x2c 19 | }; 20 | static const unsigned int cafiine_magic_bin_len = 204; 21 | static const unsigned char cafiine_text_bin[] = { 22 | 0x00, 0x00, 0x00, 0x00, 0x94, 0x21, 0xff, 0xe8, 0x7c, 0x08, 0x02, 0xa6, 23 | 0x93, 0xe1, 0x00, 0x14, 0x7c, 0xbf, 0x2b, 0x79, 0x93, 0xa1, 0x00, 0x0c, 24 | 0x7c, 0x7d, 0x1b, 0x78, 0x93, 0xc1, 0x00, 0x10, 0x7c, 0x9e, 0x23, 0x78, 25 | 0x90, 0x01, 0x00, 0x1c, 0x41, 0xa1, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x4c, 26 | 0x40, 0x9d, 0x00, 0x48, 0x7f, 0xc4, 0xf3, 0x78, 0x7f, 0xe5, 0xfb, 0x78, 27 | 0x7f, 0xa3, 0xeb, 0x78, 0x38, 0xc0, 0x00, 0x00, 0x4b, 0xee, 0x4a, 0x69, 28 | 0x2c, 0x03, 0x00, 0x00, 0x7f, 0xe3, 0xf8, 0x50, 0x7f, 0xde, 0x1a, 0x14, 29 | 0x2f, 0x9f, 0x00, 0x00, 0x40, 0x80, 0xff, 0xd8, 0x80, 0x01, 0x00, 0x1c, 30 | 0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x10, 31 | 0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20, 32 | 0x80, 0x01, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00, 0x83, 0xa1, 0x00, 0x0c, 33 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x10, 0x83, 0xe1, 0x00, 0x14, 34 | 0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20, 0x94, 0x21, 0xff, 0xe8, 35 | 0x7c, 0x08, 0x02, 0xa6, 0x93, 0xe1, 0x00, 0x14, 0x7c, 0xbf, 0x2b, 0x79, 36 | 0x93, 0xa1, 0x00, 0x0c, 0x7c, 0x7d, 0x1b, 0x78, 0x93, 0xc1, 0x00, 0x10, 37 | 0x7c, 0x9e, 0x23, 0x78, 0x90, 0x01, 0x00, 0x1c, 0x41, 0xa1, 0x00, 0x0c, 38 | 0x48, 0x00, 0x00, 0x4c, 0x40, 0x9d, 0x00, 0x48, 0x7f, 0xc4, 0xf3, 0x78, 39 | 0x7f, 0xe5, 0xfb, 0x78, 0x7f, 0xa3, 0xeb, 0x78, 0x38, 0xc0, 0x00, 0x00, 40 | 0x4b, 0xee, 0x3e, 0x15, 0x2c, 0x03, 0x00, 0x00, 0x7f, 0xe3, 0xf8, 0x50, 41 | 0x7f, 0xde, 0x1a, 0x14, 0x2f, 0x9f, 0x00, 0x00, 0x40, 0x80, 0xff, 0xd8, 42 | 0x80, 0x01, 0x00, 0x1c, 0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 43 | 0x83, 0xc1, 0x00, 0x10, 0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 44 | 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00, 45 | 0x83, 0xa1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x10, 46 | 0x83, 0xe1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x4e, 0x80, 0x00, 0x20, 47 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xc0, 0x93, 0xc1, 0x00, 0x38, 48 | 0x7c, 0x7e, 0x1b, 0x78, 0x90, 0x01, 0x00, 0x44, 0x93, 0xe1, 0x00, 0x3c, 49 | 0x4b, 0xee, 0x35, 0xb1, 0x38, 0x60, 0x00, 0x02, 0x38, 0x80, 0x00, 0x01, 50 | 0x38, 0xa0, 0x00, 0x06, 0x4b, 0xee, 0x54, 0x75, 0x2f, 0x83, 0xff, 0xff, 51 | 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0xa8, 0x3d, 0x20, 0x01, 0x1e, 52 | 0x39, 0x40, 0x00, 0x02, 0x81, 0x29, 0xcc, 0x00, 0x38, 0x81, 0x00, 0x18, 53 | 0xb1, 0x41, 0x00, 0x18, 0x38, 0xa0, 0x00, 0x10, 0x39, 0x40, 0x1c, 0xa4, 54 | 0x91, 0x21, 0x00, 0x1c, 0xb1, 0x41, 0x00, 0x1a, 0x4b, 0xee, 0x3a, 0xa1, 55 | 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x70, 0x3c, 0x80, 0x10, 0x01, 56 | 0x38, 0xa0, 0x00, 0x10, 0x38, 0x84, 0x3c, 0x10, 0x38, 0x61, 0x00, 0x08, 57 | 0x4b, 0xe5, 0x92, 0x25, 0x7f, 0xe3, 0xfb, 0x78, 0x38, 0x81, 0x00, 0x08, 58 | 0x38, 0xa0, 0x00, 0x10, 0x4b, 0xff, 0xfe, 0x51, 0x2f, 0x83, 0x00, 0x00, 59 | 0x41, 0x9c, 0x00, 0x44, 0x7f, 0xe3, 0xfb, 0x78, 0x38, 0x81, 0x00, 0x28, 60 | 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xfe, 0xcd, 0x2f, 0x83, 0x00, 0x00, 61 | 0x41, 0x9c, 0x00, 0x2c, 0x89, 0x21, 0x00, 0x28, 0x2b, 0x89, 0x00, 0xff, 62 | 0x41, 0x9e, 0x00, 0x20, 0x80, 0x01, 0x00, 0x44, 0x93, 0xfe, 0x00, 0x00, 63 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x38, 0x83, 0xe1, 0x00, 0x3c, 64 | 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x7f, 0xe3, 0xfb, 0x78, 65 | 0x4b, 0xee, 0x55, 0x11, 0x80, 0x01, 0x00, 0x44, 0x39, 0x20, 0xff, 0xff, 66 | 0x91, 0x3e, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x38, 67 | 0x83, 0xe1, 0x00, 0x3c, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 68 | 0x2f, 0x83, 0xff, 0xff, 0x4d, 0x9e, 0x00, 0x20, 0x4b, 0xee, 0x54, 0xe4, 69 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xc8, 0x93, 0x21, 0x00, 0x1c, 70 | 0x3f, 0x20, 0x10, 0x00, 0x90, 0x01, 0x00, 0x3c, 0x63, 0x39, 0x00, 0xe4, 71 | 0x93, 0x41, 0x00, 0x20, 0x7c, 0xba, 0x2b, 0x78, 0x81, 0x39, 0x00, 0x00, 72 | 0x93, 0x61, 0x00, 0x24, 0x7c, 0xfb, 0x3b, 0x78, 0x81, 0x49, 0x01, 0x80, 73 | 0x93, 0x81, 0x00, 0x28, 0x7c, 0x9c, 0x23, 0x78, 0x2f, 0x8a, 0x00, 0x00, 74 | 0x93, 0xa1, 0x00, 0x2c, 0x93, 0xc1, 0x00, 0x30, 0x7c, 0x7d, 0x1b, 0x78, 75 | 0x93, 0xe1, 0x00, 0x34, 0x7c, 0xde, 0x33, 0x78, 0x7c, 0x3f, 0x0b, 0x78, 76 | 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x4a, 0xd9, 0x81, 0x39, 0x00, 0x00, 77 | 0x81, 0x49, 0x01, 0x80, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 78 | 0x2f, 0x9d, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x80, 79 | 0x41, 0x9e, 0x01, 0x70, 0x39, 0x3a, 0xff, 0xff, 0x39, 0x00, 0x00, 0x00, 80 | 0x48, 0x00, 0x00, 0x08, 0x7d, 0x68, 0x5b, 0x78, 0x8d, 0x49, 0x00, 0x01, 81 | 0x39, 0x68, 0x00, 0x01, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 82 | 0x39, 0x3e, 0xff, 0xff, 0x39, 0x40, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x01, 83 | 0x39, 0x4a, 0x00, 0x01, 0x2f, 0x80, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf4, 84 | 0x38, 0xa8, 0x00, 0x0a, 0x80, 0xe1, 0x00, 0x00, 0x7c, 0xaa, 0x2a, 0x14, 85 | 0x7d, 0x66, 0x5b, 0x79, 0x39, 0x25, 0x00, 0x0f, 0x7c, 0x39, 0x0b, 0x78, 86 | 0x55, 0x29, 0x00, 0x36, 0x7c, 0xc9, 0x03, 0xa6, 0x7d, 0x29, 0x00, 0xd0, 87 | 0x7c, 0xe1, 0x49, 0x6e, 0x39, 0x20, 0x00, 0x00, 0x38, 0x81, 0x00, 0x08, 88 | 0x98, 0x01, 0x00, 0x08, 0x91, 0x64, 0x00, 0x01, 0x91, 0x44, 0x00, 0x05, 89 | 0x40, 0x81, 0x01, 0x40, 0x7c, 0xda, 0x48, 0xae, 0x7c, 0xe4, 0x4a, 0x14, 90 | 0x39, 0x29, 0x00, 0x01, 0x98, 0xc7, 0x00, 0x09, 0x42, 0x00, 0xff, 0xf0, 91 | 0x2f, 0x8a, 0x00, 0x00, 0x39, 0x08, 0x00, 0x09, 0x7d, 0x49, 0x03, 0xa6, 92 | 0x7d, 0x04, 0x42, 0x14, 0x39, 0x20, 0x00, 0x00, 0x40, 0x9d, 0x01, 0x20, 93 | 0x7d, 0x5e, 0x48, 0xae, 0x39, 0x29, 0x00, 0x01, 0x9d, 0x48, 0x00, 0x01, 94 | 0x42, 0x00, 0xff, 0xf4, 0x7f, 0xa3, 0xeb, 0x78, 0x4b, 0xff, 0xfc, 0x9d, 95 | 0x81, 0x21, 0x00, 0x00, 0x2f, 0x83, 0x00, 0x00, 0x91, 0x39, 0x00, 0x00, 96 | 0x7f, 0x21, 0xcb, 0x78, 0x41, 0x9c, 0x00, 0xa0, 0x7f, 0xa3, 0xeb, 0x78, 97 | 0x38, 0x9f, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xfd, 0x0d, 98 | 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x88, 0x89, 0x3f, 0x00, 0x08, 99 | 0x2b, 0x89, 0x00, 0xff, 0x41, 0x9e, 0x00, 0x7c, 0x7f, 0xa3, 0xeb, 0x78, 100 | 0x7f, 0x84, 0xe3, 0x78, 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xfc, 0xe9, 101 | 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x64, 0x7f, 0xa3, 0xeb, 0x78, 102 | 0x7f, 0x64, 0xdb, 0x78, 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xfc, 0xd1, 103 | 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x4c, 0x39, 0x7f, 0x00, 0x38, 104 | 0x80, 0x0b, 0x00, 0x04, 0x3d, 0x20, 0x10, 0x00, 0x83, 0xeb, 0xff, 0xfc, 105 | 0x7c, 0x08, 0x03, 0xa6, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 106 | 0x39, 0x40, 0x00, 0x00, 0x38, 0x60, 0x00, 0x00, 0x83, 0x2b, 0xff, 0xe4, 107 | 0x91, 0x49, 0x01, 0x80, 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 108 | 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 109 | 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 0x39, 0x7f, 0x00, 0x38, 110 | 0x80, 0x0b, 0x00, 0x04, 0x3d, 0x20, 0x10, 0x00, 0x83, 0xeb, 0xff, 0xfc, 111 | 0x7c, 0x08, 0x03, 0xa6, 0x61, 0x29, 0x00, 0xe4, 0x81, 0x29, 0x00, 0x00, 112 | 0x39, 0x40, 0x00, 0x00, 0x38, 0x60, 0xff, 0xff, 0x83, 0x2b, 0xff, 0xe4, 113 | 0x91, 0x49, 0x01, 0x80, 0x83, 0x4b, 0xff, 0xe8, 0x83, 0x6b, 0xff, 0xec, 114 | 0x83, 0x8b, 0xff, 0xf0, 0x83, 0xab, 0xff, 0xf4, 0x83, 0xcb, 0xff, 0xf8, 115 | 0x7d, 0x61, 0x5b, 0x78, 0x4e, 0x80, 0x00, 0x20, 0x38, 0xe0, 0x00, 0x01, 116 | 0x7c, 0xe9, 0x03, 0xa6, 0x4b, 0xff, 0xfe, 0xbc, 0x39, 0x40, 0x00, 0x01, 117 | 0x7d, 0x49, 0x03, 0xa6, 0x4b, 0xff, 0xfe, 0xdc, 0x7c, 0x08, 0x02, 0xa6, 118 | 0x94, 0x21, 0xff, 0xb8, 0x93, 0xe1, 0x00, 0x44, 0x3f, 0xe0, 0x10, 0x00, 119 | 0x90, 0x01, 0x00, 0x4c, 0x63, 0xff, 0x00, 0xe4, 0x93, 0x21, 0x00, 0x2c, 120 | 0x7c, 0xb9, 0x2b, 0x78, 0x81, 0x3f, 0x00, 0x00, 0x93, 0x41, 0x00, 0x30, 121 | 0x7c, 0x9a, 0x23, 0x78, 0x81, 0x49, 0x01, 0x80, 0x93, 0x61, 0x00, 0x34, 122 | 0x7c, 0xdb, 0x33, 0x78, 0x2f, 0x8a, 0x00, 0x00, 0x93, 0x81, 0x00, 0x38, 123 | 0x93, 0xa1, 0x00, 0x3c, 0x7c, 0xfc, 0x3b, 0x78, 0x93, 0xc1, 0x00, 0x40, 124 | 0x7d, 0x1d, 0x43, 0x78, 0x7c, 0x7e, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x18, 125 | 0x4b, 0xf7, 0x48, 0x91, 0x81, 0x3f, 0x00, 0x00, 0x81, 0x49, 0x01, 0x80, 126 | 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9e, 0xff, 0xff, 127 | 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x80, 0x41, 0x9e, 0x00, 0xfc, 128 | 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x0d, 129 | 0x99, 0x41, 0x00, 0x08, 0x93, 0x61, 0x00, 0x09, 0x93, 0x81, 0x00, 0x0d, 130 | 0x93, 0xa1, 0x00, 0x11, 0x4b, 0xff, 0xfa, 0xf1, 0x2f, 0x83, 0x00, 0x00, 131 | 0x41, 0x9c, 0x00, 0xd4, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x18, 132 | 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xfb, 0x6d, 0x2f, 0x83, 0x00, 0x00, 133 | 0x41, 0x9c, 0x00, 0xbc, 0x89, 0x21, 0x00, 0x18, 0x2b, 0x89, 0x00, 0xff, 134 | 0x41, 0x9e, 0x00, 0xb0, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x44, 0xd3, 0x78, 135 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xfb, 0x49, 0x2f, 0x83, 0x00, 0x00, 136 | 0x41, 0x9c, 0x00, 0x98, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x18, 137 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xfb, 0x31, 0x2f, 0x83, 0x00, 0x00, 138 | 0x41, 0x9c, 0x00, 0x80, 0x80, 0xa1, 0x00, 0x18, 0x7f, 0xc3, 0xf3, 0x78, 139 | 0x7f, 0x24, 0xcb, 0x78, 0x4b, 0xff, 0xfb, 0x19, 0x2f, 0x83, 0x00, 0x00, 140 | 0x41, 0x9c, 0x00, 0x68, 0x7c, 0x24, 0x0b, 0x78, 0x39, 0x20, 0x00, 0x03, 141 | 0x9d, 0x24, 0x00, 0x1c, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0xa0, 0x00, 0x01, 142 | 0x4b, 0xff, 0xfa, 0x65, 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x48, 143 | 0x80, 0x01, 0x00, 0x4c, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 144 | 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 145 | 0x83, 0x21, 0x00, 0x2c, 0x38, 0x60, 0x00, 0x00, 0x83, 0x41, 0x00, 0x30, 146 | 0x83, 0x61, 0x00, 0x34, 0x83, 0x81, 0x00, 0x38, 0x83, 0xa1, 0x00, 0x3c, 147 | 0x83, 0xc1, 0x00, 0x40, 0x83, 0xe1, 0x00, 0x44, 0x91, 0x49, 0x01, 0x80, 148 | 0x38, 0x21, 0x00, 0x48, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x4c, 149 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 150 | 0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 0x83, 0x21, 0x00, 0x2c, 151 | 0x38, 0x60, 0xff, 0xff, 0x83, 0x41, 0x00, 0x30, 0x83, 0x61, 0x00, 0x34, 152 | 0x83, 0x81, 0x00, 0x38, 0x83, 0xa1, 0x00, 0x3c, 0x83, 0xc1, 0x00, 0x40, 153 | 0x83, 0xe1, 0x00, 0x44, 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x48, 154 | 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd8, 155 | 0x93, 0xe1, 0x00, 0x24, 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x2c, 156 | 0x63, 0xff, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x18, 0x7c, 0x9c, 0x23, 0x78, 157 | 0x81, 0x3f, 0x00, 0x00, 0x93, 0xa1, 0x00, 0x1c, 0x7c, 0xbd, 0x2b, 0x78, 158 | 0x81, 0x49, 0x01, 0x80, 0x93, 0xc1, 0x00, 0x20, 0x7c, 0x7e, 0x1b, 0x78, 159 | 0x2f, 0x8a, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x46, 0xf1, 160 | 0x81, 0x3f, 0x00, 0x00, 0x81, 0x49, 0x01, 0x80, 0x2f, 0x8a, 0x00, 0x00, 161 | 0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9e, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 162 | 0x91, 0x49, 0x01, 0x80, 0x41, 0x9e, 0x00, 0x9c, 0x39, 0x20, 0x00, 0x02, 163 | 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x05, 164 | 0x99, 0x21, 0x00, 0x08, 0x93, 0xa1, 0x00, 0x09, 0x4b, 0xff, 0xf9, 0x55, 165 | 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x78, 0x7f, 0xc3, 0xf3, 0x78, 166 | 0x38, 0x81, 0x00, 0x10, 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xf9, 0xd1, 167 | 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x60, 0x89, 0x21, 0x00, 0x10, 168 | 0x2b, 0x89, 0x00, 0xff, 0x41, 0x9e, 0x00, 0x54, 0x7f, 0xc3, 0xf3, 0x78, 169 | 0x7f, 0x84, 0xe3, 0x78, 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xf9, 0xad, 170 | 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x3c, 0x80, 0x01, 0x00, 0x2c, 171 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 172 | 0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 0x83, 0x81, 0x00, 0x18, 173 | 0x38, 0x60, 0x00, 0x00, 0x83, 0xa1, 0x00, 0x1c, 0x83, 0xc1, 0x00, 0x20, 174 | 0x83, 0xe1, 0x00, 0x24, 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x28, 175 | 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x2c, 0x3d, 0x20, 0x10, 0x00, 176 | 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 177 | 0x81, 0x29, 0x00, 0x00, 0x83, 0x81, 0x00, 0x18, 0x38, 0x60, 0xff, 0xff, 178 | 0x83, 0xa1, 0x00, 0x1c, 0x83, 0xc1, 0x00, 0x20, 0x83, 0xe1, 0x00, 0x24, 179 | 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x28, 0x4e, 0x80, 0x00, 0x20, 180 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 0x93, 0xe1, 0x00, 0x2c, 181 | 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x34, 0x63, 0xff, 0x00, 0xe4, 182 | 0x93, 0x61, 0x00, 0x1c, 0x7c, 0x9b, 0x23, 0x78, 0x81, 0x3f, 0x00, 0x00, 183 | 0x93, 0x81, 0x00, 0x20, 0x7c, 0xbc, 0x2b, 0x78, 0x81, 0x49, 0x01, 0x80, 184 | 0x93, 0xa1, 0x00, 0x24, 0x7c, 0xdd, 0x33, 0x78, 0x2f, 0x8a, 0x00, 0x00, 185 | 0x93, 0xc1, 0x00, 0x28, 0x7c, 0x7e, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x18, 186 | 0x4b, 0xf7, 0x45, 0xb5, 0x81, 0x3f, 0x00, 0x00, 0x81, 0x49, 0x01, 0x80, 187 | 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x2f, 0x9e, 0xff, 0xff, 188 | 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x80, 0x41, 0x9e, 0x00, 0xa4, 189 | 0x39, 0x20, 0x00, 0x04, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x08, 190 | 0x38, 0xa0, 0x00, 0x09, 0x99, 0x21, 0x00, 0x08, 0x93, 0x81, 0x00, 0x09, 191 | 0x93, 0xa1, 0x00, 0x0d, 0x4b, 0xff, 0xf8, 0x15, 0x2f, 0x83, 0x00, 0x00, 192 | 0x41, 0x9c, 0x00, 0x7c, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x14, 193 | 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xf8, 0x91, 0x2f, 0x83, 0x00, 0x00, 194 | 0x41, 0x9c, 0x00, 0x64, 0x89, 0x21, 0x00, 0x14, 0x2b, 0x89, 0x00, 0xff, 195 | 0x41, 0x9e, 0x00, 0x58, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 196 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xf8, 0x6d, 0x2f, 0x83, 0x00, 0x00, 197 | 0x41, 0x9c, 0x00, 0x40, 0x80, 0x01, 0x00, 0x34, 0x3d, 0x20, 0x10, 0x00, 198 | 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 199 | 0x81, 0x29, 0x00, 0x00, 0x83, 0x61, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00, 200 | 0x83, 0x81, 0x00, 0x20, 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 201 | 0x83, 0xe1, 0x00, 0x2c, 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x30, 202 | 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x34, 0x3d, 0x20, 0x10, 0x00, 203 | 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 204 | 0x81, 0x29, 0x00, 0x00, 0x83, 0x61, 0x00, 0x1c, 0x38, 0x60, 0xff, 0xff, 205 | 0x83, 0x81, 0x00, 0x20, 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 206 | 0x83, 0xe1, 0x00, 0x2c, 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x30, 207 | 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 208 | 0x93, 0xe1, 0x00, 0x2c, 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x34, 209 | 0x63, 0xff, 0x00, 0xe4, 0x93, 0x61, 0x00, 0x1c, 0x7c, 0xdb, 0x33, 0x78, 210 | 0x81, 0x3f, 0x00, 0x00, 0x93, 0x81, 0x00, 0x20, 0x7c, 0x9c, 0x23, 0x78, 211 | 0x81, 0x49, 0x01, 0x80, 0x93, 0xa1, 0x00, 0x24, 0x7c, 0xbd, 0x2b, 0x78, 212 | 0x2f, 0x8a, 0x00, 0x00, 0x93, 0xc1, 0x00, 0x28, 0x7c, 0x7e, 0x1b, 0x78, 213 | 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x44, 0x6d, 0x81, 0x3f, 0x00, 0x00, 214 | 0x81, 0x49, 0x01, 0x80, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 215 | 0x2f, 0x9e, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x80, 216 | 0x41, 0x9e, 0x00, 0xb8, 0x39, 0x20, 0x00, 0x07, 0x7f, 0xc3, 0xf3, 0x78, 217 | 0x38, 0x81, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x05, 0x99, 0x21, 0x00, 0x08, 218 | 0x93, 0xa1, 0x00, 0x09, 0x4b, 0xff, 0xf6, 0xd1, 0x2f, 0x83, 0x00, 0x00, 219 | 0x41, 0x9c, 0x00, 0x94, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x10, 220 | 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xf7, 0x4d, 0x2f, 0x83, 0x00, 0x00, 221 | 0x41, 0x9c, 0x00, 0x7c, 0x89, 0x21, 0x00, 0x10, 0x2b, 0x89, 0x00, 0xff, 222 | 0x41, 0x9e, 0x00, 0x70, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x84, 0xe3, 0x78, 223 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xf7, 0x29, 0x2f, 0x83, 0x00, 0x00, 224 | 0x41, 0x9c, 0x00, 0x58, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 225 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xf7, 0x11, 0x2f, 0x83, 0x00, 0x00, 226 | 0x41, 0x9c, 0x00, 0x40, 0x80, 0x01, 0x00, 0x34, 0x3d, 0x20, 0x10, 0x00, 227 | 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 228 | 0x81, 0x29, 0x00, 0x00, 0x83, 0x61, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00, 229 | 0x83, 0x81, 0x00, 0x20, 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 230 | 0x83, 0xe1, 0x00, 0x2c, 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x30, 231 | 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x34, 0x3d, 0x20, 0x10, 0x00, 232 | 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 233 | 0x81, 0x29, 0x00, 0x00, 0x83, 0x61, 0x00, 0x1c, 0x38, 0x60, 0xff, 0xff, 234 | 0x83, 0x81, 0x00, 0x20, 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 235 | 0x83, 0xe1, 0x00, 0x2c, 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x30, 236 | 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 237 | 0x93, 0xe1, 0x00, 0x2c, 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x34, 238 | 0x63, 0xff, 0x00, 0xe4, 0x93, 0x61, 0x00, 0x1c, 0x7c, 0x9b, 0x23, 0x78, 239 | 0x81, 0x3f, 0x00, 0x00, 0x93, 0x81, 0x00, 0x20, 0x7c, 0xbc, 0x2b, 0x78, 240 | 0x81, 0x49, 0x01, 0x80, 0x93, 0xa1, 0x00, 0x24, 0x7c, 0xdd, 0x33, 0x78, 241 | 0x2f, 0x8a, 0x00, 0x00, 0x93, 0xc1, 0x00, 0x28, 0x7c, 0x7e, 0x1b, 0x78, 242 | 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x43, 0x11, 0x81, 0x3f, 0x00, 0x00, 243 | 0x81, 0x49, 0x01, 0x80, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 244 | 0x2f, 0x9e, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x80, 245 | 0x41, 0x9e, 0x00, 0xd8, 0x39, 0x20, 0x00, 0x05, 0x7f, 0xc3, 0xf3, 0x78, 246 | 0x38, 0x81, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x05, 0x99, 0x21, 0x00, 0x08, 247 | 0x93, 0x81, 0x00, 0x09, 0x4b, 0xff, 0xf5, 0x75, 0x2f, 0x83, 0x00, 0x00, 248 | 0x41, 0x9c, 0x00, 0xb4, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x10, 249 | 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xf5, 0xf1, 0x2f, 0x83, 0x00, 0x00, 250 | 0x41, 0x9c, 0x00, 0x9c, 0x89, 0x21, 0x00, 0x10, 0x2b, 0x89, 0x00, 0xff, 251 | 0x41, 0x9e, 0x00, 0x90, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 252 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xf5, 0xcd, 0x2f, 0x83, 0x00, 0x00, 253 | 0x41, 0x9c, 0x00, 0x78, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x10, 254 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xf5, 0xb5, 0x2f, 0x83, 0x00, 0x00, 255 | 0x41, 0x9c, 0x00, 0x60, 0x2f, 0x9d, 0x00, 0x00, 0x41, 0x9e, 0x00, 0x1c, 256 | 0x80, 0xa1, 0x00, 0x10, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0xa4, 0xeb, 0x78, 257 | 0x4b, 0xff, 0xf5, 0x95, 0x2f, 0x83, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x40, 258 | 0x80, 0x01, 0x00, 0x34, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 259 | 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 260 | 0x83, 0x61, 0x00, 0x1c, 0x38, 0x60, 0x00, 0x00, 0x83, 0x81, 0x00, 0x20, 261 | 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 0x83, 0xe1, 0x00, 0x2c, 262 | 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x30, 0x4e, 0x80, 0x00, 0x20, 263 | 0x80, 0x01, 0x00, 0x34, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 264 | 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 265 | 0x83, 0x61, 0x00, 0x1c, 0x38, 0x60, 0xff, 0xff, 0x83, 0x81, 0x00, 0x20, 266 | 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 0x83, 0xe1, 0x00, 0x2c, 267 | 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x30, 0x4e, 0x80, 0x00, 0x20, 268 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd8, 0x93, 0xe1, 0x00, 0x24, 269 | 0x3f, 0xe0, 0x10, 0x00, 0x90, 0x01, 0x00, 0x2c, 0x63, 0xff, 0x00, 0xe4, 270 | 0x93, 0x81, 0x00, 0x18, 0x7c, 0x9c, 0x23, 0x78, 0x81, 0x3f, 0x00, 0x00, 271 | 0x93, 0xa1, 0x00, 0x1c, 0x7c, 0xbd, 0x2b, 0x78, 0x81, 0x49, 0x01, 0x80, 272 | 0x93, 0xc1, 0x00, 0x20, 0x7c, 0x7e, 0x1b, 0x78, 0x2f, 0x8a, 0x00, 0x00, 273 | 0x41, 0x9e, 0x00, 0x18, 0x4b, 0xf7, 0x41, 0x9d, 0x81, 0x3f, 0x00, 0x00, 274 | 0x81, 0x49, 0x01, 0x80, 0x2f, 0x8a, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 275 | 0x2f, 0x9e, 0xff, 0xff, 0x39, 0x40, 0x00, 0x01, 0x91, 0x49, 0x01, 0x80, 276 | 0x41, 0x9e, 0x00, 0x9c, 0x39, 0x20, 0x00, 0x06, 0x7f, 0xc3, 0xf3, 0x78, 277 | 0x38, 0x81, 0x00, 0x08, 0x38, 0xa0, 0x00, 0x05, 0x99, 0x21, 0x00, 0x08, 278 | 0x93, 0xa1, 0x00, 0x09, 0x4b, 0xff, 0xf4, 0x01, 0x2f, 0x83, 0x00, 0x00, 279 | 0x41, 0x9c, 0x00, 0x78, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x81, 0x00, 0x10, 280 | 0x38, 0xa0, 0x00, 0x01, 0x4b, 0xff, 0xf4, 0x7d, 0x2f, 0x83, 0x00, 0x00, 281 | 0x41, 0x9c, 0x00, 0x60, 0x89, 0x21, 0x00, 0x10, 0x2b, 0x89, 0x00, 0xff, 282 | 0x41, 0x9e, 0x00, 0x54, 0x7f, 0xc3, 0xf3, 0x78, 0x7f, 0x84, 0xe3, 0x78, 283 | 0x38, 0xa0, 0x00, 0x04, 0x4b, 0xff, 0xf4, 0x59, 0x2f, 0x83, 0x00, 0x00, 284 | 0x41, 0x9c, 0x00, 0x3c, 0x80, 0x01, 0x00, 0x2c, 0x3d, 0x20, 0x10, 0x00, 285 | 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 286 | 0x81, 0x29, 0x00, 0x00, 0x83, 0x81, 0x00, 0x18, 0x38, 0x60, 0x00, 0x00, 287 | 0x83, 0xa1, 0x00, 0x1c, 0x83, 0xc1, 0x00, 0x20, 0x83, 0xe1, 0x00, 0x24, 288 | 0x91, 0x49, 0x01, 0x80, 0x38, 0x21, 0x00, 0x28, 0x4e, 0x80, 0x00, 0x20, 289 | 0x80, 0x01, 0x00, 0x2c, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 290 | 0x39, 0x40, 0x00, 0x00, 0x7c, 0x08, 0x03, 0xa6, 0x81, 0x29, 0x00, 0x00, 291 | 0x83, 0x81, 0x00, 0x18, 0x38, 0x60, 0xff, 0xff, 0x83, 0xa1, 0x00, 0x1c, 292 | 0x83, 0xc1, 0x00, 0x20, 0x83, 0xe1, 0x00, 0x24, 0x91, 0x49, 0x01, 0x80, 293 | 0x38, 0x21, 0x00, 0x28, 0x4e, 0x80, 0x00, 0x20, 0x3d, 0x20, 0x01, 0x1e, 294 | 0x81, 0x29, 0xe4, 0xec, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 295 | 0x3d, 0x20, 0x01, 0x1e, 0x81, 0x29, 0xe4, 0xf0, 0x7d, 0x29, 0x03, 0xa6, 296 | 0x4e, 0x80, 0x04, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 297 | 0x3d, 0x40, 0x0a, 0x00, 0x93, 0xe1, 0x00, 0x0c, 0x3f, 0xe0, 0x10, 0x00, 298 | 0x90, 0x01, 0x00, 0x14, 0x63, 0xff, 0x00, 0xe4, 0x81, 0x3f, 0x00, 0x00, 299 | 0x7f, 0x89, 0x50, 0x00, 0x41, 0x9e, 0x00, 0x24, 0x3d, 0x20, 0x01, 0x1e, 300 | 0x80, 0x01, 0x00, 0x14, 0x81, 0x29, 0xe4, 0xf4, 0x83, 0xe1, 0x00, 0x0c, 301 | 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 302 | 0x4e, 0x80, 0x04, 0x20, 0x3d, 0x20, 0x10, 0x05, 0x38, 0x80, 0x00, 0x40, 303 | 0x81, 0x29, 0xf8, 0x70, 0x38, 0x60, 0x01, 0x84, 0x7d, 0x29, 0x03, 0xa6, 304 | 0x4e, 0x80, 0x04, 0x21, 0x38, 0x80, 0x00, 0x00, 0x90, 0x7f, 0x00, 0x00, 305 | 0x38, 0xa0, 0x01, 0x84, 0x4b, 0xe5, 0x86, 0x6d, 0x3d, 0x20, 0x01, 0x1e, 306 | 0x80, 0x01, 0x00, 0x14, 0x81, 0x29, 0xe4, 0xf4, 0x83, 0xe1, 0x00, 0x0c, 307 | 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 308 | 0x4e, 0x80, 0x04, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 309 | 0x3d, 0x40, 0x0a, 0x00, 0x93, 0xe1, 0x00, 0x0c, 0x3f, 0xe0, 0x10, 0x00, 310 | 0x90, 0x01, 0x00, 0x14, 0x63, 0xff, 0x00, 0xe4, 0x81, 0x3f, 0x00, 0x00, 311 | 0x7f, 0x89, 0x50, 0x00, 0x41, 0x9e, 0x00, 0x24, 0x3d, 0x20, 0x01, 0x1e, 312 | 0x80, 0x01, 0x00, 0x14, 0x81, 0x29, 0xe4, 0xf8, 0x83, 0xe1, 0x00, 0x0c, 313 | 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 314 | 0x4e, 0x80, 0x04, 0x20, 0x3d, 0x20, 0x10, 0x05, 0x38, 0x80, 0x00, 0x40, 315 | 0x81, 0x29, 0xf8, 0x70, 0x38, 0x60, 0x01, 0x84, 0x7d, 0x29, 0x03, 0xa6, 316 | 0x4e, 0x80, 0x04, 0x21, 0x38, 0x80, 0x00, 0x00, 0x90, 0x7f, 0x00, 0x00, 317 | 0x38, 0xa0, 0x01, 0x84, 0x4b, 0xe5, 0x85, 0xdd, 0x3d, 0x20, 0x01, 0x1e, 318 | 0x80, 0x01, 0x00, 0x14, 0x81, 0x29, 0xe4, 0xf8, 0x83, 0xe1, 0x00, 0x0c, 319 | 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x7d, 0x29, 0x03, 0xa6, 320 | 0x4e, 0x80, 0x04, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x3d, 0x20, 0x01, 0x1e, 321 | 0x94, 0x21, 0xff, 0xf0, 0x81, 0x29, 0xe4, 0xfc, 0x93, 0xe1, 0x00, 0x0c, 322 | 0x7d, 0x29, 0x03, 0xa6, 0x90, 0x01, 0x00, 0x14, 0x4e, 0x80, 0x04, 0x21, 323 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x3d, 0x40, 0x0a, 0x00, 324 | 0x81, 0x29, 0x00, 0x00, 0x7c, 0x7f, 0x1b, 0x78, 0x7f, 0x89, 0x50, 0x00, 325 | 0x41, 0x9e, 0x00, 0x18, 0x2b, 0x83, 0x00, 0x1f, 0x41, 0x9d, 0x00, 0x10, 326 | 0x54, 0x63, 0x10, 0x3a, 0x7c, 0x69, 0x1a, 0x14, 0x4b, 0xff, 0xf2, 0xe5, 327 | 0x80, 0x01, 0x00, 0x14, 0x7f, 0xe3, 0xfb, 0x78, 0x83, 0xe1, 0x00, 0x0c, 328 | 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x4e, 0x80, 0x00, 0x20, 329 | 0x7c, 0x08, 0x02, 0xa6, 0x3d, 0x20, 0x01, 0x1e, 0x94, 0x21, 0xff, 0xf0, 330 | 0x81, 0x29, 0xe5, 0x00, 0x93, 0xc1, 0x00, 0x08, 0x7c, 0x7e, 0x1b, 0x78, 331 | 0x93, 0xe1, 0x00, 0x0c, 0x7d, 0x29, 0x03, 0xa6, 0x90, 0x01, 0x00, 0x14, 332 | 0x4e, 0x80, 0x04, 0x21, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 333 | 0x7c, 0x7f, 0x1b, 0x78, 0x80, 0xe9, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 334 | 0x7f, 0x87, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x5c, 0x2f, 0x83, 0x00, 0x00, 335 | 0x41, 0x9c, 0x00, 0x54, 0x39, 0x00, 0x00, 0x20, 0x39, 0x47, 0x00, 0x7c, 336 | 0x39, 0x20, 0x00, 0x00, 0x7d, 0x09, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 337 | 0x39, 0x29, 0x00, 0x01, 0x42, 0x40, 0x00, 0x38, 0x85, 0x0a, 0x00, 0x04, 338 | 0x2f, 0x88, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x39, 0x49, 0x00, 0x20, 339 | 0x39, 0x29, 0x00, 0x40, 0x55, 0x4a, 0x10, 0x3a, 0x55, 0x29, 0x10, 0x3a, 340 | 0x7f, 0xc7, 0x51, 0x2e, 0x3d, 0x40, 0x10, 0x00, 0x61, 0x4a, 0x00, 0xe4, 341 | 0x80, 0x6a, 0x00, 0x00, 0x7c, 0x63, 0x4a, 0x14, 0x4b, 0xff, 0xf2, 0x31, 342 | 0x80, 0x01, 0x00, 0x14, 0x7f, 0xe3, 0xfb, 0x78, 0x83, 0xc1, 0x00, 0x08, 343 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xe1, 0x00, 0x0c, 0x38, 0x21, 0x00, 0x10, 344 | 0x4e, 0x80, 0x00, 0x20, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xf0, 345 | 0x3d, 0x20, 0x10, 0x00, 0x3d, 0x40, 0x0a, 0x00, 0x61, 0x29, 0x00, 0xe4, 346 | 0x93, 0xe1, 0x00, 0x0c, 0x90, 0x01, 0x00, 0x14, 0x7c, 0x7f, 0x1b, 0x78, 347 | 0x81, 0x29, 0x00, 0x00, 0x7f, 0x89, 0x50, 0x00, 0x41, 0x9e, 0x00, 0x18, 348 | 0x2b, 0x83, 0x00, 0x1f, 0x41, 0x9d, 0x00, 0x10, 0x54, 0x6a, 0x10, 0x3a, 349 | 0x7c, 0x69, 0x50, 0x2e, 0x4b, 0xff, 0xf2, 0xd1, 0x3d, 0x20, 0x01, 0x1e, 350 | 0x80, 0x01, 0x00, 0x14, 0x81, 0x29, 0xe5, 0x04, 0x7f, 0xe3, 0xfb, 0x78, 351 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xe1, 0x00, 0x0c, 0x38, 0x21, 0x00, 0x10, 352 | 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 0x7c, 0x08, 0x02, 0xa6, 353 | 0x94, 0x21, 0xff, 0xf0, 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 354 | 0x93, 0xc1, 0x00, 0x08, 0x90, 0x01, 0x00, 0x14, 0x7c, 0x7e, 0x1b, 0x78, 355 | 0x93, 0xe1, 0x00, 0x0c, 0x81, 0x09, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 356 | 0x7f, 0x88, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x58, 0x39, 0x40, 0x00, 0x20, 357 | 0x39, 0x28, 0x00, 0x7c, 0x3b, 0xe0, 0x00, 0x00, 0x7d, 0x49, 0x03, 0xa6, 358 | 0x48, 0x00, 0x00, 0x0c, 0x3b, 0xff, 0x00, 0x01, 0x42, 0x40, 0x00, 0x3c, 359 | 0x85, 0x49, 0x00, 0x04, 0x7f, 0x9e, 0x50, 0x00, 0x40, 0x9e, 0xff, 0xf0, 360 | 0x39, 0x3f, 0x00, 0x40, 0x3b, 0xff, 0x00, 0x20, 0x55, 0x29, 0x10, 0x3a, 361 | 0x57, 0xff, 0x10, 0x3a, 0x7c, 0x68, 0x48, 0x2e, 0x4b, 0xff, 0xf2, 0x3d, 362 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x39, 0x40, 0x00, 0x00, 363 | 0x81, 0x29, 0x00, 0x00, 0x7d, 0x49, 0xf9, 0x2e, 0x3d, 0x20, 0x01, 0x1e, 364 | 0x80, 0x01, 0x00, 0x14, 0x81, 0x29, 0xe5, 0x08, 0x7f, 0xc3, 0xf3, 0x78, 365 | 0x83, 0xe1, 0x00, 0x0c, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x08, 366 | 0x7d, 0x29, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x10, 0x4e, 0x80, 0x04, 0x20, 367 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd8, 0x3d, 0x20, 0x10, 0x00, 368 | 0x3d, 0x40, 0x0a, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x18, 369 | 0x90, 0x01, 0x00, 0x2c, 0x7c, 0x9c, 0x23, 0x78, 0x93, 0xa1, 0x00, 0x1c, 370 | 0x7c, 0xbd, 0x2b, 0x78, 0x81, 0x29, 0x00, 0x00, 0x93, 0xc1, 0x00, 0x20, 371 | 0x7c, 0xde, 0x33, 0x78, 0x7f, 0x89, 0x50, 0x00, 0x93, 0xe1, 0x00, 0x24, 372 | 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x0c, 0x2b, 0x83, 0x00, 0x1f, 373 | 0x40, 0x9d, 0x00, 0x44, 0x3d, 0x20, 0x01, 0x1e, 0x7f, 0xe3, 0xfb, 0x78, 374 | 0x81, 0x29, 0xe5, 0x0c, 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 375 | 0x7f, 0xc6, 0xf3, 0x78, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 376 | 0x80, 0x01, 0x00, 0x2c, 0x83, 0x81, 0x00, 0x18, 0x7c, 0x08, 0x03, 0xa6, 377 | 0x83, 0xa1, 0x00, 0x1c, 0x83, 0xc1, 0x00, 0x20, 0x83, 0xe1, 0x00, 0x24, 378 | 0x38, 0x21, 0x00, 0x28, 0x4e, 0x80, 0x00, 0x20, 0x54, 0x6a, 0x10, 0x3a, 379 | 0x38, 0x81, 0x00, 0x08, 0x7c, 0x69, 0x50, 0x2e, 0x7f, 0x85, 0xe3, 0x78, 380 | 0x7f, 0xa6, 0xeb, 0x78, 0x7f, 0xc7, 0xf3, 0x78, 0x4b, 0xff, 0xf1, 0x65, 381 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xa0, 0x80, 0x61, 0x00, 0x08, 382 | 0x4b, 0xff, 0xff, 0xb8, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xc8, 383 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0x61, 0x00, 0x24, 384 | 0x90, 0x01, 0x00, 0x3c, 0x7c, 0x9b, 0x23, 0x78, 0x93, 0x81, 0x00, 0x28, 385 | 0x7c, 0xbc, 0x2b, 0x78, 0x81, 0x89, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 386 | 0x93, 0xa1, 0x00, 0x2c, 0x7c, 0xdd, 0x33, 0x78, 0x7f, 0x8c, 0x48, 0x00, 387 | 0x93, 0xc1, 0x00, 0x30, 0x93, 0xe1, 0x00, 0x34, 0x7c, 0xfe, 0x3b, 0x78, 388 | 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x58, 0x38, 0xe0, 0x00, 0x20, 389 | 0x39, 0x2c, 0x00, 0x7c, 0x39, 0x40, 0x00, 0x00, 0x7c, 0xe9, 0x03, 0xa6, 390 | 0x48, 0x00, 0x00, 0x0c, 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0x00, 0x3c, 391 | 0x85, 0x69, 0x00, 0x04, 0x7f, 0x9f, 0x58, 0x00, 0x40, 0x9e, 0xff, 0xf0, 392 | 0x55, 0x4a, 0x10, 0x3a, 0x38, 0x81, 0x00, 0x08, 0x7c, 0x6c, 0x50, 0x2e, 393 | 0x7f, 0x85, 0xe3, 0x78, 0x7f, 0xa6, 0xeb, 0x78, 0x7f, 0xc7, 0xf3, 0x78, 394 | 0x91, 0x01, 0x00, 0x18, 0x4b, 0xff, 0xf0, 0xc1, 0x2f, 0x83, 0x00, 0x00, 395 | 0x81, 0x01, 0x00, 0x18, 0x41, 0x9e, 0x00, 0x4c, 0x3d, 0x20, 0x01, 0x1e, 396 | 0x7f, 0xe3, 0xfb, 0x78, 0x81, 0x29, 0xe5, 0x10, 0x7f, 0x64, 0xdb, 0x78, 397 | 0x7f, 0x85, 0xe3, 0x78, 0x7f, 0xa6, 0xeb, 0x78, 0x7f, 0xc7, 0xf3, 0x78, 398 | 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x3c, 399 | 0x83, 0x61, 0x00, 0x24, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0x81, 0x00, 0x28, 400 | 0x83, 0xa1, 0x00, 0x2c, 0x83, 0xc1, 0x00, 0x30, 0x83, 0xe1, 0x00, 0x34, 401 | 0x38, 0x21, 0x00, 0x38, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x61, 0x00, 0x08, 402 | 0x4b, 0xff, 0xff, 0xd8, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xc0, 403 | 0x3d, 0x60, 0x10, 0x00, 0x61, 0x6b, 0x00, 0xe4, 0x93, 0xa1, 0x00, 0x34, 404 | 0x90, 0x01, 0x00, 0x44, 0x93, 0x21, 0x00, 0x24, 0x7c, 0x99, 0x23, 0x78, 405 | 0x83, 0xab, 0x00, 0x00, 0x3d, 0x60, 0x0a, 0x00, 0x93, 0x41, 0x00, 0x28, 406 | 0x7c, 0xba, 0x2b, 0x78, 0x7f, 0x9d, 0x58, 0x00, 0x93, 0x61, 0x00, 0x2c, 407 | 0x93, 0x81, 0x00, 0x30, 0x7c, 0xdb, 0x33, 0x78, 0x93, 0xc1, 0x00, 0x38, 408 | 0x7c, 0xfc, 0x3b, 0x78, 0x93, 0xe1, 0x00, 0x3c, 0x7d, 0x1e, 0x43, 0x78, 409 | 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x18, 0x3d, 0x00, 0x0f, 0xff, 410 | 0x61, 0x08, 0x00, 0xff, 0x7f, 0xc7, 0x40, 0x38, 0x7f, 0x87, 0x40, 0x00, 411 | 0x41, 0x9e, 0x00, 0x58, 0x3d, 0x00, 0x01, 0x1e, 0x7f, 0xe3, 0xfb, 0x78, 412 | 0x81, 0x68, 0xe5, 0x14, 0x7f, 0x24, 0xcb, 0x78, 0x7f, 0x45, 0xd3, 0x78, 413 | 0x7f, 0x66, 0xdb, 0x78, 0x7f, 0x87, 0xe3, 0x78, 0x7f, 0xc8, 0xf3, 0x78, 414 | 0x7d, 0x69, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x44, 415 | 0x83, 0x21, 0x00, 0x24, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0x41, 0x00, 0x28, 416 | 0x83, 0x61, 0x00, 0x2c, 0x83, 0x81, 0x00, 0x30, 0x83, 0xa1, 0x00, 0x34, 417 | 0x83, 0xc1, 0x00, 0x38, 0x83, 0xe1, 0x00, 0x3c, 0x38, 0x21, 0x00, 0x40, 418 | 0x4e, 0x80, 0x00, 0x20, 0x39, 0x00, 0x00, 0x20, 0x39, 0x7d, 0x00, 0x7c, 419 | 0x39, 0x80, 0x00, 0x00, 0x7d, 0x09, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 420 | 0x39, 0x8c, 0x00, 0x01, 0x42, 0x40, 0xff, 0x94, 0x84, 0x0b, 0x00, 0x04, 421 | 0x7f, 0x9f, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x8c, 0x10, 0x3a, 422 | 0x38, 0x81, 0x00, 0x08, 0x7c, 0x7d, 0x60, 0x2e, 0x7f, 0x45, 0xd3, 0x78, 423 | 0x7f, 0x66, 0xdb, 0x78, 0x7f, 0x87, 0xe3, 0x78, 0x7f, 0xc8, 0xf3, 0x78, 424 | 0x91, 0x21, 0x00, 0x18, 0x91, 0x41, 0x00, 0x1c, 0x4b, 0xff, 0xf1, 0x9d, 425 | 0x2f, 0x83, 0x00, 0x00, 0x81, 0x21, 0x00, 0x18, 0x81, 0x41, 0x00, 0x1c, 426 | 0x40, 0x9e, 0xff, 0x50, 0x80, 0x61, 0x00, 0x08, 0x4b, 0xff, 0xff, 0x70, 427 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xb8, 0x3d, 0x60, 0x10, 0x00, 428 | 0x61, 0x6b, 0x00, 0xe4, 0x93, 0xc1, 0x00, 0x40, 0x90, 0x01, 0x00, 0x4c, 429 | 0x93, 0x21, 0x00, 0x2c, 0x7c, 0x99, 0x23, 0x78, 0x83, 0xcb, 0x00, 0x00, 430 | 0x3d, 0x60, 0x0a, 0x00, 0x93, 0x41, 0x00, 0x30, 0x7c, 0xba, 0x2b, 0x78, 431 | 0x7f, 0x9e, 0x58, 0x00, 0x93, 0x61, 0x00, 0x34, 0x93, 0x81, 0x00, 0x38, 432 | 0x7c, 0xdb, 0x33, 0x78, 0x93, 0xa1, 0x00, 0x3c, 0x7c, 0xfc, 0x3b, 0x78, 433 | 0x93, 0xe1, 0x00, 0x44, 0x7d, 0x1d, 0x43, 0x78, 0x93, 0x01, 0x00, 0x28, 434 | 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x18, 0x3c, 0x60, 0x0f, 0xff, 435 | 0x60, 0x63, 0x00, 0xff, 0x7d, 0x28, 0x18, 0x38, 0x7f, 0x88, 0x18, 0x00, 436 | 0x41, 0x9e, 0x00, 0x64, 0x81, 0x01, 0x00, 0x50, 0x7f, 0xe3, 0xfb, 0x78, 437 | 0x7f, 0x24, 0xcb, 0x78, 0x7f, 0x45, 0xd3, 0x78, 0x91, 0x01, 0x00, 0x08, 438 | 0x3d, 0x00, 0x01, 0x1e, 0x81, 0x68, 0xe5, 0x18, 0x7f, 0x66, 0xdb, 0x78, 439 | 0x7f, 0x87, 0xe3, 0x78, 0x7f, 0xa8, 0xeb, 0x78, 0x7d, 0x69, 0x03, 0xa6, 440 | 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x4c, 0x83, 0x01, 0x00, 0x28, 441 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0x21, 0x00, 0x2c, 0x83, 0x41, 0x00, 0x30, 442 | 0x83, 0x61, 0x00, 0x34, 0x83, 0x81, 0x00, 0x38, 0x83, 0xa1, 0x00, 0x3c, 443 | 0x83, 0xc1, 0x00, 0x40, 0x83, 0xe1, 0x00, 0x44, 0x38, 0x21, 0x00, 0x48, 444 | 0x4e, 0x80, 0x00, 0x20, 0x39, 0x00, 0x00, 0x20, 0x39, 0x7e, 0x00, 0x7c, 445 | 0x39, 0x80, 0x00, 0x00, 0x7d, 0x09, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 446 | 0x39, 0x8c, 0x00, 0x01, 0x42, 0x40, 0xff, 0x88, 0x84, 0x0b, 0x00, 0x04, 447 | 0x7f, 0x9f, 0x00, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x98, 0x10, 0x3a, 448 | 0x7d, 0x25, 0x4b, 0x78, 0x7c, 0x7e, 0xc0, 0x2e, 0x38, 0x81, 0x00, 0x10, 449 | 0x7f, 0xa6, 0xeb, 0x78, 0x91, 0x21, 0x00, 0x20, 0x91, 0x41, 0x00, 0x24, 450 | 0x4b, 0xff, 0xf3, 0x59, 0x2f, 0x83, 0x00, 0x00, 0x81, 0x21, 0x00, 0x20, 451 | 0x81, 0x41, 0x00, 0x24, 0x40, 0x9e, 0xff, 0x4c, 0x3d, 0x00, 0x10, 0x00, 452 | 0x38, 0x81, 0x00, 0x10, 0x61, 0x08, 0x00, 0xe4, 0x7f, 0x45, 0xd3, 0x78, 453 | 0x81, 0x08, 0x00, 0x00, 0x7f, 0x66, 0xdb, 0x78, 0x7f, 0x87, 0xe3, 0x78, 454 | 0x7c, 0x68, 0xc0, 0x2e, 0x7d, 0x28, 0x4b, 0x78, 0x4b, 0xff, 0xf0, 0x35, 455 | 0x81, 0x21, 0x00, 0x20, 0x2f, 0x83, 0x00, 0x00, 0x81, 0x41, 0x00, 0x24, 456 | 0x40, 0x9e, 0xff, 0x14, 0x80, 0x61, 0x00, 0x10, 0x4b, 0xff, 0xff, 0x3c, 457 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 0x3d, 0x20, 0x10, 0x00, 458 | 0x61, 0x29, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x20, 0x90, 0x01, 0x00, 0x34, 459 | 0x7c, 0x9c, 0x23, 0x78, 0x93, 0xa1, 0x00, 0x24, 0x7c, 0xdd, 0x33, 0x78, 460 | 0x81, 0x69, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 0x93, 0xc1, 0x00, 0x28, 461 | 0x7c, 0xbe, 0x2b, 0x78, 0x7f, 0x8b, 0x48, 0x00, 0x93, 0xe1, 0x00, 0x2c, 462 | 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x18, 0x3d, 0x20, 0x0f, 0xff, 463 | 0x61, 0x29, 0x00, 0xff, 0x7c, 0xaa, 0x48, 0x38, 0x7f, 0x8a, 0x48, 0x00, 464 | 0x41, 0x9e, 0x00, 0x44, 0x3d, 0x20, 0x01, 0x1e, 0x7f, 0xe3, 0xfb, 0x78, 465 | 0x81, 0x29, 0xe5, 0x1c, 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0xc5, 0xf3, 0x78, 466 | 0x7f, 0xa6, 0xeb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 467 | 0x80, 0x01, 0x00, 0x34, 0x83, 0x81, 0x00, 0x20, 0x7c, 0x08, 0x03, 0xa6, 468 | 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 0x83, 0xe1, 0x00, 0x2c, 469 | 0x38, 0x21, 0x00, 0x30, 0x4e, 0x80, 0x00, 0x20, 0x39, 0x00, 0x00, 0x20, 470 | 0x39, 0x2b, 0x00, 0x7c, 0x39, 0x40, 0x00, 0x00, 0x7d, 0x09, 0x03, 0xa6, 471 | 0x48, 0x00, 0x00, 0x0c, 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0xff, 0xa8, 472 | 0x85, 0x09, 0x00, 0x04, 0x7f, 0x9f, 0x40, 0x00, 0x40, 0x9e, 0xff, 0xf0, 473 | 0x55, 0x4a, 0x10, 0x3a, 0x38, 0x81, 0x00, 0x08, 0x7c, 0x6b, 0x50, 0x2e, 474 | 0x7f, 0xc5, 0xf3, 0x78, 0x7f, 0xa6, 0xeb, 0x78, 0x90, 0xe1, 0x00, 0x18, 475 | 0x4b, 0xff, 0xf2, 0x2d, 0x80, 0xe1, 0x00, 0x18, 0x2f, 0x83, 0x00, 0x00, 476 | 0x40, 0x9e, 0xff, 0x74, 0x80, 0x61, 0x00, 0x08, 0x4b, 0xff, 0xff, 0x8c, 477 | 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 0x3d, 0x20, 0x10, 0x00, 478 | 0x61, 0x29, 0x00, 0xe4, 0x93, 0xa1, 0x00, 0x24, 0x90, 0x01, 0x00, 0x34, 479 | 0x7c, 0x9d, 0x23, 0x78, 0x93, 0xc1, 0x00, 0x28, 0x7c, 0xbe, 0x2b, 0x78, 480 | 0x80, 0xe9, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 0x93, 0xe1, 0x00, 0x2c, 481 | 0x7c, 0x7f, 0x1b, 0x78, 0x7f, 0x87, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x18, 482 | 0x3d, 0x20, 0x0f, 0xff, 0x61, 0x29, 0x00, 0xff, 0x7c, 0xaa, 0x48, 0x38, 483 | 0x7f, 0x8a, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x3c, 0x3d, 0x20, 0x01, 0x1e, 484 | 0x7f, 0xe3, 0xfb, 0x78, 0x81, 0x29, 0xe5, 0x20, 0x7f, 0xa4, 0xeb, 0x78, 485 | 0x7f, 0xc5, 0xf3, 0x78, 0x7d, 0x29, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x21, 486 | 0x80, 0x01, 0x00, 0x34, 0x83, 0xa1, 0x00, 0x24, 0x7c, 0x08, 0x03, 0xa6, 487 | 0x83, 0xc1, 0x00, 0x28, 0x83, 0xe1, 0x00, 0x2c, 0x38, 0x21, 0x00, 0x30, 488 | 0x4e, 0x80, 0x00, 0x20, 0x39, 0x00, 0x00, 0x20, 0x39, 0x27, 0x00, 0x7c, 489 | 0x39, 0x40, 0x00, 0x00, 0x7d, 0x09, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 490 | 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0xff, 0xb0, 0x85, 0x09, 0x00, 0x04, 491 | 0x7f, 0x9f, 0x40, 0x00, 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x4a, 0x10, 0x3a, 492 | 0x38, 0x81, 0x00, 0x08, 0x7c, 0x67, 0x50, 0x2e, 0x7f, 0xc5, 0xf3, 0x78, 493 | 0x90, 0xc1, 0x00, 0x18, 0x4b, 0xff, 0xf0, 0x1d, 0x80, 0xc1, 0x00, 0x18, 494 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0x80, 0x80, 0x61, 0x00, 0x08, 495 | 0x4b, 0xff, 0xff, 0x94, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 496 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x20, 497 | 0x90, 0x01, 0x00, 0x34, 0x7c, 0x9c, 0x23, 0x78, 0x93, 0xa1, 0x00, 0x24, 498 | 0x7c, 0xdd, 0x33, 0x78, 0x81, 0x69, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 499 | 0x93, 0xc1, 0x00, 0x28, 0x7c, 0xbe, 0x2b, 0x78, 0x7f, 0x8b, 0x48, 0x00, 500 | 0x93, 0xe1, 0x00, 0x2c, 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x18, 501 | 0x3d, 0x20, 0x0f, 0xff, 0x61, 0x29, 0x00, 0xff, 0x7c, 0xaa, 0x48, 0x38, 502 | 0x7f, 0x8a, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x44, 0x3d, 0x20, 0x01, 0x1e, 503 | 0x7f, 0xe3, 0xfb, 0x78, 0x81, 0x29, 0xe5, 0x24, 0x7f, 0x84, 0xe3, 0x78, 504 | 0x7f, 0xc5, 0xf3, 0x78, 0x7f, 0xa6, 0xeb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 505 | 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x34, 0x83, 0x81, 0x00, 0x20, 506 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 507 | 0x83, 0xe1, 0x00, 0x2c, 0x38, 0x21, 0x00, 0x30, 0x4e, 0x80, 0x00, 0x20, 508 | 0x39, 0x00, 0x00, 0x20, 0x39, 0x2b, 0x00, 0x7c, 0x39, 0x40, 0x00, 0x00, 509 | 0x7d, 0x09, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 0x39, 0x4a, 0x00, 0x01, 510 | 0x42, 0x40, 0xff, 0xa8, 0x85, 0x09, 0x00, 0x04, 0x7f, 0x9f, 0x40, 0x00, 511 | 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x4a, 0x10, 0x3a, 0x38, 0x81, 0x00, 0x08, 512 | 0x7c, 0x6b, 0x50, 0x2e, 0x7f, 0xc5, 0xf3, 0x78, 0x7f, 0xa6, 0xeb, 0x78, 513 | 0x90, 0xe1, 0x00, 0x18, 0x4b, 0xff, 0xf1, 0xa9, 0x80, 0xe1, 0x00, 0x18, 514 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0x74, 0x80, 0x61, 0x00, 0x08, 515 | 0x4b, 0xff, 0xff, 0x8c, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 516 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0x81, 0x00, 0x20, 517 | 0x90, 0x01, 0x00, 0x34, 0x7c, 0x9c, 0x23, 0x78, 0x93, 0xa1, 0x00, 0x24, 518 | 0x7c, 0xdd, 0x33, 0x78, 0x81, 0x69, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 519 | 0x93, 0xc1, 0x00, 0x28, 0x7c, 0xbe, 0x2b, 0x78, 0x7f, 0x8b, 0x48, 0x00, 520 | 0x93, 0xe1, 0x00, 0x2c, 0x7c, 0x7f, 0x1b, 0x78, 0x41, 0x9e, 0x00, 0x18, 521 | 0x3d, 0x20, 0x0f, 0xff, 0x61, 0x29, 0x00, 0xff, 0x7c, 0xaa, 0x48, 0x38, 522 | 0x7f, 0x8a, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x44, 0x3d, 0x20, 0x01, 0x1e, 523 | 0x7f, 0xe3, 0xfb, 0x78, 0x81, 0x29, 0xe5, 0x28, 0x7f, 0x84, 0xe3, 0x78, 524 | 0x7f, 0xc5, 0xf3, 0x78, 0x7f, 0xa6, 0xeb, 0x78, 0x7d, 0x29, 0x03, 0xa6, 525 | 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x34, 0x83, 0x81, 0x00, 0x20, 526 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xa1, 0x00, 0x24, 0x83, 0xc1, 0x00, 0x28, 527 | 0x83, 0xe1, 0x00, 0x2c, 0x38, 0x21, 0x00, 0x30, 0x4e, 0x80, 0x00, 0x20, 528 | 0x39, 0x00, 0x00, 0x20, 0x39, 0x2b, 0x00, 0x7c, 0x39, 0x40, 0x00, 0x00, 529 | 0x7d, 0x09, 0x03, 0xa6, 0x48, 0x00, 0x00, 0x0c, 0x39, 0x4a, 0x00, 0x01, 530 | 0x42, 0x40, 0xff, 0xa8, 0x85, 0x09, 0x00, 0x04, 0x7f, 0x9f, 0x40, 0x00, 531 | 0x40, 0x9e, 0xff, 0xf0, 0x55, 0x4a, 0x10, 0x3a, 0x38, 0x81, 0x00, 0x08, 532 | 0x7c, 0x6b, 0x50, 0x2e, 0x7f, 0xc5, 0xf3, 0x78, 0x7f, 0xa6, 0xeb, 0x78, 533 | 0x90, 0xe1, 0x00, 0x18, 0x4b, 0xff, 0xf2, 0x15, 0x80, 0xe1, 0x00, 0x18, 534 | 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0x74, 0x80, 0x61, 0x00, 0x08, 535 | 0x4b, 0xff, 0xff, 0x8c, 0x7c, 0x08, 0x02, 0xa6, 0x94, 0x21, 0xff, 0xd0, 536 | 0x3d, 0x20, 0x10, 0x00, 0x61, 0x29, 0x00, 0xe4, 0x93, 0xa1, 0x00, 0x24, 537 | 0x90, 0x01, 0x00, 0x34, 0x7c, 0x9d, 0x23, 0x78, 0x93, 0xc1, 0x00, 0x28, 538 | 0x7c, 0xbe, 0x2b, 0x78, 0x80, 0xe9, 0x00, 0x00, 0x3d, 0x20, 0x0a, 0x00, 539 | 0x93, 0xe1, 0x00, 0x2c, 0x7c, 0x7f, 0x1b, 0x78, 0x7f, 0x87, 0x48, 0x00, 540 | 0x41, 0x9e, 0x00, 0x18, 0x3d, 0x20, 0x0f, 0xff, 0x61, 0x29, 0x00, 0xff, 541 | 0x7c, 0xaa, 0x48, 0x38, 0x7f, 0x8a, 0x48, 0x00, 0x41, 0x9e, 0x00, 0x3c, 542 | 0x3d, 0x20, 0x01, 0x1e, 0x7f, 0xe3, 0xfb, 0x78, 0x81, 0x29, 0xe5, 0x2c, 543 | 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, 0x7d, 0x29, 0x03, 0xa6, 544 | 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x34, 0x83, 0xa1, 0x00, 0x24, 545 | 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xc1, 0x00, 0x28, 0x83, 0xe1, 0x00, 0x2c, 546 | 0x38, 0x21, 0x00, 0x30, 0x4e, 0x80, 0x00, 0x20, 0x39, 0x00, 0x00, 0x20, 547 | 0x39, 0x27, 0x00, 0x7c, 0x39, 0x40, 0x00, 0x00, 0x7d, 0x09, 0x03, 0xa6, 548 | 0x48, 0x00, 0x00, 0x0c, 0x39, 0x4a, 0x00, 0x01, 0x42, 0x40, 0xff, 0xb0, 549 | 0x85, 0x09, 0x00, 0x04, 0x7f, 0x9f, 0x40, 0x00, 0x40, 0x9e, 0xff, 0xf0, 550 | 0x55, 0x4a, 0x10, 0x3a, 0x38, 0x81, 0x00, 0x08, 0x7c, 0x67, 0x50, 0x2e, 551 | 0x7f, 0xc5, 0xf3, 0x78, 0x90, 0xc1, 0x00, 0x18, 0x4b, 0xff, 0xf2, 0xb5, 552 | 0x80, 0xc1, 0x00, 0x18, 0x2f, 0x83, 0x00, 0x00, 0x40, 0x9e, 0xff, 0x80, 553 | 0x80, 0x61, 0x00, 0x08, 0x4b, 0xff, 0xff, 0x94, 0x00, 0x00, 0x00, 0x00, 554 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 555 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 556 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 557 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 558 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 559 | 0x00, 0x00, 0x00, 0x00 560 | }; 561 | static const unsigned int cafiine_text_bin_len = 6448; 562 | --------------------------------------------------------------------------------