-
-
Save AcK77/56b86469faef238157a0e02cb962ee30 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Provide with the courtesy of the mob. | |
Ac_K. (Thanks to SciresM) | |
---------------- | |
- If mount partition gamecard failed try again (and again...). | |
- Partition: 0 - Header/Update | 1 - Normal/Secure. | |
- At the end, just merge all *.xci files on the SD Card to get a full *.xci dump. | |
Windows: copy /b TitleID-0.xci + TitleID-1.xci.0 + TitleID-1.xci.1 TitleID.xci | |
Linux: cat TitleID-0.xci TitleID-1.xci.0 TitleID-1.xci.1 > TitleID.xci | |
- You can verify your dump with Hactool. | |
*/ | |
sc.getFSPPR = function () { | |
if (sc.closed_pr !== undefined) { | |
return; | |
} | |
sc.enableTurbo(); | |
var i = 0; | |
var FspPr_Handle = null; | |
while (true) { | |
sc.ipcMsg(2).setType(5).sendTo('pm:shell'); | |
var FspPr = sc.getService('fsp-pr'); | |
if(FspPr.isOk) { | |
FspPr_Handle = FspPr.getValue(); | |
break; | |
} | |
i++; | |
} | |
utils.log('Got fsp-pr handle after ' + i + ' iterations: '); | |
utils.log('fsp-pr handle: 0x' + FspPr_Handle.toString(16)); | |
sc.svcCloseHandle(FspPr_Handle).assertOk(); | |
sc.closed_pr = true; | |
}; | |
sc.getFSPPR(); | |
sc.enableTurbo(); | |
if(sc.pr_handle) { | |
sc.svcCloseHandle(sc.pr_handle); | |
sc.pr_handle = undefined; | |
} | |
sc.getService("fsp-pr", (FspPr_Handle) => { | |
var pid = sc.getService('fsp-srv', (FspSrv_Handle) => { | |
utils.log("got fspsrv"); | |
sc.ipcMsg(1).sendPid().data(0).sendTo(FspSrv_Handle).assertOk(); | |
return sc.read4(sc.ipcBufAddr, 0xC >> 2); | |
}); | |
utils.log('Got process PID: '+pid.toString(16)); | |
var buf1_sz = 0x1C; | |
var buf2_sz = 0x2C; | |
var buf = sc.malloc(buf1_sz + buf2_sz); | |
var buf2 = utils.add2(buf, buf1_sz); | |
// buffer init | |
sc.write4(1, buf, 0x0>>2); | |
sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf, 0x4 >> 2); // This is the permissions value. | |
sc.write4(buf1_sz, buf, 0xC >> 2); | |
sc.write4(buf1_sz, buf, 0x14 >> 2); | |
sc.write4(1, buf2, 0x0 >> 2); | |
sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf2, 0x4 >> 2); // This is the permissions value -- actual perms = buf2_val & buf1_val | |
sc.write4(0xFFFFFFFF, buf2, 0x14 >> 2); | |
sc.write4(0xFFFFFFFF, buf2, 0x18 >> 2); | |
sc.write4(0xFFFFFFFF, buf2, 0x24 >> 2); | |
sc.write4(0xFFFFFFFF, buf2, 0x28 >> 2); | |
/* Change to mount a particular title's romfs */ | |
var tid = '0000000000000000'; | |
sc.ipcMsg(256).data(0).sendTo(FspPr_Handle).assertOk().show(); | |
sc.ipcMsg(1).data(pid).sendTo(FspPr_Handle).assertOk().show(); | |
sc.ipcMsg(0).data(2, [pid,0], utils.parseAddr(tid), buf1_sz, buf2_sz, pid, pid, 0, 0, 0, 0, 0).aDescriptor(buf, buf1_sz).aDescriptor(buf2, buf2_sz).sendTo(FspPr_Handle).assertOk().show(); | |
sc.free(buf); | |
sc.free(buf2); | |
}); | |
dumpIStorage = function(IStorage_Handle, SDCard_Handle, File_Path, isExFat) { | |
if (isExFat == undefined) isExFat = false; | |
sc.withHandle(IStorage_Handle, () => { | |
var size = sc.ipcMsg(4).sendTo(IStorage_Handle).assertOk().data; | |
utils.log('IStorage size: ' + utils.paddr(size)); | |
var two_gigs = 0x80000000 >>> 0; | |
var outbuf = new ArrayBuffer(0x1000000); | |
var buf_sz = 0x1000000; | |
var out_path = File_Path; | |
if ((size[1] > 0 || size[0] > two_gigs) && !isExFat) { | |
out_path = File_Path + '.0'; | |
IFileSystemCreateFile(SDCard_Handle, out_path, two_gigs); | |
} else { | |
IFileSystemCreateFile(SDCard_Handle, out_path, size); | |
} | |
var IFile_Handle = IFileSystemOpenFile(SDCard_Handle, out_path); | |
var offset = [0, 0]; | |
var ofs_in_file = 0; | |
var file_num = 0; | |
while (offset[0] < size[0] || offset[1] < size[1]) { | |
if (offset[1] == size[1] && size[0] < offset[0] + buf_sz) { | |
buf_sz = size[0] - offset[0]; | |
utils.log('Final block!'); | |
} | |
sc.ipcMsg(0).datau64(offset, buf_sz).bDescriptor(outbuf, buf_sz, 1).sendTo(IStorage_Handle).assertOk(); | |
IFileSystemWriteBufferToFile(IFile_Handle, ofs_in_file, outbuf, buf_sz); | |
offset = utils.add2(offset, buf_sz); | |
utils.log('Dumped: '+utils.paddr(offset)+'/'+utils.paddr(size)); | |
// Multi-part files. | |
ofs_in_file += buf_sz; | |
if (ofs_in_file >= two_gigs && !isExFat) { | |
sc.ipcMsg(2).sendTo(IFile_Handle).assertOk(); // flush | |
sc.svcCloseHandle(IFile_Handle); | |
file_num++; | |
var new_path = File_Path + '.' + file_num; | |
if (size[1] > offset[1] || size[0] > two_gigs + offset[0]) { | |
IFileSystemCreateFile(SDCard_Handle, new_path, two_gigs); | |
} else { | |
IFileSystemCreateFile(SDCard_Handle, new_path, size[0] - offset[0]); | |
} | |
IFile_Handle = IFileSystemOpenFile(SDCard_Handle, new_path); | |
ofs_in_file = 0; | |
} | |
} | |
sc.ipcMsg(2).sendTo(IFile_Handle).assertOk(); | |
sc.svcCloseHandle(IFile_Handle).assertOk(); | |
}); | |
}; | |
IFileSystemCreateFile = function(IFileSystem_Handle, path, size) { | |
if (size == undefined) size = 0x100; | |
var pbuf = utils.str2ab(path); | |
var res = sc.ipcMsg(0).data([0, 0], utils.trunc32(size)).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(IFileSystem_Handle); | |
utils.log('Create '+path+' (size '+size.toString(16)+'): '); | |
res.show(); | |
}; | |
IFileSystemWriteBufferToFile = function(IFile_Handle, offset, buf, sz) { | |
sc.ipcMsg(1).aDescriptor(buf, sz, 1).data([0,0], utils.pad64(offset), utils.trunc32(sz)).sendTo(IFile_Handle).show().assertOk(); | |
}; | |
IFileSystemOpenFile = function(IFileSystem_Handle, path) { | |
var pbuf = utils.str2ab(path); | |
utils.log('Open '+path+': '); | |
return sc.ipcMsg(8).datau32(3).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(IFileSystem_Handle).show().asResult().map((r) => r.movedHandles[0]).getValue(); | |
}; | |
buf2hex = function(buffer) { // buffer is an ArrayBuffer | |
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).reverse().join(''); | |
} | |
dumpXCI = function (SDCard_Handle, FspSrv_Handle) { | |
sc.getService('ncm', (Ncm_Handle) => { | |
sc.ipcMsg(11).data(2).sendTo(Ncm_Handle).assertOk(); //OpenIContentMetaDatabase | |
var IContentMetaDatabase = sc.ipcMsg(5).data(2).sendTo(Ncm_Handle).assertOk(); //GetIContentMetaDatabase | |
sc.withHandle(IContentMetaDatabase.movedHandles[0], (IContentMetaDatabase_Handle) => { | |
var TitleId = new ArrayBuffer(0x8); | |
sc.ipcMsg(7).data(0).bDescriptor(TitleId, 24, 0).sendTo(IContentMetaDatabase_Handle).assertOk(); //ListApplicationa | |
TitleId = buf2hex(TitleId); | |
utils.log("Got GameCardTitleId: " + TitleId); | |
var OpenDeviceOperator = sc.ipcMsg(400).sendTo(FspSrv_Handle).assertOk(); //OpenDeviceOperator | |
sc.withHandle(OpenDeviceOperator.movedHandles[0], (OpenDeviceOperator_handle) => { | |
utils.log('Got OpenDeviceOperator handle: 0x'+ OpenDeviceOperator_handle.toString(16)); | |
var GetGameCardHandle = sc.ipcMsg(202).sendTo(OpenDeviceOperator_handle).assertOk(); //GetGameCardHandle | |
GetGameCardHandle = GetGameCardHandle.data[0]; | |
utils.log('Got GetGameCardHandle handle: 0x'+ GetGameCardHandle.toString(16)); | |
for (var i = 0; i < 2; i++) { // Dump partitions 0 & 1 | |
var IStorage = sc.ipcMsg(30).datau32(GetGameCardHandle, i).sendTo(FspSrv_Handle).asResult(); //OpenGameCardStorage | |
if (IStorage.isOk) { | |
IStorage = IStorage.getValue(); | |
sc.withHandle(IStorage.movedHandles[0], (IStorage_Handle) => { | |
dumpIStorage(IStorage_Handle, SDCard_Handle, '/' + TitleId + '-' + i + '.xci', false); | |
}); | |
} else { | |
utils.log('Failed to mount partition '+i); | |
} | |
} | |
}); | |
}); | |
}); | |
}; | |
sc.getService('fsp-srv', (FspSrv_Handle) => { | |
utils.log('Using fsp-srv handle: 0x' + FspSrv_Handle.toString(16)); | |
sc.ipcMsg(1).sendPid().datau64(0).sendTo(FspSrv_Handle).assertOk(); | |
utils.log('Initialized fsp-srv'); | |
try { | |
var IFileSystem = sc.ipcMsg(18).sendTo(FspSrv_Handle).assertOk(); | |
} catch(e) { | |
throw new Error('Failed to open SD card. Is it inserted?'); | |
} | |
utils.log('SdCard Mounted'); | |
IFileSystem.withHandles((r, m, c) => { | |
var SDCard_Handle = m[0]; | |
dumpXCI(SDCard_Handle, FspSrv_Handle); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment