mirror of
https://github.com/zoogie/TADpole-Online.git
synced 2025-06-18 18:55:41 -04:00
additions & fixes
* browser version checker * normalkey extraction error fixed
This commit is contained in:
parent
984a0e3ab9
commit
0b6b31330e
17
index.html
17
index.html
@ -23,6 +23,7 @@
|
||||
<script src="public/js/custom/fileAccess.js"></script>
|
||||
<script src="public/js/custom/validation.js"></script>
|
||||
<script src="public/js/custom/extraction.js"></script>
|
||||
<script src="public/js/custom/signing.js"></script>
|
||||
<script src="public/js/custom/injection.js"></script>
|
||||
<script src="public/js/custom/building.js"></script>
|
||||
<script src="public/js/custom/msed.js"></script>
|
||||
@ -32,6 +33,12 @@
|
||||
|
||||
<meta name="description" content="DSiWare Injector for Seedminer.">
|
||||
<meta property="og:image" content="https://i.imgur.com/CVSu1zc.png">
|
||||
|
||||
<script>
|
||||
$(document).ready(() => {
|
||||
checkBrowserVersion();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -76,11 +83,17 @@
|
||||
</ul>
|
||||
</ul>
|
||||
<br/>
|
||||
<h5>Compatible Browsers</h5>
|
||||
<h5>Compatible Browser Versions:</h5>
|
||||
<p>
|
||||
<u>green:</u> recommended,
|
||||
<u>orange:</u> probably works,
|
||||
<u>red:</u> dont even try</p>
|
||||
<u>red:</u> dont even try
|
||||
</p>
|
||||
<div class="div-browser-version" style="display:non;">
|
||||
<p style="font-weight:bold;font-size:150%;float:left;">Your Browser: </p>
|
||||
<p class="p-browser-version" style="font-weight:bold;font-size:150%;"></p>
|
||||
<p class="p-browser-error" style="font-weight:bold;font-size:150%;"></p>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="li-browser-good">Chrome >= 60</li>
|
||||
<li class="li-browser-good">Firefox >= 50</li>
|
||||
|
@ -7,7 +7,8 @@ function extractNormalKey(movableKeyY, keyXHex) {
|
||||
n = n.xor(keyY).add(c).and(f128);
|
||||
n = n.shiftLeft(87).or(n.shiftRight(128 - 87)).and(f128);
|
||||
let arr = n.toArray(256).value;
|
||||
return (arr[0] === 0) ? arr.slice(1) : arr;
|
||||
while (arr.length < 16) arr = [0].concat(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
function extractDsiware(dsiware, normalKey) {
|
||||
@ -24,7 +25,7 @@ function extractDsiware(dsiware, normalKey) {
|
||||
|
||||
/* content list extr & decrypt */
|
||||
let buffer = sliceArr(header, 0x48, 0x2C).buffer;
|
||||
let sizes = new Int32Array(buffer)
|
||||
let sizes = new Int32Array(buffer);
|
||||
sizes.forEach((s, i) => { if (s === 0xB34) sizes[i] = 0xB40 });
|
||||
|
||||
let other = {};
|
||||
|
@ -8,7 +8,7 @@ function loadFiles() {
|
||||
|
||||
if (!fileDsiware.files.length || !fileMovable.files.length || !fileGame.files.length
|
||||
|| !fileSave.files.length || !fileCtcert.files.length)
|
||||
return resolve('Not all files provided');
|
||||
return reject('Not all files provided');
|
||||
|
||||
let promises = [];
|
||||
promises.push(loadFile(fileDsiware));
|
||||
|
@ -2,7 +2,6 @@ function start() {
|
||||
$('.btn-startInjection')[0].disabled = true;
|
||||
document.getElementById("p-error").innerHTML = '';
|
||||
loadFiles().then(data => {
|
||||
if (typeof data !== 'object') return abort(data);
|
||||
let dsiware = data[0];
|
||||
let movable = data[1];
|
||||
let game = data[2];
|
||||
@ -10,13 +9,13 @@ function start() {
|
||||
let ctcert = data[4];
|
||||
|
||||
/* Validation */
|
||||
if (movable.length !== 0x140) return abort('movable.sed not valid');
|
||||
if (ctcert.length !== 0x19E) return abort('ctcert.bin not valid');
|
||||
if (movable.length !== 0x140 && movable.length !== 0x120) throw new Error('movable.sed size not valid');
|
||||
if (ctcert.length !== 0x19E) throw new Error('ctcert.bin not valid');
|
||||
|
||||
let crcGame = getCrc(game);
|
||||
if (!constants.hashes.all.includes(crcGame)) return abort('game_XXX.app is not valid');
|
||||
if (!constants.hashes.all.includes(crcGame)) throw new Error('game_XXX.app is not valid');
|
||||
let crcSave = getCrc(save);
|
||||
if (!constants.hashes.all.includes(crcSave)) return abort('public_XXX.sav is not valid');
|
||||
if (!constants.hashes.all.includes(crcSave)) throw new Error('public_XXX.sav is not valid');
|
||||
|
||||
/* Data Extraction */
|
||||
let locC = constants.dataLocations.ctcert;
|
||||
@ -28,7 +27,7 @@ function start() {
|
||||
let movableKeyY = sliceArr(movable, locM.keyY.off, locM.keyY.len);
|
||||
let normalKey = extractNormalKey(movableKeyY, constants.keys.keyX);
|
||||
let dsiwareData = extractDsiware(dsiware, normalKey);
|
||||
if (!dsiwareData) return abort('Wrong movable.sed provided');
|
||||
if (!dsiwareData) throw new Error('DSiWare.bin can not be decrypted with the provided movable.sed');
|
||||
|
||||
/* msed_data extraction */
|
||||
let msedDataHex = extractMsedData(movable);
|
||||
@ -36,7 +35,7 @@ function start() {
|
||||
|
||||
/* app replacing */
|
||||
let srl = dsiwareData.other['srl.nds'];
|
||||
if (game.length > srl.length) return abort('Game not compatible');
|
||||
if (game.length > srl.length) throw new Error('Game not compatible');
|
||||
let end = sliceArr(srl, game.length, srl.length - game.length);
|
||||
let newApp = new Uint8Array(game.length + end.length);
|
||||
newApp.set(game);
|
||||
@ -44,7 +43,7 @@ function start() {
|
||||
|
||||
/* sav replacing */
|
||||
let sav = dsiwareData.other['public.sav'];
|
||||
if (save.length > sav.length) return abort('Save not compatible with this game');
|
||||
if (save.length > sav.length) throw new Error('Save not compatible with this game');
|
||||
end = sliceArr(sav, save.length, sav.length - save.length);
|
||||
let newSav = new Uint8Array(save.length + end.length);
|
||||
newSav.set(save);
|
||||
@ -67,28 +66,35 @@ function start() {
|
||||
msedDataHex: msedDataHex,
|
||||
movableCrc: movableCrc,
|
||||
};
|
||||
$.post('https://tsign.jisagi.net/sign', body, data => {
|
||||
data = JSON.parse(data);
|
||||
if (data.error) return abort(`Signature Error: ${data.error}`);
|
||||
let { sigHashesBlock, sigApcert } = JSON.parse(data.response);
|
||||
|
||||
sigHashesBlock = parseHexString(sigHashesBlock);
|
||||
sigApcert = parseHexString(sigApcert);
|
||||
dsiwareData.dsiwareLength = dsiware.length;
|
||||
dsiwareData.keys = {
|
||||
movableKeyY: movableKeyY,
|
||||
normalKey: normalKey,
|
||||
};
|
||||
|
||||
/* inject signatures */
|
||||
dsiwareData = injectSignatures(dsiwareData, sigHashesBlock, sigApcert);
|
||||
/* Signing */
|
||||
return signData(body, dsiwareData);
|
||||
}).then(sigData => {
|
||||
let { sigHashesBlock, sigApcert } = sigData.signatures;
|
||||
let dsiwareData = sigData.dsiwareData;
|
||||
|
||||
/* rebuild dsiware */
|
||||
dsiwareData.keys = { movableKeyY: movableKeyY, normalKey: normalKey };
|
||||
let dsiwareFinal = buildDsiware(dsiwareData, dsiware.length);
|
||||
sigHashesBlock = parseHexString(sigHashesBlock);
|
||||
sigApcert = parseHexString(sigApcert);
|
||||
|
||||
/* offer file to download */
|
||||
download(dsiwareFinal);
|
||||
/* inject signatures */
|
||||
dsiwareData = injectSignatures(dsiwareData, sigHashesBlock, sigApcert);
|
||||
|
||||
/* End */
|
||||
console.log('Done');
|
||||
}).always(() => {
|
||||
$('.btn-startInjection')[0].disabled = false;
|
||||
});
|
||||
/* rebuild dsiware */
|
||||
let dsiwareFinal = buildDsiware(dsiwareData, dsiwareData.dsiwareLength);
|
||||
|
||||
/* offer file to download */
|
||||
download(dsiwareFinal);
|
||||
|
||||
/* End */
|
||||
console.log('Done');
|
||||
$('.btn-startInjection')[0].disabled = false;
|
||||
}).catch(error => {
|
||||
abort(error.message || error);
|
||||
});
|
||||
}
|
||||
|
11
public/js/custom/signing.js
Normal file
11
public/js/custom/signing.js
Normal file
@ -0,0 +1,11 @@
|
||||
function signData(postBody, dsiwareData) {
|
||||
return new Promise((resolve, reject) => {
|
||||
$.post('https://tsign.jisagi.net/sign', postBody, response => {
|
||||
let data = JSON.parse(response);
|
||||
if (data.error) return reject(`Signing Error: ${data.error}`);
|
||||
resolve({ signatures: JSON.parse(data.response), dsiwareData: dsiwareData });
|
||||
}).fail(() => {
|
||||
reject('Couldn\'t connect to the signing server. Please check your internet connection or try again later');
|
||||
});
|
||||
});
|
||||
}
|
@ -38,3 +38,47 @@ function insertIntoArray(originalArr, toInsert, offset) {
|
||||
orig.splice(offset, insert.length, ...insert);
|
||||
return new Uint8Array(orig);
|
||||
}
|
||||
|
||||
function checkBrowserVersion() {
|
||||
try {
|
||||
let browser = {
|
||||
all: ['chrome', 'firefox', 'opera', 'edge', 'safari'],
|
||||
good: { chrome: 60, firefox: 50 },
|
||||
maybe: { opera: 45, edge: 15, safari: 10 },
|
||||
};
|
||||
let version = getBrowserVersion();
|
||||
if (version.length !== 2) throw new Error('Failed to identify browser!');
|
||||
$('.p-browser-version').text((version.join(' ').replace('MSIE', 'Internet Explorer')));
|
||||
if (!browser.all.includes(version[0].toLowerCase())) throw new Error('Browser unsupported!');
|
||||
|
||||
let reqBrowser = version[0].toLowerCase();
|
||||
let reqVersion = version[1];
|
||||
let b = browser.good[reqBrowser] || browser.maybe[reqBrowser];
|
||||
if (b > reqVersion) throw new Error('Browser version too old, please update!');
|
||||
// some bugged browsers have 3+ version digits so anything >100 should be fine to filter
|
||||
if (reqVersion > 100) throw new Error('Browser version unsupported!');
|
||||
|
||||
$('.p-browser-version').css('color', 'green');
|
||||
} catch (e) {
|
||||
$('.p-browser-error').text(e.message || 'Unknown Error');
|
||||
$('.p-browser-error').css('color', 'red');
|
||||
$('.p-browser-version').css('color', 'red');
|
||||
}
|
||||
}
|
||||
|
||||
function getBrowserVersion() {
|
||||
let ua = navigator.userAgent;
|
||||
let tem;
|
||||
let M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
|
||||
if (/trident/i.test(M[1])) {
|
||||
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
|
||||
return 'IE ' + (tem[1] || '');
|
||||
}
|
||||
if (M[1] === 'Chrome') {
|
||||
tem = ua.match(/\b(OPR|Edge)\/(\d+)/);
|
||||
if (tem != null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
|
||||
}
|
||||
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
|
||||
if ((tem = ua.match(/version\/(\d+)/i)) != null) M.splice(1, 1, tem[1]);
|
||||
return M;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user