-
-
Save kgsws/1806750e2b7dc5eb9b8170ef52d7189b to your computer and use it in GitHub Desktop.
This file contains hidden or 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
sc.killAutoHandle(); | |
function c32to8(data) | |
{ | |
var len = data.length; | |
var ret = new Uint8Array(len * 4); | |
var offs = 0; | |
for(i = 0; i < len; i++) | |
{ | |
ret[offs++] = data[i] & 0xFF; | |
ret[offs++] = (data[i] >> 8) & 0xFF; | |
ret[offs++] = (data[i] >> 16) & 0xFF; | |
ret[offs++] = data[i] >> 24; | |
} | |
return ret; | |
} | |
function c64to8(data) | |
{ | |
var len = data.length; | |
var ret = new Uint8Array(len * 8); | |
var offs = 0; | |
for(i = 0; i < len; i++) | |
{ | |
ret[offs++] = data[i][0] & 0xFF; | |
ret[offs++] = (data[i][0] >> 8) & 0xFF; | |
ret[offs++] = (data[i][0] >> 16) & 0xFF; | |
ret[offs++] = (data[i][0] >> 24) & 0xFF; | |
ret[offs++] = data[i][1] & 0xFF; | |
ret[offs++] = (data[i][1] >> 8) & 0xFF; | |
ret[offs++] = (data[i][1] >> 16) & 0xFF; | |
ret[offs++] = (data[i][1] >> 24) & 0xFF; | |
} | |
return ret; | |
} | |
function c8to32(data) | |
{ | |
var len = data.length / 4; | |
var ret = new Uint32Array(len); | |
var offs = 0; | |
for(i = 0; i < len; i++) | |
{ | |
ret[i] = data[offs++]; | |
ret[i] |= data[offs++] << 8; | |
ret[i] |= data[offs++] << 16; | |
ret[i] |= data[offs++] << 24; | |
} | |
return ret; | |
} | |
function _crc(data, len) | |
{ | |
var crc = 0; | |
for(j = 0; j < len; j++) | |
{ | |
var v = 0x80; | |
for(i = 0; i < 8; i++) | |
{ | |
var xorf = crc & 0x8000; | |
crc = (crc << 1) & 0xFFFF | |
if(data[j] & v) | |
crc = (crc + 1) & 0xFFFF; | |
if(xorf) | |
crc ^= 0x1021; | |
v >>= 1; | |
} | |
} | |
return crc; | |
} | |
function writePdm(payload) | |
{ | |
// var data = payload.buffer; | |
// utils.hexdump("dat", data); | |
sc.ipcMsg(4).sendTo('pdm:ntfy').assertOk(); | |
// sc.ipcMsg(5).aDescriptor(data, data.byteLength, 0).sendTo('pdm:ntfy').assertOk(); | |
sc.ipcMsg(5).aDescriptor(payload, payload.length, 0).sendTo('pdm:ntfy').assertOk(); | |
} | |
function getMiiAuthorId() | |
{ | |
return c32to8(sc.ipcMsg(90).sendTo('set:sys').assertOk().data); | |
} | |
function crcMiiBuf(b, authorid) | |
{ | |
var ret = new Uint8Array(b.length + 4); | |
ret.set(b); | |
var crc1 = _crc(ret, b.length + 2); | |
ret[b.length] = crc1 >> 8; | |
ret[b.length+1] = crc1 & 0xFF; | |
var temp = new Uint8Array(authorid.length + ret.length); | |
temp.set(authorid); | |
temp.set(ret, authorid.length); | |
var crc2 = _crc(temp, temp.length); | |
ret[b.length+2] = crc2 >> 8; | |
ret[b.length+3] = crc2 & 0xFF; | |
return ret; | |
} | |
function AddOrReplace(hnd, key, unm, authorid) | |
{ | |
var crcbuf = new Uint8Array(unm.length + key.length); | |
crcbuf.set(unm); | |
crcbuf.set(key, unm.length); | |
crcbuf = crcMiiBuf(crcbuf, authorid); | |
var new_mii = new Uint8Array(crcbuf.length + 4); | |
new_mii.set(crcbuf); | |
var new_mii_as_words = c8to32(new_mii); | |
var ipc = sc.ipcMsg(13); | |
ipc.datau32.apply(ipc, new_mii_as_words); | |
ipc.sendTo(hnd).assertOk(); | |
} | |
function Move(hnd, key, pos) | |
{ | |
var data = new Uint32Array(key.length / 4 + 1); | |
data.set(c8to32(key)); | |
data[data.length - 1] = pos; | |
var ipc = sc.ipcMsg(12); | |
ipc.datau32.apply(ipc, data); | |
ipc.sendTo(hnd).assertOk(); | |
} | |
function Delete(hnd, key) | |
{ | |
var data = c8to32(key); | |
var ipc = sc.ipcMsg(14); | |
ipc.datau32.apply(ipc, data); | |
ipc.sendTo(hnd).assertOk(); | |
} | |
function GetCount(hnd) | |
{ | |
ret = sc.ipcMsg(2).datau32(1).sendTo(hnd).assertOk().data[0]; | |
// utils.log("mii count is " + ret.toString()); | |
return ret; | |
} | |
function GetDefault(hnd, offset) | |
{ | |
ret = sc.ipcMsg(7).datau32(offset).sendTo(hnd).assertOk(); | |
return ret.data; | |
} | |
function GetLoadBase(hnd, authorid) | |
{ | |
var unm = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x97, 0x02, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); | |
var key = c64to8([[0xcafe, 0], [0xcafe0080, 0]]); | |
AddOrReplace(hnd, key, unm, authorid); | |
var data = GetDefault(hnd, (0x010b4b20 + 0xC + 0x44 * (GetCount(hnd) - 1) - 0x01079438) / 4); | |
Delete(hnd, key); | |
return utils.add2([data[5], data[6]], -0x9c540); | |
} | |
function Wipe(hnd) | |
{ | |
var buf = new Uint8Array(100*0x44); | |
var count = sc.ipcMsg(9).data(1).bDescriptor(buf, buf.length, 0).sendTo(hnd).assertOk().data[0]; | |
if(!count) | |
return; | |
utils.log("mii count to delete " + count.toString()); | |
var key = new Uint8Array(16); | |
for(mii = 0; mii < count; mii++) | |
{ | |
for(j = 0; j < 16; j++) | |
key[j] = buf[j + 48 + mii * 0x44]; | |
Delete(hnd, key); | |
} | |
} | |
function getServicePid(service) | |
{ | |
var res = this.ipcMsg(2).setType(3).datau64(0).sendTo(service).assertOk(); | |
this.svcCloseHandle(res.movedHandles[0]); | |
return res.pid[0]; | |
}; | |
function checkMiiCode(code) | |
{ | |
var checker = [0,1,2,3,4,5,6,7,8,16,17,18,19,20,21,22,23,24,32,33,34,35,36,37,38,39,40,48,49,50,51,52,53,54,55,56,64,65,66,67,68,69,70,71,72,80,81,82,83,84,85,86,87,88,96,97,98,99,100,101,102,103,104,112,113,114,115,116,117,118,119,120,128,129,130,131,132,133,134,135,136]; | |
return checker.indexOf(code) >= 0; | |
} | |
authorid = getMiiAuthorId(); | |
utils.log("Author ID: " + Array.apply([], authorid).join(",")); | |
// wipe all miis | |
handle = sc.ipcMsg(0).data(0xA523B78F).sendTo('mii:e').assertOk().movedHandles[0]; | |
utils.log("mii handle is 0x" + handle.toString(16)); | |
utils.log("wipe miis ..."); | |
Wipe(handle); | |
resetcount = 0; | |
sdbPid = getServicePid(handle); | |
tid = utils.parseAddr('0100000000000039'); | |
utils.log("reloading, this might take a while ..."); | |
while(1) | |
{ | |
sdbBase = GetLoadBase(handle, authorid); | |
// utils.log("sdbBase at " + utils.paddr(sdbBase)); | |
if(checkMiiCode(sdbBase[0] >>> 24) && checkMiiCode((sdbBase[0] >>> 16) & 0xFF) && sdbBase[1] > 0) | |
{ | |
sc.svcCloseHandle(handle); | |
utils.log("sdb pid is 0x" + sdbPid.toString(16) + " sdbBase at " + utils.paddr(sdbBase)); | |
utils.log("** good base ***"); | |
break; | |
} else | |
{ | |
// utils.log("this is a bad base 0x" + sdbBase[0].toString(16)); | |
sc.svcCloseHandle(handle); | |
// restart sdb | |
sc.ipcMsg(1).data(sdbPid).sendTo('pm:shell').assertOk(); | |
sdbPid = this.sc.ipcMsg(0).datau64(0, tid, 3).sendTo('pm:shell').data[0]; | |
if(!(resetcount & 15)) | |
utils.log("new sdb pid: 0x" + sdbPid.toString(16)); | |
sc.killAutoHandle(); | |
handle = sc.ipcMsg(0).data(0xA523B78F).sendTo('mii:e').assertOk().movedHandles[0]; | |
// utils.log("mii handle is 0x" + handle.toString(16)); | |
} | |
resetcount++; | |
} | |
utils.log("done"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This script resets sdb module until it's load address is usable.
Note: it also wipes all your Miis.