miijs 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/index.js +84 -3
- package/package.json +2 -1
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# MiiJS
|
|
2
|
+
Read, Edit, Write, and make Special Miis from a Wiimote binary file or 3DS QR Code to a binary file or QR code
|
|
3
|
+
|
|
4
|
+
## Installation
|
|
5
|
+
`npm i miijs` OR `npm install miijs`
|
|
6
|
+
|
|
7
|
+
## Making a Special Mii
|
|
8
|
+
To make a special Mii, read in the file using the appropriate function, set `mii.info.type="Special";`, and then write a new file with the appropriate function.
|
|
9
|
+
|
|
10
|
+
# Functions
|
|
11
|
+
- async read3DSQR(pathToQR), returns JSON
|
|
12
|
+
- write3DSQR(miiJSON, path), writes QR
|
|
13
|
+
- readWiiBin(pathToMii), returns JSON
|
|
14
|
+
- writeWiiBin(miiJSON, path), writes new bin to the path specified
|
|
15
|
+
- render3DSMiiFromJSON(miiJSON, path), writes PNG representation of Mii's face to the path specified
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Credits
|
|
20
|
+
- [kazuki-4ys' MiiInfoEditorCTR](https://github.com/kazuki-4ys/kazuki-4ys.github.io/tree/master/web_apps/MiiInfoEditorCTR), I took the code for how to decrypt and reencrypt the QR codes from here, including the asmCrypto.js file (with some slight modifications to work in my coding style). I believe I also modified the code for rendering the Mii using Nintendo's Mii Studio from here as well.
|
package/index.js
CHANGED
|
@@ -602,8 +602,7 @@ module.exports={
|
|
|
602
602
|
temp2=getBinaryFromAddress(0x47);
|
|
603
603
|
miiJson.mole.xPos=parseInt(temp2.slice(6,8)+temp.slice(0,3),2);
|
|
604
604
|
miiJson.mole.yPos=parseInt(temp2.slice(1,6),2);
|
|
605
|
-
fs.unlinkSync("./decryptedTemp.
|
|
606
|
-
fs.unlinkSync("./encryptedTemp.3dmii");
|
|
605
|
+
fs.unlinkSync("./decryptedTemp.3dMii");
|
|
607
606
|
return miiJson;
|
|
608
607
|
}
|
|
609
608
|
var data=fs.readFileSync(qrPath);
|
|
@@ -615,7 +614,6 @@ module.exports={
|
|
|
615
614
|
const qrCode = jsQR(imageData.data, imageData.width, imageData.height);
|
|
616
615
|
|
|
617
616
|
if (qrCode) {
|
|
618
|
-
fs.writeFileSync("./encryptedTemp.3dMii",Buffer.from(qrCode.binaryData));
|
|
619
617
|
var data = decodeAesCcm(new Uint8Array(qrCode.binaryData));
|
|
620
618
|
fs.writeFileSync("./decryptedTemp.3dMii",Buffer.from(data));
|
|
621
619
|
return Promise.resolve(readMii());
|
|
@@ -962,5 +960,88 @@ module.exports={
|
|
|
962
960
|
fs.unlinkSync(mii.name+"Output.png");
|
|
963
961
|
});
|
|
964
962
|
});
|
|
963
|
+
},
|
|
964
|
+
render3DSMiiFromJSON:function(jsonIn,outPath){
|
|
965
|
+
var mii=jsonIn;
|
|
966
|
+
var studioMii=new Uint8Array([0x08, 0x00, 0x40, 0x03, 0x08, 0x04, 0x04, 0x02, 0x02, 0x0c, 0x03, 0x01, 0x06, 0x04, 0x06, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x21, 0x40, 0x04, 0x00, 0x02, 0x14, 0x03, 0x13, 0x04, 0x17, 0x0d, 0x04, 0x00, 0x0a, 0x04, 0x01, 0x09]);
|
|
967
|
+
//miiPreview.src = 'https://studio.mii.nintendo.com/miis/image.png?data=' + mii.previewData + "&width=270&type=face";
|
|
968
|
+
function encodeStudio(studio) {
|
|
969
|
+
function byteToString(int){
|
|
970
|
+
var str = int.toString(16);
|
|
971
|
+
if(str.length < 2)str = '0' + str;
|
|
972
|
+
return str;
|
|
973
|
+
}
|
|
974
|
+
var n = 0;
|
|
975
|
+
var eo;
|
|
976
|
+
var dest = byteToString(n);
|
|
977
|
+
for (var i = 0; i < studio.length; i++) {
|
|
978
|
+
eo = (7 + (studio[i] ^ n)) & 0xFF;
|
|
979
|
+
n = eo;
|
|
980
|
+
dest += byteToString(eo);
|
|
981
|
+
}
|
|
982
|
+
return dest;
|
|
983
|
+
}
|
|
984
|
+
studioMii[0x16] = mii.info.gender==="Male"?0:1;
|
|
985
|
+
studioMii[0x15] = cols3DS.indexOf(mii.info.favColor);
|
|
986
|
+
studioMii[0x1E] = mii.info.height;
|
|
987
|
+
studioMii[2] = mii.info.weight;
|
|
988
|
+
studioMii[0x13] = tables.faces[mii.face.shape];
|
|
989
|
+
studioMii[0x11] = skinCols3DS.indexOf(mii.face.col);
|
|
990
|
+
studioMii[0x14] = faceFeatures3DS.indexOf(mii.face.feature);
|
|
991
|
+
studioMii[0x12] = makeups3DS.indexOf(mii.face.makeup);
|
|
992
|
+
studioMii[0x1D] = tables.hairs[mii.hair.style[0]][mii.hair.style[1]];
|
|
993
|
+
studioMii[0x1B] = hairCols3DS.indexOf(mii.hair.col);
|
|
994
|
+
if (!studioMii[0x1B]) studioMii[0x1B] = 8;
|
|
995
|
+
studioMii[0x1C] = mii.hair.flipped?1:0;
|
|
996
|
+
studioMii[7] = tables.eyes[mii.eyes.type[0]][mii.eyes.type[1]];
|
|
997
|
+
studioMii[4] = eyeCols3DS.indexOf(mii.eyes.col) + 8;
|
|
998
|
+
studioMii[6] = mii.eyes.size;
|
|
999
|
+
studioMii[3] = mii.eyes.squash;
|
|
1000
|
+
studioMii[5] = mii.eyes.rot;
|
|
1001
|
+
studioMii[8] = mii.eyes.distApart;
|
|
1002
|
+
studioMii[9] = mii.eyes.yPos;
|
|
1003
|
+
studioMii[0xE] = tables.eyebrows[mii.eyebrows.style[0]][mii.eyebrows.style[1]];
|
|
1004
|
+
studioMii[0xB] = hairCols3DS.indexOf(mii.eyebrows.col);
|
|
1005
|
+
if (!studioMii[0xB]) studioMii[0xB] = 8;
|
|
1006
|
+
studioMii[0xD] = mii.eyebrows.size;
|
|
1007
|
+
studioMii[0xA] = mii.eyebrows.squash;
|
|
1008
|
+
studioMii[0xC] = mii.eyebrows.rot;
|
|
1009
|
+
studioMii[0xF] = mii.eyebrows.distApart;
|
|
1010
|
+
studioMii[0x10] = mii.eyebrows.yPos+3;
|
|
1011
|
+
studioMii[0x2C] = tables.noses[mii.nose.type[0]][mii.nose.type[1]];
|
|
1012
|
+
studioMii[0x2B] = mii.nose.size;
|
|
1013
|
+
studioMii[0x2D] = mii.nose.yPos;
|
|
1014
|
+
studioMii[0x26] = tables.mouths[mii.mouth.type[0]][mii.mouth.type[1]];
|
|
1015
|
+
studioMii[0x24] = mouthCols3DS.indexOf(mii.mouth.col);
|
|
1016
|
+
if (studioMii[0x24] < 4) {
|
|
1017
|
+
studioMii[0x24] += 19;
|
|
1018
|
+
} else {
|
|
1019
|
+
studioMii[0x24] = 0;
|
|
1020
|
+
}
|
|
1021
|
+
studioMii[0x25] = mii.mouth.size;
|
|
1022
|
+
studioMii[0x23] = mii.mouth.squash;
|
|
1023
|
+
studioMii[0x27] = mii.mouth.yPos;
|
|
1024
|
+
studioMii[0x29] = mii.facialHair.mustacheType;
|
|
1025
|
+
studioMii[1] = mii.facialHair.beardType;
|
|
1026
|
+
studioMii[0] = mii.facialHair.col;
|
|
1027
|
+
if (!studioMii[0]) studioMii[0] = 8;
|
|
1028
|
+
studioMii[0x28] = mii.facialHair.mustacheSize;
|
|
1029
|
+
studioMii[0x2A] = mii.facialHair.mustacheYPos;
|
|
1030
|
+
studioMii[0x19] = mii.glasses.type;
|
|
1031
|
+
studioMii[0x17] = mii.glasses.col;
|
|
1032
|
+
if (!studioMii[0x17]) {
|
|
1033
|
+
studioMii[0x17] = 8;
|
|
1034
|
+
} else if (studioMii[0x17] < 6) {
|
|
1035
|
+
studioMii[0x17] += 13;
|
|
1036
|
+
} else {
|
|
1037
|
+
studioMii[0x17] = 0;
|
|
1038
|
+
}
|
|
1039
|
+
studioMii[0x18] = mii.glasses.size;
|
|
1040
|
+
studioMii[0x1A] = mii.glasses.yPos;
|
|
1041
|
+
studioMii[0x20] = mii.mole.on?1:0;
|
|
1042
|
+
studioMii[0x1F] = mii.mole.size;
|
|
1043
|
+
studioMii[0x21] = mii.mole.xPos;
|
|
1044
|
+
studioMii[0x22] = mii.mole.yPos;
|
|
1045
|
+
downloadImage('https://studio.mii.nintendo.com/miis/image.png?data=' + encodeStudio(studioMii) + "&width=270&type=face",outPath);
|
|
965
1046
|
}
|
|
966
1047
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miijs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Read, Edit, Write, and make Special Miis from a Wiimote binary file or 3DS QR Code to a binary file or QR code",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"https": "^1.0.0",
|
|
31
31
|
"jimp": "^0.22.7",
|
|
32
32
|
"jsqr": "^1.4.0",
|
|
33
|
+
"pureimage": "^0.3.17",
|
|
33
34
|
"qrcode": "^1.5.3"
|
|
34
35
|
}
|
|
35
36
|
}
|