├── CMakeLists.txt ├── README.md ├── aes.c ├── aes.h ├── build.sh ├── debugscreen ├── debugScreen.c ├── debugScreen.h ├── debugScreenFont.builder.html ├── debugScreenFont.c └── debugScreen_custom.h ├── file.c ├── file.h ├── main.c ├── main.h ├── modules ├── common │ ├── elf.h │ └── self.h ├── kernel │ ├── CMakeLists.txt │ ├── exports.yml │ ├── main.c │ └── vitashell_kernel.h ├── kplugin │ ├── CMakeLists.txt │ ├── context_130_base_kernel.h │ ├── context_130_base_sceshell.h │ ├── exports.yml │ ├── kentente.c │ ├── kentente.h │ └── kernel.h ├── patch │ ├── CMakeLists.txt │ ├── build │ │ └── Makefile │ ├── exports.yml │ └── main.c ├── uplugin │ ├── CMakeLists.txt │ ├── exports.yml │ ├── userAllied.c │ └── userAllied.h ├── usbdevice │ ├── CMakeLists.txt │ ├── exports.yml │ └── main.c └── user │ ├── CMakeLists.txt │ ├── exports.yml │ ├── main.c │ └── vitashell_user.h ├── pfs.c ├── pfs.h ├── pkg └── sce_sys │ ├── icon0.png │ └── livearea │ └── contents │ ├── bg.png │ ├── startup.png │ └── template.xml ├── sbrk.c ├── sce-elf-defs.h ├── sce-elf.c ├── sce-elf.h ├── sha256.c ├── sha256.h └── vitashell_error.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | # VitaSDK defines 4 | if( NOT DEFINED CMAKE_TOOLCHAIN_FILE ) 5 | if( DEFINED ENV{VITASDK} ) 6 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 7 | else() 8 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 9 | endif() 10 | endif() 11 | 12 | # Project start 13 | project(ShaRKF00D) 14 | include("${VITASDK}/share/vita.cmake" REQUIRED) 15 | set(VITA_APP_NAME "ShaRKF00D") 16 | set(VITA_TITLEID "SHARKF00D") 17 | set(VITA_VERSION "01.20") 18 | 19 | # Flags and includes 20 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -std=gnu11 -Wall -O0 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-format-truncation -fno-lto") 21 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11 -fno-rtti -fno-exceptions") 22 | set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1 -d ATTRIBUTE2=12") 23 | set(VITA_MAKE_FSELF_FLAGS "${VITA_MAKE_FSELF_FLAGS} -a 0x2808000000000000") 24 | 25 | add_subdirectory(modules/kernel) 26 | add_subdirectory(modules/user) 27 | add_subdirectory(modules/patch) 28 | add_subdirectory(modules/kplugin) 29 | add_subdirectory(modules/uplugin) 30 | 31 | include_directories( 32 | modules/kernel 33 | modules/user 34 | ) 35 | 36 | link_directories( 37 | ${CMAKE_CURRENT_BINARY_DIR} 38 | ) 39 | 40 | FUNCTION(ADD_RESOURCES out_var) 41 | SET(result) 42 | FOREACH(ref_f ${ARGN}) 43 | if (IS_ABSOLUTE "${ref_f}") 44 | SET(out_f "${ref_f}.o") 45 | STRING(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" in_f "${ref_f}") 46 | SET(work_dir "${CMAKE_CURRENT_BINARY_DIR}") 47 | else() 48 | SET(out_f "${CMAKE_CURRENT_BINARY_DIR}/${ref_f}.o") 49 | SET(in_f "${ref_f}") 50 | SET(work_dir "${CMAKE_SOURCE_DIR}") 51 | endif() 52 | GET_FILENAME_COMPONENT(out_dir ${out_f} DIRECTORY) 53 | ADD_CUSTOM_COMMAND(OUTPUT ${out_f} 54 | COMMAND ${CMAKE_COMMAND} -E make_directory ${out_dir} 55 | COMMAND ${CMAKE_LINKER} -r -b binary -o ${out_f} ${in_f} 56 | DEPENDS ${ref_f} 57 | WORKING_DIRECTORY ${work_dir} 58 | COMMENT "Building resource ${out_f}" 59 | VERBATIM 60 | ) 61 | LIST(APPEND result ${out_f}) 62 | ENDFOREACH() 63 | SET(${out_var} "${result}" PARENT_SCOPE) 64 | ENDFUNCTION() 65 | 66 | file(GLOB res_files RELATIVE 67 | ${CMAKE_SOURCE_DIR} 68 | resources/umass.skprx 69 | resources/default/*.png 70 | resources/default/*.txt 71 | resources/electron/*.png 72 | resources/electron/*.txt 73 | resources/*.png 74 | resources/*.txt 75 | resources/*.bin 76 | ) 77 | 78 | add_resources(sharkf00d_res 79 | ${res_files} 80 | ${CMAKE_CURRENT_BINARY_DIR}/modules/kernel/kernel.skprx 81 | ${CMAKE_CURRENT_BINARY_DIR}/modules/user/user.suprx 82 | ${CMAKE_CURRENT_BINARY_DIR}/modules/patch/patch.skprx 83 | ${CMAKE_CURRENT_BINARY_DIR}/modules/kplugin/kentente.skprx 84 | ${CMAKE_CURRENT_BINARY_DIR}/modules/uplugin/userAllied.suprx 85 | ) 86 | 87 | add_executable(ShaRKF00D 88 | ${sharkf00d_res} 89 | sbrk.c 90 | main.c 91 | file.c 92 | pfs.c 93 | sha256.c 94 | aes.c 95 | debugscreen/debugScreen.c 96 | ) 97 | 98 | add_dependencies(ShaRKF00D sharkf00d_user_stubs) 99 | add_dependencies(ShaRKF00D kernel.skprx) 100 | add_dependencies(ShaRKF00D user.suprx) 101 | add_dependencies(ShaRKF00D patch.skprx) 102 | add_dependencies(ShaRKF00D kentente.skprx) 103 | add_dependencies(ShaRKF00D userAllied.suprx) 104 | 105 | target_link_libraries(ShaRKF00D 106 | ${CMAKE_CURRENT_BINARY_DIR}/modules/user/vitashell_user_stubs/libVitaShellUser_stub_weak.a 107 | ${CMAKE_CURRENT_BINARY_DIR}/modules/uplugin/userAllied-stubs/libuserAllied_stub_weak.a 108 | z 109 | m 110 | c 111 | taihen_stub 112 | SceAppMgr_stub 113 | SceAppUtil_stub 114 | SceCommonDialog_stub 115 | SceCtrl_stub 116 | SceDisplay_stub 117 | SceFios2_stub 118 | SceLibKernel_stub 119 | SceMtpIfDriver_stub 120 | SceNpDrm_stub 121 | SceRegistryMgr_stub 122 | SceShellSvc_stub 123 | SceSysmodule_stub 124 | ScePower_stub 125 | ScePromoterUtil_stub 126 | SceTouch_stub 127 | SceVshBridge_stub 128 | ) 129 | 130 | # Create Vita artifacts 131 | vita_create_self(eboot.bin ShaRKF00D UNSAFE) 132 | vita_create_vpk(ShaRKF00D.vpk ${VITA_TITLEID} eboot.bin 133 | VERSION ${VITA_VERSION} 134 | NAME ${VITA_APP_NAME} 135 | FILE pkg/sce_sys/icon0.png sce_sys/icon0.png 136 | pkg/sce_sys/livearea/contents/bg.png sce_sys/livearea/contents/bg.png 137 | pkg/sce_sys/livearea/contents/startup.png sce_sys/livearea/contents/startup.png 138 | pkg/sce_sys/livearea/contents/template.xml sce_sys/livearea/contents/template.xml 139 | ${CMAKE_CURRENT_BINARY_DIR}/modules/kernel/kernel.skprx sce_module/kernel.skprx 140 | ${CMAKE_CURRENT_BINARY_DIR}/modules/patch/patch.skprx sce_module/patch.skprx 141 | ${CMAKE_CURRENT_BINARY_DIR}/modules/user/user.suprx sce_module/user.suprx 142 | ${CMAKE_CURRENT_BINARY_DIR}/modules/kplugin/kentente.skprx sce_module/kentente.skprx 143 | ${CMAKE_CURRENT_BINARY_DIR}/modules/uplugin/userAllied.suprx sce_module/userAllied.suprx 144 | ) 145 | 146 | add_custom_target(release 147 | COMMAND cp eboot.bin ../release/eboot.bin 148 | COMMAND cp ShaRKF00D.vpk_param.sfo ../release/param.sfo 149 | COMMAND cp ShaRKF00D.vpk ../release/ShaRKF00D.vpk 150 | COMMAND cp ../pkg/sce_sys/livearea/contents/template.xml ../release/template.xml 151 | DEPENDS eboot.bin 152 | DEPENDS ShaRKF00D.vpk 153 | DEPENDS ShaRKF00D.vpk_param.sfo 154 | ) 155 | 156 | add_custom_target(send 157 | COMMAND curl -T eboot.bin ftp://$(PSVITAIP):1337/ux0:/app/${VITA_TITLEID}/ 158 | DEPENDS eboot.bin 159 | ) 160 | 161 | add_custom_target(copy 162 | COMMAND cp eboot.bin G:/app/${VITA_TITLEID}/eboot.bin 163 | DEPENDS eboot.bin 164 | ) 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShaRKF00D 2 | ShaRKF00D is an all in one extractor, decrypter, and installer for SceShaccCg module which complements Rinnegatamante's vitaShaRK 3 | 4 | https://github.com/Rinnegatamante/vitaShaRK 5 | 6 | This project makes use of many already existing tools and is just put together to make it easier to obtain the SceShaccCg module. 7 | 8 | # Install Instructions 9 | First you will need to install PSM Runtime **with 2.01 patch update**. 10 | You will need to make sure you have 2.01 patch version as this installer is not compatible with just PSM Runtime 1.0 installed. 11 | 12 | Download and install ShaRKF00D.vpk using Vita Shell. 13 | Run the app and wait for it to exit out. There is no user dialogue for now. 14 | 15 | You should now have libshacccg.suprx module in ur0:/data/. You can check with VitaShell or ftp. 16 | The decrypted elf version of the file will be under ux0:/ShaRKF00D/. You may delete this if you like. 17 | 18 | A step by step guide by Samilop Cimmerian Iter can also be found in the link below. 19 | 20 | https://samilops2.gitbook.io/vita-troubleshooting-guide/shader-compiler/extract-libshacccg.suprx 21 | 22 | # Build Instructions 23 | ``` 24 | chmod +x build.sh 25 | mkdir build && cd build 26 | ../build.sh 27 | ``` 28 | 29 | # Credits 30 | 31 | **TheFlow** for VitaShell. 32 | 33 | **CelesteBlue/dots-tb** for FAGDec. 34 | 35 | All of whom that were involved with the development of vita-make-fself. 36 | 37 | -------------------------------------------------------------------------------- /aes.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS-197 compliant AES implementation 3 | * 4 | * Copyright (C) 2006-2010, Brainspark B.V. 5 | * 6 | * This file is part of PolarSSL (http://www.polarssl.org) 7 | * Lead Maintainer: Paul Bakker 8 | * 9 | * All rights reserved. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License along 22 | * with this program; if not, write to the Free Software Foundation, Inc., 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | */ 25 | /* 26 | * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. 27 | * 28 | * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf 29 | * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf 30 | */ 31 | 32 | #include "aes.h" 33 | 34 | /* 35 | * 32-bit integer manipulation macros (little endian) 36 | */ 37 | #ifndef GET_ULONG_LE 38 | #define GET_ULONG_LE(n,b,i) \ 39 | { \ 40 | (n) = ( (unsigned long) (b)[(i) ] ) \ 41 | | ( (unsigned long) (b)[(i) + 1] << 8 ) \ 42 | | ( (unsigned long) (b)[(i) + 2] << 16 ) \ 43 | | ( (unsigned long) (b)[(i) + 3] << 24 ); \ 44 | } 45 | #endif 46 | 47 | #ifndef PUT_ULONG_LE 48 | #define PUT_ULONG_LE(n,b,i) \ 49 | { \ 50 | (b)[(i) ] = (unsigned char) ( (n) ); \ 51 | (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ 52 | (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ 53 | (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ 54 | } 55 | #endif 56 | 57 | /* 58 | * Forward S-box 59 | */ 60 | static const unsigned char FSb[256] = 61 | { 62 | 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 63 | 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 64 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 65 | 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 66 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 67 | 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 68 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 69 | 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 70 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 71 | 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 72 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 73 | 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 74 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 75 | 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 76 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 77 | 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 78 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 79 | 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 80 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 81 | 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 82 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 83 | 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 84 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 85 | 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 86 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 87 | 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 88 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 89 | 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 90 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 91 | 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 92 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 93 | 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 94 | }; 95 | 96 | /* 97 | * Forward tables 98 | */ 99 | #define FT \ 100 | \ 101 | V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ 102 | V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ 103 | V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ 104 | V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ 105 | V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ 106 | V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ 107 | V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ 108 | V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ 109 | V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ 110 | V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ 111 | V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ 112 | V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ 113 | V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ 114 | V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ 115 | V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ 116 | V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ 117 | V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ 118 | V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ 119 | V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ 120 | V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ 121 | V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ 122 | V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ 123 | V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ 124 | V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ 125 | V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ 126 | V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ 127 | V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ 128 | V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ 129 | V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ 130 | V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ 131 | V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ 132 | V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ 133 | V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ 134 | V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ 135 | V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ 136 | V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ 137 | V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ 138 | V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ 139 | V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ 140 | V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ 141 | V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ 142 | V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ 143 | V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ 144 | V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ 145 | V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ 146 | V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ 147 | V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ 148 | V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ 149 | V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ 150 | V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ 151 | V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ 152 | V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ 153 | V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ 154 | V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ 155 | V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ 156 | V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ 157 | V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ 158 | V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ 159 | V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ 160 | V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ 161 | V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ 162 | V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ 163 | V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ 164 | V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) 165 | 166 | #define V(a,b,c,d) 0x##a##b##c##d 167 | static const unsigned long FT0[256] = { FT }; 168 | #undef V 169 | 170 | #define V(a,b,c,d) 0x##b##c##d##a 171 | static const unsigned long FT1[256] = { FT }; 172 | #undef V 173 | 174 | #define V(a,b,c,d) 0x##c##d##a##b 175 | static const unsigned long FT2[256] = { FT }; 176 | #undef V 177 | 178 | #define V(a,b,c,d) 0x##d##a##b##c 179 | static const unsigned long FT3[256] = { FT }; 180 | #undef V 181 | 182 | #undef FT 183 | 184 | /* 185 | * Reverse S-box 186 | */ 187 | static const unsigned char RSb[256] = 188 | { 189 | 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 190 | 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 191 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 192 | 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 193 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 194 | 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 195 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 196 | 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 197 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 198 | 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 199 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 200 | 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 201 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 202 | 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 203 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 204 | 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 205 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 206 | 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 207 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 208 | 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 209 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 210 | 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 211 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 212 | 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 213 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 214 | 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 215 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 216 | 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 217 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 218 | 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 219 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 220 | 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D 221 | }; 222 | 223 | /* 224 | * Reverse tables 225 | */ 226 | #define RT \ 227 | \ 228 | V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ 229 | V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ 230 | V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ 231 | V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ 232 | V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ 233 | V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ 234 | V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ 235 | V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ 236 | V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ 237 | V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ 238 | V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ 239 | V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ 240 | V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ 241 | V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ 242 | V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ 243 | V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ 244 | V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ 245 | V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ 246 | V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ 247 | V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ 248 | V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ 249 | V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ 250 | V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ 251 | V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ 252 | V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ 253 | V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ 254 | V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ 255 | V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ 256 | V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ 257 | V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ 258 | V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ 259 | V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ 260 | V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ 261 | V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ 262 | V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ 263 | V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ 264 | V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ 265 | V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ 266 | V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ 267 | V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ 268 | V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ 269 | V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ 270 | V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ 271 | V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ 272 | V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ 273 | V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ 274 | V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ 275 | V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ 276 | V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ 277 | V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ 278 | V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ 279 | V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ 280 | V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ 281 | V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ 282 | V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ 283 | V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ 284 | V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ 285 | V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ 286 | V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ 287 | V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ 288 | V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ 289 | V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ 290 | V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ 291 | V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) 292 | 293 | #define V(a,b,c,d) 0x##a##b##c##d 294 | static const unsigned long RT0[256] = { RT }; 295 | #undef V 296 | 297 | #define V(a,b,c,d) 0x##b##c##d##a 298 | static const unsigned long RT1[256] = { RT }; 299 | #undef V 300 | 301 | #define V(a,b,c,d) 0x##c##d##a##b 302 | static const unsigned long RT2[256] = { RT }; 303 | #undef V 304 | 305 | #define V(a,b,c,d) 0x##d##a##b##c 306 | static const unsigned long RT3[256] = { RT }; 307 | #undef V 308 | 309 | #undef RT 310 | 311 | /* 312 | * Round constants 313 | */ 314 | static const unsigned long RCON[10] = 315 | { 316 | 0x00000001, 0x00000002, 0x00000004, 0x00000008, 317 | 0x00000010, 0x00000020, 0x00000040, 0x00000080, 318 | 0x0000001B, 0x00000036 319 | }; 320 | 321 | /* 322 | * AES key schedule (encryption) 323 | */ 324 | int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ) 325 | { 326 | unsigned int i; 327 | unsigned long *RK; 328 | 329 | switch( keysize ) 330 | { 331 | case 128: ctx->nr = 10; break; 332 | case 192: ctx->nr = 12; break; 333 | case 256: ctx->nr = 14; break; 334 | default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); 335 | } 336 | 337 | ctx->rk = RK = ctx->buf; 338 | 339 | for( i = 0; i < (keysize >> 5); i++ ) 340 | { 341 | GET_ULONG_LE( RK[i], key, i << 2 ); 342 | } 343 | 344 | switch( ctx->nr ) 345 | { 346 | case 10: 347 | 348 | for( i = 0; i < 10; i++, RK += 4 ) 349 | { 350 | RK[4] = RK[0] ^ RCON[i] ^ 351 | ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ 352 | ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ 353 | ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ 354 | ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 ); 355 | 356 | RK[5] = RK[1] ^ RK[4]; 357 | RK[6] = RK[2] ^ RK[5]; 358 | RK[7] = RK[3] ^ RK[6]; 359 | } 360 | break; 361 | 362 | case 12: 363 | 364 | for( i = 0; i < 8; i++, RK += 6 ) 365 | { 366 | RK[6] = RK[0] ^ RCON[i] ^ 367 | ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ 368 | ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ 369 | ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ 370 | ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 ); 371 | 372 | RK[7] = RK[1] ^ RK[6]; 373 | RK[8] = RK[2] ^ RK[7]; 374 | RK[9] = RK[3] ^ RK[8]; 375 | RK[10] = RK[4] ^ RK[9]; 376 | RK[11] = RK[5] ^ RK[10]; 377 | } 378 | break; 379 | 380 | case 14: 381 | 382 | for( i = 0; i < 7; i++, RK += 8 ) 383 | { 384 | RK[8] = RK[0] ^ RCON[i] ^ 385 | ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ 386 | ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ 387 | ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ 388 | ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 ); 389 | 390 | RK[9] = RK[1] ^ RK[8]; 391 | RK[10] = RK[2] ^ RK[9]; 392 | RK[11] = RK[3] ^ RK[10]; 393 | 394 | RK[12] = RK[4] ^ 395 | ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^ 396 | ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ 397 | ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ 398 | ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); 399 | 400 | RK[13] = RK[5] ^ RK[12]; 401 | RK[14] = RK[6] ^ RK[13]; 402 | RK[15] = RK[7] ^ RK[14]; 403 | } 404 | break; 405 | 406 | default: 407 | 408 | break; 409 | } 410 | 411 | return( 0 ); 412 | } 413 | 414 | /* 415 | * AES key schedule (decryption) 416 | */ 417 | int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ) 418 | { 419 | int i, j; 420 | aes_context cty; 421 | unsigned long *RK; 422 | unsigned long *SK; 423 | int ret; 424 | 425 | switch( keysize ) 426 | { 427 | case 128: ctx->nr = 10; break; 428 | case 192: ctx->nr = 12; break; 429 | case 256: ctx->nr = 14; break; 430 | default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); 431 | } 432 | 433 | ctx->rk = RK = ctx->buf; 434 | 435 | ret = aes_setkey_enc( &cty, key, keysize ); 436 | if( ret != 0 ) 437 | return( ret ); 438 | 439 | SK = cty.rk + cty.nr * 4; 440 | 441 | *RK++ = *SK++; 442 | *RK++ = *SK++; 443 | *RK++ = *SK++; 444 | *RK++ = *SK++; 445 | 446 | for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) 447 | { 448 | for( j = 0; j < 4; j++, SK++ ) 449 | { 450 | *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ 451 | RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ 452 | RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ 453 | RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; 454 | } 455 | } 456 | 457 | *RK++ = *SK++; 458 | *RK++ = *SK++; 459 | *RK++ = *SK++; 460 | *RK++ = *SK++; 461 | 462 | memset( &cty, 0, sizeof( aes_context ) ); 463 | 464 | return( 0 ); 465 | } 466 | 467 | #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ 468 | { \ 469 | X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ 470 | FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ 471 | FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ 472 | FT3[ ( Y3 >> 24 ) & 0xFF ]; \ 473 | \ 474 | X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ 475 | FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ 476 | FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ 477 | FT3[ ( Y0 >> 24 ) & 0xFF ]; \ 478 | \ 479 | X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ 480 | FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ 481 | FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ 482 | FT3[ ( Y1 >> 24 ) & 0xFF ]; \ 483 | \ 484 | X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ 485 | FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ 486 | FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ 487 | FT3[ ( Y2 >> 24 ) & 0xFF ]; \ 488 | } 489 | 490 | #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ 491 | { \ 492 | X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ 493 | RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ 494 | RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ 495 | RT3[ ( Y1 >> 24 ) & 0xFF ]; \ 496 | \ 497 | X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ 498 | RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ 499 | RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ 500 | RT3[ ( Y2 >> 24 ) & 0xFF ]; \ 501 | \ 502 | X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ 503 | RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ 504 | RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ 505 | RT3[ ( Y3 >> 24 ) & 0xFF ]; \ 506 | \ 507 | X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ 508 | RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ 509 | RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ 510 | RT3[ ( Y0 >> 24 ) & 0xFF ]; \ 511 | } 512 | 513 | /* 514 | * AES-ECB block encryption/decryption 515 | */ 516 | int aes_crypt_ecb( aes_context *ctx, 517 | int mode, 518 | const unsigned char input[16], 519 | unsigned char output[16] ) 520 | { 521 | int i; 522 | unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; 523 | 524 | RK = ctx->rk; 525 | 526 | GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++; 527 | GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++; 528 | GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++; 529 | GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++; 530 | 531 | if( mode == AES_DECRYPT ) 532 | { 533 | for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) 534 | { 535 | AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); 536 | AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); 537 | } 538 | 539 | AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); 540 | 541 | X0 = *RK++ ^ \ 542 | ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^ 543 | ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ 544 | ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ 545 | ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); 546 | 547 | X1 = *RK++ ^ \ 548 | ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^ 549 | ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ 550 | ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ 551 | ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); 552 | 553 | X2 = *RK++ ^ \ 554 | ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^ 555 | ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ 556 | ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ 557 | ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); 558 | 559 | X3 = *RK++ ^ \ 560 | ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^ 561 | ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ 562 | ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ 563 | ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); 564 | } 565 | else /* AES_ENCRYPT */ 566 | { 567 | for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) 568 | { 569 | AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); 570 | AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); 571 | } 572 | 573 | AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); 574 | 575 | X0 = *RK++ ^ \ 576 | ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^ 577 | ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ 578 | ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ 579 | ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); 580 | 581 | X1 = *RK++ ^ \ 582 | ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^ 583 | ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ 584 | ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ 585 | ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); 586 | 587 | X2 = *RK++ ^ \ 588 | ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^ 589 | ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ 590 | ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ 591 | ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); 592 | 593 | X3 = *RK++ ^ \ 594 | ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^ 595 | ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ 596 | ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ 597 | ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); 598 | } 599 | 600 | PUT_ULONG_LE( X0, output, 0 ); 601 | PUT_ULONG_LE( X1, output, 4 ); 602 | PUT_ULONG_LE( X2, output, 8 ); 603 | PUT_ULONG_LE( X3, output, 12 ); 604 | 605 | return( 0 ); 606 | } 607 | 608 | /* 609 | * AES-CBC buffer encryption/decryption 610 | */ 611 | int aes_crypt_cbc( aes_context *ctx, 612 | int mode, 613 | size_t length, 614 | unsigned char iv[16], 615 | const unsigned char *input, 616 | unsigned char *output ) 617 | { 618 | int i; 619 | unsigned char temp[16]; 620 | 621 | if( length % 16 ) 622 | return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); 623 | 624 | if( mode == AES_DECRYPT ) 625 | { 626 | while( length > 0 ) 627 | { 628 | memcpy( temp, input, 16 ); 629 | aes_crypt_ecb( ctx, mode, input, output ); 630 | 631 | for( i = 0; i < 16; i++ ) 632 | output[i] = (unsigned char)( output[i] ^ iv[i] ); 633 | 634 | memcpy( iv, temp, 16 ); 635 | 636 | input += 16; 637 | output += 16; 638 | length -= 16; 639 | } 640 | } 641 | else 642 | { 643 | while( length > 0 ) 644 | { 645 | for( i = 0; i < 16; i++ ) 646 | output[i] = (unsigned char)( input[i] ^ iv[i] ); 647 | 648 | aes_crypt_ecb( ctx, mode, output, output ); 649 | memcpy( iv, output, 16 ); 650 | 651 | input += 16; 652 | output += 16; 653 | length -= 16; 654 | } 655 | } 656 | 657 | return( 0 ); 658 | } 659 | 660 | /* 661 | * AES-CTR buffer encryption/decryption 662 | */ 663 | int aes_crypt_ctr( aes_context *ctx, 664 | size_t length, 665 | size_t *nc_off, 666 | unsigned char nonce_counter[16], 667 | unsigned char stream_block[16], 668 | const unsigned char *input, 669 | unsigned char *output ) 670 | { 671 | int c, i, cb; 672 | size_t n = *nc_off; 673 | 674 | while( length-- ) 675 | { 676 | if( n == 0 ) { 677 | aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block ); 678 | 679 | i = 15; 680 | do { 681 | nonce_counter[i]++; 682 | cb = nonce_counter[i] == 0; 683 | } while( i-- && cb ); 684 | 685 | } 686 | c = *input++; 687 | *output++ = (unsigned char)( c ^ stream_block[n] ); 688 | 689 | n = (n + 1) & 0x0F; 690 | } 691 | 692 | *nc_off = n; 693 | 694 | return( 0 ); 695 | } 696 | -------------------------------------------------------------------------------- /aes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file aes.h 3 | * 4 | * \brief AES block cipher 5 | * 6 | * Copyright (C) 2006-2010, Brainspark B.V. 7 | * 8 | * This file is part of PolarSSL (http://www.polarssl.org) 9 | * Lead Maintainer: Paul Bakker 10 | * 11 | * All rights reserved. 12 | * 13 | * This program is free software; you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation; either version 2 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License along 24 | * with this program; if not, write to the Free Software Foundation, Inc., 25 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 26 | */ 27 | #ifndef POLARSSL_AES_H 28 | #define POLARSSL_AES_H 29 | 30 | #include 31 | 32 | #define AES_ENCRYPT 1 33 | #define AES_DECRYPT 0 34 | 35 | #define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ 36 | #define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ 37 | 38 | /** 39 | * \brief AES context structure 40 | */ 41 | typedef struct 42 | { 43 | int nr; /*!< number of rounds */ 44 | unsigned long *rk; /*!< AES round keys */ 45 | unsigned long buf[68]; /*!< unaligned data */ 46 | } 47 | aes_context; 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | /** 54 | * \brief AES key schedule (encryption) 55 | * 56 | * \param ctx AES context to be initialized 57 | * \param key encryption key 58 | * \param keysize must be 128, 192 or 256 59 | * 60 | * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH 61 | */ 62 | int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ); 63 | 64 | /** 65 | * \brief AES key schedule (decryption) 66 | * 67 | * \param ctx AES context to be initialized 68 | * \param key decryption key 69 | * \param keysize must be 128, 192 or 256 70 | * 71 | * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH 72 | */ 73 | int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ); 74 | 75 | /** 76 | * \brief AES-ECB block encryption/decryption 77 | * 78 | * \param ctx AES context 79 | * \param mode AES_ENCRYPT or AES_DECRYPT 80 | * \param input 16-byte input block 81 | * \param output 16-byte output block 82 | * 83 | * \return 0 if successful 84 | */ 85 | int aes_crypt_ecb( aes_context *ctx, 86 | int mode, 87 | const unsigned char input[16], 88 | unsigned char output[16] ); 89 | 90 | /** 91 | * \brief AES-CBC buffer encryption/decryption 92 | * Length should be a multiple of the block 93 | * size (16 bytes) 94 | * 95 | * \param ctx AES context 96 | * \param mode AES_ENCRYPT or AES_DECRYPT 97 | * \param length length of the input data 98 | * \param iv initialization vector (updated after use) 99 | * \param input buffer holding the input data 100 | * \param output buffer holding the output data 101 | * 102 | * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH 103 | */ 104 | int aes_crypt_cbc( aes_context *ctx, 105 | int mode, 106 | size_t length, 107 | unsigned char iv[16], 108 | const unsigned char *input, 109 | unsigned char *output ); 110 | 111 | /* 112 | * \brief AES-CTR buffer encryption/decryption 113 | * 114 | * Warning: You have to keep the maximum use of your counter in mind! 115 | * 116 | * Note: Due to the nature of CTR you should use the same key schedule for 117 | * both encryption and decryption. So a context initialized with 118 | * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. 119 | * 120 | * \param length The length of the data 121 | * \param nc_off The offset in the current stream_block (for resuming 122 | * within current cipher stream). The offset pointer to 123 | * should be 0 at the start of a stream. 124 | * \param nonce_counter The 128-bit nonce and counter. 125 | * \param stream_block The saved stream-block for resuming. Is overwritten 126 | * by the function. 127 | * \param input The input data stream 128 | * \param output The output data stream 129 | * 130 | * \return 0 if successful 131 | */ 132 | int aes_crypt_ctr( aes_context *ctx, 133 | size_t length, 134 | size_t *nc_off, 135 | unsigned char nonce_counter[16], 136 | unsigned char stream_block[16], 137 | const unsigned char *input, 138 | unsigned char *output ); 139 | 140 | #ifdef __cplusplus 141 | } 142 | #endif 143 | 144 | #endif /* aes.h */ 145 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cmake .. 4 | make -C modules/kernel 5 | make -C modules/patch 6 | make -C modules/user 7 | make -C modules/kplugin 8 | make -C modules/uplugin 9 | make 10 | 11 | -------------------------------------------------------------------------------- /debugscreen/debugScreen.c: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_SCREEN_C 2 | #define DEBUG_SCREEN_C 3 | 4 | /* 5 | * debugScreen.c of Vita SDK 6 | * 7 | * - psvDebugScreenInit() 8 | * Initializes debug screen for output. 9 | * 10 | * - psvDebugScreenPuts() 11 | * Similar to the C library function puts() writes a string to the debug 12 | * screen up to but not including the NUL character. 13 | * Supports the most important CSI sequences of ECMA-48 / ISO/IEC 6429:1992. 14 | * Graphic Rendition Combination Mode (GRCM) supported is Cumulative. 15 | * Modifications: 16 | * - CSI SGR codes 30-37/38/39 & 40-47/48/49 set standard/fitting/default intensity, so instead of "\e[1;31m" use "\e31;1m" 17 | * - ANSI color #8 is made darker (40<>80), so that "dark" white is still lighter than "bright" dark 18 | * - support 16 save storages for CSI s and CSI u, e.g "\e[8s" and "\e[8u" 19 | * [1] https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences 20 | * [2] https://jonasjacek.github.io/colors/ 21 | * [3] https://www.ecma-international.org/publications/standards/Ecma-048.htm 22 | * [4] https://invisible-island.net/xterm/ctlseqs/ctlseqs.html 23 | * [5] http://man7.org/linux/man-pages/man4/console_codes.4.html 24 | * 25 | * (CSI = "\e[") 26 | * CSI [n] s = Save Cursor Position to slot #n (0-15). Default 0. 27 | * CSI [n] u = Restore Cursor Position from slot #n (0-15). Default 0. 28 | * CSI n A = Cursor Up times. 29 | * CSI n B = Cursor Down times. 30 | * CSI n C = Cursor Forward times. 31 | * CSI n D = Cursor Back times. 32 | * CSI n E = Cursor Next Line times and to Beginning of that Line. 33 | * CSI n F = Cursor Previous Line times and to Beginning of that Line. 34 | * CSI n G = Cursor to Column . The value is 1-based and defaults to 1 (first column) if omitted. 35 | * CSI n ; m H = Cursor to Row and Column . The values are 1-based and default to 1 (top left corner) if omitted. 36 | * CSI n ; m f = Cursor to Row and Column . The values are 1-based and default to 1 (top left corner) if omitted. 37 | * CSI [n] J = Clears part of the screen. Cursor position does not change. 38 | * 0 (default) from cursor to end of screen. 39 | * 1 from cursor to beginning of the screen. 40 | * 2 entire screen 41 | * CSI [n] K = Clears part of the line. Cursor position does not change. 42 | * 0 (default) from cursor to end of line. 43 | * 1 from cursor to beginning of line. 44 | * 2 clear entire line. 45 | * CSI [n] m = Sets the appearance of the following characters. 46 | * 0 Reset all (colors and inversion) (default) 47 | * 1 Increased intensity ("bright" color) 48 | * 2 Decreased intensity ("faint"/"dark" color) 49 | * 7 Enable inversion 50 | * 22 Standard intensity ("normal" color) 51 | * 27 Disable inversion 52 | * 30–37 Set ANSI foreground color with standard intensity 53 | * 38 Set foreground color. Arguments are 5; or 2;;; 54 | * 39 Default foreground color 55 | * 40–47 Set standard ANSI background color with standard intensity 56 | * 48 Set background color. Arguments are 5; or 2;;; 57 | * 49 Default background color 58 | * 90–97 Set ANSI foreground color with increased intensity 59 | * 100–107 Set ANSI background color with increased intensity 60 | * 61 | * - psvDebugScreenPrintf() 62 | * Similar to the C library function printf() formats a string and ouputs 63 | * it via psvDebugScreenPuts() to the debug screen. 64 | * 65 | * - psvDebugScreenGetColorStateCopy(ColorState *copy) 66 | * Get copy of current color state. 67 | * 68 | * - psvDebugScreenGetCoordsXY(int *x, int *y) 69 | * Get copy of current pixel coordinates. 70 | * Allows for multiple and custom position stores. 71 | * Allows correct positioning when using different font sizes. 72 | * 73 | * - psvDebugScreenSetCoordsXY(int *x, int *y) 74 | * Set pixel coordinates. 75 | * Allows for multiple and custom position stores. 76 | * Allows correct positioning when using different font sizes. 77 | * 78 | * - PsvDebugScreenFont *psvDebugScreenGetFont() 79 | * Get current font. 80 | * 81 | * - PsvDebugScreenFont *psvDebugScreenSetFont(PsvDebugScreenFont *font) { 82 | * Set font. Returns current font. 83 | * 84 | * - PsvDebugScreenFont *psvDebugScreenScaleFont2x(PsvDebugScreenFont *source_font) { 85 | * Scales a font by 2 (e.g. 8x8 to 16x16) and returns new scaled font. 86 | * 87 | * Also see the following samples: 88 | * - debugscreen 89 | * - debug_print 90 | * 91 | */ 92 | 93 | #include // for malloc(), free() 94 | #include // for vsnprintf() 95 | #include // for memset(), memcpy() 96 | #include // for va_list, va_start(), va_end() 97 | #include 98 | 99 | #include "debugScreen.h" 100 | 101 | #include "debugScreenFont.c" 102 | 103 | #define SCREEN_FB_WIDTH (960) // frame buffer aligned width for accessing vram 104 | #define SCREEN_FB_SIZE (2 * 1024 * 1024) // Must be 256KB aligned 105 | #ifndef SCREEN_TAB_SIZE // this allows easy overriding 106 | #define SCREEN_TAB_SIZE (8) 107 | #endif 108 | #define SCREEN_TAB_W ((F)->size_w * (SCREEN_TAB_SIZE)) 109 | #define F psvDebugScreenFontCurrent 110 | 111 | #define FROM_FULL_RGB(r,g,b ) ( ((b)<<16) | ((g)<<8) | (r) ) 112 | #define CONVERT_RGB_BGR(rgb) rgb = ( (((rgb)&0x0000FF)<<16) | ((rgb)&0x00FF00) | (((rgb)&0xFF0000)>>16) ) 113 | 114 | #define CLEARSCRNBLOCK(H,toH,W,toW,color) for (int h = (H); h < (toH); h++) for (int w = (W); w < (toW); w++) ((uint32_t*)base)[h*(SCREEN_FB_WIDTH) + w] = (color); 115 | #define CLEARSCRNLINES(H,toH,color) { uint32_t *pixel = (uint32_t *)base + ((H) * (SCREEN_FB_WIDTH)); int i = (((toH) - (H)) * (SCREEN_FB_WIDTH)); for (; i > 0; i--) *pixel++ = (color); } 116 | 117 | #define SAVE_STORAGES 16 118 | 119 | static int mutex, coordX, coordY; 120 | static int savedX[SAVE_STORAGES] = { 0 }, savedY[SAVE_STORAGES] = { 0 }; 121 | static ColorState colors = { 122 | 0, 0, // truecolor flags 123 | 0, 0, // truecolors 124 | 0, 0, 0, 0, 0, // ANSI/VTERM/GREYSCALE colors 125 | 7, 22, 0, 22, 0, // default colors (ANSI/VTERM/GREYSCALE) 126 | }; 127 | 128 | static PsvDebugScreenFont *psvDebugScreenFontCurrent = &psvDebugScreenFont; 129 | 130 | #ifdef __vita__ 131 | #include 132 | #include 133 | #include 134 | static void* base; // pointer to frame buffer 135 | #else 136 | #define NO_psvDebugScreenInit 137 | #ifndef psvDebugScreenInitReplacement 138 | #define psvDebugScreenInitReplacement(...) 139 | #endif 140 | #define sceKernelLockMutex(m,v,x) m=v 141 | #define sceKernelUnlockMutex(m,v) m=v 142 | static char base[(SCREEN_FB_WIDTH) * (SCREEN_HEIGHT) * 4]; 143 | #endif 144 | 145 | static uint32_t DARK_COLORS_BGR[8] = { 146 | 0x000000, 0x000040, 0x004000, 0x004040, 0x400000, 0x400040, 0x404000, 0x808080, // 0-7 147 | }; 148 | 149 | // ANSI/VTERM/GREYSCALE palette: https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit 150 | // modifications: 151 | // - #8 is made darker (40<>80), so that "dark" white is still lighter than "bright" dark 152 | static uint32_t ANSI_COLORS_BGR[256] = { 153 | 0x000000, 0x000080, 0x008000, 0x008080, 0x800000, 0x800080, 0x808000, 0xc0c0c0, // 0-7 154 | 0x404040, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff, 0xffff00, 0xffffff, // 8-15 155 | 0x000000, 0x5f0000, 0x870000, 0xaf0000, 0xd70000, 0xff0000, 0x005f00, 0x5f5f00, // 16-23 156 | 0x875f00, 0xaf5f00, 0xd75f00, 0xff5f00, 0x008700, 0x5f8700, 0x878700, 0xaf8700, // 24-31 157 | 0xd78700, 0xff8700, 0x00af00, 0x5faf00, 0x87af00, 0xafaf00, 0xd7af00, 0xffaf00, // 32-39 158 | 0x00d700, 0x5fd700, 0x87d700, 0xafd700, 0xd7d700, 0xffd700, 0x00ff00, 0x5fff00, // 40-47 159 | 0x87ff00, 0xafff00, 0xd7ff00, 0xffff00, 0x00005f, 0x5f005f, 0x87005f, 0xaf005f, // 48-55 160 | 0xd7005f, 0xff005f, 0x005f5f, 0x5f5f5f, 0x875f5f, 0xaf5f5f, 0xd75f5f, 0xff5f5f, // 56-63 161 | 0x00875f, 0x5f875f, 0x87875f, 0xaf875f, 0xd7875f, 0xff875f, 0x00af5f, 0x5faf5f, // 64-71 162 | 0x87af5f, 0xafaf5f, 0xd7af5f, 0xffaf5f, 0x00d75f, 0x5fd75f, 0x87d75f, 0xafd75f, // 72-79 163 | 0xd7d75f, 0xffd75f, 0x00ff5f, 0x5fff5f, 0x87ff5f, 0xafff5f, 0xd7ff5f, 0xffff5f, // 80-87 164 | 0x000087, 0x5f0087, 0x870087, 0xaf0087, 0xd70087, 0xff0087, 0x005f87, 0x5f5f87, // 88-95 165 | 0x875f87, 0xaf5f87, 0xd75f87, 0xff5f87, 0x008787, 0x5f8787, 0x878787, 0xaf8787, // 96-103 166 | 0xd78787, 0xff8787, 0x00af87, 0x5faf87, 0x87af87, 0xafaf87, 0xd7af87, 0xffaf87, // 104-111 167 | 0x00d787, 0x5fd787, 0x87d787, 0xafd787, 0xd7d787, 0xffd787, 0x00ff87, 0x5fff87, // 112-119 168 | 0x87ff87, 0xafff87, 0xd7ff87, 0xffff87, 0x0000af, 0x5f00af, 0x8700af, 0xaf00af, // 120-127 169 | 0xd700af, 0xff00af, 0x005faf, 0x5f5faf, 0x875faf, 0xaf5faf, 0xd75faf, 0xff5faf, // 128-135 170 | 0x0087af, 0x5f87af, 0x8787af, 0xaf87af, 0xd787af, 0xff87af, 0x00afaf, 0x5fafaf, // 136-143 171 | 0x87afaf, 0xafafaf, 0xd7afaf, 0xffafaf, 0x00d7af, 0x5fd7af, 0x87d7af, 0xafd7af, // 144-151 172 | 0xd7d7af, 0xffd7af, 0x00ffaf, 0x5fffaf, 0x87ffaf, 0xafffaf, 0xd7ffaf, 0xffffaf, // 152-159 173 | 0x0000d7, 0x5f00d7, 0x8700d7, 0xaf00d7, 0xd700d7, 0xff00d7, 0x005fd7, 0x5f5fd7, // 160-167 174 | 0x875fd7, 0xaf5fd7, 0xd75fd7, 0xff5fd7, 0x0087d7, 0x5f87d7, 0x8787d7, 0xaf87d7, // 168-175 175 | 0xd787d7, 0xff87d7, 0x00afd7, 0x5fafd7, 0x87afd7, 0xafafd7, 0xd7afd7, 0xffafd7, // 176-183 176 | 0x00d7d7, 0x5fd7d7, 0x87d7d7, 0xafd7d7, 0xd7d7d7, 0xffd7d7, 0x00ffd7, 0x5fffd7, // 184-191 177 | 0x87ffd7, 0xafffd7, 0xd7ffd7, 0xffffd7, 0x0000ff, 0x5f00ff, 0x8700ff, 0xaf00ff, // 192-199 178 | 0xd700ff, 0xff00ff, 0x005fff, 0x5f5fff, 0x875fff, 0xaf5fff, 0xd75fff, 0xff5fff, // 200-207 179 | 0x0087ff, 0x5f87ff, 0x8787ff, 0xaf87ff, 0xd787ff, 0xff87ff, 0x00afff, 0x5fafff, // 208-215 180 | 0x87afff, 0xafafff, 0xd7afff, 0xffafff, 0x00d7ff, 0x5fd7ff, 0x87d7ff, 0xafd7ff, // 216-223 181 | 0xd7d7ff, 0xffd7ff, 0x00ffff, 0x5fffff, 0x87ffff, 0xafffff, 0xd7ffff, 0xffffff, // 224-231 182 | 0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e, // 232-239 183 | 0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e, // 240-247 184 | 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee, // 248-255 185 | }; 186 | 187 | /* 188 | * Reset foreground color to default 189 | */ 190 | static void psvDebugScreenResetFgColor(void) { 191 | colors.fgTrueColorFlag = 0; 192 | colors.fgTrueColor = 0; 193 | colors.fgIndex = colors.fgIndexDefault; 194 | colors.fgIntensity = colors.fgIntensityDefault; 195 | } 196 | 197 | /* 198 | * Reset background color to default 199 | */ 200 | static void psvDebugScreenResetBgColor(void) { 201 | colors.bgTrueColorFlag = 0; 202 | colors.bgTrueColor = 0; 203 | colors.bgIndex = colors.bgIndexDefault; 204 | colors.bgIntensity = colors.bgIntensityDefault; 205 | } 206 | 207 | /* 208 | * Reset inversion state to default 209 | */ 210 | static void psvDebugScreenResetInversion(void) { 211 | colors.inversion = colors.inversionDefault; 212 | } 213 | 214 | /* 215 | * Determine colors according to current color state 216 | */ 217 | static void psvDebugScreenSetColors(void) { 218 | uint32_t *color_fg, *color_bg; 219 | 220 | // special case: inversion 221 | if (!colors.inversion) { 222 | color_fg = &colors.color_fg; 223 | color_bg = &colors.color_bg; 224 | } else { 225 | color_fg = &colors.color_bg; 226 | color_bg = &colors.color_fg; 227 | } 228 | 229 | // foregound color 230 | if ((colors.fgIndex<=7) && (colors.fgIntensity==1)) { // ANSI palette with increased intensity 231 | colors.fgIndex |= 0x8; 232 | } else if ((colors.fgIndex<=15) && (colors.fgIntensity!=1)) { // ANSI palette with standard/decreased intensity 233 | colors.fgIndex &= 0x7; 234 | } 235 | if (colors.fgTrueColorFlag) { 236 | *color_fg = colors.fgTrueColor; 237 | } else { 238 | if ((colors.fgIndex<=7) && (colors.fgIntensity==2)) { // "ANSI" palette with decreased intensity 239 | *color_fg = DARK_COLORS_BGR[colors.fgIndex]; 240 | } else { // ANSI/VTERM/GREYSCALE palette 241 | *color_fg = ANSI_COLORS_BGR[colors.fgIndex]; 242 | } 243 | } 244 | *color_fg |= 0xFF000000; // opaque 245 | 246 | // backgound color 247 | if ((colors.bgIndex<=7) && (colors.bgIntensity==1)) { // ANSI palette with increased intensity 248 | colors.bgIndex |= 0x8; 249 | } else if ((colors.bgIndex<=15) && (colors.bgIntensity!=1)) { // ANSI palette with standard/decreased intensity 250 | colors.bgIndex &= 0x7; 251 | } 252 | if (colors.bgTrueColorFlag) { 253 | *color_bg = colors.bgTrueColor; 254 | } else { 255 | if ((colors.bgIndex<=7) && (colors.bgIntensity==2)) { // "ANSI" palette with decreased intensity 256 | *color_bg = DARK_COLORS_BGR[colors.bgIndex]; 257 | } else { // ANSI/VTERM/GREYSCALE palette 258 | *color_bg = ANSI_COLORS_BGR[colors.bgIndex]; 259 | } 260 | } 261 | *color_bg |= 0xFF000000; // opaque 262 | } 263 | 264 | /* 265 | * Parse CSI sequences 266 | */ 267 | static size_t psvDebugScreenEscape(const unsigned char *str) { 268 | unsigned int i, argc, arg[32] = { 0 }; 269 | unsigned int c; 270 | uint32_t unit, mode; 271 | int *colorTrueColorFlag; 272 | uint32_t *colorTrueColor; 273 | unsigned char *colorIndex, *colorIntensity; 274 | for (i = 0, argc = 0; (argc < (sizeof(arg)/sizeof(*arg))) && (str[i] != '\0'); i++) { 275 | switch (str[i]) { 276 | // numeric char 277 | case '0': 278 | case '1': 279 | case '2': 280 | case '3': 281 | case '4': 282 | case '5': 283 | case '6': 284 | case '7': 285 | case '8': 286 | case '9': 287 | arg[argc] = (arg[argc] * 10) + (str[i] - '0'); 288 | continue; 289 | // argument separator 290 | case ';': argc++; continue; 291 | // CSI commands 292 | // save/restore position 293 | case 's': 294 | if (arg[0]size_h; return i; 301 | case 'B': coordY += arg[0] * (F)->size_h; return i; 302 | case 'C': coordX += arg[0] * (F)->size_w; return i; 303 | case 'D': coordX -= arg[0] * (F)->size_w; return i; 304 | // cursor movement to beginning of next/previous line(s) 305 | case 'E': coordY += arg[0] * (F)->size_h; coordX = 0; return i; 306 | case 'F': coordY -= arg[0] * (F)->size_h; coordX = 0; return i; 307 | // cursor positioning 308 | case 'G': coordX = (arg[0]-1) * (F)->size_w; return i; 309 | case 'H': 310 | case 'f': 311 | coordY = (arg[0]-1) * (F)->size_h; 312 | coordX = (arg[1]-1) * (F)->size_w; 313 | return i; 314 | // clear part of "J"=screen or "K"=Line, so J code re-uses part of K 315 | case 'J': 316 | case 'K': 317 | if (arg[0]==0) { // from cursor to end of line/screen 318 | CLEARSCRNBLOCK(coordY, coordY + (F)->size_h, coordX, (SCREEN_WIDTH), colors.color_bg); // line 319 | if (str[i]=='J') CLEARSCRNLINES(coordY + (F)->size_h, (SCREEN_HEIGHT), colors.color_bg); // screen 320 | } else if (arg[0]==1) { // from beginning of line/screen to cursor 321 | CLEARSCRNBLOCK(coordY, coordY + (F)->size_h, 0, coordX, colors.color_bg); // line 322 | if (str[i]=='J') CLEARSCRNLINES(0, coordY, colors.color_bg); // screen 323 | } else if (arg[0]==2) { // whole line/screen 324 | if (str[i]=='K') CLEARSCRNLINES(coordY, coordY + (F)->size_h, colors.color_bg) // line 325 | else if (str[i]=='J') CLEARSCRNLINES(0, (SCREEN_HEIGHT), colors.color_bg); // screen 326 | } 327 | return i; 328 | // color 329 | case 'm': 330 | for (c = 0; c <= argc; c++) { 331 | switch (arg[c]) { 332 | // reset all 333 | case 0: 334 | psvDebugScreenResetFgColor(); 335 | psvDebugScreenResetBgColor(); 336 | psvDebugScreenResetInversion(); 337 | continue; 338 | break; 339 | // intensity 340 | case 1: // increased = "bright" color 341 | case 2: // decreased = "dark" color 342 | case 22: // standard = "normal" color 343 | colors.fgIntensity = arg[c]; 344 | continue; 345 | break; 346 | // inversion 347 | case 7: // enable 348 | colors.inversion = 1; 349 | continue; 350 | break; 351 | case 27: // disable 352 | colors.inversion = 0; 353 | continue; 354 | break; 355 | // set from color map or truecolor 356 | case 38: // foreground color 357 | case 48: // background color 358 | mode = arg[c] / 10; 359 | colorTrueColorFlag = mode&1 ? &colors.fgTrueColorFlag : &colors.bgTrueColorFlag; 360 | if (arg[c+1]==5) { // 8-bit: [0-15][16-231][232-255] color map 361 | *colorTrueColorFlag = 0; 362 | colorIndex = mode&1 ? &colors.fgIndex : &colors.bgIndex; 363 | *colorIndex = arg[c+2] & 0xFF; 364 | colorIntensity = mode&1 ? &colors.fgIntensity : &colors.bgIntensity; 365 | *colorIntensity = ((*colorIndex>=8) && (*colorIndex<=15)) ? 1 : 22; 366 | c+=2; // extra arguments 367 | } else if (arg[c+1]==2) { // 24-bit color space 368 | *colorTrueColorFlag = 1; 369 | colorTrueColor = mode&1 ? &colors.fgTrueColor : &colors.bgTrueColor; 370 | *colorTrueColor = FROM_FULL_RGB(arg[c+2], arg[c+3], arg[c+4]); 371 | c+=4; // extra arguments 372 | } 373 | continue; 374 | break; 375 | // default color 376 | case 39: // foreground color 377 | psvDebugScreenResetFgColor(); 378 | continue; 379 | break; 380 | case 49: // background color 381 | psvDebugScreenResetBgColor(); 382 | continue; 383 | break; 384 | // custom color reset 385 | default: 386 | // ANSI colors (30-37, 40-47, 90-97, 100-107) 387 | mode = arg[c] / 10; 388 | if ((mode!=3) && (mode!=4) && (mode!=9) && (mode!=10)) continue; // skip unsupported modes 389 | unit = arg[c] % 10; 390 | if (unit>7) continue; // skip unsupported modes 391 | colorTrueColorFlag = mode&1 ? &colors.fgTrueColorFlag : &colors.bgTrueColorFlag; 392 | *colorTrueColorFlag = 0; 393 | colorIndex = mode&1 ? &colors.fgIndex : &colors.bgIndex; 394 | *colorIndex = unit; 395 | colorIntensity = mode&1 ? &colors.fgIntensity : &colors.bgIntensity; 396 | *colorIntensity = mode&8 ? 1 : 22; 397 | break; 398 | } 399 | } 400 | psvDebugScreenSetColors(); 401 | return i; 402 | } 403 | } 404 | return 0; 405 | } 406 | 407 | /* 408 | * Initialize debug screen 409 | */ 410 | int psvDebugScreenInit() { 411 | psvDebugScreenResetFgColor(); 412 | psvDebugScreenResetBgColor(); 413 | psvDebugScreenResetInversion(); 414 | psvDebugScreenSetColors(); 415 | 416 | #ifdef NO_psvDebugScreenInit 417 | psvDebugScreenInitReplacement(); 418 | return 0; // avoid linking non-initializer (prx) with sceDisplay/sceMemory 419 | #else 420 | mutex = sceKernelCreateMutex("log_mutex", 0, 0, NULL); 421 | SceUID displayblock = sceKernelAllocMemBlock("display", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, (SCREEN_FB_SIZE), NULL); 422 | sceKernelGetMemBlockBase(displayblock, (void**)&base); 423 | SceDisplayFrameBuf frame = { sizeof(frame), base, (SCREEN_FB_WIDTH), 0, (SCREEN_WIDTH), (SCREEN_HEIGHT) }; 424 | return sceDisplaySetFrameBuf(&frame, SCE_DISPLAY_SETBUF_NEXTFRAME); 425 | #endif 426 | } 427 | 428 | /* 429 | * Draw text onto debug screen 430 | */ 431 | int psvDebugScreenPuts(const char * _text) { 432 | const unsigned char*text = (const unsigned char*)_text; 433 | int c; 434 | unsigned char t; 435 | unsigned char drawDummy; 436 | // 437 | uint32_t *vram; 438 | int bits_per_glyph = ((F)->width * (F)->height); 439 | int bitmap_offset; 440 | unsigned char *font; 441 | int row; 442 | int max_row; 443 | int col; 444 | unsigned char mask; 445 | uint32_t *pixel; 446 | 447 | sceKernelLockMutex(mutex, 1, NULL); 448 | for (c = 0; text[c] ; c++) { 449 | t = text[c]; 450 | // handle CSI sequence 451 | if ((t == '\e') && (text[c+1] == '[')) { 452 | c += psvDebugScreenEscape(text + c + 2) + 2; 453 | if (coordX < 0) coordX = 0; // CSI position are 1-based, 454 | if (coordY < 0) coordY = 0; // prevent 0-based coordinate from producing a negative X/Y 455 | continue; 456 | } 457 | // handle non-printable characters #1 (line-dependent codes) 458 | if (t == '\n') { 459 | coordX = 0; 460 | coordY += (F)->size_h; 461 | continue; 462 | } 463 | if (t == '\r') { 464 | coordX = 0; 465 | continue; 466 | } 467 | // check if glyph fits in line 468 | if ((coordX + (F)->width) > (SCREEN_WIDTH)) { 469 | coordY += (F)->size_h; 470 | coordX = 0; 471 | } 472 | // check if glyph fits in screen 473 | if ((coordY + (F)->height) > (SCREEN_HEIGHT)) { 474 | coordX = coordY = 0; 475 | } 476 | // handle non-printable characters #2 477 | if (t == '\t') { 478 | coordX += (SCREEN_TAB_W) - (coordX % (SCREEN_TAB_W)); 479 | continue; 480 | } 481 | 482 | // draw glyph or dummy glyph (dotted line in the middle) 483 | // works also with not byte-aligned glyphs 484 | vram = ((uint32_t*)base) + coordX + (coordY * (SCREEN_FB_WIDTH)); 485 | row = 0; 486 | // check if glyph is available in font 487 | if ((t > (F)->last) || (t < (F)->first)) { 488 | drawDummy = 1; 489 | } else { 490 | drawDummy = 0; 491 | bitmap_offset = (t - (F)->first) * bits_per_glyph; 492 | font = &(F)->glyphs[ (bitmap_offset / 8) ]; 493 | mask = 1 << 7; 494 | for (col = (bitmap_offset % 8); col > 0; col--, mask >>= 1); 495 | } 496 | // special case: dummy glyph, clear to middle height 497 | max_row = 0; 498 | if (drawDummy) { 499 | max_row = (F)->height / 2; 500 | for (; row < max_row; row++, vram += (SCREEN_FB_WIDTH)) { 501 | pixel = vram; 502 | col = 0; 503 | for (; col < (F)->size_w ; col++) { 504 | *pixel++ = colors.color_bg; 505 | } 506 | } 507 | } 508 | // draw font glyph or dummy glyph 509 | if (drawDummy) { 510 | max_row++; 511 | if (max_row > (F)->height) max_row = (F)->height; 512 | } else { 513 | max_row = (F)->height; 514 | } 515 | for (; row < max_row; row++, vram += (SCREEN_FB_WIDTH)) { 516 | pixel = vram; 517 | col = 0; 518 | for (; col < (F)->width ; col++, mask >>= 1) { 519 | if (drawDummy) { 520 | *pixel++ = (col&1) ? colors.color_fg : colors.color_bg; 521 | } else { 522 | if (!mask) { font++; mask = 1 << 7; } // no more bits: we exhausted this byte 523 | *pixel++ = (*font&mask) ? colors.color_fg : colors.color_bg; 524 | } 525 | } 526 | // right margin 527 | for (; col < (F)->size_w ; col++) 528 | *pixel++ = colors.color_bg; 529 | } 530 | // draw bottom margin 531 | max_row = (F)->size_h; 532 | for (; row < (F)->size_h; row++, vram += (SCREEN_FB_WIDTH)) 533 | for (pixel = vram, col = 0; col < (F)->size_w ; col++) 534 | *pixel++ = colors.color_bg; 535 | // advance X position 536 | coordX += (F)->size_w; 537 | } 538 | sceKernelUnlockMutex(mutex, 1); 539 | return c; 540 | } 541 | 542 | 543 | /* 544 | * Printf text onto debug screen 545 | */ 546 | __attribute__((__format__ (__printf__, 1, 2))) 547 | int psvDebugScreenPrintf(const char *format, ...) { 548 | char buf[4096]; 549 | 550 | va_list opt; 551 | va_start(opt, format); 552 | int ret = vsnprintf(buf, sizeof(buf), format, opt); 553 | psvDebugScreenPuts(buf); 554 | va_end(opt); 555 | 556 | return ret; 557 | } 558 | 559 | /* 560 | * Return copy of color state 561 | */ 562 | void psvDebugScreenGetColorStateCopy(ColorState *copy) { 563 | if (copy) { 564 | memcpy(copy, &colors, sizeof(ColorState)); 565 | CONVERT_RGB_BGR(copy->fgTrueColor); 566 | CONVERT_RGB_BGR(copy->bgTrueColor); 567 | CONVERT_RGB_BGR(copy->color_fg); 568 | CONVERT_RGB_BGR(copy->color_bg); 569 | } 570 | } 571 | 572 | /* 573 | * Return copy of pixel coordinates 574 | */ 575 | void psvDebugScreenGetCoordsXY(int *x, int *y) { 576 | if (x) *x = coordX; 577 | if (y) *y = coordY; 578 | } 579 | 580 | /* 581 | * Set pixel coordinates 582 | */ 583 | void psvDebugScreenSetCoordsXY(int *x, int *y) { 584 | if (x) { 585 | coordX = *x; 586 | if (coordX < 0) coordX = 0; 587 | } 588 | if (y) { 589 | coordY = *y; 590 | if (coordY < 0) coordY = 0; 591 | } 592 | } 593 | 594 | /* 595 | * Return pointer to current font 596 | */ 597 | PsvDebugScreenFont *psvDebugScreenGetFont(void) { 598 | return F; 599 | } 600 | 601 | /* 602 | * Set font 603 | */ 604 | PsvDebugScreenFont *psvDebugScreenSetFont(PsvDebugScreenFont *font) { 605 | if ((font) && (font->glyphs)) F = font; 606 | return F; 607 | } 608 | 609 | /* 610 | * Return scaled-by-2 copy of font 611 | */ 612 | PsvDebugScreenFont *psvDebugScreenScaleFont2x(PsvDebugScreenFont *source_font) { 613 | // works also with not byte-aligned glyphs 614 | PsvDebugScreenFont *target_font; 615 | size_t size; 616 | size_t align; 617 | int glyph; 618 | int row; 619 | int col; 620 | int count; 621 | unsigned char *source_bitmap; 622 | unsigned char source_mask; 623 | unsigned char *target_bitmap, *target_bitmap2; 624 | unsigned char target_mask, target_mask2; 625 | int target_next_row_bytes, target_next_row_bits; 626 | unsigned char pixel; 627 | 628 | if (!source_font) return NULL; 629 | 630 | // allocate target structure and bitmap 631 | target_font = (PsvDebugScreenFont *)malloc(sizeof(PsvDebugScreenFont)); 632 | memset(target_font, 0, sizeof(PsvDebugScreenFont)); 633 | // copy and scale meta information 634 | target_font->width = 2 * source_font->width; 635 | target_font->height = 2 * source_font->height; 636 | target_font->first = source_font->first; 637 | target_font->last = source_font->last; 638 | target_font->size_w = 2 * source_font->size_w; 639 | target_font->size_h = 2 * source_font->size_h; 640 | 641 | // calculate size of target bitmap 642 | size = target_font->width * target_font->height * (target_font->last - target_font->first + 1); 643 | if (size <= 0) { 644 | free(target_font); 645 | return NULL; 646 | } 647 | align = size % 8; 648 | size /= 8; 649 | if (align) size++; 650 | 651 | // allocate and initialize target bitmap 652 | target_font->glyphs = (unsigned char *)malloc(size); 653 | memset(target_font->glyphs, 0, size); 654 | 655 | // scale source bitmap and store in target bitmap 656 | source_bitmap = source_font->glyphs; 657 | source_mask = 1 << 7; 658 | // 659 | target_bitmap = target_font->glyphs; 660 | target_mask = 1 << 7; 661 | target_next_row_bytes = target_font->width / 8; 662 | target_next_row_bits = target_font->width % 8; 663 | // 664 | for (glyph = source_font->first; glyph <= source_font->last; glyph++) { 665 | for (row = source_font->height; row > 0; row--) { 666 | // Find beginning of next target row 667 | target_bitmap2 = target_bitmap + target_next_row_bytes; // advance full bytes 668 | target_mask2 = target_mask; // advance remaining bits 669 | for (col = target_next_row_bits; col > 0; col--, target_mask2 >>= 1) { 670 | if (!target_mask2) { target_bitmap2++; target_mask2 = 1 << 7; } // no more bits: we advance to the next target byte 671 | } 672 | // Get pixel from source bitmap 673 | for (col = source_font->width; col > 0; col--, source_mask >>= 1) { 674 | if (!source_mask) { source_bitmap++; source_mask = 1 << 7; } // no more bits: we advance to the next source byte 675 | pixel = *source_bitmap & source_mask; 676 | // Put pixels into target bitmap 677 | for (count = 2; count > 0; count--) { 678 | // duplicate column in origial row 679 | if (!target_mask) { target_bitmap++; target_mask = 1 << 7; } // no more bits: we advance to the next target byte 680 | if (pixel) *target_bitmap |= target_mask; 681 | target_mask >>= 1; 682 | // duplicate column in duplicated row 683 | if (!target_mask2) { target_bitmap2++; target_mask2 = 1 << 7; } // no more bits: we advance to the next target byte 684 | if (pixel) *target_bitmap2 |= target_mask2; 685 | target_mask2 >>= 1; 686 | } 687 | } 688 | // Next target row is directly behind duplicated row 689 | target_bitmap = target_bitmap2; 690 | target_mask = target_mask2; 691 | } 692 | } 693 | 694 | return target_font; 695 | } 696 | 697 | #undef SCREEN_TAB_W 698 | #undef F 699 | 700 | #endif 701 | -------------------------------------------------------------------------------- /debugscreen/debugScreen.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_SCREEN_H 2 | #define DEBUG_SCREEN_H 3 | 4 | #include "debugScreen_custom.h" 5 | 6 | typedef struct ColorState { 7 | int fgTrueColorFlag; // flag if truecolors or ANSI/VTERM/GREYSCALE colors are used 8 | int bgTrueColorFlag; // flag if truecolors or ANSI/VTERM/GREYSCALE colors are used 9 | // truecolors 10 | uint32_t fgTrueColor; // color in RGB (internal BGR) 11 | uint32_t bgTrueColor; // color in RGB (internal BGR) 12 | // ANSI/VTERM/GREYSCALE colors 13 | unsigned char fgIndex; // ANSI/VTERM/GREYSCALE color code (0-255) 14 | unsigned char fgIntensity; // 22=normal, 1=increased ("bright"), 2=decreased ("dark") 15 | unsigned char bgIndex; // ANSI/VTERM/GREYSCALE color code (0-255) 16 | unsigned char bgIntensity; // 22=normal, 1=increased ("bright") 17 | int inversion; // flag if bg/fg colors are inverted 18 | 19 | // default colors (ANSI/VTERM/GREYSCALE) 20 | unsigned char fgIndexDefault; // default ANSI/VTERM/GREYSCALE color code 21 | unsigned char fgIntensityDefault; // 22=normal, 1=increased, 2=decreased 22 | unsigned char bgIndexDefault; // default ANSI/VTERM/GREYSCALE color code 23 | unsigned char bgIntensityDefault; // 22=normal, 1=increased 24 | int inversionDefault; // flag if bg/fg colors are inverted 25 | 26 | // current colors (e.g. inverted) 27 | uint32_t color_fg; // color in RGB (internal BGR) 28 | uint32_t color_bg; // color in RGB (internal BGR) 29 | } ColorState; 30 | 31 | typedef struct PsvDebugScreenFont { 32 | unsigned char *glyphs, width, height, first, last, size_w, size_h; // only values 0-255 33 | } PsvDebugScreenFont; 34 | 35 | #define SCREEN_WIDTH (960) // screen resolution x 36 | #define SCREEN_HEIGHT (544) // screen resolution y 37 | 38 | #ifdef DEBUG_SCREEN_CODE_INCLUDE // not recommended for your own projects, but for sake of backward compatibility 39 | #include "debugScreen.c" 40 | #else 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | int psvDebugScreenInit(); 45 | int psvDebugScreenPuts(const char * _text); 46 | int psvDebugScreenPrintf(const char *format, ...); 47 | void psvDebugScreenGetColorStateCopy(ColorState *copy); 48 | void psvDebugScreenGetCoordsXY(int *x, int *y); 49 | void psvDebugScreenSetCoordsXY(int *x, int *y); 50 | PsvDebugScreenFont *psvDebugScreenGetFont(void); 51 | PsvDebugScreenFont *psvDebugScreenSetFont(PsvDebugScreenFont *font); 52 | PsvDebugScreenFont *psvDebugScreenScaleFont2x(PsvDebugScreenFont *source_font); 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | #endif 57 | 58 | #endif /* DEBUG_SCREEN_H */ 59 | -------------------------------------------------------------------------------- /debugscreen/debugScreenFont.builder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
48 | 49 | -------------------------------------------------------------------------------- /debugscreen/debugScreenFont.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PSP Software Development Kit - http://www.pspdev.org 3 | * ----------------------------------------------------------------------- 4 | * Licensed under the BSD license, see LICENSE in PSPSDK root for details. 5 | * 6 | * font.c - Debug Font. 7 | * 8 | * Copyright (c) 2005 Marcus R. Brown 9 | * Copyright (c) 2005 James Forshaw 10 | * Copyright (c) 2005 John Kelley 11 | * 12 | * $Id: font.c 540 2005-07-08 19:35:10Z warren $ 13 | */ 14 | 15 | PsvDebugScreenFont psvDebugScreenFont = { glyphs:(unsigned char*) 16 | "\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x42\xa5\x81\xa5\x99\x42\x3c" 17 | "\x3c\x7e\xdb\xff\xff\xdb\x66\x3c\x6c\xfe\xfe\xfe\x7c\x38\x10\x00" 18 | "\x10\x38\x7c\xfe\x7c\x38\x10\x00\x10\x38\x54\xfe\x54\x10\x38\x00" 19 | "\x10\x38\x7c\xfe\xfe\x10\x38\x00\x00\x00\x00\x30\x30\x00\x00\x00" 20 | "\xff\xff\xff\xe7\xe7\xff\xff\xff\x38\x44\x82\x82\x82\x44\x38\x00" 21 | "\xc7\xbb\x7d\x7d\x7d\xbb\xc7\xff\x0f\x03\x05\x79\x88\x88\x88\x70" 22 | "\x38\x44\x44\x44\x38\x10\x7c\x10\x30\x28\x24\x24\x28\x20\xe0\xc0" 23 | "\x3c\x24\x3c\x24\x24\xe4\xdc\x18\x10\x54\x38\xee\x38\x54\x10\x00" 24 | "\x10\x10\x10\x7c\x10\x10\x10\x10\x10\x10\x10\xff\x00\x00\x00\x00" 25 | "\x00\x00\x00\xff\x10\x10\x10\x10\x10\x10\x10\xf0\x10\x10\x10\x10" 26 | "\x10\x10\x10\x1f\x10\x10\x10\x10\x10\x10\x10\xff\x10\x10\x10\x10" 27 | "\x10\x10\x10\x10\x10\x10\x10\x10\x00\x00\x00\xff\x00\x00\x00\x00" 28 | "\x00\x00\x00\x1f\x10\x10\x10\x10\x00\x00\x00\xf0\x10\x10\x10\x10" 29 | "\x10\x10\x10\x1f\x00\x00\x00\x00\x10\x10\x10\xf0\x00\x00\x00\x00" 30 | "\x81\x42\x24\x18\x18\x24\x42\x81\x01\x02\x04\x08\x10\x20\x40\x80" 31 | "\x80\x40\x20\x10\x08\x04\x02\x01\x00\x10\x10\xff\x10\x10\x00\x00" 32 | "\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20\x20\x20\x00\x00\x20\x00" 33 | "\x50\x50\x50\x00\x00\x00\x00\x00\x50\x50\xf8\x50\xf8\x50\x50\x00" 34 | "\x20\x78\xa0\x70\x28\xf0\x20\x00\xc0\xc8\x10\x20\x40\x98\x18\x00" 35 | "\x40\xa0\x40\xa8\x90\x98\x60\x00\x10\x20\x40\x00\x00\x00\x00\x00" 36 | "\x10\x20\x40\x40\x40\x20\x10\x00\x40\x20\x10\x10\x10\x20\x40\x00" 37 | "\x20\xa8\x70\x20\x70\xa8\x20\x00\x00\x20\x20\xf8\x20\x20\x00\x00" 38 | "\x00\x00\x00\x00\x00\x20\x20\x40\x00\x00\x00\x78\x00\x00\x00\x00" 39 | "\x00\x00\x00\x00\x00\x60\x60\x00\x00\x00\x08\x10\x20\x40\x80\x00" 40 | "\x70\x88\x98\xa8\xc8\x88\x70\x00\x20\x60\xa0\x20\x20\x20\xf8\x00" 41 | "\x70\x88\x08\x10\x60\x80\xf8\x00\x70\x88\x08\x30\x08\x88\x70\x00" 42 | "\x10\x30\x50\x90\xf8\x10\x10\x00\xf8\x80\xe0\x10\x08\x10\xe0\x00" 43 | "\x30\x40\x80\xf0\x88\x88\x70\x00\xf8\x88\x10\x20\x20\x20\x20\x00" 44 | "\x70\x88\x88\x70\x88\x88\x70\x00\x70\x88\x88\x78\x08\x10\x60\x00" 45 | "\x00\x00\x20\x00\x00\x20\x00\x00\x00\x00\x20\x00\x00\x20\x20\x40" 46 | "\x18\x30\x60\xc0\x60\x30\x18\x00\x00\x00\xf8\x00\xf8\x00\x00\x00" 47 | "\xc0\x60\x30\x18\x30\x60\xc0\x00\x70\x88\x08\x10\x20\x00\x20\x00" 48 | "\x70\x88\x08\x68\xa8\xa8\x70\x00\x20\x50\x88\x88\xf8\x88\x88\x00" 49 | "\xf0\x48\x48\x70\x48\x48\xf0\x00\x30\x48\x80\x80\x80\x48\x30\x00" 50 | "\xe0\x50\x48\x48\x48\x50\xe0\x00\xf8\x80\x80\xf0\x80\x80\xf8\x00" 51 | "\xf8\x80\x80\xf0\x80\x80\x80\x00\x70\x88\x80\xb8\x88\x88\x70\x00" 52 | "\x88\x88\x88\xf8\x88\x88\x88\x00\x70\x20\x20\x20\x20\x20\x70\x00" 53 | "\x38\x10\x10\x10\x90\x90\x60\x00\x88\x90\xa0\xc0\xa0\x90\x88\x00" 54 | "\x80\x80\x80\x80\x80\x80\xf8\x00\x88\xd8\xa8\xa8\x88\x88\x88\x00" 55 | "\x88\xc8\xc8\xa8\x98\x98\x88\x00\x70\x88\x88\x88\x88\x88\x70\x00" 56 | "\xf0\x88\x88\xf0\x80\x80\x80\x00\x70\x88\x88\x88\xa8\x90\x68\x00" 57 | "\xf0\x88\x88\xf0\xa0\x90\x88\x00\x70\x88\x80\x70\x08\x88\x70\x00" 58 | "\xf8\x20\x20\x20\x20\x20\x20\x00\x88\x88\x88\x88\x88\x88\x70\x00" 59 | "\x88\x88\x88\x88\x50\x50\x20\x00\x88\x88\x88\xa8\xa8\xd8\x88\x00" 60 | "\x88\x88\x50\x20\x50\x88\x88\x00\x88\x88\x88\x70\x20\x20\x20\x00" 61 | "\xf8\x08\x10\x20\x40\x80\xf8\x00\x70\x40\x40\x40\x40\x40\x70\x00" 62 | "\x00\x00\x80\x40\x20\x10\x08\x00\x70\x10\x10\x10\x10\x10\x70\x00" 63 | "\x20\x50\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00" 64 | "\x40\x20\x10\x00\x00\x00\x00\x00\x00\x00\x70\x08\x78\x88\x78\x00" 65 | "\x80\x80\xb0\xc8\x88\xc8\xb0\x00\x00\x00\x70\x88\x80\x88\x70\x00" 66 | "\x08\x08\x68\x98\x88\x98\x68\x00\x00\x00\x70\x88\xf8\x80\x70\x00" 67 | "\x10\x28\x20\xf8\x20\x20\x20\x00\x00\x00\x68\x98\x98\x68\x08\x70" 68 | "\x80\x80\xf0\x88\x88\x88\x88\x00\x20\x00\x60\x20\x20\x20\x70\x00" 69 | "\x10\x00\x30\x10\x10\x10\x90\x60\x40\x40\x48\x50\x60\x50\x48\x00" 70 | "\x60\x20\x20\x20\x20\x20\x70\x00\x00\x00\xd0\xa8\xa8\xa8\xa8\x00" 71 | "\x00\x00\xb0\xc8\x88\x88\x88\x00\x00\x00\x70\x88\x88\x88\x70\x00" 72 | "\x00\x00\xb0\xc8\xc8\xb0\x80\x80\x00\x00\x68\x98\x98\x68\x08\x08" 73 | "\x00\x00\xb0\xc8\x80\x80\x80\x00\x00\x00\x78\x80\xf0\x08\xf0\x00" 74 | "\x40\x40\xf0\x40\x40\x48\x30\x00\x00\x00\x90\x90\x90\x90\x68\x00" 75 | "\x00\x00\x88\x88\x88\x50\x20\x00\x00\x00\x88\xa8\xa8\xa8\x50\x00" 76 | "\x00\x00\x88\x50\x20\x50\x88\x00\x00\x00\x88\x88\x98\x68\x08\x70" 77 | "\x00\x00\xf8\x10\x20\x40\xf8\x00\x18\x20\x20\x40\x20\x20\x18\x00" 78 | "\x20\x20\x20\x00\x20\x20\x20\x00\xc0\x20\x20\x10\x20\x20\xc0\x00" 79 | "\x40\xa8\x10\x00\x00\x00\x00\x00\x00\x00\x20\x50\xf8\x00\x00\x00" 80 | "\x70\x88\x80\x80\x88\x70\x20\x60\x90\x00\x00\x90\x90\x90\x68\x00" 81 | "\x10\x20\x70\x88\xf8\x80\x70\x00\x20\x50\x70\x08\x78\x88\x78\x00" 82 | "\x48\x00\x70\x08\x78\x88\x78\x00\x20\x10\x70\x08\x78\x88\x78\x00" 83 | "\x20\x00\x70\x08\x78\x88\x78\x00\x00\x70\x80\x80\x80\x70\x10\x60" 84 | "\x20\x50\x70\x88\xf8\x80\x70\x00\x50\x00\x70\x88\xf8\x80\x70\x00" 85 | "\x20\x10\x70\x88\xf8\x80\x70\x00\x50\x00\x00\x60\x20\x20\x70\x00" 86 | "\x20\x50\x00\x60\x20\x20\x70\x00\x40\x20\x00\x60\x20\x20\x70\x00" 87 | "\x50\x00\x20\x50\x88\xf8\x88\x00\x20\x00\x20\x50\x88\xf8\x88\x00" 88 | "\x10\x20\xf8\x80\xf0\x80\xf8\x00\x00\x00\x6c\x12\x7e\x90\x6e\x00" 89 | "\x3e\x50\x90\x9c\xf0\x90\x9e\x00\x60\x90\x00\x60\x90\x90\x60\x00" 90 | "\x90\x00\x00\x60\x90\x90\x60\x00\x40\x20\x00\x60\x90\x90\x60\x00" 91 | "\x40\xa0\x00\xa0\xa0\xa0\x50\x00\x40\x20\x00\xa0\xa0\xa0\x50\x00" 92 | "\x90\x00\x90\x90\xb0\x50\x10\xe0\x50\x00\x70\x88\x88\x88\x70\x00" 93 | "\x50\x00\x88\x88\x88\x88\x70\x00\x20\x20\x78\x80\x80\x78\x20\x20" 94 | "\x18\x24\x20\xf8\x20\xe2\x5c\x00\x88\x50\x20\xf8\x20\xf8\x20\x00" 95 | "\xc0\xa0\xa0\xc8\x9c\x88\x88\x8c\x18\x20\x20\xf8\x20\x20\x20\x40" 96 | "\x10\x20\x70\x08\x78\x88\x78\x00\x10\x20\x00\x60\x20\x20\x70\x00" 97 | "\x20\x40\x00\x60\x90\x90\x60\x00\x20\x40\x00\x90\x90\x90\x68\x00" 98 | "\x50\xa0\x00\xa0\xd0\x90\x90\x00\x28\x50\x00\xc8\xa8\x98\x88\x00" 99 | "\x00\x70\x08\x78\x88\x78\x00\xf8\x00\x60\x90\x90\x90\x60\x00\xf0" 100 | "\x20\x00\x20\x40\x80\x88\x70\x00\x00\x00\x00\xf8\x80\x80\x00\x00" 101 | "\x00\x00\x00\xf8\x08\x08\x00\x00\x84\x88\x90\xa8\x54\x84\x08\x1c" 102 | "\x84\x88\x90\xa8\x58\xa8\x3c\x08\x20\x00\x00\x20\x20\x20\x20\x00" 103 | "\x00\x00\x24\x48\x90\x48\x24\x00\x00\x00\x90\x48\x24\x48\x90\x00" 104 | "\x28\x50\x20\x50\x88\xf8\x88\x00\x28\x50\x70\x08\x78\x88\x78\x00" 105 | "\x28\x50\x00\x70\x20\x20\x70\x00\x28\x50\x00\x20\x20\x20\x70\x00" 106 | "\x28\x50\x00\x70\x88\x88\x70\x00\x50\xa0\x00\x60\x90\x90\x60\x00" 107 | "\x28\x50\x00\x88\x88\x88\x70\x00\x50\xa0\x00\xa0\xa0\xa0\x50\x00" 108 | "\xfc\x48\x48\x48\xe8\x08\x50\x20\x00\x50\x00\x50\x50\x50\x10\x20" 109 | "\xc0\x44\xc8\x54\xec\x54\x9e\x04\x10\xa8\x40\x00\x00\x00\x00\x00" 110 | "\x00\x20\x50\x88\x50\x20\x00\x00\x88\x10\x20\x40\x80\x28\x00\x00" 111 | "\x7c\xa8\xa8\x68\x28\x28\x28\x00\x38\x40\x30\x48\x48\x30\x08\x70" 112 | "\x00\x00\x00\x00\x00\x00\xff\xff\xf0\xf0\xf0\xf0\x0f\x0f\x0f\x0f" 113 | "\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00" 114 | "\x00\x00\x00\x3c\x3c\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00" 115 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x0f\x0f\x0f\x0f\xf0\xf0\xf0\xf0" 116 | "\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\x03\x03\x03\x03\x03\x03\x03\x03" 117 | "\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x11\x22\x44\x88\x11\x22\x44\x88" 118 | "\x88\x44\x22\x11\x88\x44\x22\x11\xfe\x7c\x38\x10\x00\x00\x00\x00" 119 | "\x00\x00\x00\x00\x10\x38\x7c\xfe\x80\xc0\xe0\xf0\xe0\xc0\x80\x00" 120 | "\x01\x03\x07\x0f\x07\x03\x01\x00\xff\x7e\x3c\x18\x18\x3c\x7e\xff" 121 | "\x81\xc3\xe7\xff\xff\xe7\xc3\x81\xf0\xf0\xf0\xf0\x00\x00\x00\x00" 122 | "\x00\x00\x00\x00\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x00\x00\x00\x00" 123 | "\x00\x00\x00\x00\xf0\xf0\xf0\xf0\x33\x33\xcc\xcc\x33\x33\xcc\xcc" 124 | "\x00\x20\x20\x50\x50\x88\xf8\x00\x20\x20\x70\x20\x70\x20\x20\x00" 125 | "\x00\x00\x00\x50\x88\xa8\x50\x00\xff\xff\xff\xff\xff\xff\xff\xff" 126 | "\x00\x00\x00\x00\xff\xff\xff\xff\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0" 127 | "\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xff\xff\xff\xff\x00\x00\x00\x00" 128 | "\x00\x00\x68\x90\x90\x90\x68\x00\x30\x48\x48\x70\x48\x48\x70\xc0" 129 | "\xf8\x88\x80\x80\x80\x80\x80\x00\xf8\x50\x50\x50\x50\x50\x98\x00" 130 | "\xf8\x88\x40\x20\x40\x88\xf8\x00\x00\x00\x78\x90\x90\x90\x60\x00" 131 | "\x00\x50\x50\x50\x50\x68\x80\x80\x00\x50\xa0\x20\x20\x20\x20\x00" 132 | "\xf8\x20\x70\xa8\xa8\x70\x20\xf8\x20\x50\x88\xf8\x88\x50\x20\x00" 133 | "\x70\x88\x88\x88\x50\x50\xd8\x00\x30\x40\x40\x20\x50\x50\x50\x20" 134 | "\x00\x00\x00\x50\xa8\xa8\x50\x00\x08\x70\xa8\xa8\xa8\x70\x80\x00" 135 | "\x38\x40\x80\xf8\x80\x40\x38\x00\x70\x88\x88\x88\x88\x88\x88\x00" 136 | "\x00\xf8\x00\xf8\x00\xf8\x00\x00\x20\x20\xf8\x20\x20\x00\xf8\x00" 137 | "\xc0\x30\x08\x30\xc0\x00\xf8\x00\x18\x60\x80\x60\x18\x00\xf8\x00" 138 | "\x10\x28\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xa0\x40" 139 | "\x00\x20\x00\xf8\x00\x20\x00\x00\x00\x50\xa0\x00\x50\xa0\x00\x00" 140 | "\x00\x18\x24\x24\x18\x00\x00\x00\x00\x30\x78\x78\x30\x00\x00\x00" 141 | "\x00\x00\x00\x00\x30\x00\x00\x00\x3e\x20\x20\x20\xa0\x60\x20\x00" 142 | "\xa0\x50\x50\x50\x00\x00\x00\x00\x40\xa0\x20\x40\xe0\x00\x00\x00" 143 | "\x00\x38\x38\x38\x38\x38\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00", 144 | width :8, height:8, first:0, last:255, size_w:8, size_h:8}; -------------------------------------------------------------------------------- /debugscreen/debugScreen_custom.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_SCREEN_CUSTOM_H 2 | #define DEBUG_SCREEN_CUSTOM_H 3 | 4 | //#define SCREEN_TAB_SIZE (8) 5 | 6 | // backward compatibility for sources based on older Vita SDK versions 7 | //#define DEBUG_SCREEN_CODE_INCLUDE // not recommended for your own projects, but for sake of backward compatibility 8 | #define psvDebugScreenSetFgColor(rgb) psvDebugScreenPrintf("\e[38;2;%lu;%lu;%lum", ((uint32_t)(rgb)>>16)&0xFF, ((uint32_t)(rgb)>>8)&0xFF, (uint32_t)(rgb)&0xFF) 9 | #define psvDebugScreenSetBgColor(rgb) psvDebugScreenPrintf("\e[48;2;%lu;%lu;%lum", ((uint32_t)(rgb)>>16)&0xFF, ((uint32_t)(rgb)>>8)&0xFF, (uint32_t)(rgb)&0xFF) 10 | #define psvDebugScreenClear(rgb) psvDebugScreenSetBgColor(rgb); psvDebugScreenPuts("\e[H\e[2J") 11 | 12 | // custom changes for non-Vita builds 13 | #ifndef __vita__ 14 | #define psvDebugScreenInitReplacement(...) setvbuf(stdout,NULL,_IONBF,0) 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /file.c: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 "main.h" 20 | #include "vitashell_error.h" 21 | 22 | static char *devices[] = { 23 | "gro0:", 24 | "grw0:", 25 | "imc0:", 26 | "os0:", 27 | "pd0:", 28 | "sa0:", 29 | "sd0:", 30 | "tm0:", 31 | "ud0:", 32 | "uma0:", 33 | "ur0:", 34 | "ux0:", 35 | "vd0:", 36 | "vs0:", 37 | "xmc0:", 38 | "host0:", 39 | }; 40 | 41 | #define N_DEVICES (sizeof(devices) / sizeof(char **)) 42 | 43 | const char symlink_header_bytes[SYMLINK_HEADER_SIZE] = {0xF1, 0x1E, 0x00, 0x00}; 44 | 45 | int ReadFile(const char *file, void *buf, int size) { 46 | SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0); 47 | if (fd < 0) 48 | return fd; 49 | 50 | int read = sceIoRead(fd, buf, size); 51 | 52 | sceIoClose(fd); 53 | return read; 54 | } 55 | 56 | int WriteFileSeek(const char *file, void *buf, size_t seek, size_t size) { 57 | SceUID fd = sceIoOpen(file, SCE_O_WRONLY | SCE_O_CREAT, 0777); 58 | if (fd < 0) 59 | return fd; 60 | sceIoLseek(fd, seek, SCE_SEEK_SET); 61 | int written = sceIoWrite(fd, buf, size); 62 | 63 | sceIoClose(fd); 64 | return written; 65 | } 66 | 67 | int WriteFile(const char *file, const void *buf, int size) { 68 | SceUID fd = sceIoOpen(file, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); 69 | if (fd < 0) 70 | return fd; 71 | 72 | int written = sceIoWrite(fd, buf, size); 73 | 74 | sceIoClose(fd); 75 | return written; 76 | } 77 | 78 | int getFileSize(const char *file) { 79 | SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0); 80 | if (fd < 0) 81 | return fd; 82 | 83 | int fileSize = sceIoLseek(fd, 0, SCE_SEEK_END); 84 | 85 | sceIoClose(fd); 86 | return fileSize; 87 | } 88 | 89 | int checkExists(const char *path) { 90 | SceIoStat stat; 91 | return sceIoGetstat(path, &stat); 92 | } 93 | 94 | int checkFileExist(const char *file) { 95 | SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0); 96 | if (fd < 0) 97 | return 0; 98 | 99 | sceIoClose(fd); 100 | return 1; 101 | } 102 | 103 | int checkFolderExist(const char *folder) { 104 | SceUID dfd = sceIoDopen(folder); 105 | if (dfd < 0) 106 | return 0; 107 | 108 | sceIoDclose(dfd); 109 | return 1; 110 | } 111 | 112 | int copyFile(const char *src_path, const char *dst_path, FileProcessParam *param) { 113 | // The source and destination paths are identical 114 | if (strcasecmp(src_path, dst_path) == 0) { 115 | return VITASHELL_ERROR_SRC_AND_DST_IDENTICAL; 116 | } 117 | 118 | // The destination is a subfolder of the source folder 119 | int len = strlen(src_path); 120 | if (strncasecmp(src_path, dst_path, len) == 0 && (dst_path[len] == '/' || dst_path[len - 1] == '/')) { 121 | return VITASHELL_ERROR_DST_IS_SUBFOLDER_OF_SRC; 122 | } 123 | 124 | SceUID fdsrc = sceIoOpen(src_path, SCE_O_RDONLY, 0); 125 | if (fdsrc < 0) 126 | return fdsrc; 127 | 128 | SceUID fddst = sceIoOpen(dst_path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); 129 | if (fddst < 0) { 130 | sceIoClose(fdsrc); 131 | return fddst; 132 | } 133 | 134 | void *buf = memalign(4096, TRANSFER_SIZE); 135 | 136 | while (1) { 137 | int read = sceIoRead(fdsrc, buf, TRANSFER_SIZE); 138 | 139 | if (read < 0) { 140 | free(buf); 141 | 142 | sceIoClose(fddst); 143 | sceIoClose(fdsrc); 144 | 145 | sceIoRemove(dst_path); 146 | 147 | return read; 148 | } 149 | 150 | if (read == 0) 151 | break; 152 | 153 | int written = sceIoWrite(fddst, buf, read); 154 | 155 | if (written < 0) { 156 | free(buf); 157 | 158 | sceIoClose(fddst); 159 | sceIoClose(fdsrc); 160 | 161 | sceIoRemove(dst_path); 162 | 163 | return written; 164 | } 165 | 166 | if (param) { 167 | if (param->value) 168 | (*param->value) += read; 169 | 170 | if (param->SetProgress) 171 | param->SetProgress(param->value ? *param->value : 0, param->max); 172 | 173 | if (param->cancelHandler && param->cancelHandler()) { 174 | free(buf); 175 | 176 | sceIoClose(fddst); 177 | sceIoClose(fdsrc); 178 | 179 | sceIoRemove(dst_path); 180 | 181 | return 0; 182 | } 183 | } 184 | } 185 | 186 | free(buf); 187 | 188 | // Inherit file stat 189 | SceIoStat stat; 190 | memset(&stat, 0, sizeof(SceIoStat)); 191 | sceIoGetstatByFd(fdsrc, &stat); 192 | sceIoChstatByFd(fddst, &stat, 0x3B); 193 | 194 | sceIoClose(fddst); 195 | sceIoClose(fdsrc); 196 | 197 | return 1; 198 | } 199 | 200 | int hasEndSlash(const char *path) { 201 | return path[strlen(path) - 1] == '/'; 202 | } 203 | 204 | int removePath(const char *path, FileProcessParam *param) { 205 | SceUID dfd = sceIoDopen(path); 206 | if (dfd >= 0) { 207 | int res = 0; 208 | 209 | do { 210 | SceIoDirent dir; 211 | memset(&dir, 0, sizeof(SceIoDirent)); 212 | 213 | res = sceIoDread(dfd, &dir); 214 | if (res > 0) { 215 | char *new_path = malloc(strlen(path) + strlen(dir.d_name) + 2); 216 | snprintf(new_path, MAX_PATH_LENGTH, "%s%s%s", path, hasEndSlash(path) ? "" : "/", dir.d_name); 217 | 218 | if (SCE_S_ISDIR(dir.d_stat.st_mode)) { 219 | int ret = removePath(new_path, param); 220 | if (ret <= 0) { 221 | free(new_path); 222 | sceIoDclose(dfd); 223 | return ret; 224 | } 225 | } else { 226 | int ret = sceIoRemove(new_path); 227 | if (ret < 0) { 228 | free(new_path); 229 | sceIoDclose(dfd); 230 | return ret; 231 | } 232 | 233 | if (param) { 234 | if (param->value) 235 | (*param->value)++; 236 | 237 | if (param->SetProgress) 238 | param->SetProgress(param->value ? *param->value : 0, param->max); 239 | 240 | if (param->cancelHandler && param->cancelHandler()) { 241 | free(new_path); 242 | sceIoDclose(dfd); 243 | return 0; 244 | } 245 | } 246 | } 247 | 248 | free(new_path); 249 | } 250 | } while (res > 0); 251 | 252 | sceIoDclose(dfd); 253 | 254 | int ret = sceIoRmdir(path); 255 | if (ret < 0) 256 | return ret; 257 | 258 | if (param) { 259 | if (param->value) 260 | (*param->value)++; 261 | 262 | if (param->SetProgress) 263 | param->SetProgress(param->value ? *param->value : 0, param->max); 264 | 265 | if (param->cancelHandler && param->cancelHandler()) { 266 | return 0; 267 | } 268 | } 269 | } else { 270 | int ret = sceIoRemove(path); 271 | if (ret < 0) 272 | return ret; 273 | 274 | if (param) { 275 | if (param->value) 276 | (*param->value)++; 277 | 278 | if (param->SetProgress) 279 | param->SetProgress(param->value ? *param->value : 0, param->max); 280 | 281 | if (param->cancelHandler && param->cancelHandler()) { 282 | return 0; 283 | } 284 | } 285 | } 286 | 287 | return 1; 288 | } 289 | 290 | -------------------------------------------------------------------------------- /file.h: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 __FILE_H__ 20 | #define __FILE_H__ 21 | 22 | #define SCE_ERROR_ERRNO_EEXIST 0x80010011 23 | #define SCE_ERROR_ERRNO_ENODEV 0x80010013 24 | 25 | #define MAX_PATH_LENGTH 1024 26 | #define MAX_NAME_LENGTH 256 27 | #define MAX_SHORT_NAME_LENGTH 64 28 | #define MAX_MOUNT_POINT_LENGTH 16 29 | 30 | #define DIRECTORY_SIZE (4 * 1024) 31 | #define TRANSFER_SIZE (128 * 1024) 32 | 33 | #define SYMLINK_HEADER_SIZE 4 34 | #define SYMLINK_MAX_SIZE (SYMLINK_HEADER_SIZE + MAX_PATH_LENGTH) 35 | #define SYMLINK_EXT "lnk" 36 | extern const char symlink_header_bytes[SYMLINK_HEADER_SIZE]; 37 | 38 | 39 | enum FileTypes { 40 | FILE_TYPE_UNKNOWN, 41 | FILE_TYPE_ARCHIVE, 42 | FILE_TYPE_BMP, 43 | FILE_TYPE_INI, 44 | FILE_TYPE_JPEG, 45 | FILE_TYPE_MP3, 46 | FILE_TYPE_MP4, 47 | FILE_TYPE_OGG, 48 | FILE_TYPE_PNG, 49 | FILE_TYPE_PSP2DMP, 50 | FILE_TYPE_SFO, 51 | FILE_TYPE_TXT, 52 | FILE_TYPE_VPK, 53 | FILE_TYPE_XML, 54 | }; 55 | 56 | enum FileSortFlags { 57 | SORT_NONE, 58 | SORT_BY_NAME, 59 | SORT_BY_SIZE, 60 | SORT_BY_DATE, 61 | }; 62 | 63 | enum FileMoveFlags { 64 | MOVE_INTEGRATE = 0x1, // Integrate directories 65 | MOVE_REPLACE = 0x2, // Replace files 66 | }; 67 | 68 | typedef struct { 69 | int to_file; // 1: to file, 0: to directory 70 | char *target_path; 71 | int target_path_length; 72 | } Symlink; 73 | 74 | typedef struct { 75 | uint64_t *value; 76 | uint64_t max; 77 | void (* SetProgress)(uint64_t value, uint64_t max); 78 | int (* cancelHandler)(); 79 | } FileProcessParam; 80 | 81 | typedef struct FileListEntry { 82 | struct FileListEntry *next; 83 | struct FileListEntry *previous; 84 | char *name; 85 | int name_length; 86 | int is_folder; 87 | int type; 88 | int is_symlink; 89 | Symlink *symlink; 90 | SceOff size; 91 | SceOff size2; 92 | SceDateTime ctime; 93 | SceDateTime mtime; 94 | SceDateTime atime; 95 | } FileListEntry; 96 | 97 | typedef struct { 98 | FileListEntry *head; 99 | FileListEntry *tail; 100 | int length; 101 | char path[MAX_PATH_LENGTH]; 102 | int files; 103 | int folders; 104 | int is_in_archive; 105 | } FileList; 106 | 107 | int allocateReadFile(const char *file, void **buffer); 108 | int ReadFile(const char *file, void *buf, int size); 109 | int WriteFile(const char *file, const void *buf, int size); 110 | 111 | int checkFileExist(const char *file); 112 | int checkFolderExist(const char *folder); 113 | 114 | 115 | char * getBaseDirectory(const char *path); 116 | char * getFilename(const char *path); 117 | 118 | int getFileSize(const char *file); 119 | int getFileSha1(const char *file, uint8_t *pSha1Out, FileProcessParam *param); 120 | int getPathInfo(const char *path, uint64_t *size, uint32_t *folders, uint32_t *files, int (* handler)(const char *path)); 121 | int removePath(const char *path, FileProcessParam *param); 122 | int copyFile(const char *src_path, const char *dst_path, FileProcessParam *param); 123 | int copyPath(const char *src_path, const char *dst_path, FileProcessParam *param); 124 | int movePath(const char *src_path, const char *dst_path, int flags, FileProcessParam *param); 125 | 126 | int getFileType(const char *file); 127 | 128 | int getNumberOfDevices(); 129 | char **getDevices(); 130 | 131 | FileListEntry *fileListCopyEntry(FileListEntry *src); 132 | FileListEntry *fileListFindEntry(FileList *list, const char *name); 133 | FileListEntry *fileListGetNthEntry(FileList *list, int n); 134 | int fileListGetNumberByName(FileList *list, const char *name); 135 | 136 | void fileListAddEntry(FileList *list, FileListEntry *entry, int sort); 137 | int fileListRemoveEntry(FileList *list, FileListEntry *entry); 138 | int fileListRemoveEntryByName(FileList *list, const char *name); 139 | 140 | void fileListEmpty(FileList *list); 141 | 142 | int fileListGetEntries(FileList *list, const char *path, int sort); 143 | 144 | int resolveSimLink(Symlink* symlink, const char *target); 145 | int createSymLink(const char *source_location, const char *target); 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 __MAIN_H__ 20 | #define __MAIN_H__ 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | #include 46 | 47 | #include 48 | 49 | #include "file.h" 50 | 51 | #define INCLUDE_EXTERN_RESOURCE(name) extern unsigned char _binary_resources_##name##_start; extern unsigned char _binary_resources_##name##_size; \ 52 | 53 | // VitaShell version major.minor 54 | #define VITASHELL_VERSION_MAJOR 0x02 55 | #define VITASHELL_VERSION_MINOR 0x00 56 | 57 | #define VITASHELL_VERSION ((VITASHELL_VERSION_MAJOR << 0x18) | (VITASHELL_VERSION_MINOR << 0x10)) 58 | 59 | #define VITASHELL_LASTDIR "ux0:VitaShell/internal/lastdir.txt" 60 | 61 | // needs / at the end 62 | #define VITASHELL_BOOKMARKS_PATH "ux0:VitaShell/bookmarks/" 63 | #define VITASHELL_RECENT_PATH "ux0:VitaShell/recent/" 64 | #define VITASHELL_RECENT_PATH_DELETE_INTERVAL_DAYS 14 65 | 66 | #define VITASHELL_TITLEID "VITASHELL" 67 | 68 | #define ALIGN(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) 69 | 70 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 71 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 72 | 73 | #define IS_DIGIT(i) (i >= '0' && i <= '9') 74 | 75 | #define NOALPHA 0xFF 76 | 77 | #define COLOR_ALPHA(color, alpha) (color & 0x00FFFFFF) | ((alpha & 0xFF) << 24) 78 | 79 | // Font 80 | #define FONT_SIZE 1.0f 81 | #define FONT_X_SPACE 15.0f 82 | #define FONT_Y_SPACE 23.0f 83 | 84 | #define pgf_draw_text(x, y, color, text) \ 85 | vita2d_pgf_draw_text(font, x, (y)+20, color, FONT_SIZE, text) 86 | 87 | #define pgf_draw_textf(x, y, color, ...) \ 88 | vita2d_pgf_draw_textf(font, x, (y)+20, color, FONT_SIZE, __VA_ARGS__) 89 | 90 | #define pgf_text_width(text) \ 91 | vita2d_pgf_text_width(font, FONT_SIZE, text) 92 | 93 | // Screen 94 | #define SCREEN_WIDTH 960 95 | #define SCREEN_HEIGHT 544 96 | #define SCREEN_HALF_WIDTH (SCREEN_WIDTH/2) 97 | #define SCREEN_HALF_HEIGHT (SCREEN_HEIGHT/2) 98 | 99 | // Main 100 | #define SHELL_MARGIN_X 20.0f 101 | #define SHELL_MARGIN_Y 18.0f 102 | 103 | #define PATH_Y (SHELL_MARGIN_Y + 1.0f * FONT_Y_SPACE) 104 | 105 | #define START_Y (SHELL_MARGIN_Y + 3.0f * FONT_Y_SPACE) 106 | 107 | #define MAX_WIDTH (SCREEN_WIDTH - 2.0f * SHELL_MARGIN_X) 108 | 109 | #define STATUS_BAR_SPACE_X 12.0f 110 | 111 | // Hex 112 | #define HEX_OFFSET_X 147.0f 113 | #define HEX_CHAR_X (SCREEN_WIDTH - SHELL_MARGIN_X - 0x10 * FONT_X_SPACE) 114 | #define HEX_OFFSET_SPACE 34.0f 115 | 116 | // Coredump 117 | #define COREDUMP_INFO_X (SHELL_MARGIN_X + 160.0f) 118 | #define COREDUMP_REGISTER_NAME_SPACE 45.0f 119 | #define COREDUMP_REGISTER_SPACE 165.0f 120 | 121 | // Scroll bar 122 | #define SCROLL_BAR_X 0.0f 123 | #define SCROLL_BAR_WIDTH 8.0f 124 | #define SCROLL_BAR_MIN_HEIGHT 4.0f 125 | 126 | // Context menu 127 | #define CONTEXT_MENU_MIN_WIDTH 180.0f 128 | #define CONTEXT_MENU_MARGIN 20.0f 129 | #define CONTEXT_MENU_VELOCITY 10.0f 130 | 131 | // File browser 132 | #define FILE_X (SHELL_MARGIN_X+26.0f) 133 | #define MARK_WIDTH (SCREEN_WIDTH - 2.0f * SHELL_MARGIN_X) 134 | #define INFORMATION_X 680.0f 135 | #define MAX_NAME_WIDTH 500.0f 136 | 137 | // Uncommon dialog 138 | #define UNCOMMON_DIALOG_MAX_WIDTH 800 139 | #define UNCOMMON_DIALOG_PROGRESS_BAR_BOX_WIDTH 420.0f 140 | #define UNCOMMON_DIALOG_PROGRESS_BAR_HEIGHT 8.0f 141 | #define MSG_DIALOG_MODE_QR_SCAN 10 142 | 143 | // QR Camera 144 | #define CAM_WIDTH 640 145 | #define CAM_HEIGHT 360 146 | 147 | // Max entries 148 | #define MAX_QR_LENGTH 1024 149 | #define MAX_POSITION 16 150 | #define MAX_ENTRIES 17 151 | #define MAX_URL_LENGTH 128 152 | 153 | #define BIG_BUFFER_SIZE 16 * 1024 * 1024 154 | 155 | enum RefreshModes { 156 | REFRESH_MODE_NONE, 157 | REFRESH_MODE_NORMAL, 158 | REFRESH_MODE_SETFOCUS, 159 | }; 160 | 161 | enum DialogSteps { 162 | DIALOG_STEP_NONE, 163 | 164 | DIALOG_STEP_CANCELED, 165 | 166 | DIALOG_STEP_ERROR, 167 | DIALOG_STEP_INFO, 168 | DIALOG_STEP_SYSTEM, 169 | 170 | DIALOG_STEP_REFRESH_LIVEAREA_QUESTION, 171 | DIALOG_STEP_REFRESH_LICENSE_DB_QUESTION, 172 | DIALOG_STEP_REFRESHING, 173 | 174 | DIALOG_STEP_USB_ATTACH_WAIT, 175 | 176 | DIALOG_STEP_FTP_WAIT, 177 | DIALOG_STEP_FTP, 178 | 179 | DIALOG_STEP_USB_WAIT, 180 | DIALOG_STEP_USB, 181 | 182 | DIALOG_STEP_RENAME, 183 | 184 | DIALOG_STEP_NEW_FILE, 185 | DIALOG_STEP_NEW_FOLDER, 186 | 187 | DIALOG_STEP_COPYING, 188 | DIALOG_STEP_COPIED, 189 | DIALOG_STEP_MOVED, 190 | DIALOG_STEP_PASTE, 191 | 192 | DIALOG_STEP_DELETE_QUESTION, 193 | DIALOG_STEP_DELETE_CONFIRMED, 194 | DIALOG_STEP_DELETING, 195 | DIALOG_STEP_DELETED, 196 | 197 | DIALOG_STEP_COMPRESS_NAME, 198 | DIALOG_STEP_COMPRESS_LEVEL, 199 | DIALOG_STEP_COMPRESSING, 200 | DIALOG_STEP_COMPRESSED, 201 | 202 | DIALOG_STEP_EXPORT_QUESTION, 203 | DIALOG_STEP_EXPORT_CONFIRMED, 204 | DIALOG_STEP_EXPORTING, 205 | 206 | DIALOG_STEP_INSTALL_QUESTION, 207 | DIALOG_STEP_INSTALL_CONFIRMED, 208 | DIALOG_STEP_INSTALL_CONFIRMED_QR, 209 | DIALOG_STEP_INSTALL_WARNING, 210 | DIALOG_STEP_INSTALL_WARNING_AGREED, 211 | DIALOG_STEP_INSTALLING, 212 | DIALOG_STEP_INSTALLED, 213 | 214 | DIALOG_STEP_UPDATE_QUESTION, 215 | DIALOG_STEP_DOWNLOADING, 216 | DIALOG_STEP_DOWNLOADED, 217 | DIALOG_STEP_EXTRACTING, 218 | DIALOG_STEP_EXTRACTED, 219 | 220 | DIALOG_STEP_HASH_QUESTION, 221 | DIALOG_STEP_HASH_CONFIRMED, 222 | DIALOG_STEP_HASHING, 223 | 224 | DIALOG_STEP_SETTINGS_AGREEMENT, 225 | DIALOG_STEP_SETTINGS_STRING, 226 | 227 | DIALOG_STEP_QR, 228 | DIALOG_STEP_QR_DONE, 229 | DIALOG_STEP_QR_WAITING, 230 | DIALOG_STEP_QR_CONFIRM, 231 | DIALOG_STEP_QR_DOWNLOADING, 232 | DIALOG_STEP_QR_DOWNLOADED, 233 | DIALOG_STEP_QR_DOWNLOADED_VPK, 234 | DIALOG_STEP_QR_OPEN_WEBSITE, 235 | DIALOG_STEP_QR_SHOW_CONTENTS, 236 | 237 | DIALOG_STEP_ENTER_PASSWORD, 238 | 239 | DIALOG_STEP_ADHOC_SEND_NETCHECK, 240 | DIALOG_STEP_ADHOC_SEND_WAITING, 241 | DIALOG_STEP_ADHOC_SEND_CLIENT_DECLINED, 242 | DIALOG_STEP_ADHOC_SENDING, 243 | DIALOG_STEP_ADHOC_SENDED, 244 | DIALOG_STEP_ADHOC_RECEIVE_NETCHECK, 245 | DIALOG_STEP_ADHOC_RECEIVE_SEARCHING, 246 | DIALOG_STEP_ADHOC_RECEIVE_QUESTION, 247 | DIALOG_STEP_ADHOC_RECEIVING, 248 | DIALOG_STEP_ADHOC_RECEIVED, 249 | }; 250 | 251 | extern vita2d_pgf *font; 252 | extern char font_size_cache[256]; 253 | 254 | extern char vita_ip[16]; 255 | extern unsigned short int vita_port; 256 | 257 | 258 | extern int SCE_CTRL_ENTER, SCE_CTRL_CANCEL; 259 | 260 | extern int use_custom_config; 261 | 262 | int getDialogStep(); 263 | void setDialogStep(int step); 264 | int dialogSteps(); 265 | 266 | void initFtp(); 267 | void initUsb(); 268 | 269 | void drawScrollBar(int pos, int n); 270 | void drawShellInfo(const char *path); 271 | 272 | void ftpvita_PROM(ftpvita_client_info_t *client); 273 | 274 | #endif 275 | -------------------------------------------------------------------------------- /modules/common/self.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // some info taken from the wiki, see http://vitadevwiki.com/index.php?title=SELF_File_Format 7 | 8 | #pragma pack(push, 1) 9 | typedef struct { 10 | uint32_t magic; /* 53434500 = SCE\0 */ 11 | uint32_t version; /* header version 3*/ 12 | uint16_t sdk_type; /* */ 13 | uint16_t header_type; /* 1 self, 2 unknown, 3 pkg */ 14 | uint32_t metadata_offset; /* metadata offset */ 15 | uint64_t header_len; /* self header length */ 16 | uint64_t elf_filesize; /* ELF file length */ 17 | uint64_t self_filesize; /* SELF file length */ 18 | uint64_t unknown; /* UNKNOWN */ 19 | uint64_t self_offset; /* SELF offset */ 20 | uint64_t appinfo_offset; /* app info offset */ 21 | uint64_t elf_offset; /* ELF #1 offset */ 22 | uint64_t phdr_offset; /* program header offset */ 23 | uint64_t shdr_offset; /* section header offset */ 24 | uint64_t section_info_offset; /* section info offset */ 25 | uint64_t sceversion_offset; /* version offset */ 26 | uint64_t controlinfo_offset; /* control info offset */ 27 | uint64_t controlinfo_size; /* control info size */ 28 | uint64_t padding; 29 | } SCE_header; 30 | 31 | typedef struct { 32 | uint64_t authid; /* auth id */ 33 | uint32_t vendor_id; /* vendor id */ 34 | uint32_t self_type; /* app type */ 35 | uint64_t version; /* app version */ 36 | uint64_t padding; /* UNKNOWN */ 37 | } SCE_appinfo; 38 | 39 | typedef struct { 40 | uint32_t unk1; 41 | uint32_t unk2; 42 | uint32_t unk3; 43 | uint32_t unk4; 44 | } SCE_version; 45 | 46 | typedef struct { 47 | uint32_t type; // 4==PSVita ELF digest info; 5==PSVita NPDRM info; 6==PSVita boot param info; 7==PSVita shared secret info 48 | uint32_t size; 49 | uint64_t next; // 1 if another Control Info structure follows else 0 50 | union { 51 | // type 4, 0x50 bytes 52 | struct { // 0x40 bytes of data 53 | uint8_t constant[0x14]; // same for every PSVita/PS3 SELF, hardcoded in make_fself.exe: 627CB1808AB938E32C8C091708726A579E2586E4 54 | uint8_t elf_digest[0x20]; // on PSVita: SHA-256 of source ELF file, on PS3: SHA-1 55 | uint8_t padding[8]; 56 | uint32_t min_required_fw; // ex: 0x363 for 3.63 57 | } PSVita_elf_digest_info; 58 | // type 5, 0x110 bytes 59 | struct { // 0x80 bytes of data 60 | uint32_t magic; // 7F 44 52 4D (".DRM") 61 | uint32_t finalized_flag; // ex: 80 00 00 01 62 | uint32_t drm_type; // license_type ex: 2 local, 0XD free with license 63 | uint32_t padding; 64 | uint8_t content_id[0x30]; 65 | uint8_t digest[0x10]; // ?sha-1 hash of debug self/sprx created using make_fself_npdrm? 66 | uint8_t padding_78[0x78]; 67 | uint8_t hash_signature[0x38]; // unknown hash/signature 68 | } PSVita_npdrm_info; 69 | // type 6, 0x110 bytes 70 | struct { // 0x100 bytes of data 71 | uint32_t is_used; // 0=false, 1=true 72 | uint8_t boot_param[0x9C]; // ex: starting with 02 00 00 00 73 | } PSVita_boot_param_info; 74 | // type 7, 0x50 bytes 75 | struct { // 0x40 bytes of data 76 | uint8_t shared_secret_0[0x10]; // ex: 0x7E7FD126A7B9614940607EE1BF9DDF5E or full of zeroes 77 | uint8_t shared_secret_1[0x10]; // ex: full of zeroes 78 | uint8_t shared_secret_2[0x10]; // ex: full of zeroes 79 | uint8_t shared_secret_3[0x10]; // ex: full of zeroes 80 | } PSVita_shared_secret_info; 81 | }; 82 | } __attribute__((packed)) PSVita_CONTROL_INFO; 83 | 84 | typedef struct { 85 | uint64_t offset; 86 | uint64_t length; 87 | uint64_t compression; // 1 = uncompressed, 2 = compressed 88 | uint64_t encryption; // 1 = encrypted, 2 = plain 89 | } segment_info; 90 | 91 | typedef struct { 92 | uint32_t type; 93 | uint32_t size; 94 | uint32_t unk; 95 | uint32_t pad; 96 | } SCE_controlinfo; 97 | 98 | typedef struct { 99 | SCE_controlinfo common; 100 | char unk[0x100]; 101 | } SCE_controlinfo_5; 102 | 103 | typedef struct { 104 | SCE_controlinfo common; 105 | uint32_t is_used; /* always set to 1 */ 106 | uint32_t attr; /* controls several app settings */ 107 | uint32_t phycont_memsize; /* physically contiguous memory budget */ 108 | uint32_t total_memsize; /* total memory budget (user + phycont) */ 109 | uint32_t filehandles_limit; /* max number of opened filehandles simultaneously */ 110 | uint32_t dir_max_level; /* max depth for directories support */ 111 | uint32_t encrypt_mount_max; /* UNKNOWN */ 112 | uint32_t redirect_mount_max; /* UNKNOWN */ 113 | char unk[0xE0]; 114 | } SCE_controlinfo_6; 115 | 116 | typedef struct { 117 | SCE_controlinfo common; 118 | char unk[0x40]; 119 | } SCE_controlinfo_7; 120 | 121 | typedef struct { 122 | uint32_t magic; 123 | uint32_t version; 124 | uint8_t _platform; 125 | uint8_t key_revision; 126 | uint16_t _sce_type; 127 | uint32_t metadata_offset; 128 | uint64_t header_length; 129 | uint64_t data_length; 130 | } SceHeader; 131 | 132 | typedef struct { 133 | uint64_t file_length; 134 | uint64_t field_8; 135 | uint64_t self_offset; 136 | uint64_t appinfo_offset; 137 | uint64_t elf_offset; 138 | uint64_t phdr_offset; 139 | uint64_t shdr_offset; 140 | uint64_t segment_info_offset; 141 | uint64_t sceversion_offset; 142 | uint64_t controlinfo_offset; 143 | uint64_t controlinfo_length; 144 | } SelfHeader; 145 | 146 | typedef struct { 147 | uint64_t authid; 148 | uint32_t vendor_id; 149 | uint32_t _self_type; 150 | uint64_t sys_version; 151 | uint64_t field_18; 152 | } AppInfoHeader; 153 | 154 | typedef struct { 155 | unsigned char e_ident_1[8]; 156 | unsigned char e_ident_2[8]; 157 | uint16_t e_type; 158 | uint16_t e_machine; 159 | uint32_t e_version; 160 | uint32_t e_entry; 161 | uint32_t e_phoff; 162 | uint32_t e_shoff; 163 | uint32_t e_flags; 164 | uint16_t e_ehsize; 165 | uint16_t e_phentsize; 166 | uint16_t e_phnum; 167 | uint16_t e_shentsize; 168 | uint16_t e_shnum; 169 | uint16_t e_shstrndx; 170 | } ElfHeader; 171 | 172 | typedef struct { 173 | uint32_t p_type; 174 | uint32_t p_offset; 175 | uint32_t p_vaddr; 176 | uint32_t p_paddr; 177 | uint32_t p_filesz; 178 | uint32_t p_memsz; 179 | uint32_t p_flags; 180 | uint32_t p_align; 181 | } ElfPhdr; 182 | 183 | typedef struct { 184 | uint64_t offset; 185 | uint64_t size; 186 | uint32_t _compressed; 187 | uint32_t field_14; 188 | uint32_t _plaintext; 189 | uint32_t field_1C; 190 | } SegmentInfo; 191 | 192 | typedef struct { 193 | unsigned char key[16]; 194 | uint64_t pad0; 195 | uint64_t pad1; 196 | unsigned char iv[16]; 197 | uint64_t pad2; 198 | uint64_t pad3; 199 | } MetadataInfo; 200 | 201 | typedef struct { 202 | uint64_t signature_input_length; 203 | uint32_t signature_type; 204 | uint32_t section_count; 205 | uint32_t key_count; 206 | uint32_t opt_header_size; 207 | uint32_t field_18; 208 | uint32_t field_1C; 209 | } MetadataHeader; 210 | 211 | typedef struct { 212 | uint64_t offset; 213 | uint64_t size; 214 | uint32_t type; 215 | int32_t seg_idx; 216 | uint32_t hashtype; 217 | int32_t hash_idx; 218 | uint32_t _encryption; 219 | int32_t key_idx; 220 | int32_t iv_idx; 221 | uint32_t _compression; 222 | } MetadataSection; 223 | 224 | typedef struct { 225 | uint32_t field_0; 226 | uint32_t field_4; 227 | uint64_t sys_version; 228 | uint32_t field_10; 229 | uint32_t field_14; 230 | uint32_t field_18; 231 | uint32_t field_1C; 232 | } SrvkHeader; 233 | 234 | typedef struct { 235 | uint32_t field_0; 236 | uint32_t _pkg_type; 237 | uint32_t flags; 238 | uint32_t field_C; 239 | uint64_t update_version; 240 | uint64_t final_size; 241 | uint64_t decrypted_size; 242 | uint32_t field_28; 243 | uint32_t field_30; 244 | uint32_t field_34; 245 | uint32_t field_38; 246 | uint64_t field_3C; 247 | uint64_t field_40; 248 | uint64_t field_48; 249 | uint64_t offset; 250 | uint64_t size; 251 | uint64_t part_idx; 252 | uint64_t total_parts; 253 | uint64_t field_70; 254 | uint64_t field_78; 255 | } SpkgHeader; 256 | 257 | typedef struct { 258 | uint32_t subtype; 259 | uint32_t is_present; 260 | uint64_t size; 261 | } SceVersionInfo; 262 | 263 | typedef struct { 264 | uint32_t control_type; 265 | uint32_t size; 266 | uint64_t more; 267 | } SceControlInfo; 268 | 269 | typedef struct { 270 | unsigned char sce_hash[20]; 271 | unsigned char file_hash[32]; 272 | uint32_t filler1; 273 | uint32_t filler2; 274 | uint32_t sdk_version; 275 | } SceControlInfoDigest256; 276 | 277 | typedef struct { 278 | uint32_t magic; 279 | uint16_t sig_offset; 280 | uint16_t size; 281 | uint32_t npdrm_type; 282 | uint32_t field_C; 283 | unsigned char content_id[0x30]; 284 | unsigned char digest1[0x10]; 285 | unsigned char hash1[0x20]; 286 | unsigned char hash2[0x20]; 287 | unsigned char sig1r[0x1C]; 288 | unsigned char sig1s[0x1C]; 289 | unsigned char sig2r[0x1C]; 290 | unsigned char sig2s[0x1C]; 291 | } SceControlInfoDrm; 292 | 293 | typedef struct { 294 | uint16_t majver; 295 | uint16_t minver; 296 | uint16_t style; 297 | uint16_t riftype; 298 | uint64_t cid; 299 | unsigned char content_id[0x30]; 300 | unsigned char actidx[0x10]; 301 | unsigned char klicense[0x10]; 302 | unsigned char dates[0x10]; 303 | unsigned char filler[0x8]; 304 | unsigned char sig1r[0x14]; 305 | unsigned char sig1s[0xC]; 306 | } SceRIF; 307 | 308 | typedef struct { 309 | uint64_t offset; 310 | int32_t idx; 311 | uint64_t size; 312 | bool compressed; 313 | char *key; 314 | char *iv; 315 | } SceSegment; 316 | 317 | typedef struct { 318 | } SCE_KEYS; 319 | 320 | typedef struct { 321 | SCE_KEYS keys[1]; 322 | } KeyStore; 323 | 324 | typedef struct { 325 | uint64_t minver; 326 | uint64_t maxver; 327 | int keyrev; 328 | char *key; 329 | char *iv; 330 | } KeyEntry; 331 | 332 | #pragma pack(pop) 333 | 334 | enum { 335 | HEADER_LEN = 0x1000, 336 | SCE_MAGIC = 0x454353 337 | }; 338 | -------------------------------------------------------------------------------- /modules/kernel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(kernel) 12 | include("${VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") 16 | 17 | add_executable(kernel 18 | main.c 19 | ) 20 | 21 | target_link_libraries(kernel 22 | SceIofilemgrForDriver_stub 23 | SceSysclibForDriver_stub 24 | SceSysmemForDriver_stub 25 | SceModulemgrForDriver_stub 26 | SceThreadmgrForDriver_stub 27 | SceProcessmgrForDriver_stub 28 | SceNpDrmForDriver_stub 29 | taihenForKernel_stub 30 | taihenModuleUtils_stub 31 | ) 32 | 33 | vita_create_self(kernel.skprx kernel CONFIG exports.yml UNSAFE) 34 | 35 | vita_create_stubs(vitashell_kernel_stubs kernel exports.yml KERNEL) 36 | -------------------------------------------------------------------------------- /modules/kernel/exports.yml: -------------------------------------------------------------------------------- 1 | VitaShellKernel2: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 0 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | modules: 10 | VitaShellKernel2Library: 11 | syscall: true 12 | functions: 13 | - shellKernelIsUx0Redirected 14 | - shellKernelRedirectUx0 15 | - shellKernelMountById 16 | - shellKernelGetRifVitaKey 17 | -------------------------------------------------------------------------------- /modules/kernel/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 | 25 | #include 26 | #include 27 | 28 | //#include 29 | #include "taihen.h" 30 | 31 | #include "vitashell_kernel.h" 32 | 33 | #define MOUNT_POINT_ID 0x800 34 | 35 | int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func); 36 | int module_get_offset(SceUID pid, SceUID modid, int segidx, size_t offset, uintptr_t *addr); 37 | 38 | int ksceNpDrmGetRifVitaKey(void *license_buf, uint8_t *klicensee, uint32_t *flags, 39 | uint32_t *sku_flag, uint64_t *start_time, uint64_t *expiration_time); 40 | 41 | typedef struct { 42 | const char *dev; 43 | const char *dev2; 44 | const char *blkdev; 45 | const char *blkdev2; 46 | int id; 47 | } SceIoDevice; 48 | 49 | typedef struct { 50 | int id; 51 | const char *dev_unix; 52 | int unk; 53 | int dev_major; 54 | int dev_minor; 55 | const char *dev_filesystem; 56 | int unk2; 57 | SceIoDevice *dev; 58 | int unk3; 59 | SceIoDevice *dev2; 60 | int unk4; 61 | int unk5; 62 | int unk6; 63 | int unk7; 64 | } SceIoMountPoint; 65 | 66 | static char ux0_blkdev[64], ux0_blkdev2[64]; 67 | 68 | static SceIoDevice ux0_dev = { "ux0:", "exfatux0", ux0_blkdev, ux0_blkdev2, MOUNT_POINT_ID }; 69 | 70 | static SceIoMountPoint *(* sceIoFindMountPoint)(int id) = NULL; 71 | 72 | static SceUID hookid = -1; 73 | 74 | static tai_hook_ref_t ksceSysrootIsSafeModeRef; 75 | 76 | static tai_hook_ref_t ksceSblAimgrIsDolceRef; 77 | 78 | static int ksceSysrootIsSafeModePatched() { 79 | return 1; 80 | } 81 | 82 | static int ksceSblAimgrIsDolcePatched() { 83 | return 1; 84 | } 85 | 86 | int shellKernelIsUx0Redirected(const char *blkdev, const char *blkdev2) { 87 | char k_blkdev[64], k_blkdev2[64]; 88 | 89 | uint32_t state; 90 | ENTER_SYSCALL(state); 91 | 92 | SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID); 93 | if (!mount) { 94 | EXIT_SYSCALL(state); 95 | return 0; 96 | } 97 | 98 | ksceKernelStrncpyUserToKernel(k_blkdev, (uintptr_t)blkdev, sizeof(k_blkdev)-1); 99 | ksceKernelStrncpyUserToKernel(k_blkdev2, (uintptr_t)blkdev2, sizeof(k_blkdev2)-1); 100 | 101 | if (mount && mount->dev && mount->dev->blkdev && strcmp(mount->dev->blkdev, k_blkdev) == 0) { 102 | EXIT_SYSCALL(state); 103 | return 1; 104 | } 105 | 106 | EXIT_SYSCALL(state); 107 | return 0; 108 | } 109 | 110 | int shellKernelRedirectUx0(const char *blkdev, const char *blkdev2) { 111 | uint32_t state; 112 | ENTER_SYSCALL(state); 113 | 114 | SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID); 115 | if (!mount) { 116 | EXIT_SYSCALL(state); 117 | return -1; 118 | } 119 | 120 | ksceKernelStrncpyUserToKernel(ux0_blkdev, (uintptr_t)blkdev, sizeof(ux0_blkdev)-1); 121 | ksceKernelStrncpyUserToKernel(ux0_blkdev2, (uintptr_t)blkdev2, sizeof(ux0_blkdev2)-1); 122 | 123 | mount->dev = &ux0_dev; 124 | mount->dev2 = &ux0_dev; 125 | 126 | EXIT_SYSCALL(state); 127 | return 0; 128 | } 129 | 130 | int _shellKernelMountById(ShellMountIdArgs *args) { 131 | int res; 132 | 133 | void *(* sceAppMgrFindProcessInfoByPid)(void *data, SceUID pid); 134 | int (* sceAppMgrMountById)(SceUID pid, void *info, int id, const char *titleid, const char *path, 135 | const char *desired_mount_point, const void *klicensee, char *mount_point); 136 | int (* _ksceKernelGetModuleInfo)(SceUID pid, SceUID modid, SceKernelModuleInfo *info); 137 | 138 | // Get tai module info 139 | tai_module_info_t tai_info; 140 | tai_info.size = sizeof(tai_module_info_t); 141 | if (taiGetModuleInfoForKernel(KERNEL_PID, "SceAppMgr", &tai_info) < 0) 142 | return SCE_KERNEL_START_SUCCESS; 143 | 144 | switch (tai_info.module_nid) { 145 | case 0x94CEFE4B: // 3.55 retail 146 | case 0xDFBC288C: // 3.57 retail 147 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid); 148 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E15, (uintptr_t *)&sceAppMgrMountById); 149 | break; 150 | 151 | case 0xDBB29DB7: // 3.60 retail 152 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid); 153 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19B51, (uintptr_t *)&sceAppMgrMountById); 154 | break; 155 | 156 | case 0x1C9879D6: // 3.65 retail 157 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid); 158 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E61, (uintptr_t *)&sceAppMgrMountById); 159 | break; 160 | 161 | case 0x54E2E984: // 3.67 retail 162 | case 0xC3C538DE: // 3.68 retail 163 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid); 164 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E6D, (uintptr_t *)&sceAppMgrMountById); 165 | break; 166 | 167 | case 0x321E4852: // 3.69 retail 168 | case 0x700DA0CD: // 3.70 retail 169 | case 0xF7846B4E: // 3.71 retail 170 | case 0xA8E80BA8: // 3.72 retail 171 | case 0xB299D195: // 3.73 retail 172 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE9, (uintptr_t *)&sceAppMgrFindProcessInfoByPid); 173 | module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E95, (uintptr_t *)&sceAppMgrMountById); 174 | break; 175 | } 176 | 177 | res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 178 | 0xC445FA63, 0xD269F915, (uintptr_t *)&_ksceKernelGetModuleInfo); 179 | if (res < 0) 180 | res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 181 | 0x92C9FFC2, 0xDAA90093, (uintptr_t *)&_ksceKernelGetModuleInfo); 182 | if (res < 0) 183 | return res; 184 | 185 | // Module info 186 | SceKernelModuleInfo mod_info; 187 | mod_info.size = sizeof(SceKernelModuleInfo); 188 | res = _ksceKernelGetModuleInfo(KERNEL_PID, tai_info.modid, &mod_info); 189 | if (res < 0) 190 | return res; 191 | 192 | uint32_t appmgr_data_addr = (uint32_t)mod_info.segments[1].vaddr; 193 | 194 | SceUID process_id = ksceKernelGetProcessId(); 195 | 196 | void *info = sceAppMgrFindProcessInfoByPid((void *)(appmgr_data_addr + 0x500), process_id); 197 | if (!info) 198 | return -1; 199 | 200 | char process_titleid[12]; 201 | char path[256]; 202 | char desired_mount_point[16]; 203 | char mount_point[16]; 204 | char klicensee[16]; 205 | 206 | memset(mount_point, 0, sizeof(mount_point)); 207 | 208 | if (args->process_titleid) 209 | ksceKernelStrncpyUserToKernel(process_titleid, (uintptr_t)args->process_titleid, 11); 210 | if (args->path) 211 | ksceKernelStrncpyUserToKernel(path, (uintptr_t)args->path, 255); 212 | if (args->desired_mount_point) 213 | ksceKernelStrncpyUserToKernel(desired_mount_point, (uintptr_t)args->desired_mount_point, 15); 214 | if (args->klicensee) 215 | ksceKernelMemcpyUserToKernel(klicensee, (uintptr_t)args->klicensee, 0x10); 216 | 217 | res = sceAppMgrMountById(process_id, 218 | info + 0x580, 219 | args->id, 220 | args->process_titleid ? process_titleid : NULL, 221 | args->path ? path : NULL, 222 | args->desired_mount_point ? desired_mount_point : NULL, 223 | args->klicensee ? klicensee : NULL, 224 | mount_point); 225 | 226 | if (args->mount_point) 227 | ksceKernelStrncpyKernelToUser((uintptr_t)args->mount_point, mount_point, 15); 228 | 229 | return res; 230 | } 231 | 232 | int shellKernelMountById(ShellMountIdArgs *args) { 233 | uint32_t state; 234 | ENTER_SYSCALL(state); 235 | 236 | ShellMountIdArgs k_args; 237 | ksceKernelMemcpyUserToKernel(&k_args, (uintptr_t)args, sizeof(ShellMountIdArgs)); 238 | 239 | int res = ksceKernelRunWithStack(0x2000, (void *)_shellKernelMountById, &k_args); 240 | 241 | EXIT_SYSCALL(state); 242 | return res; 243 | } 244 | 245 | int shellKernelGetRifVitaKey(const void *license_buf, void *klicensee) { 246 | char k_license_buf[0x200]; 247 | char k_klicensee[0x10]; 248 | 249 | memset(k_klicensee, 0, sizeof(k_klicensee)); 250 | 251 | if (license_buf) 252 | ksceKernelMemcpyUserToKernel(k_license_buf, (uintptr_t)license_buf, sizeof(k_license_buf)); 253 | 254 | int res = ksceNpDrmGetRifVitaKey(k_license_buf, (uint8_t *)k_klicensee, NULL, NULL, NULL, NULL); 255 | 256 | if (klicensee) 257 | ksceKernelMemcpyKernelToUser((uintptr_t)klicensee, k_klicensee, sizeof(k_klicensee)); 258 | 259 | return res; 260 | } 261 | 262 | void _start() __attribute__ ((weak, alias("module_start"))); 263 | int module_start(SceSize args, void *argp) { 264 | SceUID tmp1, tmp2; 265 | // Get tai module info 266 | tai_module_info_t info; 267 | info.size = sizeof(tai_module_info_t); 268 | if (taiGetModuleInfoForKernel(KERNEL_PID, "SceIofilemgr", &info) < 0) 269 | return SCE_KERNEL_START_SUCCESS; 270 | 271 | // Get important function 272 | switch (info.module_nid) { 273 | case 0x7A1DBDE6: // 3.55 retail 274 | case 0xEF58597E: // 3.57 retail 275 | case 0x9642948C: // 3.60 retail 276 | module_get_offset(KERNEL_PID, info.modid, 0, 0x138C1, (uintptr_t *)&sceIoFindMountPoint); 277 | break; 278 | 279 | case 0xA96ACE9D: // 3.65 retail 280 | case 0x3347A95F: // 3.67 retail 281 | case 0x90DA33DE: // 3.68 retail 282 | module_get_offset(KERNEL_PID, info.modid, 0, 0x182F5, (uintptr_t *)&sceIoFindMountPoint); 283 | break; 284 | 285 | case 0xF16E72C7: // 3.69 retail 286 | case 0x81A49C2B: // 3.70 retail 287 | case 0xF2D59083: // 3.71 retail 288 | case 0x9C16D40A: // 3.72 retail 289 | case 0xF7794A6C: // 3.73 retail 290 | module_get_offset(KERNEL_PID, info.modid, 0, 0x18735, (uintptr_t *)&sceIoFindMountPoint); 291 | break; 292 | 293 | default: 294 | return SCE_KERNEL_START_SUCCESS; 295 | } 296 | 297 | // Fake safe mode so that SceUsbMass can be loaded 298 | tmp1 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceSysmem", 299 | 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched); 300 | if (tmp1 < 0) 301 | return SCE_KERNEL_START_SUCCESS; 302 | // this patch is only needed on handheld units 303 | tmp2 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSblAimgrIsDolceRef, "SceSysmem", 304 | 0xFD00C69A, 0x71608CA3, ksceSblAimgrIsDolcePatched); 305 | if (tmp2 < 0) 306 | return SCE_KERNEL_START_SUCCESS; 307 | 308 | // Load SceUsbMass 309 | SceUID modid = ksceKernelLoadStartModule("ux0:VitaShell/module/umass.skprx", 0, NULL, 0, NULL, NULL); 310 | 311 | // Release patch 312 | taiHookReleaseForKernel(tmp1, ksceSysrootIsSafeModeRef); 313 | taiHookReleaseForKernel(tmp2, ksceSblAimgrIsDolceRef); 314 | 315 | // Check result 316 | if (modid < 0) 317 | return SCE_KERNEL_START_SUCCESS; 318 | 319 | // Fake safe mode in SceUsbServ 320 | hookid = taiHookFunctionImportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceUsbServ", 321 | 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched); 322 | 323 | return SCE_KERNEL_START_SUCCESS; 324 | } 325 | 326 | int module_stop(SceSize args, void *argp) { 327 | if (hookid >= 0) 328 | taiHookReleaseForKernel(hookid, ksceSysrootIsSafeModeRef); 329 | 330 | return SCE_KERNEL_STOP_SUCCESS; 331 | } 332 | -------------------------------------------------------------------------------- /modules/kernel/vitashell_kernel.h: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 __VITASHELL_KERNEL_H__ 20 | #define __VITASHELL_KERNEL_H__ 21 | 22 | typedef struct { 23 | int id; 24 | const char *process_titleid; 25 | const char *path; 26 | const char *desired_mount_point; 27 | const void *klicensee; 28 | char *mount_point; 29 | } ShellMountIdArgs; 30 | 31 | int shellKernelIsUx0Redirected(const char *blkdev, const char *blkdev2); 32 | int shellKernelRedirectUx0(const char *blkdev, const char *blkdev2); 33 | int shellKernelMountById(ShellMountIdArgs *args); 34 | int shellKernelGetRifVitaKey(const void *license_buf, void *klicensee); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /modules/kplugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(kentente) 12 | include("$ENV{VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -std=gnu99") 15 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib") 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions") 17 | 18 | link_directories( 19 | ${CMAKE_CURRENT_BINARY_DIR} 20 | ) 21 | 22 | add_executable(${PROJECT_NAME} 23 | kentente.c 24 | ) 25 | 26 | target_link_libraries(${PROJECT_NAME} 27 | taihenModuleUtils_stub 28 | SceNpDrmForDriver_stub 29 | SceIofilemgrForDriver_stub 30 | SceThreadmgrForDriver_stub 31 | SceSysmemForDriver_stub 32 | k 33 | gcc 34 | ) 35 | 36 | vita_create_self(${PROJECT_NAME}.skprx ${PROJECT_NAME} 37 | UNSAFE 38 | CONFIG ${CMAKE_SOURCE_DIR}/modules/kplugin/exports.yml 39 | ) 40 | 41 | vita_create_stubs(${PROJECT_NAME}-stubs ${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/modules/kplugin/exports.yml 42 | KERNEL 43 | ) 44 | 45 | install(DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-stubs/ 46 | DESTINATION lib 47 | FILES_MATCHING PATTERN "*.a" 48 | ) 49 | 50 | install(FILES kentente.h 51 | DESTINATION include 52 | ) 53 | -------------------------------------------------------------------------------- /modules/kplugin/context_130_base_kernel.h: -------------------------------------------------------------------------------- 1 | #define CONTEXT_130_BASE_KERNEL_SIZE 304 2 | 3 | 4 | unsigned char CONTEXT_130_BASE_KERNEL[] = { 5 | 0,0,0,0,0,0,0,0,1,0,0,0,0,0,8,40, 6 | 0,0,0,0,0,0,0,0,128,0,0,0,192,0,240,0, 7 | 0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0, 8 | 0,0,0,0,0,0,0,0,128,9,128,3,0,48,12,0, 9 | 0,0,128,9,128,0,0,0,0,0,0,0,0,0,0,0, 10 | 0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0, 11 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 12 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 13 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 14 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 15 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 16 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 17 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 18 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 19 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 20 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 21 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 22 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 23 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 24 | }; 25 | -------------------------------------------------------------------------------- /modules/kplugin/context_130_base_sceshell.h: -------------------------------------------------------------------------------- 1 | #define CONTEXT_130_BASE_SCESHELL_SIZE 304 2 | 3 | 4 | unsigned char CONTEXT_130_BASE_SCESHELL[] = { 5 | 0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,40, 6 | 0,0,0,0,0,0,0,0,64,0,0,0,192,0,240,0, 7 | 0,0,0,0,255,255,255,255,224,0,0,0,0,0,0,0, 8 | 0,0,0,0,0,0,0,0,128,9,128,7,0,0,195,0, 9 | 0,0,32,9,64,0,0,0,0,0,0,0,0,0,0,0, 10 | 0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0, 11 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 12 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 13 | 0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0, 14 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 15 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 16 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 17 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 18 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 19 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 20 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 21 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 22 | 0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0, 23 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 24 | }; 25 | -------------------------------------------------------------------------------- /modules/kplugin/exports.yml: -------------------------------------------------------------------------------- 1 | kentente: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 0 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | modules: 10 | kuentente: 11 | syscall: true 12 | functions: 13 | - kuEntenteDecryptSelf 14 | - kuEntenteGetLogs 15 | - kuEntenteStatus -------------------------------------------------------------------------------- /modules/kplugin/kentente.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "../common/elf.h" 11 | #include "../common/self.h" 12 | #include "kernel.h" 13 | #include "context_130_base_sceshell.h" 14 | #include "context_130_base_kernel.h" 15 | #include "kentente.h" 16 | 17 | #define printf ksceDebugPrintf 18 | static char log[128]; 19 | static int status = ENTENTE_DONE; 20 | 21 | void _log(int stat, const char *text, ...) { 22 | va_list args; 23 | va_start(args, text); 24 | vsprintf(log, text, args); 25 | va_end(args); 26 | status = stat; 27 | } 28 | 29 | void kuEntenteGetLogs(char *dest) { 30 | int state; 31 | ENTER_SYSCALL(state); 32 | ksceKernelMemcpyKernelToUser((uintptr_t)dest, log, sizeof(log)); 33 | status = ENTENTE_NONE; 34 | EXIT_SYSCALL(state); 35 | } 36 | 37 | int kuEntenteStatus() { 38 | int state, ret; 39 | ENTER_SYSCALL(state); 40 | ret = status; 41 | EXIT_SYSCALL(state); 42 | return ret; 43 | } 44 | 45 | int decrypt_self(char *path, char *outpath, char *klicensee, int path_id, int usecdram, int self_type, int self_auth) { 46 | int ctx, ret; 47 | SceUID fd = 0, wfd = 0; 48 | char *data_buf = NULL, *data_buf_aligned; 49 | char *hdr_buf = NULL, *hdr_buf_aligned; 50 | 51 | // set up F00D context 52 | if ((ret = sceSblAuthMgrSmStartForKernel(&ctx)) < 0) 53 | return 1; 54 | 55 | // set up SceSblSmCommContext130 56 | SceSblSmCommContext130 *context_130 = (SceSblSmCommContext130 *)sceSysmemMallocForKernel(0x130); 57 | if (context_130 == NULL) 58 | goto fail; 59 | memset(context_130, 0, 0x130); 60 | if (klicensee == NULL) { 61 | memcpy(context_130, CONTEXT_130_BASE_KERNEL, CONTEXT_130_BASE_KERNEL_SIZE); 62 | context_130->self_type = self_type; 63 | } else { 64 | memcpy(context_130, CONTEXT_130_BASE_SCESHELL, CONTEXT_130_BASE_SCESHELL_SIZE); 65 | memcpy(context_130->called_self_auth_info.klicensee, klicensee, 0x10); 66 | } 67 | 68 | // Set path_id according to the normal path 69 | if (path_id >= 0) 70 | context_130->path_id = path_id; 71 | else if ((ret = sceIoGetPathIdExForDriver(KERNEL_PID, path, 1, (int *)&(context_130->path_id))) < 0) 72 | goto fail; 73 | 74 | hdr_buf = sceSysmemMallocForKernel(HEADER_LEN + 63); 75 | hdr_buf_aligned = (char *)(((int)hdr_buf + 63) & 0xFFFFFFC0); 76 | 77 | if (hdr_buf == NULL) 78 | goto fail; 79 | 80 | if ((fd = ksceIoOpen(path, 1, 0)) < 0) 81 | goto fail; 82 | ret = ksceIoRead(fd, hdr_buf_aligned, HEADER_LEN); 83 | 84 | SCE_header *shdr = (SCE_header *)(hdr_buf_aligned); 85 | 86 | if (shdr->header_len > HEADER_LEN) 87 | goto fail; 88 | 89 | // set up SBL decryption for this SELF. 90 | if ((ret = sceSblAuthMgrAuthHeaderForKernel(ctx, hdr_buf_aligned, shdr->header_len, context_130)) < 0) 91 | goto fail; 92 | char *ending = strchr(outpath, 0); 93 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr_buf_aligned + shdr->elf_offset); 94 | Elf32_Phdr *phdrs = (Elf32_Phdr *)(hdr_buf_aligned + shdr->phdr_offset); 95 | segment_info *segs = (segment_info*)(hdr_buf_aligned + shdr->section_info_offset); 96 | 97 | data_buf = sceSysmemMallocForKernel(0x10000 + 63); 98 | data_buf_aligned = (char *)(((int)data_buf + 63) & 0xFFFFFFC0); 99 | if (data_buf == NULL) 100 | goto fail; 101 | void *pgr_buf; 102 | 103 | // decrypt sections 104 | SceUID blkid = 0; 105 | 106 | for (int i=0; i < ehdr->e_phnum; i++) { 107 | _log(ENTENTE_UPDATE, "Decrypting segment: %i", i); 108 | if (segs[i].encryption == 1) { 109 | *ending = 0; 110 | snprintf(outpath, PATH_MAX, "%s.temp%i",outpath, i); 111 | ksceIoClose(wfd); 112 | 113 | wfd = ksceIoOpen(outpath, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 6); 114 | if (wfd < 0) 115 | break; 116 | size_t aligned_size = (phdrs[i].p_filesz + 4095) & 0xFFFFF000; 117 | 118 | // set up read buffer 119 | if (blkid) 120 | ksceKernelFreeMemBlock(blkid); 121 | 122 | if (usecdram) 123 | blkid = ksceKernelAllocMemBlock("self_decrypt_buffer", 0x40404006, 0x4000000, NULL); 124 | else 125 | blkid = ksceKernelAllocMemBlock("self_decrypt_buffer", 0x1020D006, aligned_size, NULL); 126 | 127 | if ((ret = ksceKernelGetMemBlockBase(blkid, &pgr_buf)) < 0) 128 | break; 129 | 130 | // setup buffer for output 131 | if ((ret = sceSblAuthMgrLoadSelfSegmentForKernel(ctx, i, segs[i].length, pgr_buf, phdrs[i].p_filesz)) < 0) 132 | break; 133 | 134 | if ((ret = ksceIoLseek(fd, segs[i].offset, SCE_SEEK_SET)) < 0) 135 | break; 136 | 137 | size_t length = segs[i].length; 138 | int to_read = length > 0x10000 ? 0x10000 : length; 139 | size_t num_read, off = 0; 140 | 141 | while (length > 0 && (num_read = ksceIoRead(fd, data_buf_aligned+off, to_read)) > 0) { 142 | off += num_read; 143 | length -= num_read; 144 | if (num_read < to_read) { 145 | to_read -= num_read; 146 | continue; 147 | } 148 | ret = sceSblAuthMgrLoadSelfBlockForKernel(ctx, data_buf_aligned, off); // decrypt buffer 149 | if (ret < 0) 150 | _log(ENTENTE_UPDATE, "!!! ERROR !!!\n"); 151 | ksceIoWrite(wfd, data_buf_aligned, to_read); 152 | off = 0; 153 | to_read = length > 0x10000 ? 0x10000 : length; 154 | } 155 | // write buffer 156 | off = 0; 157 | while ((off += ksceIoWrite(wfd, pgr_buf+off, phdrs[i].p_filesz-off)) < phdrs[i].p_filesz); 158 | 159 | 160 | ksceIoClose(wfd); 161 | strncpy(outpath + PATH_MAX/2, outpath, PATH_MAX/2); 162 | *ending = 0; 163 | snprintf(outpath, PATH_MAX/2, "%s.seg%i",outpath, i); 164 | ksceKernelDelayThread(10 * 1000); 165 | ksceIoRename(outpath + PATH_MAX/2, outpath); 166 | _log(ENTENTE_DONESEG, "Segment decrypted: %i", i); 167 | } 168 | 169 | } 170 | *ending = 0; 171 | if (blkid) 172 | ksceKernelFreeMemBlock(blkid); 173 | 174 | if (self_auth) { 175 | snprintf(outpath, PATH_MAX, "%s.auth",outpath); 176 | wfd = ksceIoOpen(outpath, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 6); 177 | memset(context_130->called_self_auth_info.klicensee, 0, 0x10); 178 | ksceIoWrite(wfd, &context_130->called_self_auth_info, sizeof(context_130->called_self_auth_info)); 179 | ksceIoClose(wfd); 180 | *ending = 0; 181 | } 182 | 183 | fail: 184 | _log(ENTENTE_DONE, "kuEntente Returned: %x", ret); 185 | sceSblAuthMgrSmFinalizeForKernel(ctx); 186 | if (fd) 187 | ksceIoClose(fd); 188 | if (context_130) 189 | sceSysmemFreeForKernel(context_130); 190 | if (hdr_buf) 191 | sceSysmemFreeForKernel(hdr_buf); 192 | if (data_buf) 193 | sceSysmemFreeForKernel(data_buf); 194 | return 1; 195 | } 196 | 197 | int getlicensee_rif(char *path, char *klicensee) { 198 | int res, fd; 199 | char *klicensee_buf = NULL, *klicensee_buf_aligned; 200 | klicensee_buf = sceSysmemMallocForKernel(0x200 + 63); 201 | klicensee_buf_aligned = (char *)(((int)klicensee_buf + 63) & 0xFFFFFFC0); 202 | memset(klicensee, 0, 0x10); 203 | fd = ksceIoOpen(path, SCE_O_RDONLY, 0); 204 | ksceIoRead(fd, klicensee_buf_aligned, 0x200); 205 | ksceIoClose(fd); 206 | res = ksceNpDrmGetRifVitaKey((SceNpDrmLicense *)klicensee_buf_aligned, klicensee, NULL, NULL, NULL, NULL); 207 | sceSysmemFreeForKernel(klicensee_buf); 208 | return res; 209 | } 210 | static ententeParams param; 211 | 212 | int decrypt_thread(SceSize args, void *argp) { 213 | char klicensee[0x10]; 214 | char *outpath_buf = param.outpath, *outpath_buf_aligned; 215 | char *inpath_buf = param.rifpath, *inpath_buf_aligned; 216 | char *path_buf = param.path, *path_buf_aligned; 217 | outpath_buf_aligned = (char *)(((int)outpath_buf + 63) & 0xFFFFFFC0); 218 | path_buf_aligned = (char *)(((int)path_buf + 63) & 0xFFFFFFC0); 219 | 220 | char *klicensee_ptr = klicensee; 221 | _log(ENTENTE_UPDATE, "Starting decryption..."); 222 | if (inpath_buf!=NULL) { 223 | inpath_buf_aligned = (char *)(((int)inpath_buf + 63) & 0xFFFFFFC0); 224 | _log(ENTENTE_UPDATE, "Getting klicense from rif"); 225 | getlicensee_rif(inpath_buf_aligned, klicensee); 226 | sceSysmemFreeForKernel(inpath_buf); 227 | } else 228 | klicensee_ptr = NULL; 229 | decrypt_self(path_buf_aligned, outpath_buf_aligned, klicensee_ptr, param.path_id, param.usecdram, param.self_type, param.self_auth); 230 | sceSysmemFreeForKernel(outpath_buf); 231 | sceSysmemFreeForKernel(path_buf); 232 | ksceKernelExitDeleteThread(0); 233 | return 0; 234 | } 235 | 236 | int kuEntenteDecryptSelf(ententeParams *u_param) { 237 | int state, res, tid; 238 | char *outpath_buf = NULL, *outpath_buf_aligned; 239 | char *inpath_buf = NULL, *inpath_buf_aligned; 240 | char *path_buf = NULL, *path_buf_aligned; 241 | 242 | ENTER_SYSCALL(state); 243 | 244 | outpath_buf = sceSysmemMallocForKernel(PATH_MAX + 63); 245 | outpath_buf_aligned = (char *)(((int)outpath_buf + 63) & 0xFFFFFFC0); 246 | 247 | inpath_buf = sceSysmemMallocForKernel(PATH_MAX + 63); 248 | inpath_buf_aligned = (char *)(((int)inpath_buf + 63) & 0xFFFFFFC0); 249 | 250 | path_buf = sceSysmemMallocForKernel(PATH_MAX + 63); 251 | path_buf_aligned = (char *)(((int)path_buf + 63) & 0xFFFFFFC0); 252 | ksceKernelMemcpyUserToKernel(¶m, (uintptr_t)u_param, sizeof(ententeParams)); 253 | ksceKernelStrncpyUserToKernel(path_buf_aligned, (uintptr_t)param.path, PATH_MAX); 254 | ksceKernelStrncpyUserToKernel(outpath_buf_aligned, (uintptr_t)param.outpath, PATH_MAX); 255 | if (param.rifpath!=NULL) 256 | ksceKernelStrncpyUserToKernel(inpath_buf_aligned, (uintptr_t)param.rifpath, PATH_MAX); 257 | else { 258 | sceSysmemFreeForKernel(inpath_buf); 259 | inpath_buf = NULL; 260 | } 261 | param.path = path_buf; 262 | param.outpath = outpath_buf; 263 | param.rifpath = inpath_buf; 264 | tid = ksceKernelCreateThread("kuEntente_thread", (SceKernelThreadEntry)decrypt_thread, 64, 0x1000, 0, 0, NULL); 265 | res = ksceKernelStartThread(tid, 0, NULL); 266 | 267 | EXIT_SYSCALL(state); 268 | return res; 269 | } 270 | 271 | void _start() __attribute__ ((weak, alias ("module_start"))); 272 | int module_start(SceSize argc, const void *args) { 273 | module_get_export_func(KERNEL_PID, "SceSblAuthMgr", 0x7ABF5135, 0xA9CD2A09, (uintptr_t*)&sceSblAuthMgrSmStartForKernel); 274 | module_get_export_func(KERNEL_PID, "SceSblAuthMgr", 0x7ABF5135, 0xF3411881, (uintptr_t*)&sceSblAuthMgrAuthHeaderForKernel); 275 | module_get_export_func(KERNEL_PID, "SceSblAuthMgr", 0x7ABF5135, 0x026ACBAD, (uintptr_t*)&sceSblAuthMgrSmFinalizeForKernel); 276 | module_get_export_func(KERNEL_PID, "SceSblAuthMgr", 0x7ABF5135, 0x89CCDA2C, (uintptr_t*)&sceSblAuthMgrLoadSelfSegmentForKernel); 277 | module_get_export_func(KERNEL_PID, "SceSblAuthMgr", 0x7ABF5135, 0xBC422443, (uintptr_t*)&sceSblAuthMgrLoadSelfBlockForKernel); 278 | 279 | if (module_get_export_func(KERNEL_PID, "SceSysmem", 0x63A519E5, 0xC0A4D2F3, (uintptr_t*)&sceSysmemMallocForKernel) < 0) 280 | module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0x85571907, (uintptr_t*)&sceSysmemMallocForKernel); 281 | if (module_get_export_func(KERNEL_PID, "SceSysmem", 0x63A519E5, 0xABAB0FAB, (uintptr_t*)&sceSysmemFreeForKernel) < 0) 282 | module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0x4233C16D, (uintptr_t*)&sceSysmemFreeForKernel); 283 | 284 | module_get_export_func(KERNEL_PID, "SceIofilemgr", 0x40FD29C7, 0x9C220246, (uintptr_t*)&sceIoGetPathIdExForDriver); 285 | 286 | status = ENTENTE_DONE; 287 | return SCE_KERNEL_START_SUCCESS; 288 | } 289 | 290 | int module_stop(SceSize argc, const void *args) { 291 | return SCE_KERNEL_STOP_SUCCESS; 292 | } 293 | -------------------------------------------------------------------------------- /modules/kplugin/kentente.h: -------------------------------------------------------------------------------- 1 | enum Status { 2 | ENTENTE_NONE, 3 | ENTENTE_UPDATE, 4 | ENTENTE_DONE, 5 | ENTENTE_DONESEG 6 | }; 7 | typedef struct ententeParams { 8 | char *path; 9 | char *outpath; 10 | char *rifpath; 11 | int path_id; 12 | int usecdram; 13 | int self_auth; 14 | int self_type; 15 | } ententeParams; 16 | 17 | int kuEntenteDecryptSelf(ententeParams *u_param) ; 18 | int kuEntenteStatus(); 19 | void kuEntenteGetLogs(char *dest); -------------------------------------------------------------------------------- /modules/kplugin/kernel.h: -------------------------------------------------------------------------------- 1 | // taihen 2 | 3 | int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func); 4 | 5 | // SceSblAuthMgr 6 | 7 | typedef struct SceSelfInfo // size is 0x90 8 | { 9 | SceUInt64 program_authority_id; 10 | SceUInt64 padding1; 11 | uint8_t capability[0x20]; 12 | uint8_t attribute[0x20]; 13 | uint8_t padding2[0x10]; 14 | uint8_t klicensee[0x10]; 15 | uint32_t unk_70; 16 | uint32_t unk_74; 17 | uint32_t unk_78; 18 | uint32_t unk_7C; 19 | uint32_t unk_80; // ex: 0x10 20 | uint32_t unk_84; 21 | uint32_t unk_88; 22 | uint32_t unk_8C; 23 | } SceSelfInfo; 24 | 25 | typedef struct SceSblSmCommContext130 // size is 0x130 as its name indicates 26 | { 27 | uint32_t unk_0; 28 | uint32_t self_type; // kernel = 0, user = 1, SM = 2 29 | SceSelfInfo caller_self_auth_info; // can be obtained with sceKernelGetSelfInfoForKernel 30 | SceSelfInfo called_self_auth_info; // set by F00D in F00D SceSblSmCommContext130 response 31 | uint32_t path_id; // can be obtained with sceSblACMgrGetPathIdForKernel or sceIoGetPathIdExForDriver 32 | uint32_t unk_12C; 33 | } SceSblSmCommContext130; 34 | 35 | int (*sceSblAuthMgrSmStartForKernel)(int* ctx); 36 | void *(*sceSysmemMallocForKernel)(size_t size); 37 | int (*sceSysmemFreeForKernel)(void *ptr); 38 | int (*sceSblAuthMgrAuthHeaderForKernel)(int ctx, char *header, int header_size, SceSblSmCommContext130 *context_130); 39 | int (*sceSblAuthMgrSmFinalizeForKernel)(int ctx); 40 | int (*sceSblAuthMgrLoadSelfSegmentForKernel)(int ctx, int segment_number, size_t segment_size, void *output_buffer, size_t program_size); 41 | //int (*sceSblAuthMgrLoadSelfSegmentForKernel)(int ctx, int segment_number); 42 | int (*sceSblAuthMgrLoadSelfBlockForKernel)(int ctx, char *buffer, int offset); 43 | int (*sceIoGetPathIdExForDriver)(SceUID pid, const char *path, int ignored, int *pathId); 44 | 45 | // SceNpDrm 46 | 47 | typedef struct { 48 | uint16_t version; // 0x00 49 | uint16_t version_flag; // 0x02 50 | uint16_t type; // 0x04 51 | uint16_t flags; // 0x06 52 | uint64_t aid; // 0x08 53 | char content_id[0x30]; // 0x10 54 | uint8_t key_table[0x10]; // 0x40 55 | uint8_t key[0x10]; // 0x50 56 | uint64_t start_time; // 0x60 57 | uint64_t expiration_time; // 0x68 58 | uint8_t ecdsa_signature[0x28]; // 0x70 59 | 60 | uint64_t flags2; // 0x98 61 | uint8_t key2[0x10]; // 0xA0 62 | uint8_t unk_B0[0x10]; // 0xB0 63 | uint8_t openpsid[0x10]; // 0xC0 64 | uint8_t unk_D0[0x10]; // 0xD0 65 | uint8_t cmd56_handshake[0x14]; // 0xE0 66 | uint32_t unk_F4; // 0xF4 67 | uint32_t unk_F8; // 0xF8 68 | uint32_t sku_flag; // 0xFC 69 | uint8_t rsa_signature[0x100]; // 0x100 70 | } SceNpDrmLicense; 71 | 72 | int ksceNpDrmGetRifVitaKey(SceNpDrmLicense *license_buf, char *klicensee, uint32_t *flags, uint32_t *sku_flag, uint64_t *start_time, uint64_t *expiration_time); 73 | -------------------------------------------------------------------------------- /modules/patch/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(patch) 12 | include("${VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") 16 | 17 | add_executable(patch 18 | main.c 19 | ) 20 | 21 | target_link_libraries(patch 22 | taihenForKernel_stub 23 | ) 24 | 25 | vita_create_self(patch.skprx patch CONFIG exports.yml UNSAFE) 26 | -------------------------------------------------------------------------------- /modules/patch/build/Makefile: -------------------------------------------------------------------------------- 1 | ifdef VITASDK 2 | PREFIX = $(VITASDK)/bin/ 3 | endif 4 | 5 | ARCH ?= $(PREFIX)arm-vita-eabi 6 | AS = $(ARCH)-as 7 | AR = $(ARCH)-ar 8 | RANLIB = $(ARCH)-ranlib 9 | 10 | TARGETS = 11 | TARGETS_WEAK = 12 | 13 | SceKernel_OBJS = 14 | ALL_OBJS= 15 | 16 | all: $(TARGETS) $(TARGETS_WEAK) 17 | 18 | define LIBRARY_template 19 | $(1): $$($(1:lib%_stub.a=%)_OBJS) 20 | ALL_OBJS += $$($(1:lib%_stub.a=%)_OBJS) 21 | endef 22 | define LIBRARY_WEAK_template 23 | $(1): $$($(1:lib%_stub_weak.a=%)_weak_OBJS) 24 | ALL_OBJS += $$($(1:lib%_stub_weak.a=%)_weak_OBJS) 25 | endef 26 | 27 | $(foreach library,$(TARGETS),$(eval $(call LIBRARY_template,$(library)))) 28 | $(foreach library,$(TARGETS_WEAK),$(eval $(call LIBRARY_WEAK_template,$(library)))) 29 | 30 | install: $(TARGETS) $(TARGETS_WEAK) 31 | cp $(TARGETS) $(VITASDK)/arm-vita-eabi/lib 32 | cp $(TARGETS_WEAK) $(VITASDK)/arm-vita-eabi/lib 33 | 34 | clean: 35 | rm -f $(TARGETS) $(TARGETS_WEAK) $(ALL_OBJS) 36 | 37 | $(TARGETS) $(TARGETS_WEAK): 38 | $(AR) cru $@ $? 39 | $(RANLIB) $@ 40 | 41 | %.o: %.S 42 | $(AS) --defsym GEN_WEAK_EXPORTS=0 $< -o $@ 43 | 44 | %.wo: %.S 45 | $(AS) --defsym GEN_WEAK_EXPORTS=1 $< -o $@ 46 | -------------------------------------------------------------------------------- /modules/patch/exports.yml: -------------------------------------------------------------------------------- 1 | VitaShellPatch: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 0 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | -------------------------------------------------------------------------------- /modules/patch/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 | 22 | static SceUID hooks[2]; 23 | 24 | void _start() __attribute__ ((weak, alias("module_start"))); 25 | int module_start(SceSize args, void *argp) { 26 | // Get tai module info 27 | tai_module_info_t info; 28 | info.size = sizeof(tai_module_info_t); 29 | if (taiGetModuleInfoForKernel(KERNEL_PID, "SceAppMgr", &info) < 0) 30 | return SCE_KERNEL_START_SUCCESS; 31 | 32 | // Patch to allow Memory Card remount 33 | uint32_t nop_nop_opcode = 0xBF00BF00; 34 | switch (info.module_nid) { 35 | case 0x94CEFE4B: // 3.55 retail 36 | case 0xDFBC288C: // 3.57 retail 37 | case 0xDBB29DB7: // 3.60 retail 38 | case 0x1C9879D6: // 3.65 retail 39 | hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB338, &nop_nop_opcode, 4); 40 | hooks[1] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB368, &nop_nop_opcode, 2); 41 | break; 42 | 43 | case 0x54E2E984: // 3.67 retail 44 | case 0xC3C538DE: // 3.68 retail 45 | hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB344, &nop_nop_opcode, 4); 46 | hooks[1] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB374, &nop_nop_opcode, 2); 47 | break; 48 | 49 | case 0x321E4852: // 3.69 retail 50 | case 0x700DA0CD: // 3.70 retail 51 | case 0xF7846B4E: // 3.71 retail 52 | case 0xA8E80BA8: // 3.72 retail 53 | case 0xB299D195: // 3.73 retail 54 | hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB34C, &nop_nop_opcode, 4); 55 | hooks[1] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB37C, &nop_nop_opcode, 2); 56 | break; 57 | } 58 | 59 | return SCE_KERNEL_START_SUCCESS; 60 | } 61 | 62 | int module_stop(SceSize args, void *argp) { 63 | if (hooks[1] >= 0) 64 | taiInjectReleaseForKernel(hooks[1]); 65 | 66 | if (hooks[0] >= 0) 67 | taiInjectReleaseForKernel(hooks[0]); 68 | 69 | return SCE_KERNEL_STOP_SUCCESS; 70 | } 71 | -------------------------------------------------------------------------------- /modules/uplugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(userAllied) 12 | include("$ENV{VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -std=gnu99") 15 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib") 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions") 17 | 18 | add_executable(userAllied 19 | userAllied.c 20 | ) 21 | 22 | target_link_libraries(userAllied 23 | SceLibKernel_stub 24 | ${CMAKE_BINARY_DIR}/modules/kplugin/kentente-stubs/libkentente_stub.a 25 | ) 26 | 27 | vita_create_self(${PROJECT_NAME}.suprx ${PROJECT_NAME} 28 | UNSAFE 29 | CONFIG ${CMAKE_SOURCE_DIR}/modules/uplugin/exports.yml 30 | ) 31 | 32 | vita_create_stubs(${PROJECT_NAME}-stubs ${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/modules/uplugin/exports.yml 33 | ) 34 | 35 | install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/ 36 | DESTINATION lib 37 | FILES_MATCHING PATTERN "*.a" 38 | ) 39 | 40 | install(FILES userAllied.h 41 | DESTINATION include 42 | ) 43 | -------------------------------------------------------------------------------- /modules/uplugin/exports.yml: -------------------------------------------------------------------------------- 1 | userAllied: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 0 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | modules: 10 | userAlliedLib: 11 | syscall: false 12 | functions: 13 | - userAlliedDecryptSelf 14 | - userAlliedStatus 15 | - userAlliedGetLogs -------------------------------------------------------------------------------- /modules/uplugin/userAllied.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //#include 4 | #include "../kplugin/kentente.h" 5 | #include "userAllied.h" 6 | 7 | 8 | int userAlliedDecryptSelf(struct ententeParams *u_param) { 9 | return kuEntenteDecryptSelf(u_param); 10 | } 11 | 12 | int userAlliedStatus() { 13 | return kuEntenteStatus(); 14 | } 15 | 16 | void userAlliedGetLogs(char *dest) { 17 | kuEntenteGetLogs(dest); 18 | } 19 | 20 | void _start() __attribute__ ((weak, alias("module_start"))); 21 | int module_start(SceSize args, void *argp) { 22 | return SCE_KERNEL_START_SUCCESS; 23 | } 24 | 25 | int module_stop(SceSize args, void *argp) { 26 | return SCE_KERNEL_STOP_SUCCESS; 27 | } 28 | -------------------------------------------------------------------------------- /modules/uplugin/userAllied.h: -------------------------------------------------------------------------------- 1 | 2 | int userAlliedDecryptSelf(struct ententeParams *u_param); 3 | int userAlliedStatus(); 4 | void userAlliedGetLogs(char *dest); -------------------------------------------------------------------------------- /modules/usbdevice/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(usbdevice) 12 | include("${VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") 16 | 17 | add_executable(usbdevice 18 | main.c 19 | ) 20 | 21 | target_link_libraries(usbdevice 22 | SceUdcdForDriver_stub 23 | SceIofilemgrForDriver_stub 24 | SceSysclibForDriver_stub 25 | taihenForKernel_stub 26 | ) 27 | 28 | vita_create_self(usbdevice.skprx usbdevice CONFIG exports.yml UNSAFE) 29 | -------------------------------------------------------------------------------- /modules/usbdevice/exports.yml: -------------------------------------------------------------------------------- 1 | VitaShellUsbDevice: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 0 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | -------------------------------------------------------------------------------- /modules/usbdevice/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | static tai_hook_ref_t ksceIoOpenRef; 29 | static tai_hook_ref_t ksceIoReadRef; 30 | 31 | static SceUID hooks[3]; 32 | 33 | static int first = 1; 34 | 35 | static SceUID ksceIoOpenPatched(const char *file, int flags, SceMode mode) { 36 | first = 1; 37 | 38 | SceUID fd = TAI_CONTINUE(SceUID, ksceIoOpenRef, file, flags, mode); 39 | 40 | if (fd == 0x800F090D) 41 | return TAI_CONTINUE(SceUID, ksceIoOpenRef, file, flags & ~SCE_O_WRONLY, mode); 42 | 43 | return fd; 44 | } 45 | 46 | static int ksceIoReadPatched(SceUID fd, void *data, SceSize size) { 47 | int res = TAI_CONTINUE(int, ksceIoReadRef, fd, data, size); 48 | 49 | if (first) { 50 | first = 0; 51 | 52 | // Manipulate boot sector to support exFAT 53 | if (memcmp(data + 0x3, "EXFAT", 5) == 0) { 54 | // Sector size 55 | *(uint16_t *)(data + 0xB) = 1 << *(uint8_t *)(data + 0x6C); 56 | 57 | // Volume size 58 | *(uint32_t *)(data + 0x20) = *(uint32_t *)(data + 0x48); 59 | } 60 | } 61 | 62 | return res; 63 | } 64 | 65 | void _start() __attribute__ ((weak, alias("module_start"))); 66 | int module_start(SceSize args, void *argp) { 67 | // Get tai module info 68 | tai_module_info_t info; 69 | info.size = sizeof(tai_module_info_t); 70 | if (taiGetModuleInfoForKernel(KERNEL_PID, "SceUsbstorVStorDriver", &info) < 0) 71 | return SCE_KERNEL_START_SUCCESS; 72 | 73 | // Remove image path limitation 74 | char zero[0x6E]; 75 | memset(zero, 0, 0x6E); 76 | hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0x1738, zero, 0x6E); 77 | 78 | // Add patches to support exFAT 79 | hooks[1] = taiHookFunctionImportForKernel(KERNEL_PID, &ksceIoOpenRef, "SceUsbstorVStorDriver", 80 | 0x40FD29C7, 0x75192972, ksceIoOpenPatched); 81 | hooks[2] = taiHookFunctionImportForKernel(KERNEL_PID, &ksceIoReadRef, "SceUsbstorVStorDriver", 82 | 0x40FD29C7, 0xE17EFC03, ksceIoReadPatched); 83 | 84 | ksceUdcdStopCurrentInternal(2); 85 | 86 | return SCE_KERNEL_START_SUCCESS; 87 | } 88 | 89 | int module_stop(SceSize args, void *argp) { 90 | if (hooks[2] >= 0) 91 | taiHookReleaseForKernel(hooks[2], ksceIoReadRef); 92 | if (hooks[1] >= 0) 93 | taiHookReleaseForKernel(hooks[1], ksceIoOpenRef); 94 | if (hooks[0] >= 0) 95 | taiInjectReleaseForKernel(hooks[0]); 96 | 97 | return SCE_KERNEL_STOP_SUCCESS; 98 | } 99 | -------------------------------------------------------------------------------- /modules/user/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(user) 12 | include("${VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") 16 | 17 | include_directories( 18 | ../kernel 19 | ) 20 | 21 | add_executable(user 22 | main.c 23 | ) 24 | 25 | add_dependencies(user vitashell_kernel_stubs) 26 | 27 | target_link_libraries(user 28 | ${CMAKE_BINARY_DIR}/modules/kernel/vitashell_kernel_stubs/libVitaShellKernel2_stub.a 29 | SceLibKernel_stub 30 | SceIofilemgr_stub 31 | ) 32 | 33 | vita_create_self(user.suprx user CONFIG exports.yml UNSAFE) 34 | 35 | vita_create_stubs(vitashell_user_stubs user exports.yml) 36 | -------------------------------------------------------------------------------- /modules/user/exports.yml: -------------------------------------------------------------------------------- 1 | VitaShellUser: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 0 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | modules: 10 | VitaShellUserLibrary: 11 | syscall: false 12 | functions: 13 | - shellUserIsUx0Redirected 14 | - shellUserRedirectUx0 15 | - shellUserMountById 16 | - shellUserGetRifVitaKey 17 | -------------------------------------------------------------------------------- /modules/user/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "vitashell_user.h" 28 | 29 | int shellUserIsUx0Redirected(const char *blkdev, const char *blkdev2) { 30 | return shellKernelIsUx0Redirected(blkdev, blkdev2); 31 | } 32 | 33 | int shellUserRedirectUx0(const char *blkdev, const char *blkdev2) { 34 | return shellKernelRedirectUx0(blkdev, blkdev2); 35 | } 36 | 37 | int shellUserMountById(ShellMountIdArgs *args) { 38 | return shellKernelMountById(args); 39 | } 40 | 41 | int shellUserGetRifVitaKey(const void *license_buf, void *klicensee) { 42 | return shellKernelGetRifVitaKey(license_buf, klicensee); 43 | } 44 | 45 | void _start() __attribute__ ((weak, alias("module_start"))); 46 | int module_start(SceSize args, void *argp) { 47 | return SCE_KERNEL_START_SUCCESS; 48 | } 49 | 50 | int module_stop(SceSize args, void *argp) { 51 | return SCE_KERNEL_STOP_SUCCESS; 52 | } 53 | -------------------------------------------------------------------------------- /modules/user/vitashell_user.h: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 __VITASHELL_USER_H__ 20 | #define __VITASHELL_USER_H__ 21 | 22 | #include "vitashell_kernel.h" 23 | 24 | int shellUserIsUx0Redirected(const char *blkdev, const char *blkdev2); 25 | int shellUserRedirectUx0(const char *blkdev, const char *blkdev2); 26 | int shellUserMountById(ShellMountIdArgs *args); 27 | int shellUserGetRifVitaKey(const void *license_buf, void *klicensee); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /pfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 "main.h" 20 | #include "pfs.h" 21 | 22 | /* 23 | SceAppMgr mount IDs: 24 | 0x64: ux0:picture 25 | 0x65: ur0:user/00/psnfriend 26 | 0x66: ur0:user/00/psnmsg 27 | 0x69: ux0:music 28 | 0x6E: ux0:appmeta 29 | 0xC8: ur0:temp/sqlite 30 | 0xCD: ux0:cache 31 | 0x12E: ur0:user/00/trophy/data/sce_trop 32 | 0x12F: ur0:user/00/trophy/data 33 | 0x3E8: ux0:app, vs0:app, gro0:app 34 | 0x3E9: ux0:patch 35 | 0x3EB: ? 36 | 0x3EA: ux0:addcont 37 | 0x3EC: ux0:theme 38 | 0x3ED: ux0:user/00/savedata 39 | 0x3EE: ur0:user/00/savedata 40 | 0x3EF: vs0:sys/external 41 | 0x3F0: vs0:data/external 42 | */ 43 | 44 | int known_pfs_ids[] = { 45 | 0x6E, 46 | 0x12E, 47 | 0x12F, 48 | 0x3ED, 49 | }; 50 | 51 | int pfsMount(const char *path) { 52 | int res; 53 | char work_path[MAX_PATH_LENGTH]; 54 | char klicensee[0x10]; 55 | char license_buf[0x200]; 56 | ShellMountIdArgs args; 57 | 58 | memset(klicensee, 0, sizeof(klicensee)); 59 | 60 | 61 | snprintf(work_path, MAX_PATH_LENGTH, "%ssce_sys/package/work.bin", path); 62 | printf("pfsMount ReadFile %s\n", work_path); 63 | if (ReadFile(work_path, license_buf, sizeof(license_buf)) == sizeof(license_buf)) { 64 | printf("shellUserGetRifVitaKey\n"); 65 | int res = shellUserGetRifVitaKey(license_buf, klicensee); 66 | printf("read license: 0x%08X\n", res); 67 | } 68 | 69 | //args.process_titleid = VITASHELL_TITLEID; 70 | args.process_titleid = "SHARKF00D"; 71 | args.path = path; 72 | args.desired_mount_point = NULL; 73 | args.klicensee = klicensee; 74 | args.mount_point = pfs_mount_point; 75 | 76 | read_only = 0; 77 | 78 | int i; 79 | printf("pfsMount shellUserMountById\n"); 80 | for (i = 0; i < sizeof(known_pfs_ids) / sizeof(int); i++) { 81 | args.id = known_pfs_ids[i]; 82 | 83 | res = shellUserMountById(&args); 84 | if (res >= 0) 85 | return res; 86 | } 87 | 88 | read_only = 1; 89 | printf("pfsMount sceAppMgrGameDataMount %s %s\n", path, pfs_mount_point); 90 | return sceAppMgrGameDataMount(path, 0, 0, pfs_mount_point); 91 | } 92 | 93 | int pfsUmount() { 94 | if (pfs_mount_point[0] == 0) 95 | return -1; 96 | 97 | int res = sceAppMgrUmount(pfs_mount_point); 98 | if (res >= 0) { 99 | memset(pfs_mount_point, 0, sizeof(pfs_mount_point)); 100 | memset(pfs_mounted_path, 0, sizeof(pfs_mounted_path)); 101 | } 102 | 103 | return res; 104 | } 105 | -------------------------------------------------------------------------------- /pfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 __PFS_H__ 20 | #define __PFS_H__ 21 | 22 | char pfs_mounted_path[MAX_PATH_LENGTH]; 23 | char pfs_mount_point[MAX_MOUNT_POINT_LENGTH]; 24 | int read_only; 25 | 26 | int known_pfs_ids[4]; 27 | int pfsMount(const char *path); 28 | int pfsUmount(); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /pkg/sce_sys/icon0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsirizX/ShaRKF00D/400a8b03c3b2e8da2fbdb06bff88d07b62f9bbc8/pkg/sce_sys/icon0.png -------------------------------------------------------------------------------- /pkg/sce_sys/livearea/contents/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsirizX/ShaRKF00D/400a8b03c3b2e8da2fbdb06bff88d07b62f9bbc8/pkg/sce_sys/livearea/contents/bg.png -------------------------------------------------------------------------------- /pkg/sce_sys/livearea/contents/startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OsirizX/ShaRKF00D/400a8b03c3b2e8da2fbdb06bff88d07b62f9bbc8/pkg/sce_sys/livearea/contents/startup.png -------------------------------------------------------------------------------- /pkg/sce_sys/livearea/contents/template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bg.png 6 | 7 | 8 | 9 | startup.png 10 | 11 | 12 | 13 | 14 | 15 | ShaRKF00D 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | by OsirisX 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | v1.00 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /sbrk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of vitaGL 3 | * Copyright 2017, 2018, 2019, 2020 Rinnegatamante 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published 7 | * by the Free Software Foundation, version 3 of the License, or (at your 8 | * option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * 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 | /* 20 | * Copyright (c) 2016, 2017, 2018 vitasdk 21 | * All rights reserved. 22 | * 23 | * Redistribution and use in source and binary forms, with or without 24 | * modification, are permitted provided that the following conditions 25 | * are met: 26 | * 1. Redistributions of source code must retain the above copyright 27 | * notice, this list of conditions and the following disclaimer. 28 | * 2. Redistributions in binary form must reproduce the above copyright 29 | * notice, this list of conditions and the following disclaimer in the 30 | * documentation and/or other materials provided with the distribution. 31 | * 3. Neither the name of the copyright holder nor the names of its 32 | * contributors may be used to endorse or promote products derived from 33 | * this software without specific prior written permission. 34 | * 35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36 | * "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 38 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 39 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 41 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 42 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 43 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 44 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 45 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | */ 47 | 48 | #include 49 | #include 50 | #include 51 | 52 | extern unsigned int _newlib_heap_size_user __attribute__((weak)); 53 | 54 | int _newlib_heap_memblock; 55 | unsigned _newlib_heap_size; 56 | char *_newlib_heap_base, *_newlib_heap_end, *_newlib_heap_cur; 57 | char _newlib_sbrk_mutex[32] __attribute__((aligned(8))); 58 | 59 | void *_sbrk_r(struct _reent *reent, ptrdiff_t incr) { 60 | if (sceKernelLockLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, 1, 0) < 0) 61 | goto fail; 62 | if (!_newlib_heap_base || _newlib_heap_cur + incr >= _newlib_heap_end) { 63 | sceKernelUnlockLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, 1); 64 | fail: 65 | reent->_errno = ENOMEM; 66 | return (void *)-1; 67 | } 68 | 69 | char *prev_heap_end = _newlib_heap_cur; 70 | _newlib_heap_cur += incr; 71 | 72 | sceKernelUnlockLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, 1); 73 | return (void *)prev_heap_end; 74 | } 75 | 76 | void _init_vita_heap(void) { 77 | // Create a mutex to use inside _sbrk_r 78 | if (sceKernelCreateLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, "sbrk mutex", 0, 0, 0) < 0) { 79 | goto failure; 80 | } 81 | if (&_newlib_heap_size_user != NULL) { 82 | _newlib_heap_size = _newlib_heap_size_user; 83 | } else { 84 | // Create a memblock for the heap memory, 32MB 85 | _newlib_heap_size = 32 * 1024 * 1024; 86 | } 87 | _newlib_heap_memblock = sceKernelAllocMemBlock("Newlib heap", 0x0c20d060, _newlib_heap_size, 0); 88 | if (_newlib_heap_memblock < 0) { 89 | goto failure; 90 | } 91 | if (sceKernelGetMemBlockBase(_newlib_heap_memblock, (void *)&_newlib_heap_base) < 0) { 92 | goto failure; 93 | } 94 | _newlib_heap_end = _newlib_heap_base + _newlib_heap_size; 95 | _newlib_heap_cur = _newlib_heap_base; 96 | 97 | return; 98 | failure: 99 | _newlib_heap_memblock = 0; 100 | _newlib_heap_base = 0; 101 | _newlib_heap_cur = 0; 102 | } 103 | 104 | void _free_vita_heap(void) { 105 | // Destroy the sbrk mutex 106 | sceKernelDeleteLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex); 107 | 108 | // Free the heap memblock to avoid memory leakage. 109 | sceKernelFreeMemBlock(_newlib_heap_memblock); 110 | 111 | _newlib_heap_memblock = 0; 112 | _newlib_heap_base = 0; 113 | _newlib_heap_cur = 0; 114 | } 115 | -------------------------------------------------------------------------------- /sce-elf-defs.h: -------------------------------------------------------------------------------- 1 | /* This file gets included multiple times to generate the host-visible and target-visible versions of each struct */ 2 | 3 | #if defined(SCE_ELF_DEFS_HOST) 4 | # define SCE_TYPE(type) type ## _t 5 | # define SCE_PTR(type) type 6 | #elif defined(SCE_ELF_DEFS_TARGET) 7 | # define SCE_TYPE(type) type ## _raw 8 | # define SCE_PTR(type) uint32_t 9 | #else 10 | # error "Do not include sce-elf-defs.h directly! Include sce-elf.h!" 11 | #endif 12 | 13 | #include 14 | 15 | struct SCE_TYPE(sce_module_exports); 16 | struct SCE_TYPE(sce_module_imports); 17 | 18 | typedef struct SCE_TYPE(sce_module_info) { 19 | uint16_t attributes; 20 | uint16_t version; /* Set to 0x0101 */ 21 | char name[27]; /* Name of the library */ 22 | uint8_t type; /* 0x0 for executable, 0x6 for PRX */ 23 | SCE_PTR(const void *) gp_value; 24 | SCE_PTR(struct sce_module_exports_t *) 25 | export_top; /* Offset to start of export table */ 26 | SCE_PTR(struct sce_module_exports_t *) 27 | export_end; /* Offset to end of export table */ 28 | SCE_PTR(struct sce_module_imports_t *) 29 | import_top; /* Offset to start of import table */ 30 | SCE_PTR(struct sce_module_imports_t *) 31 | import_end; /* Offset to end of import table */ 32 | uint32_t library_nid; /* NID of this library */ 33 | uint32_t tls_start; 34 | uint32_t tls_filesz; 35 | uint32_t tls_memsz; 36 | SCE_PTR(const void *) module_start; /* Offset to function to run when library is started, 0 to disable */ 37 | SCE_PTR(const void *) module_stop; /* Offset to function to run when library is exiting, 0 to disable */ 38 | SCE_PTR(const void *) exidx_top; /* Offset to start of ARM EXIDX (optional) */ 39 | SCE_PTR(const void *) exidx_end; /* Offset to end of ARM EXIDX (optional) */ 40 | SCE_PTR(const void *) extab_top; /* Offset to start of ARM EXTAB (optional) */ 41 | SCE_PTR(const void *) extab_end; /* Offset to end of ARM EXTAB (optional */ 42 | 43 | // i decided to include process param into module_info (xyz) 44 | uint32_t process_param_size; 45 | uint32_t process_param_magic; 46 | uint32_t process_param_ver; 47 | uint32_t process_param_fw_ver; 48 | SCE_PTR(const char *) process_param_main_thread_name; 49 | int32_t process_param_main_thread_priority; 50 | uint32_t process_param_main_thread_stacksize; 51 | uint32_t process_param_main_thread_attribute; 52 | SCE_PTR(const char *) process_param_process_name; 53 | uint32_t process_param_process_preload_disabled; 54 | uint32_t process_param_main_thread_cpu_affinity_mask; 55 | SCE_PTR(const void *) process_param_sce_libc_param; 56 | uint32_t process_param_unk; 57 | } SCE_TYPE(sce_module_info); 58 | 59 | typedef struct SCE_TYPE(sce_module_exports) { 60 | uint16_t size; /* Size of this struct, set to 0x20 */ 61 | uint16_t version; /* 0x1 for normal export, 0x0 for main module export */ 62 | uint16_t flags; /* 0x1 for normal export, 0x8000 for main module export */ 63 | uint16_t num_syms_funcs; /* Number of function exports */ 64 | uint32_t num_syms_vars; /* Number of variable exports */ 65 | uint32_t num_syms_unk; 66 | uint32_t module_nid; /* NID of this module */ 67 | SCE_PTR(const char *) module_name; /* Pointer to name of this module */ 68 | SCE_PTR(uint32_t *) nid_table; /* Pointer to array of 32-bit NIDs to export */ 69 | SCE_PTR(const void **) entry_table; /* Pointer to array of data pointers for each NID */ 70 | } SCE_TYPE(sce_module_exports); 71 | 72 | typedef struct SCE_TYPE(sce_module_imports) { 73 | uint16_t size; /* Size of this struct, set to 0x34 */ 74 | uint16_t version; /* Set to 0x1 */ 75 | uint16_t flags; /* Set to 0x0 */ 76 | uint16_t num_syms_funcs; /* Number of function imports */ 77 | uint16_t num_syms_vars; /* Number of variable imports */ 78 | uint16_t num_syms_unk; 79 | 80 | uint32_t reserved1; 81 | uint32_t module_nid; /* NID of module to import */ 82 | SCE_PTR(const char *) module_name; /* Pointer to name of imported module, for debugging */ 83 | uint32_t reserved2; 84 | SCE_PTR(uint32_t *) func_nid_table; /* Pointer to array of function NIDs to import */ 85 | SCE_PTR(const void **) func_entry_table;/* Pointer to array of stub functions to fill */ 86 | SCE_PTR(uint32_t *) var_nid_table; /* Pointer to array of variable NIDs to import */ 87 | SCE_PTR(const void **) var_entry_table; /* Pointer to array of data pointers to write to */ 88 | SCE_PTR(uint32_t *) unk_nid_table; 89 | SCE_PTR(const void **) unk_entry_table; 90 | } SCE_TYPE(sce_module_imports); 91 | 92 | /* alternative module imports struct with a size of 0x24 */ 93 | typedef struct SCE_TYPE(sce_module_imports_short) { 94 | uint16_t size; /* Size of this struct, set to 0x24 */ 95 | uint16_t version; /* Set to 0x1 */ 96 | uint16_t flags; /* Set to 0x0 */ 97 | uint16_t num_syms_funcs; /* Number of function imports */ 98 | uint16_t num_syms_vars; /* Number of variable imports */ 99 | uint16_t num_syms_unk; 100 | 101 | uint32_t module_nid; /* NID of module to import */ 102 | SCE_PTR(const char *) module_name; /* Pointer to name of imported module, for debugging */ 103 | SCE_PTR(uint32_t *) func_nid_table; /* Pointer to array of function NIDs to import */ 104 | SCE_PTR(const void **) func_entry_table; /* Pointer to array of stub functions to fill */ 105 | SCE_PTR(uint32_t *) var_nid_table; /* Pointer to array of variable NIDs to import */ 106 | SCE_PTR(const void **) var_entry_table; /* Pointer to array of data pointers to write to */ 107 | } SCE_TYPE(sce_module_imports_short); 108 | 109 | #undef SCE_TYPE 110 | #undef SCE_PTR 111 | -------------------------------------------------------------------------------- /sce-elf.h: -------------------------------------------------------------------------------- 1 | #ifndef SCE_ELF_H 2 | #define SCE_ELF_H 3 | 4 | //#include "vita-elf.h" 5 | 6 | /* SCE-specific definitions for e_type: */ 7 | #define ET_SCE_EXEC 0xFE00 /* SCE Executable file */ 8 | #define ET_SCE_RELEXEC 0xFE04 /* SCE Relocatable file */ 9 | #define ET_SCE_STUBLIB 0xFE0C /* SCE SDK Stubs */ 10 | #define ET_SCE_DYNAMIC 0xFE18 /* Unused */ 11 | #define ET_SCE_PSPRELEXEC 0xFFA0 /* Unused (PSP ELF only) */ 12 | #define ET_SCE_PPURELEXEC 0xFFA4 /* Unused (SPU ELF only) */ 13 | #define ET_SCE_UNK 0xFFA5 /* Unknown */ 14 | 15 | /* SCE-specific definitions for sh_type: */ 16 | #define SHT_SCE_RELA 0x60000000 /* SCE Relocations */ 17 | #define SHT_SCENID 0x61000001 /* Unused (PSP ELF only) */ 18 | #define SHT_SCE_PSPRELA 0x700000A0 /* Unused (PSP ELF only) */ 19 | #define SHT_SCE_ARMRELA 0x700000A4 /* Unused (PSP ELF only) */ 20 | 21 | /* SCE-specific definitions for p_type: */ 22 | #define PT_SCE_RELA 0x60000000 /* SCE Relocations */ 23 | #define PT_SCE_COMMENT 0x6FFFFF00 /* Unused */ 24 | #define PT_SCE_VERSION 0x6FFFFF01 /* Unused */ 25 | #define PT_SCE_UNK 0x70000001 /* Unknown */ 26 | #define PT_SCE_PSPRELA 0x700000A0 /* Unused (PSP ELF only) */ 27 | #define PT_SCE_PPURELA 0x700000A4 /* Unused (SPU ELF only) */ 28 | 29 | #define NID_MODULE_STOP 0x79F8E492 30 | #define NID_MODULE_EXIT 0x913482A9 31 | #define NID_MODULE_START 0x935CD196 32 | #define NID_MODULE_INFO 0x6C2224BA 33 | #define NID_PROCESS_PARAM 0x70FBA1E7 34 | 35 | typedef union { 36 | Elf32_Word r_short : 4; 37 | struct { 38 | Elf32_Word r_short : 4; 39 | Elf32_Word r_symseg : 4; 40 | Elf32_Word r_code : 8; 41 | Elf32_Word r_datseg : 4; 42 | Elf32_Word r_offset_lo : 12; 43 | Elf32_Word r_offset_hi : 20; 44 | Elf32_Word r_addend : 12; 45 | } r_short_entry; 46 | struct { 47 | Elf32_Word r_short : 4; 48 | Elf32_Word r_symseg : 4; 49 | Elf32_Word r_code : 8; 50 | Elf32_Word r_datseg : 4; 51 | Elf32_Word r_code2 : 8; 52 | Elf32_Word r_dist2 : 4; 53 | Elf32_Word r_addend; 54 | Elf32_Word r_offset; 55 | } r_long_entry; 56 | struct { 57 | Elf32_Word r_word1; 58 | Elf32_Word r_word2; 59 | Elf32_Word r_word3; 60 | } r_raw_entry; 61 | } SCE_Rel; 62 | 63 | #define SCE_ELF_DEFS_HOST 64 | #include "sce-elf-defs.h" 65 | #undef SCE_ELF_DEFS_HOST 66 | 67 | #define SCE_ELF_DEFS_TARGET 68 | #include "sce-elf-defs.h" 69 | #undef SCE_ELF_DEFS_TARGET 70 | 71 | /* This struct must only contain Elf32_Words, because we use it as an array in sce-elf.c */ 72 | typedef struct { 73 | Elf32_Word sceModuleInfo_rodata; /* The sce_module_info structure */ 74 | Elf32_Word sceLib_ent; /* All sce_module_exports structures */ 75 | Elf32_Word sceExport_rodata; /* The tables referenced by sce_module_exports */ 76 | Elf32_Word sceLib_stubs; /* All sce_module_imports structures */ 77 | Elf32_Word sceImport_rodata; /* Misc data referenced by sce_module_imports */ 78 | Elf32_Word sceFNID_rodata; /* The imported function NID arrays */ 79 | Elf32_Word sceFStub_rodata; /* The imported function pointer arrays */ 80 | Elf32_Word sceVNID_rodata; /* The imported function NID arrays */ 81 | Elf32_Word sceVStub_rodata; /* The imported function NID arrays */ 82 | } sce_section_sizes_t; 83 | 84 | int sce_elf_module_info_get_size(sce_module_info_t *module_info, sce_section_sizes_t *sizes); 85 | 86 | void sce_elf_module_info_free(sce_module_info_t *module_info); 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /sha256.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "sha256.h" 6 | #include 7 | 8 | #define READ_BUFFER (1*1024*1024) 9 | 10 | uint32_t k[64] = { 11 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 12 | 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 13 | 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 14 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 15 | 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 16 | 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 17 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 18 | 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 19 | }; 20 | 21 | void sha256_transform(SHA256_CTX *ctx, uint8_t data[]) 22 | { 23 | uint32_t a,b,c,d,e,f,g,h,i,j,t1,t2,m[64]; 24 | 25 | for (i=0,j=0; i < 16; ++i, j += 4) 26 | m[i] = (data[j] << 24) | (data[j+1] << 16) | (data[j+2] << 8) | (data[j+3]); 27 | for ( ; i < 64; ++i) 28 | m[i] = SIG1(m[i-2]) + m[i-7] + SIG0(m[i-15]) + m[i-16]; 29 | 30 | a = ctx->state[0]; 31 | b = ctx->state[1]; 32 | c = ctx->state[2]; 33 | d = ctx->state[3]; 34 | e = ctx->state[4]; 35 | f = ctx->state[5]; 36 | g = ctx->state[6]; 37 | h = ctx->state[7]; 38 | 39 | for (i = 0; i < 64; ++i) { 40 | t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; 41 | t2 = EP0(a) + MAJ(a,b,c); 42 | h = g; 43 | g = f; 44 | f = e; 45 | e = d + t1; 46 | d = c; 47 | c = b; 48 | b = a; 49 | a = t1 + t2; 50 | } 51 | 52 | ctx->state[0] += a; 53 | ctx->state[1] += b; 54 | ctx->state[2] += c; 55 | ctx->state[3] += d; 56 | ctx->state[4] += e; 57 | ctx->state[5] += f; 58 | ctx->state[6] += g; 59 | ctx->state[7] += h; 60 | } 61 | 62 | void sha256_init(SHA256_CTX *ctx) 63 | { 64 | ctx->datalen = 0; 65 | ctx->bitlen[0] = 0; 66 | ctx->bitlen[1] = 0; 67 | ctx->state[0] = 0x6a09e667; 68 | ctx->state[1] = 0xbb67ae85; 69 | ctx->state[2] = 0x3c6ef372; 70 | ctx->state[3] = 0xa54ff53a; 71 | ctx->state[4] = 0x510e527f; 72 | ctx->state[5] = 0x9b05688c; 73 | ctx->state[6] = 0x1f83d9ab; 74 | ctx->state[7] = 0x5be0cd19; 75 | } 76 | 77 | void sha256_update(SHA256_CTX *ctx, uint8_t data[], uint32_t len) 78 | { 79 | uint32_t i; 80 | 81 | for (i=0; i < len; ++i) { 82 | ctx->data[ctx->datalen] = data[i]; 83 | ctx->datalen++; 84 | if (ctx->datalen == 64) { 85 | sha256_transform(ctx,ctx->data); 86 | DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],512); 87 | ctx->datalen = 0; 88 | } 89 | } 90 | } 91 | 92 | void sha256_final(SHA256_CTX *ctx, uint8_t hash[]) 93 | { 94 | uint32_t i; 95 | 96 | i = ctx->datalen; 97 | 98 | // Pad whatever data is left in the buffer. 99 | if (ctx->datalen < 56) { 100 | ctx->data[i++] = 0x80; 101 | while (i < 56) 102 | ctx->data[i++] = 0x00; 103 | } 104 | else { 105 | ctx->data[i++] = 0x80; 106 | while (i < 64) 107 | ctx->data[i++] = 0x00; 108 | sha256_transform(ctx,ctx->data); 109 | memset(ctx->data,0,56); 110 | } 111 | 112 | // Append to the padding the total message's length in bits and transform. 113 | DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],ctx->datalen * 8); 114 | ctx->data[63] = ctx->bitlen[0]; 115 | ctx->data[62] = ctx->bitlen[0] >> 8; 116 | ctx->data[61] = ctx->bitlen[0] >> 16; 117 | ctx->data[60] = ctx->bitlen[0] >> 24; 118 | ctx->data[59] = ctx->bitlen[1]; 119 | ctx->data[58] = ctx->bitlen[1] >> 8; 120 | ctx->data[57] = ctx->bitlen[1] >> 16; 121 | ctx->data[56] = ctx->bitlen[1] >> 24; 122 | sha256_transform(ctx,ctx->data); 123 | 124 | // Since this implementation uses little endian byte ordering and SHA uses big endian, 125 | // reverse all the bytes when copying the final state to the output hash. 126 | for (i=0; i < 4; ++i) { 127 | hash[i] = (ctx->state[0] >> (24-i*8)) & 0x000000ff; 128 | hash[i+4] = (ctx->state[1] >> (24-i*8)) & 0x000000ff; 129 | hash[i+8] = (ctx->state[2] >> (24-i*8)) & 0x000000ff; 130 | hash[i+12] = (ctx->state[3] >> (24-i*8)) & 0x000000ff; 131 | hash[i+16] = (ctx->state[4] >> (24-i*8)) & 0x000000ff; 132 | hash[i+20] = (ctx->state[5] >> (24-i*8)) & 0x000000ff; 133 | hash[i+24] = (ctx->state[6] >> (24-i*8)) & 0x000000ff; 134 | hash[i+28] = (ctx->state[7] >> (24-i*8)) & 0x000000ff; 135 | } 136 | } 137 | 138 | 139 | /** 140 | * sha256_vector - SHA256 hash for data vector 141 | * @num_elem: Number of elements in the data vector 142 | * @addr: Pointers to the data areas 143 | * @len: Lengths of the data blocks 144 | * @mac: Buffer for the hash 145 | */ 146 | void sha256_vector(size_t num_elem, uint8_t *addr[], size_t *len, 147 | uint8_t *mac) 148 | { 149 | SHA256_CTX ctx; 150 | size_t i; 151 | 152 | sha256_init(&ctx); 153 | for (i = 0; i < num_elem; i++) 154 | sha256_update(&ctx, addr[i], len[i]); 155 | sha256_final(&ctx, mac); 156 | } 157 | 158 | uint32_t sha256_32_vector(size_t num_elem, uint8_t *addr[], size_t *len) 159 | { 160 | uint8_t hash[32]; 161 | 162 | sha256_vector(num_elem, addr, len, hash); 163 | 164 | // swap to little endian 165 | return (hash[0] << 24) | (hash[1] << 16) | (hash[2] << 8) | hash[3]; 166 | } 167 | 168 | int sha256_file(const char *file, uint8_t *mac) 169 | { 170 | size_t read = 0; 171 | SHA256_CTX ctx; 172 | SceUID fp = sceIoOpen(file, SCE_O_RDONLY, 0); 173 | 174 | if (!fp) 175 | return -1; 176 | 177 | uint8_t *data = malloc(READ_BUFFER); 178 | 179 | sha256_init(&ctx); 180 | 181 | while ((read = sceIoRead(fp, data, READ_BUFFER)) > 0) { 182 | sha256_update(&ctx, data, read); 183 | } 184 | 185 | sha256_final(&ctx, mac); 186 | free(data); 187 | sceIoClose(fp); 188 | return 0; 189 | } 190 | 191 | int sha256_32_file(const char *file, uint32_t *nid) 192 | { 193 | uint8_t hash[32]; 194 | uint8_t *hash_ptr = hash; 195 | 196 | if (sha256_file(file, hash) < 0) 197 | { 198 | printf("error: could not calculate SHA256 of '%s'\n", file); 199 | return -1; 200 | } 201 | 202 | size_t len = 32; 203 | *nid = sha256_32_vector(1, &hash_ptr, &len); 204 | return 0; 205 | } 206 | -------------------------------------------------------------------------------- /sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA256_H__ 2 | #define SHA256_H__ 3 | 4 | #include 5 | #include 6 | 7 | #define SHA256_MAC_LEN 32 8 | 9 | 10 | // DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds c to it 11 | #define DBL_INT_ADD(a,b,c) if (a > 0xffffffff - (c)) ++b; a += c; 12 | #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) 13 | #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) 14 | 15 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) 16 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 17 | #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) 18 | #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) 19 | #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 20 | #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 21 | 22 | typedef struct { 23 | uint8_t data[64]; 24 | uint32_t datalen; 25 | uint32_t bitlen[2]; 26 | uint32_t state[8]; 27 | } SHA256_CTX; 28 | 29 | 30 | void sha256_vector(size_t num_elem, uint8_t *addr[], size_t *len, 31 | uint8_t *mac); 32 | 33 | void sha256_transform(SHA256_CTX *ctx, uint8_t data[]); 34 | void sha256_init(SHA256_CTX *ctx); 35 | void sha256_update(SHA256_CTX *ctx, uint8_t data[], uint32_t len); 36 | void sha256_final(SHA256_CTX *ctx, uint8_t hash[]); 37 | void hmac_sha256_vector( uint8_t *key, size_t key_len, size_t num_elem, 38 | uint8_t *addr[], size_t *len, uint8_t *mac); 39 | void hmac_sha256( uint8_t *key, size_t key_len, uint8_t *data, 40 | size_t data_len, uint8_t *mac); 41 | void sha256_vector(size_t num_elem, uint8_t *addr[], size_t *len, 42 | uint8_t *mac); 43 | 44 | uint32_t sha256_32_vector(size_t num_elem, uint8_t *addr[], size_t *len); 45 | int sha256_file(const char *file, uint8_t *mac); 46 | int sha256_32_file(const char *file, uint32_t *nid); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /vitashell_error.h: -------------------------------------------------------------------------------- 1 | /* 2 | VitaShell 3 | Copyright (C) 2015-2018, TheFloW 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 __VITASHELL_ERROR_H__ 20 | #define __VITASHELL_ERROR_H__ 21 | 22 | enum VitaShellErrors { 23 | VITASHELL_ERROR_INTERNAL = 0xF0010000, 24 | VITASHELL_ERROR_NO_MEMORY = 0xF0010001, 25 | VITASHELL_ERROR_NOT_FOUND = 0xF0010002, 26 | VITASHELL_ERROR_INVALID_ARGUMENT = 0xF0010003, 27 | VITASHELL_ERROR_INVALID_MAGIC = 0xF0010004, 28 | VITASHELL_ERROR_INVALID_TYPE = 0xF0010005, 29 | VITASHELL_ERROR_ILLEGAL_ADDR = 0xF0010006, 30 | VITASHELL_ERROR_ALREADY_RUNNING = 0xF0010007, 31 | VITASHELL_ERROR_NOT_RUNNING = 0xF0010008, 32 | 33 | VITASHELL_ERROR_SRC_AND_DST_IDENTICAL = 0xF0020000, 34 | VITASHELL_ERROR_DST_IS_SUBFOLDER_OF_SRC = 0xF0020001, 35 | 36 | VITASHELL_ERROR_INVALID_TITLEID = 0xF0030000, 37 | 38 | VITASHELL_ERROR_SYMLINK_INVALID_PATH = 0xF0040000, 39 | VITASHELL_ERROR_SYMLINK_CANT_RESOLVE_BASEDIR = 0xF0040001, 40 | VITASHELL_ERROR_SYMLINK_CANT_RESOLVE_FILENAME = 0xF0040002, 41 | VITASHELL_ERROR_SYMLINK_INTERNAL = 0xF0040003, 42 | 43 | VITASHELL_ERROR_NAVIGATION = 0xF0050000, 44 | 45 | 46 | 47 | 48 | }; 49 | 50 | #endif 51 | --------------------------------------------------------------------------------