CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Tools/SaveTool/main.c
Views: 1401
1
#include <pspsdk.h>
2
#include <pspkernel.h>
3
#include <pspdebug.h>
4
#include <pspmoduleinfo.h>
5
#include <pspctrl.h>
6
#include <pspchnnlsv.h>
7
#include <psputility.h>
8
#include "kernelcall/kernelcall.h"
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <string.h>
12
#include "encrypt.h"
13
#include "decrypt.h"
14
#include "psf.h"
15
16
#define printf pspDebugScreenPrintf
17
18
/* Define the module info section */
19
PSP_MODULE_INFO("ppssppsavetool", 0, 1, 0);
20
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
21
PSP_HEAP_SIZE_KB(-64);
22
23
#define ENCRYPT_FILE_VERSION 1
24
25
26
int currentMenu = 0;
27
int selectedOption = 0;
28
int basePath = 0;
29
int workDir = 0;
30
31
char *menuList0[] = {"Encrypt","Decrypt", "Exit", NULL};
32
char *menuList1[] = {"ms0:/PSP/SAVEDATAPPSSPP/","host0:/","host1:/", "host2:/", "Back", NULL};
33
char *menuList2[] = {"Back", NULL};
34
35
int GetSDKMainVersion(int sdkVersion)
36
{
37
if(sdkVersion > 0x307FFFF)
38
return 6;
39
if(sdkVersion > 0x300FFFF)
40
return 5;
41
if(sdkVersion > 0x206FFFF)
42
return 4;
43
if(sdkVersion > 0x205FFFF)
44
return 3;
45
if(sdkVersion >= 0x2000000)
46
return 2;
47
if(sdkVersion >= 0x1000000)
48
return 1;
49
return 0;
50
};
51
52
int ProcessInput(int maxOption, int *selectedOption)
53
{
54
SceCtrlData pad, oldpad;
55
sceCtrlReadBufferPositive(&oldpad, 1);
56
while(1)
57
{
58
sceCtrlReadBufferPositive(&pad, 1);
59
60
if (pad.Buttons != 0)
61
{
62
if (!(oldpad.Buttons & PSP_CTRL_CROSS) && pad.Buttons & PSP_CTRL_CROSS)
63
{
64
return *selectedOption;
65
}
66
else if (!(oldpad.Buttons & PSP_CTRL_UP) && pad.Buttons & PSP_CTRL_UP && *selectedOption > 0)
67
{
68
*selectedOption = *selectedOption-1;
69
return -1;
70
}
71
else if (!(oldpad.Buttons & PSP_CTRL_DOWN) && pad.Buttons & PSP_CTRL_DOWN && *selectedOption < maxOption-1)
72
{
73
*selectedOption = *selectedOption + 1;
74
return -1;
75
}
76
}
77
oldpad = pad;
78
}
79
}
80
81
typedef struct
82
{
83
char name[30];
84
char saveFile[30];
85
int errorId;
86
} DirInfo;
87
88
typedef struct
89
{
90
int fileVersion;
91
u8 key[16];
92
int sdkVersion;
93
} EncryptFileInfo;
94
95
DirInfo dirList[128];
96
int numDirList;
97
DirInfo invalidDirList[128];
98
int numInvalidDirList;
99
100
int FileExist(char* basePath, char* dirPath, char* fileName)
101
{
102
SceIoStat fileStat;
103
char path[1024];
104
sprintf(path,"%s%s/%s",basePath, dirPath, fileName);
105
if(sceIoGetstat(path, &fileStat) < 0) // no file
106
return 0;
107
return 1;
108
}
109
110
int FileRead(char* basePath, char* dirPath, char* fileName, u8* dataout, int size)
111
{
112
char path[1024];
113
sprintf(path,"%s%s/%s",basePath, dirPath, fileName);
114
SceUID fileId = sceIoOpen(path, PSP_O_RDONLY, 0777);
115
if(fileId < 0)
116
return -1;
117
sceIoRead(fileId, dataout, size);
118
sceIoClose(fileId);
119
return 0;
120
}
121
122
void AddErrorDir(char* dirName, int error)
123
{
124
if(numInvalidDirList >= 128)
125
return;
126
DirInfo *inf = &invalidDirList[numInvalidDirList];
127
strcpy(inf->name,dirName);
128
inf->errorId = error;
129
numInvalidDirList++;
130
}
131
132
int UpdateValidDir(int isEncrypt)
133
{
134
numDirList = 0;
135
numInvalidDirList = 0;
136
137
const char* pspPath = "ms0:/PSP/SAVEDATA/";
138
139
char* pathSrc;
140
char* pathDst;
141
if(isEncrypt)
142
{
143
pathSrc = menuList1[basePath];
144
pathDst = pspPath;
145
}
146
else
147
{
148
pathSrc = pspPath;
149
pathDst = menuList1[basePath];
150
}
151
152
int dfd;
153
dfd = sceIoDopen(menuList1[basePath]);
154
if(dfd >= 0)
155
{
156
SceIoDirent data;
157
while(sceIoDread(dfd, &data) > 0 && numDirList < 128)
158
{
159
if(!(data.d_stat.st_attr & 0x10)) // is not a directory
160
{
161
continue;
162
}
163
164
if(data.d_name[0] == '.') // ignore "." and ".."
165
continue;
166
167
if(FileExist(menuList1[basePath], data.d_name, "ENCRYPT_INFO.BIN") < 0)
168
{
169
AddErrorDir(data.d_name,1);
170
continue;
171
}
172
173
EncryptFileInfo encryptInfo;
174
if(FileRead(menuList1[basePath], data.d_name, "ENCRYPT_INFO.BIN",(u8*)&encryptInfo,sizeof(encryptInfo)) < 0)
175
{
176
AddErrorDir(data.d_name,2);
177
continue;
178
}
179
180
if(encryptInfo.fileVersion != ENCRYPT_FILE_VERSION) // Not good version
181
{
182
AddErrorDir(data.d_name,3);
183
continue;
184
}
185
186
if(FileExist(pathSrc, data.d_name, "PARAM.SFO") < 0)
187
{
188
AddErrorDir(data.d_name,4);
189
continue;
190
}
191
192
u8 paramsfo[0x1330];
193
if(FileRead(pathSrc, data.d_name, "PARAM.SFO",(u8*)&paramsfo,0x1330) < 0)
194
{
195
AddErrorDir(data.d_name,5);
196
continue;
197
}
198
199
u8 *datafile;
200
int listLen;
201
if (find_psf_section("SAVEDATA_FILE_LIST", paramsfo, 0x1330,
202
&datafile, &listLen) < 0)
203
{
204
AddErrorDir(data.d_name,6);
205
continue;
206
}
207
if(datafile[0] == 0)
208
{
209
AddErrorDir(data.d_name,7);
210
continue;
211
}
212
213
char filename[32];
214
strcpy(filename, (char*)datafile);
215
216
if(FileExist(pathSrc, data.d_name, filename) < 0)
217
{
218
AddErrorDir(data.d_name,8);
219
continue;
220
}
221
222
DirInfo *inf = &dirList[numDirList];
223
inf->errorId = 0;
224
strcpy(inf->name, data.d_name);
225
strcpy(inf->saveFile, filename);
226
227
numDirList++;
228
229
}
230
sceIoDclose(dfd);
231
if(numDirList == 0)
232
{
233
return -1;
234
}
235
}
236
else
237
{
238
return -2;
239
}
240
return 0;
241
}
242
243
int FileCopy(char* srcPath, char* destPath, char* fileName)
244
{
245
SceIoStat fileStat;
246
char path[258];
247
sprintf(path,"%s/%s",srcPath, fileName);
248
249
if(sceIoGetstat(path, &fileStat) < 0)
250
return -1;
251
u8* data = malloc(fileStat.st_size);
252
253
SceUID fileId = sceIoOpen(path, PSP_O_RDONLY, 0777);
254
if(fileId < 0)
255
{
256
printf("Fail opening %s\n",path);
257
free(data);
258
return -1;
259
}
260
sceIoRead(fileId, data, fileStat.st_size);
261
sceIoClose(fileId);
262
263
sprintf(path,"%s/%s",destPath, fileName);
264
265
fileId = sceIoOpen(path, PSP_O_WRONLY | PSP_O_CREAT, 0777);
266
if(fileId < 0)
267
{
268
printf("Fail opening %s\n",path);
269
return -1;
270
}
271
sceIoWrite(fileId, data, fileStat.st_size);
272
sceIoClose(fileId);
273
274
free(data);
275
return 0;
276
}
277
278
int main(int argc, char *argv[])
279
{
280
int i;
281
pspDebugScreenInit();
282
283
SceUID mod = pspSdkLoadStartModule ("flash0:/kd/chnnlsv.prx",PSP_MEMORY_PARTITION_KERNEL);
284
if (mod < 0) {
285
printf("Error 0x%08X loading/starting chnnlsv.prx.\n", mod);
286
}
287
288
mod = pspSdkLoadStartModule ("kernelcall.prx",PSP_MEMORY_PARTITION_KERNEL);
289
if (mod < 0) {
290
printf("Error 0x%08X loading/starting kernelcall.prx.\n", mod);
291
}
292
293
sceCtrlSetSamplingCycle(0);
294
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
295
for(;;)
296
{
297
printf("====================================================================");
298
printf("PPSSPP Save Tool\n");
299
printf("====================================================================\n\n\n");
300
301
switch(currentMenu)
302
{
303
304
case 0:
305
{
306
int maxOption = 0;
307
for(i = 0; menuList0[i]; i++)
308
{
309
if(i == selectedOption)
310
printf(" > %s\n",menuList0[i]);
311
else
312
printf(" %s\n",menuList0[i]);
313
maxOption++;
314
}
315
316
int input = ProcessInput(maxOption, &selectedOption);
317
if(input == 0)
318
{
319
currentMenu = 1;
320
selectedOption = 0;
321
}
322
else if(input == 1)
323
{
324
currentMenu = 4;
325
selectedOption = 0;
326
}
327
else if(input == 2)
328
{
329
sceKernelExitGame();
330
}
331
}
332
break;
333
case 4:
334
case 1:
335
{
336
int maxOption = 0;
337
printf("PPSSPP Decrypted Save Directory : \n");
338
for(i = 0; menuList1[i]; i++)
339
{
340
if(i == selectedOption)
341
printf(" > %s\n",menuList1[i]);
342
else
343
printf(" %s\n",menuList1[i]);
344
maxOption++;
345
}
346
347
int input = ProcessInput(maxOption, &selectedOption);
348
if(input == maxOption-1)
349
{
350
if(currentMenu == 1)
351
selectedOption = 0;
352
else
353
selectedOption = 1;
354
currentMenu = 0;
355
}
356
else if(input >= 0)
357
{
358
basePath = selectedOption;
359
if(currentMenu == 1)
360
{
361
currentMenu = 2;
362
UpdateValidDir(1);
363
}
364
else
365
{
366
currentMenu = 5;
367
UpdateValidDir(0);
368
}
369
selectedOption = 0;
370
}
371
}
372
break;
373
case 5:
374
case 2:
375
{
376
int maxOption = 0;
377
if(currentMenu == 2)
378
printf("Save to encrypt : \n");
379
else
380
printf("Save to decrypt : \n");
381
382
if(numDirList == 0)
383
{
384
printf("No compatible data, see README for help on use\n");
385
}
386
for(i = 0; i < numDirList; i++)
387
{
388
if(i == selectedOption)
389
printf(" > %s\n",dirList[i].name);
390
else
391
printf(" %s\n",dirList[i].name);
392
maxOption++;
393
}
394
395
for(i = 0; menuList2[i]; i++)
396
{
397
if((i+numDirList) == selectedOption)
398
printf(" > %s\n",menuList2[i]);
399
else
400
printf(" %s\n",menuList2[i]);
401
maxOption++;
402
}
403
404
printf("\n Invalid path : \n");
405
for(i = 0; i < numInvalidDirList && i < (22-numDirList); i++)
406
{
407
switch(invalidDirList[i].errorId)
408
{
409
case 1:
410
printf(" %s : ENCRYPT_INFO.BIN not found\n",invalidDirList[i].name);
411
break;
412
case 2:
413
printf(" %s : ENCRYPT_INFO.BIN read error\n",invalidDirList[i].name);
414
break;
415
case 3:
416
printf(" %s : ENCRYPT_INFO.BIN wrong version\n",invalidDirList[i].name);
417
break;
418
case 4:
419
printf(" %s : PARAM.SFO not found\n",invalidDirList[i].name);
420
break;
421
case 5:
422
printf(" %s : PARAM.SFO read error\n",invalidDirList[i].name);
423
break;
424
case 6:
425
printf(" %s : SAVEDATA_FILE_LIST not found in PARAM.SFO\n",invalidDirList[i].name);
426
break;
427
case 7:
428
printf(" %s : no save name in SAVEDATA_FILE_LIST\n",invalidDirList[i].name);
429
break;
430
case 8:
431
printf(" %s : no save found\n",invalidDirList[i].name);
432
break;
433
default:
434
break;
435
}
436
}
437
438
int input = ProcessInput(maxOption, &selectedOption);
439
if(input == numDirList)
440
{
441
if(currentMenu == 2)
442
currentMenu = 1;
443
else
444
currentMenu = 4;
445
selectedOption = basePath;
446
}
447
else if(input >= 0)
448
{
449
if(currentMenu == 2)
450
currentMenu = 3;
451
else
452
currentMenu = 6;
453
workDir = input;
454
selectedOption = 0;
455
}
456
}
457
break;
458
case 6:
459
case 3:
460
{
461
462
EncryptFileInfo encryptInfo;
463
if(FileRead(menuList1[basePath], dirList[workDir].name, "ENCRYPT_INFO.BIN",(u8*)&encryptInfo,sizeof(encryptInfo)) < 0)
464
{
465
printf("Can't read encrypt file\n");
466
}
467
else
468
{
469
printf("Key : ");
470
for(i = 0; i < 16; i++)
471
printf(" %02x",(u8)encryptInfo.key[i]);
472
printf("\n");
473
printf("SDK Version : 0x%x\n",encryptInfo.sdkVersion);
474
475
char srcPath[128];
476
char dstPath[128];
477
if(currentMenu == 3)
478
{
479
sprintf(srcPath,"%s%s",menuList1[basePath], dirList[workDir].name);
480
sprintf(dstPath,"ms0:/PSP/SAVEDATA/%s",dirList[workDir].name);
481
sceIoMkdir(dstPath,0777);
482
}
483
else
484
{
485
sprintf(srcPath,"ms0:/PSP/SAVEDATA/%s",dirList[workDir].name);
486
sprintf(dstPath,"%s%s",menuList1[basePath], dirList[workDir].name);
487
}
488
489
int dfd;
490
dfd = sceIoDopen(srcPath);
491
if(dfd >= 0)
492
{
493
SceIoDirent dirinfo;
494
while(sceIoDread(dfd, &dirinfo) > 0)
495
{
496
497
if(!(dirinfo.d_stat.st_mode & 0x2000)) // is not a file
498
continue;
499
500
if(strcmp(dirinfo.d_name,"ENCRYPT_INFO.BIN") == 0) // don't copy encrypt info
501
continue;
502
503
FileCopy(srcPath, dstPath, dirinfo.d_name);
504
505
}
506
sceIoDclose(dfd);
507
}
508
509
if(currentMenu == 3)
510
{
511
512
char decryptedFile[258], encryptedFile[258], srcSFO[258], dstSFO[258];
513
sprintf(decryptedFile,"%s/%s",srcPath ,dirList[workDir].saveFile);
514
sprintf(srcSFO,"%s/PARAM.SFO",srcPath);
515
516
sprintf(encryptedFile,"%s/%s",dstPath ,dirList[workDir].saveFile);
517
sprintf(dstSFO,"%s/PARAM.SFO",dstPath);
518
519
printf("Encoding %s into %s\n",decryptedFile, encryptedFile);
520
521
int ret = encrypt_file(decryptedFile,
522
encryptedFile,
523
dirList[workDir].saveFile,
524
srcSFO,
525
dstSFO,
526
encryptInfo.key[0] != 0 ? encryptInfo.key : NULL,
527
GetSDKMainVersion(encryptInfo.sdkVersion)
528
);
529
530
if(ret < 0) {
531
printf("Error: encrypt_file() returned %d\n\n", ret);
532
} else {
533
printf("Successfully wrote %d bytes to\n", ret);
534
printf(" %s\n", encryptedFile);
535
printf("and updated hashes in\n");
536
printf(" %s\n\n", dstSFO);
537
}
538
}
539
else
540
{
541
char decryptedFile[258], encryptedFile[258];
542
sprintf(encryptedFile,"%s/%s",srcPath ,dirList[workDir].saveFile);
543
sprintf(decryptedFile,"%s/%s",dstPath ,dirList[workDir].saveFile);
544
545
printf("Decoding %s into %s\n",encryptedFile, decryptedFile);
546
547
int ret = decrypt_file(decryptedFile, encryptedFile, encryptInfo.key[0] != 0 ? encryptInfo.key : NULL, GetSDKMainVersion(encryptInfo.sdkVersion));
548
549
if(ret < 0) {
550
printf("Error: decrypt_file() returned %d\n\n", ret);
551
} else {
552
printf("Successfully wrote %d bytes to\n", ret);
553
printf(" %s\n", decryptedFile);
554
}
555
}
556
printf(" > Back\n");
557
558
int input = ProcessInput(1, &selectedOption);
559
if(input >= 0)
560
{
561
if(currentMenu == 3)
562
currentMenu = 2;
563
else
564
currentMenu = 5;
565
selectedOption = 0;
566
}
567
}
568
}
569
break;
570
default:
571
sceKernelExitGame();
572
break;
573
}
574
575
pspDebugScreenClear();
576
sceDisplayWaitVblankStart();
577
sceGuSwapBuffers();
578
}
579
return 0;
580
}
581
582