diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9516376 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 2.8) + +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(DEFINED ENV{VITASDK}) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") + else() + message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") + endif() +endif() + +set(SHORT_NAME storagemgr_installer) +project(${SHORT_NAME}) +include("${VITASDK}/share/vita.cmake" REQUIRED) + +set(VITA_APP_NAME "Storage Manager") +set(VITA_TITLEID "STORAGEMG") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -fno-builtin-printf") +set(VITA_MAKE_FSELF_FLAGS "${VITA_MAKE_FSELF_FLAGS} -a 0x2800000000000001") + +add_subdirectory(kernel) + +add_executable(${SHORT_NAME} + main.c + debug_screen.c + debug_screen_font.c +) + +target_link_libraries(${SHORT_NAME} + SceDisplay_stub + SceCtrl_stub + SceProcessmgr_stub + ScePower_stub + SceRegistryMgr_stub + SceAppMgr_stub + SceVshBridge_stub +) + +vita_create_self(${SHORT_NAME}.self ${SHORT_NAME} UNSAFE) + +vita_create_vpk(${SHORT_NAME}.vpk ${VITA_TITLEID} ${SHORT_NAME}.self + VERSION ${VITA_VERSION} + NAME ${VITA_APP_NAME} + FILE ${CMAKE_BINARY_DIR}/kernel/storagemgr.skprx storagemgr.skprx + FILE sce_sys/icon0.png sce_sys/icon0.png + FILE sce_sys/livearea/contents/startup.png sce_sys/livearea/contents/startup.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 +) + +add_dependencies(${SHORT_NAME}.vpk storagemgr.skprx) diff --git a/build.sh b/build.sh deleted file mode 100644 index 1e255d0..0000000 --- a/build.sh +++ /dev/null @@ -1,7 +0,0 @@ -cd kernel -mkdir build -cd build -cmake .. -make clean -make install -cd ../.. \ No newline at end of file diff --git a/debug_screen.c b/debug_screen.c new file mode 100644 index 0000000..126fb60 --- /dev/null +++ b/debug_screen.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include + +#include +#include +#include + +extern unsigned char psvDebugScreenFont[]; + +#define SCREEN_WIDTH (960) +#define SCREEN_HEIGHT (544) +#define SCREEN_FB_WIDTH (960) +#define SCREEN_FB_SIZE (2 * 1024 * 1024) +#define SCREEN_FB_ALIGN (256 * 1024) +#define SCREEN_GLYPH_W (8) +#define SCREEN_GLYPH_H (8) + +#define COLOR_BLACK 0xFF000000 +#define COLOR_RED 0xFF0000FF +#define COLOR_BLUE 0xFF00FF00 +#define COLOR_YELLOW 0xFF00FFFF +#define COLOR_GREEN 0xFFFF0000 +#define COLOR_MAGENTA 0xFFFF00FF +#define COLOR_CYAN 0xFFFFFF00 +#define COLOR_WHITE 0xFFFFFFFF +#define COLOR_GREY 0xFF808080 +#define COLOR_DEFAULT_FG COLOR_WHITE +#define COLOR_DEFAULT_BG COLOR_BLACK + +static int psvDebugScreenMutex; /*< avoid race condition when outputing strings */ +static uint32_t psvDebugScreenCoordX = 0; +static uint32_t psvDebugScreenCoordY = 0; +static uint32_t psvDebugScreenColorFg = COLOR_DEFAULT_FG; +static uint32_t psvDebugScreenColorBg = COLOR_DEFAULT_BG; +static SceDisplayFrameBuf psvDebugScreenFrameBuf = { + sizeof(SceDisplayFrameBuf), NULL, SCREEN_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; + +uint32_t psvDebugScreenSetFgColor(uint32_t color) { + uint32_t prev_color = psvDebugScreenColorFg; + psvDebugScreenColorFg = color; + return prev_color; +} + +uint32_t psvDebugScreenSetBgColor(uint32_t color) { + uint32_t prev_color = psvDebugScreenColorBg; + psvDebugScreenColorBg = color; + return prev_color; +} + +static size_t psvDebugScreenEscape(const char *str){ + int i,j, p=0, params[8]={}; + for(i=0; i<8 && str[i]!='\0'; i++){ + if(str[i] >= '0' && str[i] <= '9'){ + params[p]=(params[p]*10) + (str[i] - '0'); + }else if(str[i] == ';'){ + p++; + }else if(str[i] == 'f' || str[i] == 'H'){ + psvDebugScreenCoordX = params[0] * SCREEN_GLYPH_W; + psvDebugScreenCoordY = params[1] * SCREEN_GLYPH_H; + break; + }else if (str[i] == 'm'){ + for(j=0; j<=p; j++){ + switch(params[j]/10){/*bold,dim,underline,blink,invert,hidden => unsupported yet */ + #define BIT2BYTE(bit) ( ((!!(bit&4))<<23) | ((!!(bit&2))<<15) | ((!!(bit&1))<<7) ) + case 0:psvDebugScreenSetFgColor(COLOR_DEFAULT_FG);psvDebugScreenSetBgColor(COLOR_DEFAULT_BG);break; + case 3:psvDebugScreenSetFgColor(BIT2BYTE(params[j]%10));break; + case 9:psvDebugScreenSetFgColor(BIT2BYTE(params[j]%10) | 0x7F7F7F7F);break; + case 4:psvDebugScreenSetBgColor(BIT2BYTE(params[j]%10));break; + case 10:psvDebugScreenSetBgColor(BIT2BYTE(params[j]%10) | 0x7F7F7F7F);break; + #undef BIT2BYTE + } + } + break; + } + } + return i; +} + +int psvDebugScreenInit() { + psvDebugScreenMutex = sceKernelCreateMutex("log_mutex", 0, 0, NULL); + SceUID displayblock = sceKernelAllocMemBlock("display", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, SCREEN_FB_SIZE, NULL); + sceKernelGetMemBlockBase(displayblock, (void**)&psvDebugScreenFrameBuf.base); + + SceDisplayFrameBuf framebuf = { + .size = sizeof(framebuf), + .base = psvDebugScreenFrameBuf.base, + .pitch = SCREEN_WIDTH, + .pixelformat = SCE_DISPLAY_PIXELFORMAT_A8B8G8R8, + .width = SCREEN_WIDTH, + .height = SCREEN_HEIGHT, + }; + + return sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME); +} + +void psvDebugScreenClear(int bg_color){ + psvDebugScreenCoordX = psvDebugScreenCoordY = 0; + int i; + for(i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) { + ((uint32_t*)psvDebugScreenFrameBuf.base)[i] = bg_color; + } +} + +void* psvDebugScreenBase(void) { + return psvDebugScreenFrameBuf.base; +} + +int psvDebugScreenPuts(const char * text){ + int c, i, j, l; + uint8_t *font; + uint32_t *vram_ptr; + uint32_t *vram; + + sceKernelLockMutex(psvDebugScreenMutex, 1, NULL); + + for (c = 0; text[c] != '\0' ; c++) { + if (psvDebugScreenCoordX + 8 > SCREEN_WIDTH) { + psvDebugScreenCoordY += SCREEN_GLYPH_H; + psvDebugScreenCoordX = 0; + } + if (psvDebugScreenCoordY + 8 > SCREEN_HEIGHT) { + psvDebugScreenClear(psvDebugScreenColorBg); + } + if (text[c] == '\n') { + psvDebugScreenCoordX = 0; + psvDebugScreenCoordY += SCREEN_GLYPH_H; + continue; + } else if (text[c] == '\r') { + psvDebugScreenCoordX = 0; + continue; + } else if ((text[c] == '\e') && (text[c+1] == '[')) { /* escape code (change color, position ...) */ + c+=psvDebugScreenEscape(text+2)+2; + continue; + } + + vram = ((uint32_t*)psvDebugScreenFrameBuf.base) + psvDebugScreenCoordX + psvDebugScreenCoordY * SCREEN_FB_WIDTH; + + font = &psvDebugScreenFont[ (int)text[c] * 8]; + for (i = l = 0; i < SCREEN_GLYPH_W; i++, l += SCREEN_GLYPH_W, font++) { + vram_ptr = vram; + for (j = 0; j < SCREEN_GLYPH_W; j++) { + if ((*font & (128 >> j))) *vram_ptr = psvDebugScreenColorFg; + else *vram_ptr = psvDebugScreenColorBg; + vram_ptr++; + } + vram += SCREEN_FB_WIDTH; + } + psvDebugScreenCoordX += SCREEN_GLYPH_W; + } + + sceKernelUnlockMutex(psvDebugScreenMutex, 1); + return c; +} + +int psvDebugScreenPrintf(const char *format, ...) { + char buf[512]; + + va_list opt; + va_start(opt, format); + int ret = vsnprintf(buf, sizeof(buf), format, opt); + psvDebugScreenPuts(buf); + va_end(opt); + + return ret; +} diff --git a/debug_screen.h b/debug_screen.h new file mode 100644 index 0000000..e099d7a --- /dev/null +++ b/debug_screen.h @@ -0,0 +1,5 @@ +#pragma once + +int psvDebugScreenPrintf(const char *format, ...); +int psvDebugScreenInit(); +void* psvDebugScreenBase(void); diff --git a/debug_screen_font.c b/debug_screen_font.c new file mode 100644 index 0000000..b1ff939 --- /dev/null +++ b/debug_screen_font.c @@ -0,0 +1,145 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * font.c - Debug Font. + * + * Copyright (c) 2005 Marcus R. Brown + * Copyright (c) 2005 James Forshaw + * Copyright (c) 2005 John Kelley + * + * $Id: font.c 540 2005-07-08 19:35:10Z warren $ + */ + +unsigned char psvDebugScreenFont[]= +"\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x42\xa5\x81\xa5\x99\x42\x3c" +"\x3c\x7e\xdb\xff\xff\xdb\x66\x3c\x6c\xfe\xfe\xfe\x7c\x38\x10\x00" +"\x10\x38\x7c\xfe\x7c\x38\x10\x00\x10\x38\x54\xfe\x54\x10\x38\x00" +"\x10\x38\x7c\xfe\xfe\x10\x38\x00\x00\x00\x00\x30\x30\x00\x00\x00" +"\xff\xff\xff\xe7\xe7\xff\xff\xff\x38\x44\x82\x82\x82\x44\x38\x00" +"\xc7\xbb\x7d\x7d\x7d\xbb\xc7\xff\x0f\x03\x05\x79\x88\x88\x88\x70" +"\x38\x44\x44\x44\x38\x10\x7c\x10\x30\x28\x24\x24\x28\x20\xe0\xc0" +"\x3c\x24\x3c\x24\x24\xe4\xdc\x18\x10\x54\x38\xee\x38\x54\x10\x00" +"\x10\x10\x10\x7c\x10\x10\x10\x10\x10\x10\x10\xff\x00\x00\x00\x00" +"\x00\x00\x00\xff\x10\x10\x10\x10\x10\x10\x10\xf0\x10\x10\x10\x10" +"\x10\x10\x10\x1f\x10\x10\x10\x10\x10\x10\x10\xff\x10\x10\x10\x10" +"\x10\x10\x10\x10\x10\x10\x10\x10\x00\x00\x00\xff\x00\x00\x00\x00" +"\x00\x00\x00\x1f\x10\x10\x10\x10\x00\x00\x00\xf0\x10\x10\x10\x10" +"\x10\x10\x10\x1f\x00\x00\x00\x00\x10\x10\x10\xf0\x00\x00\x00\x00" +"\x81\x42\x24\x18\x18\x24\x42\x81\x01\x02\x04\x08\x10\x20\x40\x80" +"\x80\x40\x20\x10\x08\x04\x02\x01\x00\x10\x10\xff\x10\x10\x00\x00" +"\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20\x20\x20\x00\x00\x20\x00" +"\x50\x50\x50\x00\x00\x00\x00\x00\x50\x50\xf8\x50\xf8\x50\x50\x00" +"\x20\x78\xa0\x70\x28\xf0\x20\x00\xc0\xc8\x10\x20\x40\x98\x18\x00" +"\x40\xa0\x40\xa8\x90\x98\x60\x00\x10\x20\x40\x00\x00\x00\x00\x00" +"\x10\x20\x40\x40\x40\x20\x10\x00\x40\x20\x10\x10\x10\x20\x40\x00" +"\x20\xa8\x70\x20\x70\xa8\x20\x00\x00\x20\x20\xf8\x20\x20\x00\x00" +"\x00\x00\x00\x00\x00\x20\x20\x40\x00\x00\x00\x78\x00\x00\x00\x00" +"\x00\x00\x00\x00\x00\x60\x60\x00\x00\x00\x08\x10\x20\x40\x80\x00" +"\x70\x88\x98\xa8\xc8\x88\x70\x00\x20\x60\xa0\x20\x20\x20\xf8\x00" +"\x70\x88\x08\x10\x60\x80\xf8\x00\x70\x88\x08\x30\x08\x88\x70\x00" +"\x10\x30\x50\x90\xf8\x10\x10\x00\xf8\x80\xe0\x10\x08\x10\xe0\x00" +"\x30\x40\x80\xf0\x88\x88\x70\x00\xf8\x88\x10\x20\x20\x20\x20\x00" +"\x70\x88\x88\x70\x88\x88\x70\x00\x70\x88\x88\x78\x08\x10\x60\x00" +"\x00\x00\x20\x00\x00\x20\x00\x00\x00\x00\x20\x00\x00\x20\x20\x40" +"\x18\x30\x60\xc0\x60\x30\x18\x00\x00\x00\xf8\x00\xf8\x00\x00\x00" +"\xc0\x60\x30\x18\x30\x60\xc0\x00\x70\x88\x08\x10\x20\x00\x20\x00" +"\x70\x88\x08\x68\xa8\xa8\x70\x00\x20\x50\x88\x88\xf8\x88\x88\x00" +"\xf0\x48\x48\x70\x48\x48\xf0\x00\x30\x48\x80\x80\x80\x48\x30\x00" +"\xe0\x50\x48\x48\x48\x50\xe0\x00\xf8\x80\x80\xf0\x80\x80\xf8\x00" +"\xf8\x80\x80\xf0\x80\x80\x80\x00\x70\x88\x80\xb8\x88\x88\x70\x00" +"\x88\x88\x88\xf8\x88\x88\x88\x00\x70\x20\x20\x20\x20\x20\x70\x00" +"\x38\x10\x10\x10\x90\x90\x60\x00\x88\x90\xa0\xc0\xa0\x90\x88\x00" +"\x80\x80\x80\x80\x80\x80\xf8\x00\x88\xd8\xa8\xa8\x88\x88\x88\x00" +"\x88\xc8\xc8\xa8\x98\x98\x88\x00\x70\x88\x88\x88\x88\x88\x70\x00" +"\xf0\x88\x88\xf0\x80\x80\x80\x00\x70\x88\x88\x88\xa8\x90\x68\x00" +"\xf0\x88\x88\xf0\xa0\x90\x88\x00\x70\x88\x80\x70\x08\x88\x70\x00" +"\xf8\x20\x20\x20\x20\x20\x20\x00\x88\x88\x88\x88\x88\x88\x70\x00" +"\x88\x88\x88\x88\x50\x50\x20\x00\x88\x88\x88\xa8\xa8\xd8\x88\x00" +"\x88\x88\x50\x20\x50\x88\x88\x00\x88\x88\x88\x70\x20\x20\x20\x00" +"\xf8\x08\x10\x20\x40\x80\xf8\x00\x70\x40\x40\x40\x40\x40\x70\x00" +"\x00\x00\x80\x40\x20\x10\x08\x00\x70\x10\x10\x10\x10\x10\x70\x00" +"\x20\x50\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00" +"\x40\x20\x10\x00\x00\x00\x00\x00\x00\x00\x70\x08\x78\x88\x78\x00" +"\x80\x80\xb0\xc8\x88\xc8\xb0\x00\x00\x00\x70\x88\x80\x88\x70\x00" +"\x08\x08\x68\x98\x88\x98\x68\x00\x00\x00\x70\x88\xf8\x80\x70\x00" +"\x10\x28\x20\xf8\x20\x20\x20\x00\x00\x00\x68\x98\x98\x68\x08\x70" +"\x80\x80\xf0\x88\x88\x88\x88\x00\x20\x00\x60\x20\x20\x20\x70\x00" +"\x10\x00\x30\x10\x10\x10\x90\x60\x40\x40\x48\x50\x60\x50\x48\x00" +"\x60\x20\x20\x20\x20\x20\x70\x00\x00\x00\xd0\xa8\xa8\xa8\xa8\x00" +"\x00\x00\xb0\xc8\x88\x88\x88\x00\x00\x00\x70\x88\x88\x88\x70\x00" +"\x00\x00\xb0\xc8\xc8\xb0\x80\x80\x00\x00\x68\x98\x98\x68\x08\x08" +"\x00\x00\xb0\xc8\x80\x80\x80\x00\x00\x00\x78\x80\xf0\x08\xf0\x00" +"\x40\x40\xf0\x40\x40\x48\x30\x00\x00\x00\x90\x90\x90\x90\x68\x00" +"\x00\x00\x88\x88\x88\x50\x20\x00\x00\x00\x88\xa8\xa8\xa8\x50\x00" +"\x00\x00\x88\x50\x20\x50\x88\x00\x00\x00\x88\x88\x98\x68\x08\x70" +"\x00\x00\xf8\x10\x20\x40\xf8\x00\x18\x20\x20\x40\x20\x20\x18\x00" +"\x20\x20\x20\x00\x20\x20\x20\x00\xc0\x20\x20\x10\x20\x20\xc0\x00" +"\x40\xa8\x10\x00\x00\x00\x00\x00\x00\x00\x20\x50\xf8\x00\x00\x00" +"\x70\x88\x80\x80\x88\x70\x20\x60\x90\x00\x00\x90\x90\x90\x68\x00" +"\x10\x20\x70\x88\xf8\x80\x70\x00\x20\x50\x70\x08\x78\x88\x78\x00" +"\x48\x00\x70\x08\x78\x88\x78\x00\x20\x10\x70\x08\x78\x88\x78\x00" +"\x20\x00\x70\x08\x78\x88\x78\x00\x00\x70\x80\x80\x80\x70\x10\x60" +"\x20\x50\x70\x88\xf8\x80\x70\x00\x50\x00\x70\x88\xf8\x80\x70\x00" +"\x20\x10\x70\x88\xf8\x80\x70\x00\x50\x00\x00\x60\x20\x20\x70\x00" +"\x20\x50\x00\x60\x20\x20\x70\x00\x40\x20\x00\x60\x20\x20\x70\x00" +"\x50\x00\x20\x50\x88\xf8\x88\x00\x20\x00\x20\x50\x88\xf8\x88\x00" +"\x10\x20\xf8\x80\xf0\x80\xf8\x00\x00\x00\x6c\x12\x7e\x90\x6e\x00" +"\x3e\x50\x90\x9c\xf0\x90\x9e\x00\x60\x90\x00\x60\x90\x90\x60\x00" +"\x90\x00\x00\x60\x90\x90\x60\x00\x40\x20\x00\x60\x90\x90\x60\x00" +"\x40\xa0\x00\xa0\xa0\xa0\x50\x00\x40\x20\x00\xa0\xa0\xa0\x50\x00" +"\x90\x00\x90\x90\xb0\x50\x10\xe0\x50\x00\x70\x88\x88\x88\x70\x00" +"\x50\x00\x88\x88\x88\x88\x70\x00\x20\x20\x78\x80\x80\x78\x20\x20" +"\x18\x24\x20\xf8\x20\xe2\x5c\x00\x88\x50\x20\xf8\x20\xf8\x20\x00" +"\xc0\xa0\xa0\xc8\x9c\x88\x88\x8c\x18\x20\x20\xf8\x20\x20\x20\x40" +"\x10\x20\x70\x08\x78\x88\x78\x00\x10\x20\x00\x60\x20\x20\x70\x00" +"\x20\x40\x00\x60\x90\x90\x60\x00\x20\x40\x00\x90\x90\x90\x68\x00" +"\x50\xa0\x00\xa0\xd0\x90\x90\x00\x28\x50\x00\xc8\xa8\x98\x88\x00" +"\x00\x70\x08\x78\x88\x78\x00\xf8\x00\x60\x90\x90\x90\x60\x00\xf0" +"\x20\x00\x20\x40\x80\x88\x70\x00\x00\x00\x00\xf8\x80\x80\x00\x00" +"\x00\x00\x00\xf8\x08\x08\x00\x00\x84\x88\x90\xa8\x54\x84\x08\x1c" +"\x84\x88\x90\xa8\x58\xa8\x3c\x08\x20\x00\x00\x20\x20\x20\x20\x00" +"\x00\x00\x24\x48\x90\x48\x24\x00\x00\x00\x90\x48\x24\x48\x90\x00" +"\x28\x50\x20\x50\x88\xf8\x88\x00\x28\x50\x70\x08\x78\x88\x78\x00" +"\x28\x50\x00\x70\x20\x20\x70\x00\x28\x50\x00\x20\x20\x20\x70\x00" +"\x28\x50\x00\x70\x88\x88\x70\x00\x50\xa0\x00\x60\x90\x90\x60\x00" +"\x28\x50\x00\x88\x88\x88\x70\x00\x50\xa0\x00\xa0\xa0\xa0\x50\x00" +"\xfc\x48\x48\x48\xe8\x08\x50\x20\x00\x50\x00\x50\x50\x50\x10\x20" +"\xc0\x44\xc8\x54\xec\x54\x9e\x04\x10\xa8\x40\x00\x00\x00\x00\x00" +"\x00\x20\x50\x88\x50\x20\x00\x00\x88\x10\x20\x40\x80\x28\x00\x00" +"\x7c\xa8\xa8\x68\x28\x28\x28\x00\x38\x40\x30\x48\x48\x30\x08\x70" +"\x00\x00\x00\x00\x00\x00\xff\xff\xf0\xf0\xf0\xf0\x0f\x0f\x0f\x0f" +"\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00" +"\x00\x00\x00\x3c\x3c\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00" +"\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x0f\x0f\x0f\x0f\xf0\xf0\xf0\xf0" +"\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\x03\x03\x03\x03\x03\x03\x03\x03" +"\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x11\x22\x44\x88\x11\x22\x44\x88" +"\x88\x44\x22\x11\x88\x44\x22\x11\xfe\x7c\x38\x10\x00\x00\x00\x00" +"\x00\x00\x00\x00\x10\x38\x7c\xfe\x80\xc0\xe0\xf0\xe0\xc0\x80\x00" +"\x01\x03\x07\x0f\x07\x03\x01\x00\xff\x7e\x3c\x18\x18\x3c\x7e\xff" +"\x81\xc3\xe7\xff\xff\xe7\xc3\x81\xf0\xf0\xf0\xf0\x00\x00\x00\x00" +"\x00\x00\x00\x00\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x00\x00\x00\x00" +"\x00\x00\x00\x00\xf0\xf0\xf0\xf0\x33\x33\xcc\xcc\x33\x33\xcc\xcc" +"\x00\x20\x20\x50\x50\x88\xf8\x00\x20\x20\x70\x20\x70\x20\x20\x00" +"\x00\x00\x00\x50\x88\xa8\x50\x00\xff\xff\xff\xff\xff\xff\xff\xff" +"\x00\x00\x00\x00\xff\xff\xff\xff\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0" +"\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xff\xff\xff\xff\x00\x00\x00\x00" +"\x00\x00\x68\x90\x90\x90\x68\x00\x30\x48\x48\x70\x48\x48\x70\xc0" +"\xf8\x88\x80\x80\x80\x80\x80\x00\xf8\x50\x50\x50\x50\x50\x98\x00" +"\xf8\x88\x40\x20\x40\x88\xf8\x00\x00\x00\x78\x90\x90\x90\x60\x00" +"\x00\x50\x50\x50\x50\x68\x80\x80\x00\x50\xa0\x20\x20\x20\x20\x00" +"\xf8\x20\x70\xa8\xa8\x70\x20\xf8\x20\x50\x88\xf8\x88\x50\x20\x00" +"\x70\x88\x88\x88\x50\x50\xd8\x00\x30\x40\x40\x20\x50\x50\x50\x20" +"\x00\x00\x00\x50\xa8\xa8\x50\x00\x08\x70\xa8\xa8\xa8\x70\x80\x00" +"\x38\x40\x80\xf8\x80\x40\x38\x00\x70\x88\x88\x88\x88\x88\x88\x00" +"\x00\xf8\x00\xf8\x00\xf8\x00\x00\x20\x20\xf8\x20\x20\x00\xf8\x00" +"\xc0\x30\x08\x30\xc0\x00\xf8\x00\x18\x60\x80\x60\x18\x00\xf8\x00" +"\x10\x28\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xa0\x40" +"\x00\x20\x00\xf8\x00\x20\x00\x00\x00\x50\xa0\x00\x50\xa0\x00\x00" +"\x00\x18\x24\x24\x18\x00\x00\x00\x00\x30\x78\x78\x30\x00\x00\x00" +"\x00\x00\x00\x00\x30\x00\x00\x00\x3e\x20\x20\x20\xa0\x60\x20\x00" +"\xa0\x50\x50\x50\x00\x00\x00\x00\x40\xa0\x20\x40\xe0\x00\x00\x00" +"\x00\x38\x38\x38\x38\x38\x38\x00\x00\x00\x00\x00\x00\x00\x00"; + + diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index bd5406f..f0f9ae0 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -29,13 +29,20 @@ target_link_libraries(storagemgr SceModulemgrForDriver_stub SceThreadmgrForDriver_stub SceKernelSuspendForDriver_stub + + SceCtrlForDriver_stub + SceSysmemForDriver_stub + SceSblACMgrForDriver_stub + ScePowerForDriver_stub + SceModulemgrForKernel_stub + SceKernelSuspendForDriver_stub ) vita_create_self(storagemgr.skprx storagemgr CONFIG exports.yml UNSAFE) -vita_create_stubs(stubs storagemgr ${CMAKE_SOURCE_DIR}/exports.yml KERNEL) +vita_create_stubs(stubs storagemgr ${CMAKE_SOURCE_DIR}/kernel/exports.yml KERNEL) -install(DIRECTORY build/stubs/ +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/stubs/ DESTINATION lib FILES_MATCHING PATTERN "*.a" ) \ No newline at end of file diff --git a/kernel/main.c b/kernel/main.c index 4d5537d..60ed339 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include @@ -42,7 +44,7 @@ const char *log_ur0_path = "ur0:tai/storagemgr_log.txt"; int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func); int module_get_offset(SceUID pid, SceUID modid, int segidx, size_t offset, uintptr_t *addr); -const char* default_config_path = "ur0:tai/storage_config.txt"; +char* default_config_path = "ur0:tai/storage_config.txt"; typedef struct { const char *dev; @@ -116,6 +118,7 @@ typedef struct { #define UMA_BLKDEV2 "sdstor0:uma-lp-act-entire" #define GCD_BLKDEV "sdstor0:gcd-lp-ign-entire" #define GCD_BLKDEV2 NULL +#define SWAP_BUTTON SCE_CTRL_SQUARE static SceIoMountPoint *(* sceIoFindMountPoint)(int id) = NULL; @@ -882,6 +885,15 @@ int isEnsoLaunched(void) { return 1; } +int isSwapKeyPressed() { + ksceCtrlSetSamplingMode(SCE_CTRL_MODE_DIGITAL); + + SceCtrlData ctrl; + ksceCtrlPeekBufferPositive(0, &ctrl, 1); + + return ctrl.buttons & SWAP_BUTTON; +} + void _start() __attribute__ ((weak, alias("module_start"))); int module_start(SceSize args, void *argp) { @@ -913,6 +925,9 @@ int module_start(SceSize args, void *argp) { default: return -1; } + if (isSwapKeyPressed(SWAP_BUTTON)) { + default_config_path = "ur0:tai/storage_config_mod.txt"; + } UMAuma0 = 0; suspend_workaround(); // To keep uma0: mounted after PSVita exit suspend mode diff --git a/main.c b/main.c new file mode 100644 index 0000000..60203fd --- /dev/null +++ b/main.c @@ -0,0 +1,541 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "debug_screen.h" + +#define STORAGEMGR_INSTALL_PATH "ur0:tai/storagemgr.skprx" +#define GB_IN_BYTES (1073741824.0f) + +#define printf psvDebugScreenPrintf + +int configpath = 0; + +int _vshIoMount(int id, const char *path, int permission, void *buf); + +enum { + SCREEN_WIDTH = 960, + SCREEN_HEIGHT = 544, + PROGRESS_BAR_WIDTH = SCREEN_WIDTH, + PROGRESS_BAR_HEIGHT = 10, + LINE_SIZE = SCREEN_WIDTH, +}; + +static unsigned buttons[] = { + SCE_CTRL_SELECT, + SCE_CTRL_START, + SCE_CTRL_UP, + SCE_CTRL_RIGHT, + SCE_CTRL_DOWN, + SCE_CTRL_LEFT, + SCE_CTRL_LTRIGGER, + SCE_CTRL_RTRIGGER, + SCE_CTRL_TRIANGLE, + SCE_CTRL_CIRCLE, + SCE_CTRL_CROSS, + SCE_CTRL_SQUARE, +}; + +int vshIoMount(int id, const char *path, int permission, int a4, int a5, int a6) { + uint32_t buf[3]; + + buf[0] = a4; + buf[1] = a5; + buf[2] = a6; + + return _vshIoMount(id, path, permission, buf); +} + +uint32_t get_key(void) { + static unsigned prev = 0; + SceCtrlData pad; + while (1) { + memset(&pad, 0, sizeof(pad)); + sceCtrlPeekBufferPositive(0, &pad, 1); + unsigned new = prev ^ (pad.buttons & prev); + prev = pad.buttons; + for (size_t i = 0; i < sizeof(buttons)/sizeof(*buttons); ++i) + if (new & buttons[i]) + return buttons[i]; + + sceKernelDelayThread(1000); // 1ms + } +} + +void press_exit(void) { + printf("Press any key to exit this application.\n"); + get_key(); + sceKernelExitProcess(0); +} + +void press_reboot(void) { + printf("Press any key to reboot.\n"); + get_key(); + scePowerRequestColdReset(); +} + +void press_shutdown(void) { + printf("Press any key to power off.\n"); + get_key(); + scePowerRequestStandby(); +} + +void draw_rect(int x, int y, int width, int height, uint32_t color) { + void *base = psvDebugScreenBase(); + + for (int j = y; j < y + height; ++j) + for (int i = x; i < x + width; ++i) + ((uint32_t*)base)[j * LINE_SIZE + i] = color; +} + +int exists(const char *path) { + int fd = sceIoOpen(path, SCE_O_RDONLY, 0); + if (fd < 0) + return 0; + sceIoClose(fd); + return 1; +} + +int check_safe_mode(void) { + if (sceIoDevctl("ux0:", 0x3001, NULL, 0, NULL, 0) == 0x80010030) { + return 1; + } else { + return 0; + } +} + +int check_enso(void) { + return exists("ur0:tai/boot_config.txt") || exists("vs0:tai/boot_config.txt"); +} + +int copy_file(const char *dst, const char *src) { + char buffer[0x1000]; + int ret; + int off; + SceIoStat stat; + + printf("Copying %s ...\n", src); + + int fd = sceIoOpen(src, SCE_O_RDONLY, 0); + if (fd < 0) { + printf("sceIoOpen(%s): 0x%08X\n", src, fd); + return -1; + } + int wfd = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_TRUNC | SCE_O_CREAT, 0777); + if (wfd < 0) { + printf("sceIoOpen(%s): 0x%08X\n", dst, wfd); + sceIoClose(fd); + return -1; + } + ret = sceIoGetstatByFd(fd, &stat); + if (ret < 0) { + printf("sceIoGetstatByFd: 0x%08X\n", ret); + goto error; + } + ret = sceIoChstatByFd(wfd, &stat, SCE_CST_CT | SCE_CST_AT | SCE_CST_MT); + if (ret < 0) { + printf("sceIoChstat: 0x%08X\n", ret); + return -1; + } + + size_t rd, wr, total, write; + total = 0; + draw_rect(0, SCREEN_HEIGHT - PROGRESS_BAR_HEIGHT, PROGRESS_BAR_WIDTH, PROGRESS_BAR_HEIGHT, 0xFF666666); + while ((rd = sceIoRead(fd, buffer, sizeof(buffer))) > 0){ + off = 0; + while ((off += (wr = sceIoWrite(wfd, buffer+off, rd-off))) < rd){ + if (wr < 0){ + printf("sceIoWrite: 0x%08X\n", wr); + goto error; + } + } + total += rd; + draw_rect(1, SCREEN_HEIGHT - PROGRESS_BAR_HEIGHT + 1, ((uint64_t)(PROGRESS_BAR_WIDTH - 2)) * total / stat.st_size, PROGRESS_BAR_HEIGHT - 2, 0xFFFFFFFF); + } + if (rd < 0) { + printf("sceIoRead: 0x%08X\n", rd); + goto error; + } + + sceIoClose(fd); + sceIoClose(wfd); + + return 0; + +error: + sceIoClose(fd); + sceIoClose(wfd); + return -1; +} + +int find_config(const char *configpath, int remove) { + int fd; + int size; + char *buffer; + char *line; + size_t offset, newsize; + + if ((fd = sceIoOpen(configpath, SCE_O_RDONLY, 0)) < 0) { + return 0; + } + + size = sceIoLseek32(fd, 0, SEEK_END); + if (size < 0) { + sceIoClose(fd); + return 0; + } + if (sceIoLseek32(fd, 0, SEEK_SET) < 0) { + sceIoClose(fd); + return 0; + } + + buffer = malloc(size); + if (buffer == NULL) { + sceIoClose(fd); + return 0; + } + + int rd, total; + total = 0; + while ((rd = sceIoRead(fd, buffer+total, size-total)) > 0) { + total += rd; + } + sceIoClose(fd); + if (rd < 0 || total != size) { + free(buffer); + return 0; + } + + if ((line = strstr(buffer, STORAGEMGR_INSTALL_PATH "\n")) == NULL) { + free(buffer); + return 0; + } else { + if (remove) { + offset = (line - buffer); + newsize = size - strlen(STORAGEMGR_INSTALL_PATH "\n"); + memmove(line, line + strlen(STORAGEMGR_INSTALL_PATH "\n"), newsize - offset); + fd = sceIoOpen(configpath, SCE_O_TRUNC | SCE_O_CREAT | SCE_O_WRONLY, 6); + sceIoWrite(fd, buffer, newsize); + sceIoClose(fd); + } + free(buffer); + return 1; + } +} + +int install_config(const char *path) { + int fd; + + if (exists(path)) { + printf("%s detected!\n", path); + + if (find_config(path, 0)) { + printf("already installed to %s\n", path); + } else { + printf("installing to %s ", path); + fd = sceIoOpen(path, SCE_O_WRONLY | SCE_O_APPEND, 0); + sceIoWrite(fd, "\n*KERNEL\n", strlen("\n*KERNEL\n")); + sceIoWrite(fd, STORAGEMGR_INSTALL_PATH "\n", strlen(STORAGEMGR_INSTALL_PATH) + 1); + sceIoClose(fd); + if (fd < 0) { + printf("failed.\n"); + } else { + printf("success.\n"); + return 0; + } + } + } + return -1; +} + +int enable_modem(void) { + printf("\nenabling 3G modem... "); + if (sceRegMgrSetKeyInt("/CONFIG/TEL/", "use_debug_settings", 0) < 0) { + printf("failed.\n"); + } else { + printf("success.\n"); + } + + return 0; +} + +int disable_modem(void) { + printf("\ndisabling 3G modem... "); + if (sceRegMgrSetKeyInt("/CONFIG/TEL/", "use_debug_settings", 1) < 0) { + printf("failed.\n"); + } else { + printf("success.\n"); + } + + return 0; +} + +int install_plugin(void) { + printf("writing plugin...\n"); + if (copy_file(STORAGEMGR_INSTALL_PATH, "app0:storagemgr.skprx") < 0) { + printf("failed, plugin does not exists.\n"); + return -1; + } else { + printf("success.\n"); + } + + if (install_config("ur0:tai/config.txt") < 0) { + printf("failed install to ur0:tai/config.txt, perhaps you should upgrade HENkaku\n"); + return -1; + } + + vshIoMount(0xD00, NULL, 2, 0, 0, 0); + install_config("imc0:tai/config.txt"); + install_config("ux0:tai/config.txt"); + + disable_modem(); + + return 0; +} + +int uninstall_plugin(void) { + printf("deleting plugin... "); + if (sceIoRemove(STORAGEMGR_INSTALL_PATH) < 0) { + printf("failed.\n"); + return -1; + } else { + printf("success.\n"); + } + + if (find_config("ur0:tai/config.txt", 1)) { + printf("removed from ur0:tai/config.txt\n"); + } + + vshIoMount(0xD00, NULL, 2, 0, 0, 0); + if (find_config("imc0:tai/config.txt", 1)) { + printf("removed from imc0:tai/config.txt\n"); + } + if (find_config("ux0:tai/config.txt", 1)) { + printf("removed from ux0:tai/config.txt\n"); + } + + enable_modem(); + + return 0; +} + +int configure_modem(void) { + + printf(" CROSS Disable 3G Modem.\n"); + printf(" TRIANGLE Enable 3G Modem.\n"); + printf(" CIRCLE Exit App.\n"); + + switch (get_key()) { + case SCE_CTRL_CROSS: + disable_modem(); + break; + case SCE_CTRL_TRIANGLE: + enable_modem(); + break; + case SCE_CTRL_CIRCLE: + press_exit(); + break; + } + + return 0; +} + +int storage_config(const char *path, char *memcard, char *sd2vita, char *intmem, char *psvsd, int confpath) { + if (!exists(path)){ + if (confpath == 0){ + printf("storage_config.txt does not exist. Creating it... %s ", "\n"); + FILE *fd = fopen("ur0:tai/storage_config.txt", "w"); + } + else { + printf("storage_config_mod.txt does not exist. Creating it... %s ", "\n"); + FILE *fd = fopen("ur0:tai/storage_config_mod.txt", "w"); + } + } + else { + if (confpath == 0){ + printf("Clearing storage_config.txt for new settings... %s ", "\n"); + FILE *fd = fopen("ur0:tai/storage_config.txt", "w"); + } + else{ + printf("Clearing storage_config_mod.txt for new settings... %s ", "\n"); + FILE *fd = fopen("ur0:tai/storage_config_mod.txt", "w"); + } + } + + printf("Writing storage mount points to storage_config.txt... %s ", "\n"); + + int fd = sceIoOpen(path, SCE_O_WRONLY | SCE_O_APPEND, 0); + if (memcard != ""){ + sceIoWrite(fd, "MCD=", strlen("MCD=")); + sceIoWrite(fd, memcard, strlen(memcard) + 1); + } + if (intmem != ""){ + sceIoWrite(fd, "\nINT=", strlen("INT=") +1); + sceIoWrite(fd, intmem, strlen(intmem) + 1); + } + if (psvsd != ""){ + sceIoWrite(fd, "\nUMA=", strlen("UMA=") + 1); + sceIoWrite(fd, psvsd, strlen(psvsd) + 1); + } + if (sd2vita != ""){ + sceIoWrite(fd, "\nGCD=", strlen("GCD=") + 1); + sceIoWrite(fd, sd2vita, strlen(sd2vita) + 1); + } + sceIoClose(fd); + if (fd < 0) { + printf("failed.\n"); + } else { + printf("success.\n"); + return 0; + } +} + +char * mount_selection(void) { + char *selection = NULL; + + printf(" CROSS Mount as uma0.\n"); + printf(" TRIANGLE Mount as imc0.\n"); + printf(" SQUARE Mount as grw0.\n"); + printf(" CIRCLE Mount as ux0.\n"); + printf(" RTRIGGER Mount as xmc0.\n"); + printf(" LTRIGGER Do not mount.\n"); + +again: + switch (get_key()) { + case SCE_CTRL_CROSS: + selection = "uma0"; + break; + case SCE_CTRL_TRIANGLE: + selection = "imc0"; + break; + case SCE_CTRL_SQUARE: + selection = "grw0"; + break; + case SCE_CTRL_CIRCLE: + selection = "ux0"; + break; + case SCE_CTRL_RTRIGGER: + selection = "xmc0"; + break; + case SCE_CTRL_LTRIGGER: + selection = ""; + break; + default: + goto again; + } + + return selection; +} + +int configure_plugin(int confpath) { + + printf("\nSelect how to mount the Sony Memory Card.\n\n"); + char *memcard = mount_selection(); + + printf("\nSelect how to mount the SD2Vita Card.\n\n"); + char *sd2vita = mount_selection(); + + printf("\nSelect how to mount the Internal Memory.\n\n"); + char *intmem = mount_selection(); + + printf("\nSelect how to mount the USB Mass Storage (External on PSTV or PSVSD on 3G OLED).\n\n"); + char *psvsd = mount_selection(); + + if (confpath == 0) { + storage_config("ur0:tai/storage_config.txt", memcard, sd2vita, intmem, psvsd, confpath); + } + else { + storage_config("ur0:tai/storage_config_mod.txt", memcard, sd2vita, intmem, psvsd, confpath); + } + + return 0; +} + +int main(int argc, char *argv[]) { + (void)argc; + (void)argv; + + int ret = 0; + + psvDebugScreenInit(); + + if (check_safe_mode()) { + printf("Please enable HENkaku unsafe homebrew from Settings before running this installer.\n\n"); + press_exit(); + } + + if (!check_enso()) { + printf("HENkaku Enso must be installed and not deactivated. Visit https://enso.henkaku.xyz/ for more information.\n\n"); + press_exit(); + } + + if (!find_config("ur0:tai/config.txt", 0)) { + printf("Press CROSS to install and configure the plugin and reboot or any other key to exit.\n\n"); + + if (get_key() == SCE_CTRL_CROSS) { + install_plugin(); + if (!exists("ur0:tai/storage_config.txt")){ + configure_plugin(0); + } + else { + printf("storage_config.txt already exists. Press CROSS to re-configure or CIRCLE to keep the original.\n\n"); + switch (get_key()) { + case SCE_CTRL_CROSS: + break; + case SCE_CTRL_TRIANGLE: + configure_plugin(0); + break; + } + } + press_reboot(); + } + + sceKernelExitProcess(0); + } + + printf("Options:\n\n"); + printf(" CROSS Configure StorageMgr plugin. Warning this will clear current settings.\n"); + printf(" TRIANGLE Configure Alternate StorageMgr mount points.\n"); + printf(" SQUARE Enable or Disable the internal modem. (OLED 3G Models only)\n"); + printf(" CIRCLE Uninstall StorageMgr plugin.\n"); + printf(" RTRIGGER Exit without doing anything.\n\n"); + +again: + switch (get_key()) { + case SCE_CTRL_CROSS: + configpath = 0; + configure_plugin(configpath); + press_reboot(); + break; + case SCE_CTRL_TRIANGLE: + configpath = 1; + configure_plugin(configpath); + break; + case SCE_CTRL_SQUARE: + configure_modem(); + press_reboot(); + break; + case SCE_CTRL_CIRCLE: + uninstall_plugin(); + break; + case SCE_CTRL_RTRIGGER: + break; + default: + goto again; + } + + press_exit(); + + return 0; +} diff --git a/sce_sys/icon0.png b/sce_sys/icon0.png new file mode 100644 index 0000000..7defd95 Binary files /dev/null and b/sce_sys/icon0.png differ diff --git a/sce_sys/livearea/contents/bg.png b/sce_sys/livearea/contents/bg.png new file mode 100644 index 0000000..c533615 Binary files /dev/null and b/sce_sys/livearea/contents/bg.png differ diff --git a/sce_sys/livearea/contents/startup.png b/sce_sys/livearea/contents/startup.png new file mode 100644 index 0000000..43e55f8 Binary files /dev/null and b/sce_sys/livearea/contents/startup.png differ diff --git a/sce_sys/livearea/contents/template.xml b/sce_sys/livearea/contents/template.xml new file mode 100644 index 0000000..538070b --- /dev/null +++ b/sce_sys/livearea/contents/template.xml @@ -0,0 +1,35 @@ + + + + + bg.png + + + + startup.png + + + + + + StorageMgr + + + + + + + + by CelesteBlue + + + + + + + + v1.20 + + + +