Inital src

This commit is contained in:
AtelierWindows 2019-07-11 15:49:15 +12:00
parent 145414fb02
commit c29116774f
43 changed files with 3223 additions and 117 deletions

41
.gitignore vendored
View File

@ -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

View File

@ -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 <taihen.h>
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.

21
LICENSE
View File

@ -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.

View File

@ -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

33
app.xml Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<application project_name="*" version="1.00" runtime_version="2.00" sdk_version="2.00.00" default_locale="en-US">
<app_xml_format version="1.00.00" sdk_type="PSM SDK" />
<name />
<short_name />
<parental_control lock_level="2" />
<rating_list highest_age_limit="3" has_online_features="false">
<online_features chat="false" personal_info="false" user_location="false" exchange_content="false" />
<rating type="ESRB" value="3" age="3" code="" />
<rating type="PEGIEX" value="3" age="3" code="" />
</rating_list>
<images />
<genre_list />
<developer>
<name value="" />
</developer>
<website href="" />
<copyright author="" text="Interlectural Property Notices.txt" />
<purchase>
<product_list />
</purchase>
<runtime_config>
<memory managed_heap_size="32768" resource_heap_size="65536" />
<display max_screen_size="1280x800" />
<camera max_capture_resolution="800x600" />
</runtime_config>
<feature_list>
<feature value="GamePad" />
<feature value="Touch" />
<feature value="##SDKType:PSM SDK" />
</feature_list>
<psn_service_list />
</application>

70
app/CMakeLists.txt Normal file
View File

@ -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
)

BIN
app/app.info Normal file

Binary file not shown.

120
app/pstvConfig.txt Normal file
View File

@ -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:

BIN
app/sce_sys/icon0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<livearea style="psmobile" format-ver="01.00" content-rev="1">
<livearea-background>
<image>bg.png</image>
</livearea-background>
<frame id="frame4">
<liveitem>
<lang>ja</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| 知的財産の表記 |</str>
</text>
</liveitem>
<liveitem>
<lang>en</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Intellectual Property Notices |</str>
</text>
</liveitem>
<liveitem>
<lang>fr</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Avis de propriété intellectuelle |</str>
</text>
</liveitem>
<liveitem>
<lang>es</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Avisos sobre propiedad intelectual |</str>
</text>
</liveitem>
<liveitem>
<lang>de</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Geistiges Eigentum |</str>
</text>
</liveitem>
<liveitem>
<lang>it</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Avvisi sulla proprietà intellettuale |</str>
</text>
</liveitem>
<liveitem>
<lang>nl</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Intellectuele eigendomsmeldingen |</str>
</text>
</liveitem>
<liveitem>
<lang>pt</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Avisos de propriedade intelectual |</str>
</text>
</liveitem>
<liveitem>
<lang>ru</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Уведомления об интеллектуальной собственности |</str>
</text>
</liveitem>
<liveitem>
<lang>ko</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| 지적 재산권 표기 |</str>
</text>
</liveitem>
<liveitem>
<lang>ch</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| 知識產權資訊 |</str>
</text>
</liveitem>
<liveitem>
<lang>zh</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| 知识产权信息 |</str>
</text>
</liveitem>
<liveitem>
<lang>fi</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Immateriaalioikeudelliset huomautukset |</str>
</text>
</liveitem>
<liveitem>
<lang>sv</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Meddelande om upphovsrätt |</str>
</text>
</liveitem>
<liveitem>
<lang>da</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Meddelelser om immateriel ejendomsret |</str>
</text>
</liveitem>
<liveitem>
<lang>no</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Opphavsrettvarsel |</str>
</text>
</liveitem>
<liveitem>
<lang>pl</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Informacje dotyczące własności intelektualnej |</str>
</text>
</liveitem>
<liveitem>
<lang>pt-br</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Avisos de propriedade intelectual |</str>
</text>
</liveitem>
<liveitem>
<lang>en-gb</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Intellectual Property Notices |</str>
</text>
</liveitem>
<liveitem>
<lang>tr</lang>
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Fikri Mülkiyet Bildirimleri |</str>
</text>
</liveitem>
<liveitem default="on">
<target>psm_manual:ux0:psm/CEXR20202</target>
<text align="center" text-align="center" word-wrap="off" ellipsis="on">
<str size="18" color="#63FDFF" shadow="on">| Intellectual Property Notices |</str>
</text>
</liveitem>
</frame>
</livearea>

58
app/src/ctrl.c Normal file
View File

@ -0,0 +1,58 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <vitasdk.h>
#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);
}

2
app/src/ctrl.h Normal file
View File

@ -0,0 +1,2 @@
int get_key(int type);
void press_exit(void);

184
app/src/debugScreen.h Normal file
View File

@ -0,0 +1,184 @@
#ifndef DEBUG_SCREEN_H
#define DEBUG_SCREEN_H
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <inttypes.h>
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 <psp2/display.h>
#include <psp2/kernel/sysmem.h>
#include <psp2/kernel/threadmgr.h>
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

111
app/src/debugScreenFont.c Normal file
View File

@ -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 <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $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" // <space>
"\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" // <backslash>
"\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};

525
app/src/main.c Normal file
View File

@ -0,0 +1,525 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <vitasdk.h>
#include <taihen.h>
#include <cex2rex_user.h>
#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;
}

222
app/src/pup.c Normal file
View File

@ -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;i<header.file_count;i++){
scePlayStartionUpdatePackageExtractFiles(pup_dec_dir, file_check, i, header.file_count, temp_buff);
}
sceIoClose(file_check);
return 0;
}
int sceGetPlayStartionUpdatePackageType(int pup_type){
memset(pup_type_buf, 0, sizeof(pup_type_buf));
switch (pup_type){
case 4:sprintf(pup_type_buf, "TestKit");break;
//case 3:sprintf(pup_type_buf, "???\n");break;
case 2:sprintf(pup_type_buf, "Retail");break;
case 1:sprintf(pup_type_buf, "DevKit");break;
default:sprintf(pup_type_buf, "unknown");break;
}
return 0;
}
int sceGetPlayStartionUpdatePackageInfo(ScePlayStartionUpdatePackageHeader1 *header){
sceGetPlayStartionUpdatePackageType(header->pup_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;
}

102
app/src/pup.h Normal file
View File

@ -0,0 +1,102 @@
/*
* Adapted from Princess Of Sleeping's PUP extractor
* https://github.com/Princess-of-Sleeping/PSV-PUP-Extractor
*/
#include <psp2/kernel/processmgr.h>
#include <psp2/io/dirent.h>
#include <psp2/io/fcntl.h>
#include <psp2/io/stat.h>
#include <psp2/ctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);

139
app/vitaConfig.txt Normal file
View File

@ -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:

27
build.sh Normal file
View File

@ -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

51
kernel/CMakeLists.txt Normal file
View File

@ -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
)

16
kernel/exports.yml Normal file
View File

@ -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

View File

@ -0,0 +1,4 @@
int kdd(char *inf, char *of, int size);
int kDecryptSpkgFile(char *in, char *out);
int kgetTotalLeft();
int kscePowerSetCallbackEnabledForUser(int enable);

183
kernel/src/main.c Normal file
View File

@ -0,0 +1,183 @@
#include <vitasdkkern.h>
#include <stdio.h>
#include <string.h>
#include <taihen.h>
#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;
}

1
kernel/src/power.h Normal file
View File

@ -0,0 +1 @@
int kscePowerSetCallbackEnabled(int enable);

121
kernel/src/spkg.c Normal file
View File

@ -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 <psp2kern/kernel/cpu.h>
#include <psp2kern/kernel/utils.h>
#include <stdio.h>
#include <string.h>
#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;
}

78
kernel/src/spkg.h Normal file
View File

@ -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

1
kernel/src/sysroot.h Normal file
View File

@ -0,0 +1 @@
void* ksceKernelSysrootAlloc(int size);

42
kmspico/CMakeLists.txt Normal file
View File

@ -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"
)

8
kmspico/exports.yml Normal file
View File

@ -0,0 +1,8 @@
kmspico:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop

28
kmspico/src/main.c Normal file
View File

@ -0,0 +1,28 @@
#include <vitasdkkern.h>
#include <stdio.h>
#include <string.h>
#include <taihen.h>
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;
}

6
make_appinfo.bat Normal file
View File

@ -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"

View File

@ -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.

201
spoofer/LICENSE Normal file
View File

@ -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.

31
spoofer/Makefile Normal file
View File

@ -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."

7
spoofer/README.md Normal file
View File

@ -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!)

8
spoofer/exports.yml Normal file
View File

@ -0,0 +1,8 @@
vita_dump:
attributes: 0
version:
major: 1
minor: 1
main:
start: module_start
stop: module_stop

286
spoofer/mmu_dump.c Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#include <psp2kern/kernel/modulemgr.h>
#include <psp2kern/kernel/threadmgr.h>
#include <psp2kern/kernel/sysmem.h>
#include <psp2kern/io/fcntl.h>
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;
}

BIN
spoofer/mmu_dump.o Normal file

Binary file not shown.

40
user/CMakeLists.txt Normal file
View File

@ -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
)

16
user/exports.yml Normal file
View File

@ -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

6
user/src/cex2rex_user.h Normal file
View File

@ -0,0 +1,6 @@
#include <cex2rex_kern.h>
int dd(char *inf, char *of, int size);
int DecryptSpkgFile(char *in, char *out);
int getTotalLeft();
int scePowerSetCallbackEnabled(int enable);

33
user/src/main.c Normal file
View File

@ -0,0 +1,33 @@
#include <psp2/kernel/modulemgr.h>
#include <vitasdk.h>
#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;
}