-
-
Save AcK77/8e9ac39ed9ead40261b90e0ca0ae64b6 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. | |
*/ | |
CrashFspPr = function(callback) { | |
if (sc.closed_pr !== undefined) return; | |
sc.enableTurbo(); | |
var i = 0; | |
while (true) { | |
sc.ipcMsg(2).setType(5).sendTo('pm:shell'); | |
var fsppr_result = sc.getService('fsp-pr'); | |
if(fsppr_result.isOk) { | |
fsppr_handle = fsppr_result.getValue(); | |
break; | |
} | |
i++; | |
} | |
utils.log('Got fsp-pr handle after ' + i + ' iterations: 0x' + fsppr_handle.toString(16)); | |
sc.svcCloseHandle(fsppr_handle).assertOk(); | |
sc.closed_pr = true; | |
if(sc.pr_handle) { | |
sc.svcCloseHandle(sc.pr_handle); | |
sc.pr_handle = undefined; | |
} | |
sc.enableTurbo(); | |
callback(); | |
}; | |
HookFspLdrHandle = function(callback){ | |
var fspldr_handle = sc.getService('fsp-ldr'); | |
if (fspldr_handle.isOk) | |
{ | |
var i = 0; | |
while (true) { | |
sc.ipcMsg(2).setType(5).sendTo('ldr:dmnt'); | |
fspldr_handle = sc.getService('fsp-ldr'); | |
if (fspldr_handle.isOk) break; | |
i++; | |
} | |
utils.log('Got fsp-ldr handle after ' + i + ' iterations: 0x' + fspldr_handle.toString(16)); | |
fspldr_handle = fspldr_handle.assertOk(); | |
} | |
callback(fspldr_handle); | |
}; | |
HookFspSrvPerms = function(callback) { //by SciresM | |
sc.getService('fsp-pr', (fsppr_hd) => { | |
var pid = sc.getService('fsp-srv', (tmp_hnd) => { | |
utils.log('Got fsp-srv'); | |
sc.ipcMsg(1).sendPid().data(0).sendTo(tmp_hnd).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_hd).assertOk().show(); | |
sc.ipcMsg(1).data(pid).sendTo(fsppr_hd).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_hd).assertOk().show(); | |
sc.free(buf); | |
sc.free(buf2); | |
callback(); | |
}); | |
}; | |
FspSrvInit = function(callback) { | |
sc.getService('fsp-srv', (fspsrv_Handle) => { | |
sc.ipcMsg(1).sendPid().datau64(0).sendTo(fspsrv_Handle).assertOk(); | |
utils.log("Initialized fsp-srv"); | |
callback(fspsrv_Handle); | |
}); | |
}; | |
function buf2hex(buffer) { // buffer is an ArrayBuffer | |
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).reverse().join(''); | |
} | |
GetGameCardTitleId = function(callback) { | |
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 | |
callback(buf2hex(TitleId)); | |
}); | |
}); | |
}; | |
MoundSdCard = function(fspsrv_handle, callback) { //by SciresM | |
var SD_IFileSystem; | |
try { | |
SD_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"); | |
SD_IFileSystem.withHandles((r, m, c) => { | |
callback(m[0]); | |
}); | |
}; | |
IFileSystemCreateFile = function(ifs_hnd, path, size) { //by SciresM | |
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(ifs_hnd); | |
utils.log('Create '+path+' (size ' + size.toString(16) + ')'); | |
res.show(); | |
// ignore failure, it probably just means the file already existed | |
//res.assertOk(); | |
}; | |
IFileSystemWriteBufferToFile = function(f_hnd, offset, buf, sz) { //by SciresM | |
sc.ipcMsg(1).aDescriptor(buf, sz, 1).data([0,0], utils.pad64(offset), utils.trunc32(sz)).sendTo(f_hnd).show().assertOk(); | |
}; | |
IFileSystemOpenFilepenDirectory = function(ifs_hnd, path) { //by SciresM | |
var pbuf = utils.str2ab(path); | |
return sc.ipcMsg(9).datau32(3).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(ifs_hnd).asResult().map((r) => r.movedHandles[0]).getValue(); | |
}; | |
IFileSystemOpenFile = function(ifs_hnd, path) { //by SciresM | |
var pbuf = utils.str2ab(path); | |
utils.log('Open ' + path); | |
return sc.ipcMsg(8).datau32(3).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(ifs_hnd).show().asResult().map((r) => r.movedHandles[0]).getValue(); | |
}; | |
IFileSystemOpenReadFile = function(ifs_hnd, path) { //by SciresM | |
var pbuf = utils.str2ab(path); | |
utils.log('Open '+path+': '); | |
return sc.ipcMsg(8).datau32(1).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(ifs_hnd).show().asResult().map((r) => r.movedHandles[0]).getValue(); | |
}; | |
IFileSystemCreateDirectory = function(ifs_hnd, path) { | |
var pbuf = utils.str2ab(path); | |
var res = sc.ipcMsg(2).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(ifs_hnd); | |
utils.log('Create '+path+' directory'); | |
res.show(); | |
}; | |
IDirectoryGetEntryCount = function (iDir_hnd) { | |
return sc.ipcMsg(1).sendTo(iDir_hnd).asResult().map((r) => [r.dataBuffer[0], r.dataBuffer[1]]); | |
}; | |
IDirectoryGetEntries = function (iDir_hnd, buf, numEntries) { | |
if(buf.byteLength < 0x310 * numEntries) { | |
throw new Error("buffer too small"); | |
} | |
return sc.ipcMsg(0).data(0).bDescriptor(buf, 0x310 * numEntries, 0).sendTo(iDir_hnd).asResult(); | |
}; | |
IFileGetSize = function (iFile_hnd) { | |
return sc.ipcMsg(4).sendTo(iFile_hnd).assertOk().data; | |
}; | |
IFileRead = function (iFile_hnd, offset, buf_sz, outbuf) { | |
return sc.ipcMsg(0).datau64(0, offset, buf_sz).bDescriptor(outbuf, buf_sz, 1).sendTo(iFile_hnd).assertOk(); | |
}; | |
DumpIFileSystem = function(IFileSystem, sdcard_Handle, Partition_path) { | |
var IDirectory = IFileSystemOpenFilepenDirectory(IFileSystem, '/'); | |
sc.withHandle(IDirectory, () => { | |
utils.log('Got IDirectory handle: 0x'+ IDirectory.toString(16)); | |
var entryCount = utils.trunc32(IDirectoryGetEntryCount(IDirectory).assertOk()); | |
if (entryCount > 0) { | |
var entryBuf = new Uint32Array(0x310 * entryCount); | |
IDirectoryGetEntries(IDirectory, entryBuf, entryCount).assertOk(); | |
for (i = 0; i < entryCount; i++) { | |
var IFilePath = '/' + utils.u8a2nullstr(new Uint8Array(entryBuf.buffer, 0x310 * i, 0x300)); | |
var eType = entryBuf[(0x310 * i + 0x304) >> 2]; | |
if (eType === 1) { | |
var IFile = IFileSystemOpenReadFile(IFileSystem, IFilePath); | |
sc.withHandle(IFile, () => { | |
var IFileSize = IFileGetSize(IFile); | |
utils.log('Size: ' + IFileSize + 'bytes - ' + IFilePath); | |
//SciresM Code. | |
utils.log('size: '+utils.paddr(IFileSize)); | |
var two_gigs = 0x80000000 >>> 0; | |
var outbuf = new ArrayBuffer(0x1000000); | |
var buf_sz = 0x1000000; | |
var out_path = Partition_path + IFilePath; | |
if ((IFileSize[1] > 0 || IFileSize[0] > two_gigs)) { | |
out_path = Partition_path + IFilePath + '.0'; | |
IFileSystemCreateFile(sdcard_Handle, out_path, two_gigs); | |
} else { | |
IFileSystemCreateFile(sdcard_Handle, out_path, IFileSize); | |
} | |
var f_hnd = IFileSystemOpenFile(sdcard_Handle, out_path); | |
var offset = [0, 0]; | |
var ofs_in_file = 0; | |
var file_num = 0; | |
while (offset[0] < IFileSize[0] || offset[1] < IFileSize[1]) { | |
if (offset[1] == IFileSize[1] && IFileSize[0] < offset[0] + buf_sz) { | |
buf_sz = IFileSize[0] - offset[0]; | |
utils.log('Final block!'); | |
} | |
IFileRead(IFile, offset, buf_sz, outbuf); | |
IFileSystemWriteBufferToFile(f_hnd, ofs_in_file, outbuf, buf_sz); | |
offset = utils.add2(offset, buf_sz); | |
utils.log('Dumped: '+utils.paddr(offset)+'/'+utils.paddr(IFileSize)); | |
// Multi-part files. | |
ofs_in_file += buf_sz; | |
if (ofs_in_file >= two_gigs) { | |
sc.ipcMsg(2).sendTo(f_hnd).assertOk(); // flush | |
sc.svcCloseHandle(f_hnd); | |
file_num++; | |
var new_path = Partition_path + IFilePath + '.' + file_num; | |
if (IFileSize[1] > offset[1] || IFileSize[0] > two_gigs + offset[0]) { | |
IFileSystemCreateFile(sdcard_Handle, new_path, two_gigs); | |
} else { | |
IFileSystemCreateFile(sdcard_Handle, new_path, IFileSize[0] - offset[0]); | |
} | |
f_hnd = IFileSystemOpenFile(sdcard_Handle, new_path); | |
ofs_in_file = 0; | |
} | |
} | |
sc.ipcMsg(2).sendTo(f_hnd).assertOk(); | |
sc.svcCloseHandle(f_hnd).assertOk(); | |
}); | |
} | |
} | |
} | |
}); | |
}; | |
//Partition 0 - Update | 1 - Normal | 2 - Secure | |
MountAndDumpGameCard = function(fspsrv_Handle, sdcard_Handle, TitleId) { | |
var Partition_ID = 2; | |
var Partition_Path = '/' + TitleId + '/' + Partition_ID; | |
IFileSystemCreateDirectory(sdcard_Handle, Partition_Path); | |
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]; | |
var IFileSystem = sc.ipcMsg(31).datau32(GetGameCardHandle, Partition_ID).sendTo(fspsrv_Handle).show(); //OpenGameCardFileSystem | |
sc.withHandle(IFileSystem.movedHandles[0], (IFileSystem_handle) => { | |
utils.log('Gamecard Mounted! Got handle: 0x'+ IFileSystem_handle.toString(16)); | |
DumpIFileSystem(IFileSystem_handle, sdcard_Handle, Partition_Path); | |
}); | |
}); | |
}; | |
CrashFspPr(function() { | |
HookFspSrvPerms(function() { | |
FspSrvInit(function(fspsrv_Handle) { | |
MoundSdCard(fspsrv_Handle, function(sdcard_Handle) { | |
GetGameCardTitleId(function(TitleId) { | |
utils.log("GameCardTitleId: " + TitleId); | |
IFileSystemCreateDirectory(sdcard_Handle, '/' + TitleId); | |
MountAndDumpGameCard(fspsrv_Handle, sdcard_Handle, TitleId); | |
}); | |
}); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment