diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6fd0a37..0000000 --- a/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -# Compiled Lua sources -luac.out - -# luarocks build files -*.src.rock -*.zip -*.tar.gz - -# Object files -*.o -*.os -*.ko -*.obj -*.elf - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo -*.def -*.exp - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - diff --git a/Interlectural Property Notices.txt b/Interlectural Property Notices.txt new file mode 100644 index 0000000..fc8c65a --- /dev/null +++ b/Interlectural Property Notices.txt @@ -0,0 +1,295 @@ +Credits: + +Silica - All Graphics, Most Code +PSM INSTITUTIONS LLC (aka Silica) - Epic "Intellectual Property Notices" +Princess Of Sleeping - PUP Extractor +TheFlow0 - SPKG Decryptor (modoru) +"FAPS TEAM" / dots_tb - kscePowerSetCallbackEnabled(); nid +zecoaxco - spoof_testkit / memdump + +-- MEMDUMP CHANGES: + Removed #include + Removed all calls to LOG() + + +CEX 2 REX 2.0-- + +The MIT License (MIT) + +Copyright (c) 2019 Silica + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +KMSPico Activator-- + +The MIT License (MIT) + +Copyright (c) 2019 Silica + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Modoru-- https://github.com/TheOfficialFloW/modoru + +The MIT License (MIT) + +Copyright (c) 2019 TheFloW + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +PSV-PUP-Extractor-- https://github.com/Princess-of-Sleeping/PSV-PUP-Extractor + +NO LICENSE INFORMATION + +memdump / testkit spoofer-- https://github.com/zecoxao/memdump/tree/spoof_testkit + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9cdff5b..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Silica - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index a4dcf8d..fc60acd 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,14 @@ -# RELEASES: -Its VERY important that you download the correct binary for your console.. if you dont you will probably have a semibrick after install +# CEX2REX 2.0 +How to use: +1) Download the Testkit/DEX PUP file for your firmware and put it @ ux0:/DEX.PUP +2) Run the app and press X to install -!!3.61, 3.63, 3.67, and 3.68 are NOT supported! ONLY 3.60 and 3.65!! - -# For PSTV's ON 3.60: -use: https://bitbucket.org/SilicaAndPina/cex-2-rex/downloads/CexToRex360PSTV.vpk - -# For PSVITA's ON 3.60: -use: https://bitbucket.org/SilicaAndPina/cex-2-rex/downloads/CexToRex360VITA.vpk - -# For PSTV's ON 3.65: -use: https://bitbucket.org/SilicaAndPina/cex-2-rex/downloads/CexToRex365PSTV.vpk - -# For PSVITA's ON 3.65: -use: https://bitbucket.org/SilicaAndPina/cex-2-rex/downloads/CexToRex365VITA.vpk - -# Readme - -Cex To Rex aims to convert a retail console into a Testkit (DEX) console, - -Currently working Testkit features: -Debug Utility -Trophy App "Unlock All" (Doesnt sync, for trophy hacks that sync. check out TropHAX) -Package Installer -Set Auto-Time Off to Never or 60 seconds -Browser app has no "Playstation.com" -PS Store doesnt show up. (can still be added to app.db or launched with psns:) -Both Title Stores. -CMA "Copy Savedata Only" -Show Mode Key Combo (L + R + RIGHT on DPAD + START) -Checker -MiniSettings For QA -Debug Settings -Quick Sign Up -Executing Unsigned Code. (henkaku allready allows this.) - -Currently not working: -Testkit Activation (do we really want this?) -Downgrading.. - -Made in LPP Makes use of VitaRW by Major_Tom, Thx to CelesteBlue for VitaRW_for_lua.bin Thx to: notzecoxao for the Testkit Spoofer kDump.skprx Thx to Voxel9 for Checker and Debug Settings unlock. Thx to: skgleba for dumping 3.65 DEX Firmware. +# Credits +Silica - All Graphics, Most Code +PSM INSTITUTIONS LLC (aka Silica) - Epic "Intellectual Property Notices" +Princess Of Sleeping - PUP Extractor +TheFlow0 - SPKG Decryptor (modoru) +"FAPS TEAM" / dots_tb - CUTTING EDGE NID TECHNOLOGY!!! NOT YET IN VITASDK/MASTER +zecoaxco - spoof_testkit / memdump diff --git a/app.xml b/app.xml new file mode 100644 index 0000000..20339f5 --- /dev/null +++ b/app.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..ef7f229 --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 2.8) + +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(DEFINED ENV{VITASDK}) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") + else() + message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") + endif() +endif() + +project(CEX2REX) + +include("${VITASDK}/share/vita.cmake" REQUIRED) + +set(VITA_APP_NAME "CEX 2 REX 2.0") +set(VITA_TITLEID "CEX2REX20") + +set(VITA_VERSION "02.00") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -s CATEGORY=gdb") +set(VITA_MAKE_FSELF_FLAGS "${VITA_MAKE_FSELF_FLAGS}") + +include_directories( +) + +link_directories( + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_executable(${PROJECT_NAME} + src/main.c + src/ctrl.c + src/pup.c +) + +target_link_libraries(${PROJECT_NAME} + c + SceLibKernel_stub + SceIofilemgr_stub + SceAppMgr_stub + SceCtrl_stub + SceDisplay_stub + SceVshBridge_stub + SceShellSvc_stub + ScePower_stub + SceRegistryMgr_stub + Cex2Rex_User_stub_weak + taihen_stub +) + +vita_create_self(eboot.bin ${PROJECT_NAME} UNSAFE) + +vita_create_vpk(${PROJECT_NAME}.vpk ${VITA_TITLEID} eboot.bin + VERSION ${VITA_VERSION} + NAME ${VITA_APP_NAME} + + FILE sce_sys/icon0.png sce_sys/icon0.png + FILE sce_sys/livearea/contents/bg.png sce_sys/livearea/contents/bg.png + FILE sce_sys/livearea/contents/template.xml sce_sys/livearea/contents/template.xml + FILE user.suprx user.suprx + FILE kernel.skprx kernel.skprx + FILE kmspico.skprx kmspico.skprx + FILE testkit.skprx testkit.skprx + FILE vitaConfig.txt vitaConfig.txt + FILE pstvConfig.txt pstvConfig.txt + FILE app.info app.info +) diff --git a/app/app.info b/app/app.info new file mode 100644 index 0000000..ad03e97 Binary files /dev/null and b/app/app.info differ diff --git a/app/pstvConfig.txt b/app/pstvConfig.txt new file mode 100644 index 0000000..d860c2f --- /dev/null +++ b/app/pstvConfig.txt @@ -0,0 +1,120 @@ +load os0:kd/clockgen.skprx + +load os0:kd/idstorage.skprx + +load os0:kd/ctrl.skprx +load os0:kd/touch_dummy.skprx +load os0:kd/motion_dummy.skprx +load os0:kd/codec.skprx +load os0:kd/audio.skprx +load os0:kd/hpremote.skprx +load os0:kd/power.skprx + +load os0:kd/usbd.skprx +load os0:kd/udcd.skprx +load os0:kd/usbserv.skprx +load os0:kd/usbserial.skprx +load os0:kd/usbmtp.skprx +load os0:kd/mtpif.skprx + +load os0:kd/post_ss_mgr.skprx +load os0:kd/update_mgr.skprx +load os0:kd/usbstor.skprx +load os0:kd/usbstorvstor.skprx +load os0:kd/usbpspcm.skprx +- load ur0:tai/testkit.skprx +load os0:kd/regmgr.skprx + +if USB_ENUM_WAKEUP +load os0:kd/enum_wakeup.skprx +else + +load os0:kd/vnz_wrapper.skprx +- load os0:kd/mgkeymgr.skprx + +load os0:kd/error.skprx + +load os0:kd/npdrm.skprx + +load os0:kd/ulobjmgr.skprx + +load os0:kd/net_ps.skprx +load os0:kd/gps.skprx +load os0:kd/bbmc.skprx +load os0:kd/wlanbt.skprx +load os0:kd/usb_ether_smsc.skprx +load os0:kd/usb_ether_rtl.skprx +load os0:kd/bt.skprx + +- load os0:kd/magicgate.skprx +- load os0:kd/usbstormg.skprx +- load os0:kd/mgvideo.skprx + +load os0:kd/avcodec.skprx +load os0:kd/audioin.skprx +load os0:kd/ngs.skprx +load os0:kd/ds3.skprx +load os0:kd/usbaudio.skprx +if SAFE_MODE +load os0:kd/umass.skprx +endif +load os0:kd/hid.skprx + +load os0:kd/gpu_es4.skprx +load os0:kd/gpuinit_es4.skprx + +- load os0:kd/compat.skprx +load os0:kd/camera_dummy.skprx +load os0:kd/coredump.skprx + +if BSOD_REBOOT +load os0:kd/crashdump.skprx +endif + +load os0:kd/av_config.skprx +load os0:kd/fios2.skprx +load os0:kd/pfsmgr.skprx +load os0:kd/appmgr.skprx + +load os0:kd/sysmodule.skprx +load os0:kd/vshbridge.skprx +load os0:kd/marlin_hci.skprx +load os0:kd/krm.skprx +- load os0:kd/tty2uart.skprx + +umount_bootfs + +if MANUFACTURING_MODE +- spawnwait sd0:psp2diag.self +- spawnwait ux0:psp2diag.self +endif + +if SAFE_MODE +spawn os0:ue/safemode.self +end +endif + +if UPDATE_MODE +if UD0_EXIST +spawn ud0:PSP2UPDATE/psp2swu.self +else +spawn ur0:PSP2UPDATE/psp2swu.self +endif +end +endif + +- load ur0:tai/taihen.skprx +- load ur0:tai/henkaku.skprx +- load ur0:tai/kmspico.skprx + +- appspawn vs0:vsh/shell/shell.self SHELL_BUDGET_ID + +endif +end + +# Local variables: +# mode: c +# tab-width: 4 +# c-basic-offset: 4 +# coding: utf-8 +# End: diff --git a/app/sce_sys/icon0.png b/app/sce_sys/icon0.png new file mode 100644 index 0000000..135de73 Binary files /dev/null and b/app/sce_sys/icon0.png differ diff --git a/app/sce_sys/livearea/contents/bg.png b/app/sce_sys/livearea/contents/bg.png new file mode 100644 index 0000000..70ff09f Binary files /dev/null and b/app/sce_sys/livearea/contents/bg.png differ diff --git a/app/sce_sys/livearea/contents/template.xml b/app/sce_sys/livearea/contents/template.xml new file mode 100644 index 0000000..bf0c200 --- /dev/null +++ b/app/sce_sys/livearea/contents/template.xml @@ -0,0 +1,157 @@ + + + + + bg.png + + + + + ja + psm_manual:ux0:psm/CEXR20202 + + | 知的財産の表記 | + + + + en + psm_manual:ux0:psm/CEXR20202 + + | Intellectual Property Notices | + + + + fr + psm_manual:ux0:psm/CEXR20202 + + | Avis de propriété intellectuelle | + + + + es + psm_manual:ux0:psm/CEXR20202 + + | Avisos sobre propiedad intelectual | + + + + de + psm_manual:ux0:psm/CEXR20202 + + | Geistiges Eigentum | + + + + it + psm_manual:ux0:psm/CEXR20202 + + | Avvisi sulla proprietà intellettuale | + + + + nl + psm_manual:ux0:psm/CEXR20202 + + | Intellectuele eigendomsmeldingen | + + + + pt + psm_manual:ux0:psm/CEXR20202 + + | Avisos de propriedade intelectual | + + + + ru + psm_manual:ux0:psm/CEXR20202 + + | Уведомления об интеллектуальной собственности | + + + + ko + psm_manual:ux0:psm/CEXR20202 + + | 지적 재산권 표기 | + + + + ch + psm_manual:ux0:psm/CEXR20202 + + | 知識產權資訊 | + + + + zh + psm_manual:ux0:psm/CEXR20202 + + | 知识产权信息 | + + + + fi + psm_manual:ux0:psm/CEXR20202 + + | Immateriaalioikeudelliset huomautukset | + + + + sv + psm_manual:ux0:psm/CEXR20202 + + | Meddelande om upphovsrätt | + + + + da + psm_manual:ux0:psm/CEXR20202 + + | Meddelelser om immateriel ejendomsret | + + + + no + psm_manual:ux0:psm/CEXR20202 + + | Opphavsrettvarsel | + + + + pl + psm_manual:ux0:psm/CEXR20202 + + | Informacje dotyczące własności intelektualnej | + + + + pt-br + psm_manual:ux0:psm/CEXR20202 + + | Avisos de propriedade intelectual | + + + + en-gb + psm_manual:ux0:psm/CEXR20202 + + | Intellectual Property Notices | + + + + tr + psm_manual:ux0:psm/CEXR20202 + + | Fikri Mülkiyet Bildirimleri | + + + + psm_manual:ux0:psm/CEXR20202 + + | Intellectual Property Notices | + + + + + diff --git a/app/src/ctrl.c b/app/src/ctrl.c new file mode 100644 index 0000000..e7d50d1 --- /dev/null +++ b/app/src/ctrl.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +#define printf psvDebugScreenPrintf + +int get_key(int type) { + + + SceCtrlData pad; + + if(type == 0){ + + while (1) { + //memset(&pad, 0, sizeof(pad)); + sceCtrlPeekBufferPositive(0, &pad, 1); + + if (pad.buttons != 0) + return pad.buttons; + + sceKernelDelayThread(1000); // 1ms + } + + }else{ + + while (1) { + + //memset(&pad, 0, sizeof(pad)); + sceCtrlPeekBufferPositive(0, &pad, 1); + if(pad.buttons == 0){ + + break; + + } + + sceKernelDelayThread(1000); // 1ms + + } + + } + + return 0; + +} + + +void press_exit(void) { + + get_key(1); + + printf("Press any key to exit this application.\n"); + + get_key(0); + + sceKernelExitProcess(0); + +} \ No newline at end of file diff --git a/app/src/ctrl.h b/app/src/ctrl.h new file mode 100644 index 0000000..7c21e14 --- /dev/null +++ b/app/src/ctrl.h @@ -0,0 +1,2 @@ +int get_key(int type); +void press_exit(void); \ No newline at end of file diff --git a/app/src/debugScreen.h b/app/src/debugScreen.h new file mode 100644 index 0000000..e06ce5d --- /dev/null +++ b/app/src/debugScreen.h @@ -0,0 +1,184 @@ +#ifndef DEBUG_SCREEN_H +#define DEBUG_SCREEN_H + +#include +#include +#include +#include + + +typedef struct PsvDebugScreenFont { + unsigned char* glyphs, width, height, first, last, size_w, size_h; +} PsvDebugScreenFont; + +#include "debugScreenFont.c" + +#define SCREEN_WIDTH (960) +#define SCREEN_HEIGHT (544) +#define SCREEN_FB_WIDTH (960) +#define SCREEN_FB_SIZE (2 * 1024 * 1024) //Must be 256KB aligned +#ifndef SCREEN_TAB_SIZE /* this allow easy overriding */ +#define SCREEN_TAB_SIZE (8) +#endif +#define SCREEN_TAB_W ((F.size_w) * SCREEN_TAB_SIZE) +#define F psvDebugScreenFont + +#define FROM_GREY(c ) ((((c)*9) <<16) | (((c)*9) <<8) | ((c)*9)) +#define FROM_3BIT(c,dark) (((!!((c)&4))<<23) | ((!!((c)&2))<<15) | ((!!((c)&1))<<7) | (dark ? 0 : 0x7F7F7F)) +#define FROM_6BIT(c ) ((((c)%6)*(51<<16)) | ((((c)/6)%6)*(51<<8)) | ((((c)/36)%6)*51)) +#define FROM_FULL(r,g,b ) ((r<<16) | (g<<8) | (b)) +#define CLEARSCRN(H,toH,W,toW) for(int h = H; h < toH; h++)for(int w = W; w < toW; w++)((uint32_t*)base)[h*SCREEN_FB_WIDTH + w] = colorBg; + +static int mutex, coordX, savedX, coordY, savedY; +static uint32_t defaultFg = 0xFFFFFFFF, colorFg = 0xFFFFFFFF; +static uint32_t defaultBg = 0xFF000000, colorBg = 0xFF000000; + + +#ifdef __vita__ +#include +#include +#include +static void* base; // pointer to frame buffer +#else +#define sceKernelLockMutex(m,v,x) m=v +#define sceKernelUnlockMutex(m,v) m=v +static char base[SCREEN_FB_WIDTH * SCREEN_HEIGHT * 4]; +#endif + +static size_t psvDebugScreenEscape(const unsigned char *str) { + for(unsigned i = 0, argc = 0, arg[32] = {0}; argc < (sizeof(arg)/sizeof(*arg)) && str[i]!='\0'; i++) + switch(str[i]) { + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + arg[argc]=(arg[argc]*10) + (str[i] - '0');continue; + case ';': argc++;continue; + case 's': savedX = coordX; savedY = coordY; return i; + case 'u': coordX = savedX; coordY = savedY; return i; + case 'A': coordY -= arg[0] * (F.size_h); return i; + case 'B': coordY += arg[0] * (F.size_h); return i; + case 'C': coordX += arg[0] * (F.size_w); return i; + case 'D': coordX -= arg[0] * (F.size_w); return i; + case 'E': coordY += arg[0] * (F.size_h); coordX = 0; return i; + case 'F': coordY -= arg[0] * (F.size_h); coordX = 0; return i; + case 'G': coordX = (arg[0]-1) * (F.size_w); return i; + case 'H': + case 'f': coordY = (arg[0]-1) * (F.size_h); + coordX = (arg[1]-1) * (F.size_w); return i; + case 'J': //clear part of (J=screen, K=Line) so J code reuse part of K + case 'K': if(arg[0]==0)CLEARSCRN(coordY, coordY + F.size_h, coordX, SCREEN_WIDTH);//from curosr to end + if(arg[0]==1)CLEARSCRN(coordY, coordY + F.size_h, 0, coordX);//from begining to cursor + if(arg[0]==2)CLEARSCRN(coordY, coordY + F.size_h, 0, SCREEN_WIDTH);//whole line + if(str[i]=='K')return i; + if(arg[0]==0)CLEARSCRN(coordY, SCREEN_HEIGHT, 0, SCREEN_WIDTH); + if(arg[0]==1)CLEARSCRN(0, coordY, 0, SCREEN_WIDTH); + if(arg[0]==2)CLEARSCRN(0, SCREEN_HEIGHT, 0, SCREEN_WIDTH); + return i; + case 'm':// Color + if(!arg[0]) {arg[0] = 39;arg[1] = 49;argc = 1;}//no/0 args == reset BG + FG + for(unsigned c = 0; c <= argc; c++) { + uint32_t unit = arg[c] % 10, mode = arg[c] / 10, *color = mode&1 ? &colorFg : &colorBg; + if (arg[c]==1)colorFg|=0x808080; + if (arg[c]==2)colorFg&=0x7F7F7F; + if (mode!=3 && mode!=4 && mode!=9 && mode!=10)continue;//skip unsported modes + if (unit == 9){ // reset FG or BG + *color = mode&1 ? defaultFg : defaultBg; + } else if ((unit==8) && (arg[c+1]==5)) { // 8bit : [0-15][16-231][232-256] color map + c+=2;*color = arg[c]<=15?FROM_3BIT(arg[c],mode<9):arg[c]>=232?FROM_GREY(arg[c]-232):FROM_6BIT(arg[c]-16); + } else if ((unit==8) && (arg[c+1]==2)) { // 24b color space + *color = FROM_FULL(arg[c+4], arg[c+3], arg[c+2]);c+=4; + } else *color = FROM_3BIT(unit,mode<9); // standard 8+8 colors + } + return i; + } + return 0; +} +int psvDebugScreenInit() { + mutex = sceKernelCreateMutex("log_mutex", 0, 0, NULL); + SceUID displayblock = sceKernelAllocMemBlock("display", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, SCREEN_FB_SIZE, NULL); + sceKernelGetMemBlockBase(displayblock, (void**)&base); + SceDisplayFrameBuf frame = { sizeof(frame), base, SCREEN_FB_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; + //reset X/Y + coordX = 0; + coordY = 0; + return sceDisplaySetFrameBuf(&frame, SCE_DISPLAY_SETBUF_NEXTFRAME); +} + +int psvDebugScreenPuts(const char * _text) { + const unsigned char*text = (const unsigned char*)_text; + int bytes_per_glyph = (F.width * F.height) / 8; + sceKernelLockMutex(mutex, 1, NULL); + int c; + for (c = 0; text[c] ; c++) { + unsigned char t = text[c]; + if (t == '\t') { + coordX += SCREEN_TAB_W - coordX % SCREEN_TAB_W; + continue; + } + if (coordX + F.width > SCREEN_WIDTH) { + coordY += F.size_h; + coordX = 0; + } + if (coordY + F.height > SCREEN_HEIGHT) { + coordX = coordY = 0; + } + if (t == '\n') { + coordX = 0; + coordY += F.size_h; + continue; + } else if (t == '\r') { + coordX = 0; + continue; + } else if ((t == '\e') && (text[c+1] == '[')) { + c += psvDebugScreenEscape(text + c + 2) + 2; + if(coordX < 0)coordX = 0;// CSI position are 1-based, + if(coordY < 0)coordY = 0;// prevent 0-based coordiate from producing a negativ X/Y + continue; + }else if ((t > F.last) || (t < F.first)) + continue; // skip non printable glyph + uint32_t *vram = ((uint32_t*)base) + coordX + coordY * SCREEN_FB_WIDTH; + uint8_t *font = &F.glyphs[ (t - F.first) * bytes_per_glyph]; + for (int row = 0, mask = 1 << 7; row < F.height; row++, vram += SCREEN_FB_WIDTH) { + for (uint32_t *pixel = vram, col = 0; col < F.width ; col++, mask>>=1) { + if (!mask) {font++; mask = 1 << 7;}// no more mask : we exausted this byte + *pixel++ = (*font&mask)?colorFg:colorBg; + } + for (uint32_t *pixel = vram + F.width, col = F.width; col < F.size_w ; col++) + *pixel++ = colorBg;// right margin + } + for (int row = F.height; row < F.size_h; row++, vram += SCREEN_FB_WIDTH) + for (uint32_t *pixel = vram, col = 0; col < F.size_w ; col++) + *pixel++ = colorBg;// bottom margin + coordX += F.size_w; + } + sceKernelUnlockMutex(mutex, 1); + return c; +} + +__attribute__((__format__ (__printf__, 1, 2))) +int psvDebugScreenPrintf(const char *format, ...) { + char buf[4096]; + + va_list opt; + va_start(opt, format); + int ret = vsnprintf(buf, sizeof(buf), format, opt); + psvDebugScreenPuts(buf); + va_end(opt); + + return ret; +} + +void psvDebugScreenSetFgColor(uint32_t rgb){ + psvDebugScreenPrintf("\e[38;2;%lu;%lu;%lum", (rgb>>16)&0xFF, (rgb>>8)&0xFF, rgb&0xFF); +} +void psvDebugScreenSetBgColor(uint32_t rgb){ + psvDebugScreenPrintf("\e[48;2;%lu;%lu;%lum", (rgb>>16)&0xFF, (rgb>>8)&0xFF, rgb&0xFF); +} +void psvDebugScreenClear(){ + psvDebugScreenPrintf(" "); + psvDebugScreenPrintf(" "); + psvDebugScreenPrintf(" "); + psvDebugScreenPrintf(" "); + coordX = 0; + coordY = 0; +} +#undef F +#endif diff --git a/app/src/debugScreenFont.c b/app/src/debugScreenFont.c new file mode 100644 index 0000000..cc7f41c --- /dev/null +++ b/app/src/debugScreenFont.c @@ -0,0 +1,111 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * font.c - Debug Font. + * + * Copyright (c) 2005 Marcus R. Brown + * Copyright (c) 2005 James Forshaw + * Copyright (c) 2005 John Kelley + * + * $Id: font.c 540 2005-07-08 19:35:10Z warren $ + */ + +PsvDebugScreenFont psvDebugScreenFont = { glyphs:(unsigned char*) +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // +"\x01\x80\x03\xC0\x03\xC0\x03\xC0\x03\xC0\x03\xC0\x03\xC0\x03\xC0\x03\xC0\x03\x80\x01\x80\x01\x80\x01\x80\x00\x00\x00\x00\x01\x80\x03\xC0\x03\xC0\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ! +"\x00\x00\x00\x00\x06\x30\x06\x30\x0C\x60\x0C\x60\x0E\x70\x0E\x70\x06\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // " +"\x00\x00\x00\x00\x03\x18\x03\x18\x07\x38\x07\x38\x3F\xFC\x3F\xFC\x06\x70\x0E\x70\x0E\x70\x0E\x60\x3F\xFC\x3F\xFC\x1C\xE0\x1C\xE0\x1C\xC0\x18\xC0\x18\xC0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // # +"\x01\x80\x01\x80\x07\xC0\x1F\xF0\x1F\xF8\x3D\xB8\x39\xB8\x39\x98\x3D\x80\x1F\x80\x0F\xF0\x03\xF8\x01\xBC\x31\x9C\x39\x9C\x39\x9C\x3D\xB8\x1F\xF8\x07\xE0\x01\x80\x01\x80\x01\x80\x00\x00\x00\x00" // $ +"\x00\x00\x78\x10\xF8\x30\xCC\x20\xCC\x60\xCC\x40\xCC\xC0\xCC\x80\x79\x80\x01\x3C\x03\x66\x02\x66\x06\x66\x0C\x66\x0C\x66\x18\x3C\x10\x3C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // % +"\x00\x00\x00\x00\x00\x00\x00\x00\x07\x80\x0F\xC0\x1C\xE0\x1C\xE0\x1C\xE0\x0F\xC0\x07\x00\x1F\x08\x3B\x9C\x71\xD8\x71\xF8\x70\xF0\x78\xFC\x3F\xDE\x0F\x8C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // & +"\x00\xE0\x00\xC0\x01\xC0\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ' +"\x00\x40\x00\xC0\x01\xC0\x01\x80\x03\x80\x03\x80\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x03\x80\x03\x80\x01\x80\x01\xC0\x00\xC0\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00" // ( +"\x02\x00\x03\x00\x03\x80\x01\x80\x01\xC0\x01\xC0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x01\xC0\x01\xC0\x01\x80\x03\x80\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ) +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\x00\xC0\x00\xC0\x06\xD8\x07\xF8\x00\xC0\x01\xE0\x03\x30\x03\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // * +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x01\x80\x01\x80\x01\x80\x1F\xF8\x1F\xF8\x01\x80\x01\x80\x01\x80\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // + +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x80\x03\x80\x01\x80\x01\x80\x03\x00\x00\x00\x00\x00" // , +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0F\xF0\x0F\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // - +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // . +"\x00\x30\x00\x70\x00\x70\x00\x60\x00\xE0\x00\xE0\x00\xE0\x00\xC0\x01\xC0\x01\xC0\x01\xC0\x01\x80\x03\x80\x03\x80\x03\x80\x03\x00\x07\x00\x07\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // / +"\x00\x00\x07\xE0\x0F\xF0\x1F\xF8\x1C\x38\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x1C\x38\x1F\xF8\x0F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 0 +"\x00\x00\x00\x60\x00\xE0\x01\xE0\x03\xE0\x07\xE0\x1F\xE0\x1C\xE0\x18\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 1 +"\x00\x00\x07\xE0\x1F\xF8\x1F\xF8\x3C\x3C\x38\x1C\x38\x1C\x00\x1C\x00\x38\x00\x78\x00\xF0\x03\xE0\x07\x80\x0F\x00\x1E\x00\x3C\x00\x3F\xF8\x3F\xFC\x3F\xFC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 2 +"\x00\x00\x07\xE0\x0F\xF0\x1F\xF8\x3C\x78\x38\x38\x00\x38\x00\x78\x01\xF0\x01\xF0\x00\xF8\x00\x3C\x30\x1C\x38\x1C\x38\x3C\x3C\x78\x1F\xF8\x0F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 3 +"\x00\x00\x00\x60\x00\xF0\x00\xF0\x01\xF0\x03\xF0\x03\x70\x07\x70\x0E\x70\x0C\x70\x1C\x70\x38\x70\x38\x70\x3F\xFC\x3F\xFC\x00\x70\x00\x70\x00\x70\x00\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 4 +"\x00\x00\x1F\xFC\x1F\xFC\x1F\xF8\x1C\x00\x1C\x00\x1C\x00\x1F\xE0\x1F\xF0\x1F\xF8\x1C\x3C\x00\x1C\x00\x1C\x00\x1C\x38\x1C\x3C\x38\x3F\xF8\x1F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 5 +"\x00\x00\x03\xE0\x0F\xF0\x1F\xF8\x1C\x38\x3C\x18\x38\x00\x38\x00\x3B\xE0\x3F\xF0\x3F\xF8\x3C\x3C\x38\x1C\x38\x1C\x38\x1C\x1C\x3C\x1F\xF8\x0F\xF0\x03\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 6 +"\x00\x00\x3F\xFC\x3F\xFC\x1F\xFC\x00\x38\x00\x70\x00\x70\x00\xE0\x01\xC0\x01\xC0\x03\x80\x03\x80\x03\x80\x07\x80\x07\x00\x07\x00\x07\x00\x07\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 7 +"\x00\x00\x07\xE0\x0F\xF0\x1F\xF8\x1E\x78\x1C\x38\x1C\x38\x1E\x78\x0F\xF0\x0F\xF0\x1C\x38\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x3C\x3C\x1F\xF8\x0F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 8 +"\x00\x00\x07\xC0\x0F\xF0\x1F\xF8\x3C\x38\x38\x1C\x38\x1C\x38\x1C\x3C\x3C\x1F\xFC\x0F\xFC\x07\xDC\x00\x1C\x00\x1C\x18\x3C\x1C\x38\x1F\xF8\x0F\xF0\x07\xC0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 9 +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // : +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x80\x03\x80\x01\x80\x01\x80\x03\x00\x02\x00\x00\x00" // ; +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x38\x00\xF8\x03\xF8\x0F\xC0\x1F\x00\x1C\x00\x1F\x00\x0F\xC0\x03\xF8\x00\xF8\x00\x38\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // < +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3F\xFC\x3F\xFC\x3F\xFC\x00\x00\x00\x00\x3F\xFC\x3F\xFC\x3F\xFC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // = +"\x00\x00\x00\x00\x00\x00\x10\x00\x1C\x00\x1F\x00\x1F\xC0\x03\xF0\x00\xF8\x00\x38\x00\xF8\x03\xF0\x1F\xC0\x1F\x00\x1C\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // > +"\x07\xC0\x0F\xF0\x1F\xF0\x3C\x78\x38\x38\x38\x38\x30\x38\x00\x70\x00\xF0\x01\xE0\x03\xC0\x03\x80\x03\x80\x01\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ? +"\x00\x00\x00\x00\x00\x00\x00\x00\x03\xE0\x0F\xF8\x1C\x1C\x10\x04\x23\xB6\x27\xF2\x4C\x72\x5C\x62\x58\x62\x58\x62\x58\x64\x58\xEC\x6F\xF8\x27\x70\x30\x06\x18\x0C\x0F\xFC\x03\xF0\x00\x00\x00\x00" // @ +"\x00\x00\x00\x00\x01\x80\x03\xC0\x03\xC0\x07\xE0\x07\xE0\x0E\x60\x0E\x70\x0E\x70\x1C\x78\x1C\x38\x1C\x38\x3F\xFC\x3F\xFC\x38\x1C\x70\x0E\x70\x0E\x60\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // A +"\x00\x00\x00\x00\x3F\xE0\x3F\xF0\x38\x78\x38\x38\x38\x38\x38\x38\x38\x38\x3F\xF0\x3F\xF0\x38\x38\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x3C\x3F\xF8\x3F\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // B +"\x00\x00\x00\x00\x07\xE0\x0F\xF0\x1E\x78\x3C\x3C\x38\x1C\x78\x0C\x70\x00\x70\x00\x70\x00\x70\x00\x70\x0C\x70\x0C\x38\x1C\x3C\x3C\x1E\x78\x0F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // C +"\x00\x00\x00\x00\x3F\xC0\x3F\xF0\x38\xF0\x38\x78\x38\x38\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x38\x38\x78\x38\xF0\x3F\xF0\x3F\xC0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // D +"\x00\x00\x00\x00\x1F\xFC\x1F\xFC\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1F\xF8\x1F\xF8\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1F\xFC\x1F\xFC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // E +"\x00\x00\x00\x00\x0F\xFC\x0F\xFC\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0F\xF8\x0F\xF8\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // F +"\x00\x00\x00\x00\x03\xE0\x0F\xF8\x1C\x3C\x38\x1C\x38\x0E\x70\x0C\x70\x00\x70\x00\x70\xFE\x70\xFE\x70\x0E\x70\x0E\x38\x0E\x38\x0E\x1C\x3E\x0F\xFC\x03\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // G +"\x00\x00\x00\x00\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x3F\xFC\x3F\xFC\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // H +"\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // I +"\x00\x00\x00\x00\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x00\xE0\x70\xE0\x70\xE0\x70\xE0\x79\xE0\x3F\xC0\x3F\xC0\x0F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // J +"\x00\x00\x00\x00\x38\x0C\x38\x1C\x38\x3C\x38\x78\x38\xF0\x39\xE0\x3B\xC0\x3F\xC0\x3F\xE0\x3E\xF0\x3C\x70\x38\x78\x38\x3C\x38\x3C\x38\x1E\x38\x0E\x38\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // K +"\x00\x00\x00\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1F\xF8\x1F\xF8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // L +"\x00\x00\x00\x00\xF8\x1F\xF8\x1F\xFC\x3F\xFC\x3F\xFC\x3F\xEC\x37\xEE\x77\xEE\x77\xEE\x77\xE6\x67\xE7\xE7\xE7\xE7\xE7\xE7\xE3\xC7\xE3\xC7\xE3\xC7\xE1\x87\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // M +"\x00\x00\x00\x00\x18\x1C\x3C\x1C\x3C\x1C\x3E\x1C\x3E\x1C\x3F\x1C\x3B\x1C\x3B\x9C\x39\x9C\x39\xDC\x38\xDC\x38\xFC\x38\x7C\x38\x7C\x38\x3C\x38\x3C\x38\x1C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // N +"\x00\x00\x00\x00\x07\xE0\x0F\xF0\x1F\xF8\x3C\x3C\x38\x1C\x78\x1E\x70\x0E\x70\x0E\x70\x0E\x70\x0E\x70\x0E\x78\x1E\x38\x1C\x3C\x3C\x1F\xF8\x0F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // O +"\x00\x00\x00\x00\x3F\xF0\x3F\xF8\x38\x3C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x38\x3F\xF8\x3F\xE0\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // P +"\x00\x00\x00\x00\x07\xE0\x0F\xF0\x1F\xF8\x3C\x3C\x38\x1C\x78\x0E\x70\x0E\x70\x0E\x70\x0E\x70\x0E\x70\x0E\x79\x9E\x38\xFC\x3C\x7C\x1F\xF8\x0F\xFE\x07\xEF\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00" // Q +"\x00\x00\x00\x00\x3F\xF8\x3F\xFC\x38\x1E\x38\x0E\x38\x0E\x38\x0E\x38\x1E\x3F\xFC\x3F\xF0\x38\xE0\x38\x70\x38\x78\x38\x3C\x38\x3C\x38\x1E\x38\x0E\x38\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // R +"\x00\x00\x00\x00\x07\xE0\x1F\xF0\x1C\x38\x38\x38\x38\x18\x3C\x00\x3F\x00\x1F\xE0\x0F\xF8\x01\xF8\x00\x3C\x30\x1C\x38\x1C\x38\x1C\x3C\x38\x1F\xF8\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // S +"\x00\x00\x00\x00\x7F\xFC\x7F\xFC\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // T +"\x00\x00\x00\x00\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x3C\x38\x1F\xF8\x0F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // U +"\x00\x00\x00\x00\x38\x06\x38\x0E\x38\x0E\x1C\x1C\x1C\x1C\x1C\x1C\x0E\x18\x0E\x38\x0E\x38\x0E\x30\x07\x70\x07\x70\x07\x60\x03\xE0\x03\xE0\x03\xC0\x01\xC0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // V +"\x00\x00\x00\x00\xC1\x83\xC3\xC3\xE3\xC7\xE3\xC7\xE3\xC7\x63\xC6\x66\x66\x66\x66\x76\x6E\x76\x6E\x36\x6C\x3C\x3C\x3C\x3C\x3C\x3C\x3C\x3C\x1C\x38\x18\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // W +"\x00\x00\x00\x00\x30\x0C\x38\x1E\x3C\x1C\x1C\x3C\x1E\x78\x0F\xF0\x07\xF0\x07\xE0\x03\xC0\x07\xE0\x0F\xF0\x1F\xF8\x1E\x78\x3C\x3C\x78\x1E\x78\x1E\x70\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // X +"\x00\x00\x00\x00\x30\x18\x78\x1C\x38\x38\x3C\x38\x1C\x70\x1E\xF0\x0E\xE0\x07\xC0\x07\xC0\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // Y +"\x00\x00\x00\x00\x3F\xF8\x3F\xF8\x00\x78\x00\x78\x00\xF0\x01\xF0\x01\xE0\x03\xC0\x07\x80\x07\x80\x0F\x00\x1E\x00\x1E\x00\x3C\x00\x78\x00\x7F\xFC\x7F\xFC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // Z +"\x00\x00\x01\xE0\x01\xE0\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\xE0\x01\xE0\x00\x00\x00\x00" // [ +"\x00\x00\x00\x00\x0C\x00\x1E\x00\x0E\x00\x0F\x00\x07\x00\x07\x00\x07\x80\x03\x80\x03\x80\x03\xC0\x01\xC0\x01\xC0\x01\xE0\x00\xE0\x00\xE0\x00\xF0\x00\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // +"\x00\x00\x0F\x80\x0F\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x0F\x80\x0F\x80\x00\x00\x00\x00" // ] +"\x00\x00\x00\x00\x03\x80\x07\x80\x07\x80\x07\xC0\x0E\xC0\x0C\xE0\x1C\xE0\x1C\x60\x38\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ^ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00" // _ +"\x00\x00\x00\x00\x1C\x00\x3E\x00\x63\x00\x63\x00\x63\x00\x3E\x00\x1C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ` +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0F\xC0\x1F\xE0\x18\x70\x10\x70\x00\xF0\x0F\xF0\x1E\x70\x38\x70\x38\x70\x38\xF0\x1F\xF0\x0E\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // a +"\x00\x00\x00\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1C\x00\x1D\xF0\x1F\xF8\x1E\x38\x1E\x1C\x1C\x1C\x1C\x1C\x1C\x1C\x1C\x1C\x1E\x1C\x1E\x38\x1F\xF8\x1D\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // b +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xC0\x0F\xF0\x1C\x70\x3C\x38\x38\x10\x38\x00\x38\x00\x38\x10\x3C\x38\x1C\x78\x0F\xF0\x07\xC0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // c +"\x00\x00\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x0F\xB8\x1F\xF8\x1C\x78\x38\x78\x38\x38\x38\x38\x38\x38\x38\x38\x38\x78\x1C\x78\x1F\xF8\x07\xB8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // d +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xC0\x0F\xE0\x1C\x70\x38\x38\x38\x38\x3F\xF8\x3F\xF0\x38\x00\x38\x10\x1C\x38\x0F\xF0\x07\xC0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // e +"\x00\x00\x00\x00\x03\xE0\x07\xE0\x07\x00\x07\x00\x07\x00\x1F\xC0\x1F\xC0\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // f +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0F\xB8\x1F\xF8\x1C\x78\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x1C\x78\x1F\xF8\x07\xB8\x10\x38\x38\x38\x1C\x70\x1F\xF0\x07\xC0" // g +"\x00\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3B\xC0\x3F\xE0\x3C\xF0\x38\x70\x38\x70\x38\x70\x38\x70\x38\x70\x38\x70\x38\x70\x38\x70\x38\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // h +"\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // i +"\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x1F\x80\x1F\x00" // j +"\x00\x00\x00\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x18\x0E\x38\x0E\x70\x0E\xE0\x0F\xC0\x0F\xE0\x0F\x70\x0E\x70\x0E\x38\x0E\x38\x0E\x1C\x0E\x0C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // k +"\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // l +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xEF\x9E\xFF\xFF\xF1\xE7\xE1\xC7\xE1\xC7\xE1\xC7\xE1\xC7\xE1\xC7\xE1\xC7\xE1\xC7\xE1\xC7\xE1\xC7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // m +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1D\xE0\x1F\xF0\x1E\x78\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // n +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0F\x80\x1F\xC0\x38\xE0\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x38\xE0\x1F\xC0\x0F\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // o +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3B\xC0\x3F\xF0\x3C\x70\x3C\x38\x38\x38\x38\x38\x38\x38\x38\x38\x3C\x38\x3C\x70\x3F\xF0\x3B\xC0\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00" // p +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xB8\x1F\xF8\x1C\x78\x38\x78\x38\x38\x38\x38\x38\x38\x38\x38\x38\x78\x1C\x78\x1F\xF8\x07\xB8\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38" // q +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0E\xE0\x0F\xF0\x0F\x10\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // r +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xC0\x0F\xF0\x1C\x70\x1C\x30\x1F\x00\x0F\xE0\x03\xF0\x00\x78\x1C\x38\x1E\x38\x0F\xF0\x07\xE0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // s +"\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x07\xE0\x0F\xE0\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\xF0\x01\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // t +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1C\x38\x1E\x78\x0F\xF8\x07\xB8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // u +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x18\x1C\x38\x1C\x38\x0C\x30\x0E\x70\x0E\x70\x06\x60\x07\xE0\x03\xC0\x03\xC0\x03\xC0\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // v +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC1\x83\xE3\xC7\xE3\xC7\x63\xC6\x67\xE6\x76\x6E\x36\x6C\x36\x6C\x3E\x7C\x1C\x38\x1C\x38\x1C\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // w +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x38\x3C\x78\x1E\xF0\x0F\xE0\x07\xC0\x07\xC0\x0F\xE0\x0E\xE0\x1E\xF0\x3C\x78\x38\x38\x30\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // x +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x18\x1C\x38\x1C\x38\x0C\x30\x0E\x70\x0E\x70\x06\x60\x07\x60\x07\xE0\x03\xC0\x03\xC0\x03\xC0\x01\x80\x03\x80\x03\x80\x1F\x00\x1E\x00" // y +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3F\xF8\x3F\xF8\x00\x78\x00\xF0\x01\xE0\x03\xC0\x07\x80\x07\x00\x0E\x00\x1E\x00\x3F\xF8\x3F\xF8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // z +"\x00\x70\x00\xF0\x01\xF0\x01\xC0\x01\xC0\x01\xC0\x01\xC0\x01\xC0\x01\xC0\x03\x80\x07\x80\x07\x80\x03\x80\x01\xC0\x01\xC0\x01\xC0\x01\xC0\x01\xC0\x01\xC0\x01\xF0\x00\xF0\x00\x70\x00\x00\x00\x00" // { +"\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00" // | +"\x1C\x00\x1E\x00\x1F\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x03\x80\x03\xC0\x03\xC0\x03\x80\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x1F\x00\x1E\x00\x1C\x00\x00\x00\x00\x00" // } +"\x00\x00\x00\x00\x00\x00\x1E\x08\x3F\xF8\x3F\xF8\x20\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", // ~ +width:16, height:24, first:32, last:126, size_w:16, size_h:24}; \ No newline at end of file diff --git a/app/src/main.c b/app/src/main.c new file mode 100644 index 0000000..bae80d8 --- /dev/null +++ b/app/src/main.c @@ -0,0 +1,525 @@ +#include +#include +#include +#include +#include + +#include + +#include "ctrl.h" +#include "debugScreen.h" +#include "pup.h" + +#define printf psvDebugScreenPrintf + +int ret; +int left = -1; + +int getFileSize(const char *file) { + SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0); + if (fd < 0) + return fd; + int fileSize = sceIoLseek(fd, 0, SCE_SEEK_END); + sceIoClose(fd); + return fileSize; +} + +int WriteFile(char *file, void *buf, int size) { + SceUID fd = sceIoOpen(file, SCE_O_RDWR | SCE_O_CREAT, 0777); + if (fd < 0) + return fd; + + int written = sceIoWrite(fd, buf, size); + + sceIoClose(fd); + return written; +} + +int ReadFile(char *file, void *buf, int size) { + SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0777); + if (fd < 0) + return fd; + + int readed = sceIoRead(fd, buf, size); + + sceIoClose(fd); + return readed; +} + +int CopyFile(char *src, char *dst) +{ + int size = getFileSize(src); + char *data = malloc(size); + memset(data,0,size); + ret = ReadFile(src,data,size); + if(ret < 0){ + psvDebugScreenPrintf("ReadFile() failed. ret = 0x%x\n", ret); + while(1){}; + } + ret = WriteFile(dst,data,size); + if(ret < 0){ + psvDebugScreenPrintf("WriteFile() failed. ret = 0x%x\n", ret); + } + return 0; +} + +void load_modules() +{ + char titleid[12]; + char kplugin_path[0x200]; + char uplugin_path[0x200]; + + sceAppMgrUmount("app0:"); + sceAppMgrAppParamGetString(0, 12, titleid , 256); + + sprintf(kplugin_path, "ux0:app/%s/kernel.skprx", titleid); + sprintf(uplugin_path, "ux0:app/%s/user.suprx", titleid); + printf("kplugin_path: %s\n",kplugin_path); + printf("uplugin_path: %s\n",uplugin_path); + int kernel_modid, user_modid; + + kernel_modid = taiLoadStartKernelModule(kplugin_path, 0, NULL, 0); + if(kernel_modid < 0){ + printf("taiLoadStartKernelModule() failed. ret = 0x%x\n", kernel_modid); + } + user_modid = sceKernelLoadStartModule(uplugin_path, 0, NULL, 0, NULL, NULL); + if(user_modid < 0){ + printf("sceKernelLoadStartModule() failed. ret = 0x%x\n", user_modid); + } + psvDebugScreenClear(0); + return; +} + + +void config() +{ + int spoofer = 0; + int activator = 0; + psvDebugScreenClear(0); + + psvDebugScreenPrintf("Installation Type\n"); + psvDebugScreenPrintf("X: Full Install (spoofer + activator + testkit vsh)\n"); + psvDebugScreenPrintf("O: Warning Message Install (spoofer + testkit vsh)\n"); + psvDebugScreenPrintf("[]: Enso-less Install (testkit vsh)\n"); + + sceKernelDelayThread(100000); + + switch(get_key(0)) { + case SCE_CTRL_CROSS: + activator = 1; + spoofer = 1; + break; + case SCE_CTRL_CIRCLE: + spoofer = 1; + break; + case SCE_CTRL_SQUARE: + break; + default: + sceKernelExitProcess(0); + break; + } + + + psvDebugScreenClear(); + sceIoRemove("ur0:tai/testkit.skprx"); + sceIoRemove("ur0:tai/kmspico.skprx"); + + if(spoofer) + { + psvDebugScreenPrintf("Writing testkit.skprx"); + CopyFile("app0:/testkit.skprx","ur0:tai/testkit.skprx"); + + int pstv = vshSblAimgrIsGenuineDolce(); + if(pstv) + { + CopyFile("app0:/pstvConfig.txt","ur0:tai/boot_config.txt"); + } + else + { + CopyFile("app0:/vitaConfig.txt","ur0:tai/boot_config.txt"); + } + } + + if(activator) + { + psvDebugScreenPrintf("Writing kmspico.skprx"); + CopyFile("app0:/kmspico.skprx","ur0:tai/kmspico.skprx"); + } +} + +void cleanup() +{ + char path[0x1028]; + SceUID dfd = sceIoDopen("ur0:/pup_out"); + if (dfd >= 0) { + int ret = 0; + do { + SceIoDirent dir; + memset(&dir, 0, sizeof(SceIoDirent)); + ret = sceIoDread(dfd, &dir); + if (ret > 0) { + snprintf(path, 0x1028, "ur0:/pup_out/%s", dir.d_name); + sceIoRemove(path); + } + } + while(ret > 0); + } + sceIoRemove("ur0:/vs0.img"); + sceIoRmdir("ur0:/pup_out"); +} + +void lock() +{ + sceShellUtilInitEvents(0); + sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_QUICK_MENU | + SCE_SHELL_UTIL_LOCK_TYPE_POWEROFF_MENU | + SCE_SHELL_UTIL_LOCK_TYPE_USB_CONNECTION | + SCE_SHELL_UTIL_LOCK_TYPE_MC_INSERTED | + SCE_SHELL_UTIL_LOCK_TYPE_MC_REMOVED | + SCE_SHELL_UTIL_LOCK_TYPE_MUSIC_PLAYER | + SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN_2); + scePowerSetCallbackEnabled(0); // Magical NID engineered by FAPS TEAM ;) +} + +void extract() +{ + cleanup(); + psvDebugScreenClear(); + psvDebugScreenPrintf("Extracting DEX.PUP...\n"); + scePlayStartionUpdatePackageExtractStage1("ux0:/DEX.PUP"); +} + +void vercheck() +{ + static char version[16]; + char target_version[16]; + + memset(version, 0x00, 16); + memset(target_version, 0x00, 16); + + psvDebugScreenClear(); + + SceKernelFwInfo data; + data.size = sizeof(SceKernelFwInfo); + + _vshSblGetSystemSwVersion(&data); + + snprintf(version, 16, "%s", data.versionString); + ReadFile("ur0:/pup_out/version.txt",target_version,4); + + if(strcmp(target_version,version) != 0) + { + psvDebugScreenPrintf("ux0:/DEX.PUP version is %s\nBut your current version is %s. cannot continue\nPlease update your console to retail %s first.\nor download the DEX %s.PUP",target_version,version,target_version,version); + sceKernelDelayThread(10000000); + cleanup(); + sceKernelExitProcess(0); + } + +} + +void decrypt() +{ + char path[0x1028]; + char pathout[0x1028]; + + int vs0Count = 0; + int type = 0; + + psvDebugScreenClear(); + psvDebugScreenPrintf("Decrypting DEX.PUP\n"); + + for(int i = 0; i <= 26; i++) + { + memset(path,0x00,0x1028); + memset(pathout,0x00,0x1028); + sprintf(path,"ur0:/pup_out/package_data%02i.pkg",i); + sprintf(pathout,"ur0:/pup_out/pkg-%i.dec",i); + int sz = getFileSize(path); + if(sz > 0) + { + + psvDebugScreenPrintf("Decrypting %s\n",path); + int ret = DecryptSpkgFile(path,pathout); + if(ret < 0) + { + psvDebugScreenClear(); + psvDebugScreenPrintf("Error decrypting %s",path); + sceKernelDelayThread(10000000); + cleanup(); + sceKernelExitProcess(0); + } + sceIoRemove(path); + + int fd = sceIoOpen(pathout, SCE_O_RDONLY, 0777); + sceIoLseek(fd,0x404,SCE_SEEK_SET); + sceIoRead(fd,&type, sizeof(int)); + sceIoClose(fd); + + if(type == 0x0A) + { + char newName[0x1028]; + memset(newName,0x00,0x1028); + sprintf(newName,"ur0:/pup_out/vs0-%i.dec",vs0Count); + sceIoRename(pathout, newName); + vs0Count += 1; + } + sceIoRemove(pathout); + + } + + } + return; +} + +void join() +{ + psvDebugScreenClear(); + psvDebugScreenPrintf("Concatenating package data...\n"); + char path[0x1028]; + int fd = 0; + int sz = 0; + char buffer[0x8000]; + int vs0Img = sceIoOpen("ur0:/vs0.img", SCE_O_RDWR | SCE_O_CREAT, 0777); + + for(int i = 0; i <= 26; i++) + { + memset(path,0x00,0x1028); + sprintf(path,"ur0:/pup_out/vs0-%i.dec",i); + psvDebugScreenPrintf("Adding %s to vs0.img\n",path); + + sz = getFileSize(path) - 0x480; + + fd = sceIoOpen(path,SCE_O_RDONLY, 0777); + sceIoLseek(fd, 0x480, SCE_SEEK_SET); + + while(!(sz <= 0)) + { + memset(buffer,0x00,0x8000); + if(sz < 0x8000) + { + sceIoRead(fd, buffer, sz); + ret = sceIoWrite(vs0Img, buffer, sz); + sz -= sz; + } + else + { + sceIoRead(fd, buffer, 0x8000); + ret = sceIoWrite(vs0Img, buffer, 0x8000); + sz -= 0x8000; + } + } + sceIoClose(fd); + sceIoRemove(path); + + } + sceIoClose(vs0Img); + psvDebugScreenClear(); +} + +void restore() +{ + psvDebugScreenClear(); + if(getFileSize("ur0:/vs0-orig.img") < 0){ + psvDebugScreenPrintf("ur0:/vs0-orig.img MISSING, cannot restore\nIf you must go back, reinstall your firmware w official updater"); + sceKernelDelayThread(10000000); + sceKernelExitProcess(0); + } + + psvDebugScreenPrintf("Beginning restore in 10 seconds,\nDO NOT TURN OFF YOUR CONSOLE\nOR EXIT THIS APP WHILE RESTORING!\n"); + sceKernelDelayThread(10000000); + + psvDebugScreenClear(); + + dd("ur0:/vs0-orig.img","sdstor0:int-lp-ign-vsh", 0x10000000); // start dd + do + { + left = getTotalLeft(); + + int total = 0x10000000 - left; + float percent = (float)total / 268435456 * 100.0; + + psvDebugScreenPrintf("Restoring ur0:/vs0-orig.img %i/268435456 - %.2f%%\n",total, percent); + + sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND); + sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF); + coordX = 0; + coordY = 0; + } + while(left != 0x50000001); + + psvDebugScreenClear(); + + sceIoRemove("ur0:tai/testkit.skprx"); + sceIoRemove("ur0:tai/kmspico.skprx"); + sceIoRemove("ur0:/vs0-orig.img"); + + psvDebugScreenClear(); + psvDebugScreenPrintf("Restore complete~ Your console is now a retail again"); + sceKernelDelayThread(10000000); + scePowerRequestColdReset(); +} + +void backup() +{ + sceIoRemove("ur0:/vs0-orig.img"); + WriteFile("ur0:/vs0-orig.img",NULL,0x00); // create vs0.img + + dd("sdstor0:int-lp-ign-vsh","ur0:/vs0-orig.img", 0x10000000); //start dd + do + { + left = getTotalLeft(); + + int total = 0x10000000 - left; + float percent = (float)total / 268435456 * 100.0; + + psvDebugScreenPrintf("Creating ur0:/vs0-orig.img %i/268435456 - %.2f%%\n",total, percent); + + sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND); + sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF); + coordX = 0; + coordY = 0; + } + while(left != 0x50000001); + + psvDebugScreenClear(); +} + +void flash() +{ + psvDebugScreenPrintf("Beginning flash in 10 seconds,\nDO NOT TURN OFF YOUR CONSOLE OR EXIT THIS APP WHILE FLASHING\n"); + sceKernelDelayThread(10000000); + + psvDebugScreenClear(); + + dd("ur0:/vs0.img","sdstor0:int-lp-ign-vsh", 0x10000000); // start dd + do + { + left = getTotalLeft(); + + int total = 0x10000000 - left; + float percent = (float)total / 268435456 * 100.0; + + psvDebugScreenPrintf("Flashing ur0:/vs0.img %i/268435456 - %.2f%%\n",total, percent); + + sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND); + sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF); + coordX = 0; + coordY = 0; + } + while(left != 0x50000001); + + cleanup(); + psvDebugScreenClear(); + psvDebugScreenPrintf("Flash complete~ Your console is now a \"testkit\""); + sceKernelDelayThread(10000000); + scePowerRequestColdReset(); +} + +void uninstall() +{ + load_modules(); + lock(); + restore(); +} + +void install() +{ + extract(); + vercheck(); + config(); + load_modules(); + lock(); + decrypt(); + join(); + backup(); + flash(); +} + +int isRex() +{ + if(getFileSize("vs0:/app/NPXS10104/eboot.bin") > 0) + { + return 1; + } + else + { + return 0; + } +} + +void copyappinfo() // Setup Epic "interlectural property notices" thing +{ + if(getFileSize("ux0:/psm/CEXR20202/RO/Application/app.info") != getFileSize("app0:/app.info")) + { + sceIoMkdir("ux0:/psm", 0777); + sceIoMkdir("ux0:/psm/CEXR20202", 0777); + sceIoMkdir("ux0:/psm/CEXR20202/RO", 0777); + sceIoMkdir("ux0:/psm/CEXR20202/RO/Application", 0777); + CopyFile("app0:/app.info","ux0:/psm/CEXR20202/RO/Application/app.info"); + } +} + +int main() { + copyappinfo(); + psvDebugScreenInit(); + psvDebugScreenClear(0); + int size = getFileSize("ux0:/DEX.PUP"); + if(size <= 0) + { + char version[16]; + SceKernelFwInfo data; + data.size = sizeof(SceKernelFwInfo); + _vshSblGetSystemSwVersion(&data); + snprintf(version, 16, "%s", data.versionString); + + psvDebugScreenPrintf("ux0:/DEX.PUP NOT FOUND!\nPlease download the DEX %s firmware update file (.PUP)\nAnd place it in ux0:/DEX.PUP",version); + while(1){}; + } + + if(isRex() == 0) + { + psvDebugScreenPrintf("CEX-2-REX 2.0 - Currently CEX\n"); + psvDebugScreenPrintf("X: Install TestKit Firmware\n"); + + sceKernelDelayThread(100000); + while(1) + { + switch(get_key(0)) { + case SCE_CTRL_CROSS: + install(); + break; + default: + break; + } + } + } + else + { + psvDebugScreenPrintf("CEX-2-REX 2.0 - Currently REX\n"); + psvDebugScreenPrintf("X: Uninstall TestKit Firmware\n"); + psvDebugScreenPrintf("O: Change Installation Type\n"); + + sceKernelDelayThread(100000); + while(1) + { + switch(get_key(0)) { + case SCE_CTRL_CROSS: + uninstall(); + break; + case SCE_CTRL_CIRCLE: + config(); + scePowerRequestColdReset(); + break; + default: + break; + } + } + } + + + + + + + return 0; +} diff --git a/app/src/pup.c b/app/src/pup.c new file mode 100644 index 0000000..37d62f4 --- /dev/null +++ b/app/src/pup.c @@ -0,0 +1,222 @@ +/* +* Adapted from Princess Of Sleeping's PUP extractor +* https://github.com/Princess-of-Sleeping/PSV-PUP-Extractor +*/ + +#include "pup.h" +int psvDebugScreenPrintf(const char *format, ...); +void psvDebugScreenClear(); + +int NotExistMkdir(char *path){ + + int dfd = sceIoDopen(path); + if(dfd >= 0){ + + sceIoDclose(dfd); + + }else{ + + sceIoMkdir(path, 0777); + + } + + return 0; + +} + + +int scePlayStartionUpdatePackageExtractStage1(char *ext_pup_path) { + SceUID file_check = sceIoOpen(ext_pup_path, SCE_O_RDONLY, 0); + if(file_check < 0){ + return file_check; + } + + ScePlayStartionUpdatePackageHeader1 header; + sceIoPread(file_check, &header, sizeof(ScePlayStartionUpdatePackageHeader1), 0); + sceIoPread(file_check, temp_buff, sizeof(temp_buff), 0); + + if(BYTE_SWAP_64(header.magic) != 0x5343455546000001){ + return -1; + } + + sceGetPlayStartionUpdatePackageInfo(&header); + + sprintf(pup_dec_dir, "ur0:/pup_out/"); + NotExistMkdir(pup_dec_dir); + + for(int i=0;ipup_type); + return 0; + +} + + +void sceGetPlayStartionUpdatePackageFileEntryId(void *buff, int entry_id){ + switch (entry_id) { + + case 0x100:sprintf(buff, "version.txt");break; + case 0x101:sprintf(buff, "license.xml");break; + case 0x200:sprintf(buff, "psp2swu.self");break; + case 0x204:sprintf(buff, "cui_setupper.self");break; + + case 0x221:sprintf(buff, "psv_package_data01.pkg");break; + case 0x231:sprintf(buff, "psv_package_data02.pkg");break; + + case 0x301:sprintf(buff, "package_data01.pkg");break; + case 0x302:sprintf(buff, "package_data02.pkg");break; + case 0x303:sprintf(buff, "package_data03.pkg");break; + case 0x304:sprintf(buff, "package_data04.pkg");break; + case 0x305:sprintf(buff, "package_data05.pkg");break; + case 0x306:sprintf(buff, "package_data06.pkg");break; + case 0x307:sprintf(buff, "package_data07.pkg");break; + case 0x308:sprintf(buff, "package_data08.pkg");break; + case 0x309:sprintf(buff, "package_data09.pkg");break; + case 0x30A:sprintf(buff, "package_data10.pkg");break; + case 0x30B:sprintf(buff, "package_data11.pkg");break; + case 0x30C:sprintf(buff, "package_data12.pkg");break; + case 0x30D:sprintf(buff, "package_data13.pkg");break; + case 0x30E:sprintf(buff, "package_data14.pkg");break; + case 0x30F:sprintf(buff, "package_data15.pkg");break; + case 0x310:sprintf(buff, "package_data16.pkg");break; + case 0x311:sprintf(buff, "package_data17.pkg");break; + case 0x312:sprintf(buff, "package_data18.pkg");break; + case 0x313:sprintf(buff, "package_data19.pkg");break; + case 0x314:sprintf(buff, "package_data20.pkg");break; + case 0x315:sprintf(buff, "package_data21.pkg");break; + case 0x316:sprintf(buff, "package_data22.pkg");break; + case 0x317:sprintf(buff, "package_data23.pkg");break; + case 0x318:sprintf(buff, "package_data24.pkg");break; + case 0x319:sprintf(buff, "package_data25.pkg");break; + case 0x31A:sprintf(buff, "package_data26.pkg");break; + + case 0x31B:sprintf(buff, "unknown_0x31B");break; + case 0x31C:sprintf(buff, "unknown_0x31C");break; + case 0x31D:sprintf(buff, "unknown_0x31D");break; + case 0x31E:sprintf(buff, "unknown_0x31E");break; + case 0x31F:sprintf(buff, "unknown_0x31F");break; + case 0x320:sprintf(buff, "unknown_0x320");break; + case 0x321:sprintf(buff, "unknown_0x321");break; + case 0x322:sprintf(buff, "unknown_0x322");break; + case 0x323:sprintf(buff, "unknown_0x323");break; + case 0x324:sprintf(buff, "unknown_0x324");break; + case 0x325:sprintf(buff, "unknown_0x325");break; + + case 0x326:sprintf(buff, "debug_data00.pkg");break; + case 0x327:sprintf(buff, "debug_data01.pkg");break; + case 0x328:sprintf(buff, "debug_data02.pkg");break; + case 0x329:sprintf(buff, "debug_data03.pkg");break; + case 0x32A:sprintf(buff, "debug_data04.pkg");break; + case 0x32B:sprintf(buff, "debug_data05.pkg");break; + case 0x32C:sprintf(buff, "debug_data06.pkg");break; + + case 0x32D:sprintf(buff, "unknown_0x32D");break; + case 0x32E:sprintf(buff, "unknown_0x32E");break; + case 0x32F:sprintf(buff, "unknown_0x32F");break; + case 0x330:sprintf(buff, "unknown_0x330");break; + case 0x331:sprintf(buff, "unknown_0x331");break; + case 0x332:sprintf(buff, "unknown_0x332");break; + case 0x333:sprintf(buff, "unknown_0x333");break; + case 0x334:sprintf(buff, "unknown_0x334");break; + case 0x335:sprintf(buff, "unknown_0x335");break; + case 0x336:sprintf(buff, "unknown_0x336");break; + case 0x337:sprintf(buff, "unknown_0x337");break; + case 0x338:sprintf(buff, "unknown_0x338");break; + + case 0x400:sprintf(buff, "package_scewm.wm");break; + case 0x401:sprintf(buff, "package_sceas.as");break; + + + default:{ + + sprintf(buff, "unknown_0x%X", entry_id); + + } + + } + psvDebugScreenPrintf("Extracting ur0:/pup_out/%s\n",(char*)buff); +} + + +char pup_buffer[0x20000]; + +int scePlayStartionUpdatePackageExtractFiles(char *pup_dec_dir, SceUID file_check, int i, SceUInt32 file_count, void *header){ + + char write_file_name[0x100]; + char write_file_path[0x200]; + + uint32_t base_addr1 = 0x80 + (0x20 * i); + uint32_t base_addr2 = (0x80 + (0x20 * file_count)) + (0x40 * i); + + ScePlayStartionUpdatePackageHeader2 header2; + ScePlayStartionUpdatePackageHeader3 header3; + + sceIoPread(file_check, &header2, sizeof(ScePlayStartionUpdatePackageHeader2), base_addr1); + sceIoPread(file_check, &header3, sizeof(ScePlayStartionUpdatePackageHeader3), base_addr2); + + sceGetPlayStartionUpdatePackageFileEntryId(write_file_name, header2.entry_id); + + sprintf(write_file_path, "%s%s", pup_dec_dir, write_file_name); + + int fd = sceIoOpen(write_file_path, SCE_O_TRUNC | SCE_O_CREAT | SCE_O_WRONLY, 0777); + + + if(fd < 0){ + return fd; + } + + + uint32_t plus_address = 0x0, read_size = sizeof(pup_buffer); + + do { + + if((plus_address + sizeof(pup_buffer)) > header2.data_length){ + + read_size = (plus_address + sizeof(pup_buffer)) - header2.data_length; + + read_size = sizeof(pup_buffer) - read_size; + + } + + int sipr = sceIoPread(file_check, pup_buffer, read_size, header2.data_offset + plus_address); + + sceIoWrite(fd, pup_buffer, sipr); + + plus_address += sizeof(pup_buffer); + + } while (plus_address < header2.data_length); + + + + sceIoClose(fd); + + + return 0; + +} + diff --git a/app/src/pup.h b/app/src/pup.h new file mode 100644 index 0000000..ed285ae --- /dev/null +++ b/app/src/pup.h @@ -0,0 +1,102 @@ +/* +* Adapted from Princess Of Sleeping's PUP extractor +* https://github.com/Princess-of-Sleeping/PSV-PUP-Extractor +*/ + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#define _BYTE1(x) ( (x >> 0x00) & 0xFF ) +#define _BYTE2(x) ( (x >> 0x08) & 0xFF ) +#define _BYTE3(x) ( (x >> 0x10) & 0xFF ) +#define _BYTE4(x) ( (x >> 0x18) & 0xFF ) +#define _BYTE5(x) ( (x >> 0x20) & 0xFF ) +#define _BYTE6(x) ( (x >> 0x28) & 0xFF ) +#define _BYTE7(x) ( (x >> 0x30) & 0xFF ) +#define _BYTE8(x) ( (x >> 0x38) & 0xFF ) + +#define BYTE_SWAP_16(x) ((uint16_t)( _BYTE1(x)<<8 | _BYTE2(x) )) +#define BYTE_SWAP_32(x) ((uint32_t)( _BYTE1(x)<<0x18 | _BYTE2(x)<<0x10 | _BYTE3(x)<<8 | _BYTE4(x) )) +#define BYTE_SWAP_64(x) ((SceUInt64)( _BYTE1(x)<<0x38 | _BYTE2(x)<<0x30 | _BYTE3(x)<<0x28 | _BYTE4(x)<<0x20 | _BYTE5(x)<<0x18 | _BYTE6(x)<<0x10 | _BYTE7(x)<<0x8 | _BYTE8(x)<<0x0 )) + +typedef struct { + SceUInt64 magic; + SceUInt32 package_version; //0x00000008 + SceUInt32 unknown_0x0C; + SceUInt32 image_version; //0x00000010 + SceUInt32 unknown_0x14; + SceUInt32 file_count; //0x00000018 + SceUInt32 unknown_0x1C; + SceUInt32 header_length; //0x00000020 + SceUInt32 unknown_0x24; + SceUInt32 package_length; //0x00000028 + SceUInt32 unknown_0x2C; + SceUInt32 unknown_0x30; + SceUInt32 unknown_0x34; + SceUInt32 unknown_0x38; + SceUInt32 pup_type; //0x0000003C + SceUInt32 unknown_0x40; + SceUInt32 unknown_0x44; + SceUInt32 unknown_0x48; + SceUInt32 unknown_0x4C; + SceUInt32 unknown_0x50; + SceUInt32 unknown_0x54; + SceUInt32 unknown_0x58; + SceUInt32 unknown_0x5C; + SceUInt32 unknown_0x60; + SceUInt32 unknown_0x74; + SceUInt32 unknown_0x78; + SceUInt32 unknown_0x7C; +} __attribute__((packed)) ScePlayStartionUpdatePackageHeader1; + +typedef struct { + SceUInt32 entry_id; + SceUInt32 unknown_0x04; + SceUInt32 data_offset; //0x00000008 + SceUInt32 unknown_0x0C; + SceUInt32 data_length; //0x00000010 + SceUInt32 unknown_0x14; + SceUInt32 unknown_0x18; // 2? + SceUInt32 unknown_0x1C; +} __attribute__((packed)) ScePlayStartionUpdatePackageHeader2; + +typedef struct { + SceUInt32 index; + SceUInt32 unknown_0x04; + char hash[0x20]; //HMAC-sha256? + SceUInt32 unknown_0x28; + SceUInt32 unknown_0x2C; + SceUInt32 unknown_0x30; + SceUInt32 unknown_0x34; + SceUInt32 unknown_0x38; + SceUInt32 unknown_0x3C; +} __attribute__((packed)) ScePlayStartionUpdatePackageHeader3; + +char pup_type_buf[0x20]; +char pup_dec_dir[0x100]; +char temp_buff[0x2000]; + + +int get_key(int type); + +void press_next(void); + +void press_exit(void); + + +int scePlayStartionUpdatePackageExtractFiles(char *pup_dec_dir, SceUID file_check, int i, SceUInt32 file_count, void *header); + +void sceGetPlayStartionUpdatePackageFileEntryId(void *buff, int entry_id); + +int sceGetPlayStartionUpdatePackageInfo(ScePlayStartionUpdatePackageHeader1 *header); + +int scePlayStartionUpdatePackageExtractStage1(char *ext_pup_path); \ No newline at end of file diff --git a/app/vitaConfig.txt b/app/vitaConfig.txt new file mode 100644 index 0000000..18e0d53 --- /dev/null +++ b/app/vitaConfig.txt @@ -0,0 +1,139 @@ +# WARNING: DO NOT EDIT THIS FILE. IF YOU JUST WANT TO RUN A PLUGIN ON BOOT, +# EDIT ux0:tai/config.txt INSTEAD. IF YOU BREAK THIS FILE, YOUR VITA WILL NO +# LONGER BOOT. IF THAT HAPPENS, YOU CAN ENTER SAFE MODE AND RESET ALL SETTINGS +# TO RESET THIS FILE. THIS FILE IS UNIQUE TO EACH VITA MODEL. DO NOT BLINDLY +# USE SOMEONE ELSE'S CONFIG. +# +# PSP2 System Configuration for Release +# +# [NOTICE] +# +# This configuration is only for kernel_boot_loader_release.self. +# + +- load ur0:tai/testkit.skprx +load os0:kd/clockgen.skprx +#load os0:kd/syscon.skprx +#load os0:kd/rtc.skprx + +#load os0:kd/sm_comm.skprx +#load os0:kd/ss_mgr.skprx +load os0:kd/idstorage.skprx + +load os0:kd/ctrl.skprx +load os0:kd/touch.skprx +load os0:kd/motion.skprx +if AU_CODEC_IC_CONEXANT +load os0:kd/codec_cx.skprx +else +load os0:kd/codec.skprx +endif +load os0:kd/audio.skprx +load os0:kd/hpremote.skprx +load os0:kd/power.skprx + +load os0:kd/usbd.skprx +load os0:kd/udcd.skprx +load os0:kd/usbserv.skprx +load os0:kd/usbserial.skprx +load os0:kd/usbmtp.skprx +load os0:kd/mtpif.skprx + +load os0:kd/post_ss_mgr.skprx +load os0:kd/update_mgr.skprx +load os0:kd/regmgr.skprx + +if USB_ENUM_WAKEUP +load os0:kd/enum_wakeup.skprx +else + +load os0:kd/vnz_wrapper.skprx +#load os0:kd/applier.skprx +- load os0:kd/mgkeymgr.skprx + +load os0:kd/error.skprx + +#load os0:kd/gcauthmgr.skprx +load os0:kd/npdrm.skprx + +load os0:kd/ulobjmgr.skprx + +load os0:kd/net_ps.skprx +load os0:kd/gps.skprx +load os0:kd/bbmc.skprx +load os0:kd/wlanbt.skprx +load os0:kd/usb_ether_smsc.skprx +load os0:kd/usb_ether_rtl.skprx +load os0:kd/bt.skprx +load os0:kd/usbstor.skprx +load os0:kd/usbstorvstor.skprx +load os0:kd/usbpspcm.skprx + +- load os0:kd/magicgate.skprx +- load os0:kd/usbstormg.skprx +- load os0:kd/mgvideo.skprx + +load os0:kd/avcodec.skprx +load os0:kd/audioin.skprx +load os0:kd/ngs.skprx + +load os0:kd/hid.skprx + +load os0:kd/gpu_es4.skprx +load os0:kd/gpuinit_es4.skprx + +- load os0:kd/compat.skprx +load os0:kd/camera.skprx +load os0:kd/coredump.skprx + +if BSOD_REBOOT +load os0:kd/crashdump.skprx +endif + +load os0:kd/av_config.skprx +load os0:kd/fios2.skprx +load os0:kd/pfsmgr.skprx +load os0:kd/appmgr.skprx + +load os0:kd/sysmodule.skprx +load os0:kd/vshbridge.skprx +load os0:kd/marlin_hci.skprx +load os0:kd/krm.skprx +- load os0:kd/tty2uart.skprx + +umount_bootfs + +if MANUFACTURING_MODE +- spawnwait sd0:psp2diag.self +- spawnwait ux0:psp2diag.self +endif + +if SAFE_MODE +spawn os0:ue/safemode.self +end +endif + +if UPDATE_MODE +if UD0_EXIST +spawn ud0:PSP2UPDATE/psp2swu.self +else +spawn ur0:PSP2UPDATE/psp2swu.self +endif +end +endif + +- load ur0:tai/taihen.skprx +- load ur0:tai/henkaku.skprx +- load ur0:tai/kmspico.skprx + +- appspawn vs0:vsh/shell/shell.self SHELL_BUDGET_ID + +endif +end + +# Local variables: +# mode: c +# tab-width: 4 +# c-basic-offset: 4 +# coding: utf-8 +# End: diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..e04197b --- /dev/null +++ b/build.sh @@ -0,0 +1,27 @@ +export VITASDK=/usr/local/vitasdk +export PATH=$VITASDK/bin:$PATH + + +cd kernel/ +cmake . +make install + +cd ../spoofer/ +make clean +make + +cd ../user/ +cmake . +make install + +cd ../kmspico/ +cmake . +make install + +cd ../app/ +mv ../kmspico/kmspico.skprx kmspico.skprx +mv ../spoofer/kDump.skprx testkit.skprx +mv ../kernel/kernel.skprx kernel.skprx +mv ../user/user.suprx user.suprx +cmake . +make \ No newline at end of file diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt new file mode 100644 index 0000000..08dd1c7 --- /dev/null +++ b/kernel/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 2.8) + +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(DEFINED ENV{VITASDK}) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") + else() + message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") + endif() +endif() + +project(cex2rex_kern) +include("${VITASDK}/share/vita.cmake" REQUIRED) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") + +add_executable(${PROJECT_NAME} + src/main.c + src/spkg.c +) + +target_link_libraries(${PROJECT_NAME} + SceIofilemgrForDriver_stub + SceSysclibForDriver_stub + SceModulemgrForDriver_stub + SceThreadmgrForDriver_stub + SceProcessmgrForDriver_stub + ScePowerForDriver_stub + SceSysmemForDriver_stub + SceSysrootForKernel_stub + SceSblSsMgrForDriver_stub + SceCpuForDriver_stub + SceKernelUtilsForDriver_stub + SceSysmemForKernel_stub + SceDebugForDriver_stub + taihenForKernel_stub + taihenModuleUtils_stub +) + +vita_create_self(kernel.skprx ${PROJECT_NAME} CONFIG exports.yml UNSAFE) + +vita_create_stubs(stubs ${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/exports.yml KERNEL) + +install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/ + DESTINATION lib + FILES_MATCHING PATTERN "*.a" +) + +install(FILES src/cex2rex_kern.h + DESTINATION include +) diff --git a/kernel/exports.yml b/kernel/exports.yml new file mode 100644 index 0000000..3903647 --- /dev/null +++ b/kernel/exports.yml @@ -0,0 +1,16 @@ +Cex2Rex_Kern: + attributes: 0 + version: + major: 1 + minor: 0 + main: + start: module_start + stop: module_stop + modules: + kC2R: + syscall: true + functions: + - kdd + - kDecryptSpkgFile + - kgetTotalLeft + - kscePowerSetCallbackEnabledForUser \ No newline at end of file diff --git a/kernel/src/cex2rex_kern.h b/kernel/src/cex2rex_kern.h new file mode 100644 index 0000000..353e2f6 --- /dev/null +++ b/kernel/src/cex2rex_kern.h @@ -0,0 +1,4 @@ +int kdd(char *inf, char *of, int size); +int kDecryptSpkgFile(char *in, char *out); +int kgetTotalLeft(); +int kscePowerSetCallbackEnabledForUser(int enable); \ No newline at end of file diff --git a/kernel/src/main.c b/kernel/src/main.c new file mode 100644 index 0000000..b66a8f9 --- /dev/null +++ b/kernel/src/main.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include "power.h" +#include "sysroot.h" +#include "spkg.h" + +#define printf + +char infile[128]; +char outfile[128]; +int sz = -1; +int offst; +int progress = -1; + + +int getFileSize(const char *file) { + SceUID fd = ksceIoOpen(file, SCE_O_RDONLY, 0); + if (fd < 0) + return fd; + int fileSize = ksceIoLseek(fd, 0, SCE_SEEK_END); + ksceIoClose(fd); + return fileSize; +} + +int WriteFile(char *file, void *buf, int size) { + SceUID fd = ksceIoOpen(file, SCE_O_RDWR | SCE_O_CREAT, 0777); + if (fd < 0) + return fd; + + int written = ksceIoWrite(fd, buf, size); + + ksceIoClose(fd); + return written; +} + +int ReadFile(char *file, void *buf, int size) { + SceUID fd = ksceIoOpen(file, SCE_O_RDONLY, 0777); + if (fd < 0) + return fd; + + int readed = ksceIoRead(fd, buf, size); + + ksceIoClose(fd); + return readed; +} + +int run_on_thread(void *func) { + + int ret = 0; + int res = 0; + int uid = 0; + + ret = uid = ksceKernelCreateThread("run_on_thread", func, 64, 0x10000, 0, 0, 0); + + if (ret < 0) { + ret = -1; + goto cleanup; + } + if ((ret = ksceKernelStartThread(uid, 0, NULL)) < 0) { + ret = -1; + goto cleanup; + } + + ret = res; + +cleanup: + if (uid > 0) + ksceKernelDeleteThread(uid); + + return ret; +} + + + +int run_dd(void) +{ + int ret = 0; + + SceUID fd = ksceIoOpen(infile, SCE_O_RDONLY, 0777); + SceUID wfd = ksceIoOpen(outfile, SCE_O_WRONLY, 6); + static char buffer[0x100000]; + + while(!(sz <= 0)) + { + memset(buffer,0x00,0x100000); + if(sz < 0x100000) + { + ksceIoRead(fd, buffer, sz); + ret = ksceIoWrite(wfd, buffer, sz); + sz -= sz; + } + else + { + ksceIoRead(fd, buffer, 0x100000); + ret = ksceIoWrite(wfd, buffer, 0x100000); + sz -= 0x100000; + } + } + + if (fd > 0) + ksceIoClose(fd); + if (wfd > 0) + ksceIoClose(wfd); + sz = 0x50000001; + return ret; +} + + +int kgetTotalLeft() +{ + return sz; +} + +int kdd(char *inf, char *of, int size) +{ + + int state = 0; + ENTER_SYSCALL(state); + + ksceKernelStrncpyUserToKernel(&infile, (uintptr_t)inf, sizeof(infile)); + ksceKernelStrncpyUserToKernel(&outfile, (uintptr_t)of, sizeof(outfile)); + + sz = size; + + int ret = run_on_thread(run_dd); + EXIT_SYSCALL(state); + return ret; +} + +/* +* Magical FAPS TEAM technology V V V +*/ +int kscePowerSetCallbackEnabledForUser(int enable) +{ + return kscePowerSetCallbackEnabled(enable); +} + +int kDecryptSpkgFile(char *in, char *out) +{ + char infile[128]; + char outfile[128]; + void *spkg = 0; + + ksceKernelStrncpyUserToKernel(&infile, (uintptr_t)in, sizeof(infile)); + ksceKernelStrncpyUserToKernel(&outfile, (uintptr_t)out, sizeof(outfile)); + + int size = getFileSize(infile); + + int memblk = ksceKernelAllocMemBlock("spkg_block", 0x10C0D006, (size + 0xfff) & ~0xfff, NULL); + if(memblk < 0) + { + return memblk; + } + + int base = ksceKernelGetMemBlockBase(memblk, &spkg); + if(base < 0) + { + return base; + } + + if(spkg < 0) + { + return (int)spkg; + } + + ReadFile(infile,spkg,size); + int ret = decrypt_spkg(spkg, size); + WriteFile(outfile, spkg, size); + ksceKernelFreeMemBlock(memblk); + return ret; +} + +void _start() __attribute__ ((weak, alias("module_start"))); +int module_start(SceSize args, void *argp) { + return SCE_KERNEL_START_SUCCESS; +} + +int module_stop(SceSize args, void *argp) { + return SCE_KERNEL_STOP_SUCCESS; +} + \ No newline at end of file diff --git a/kernel/src/power.h b/kernel/src/power.h new file mode 100644 index 0000000..7f65fd6 --- /dev/null +++ b/kernel/src/power.h @@ -0,0 +1 @@ +int kscePowerSetCallbackEnabled(int enable); \ No newline at end of file diff --git a/kernel/src/spkg.c b/kernel/src/spkg.c new file mode 100644 index 0000000..9bdcac4 --- /dev/null +++ b/kernel/src/spkg.c @@ -0,0 +1,121 @@ +/* spkg.c -- spkg decryption + * + * Copyright (C) 2019 TheFloW + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include +#include + +#include +#include + +#include "spkg.h" + +int ksceSblDmac5AesCbcDec(void *src, void *dst, int size, void *key, int key_size, void *iv, int mask_enable); + +uint8_t spkg_key[0x20] = { + 0x2E, 0x6F, 0x47, 0x51, 0xD1, 0x5B, 0x06, 0xC5, 0x1F, 0x57, 0x2A, 0x93, 0x06, 0xE5, 0x2D, 0xD7, 0x00, 0x7E, 0xA5, 0x6A, 0x31, 0xD4, 0x59, 0xEC, 0x6D, 0x36, 0x81, 0xAB, 0x08, 0x62,0x55, 0x01 +}; + +uint8_t spkg_iv[0x10] = { + 0xB3,0xD5,0x41,0xA5,0x68,0x75,0x1D,0xF8,0xF4,0x83,0x3B,0xAB,0x4E,0xFE,0x05,0x37 +}; + +void xor_key(uint8_t *dst, uint8_t *src, int len) { + int i; + for (i = 0; i < len; i++) { + dst[i] ^= src[i]; + } +} + +void key_inc(uint8_t *key, int pos) { + if (key[pos] == 0xFF) { + key[pos] = 0; + key_inc(key, pos - 1); + } else { + key[pos] += 1; + } +} + +int aes_ctr_encrypt(void *data, int size, void *key, void *iv) { + uint8_t ikey[16], xkey[16]; + int res; + + SceAesContext ctx; + res = ksceAesInit1(&ctx, 128, 128, key); + if (res < 0) + return res; + + memcpy(ikey, iv, 16); + + int i; + for (i = 0; i < size; i += 16) { + memcpy(xkey, ikey, 16); + res = ksceAesEncrypt1(&ctx, xkey, xkey); + if (res < 0) + return res; + xor_key(data + i, xkey, 16); + key_inc(ikey, 15); + } + + return 0; +} + +int decrypt_spkg(void *buf, int size) { + char key[0x20], iv[0x10]; + int res; + + SceHeader *sce_header = (SceHeader *)buf; + if (sce_header->magic != 0x00454353 || sce_header->version != 3 || sce_header->sce_type != 3) + return SCE_SBL_ERROR_SL_EDATA; + + MetadataInfo *metadata_info = (MetadataInfo *)((char *)sce_header + sce_header->metadata_offset + 0x30); + + memcpy(key, spkg_key, 0x20); + memcpy(iv, spkg_iv, 0x10); + + res = ksceSblDmac5AesCbcDec(metadata_info, metadata_info, sizeof(MetadataInfo), key, 256, iv, 1); + if (res < 0) + return res; + + if (metadata_info->pad0 != 0 || metadata_info->pad1 != 0 || + metadata_info->pad2 != 0 || metadata_info->pad3 != 0) + return SCE_SBL_ERROR_SL_EDATA; + + char *dec = (char *)metadata_info + sizeof(MetadataInfo); + int dec_size = sce_header->header_length - sce_header->metadata_offset - 0x30 - sizeof(MetadataInfo); + + memcpy(key, metadata_info->key, 0x10); + memcpy(iv, metadata_info->iv, 0x10); + + res = ksceSblDmac5AesCbcDec(dec, dec, dec_size, key, 128, iv, 1); + if (res < 0) + return res; + + MetadataHeader *metadata_header = (MetadataHeader *)dec; + MetadataSection *metadata_section = (MetadataSection *)((char *)metadata_header + sizeof(MetadataHeader)); + + char *vault = (char *)metadata_section + metadata_header->section_count * sizeof(MetadataSection); + + int i; + for (i = 0; i < metadata_header->section_count; i++) { + if (metadata_section[i].encryption == 3) { + char *vault_key = vault + metadata_section[i].key_idx * 0x10; + char *vault_iv = vault + metadata_section[i].iv_idx * 0x10; + + memcpy(key, vault_key, 0x10); + memcpy(iv, vault_iv, 0x10); + + res = aes_ctr_encrypt(buf + metadata_section[i].offset, metadata_section[i].size, key, iv); + if (res < 0) + return res; + } + } + + ksceKernelCpuDcacheAndL2WritebackRange(buf, ALIGN(size, 0x40)); + + return 0; +} diff --git a/kernel/src/spkg.h b/kernel/src/spkg.h new file mode 100644 index 0000000..6e3dbf7 --- /dev/null +++ b/kernel/src/spkg.h @@ -0,0 +1,78 @@ +#ifndef __SPKG_H__ +#define __SPKG_H__ + +#define ALIGN(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) + +#define SCE_SBL_ERROR_SL_EDATA 0x800F0226 +#define SCE_SBL_ERROR_SL_ESYSVER 0x800F0237 +#define SCE_SBL_SM_COMM_FID_SM_AUTH_SPKG 0x40002 + +typedef struct { + uint32_t magic; + uint32_t version; + uint8_t platform; + uint8_t key_revision; + uint16_t sce_type; + uint32_t metadata_offset; + uint64_t header_length; + uint64_t data_length; +} SceHeader; + +typedef struct { + uint8_t key[0x10]; + uint64_t pad0; + uint64_t pad1; + uint8_t iv[0x10]; + uint64_t pad2; + uint64_t pad3; +} MetadataInfo; + +typedef struct { + uint64_t signature_input_length; + uint32_t signature_type; + uint32_t section_count; + uint32_t key_count; + uint32_t opt_header_size; + uint32_t field_18; + uint32_t field_1C; +} MetadataHeader; + +typedef struct { + uint64_t offset; + uint64_t size; + uint32_t type; + uint32_t seg_idx; + uint32_t hashtype; + uint32_t hash_idx; + uint32_t encryption; + uint32_t key_idx; + uint32_t iv_idx; + uint32_t compression; +} MetadataSection; + +typedef struct { + uint32_t field_0; + uint32_t pkg_type; + uint32_t flags; + uint32_t field_C; + uint64_t update_version; + uint64_t final_size; + uint64_t decrypted_size; + uint64_t field_28; + uint32_t field_30; + uint32_t field_34; + uint32_t field_38; + uint32_t field_3C; + uint64_t field_40; + uint64_t field_48; + uint64_t offset; + uint64_t size; + uint64_t part_idx; + uint64_t total_parts; + uint64_t field_70; + uint64_t field_78; +} SpkgHeader; + +int decrypt_spkg(void *buf, int size); + +#endif diff --git a/kernel/src/sysroot.h b/kernel/src/sysroot.h new file mode 100644 index 0000000..88e38fc --- /dev/null +++ b/kernel/src/sysroot.h @@ -0,0 +1 @@ +void* ksceKernelSysrootAlloc(int size); \ No newline at end of file diff --git a/kmspico/CMakeLists.txt b/kmspico/CMakeLists.txt new file mode 100644 index 0000000..8ad1a3d --- /dev/null +++ b/kmspico/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 2.8) + +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(DEFINED ENV{VITASDK}) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") + else() + message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") + endif() +endif() + +project(kmspico) +include("${VITASDK}/share/vita.cmake" REQUIRED) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") + +add_executable(${PROJECT_NAME} + src/main.c +) + +target_link_libraries(${PROJECT_NAME} + SceIofilemgrForDriver_stub + SceSysclibForDriver_stub + SceModulemgrForDriver_stub + SceThreadmgrForDriver_stub + SceProcessmgrForDriver_stub + SceSysmemForDriver_stub + SceSysrootForKernel_stub + SceSysmemForKernel_stub + SceDebugForDriver_stub + taihenForKernel_stub + taihenModuleUtils_stub +) + +vita_create_self(kmspico.skprx ${PROJECT_NAME} CONFIG exports.yml UNSAFE) + +vita_create_stubs(stubs ${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/exports.yml KERNEL) + +install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/ + DESTINATION lib + FILES_MATCHING PATTERN "*.a" +) diff --git a/kmspico/exports.yml b/kmspico/exports.yml new file mode 100644 index 0000000..1bb4427 --- /dev/null +++ b/kmspico/exports.yml @@ -0,0 +1,8 @@ +kmspico: + attributes: 0 + version: + major: 1 + minor: 0 + main: + start: module_start + stop: module_stop diff --git a/kmspico/src/main.c b/kmspico/src/main.c new file mode 100644 index 0000000..16f7b5b --- /dev/null +++ b/kmspico/src/main.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +static int hook = -1; +static tai_hook_ref_t ref_hook; + +int ksceSblPostSsMgrGetExpireDate_patched(int *arg1, int arg2) +{ + return 1; +} + +void _start() __attribute__ ((weak, alias("module_start"))); +int module_start(SceSize args, void *argp) { + hook = taiHookFunctionExportForKernel(KERNEL_PID, + &ref_hook, + "SceSblPostSsMgr", + 0x2254E1B2, + 0x4FF2682F, + ksceSblPostSsMgrGetExpireDate_patched); + return SCE_KERNEL_START_SUCCESS; +} + +int module_stop(SceSize args, void *argp) { + return SCE_KERNEL_STOP_SUCCESS; +} + \ No newline at end of file diff --git a/make_appinfo.bat b/make_appinfo.bat new file mode 100644 index 0000000..d8f98ba --- /dev/null +++ b/make_appinfo.bat @@ -0,0 +1,6 @@ +@echo off +echo Building app.info +echo (needs PSM SDK) +"%SCE_PSM_SDK%\tools\python\python.exe" "%SCE_PSM_SDK%\tools\PublishingUtility\cxml\appinfo\appinfo_compiler.py" "%CD%\app.xml" +copy "app.cxml" "app/app.info" /y +del "app.cxml" diff --git a/memdump_license b/memdump_license deleted file mode 100644 index a366c23..0000000 --- a/memdump_license +++ /dev/null @@ -1,14 +0,0 @@ - memdump ---- - Copyright 2017 notzecoxao - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/spoofer/LICENSE b/spoofer/LICENSE new file mode 100644 index 0000000..5c304d1 --- /dev/null +++ b/spoofer/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/spoofer/Makefile b/spoofer/Makefile new file mode 100644 index 0000000..aa23206 --- /dev/null +++ b/spoofer/Makefile @@ -0,0 +1,31 @@ +TITLE_ID = NIDUMP001 +TARGET = mDump +PSVITAIP = 192.168.1.115 + +PLUGIN_OBJS = mmu_dump.o +HEADERS = $(wildcard *.h) + +PLUGIN_LIBS = -ltaihen_stub -lSceSysclibForDriver_stub -lSceModulemgrForKernel_stub -lSceIofilemgrForDriver_stub + +PREFIX = arm-vita-eabi +CC = $(PREFIX)-gcc +CFLAGS = -Wl,-q -Wall -O3 +ASFLAGS = $(CFLAGS) + +all: kDump.skprx + +kDump.skprx: kDump.velf + vita-make-fself -c $< $@ + +kDump.velf: kDump.elf + vita-elf-create -e exports.yml $< $@ + +kDump.elf: $(PLUGIN_OBJS) + $(CC) $(CFLAGS) $^ $(PLUGIN_LIBS) -o $@ -nostdlib + +clean: + @rm -rf *.velf *.elf *.vpk *.skprx $(MAIN_OBJS) $(PLUGIN_OBJS) param.sfo eboot.bin + +send: eboot.bin + curl -T eboot.bin ftp://$(PSVITAIP):1337/ux0:/app/$(TITLE_ID)/ + @echo "Sent." diff --git a/spoofer/README.md b/spoofer/README.md new file mode 100644 index 0000000..31d7b32 --- /dev/null +++ b/spoofer/README.md @@ -0,0 +1,7 @@ +# memdump +This homebrew can dump memory + +Credits: +anonymous - precious info + +yifanlu - for his mmu_dump code (which saves a lot of work when dumping both the table and memory!) diff --git a/spoofer/exports.yml b/spoofer/exports.yml new file mode 100644 index 0000000..b4b87cb --- /dev/null +++ b/spoofer/exports.yml @@ -0,0 +1,8 @@ +vita_dump: + attributes: 0 + version: + major: 1 + minor: 1 + main: + start: module_start + stop: module_stop diff --git a/spoofer/mmu_dump.c b/spoofer/mmu_dump.c new file mode 100644 index 0000000..aff2f38 --- /dev/null +++ b/spoofer/mmu_dump.c @@ -0,0 +1,286 @@ +/* + * mmu_dump.c - Bare metal ARMv7 translation table dumper + * Copyright 2014 Yifan Lu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +static int afe; + +#define DUMP_PATH "ux0:dump/" + +void _start() __attribute__ ((weak, alias ("module_start"))); + +static unsigned int pa2va(unsigned int pa) +{ + unsigned int va; + unsigned int vaddr; + unsigned int paddr; + unsigned int i; + + va = 0; + for (i = 0; i < 0x100000; i++) + { + vaddr = i << 12; + __asm__("mcr p15,0,%1,c7,c8,0\n\t" + "mrc p15,0,%0,c7,c4,0\n\t" : "=r" (paddr) : "r" (vaddr)); + if ((pa & 0xFFFFF000) == (paddr & 0xFFFFF000)) + { + va = vaddr + (pa & 0xFFF); + break; + } + } + return va; +} + +static void mmu_get_perms(int ap2, int ap1, int *ur, int *uw, int *pr, int *pw) +{ + /* AFE enabled, use simple permissions */ + if (afe) + { + *ur = ap1 > 1; + *uw = !ap2 && ap1 > 1; + *pr = 1; + *pw = !ap2 && ap1 < 2; + } + else + { + *pw = (!ap2 && ap1); + *pr = *pw || ap1; + *ur = ap1 > 1; + *uw = !ap2 && ap1 == 3; + } +} + +//magic +unsigned char magic[0x8] = { + 0xA5, 0x9D, 0xCE, 0xAB, 0x00, 0x01, 0x01 +}; + +//spoof +unsigned char testkit_pscode[0x8] = { + 0x00, 0x01, 0x01, 0x02, 0x00, 0x10, 0x00, 0x03 +}; + +static int mmu_dump_pages(unsigned int vaddr, unsigned int entry) +{ + int xn; + int ng; + int s; + int ap2; + int ap1; + int pr; + int pw; + int ur; + int uw; + unsigned int paddr; + SceUID fd; + + if ((entry & 0x3) == 0x1) /* large page */ + { + xn = entry & 0x8000; + ng = entry & 0x800; + s = entry & 0x400; + ap2 = entry & 0x200; + ap1 = (entry >> 4) & 3; + mmu_get_perms(ap2, ap1, &ur, &uw, &pr, &pw); + paddr = entry & 0xFFFF0000; + if( paddr >= 0x40201000 && paddr < 0x5FD00000 && paddr != 0x44C20000 && paddr != 0x44C30000 && paddr != 0x443C0000){ + if( (paddr-0x44300000) <= (0x44400000-0x44300000) ){ + + }else if ( (paddr-0x45020000) <= (0x45030000-0x45020000) ){ + }else{ + + + + + //spoofing happens here + int counter = 0; + for (counter = 0; counter < 0x1000; counter ++){ + if(memcmp((void*)vaddr + counter, magic, 7) == 0 && counter == 0x5B0){ + counter = counter + 4; + memcpy((void*) vaddr + counter, testkit_pscode, 8); + return 0; + } + } + } + } + else{ + + } + } + else if ((entry & 0x2)) /* small page */ + { + xn = entry & 1; + ng = entry & 0x800; + s = entry & 0x400; + ap2 = entry & 0x200; + ap1 = (entry >> 4) & 3; + mmu_get_perms(ap2, ap1, &ur, &uw, &pr, &pw); + paddr = entry & 0xFFFFF000; + //0x4434C000 + if( paddr >= 0x40201000 && paddr < 0x5FD00000){ + if( (paddr-0x47D80000) <= (0x47D90000-0x47D80000) ){ + }else if ( (paddr-0x44C09000) <= (0x44C1A000-0x44C09000) ){ + }else if ( (paddr-0x44300000) <= (0x44400000-0x44300000) ){ + }else if ( (paddr-0x45009000) <= (0x45019000-0x45009000) ){ + }else if ( (paddr-0x44700000) <= (0x44710000-0x44700000) ){ + }else{ + + + //spoofing also happens here + int counter = 0; + for (counter = 0; counter < 0x1000; counter ++){ + if(memcmp((void*)vaddr + counter, magic, 7) == 0 && counter == 0x5B0){ + counter = counter + 4; + memcpy((void*) vaddr + counter, testkit_pscode, 8); + return 0; + } + } + } + + } + else{ + } + } + else + { + } + return 1; +} + +static int mmu_dump_sections(unsigned int vaddr, unsigned int entry) +{ + int ns; + int ss; + int ng; + int s; + int ap1; + int ap2; + int domain; + int xn; + int pr; + int pw; + int ur; + int uw; + unsigned int paddr; + unsigned int i; + unsigned int *tbl; + + + if ((entry & 0x3) == 2) /* section or supersection */ + { + ns = entry & 0x80000; + ss = entry & 0x40000; + ng = entry & 0x20000; + s = entry & 0x10000; + ap2 = entry & 0x8000; + ap1 = (entry >> 10) & 3; + domain = (entry >> 5) & 15; + xn = entry & 0x10; + mmu_get_perms(ap2, ap1, &ur, &uw, &pr, &pw); + paddr = ss ? entry & 0xFF000000 : entry & 0xFFF00000; + + } + else if ((entry & 0x3) == 1) /* page table */ + { + domain = (entry >> 5) & 15; + ns = entry & 8; + paddr = entry & 0xFFFFFC00; + tbl = (unsigned int *)pa2va(paddr); + for (i = 0; i < 0x100; i++) + { + int ret = mmu_dump_pages(vaddr+(i<<12), tbl[i]); + if (ret == 0) { + return 0; + } + } + } + else if ((entry & 0x3) == 0) /* not mapped */ + { + } + else + { + } + return 1; +} + +int mmu_dump(void) +{ + unsigned int ttbr[2]; + int ttbcr; + int n; + unsigned int i = 0; + + unsigned int *ttb_vaddr[2]; + unsigned int entry; + + + __asm__("mrc p15,0,%0,c2,c0,0" : "=r" (ttbr[0])); + __asm__("mrc p15,0,%0,c2,c0,1" : "=r" (ttbr[1])); + __asm__("mrc p15,0,%0,c2,c0,2" : "=r" (ttbcr)); + + n = ttbcr & 0x7; + ttbr[0] &= (unsigned int)((int)0x80000000 >> (31 - 14 + 1 - n)); + ttbr[1] &= 0xFFFFC000; + + ttb_vaddr[0] = (unsigned int *)pa2va(ttbr[0]); + ttb_vaddr[1] = (unsigned int *)pa2va(ttbr[1]); + + for (i = 0; i < (1 << (12 - n)); i++) + { + entry = ttb_vaddr[0][i]; + int ret = mmu_dump_sections(i<<20, entry); + if(ret == 0){ + return 0; + } + } + + if (n) + { + for (i = ((~0xEFFF & 0xFFFF) >> n); i < 0x1000; i++) + { + entry = ttb_vaddr[1][i]; + int ret = mmu_dump_sections(i<<20, entry); + if(ret == 0){ + return 0; + } + } + } + return 1; +} + +int module_start(SceSize argc, const void *args) +{ + unsigned int sctlr; + + __asm__("mrc p15,0,%0,c1,c0,0" : "=r" (sctlr)); + afe = sctlr & 0x20000000; + mmu_dump(); + + return SCE_KERNEL_START_SUCCESS; +} + +int module_stop(SceSize argc, const void *args) +{ + return SCE_KERNEL_STOP_SUCCESS; +} + + diff --git a/spoofer/mmu_dump.o b/spoofer/mmu_dump.o new file mode 100644 index 0000000..39cdad8 Binary files /dev/null and b/spoofer/mmu_dump.o differ diff --git a/user/CMakeLists.txt b/user/CMakeLists.txt new file mode 100644 index 0000000..309d1c8 --- /dev/null +++ b/user/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 2.8) + +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(DEFINED ENV{VITASDK}) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") + else() + message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") + endif() +endif() + +project(cex2rex_user) +include("${VITASDK}/share/vita.cmake" REQUIRED) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") + +add_executable(${PROJECT_NAME} + src/main.c +) + +target_link_libraries(${PROJECT_NAME} + SceLibKernel_stub + SceIofilemgr_stub + Cex2Rex_Kern_stub + SceLibc_stub +) + +vita_create_self(user.suprx ${PROJECT_NAME} CONFIG exports.yml UNSAFE) + +vita_create_stubs(stubs ${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/exports.yml) + +install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/ + DESTINATION lib + FILES_MATCHING PATTERN "*.a" +) + +install(FILES src/cex2rex_user.h + DESTINATION include +) + diff --git a/user/exports.yml b/user/exports.yml new file mode 100644 index 0000000..0b37eff --- /dev/null +++ b/user/exports.yml @@ -0,0 +1,16 @@ +Cex2Rex_User: + attributes: 0 + version: + major: 1 + minor: 0 + main: + start: module_start + stop: module_stop + modules: + uC2R: + syscall: false + functions: + - dd + - DecryptSpkgFile + - getTotalLeft + - scePowerSetCallbackEnabled \ No newline at end of file diff --git a/user/src/cex2rex_user.h b/user/src/cex2rex_user.h new file mode 100644 index 0000000..f308f15 --- /dev/null +++ b/user/src/cex2rex_user.h @@ -0,0 +1,6 @@ +#include + +int dd(char *inf, char *of, int size); +int DecryptSpkgFile(char *in, char *out); +int getTotalLeft(); +int scePowerSetCallbackEnabled(int enable); \ No newline at end of file diff --git a/user/src/main.c b/user/src/main.c new file mode 100644 index 0000000..db99b79 --- /dev/null +++ b/user/src/main.c @@ -0,0 +1,33 @@ +#include +#include +#include "cex2rex_user.h" + +int dd(char *inf, char *of, int size) +{ + return kdd(inf, of, size); +} + + +int DecryptSpkgFile(char *in, char *out) +{ + return kDecryptSpkgFile(in, out); +} + +int getTotalLeft() +{ + return kgetTotalLeft(); +} + +int scePowerSetCallbackEnabled(int enable) +{ + return kscePowerSetCallbackEnabledForUser(enable); +} + +void _start() __attribute__ ((weak, alias("module_start"))); +int module_start(SceSize args, void *argp) { + return SCE_KERNEL_START_SUCCESS; +} + +int module_stop(SceSize args, void *argp) { + return SCE_KERNEL_STOP_SUCCESS; +}