CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Tools/SaveTool/main.c
Views: 1401
#include <pspsdk.h>1#include <pspkernel.h>2#include <pspdebug.h>3#include <pspmoduleinfo.h>4#include <pspctrl.h>5#include <pspchnnlsv.h>6#include <psputility.h>7#include "kernelcall/kernelcall.h"8#include <stdio.h>9#include <stdlib.h>10#include <string.h>11#include "encrypt.h"12#include "decrypt.h"13#include "psf.h"1415#define printf pspDebugScreenPrintf1617/* Define the module info section */18PSP_MODULE_INFO("ppssppsavetool", 0, 1, 0);19PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);20PSP_HEAP_SIZE_KB(-64);2122#define ENCRYPT_FILE_VERSION 1232425int currentMenu = 0;26int selectedOption = 0;27int basePath = 0;28int workDir = 0;2930char *menuList0[] = {"Encrypt","Decrypt", "Exit", NULL};31char *menuList1[] = {"ms0:/PSP/SAVEDATAPPSSPP/","host0:/","host1:/", "host2:/", "Back", NULL};32char *menuList2[] = {"Back", NULL};3334int GetSDKMainVersion(int sdkVersion)35{36if(sdkVersion > 0x307FFFF)37return 6;38if(sdkVersion > 0x300FFFF)39return 5;40if(sdkVersion > 0x206FFFF)41return 4;42if(sdkVersion > 0x205FFFF)43return 3;44if(sdkVersion >= 0x2000000)45return 2;46if(sdkVersion >= 0x1000000)47return 1;48return 0;49};5051int ProcessInput(int maxOption, int *selectedOption)52{53SceCtrlData pad, oldpad;54sceCtrlReadBufferPositive(&oldpad, 1);55while(1)56{57sceCtrlReadBufferPositive(&pad, 1);5859if (pad.Buttons != 0)60{61if (!(oldpad.Buttons & PSP_CTRL_CROSS) && pad.Buttons & PSP_CTRL_CROSS)62{63return *selectedOption;64}65else if (!(oldpad.Buttons & PSP_CTRL_UP) && pad.Buttons & PSP_CTRL_UP && *selectedOption > 0)66{67*selectedOption = *selectedOption-1;68return -1;69}70else if (!(oldpad.Buttons & PSP_CTRL_DOWN) && pad.Buttons & PSP_CTRL_DOWN && *selectedOption < maxOption-1)71{72*selectedOption = *selectedOption + 1;73return -1;74}75}76oldpad = pad;77}78}7980typedef struct81{82char name[30];83char saveFile[30];84int errorId;85} DirInfo;8687typedef struct88{89int fileVersion;90u8 key[16];91int sdkVersion;92} EncryptFileInfo;9394DirInfo dirList[128];95int numDirList;96DirInfo invalidDirList[128];97int numInvalidDirList;9899int FileExist(char* basePath, char* dirPath, char* fileName)100{101SceIoStat fileStat;102char path[1024];103sprintf(path,"%s%s/%s",basePath, dirPath, fileName);104if(sceIoGetstat(path, &fileStat) < 0) // no file105return 0;106return 1;107}108109int FileRead(char* basePath, char* dirPath, char* fileName, u8* dataout, int size)110{111char path[1024];112sprintf(path,"%s%s/%s",basePath, dirPath, fileName);113SceUID fileId = sceIoOpen(path, PSP_O_RDONLY, 0777);114if(fileId < 0)115return -1;116sceIoRead(fileId, dataout, size);117sceIoClose(fileId);118return 0;119}120121void AddErrorDir(char* dirName, int error)122{123if(numInvalidDirList >= 128)124return;125DirInfo *inf = &invalidDirList[numInvalidDirList];126strcpy(inf->name,dirName);127inf->errorId = error;128numInvalidDirList++;129}130131int UpdateValidDir(int isEncrypt)132{133numDirList = 0;134numInvalidDirList = 0;135136const char* pspPath = "ms0:/PSP/SAVEDATA/";137138char* pathSrc;139char* pathDst;140if(isEncrypt)141{142pathSrc = menuList1[basePath];143pathDst = pspPath;144}145else146{147pathSrc = pspPath;148pathDst = menuList1[basePath];149}150151int dfd;152dfd = sceIoDopen(menuList1[basePath]);153if(dfd >= 0)154{155SceIoDirent data;156while(sceIoDread(dfd, &data) > 0 && numDirList < 128)157{158if(!(data.d_stat.st_attr & 0x10)) // is not a directory159{160continue;161}162163if(data.d_name[0] == '.') // ignore "." and ".."164continue;165166if(FileExist(menuList1[basePath], data.d_name, "ENCRYPT_INFO.BIN") < 0)167{168AddErrorDir(data.d_name,1);169continue;170}171172EncryptFileInfo encryptInfo;173if(FileRead(menuList1[basePath], data.d_name, "ENCRYPT_INFO.BIN",(u8*)&encryptInfo,sizeof(encryptInfo)) < 0)174{175AddErrorDir(data.d_name,2);176continue;177}178179if(encryptInfo.fileVersion != ENCRYPT_FILE_VERSION) // Not good version180{181AddErrorDir(data.d_name,3);182continue;183}184185if(FileExist(pathSrc, data.d_name, "PARAM.SFO") < 0)186{187AddErrorDir(data.d_name,4);188continue;189}190191u8 paramsfo[0x1330];192if(FileRead(pathSrc, data.d_name, "PARAM.SFO",(u8*)¶msfo,0x1330) < 0)193{194AddErrorDir(data.d_name,5);195continue;196}197198u8 *datafile;199int listLen;200if (find_psf_section("SAVEDATA_FILE_LIST", paramsfo, 0x1330,201&datafile, &listLen) < 0)202{203AddErrorDir(data.d_name,6);204continue;205}206if(datafile[0] == 0)207{208AddErrorDir(data.d_name,7);209continue;210}211212char filename[32];213strcpy(filename, (char*)datafile);214215if(FileExist(pathSrc, data.d_name, filename) < 0)216{217AddErrorDir(data.d_name,8);218continue;219}220221DirInfo *inf = &dirList[numDirList];222inf->errorId = 0;223strcpy(inf->name, data.d_name);224strcpy(inf->saveFile, filename);225226numDirList++;227228}229sceIoDclose(dfd);230if(numDirList == 0)231{232return -1;233}234}235else236{237return -2;238}239return 0;240}241242int FileCopy(char* srcPath, char* destPath, char* fileName)243{244SceIoStat fileStat;245char path[258];246sprintf(path,"%s/%s",srcPath, fileName);247248if(sceIoGetstat(path, &fileStat) < 0)249return -1;250u8* data = malloc(fileStat.st_size);251252SceUID fileId = sceIoOpen(path, PSP_O_RDONLY, 0777);253if(fileId < 0)254{255printf("Fail opening %s\n",path);256free(data);257return -1;258}259sceIoRead(fileId, data, fileStat.st_size);260sceIoClose(fileId);261262sprintf(path,"%s/%s",destPath, fileName);263264fileId = sceIoOpen(path, PSP_O_WRONLY | PSP_O_CREAT, 0777);265if(fileId < 0)266{267printf("Fail opening %s\n",path);268return -1;269}270sceIoWrite(fileId, data, fileStat.st_size);271sceIoClose(fileId);272273free(data);274return 0;275}276277int main(int argc, char *argv[])278{279int i;280pspDebugScreenInit();281282SceUID mod = pspSdkLoadStartModule ("flash0:/kd/chnnlsv.prx",PSP_MEMORY_PARTITION_KERNEL);283if (mod < 0) {284printf("Error 0x%08X loading/starting chnnlsv.prx.\n", mod);285}286287mod = pspSdkLoadStartModule ("kernelcall.prx",PSP_MEMORY_PARTITION_KERNEL);288if (mod < 0) {289printf("Error 0x%08X loading/starting kernelcall.prx.\n", mod);290}291292sceCtrlSetSamplingCycle(0);293sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);294for(;;)295{296printf("====================================================================");297printf("PPSSPP Save Tool\n");298printf("====================================================================\n\n\n");299300switch(currentMenu)301{302303case 0:304{305int maxOption = 0;306for(i = 0; menuList0[i]; i++)307{308if(i == selectedOption)309printf(" > %s\n",menuList0[i]);310else311printf(" %s\n",menuList0[i]);312maxOption++;313}314315int input = ProcessInput(maxOption, &selectedOption);316if(input == 0)317{318currentMenu = 1;319selectedOption = 0;320}321else if(input == 1)322{323currentMenu = 4;324selectedOption = 0;325}326else if(input == 2)327{328sceKernelExitGame();329}330}331break;332case 4:333case 1:334{335int maxOption = 0;336printf("PPSSPP Decrypted Save Directory : \n");337for(i = 0; menuList1[i]; i++)338{339if(i == selectedOption)340printf(" > %s\n",menuList1[i]);341else342printf(" %s\n",menuList1[i]);343maxOption++;344}345346int input = ProcessInput(maxOption, &selectedOption);347if(input == maxOption-1)348{349if(currentMenu == 1)350selectedOption = 0;351else352selectedOption = 1;353currentMenu = 0;354}355else if(input >= 0)356{357basePath = selectedOption;358if(currentMenu == 1)359{360currentMenu = 2;361UpdateValidDir(1);362}363else364{365currentMenu = 5;366UpdateValidDir(0);367}368selectedOption = 0;369}370}371break;372case 5:373case 2:374{375int maxOption = 0;376if(currentMenu == 2)377printf("Save to encrypt : \n");378else379printf("Save to decrypt : \n");380381if(numDirList == 0)382{383printf("No compatible data, see README for help on use\n");384}385for(i = 0; i < numDirList; i++)386{387if(i == selectedOption)388printf(" > %s\n",dirList[i].name);389else390printf(" %s\n",dirList[i].name);391maxOption++;392}393394for(i = 0; menuList2[i]; i++)395{396if((i+numDirList) == selectedOption)397printf(" > %s\n",menuList2[i]);398else399printf(" %s\n",menuList2[i]);400maxOption++;401}402403printf("\n Invalid path : \n");404for(i = 0; i < numInvalidDirList && i < (22-numDirList); i++)405{406switch(invalidDirList[i].errorId)407{408case 1:409printf(" %s : ENCRYPT_INFO.BIN not found\n",invalidDirList[i].name);410break;411case 2:412printf(" %s : ENCRYPT_INFO.BIN read error\n",invalidDirList[i].name);413break;414case 3:415printf(" %s : ENCRYPT_INFO.BIN wrong version\n",invalidDirList[i].name);416break;417case 4:418printf(" %s : PARAM.SFO not found\n",invalidDirList[i].name);419break;420case 5:421printf(" %s : PARAM.SFO read error\n",invalidDirList[i].name);422break;423case 6:424printf(" %s : SAVEDATA_FILE_LIST not found in PARAM.SFO\n",invalidDirList[i].name);425break;426case 7:427printf(" %s : no save name in SAVEDATA_FILE_LIST\n",invalidDirList[i].name);428break;429case 8:430printf(" %s : no save found\n",invalidDirList[i].name);431break;432default:433break;434}435}436437int input = ProcessInput(maxOption, &selectedOption);438if(input == numDirList)439{440if(currentMenu == 2)441currentMenu = 1;442else443currentMenu = 4;444selectedOption = basePath;445}446else if(input >= 0)447{448if(currentMenu == 2)449currentMenu = 3;450else451currentMenu = 6;452workDir = input;453selectedOption = 0;454}455}456break;457case 6:458case 3:459{460461EncryptFileInfo encryptInfo;462if(FileRead(menuList1[basePath], dirList[workDir].name, "ENCRYPT_INFO.BIN",(u8*)&encryptInfo,sizeof(encryptInfo)) < 0)463{464printf("Can't read encrypt file\n");465}466else467{468printf("Key : ");469for(i = 0; i < 16; i++)470printf(" %02x",(u8)encryptInfo.key[i]);471printf("\n");472printf("SDK Version : 0x%x\n",encryptInfo.sdkVersion);473474char srcPath[128];475char dstPath[128];476if(currentMenu == 3)477{478sprintf(srcPath,"%s%s",menuList1[basePath], dirList[workDir].name);479sprintf(dstPath,"ms0:/PSP/SAVEDATA/%s",dirList[workDir].name);480sceIoMkdir(dstPath,0777);481}482else483{484sprintf(srcPath,"ms0:/PSP/SAVEDATA/%s",dirList[workDir].name);485sprintf(dstPath,"%s%s",menuList1[basePath], dirList[workDir].name);486}487488int dfd;489dfd = sceIoDopen(srcPath);490if(dfd >= 0)491{492SceIoDirent dirinfo;493while(sceIoDread(dfd, &dirinfo) > 0)494{495496if(!(dirinfo.d_stat.st_mode & 0x2000)) // is not a file497continue;498499if(strcmp(dirinfo.d_name,"ENCRYPT_INFO.BIN") == 0) // don't copy encrypt info500continue;501502FileCopy(srcPath, dstPath, dirinfo.d_name);503504}505sceIoDclose(dfd);506}507508if(currentMenu == 3)509{510511char decryptedFile[258], encryptedFile[258], srcSFO[258], dstSFO[258];512sprintf(decryptedFile,"%s/%s",srcPath ,dirList[workDir].saveFile);513sprintf(srcSFO,"%s/PARAM.SFO",srcPath);514515sprintf(encryptedFile,"%s/%s",dstPath ,dirList[workDir].saveFile);516sprintf(dstSFO,"%s/PARAM.SFO",dstPath);517518printf("Encoding %s into %s\n",decryptedFile, encryptedFile);519520int ret = encrypt_file(decryptedFile,521encryptedFile,522dirList[workDir].saveFile,523srcSFO,524dstSFO,525encryptInfo.key[0] != 0 ? encryptInfo.key : NULL,526GetSDKMainVersion(encryptInfo.sdkVersion)527);528529if(ret < 0) {530printf("Error: encrypt_file() returned %d\n\n", ret);531} else {532printf("Successfully wrote %d bytes to\n", ret);533printf(" %s\n", encryptedFile);534printf("and updated hashes in\n");535printf(" %s\n\n", dstSFO);536}537}538else539{540char decryptedFile[258], encryptedFile[258];541sprintf(encryptedFile,"%s/%s",srcPath ,dirList[workDir].saveFile);542sprintf(decryptedFile,"%s/%s",dstPath ,dirList[workDir].saveFile);543544printf("Decoding %s into %s\n",encryptedFile, decryptedFile);545546int ret = decrypt_file(decryptedFile, encryptedFile, encryptInfo.key[0] != 0 ? encryptInfo.key : NULL, GetSDKMainVersion(encryptInfo.sdkVersion));547548if(ret < 0) {549printf("Error: decrypt_file() returned %d\n\n", ret);550} else {551printf("Successfully wrote %d bytes to\n", ret);552printf(" %s\n", decryptedFile);553}554}555printf(" > Back\n");556557int input = ProcessInput(1, &selectedOption);558if(input >= 0)559{560if(currentMenu == 3)561currentMenu = 2;562else563currentMenu = 5;564selectedOption = 0;565}566}567}568break;569default:570sceKernelExitGame();571break;572}573574pspDebugScreenClear();575sceDisplayWaitVblankStart();576sceGuSwapBuffers();577}578return 0;579}580581582