Socket
Socket
Sign inDemoInstall

cemu-smm

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cemu-smm - npm Package Compare versions

Comparing version 1.0.4 to 1.0.5

214

index.js

@@ -1,3 +0,4 @@

const crc32 = require("buffer-crc32");
const jimp = require("jimp");
const Promise = require("bluebird");
const crc32 = require("buffer-crc32");
const jimp = require("jimp");

@@ -12,2 +13,14 @@ const fs = require("fs");

const COURSE_SAVE_NAME_OFFSET = 0x28;
const COURSE_SAVE_NAME_LENGTH = 0x42;
const COURSE_SAVE_MAKER_OFFSET = 0x92;
const COURSE_SAVE_MAKER_LENGTH = 0x14;
const COURSE_SAVE_TYPE_OFFSET = 0x6A;
const COURSE_SAVE_TYPE_READABLE = {
"M1": "Super Mario Bros",
"M3": "Super Mario Bros 3",
"MW": "Super Mario World",
"WU": "New Super Mario Bros U"
};
const TNL_SIZE = 0xC800;

@@ -33,2 +46,6 @@ const TNL_JPEG_MAX_SIZE = 0xC7F8;

pathToSave = path.resolve(pathToSave);
if (!fs.existsSync(pathToSave)) throw new Error(`No such folder exists:\n${pathToSave}`);
fs.access(pathToSave, fs.constants.R_OK | fs.constants.W_OK, (err) => {
if (err) throw new Error("Please close you emuulator before executing your script");
});
fs.readFile(path.resolve(`${pathToSave}/save.dat`), (err, data) => {

@@ -48,2 +65,3 @@ if (err) throw err;

this.data = data;
this.courses = {};
}

@@ -161,3 +179,3 @@

let tnl = new Tnl(coursePath + "/thumbnail0.tnl");
let jpeg = await tnl.toJpeg(true);
let jpeg = await tnl.toJpeg();
fs.writeFile(coursePath + "/thumbnail0.jpg", jpeg, null, () => {

@@ -173,3 +191,3 @@ resolve();

let tnl = new Tnl(coursePath + "/thumbnail1.tnl");
let jpeg = await tnl.toJpeg(false);
let jpeg = await tnl.toJpeg();
fs.writeFile(coursePath + "/thumbnail1.jpg", jpeg, null, () => {

@@ -189,2 +207,105 @@ resolve();

},
importJpeg: async function () {
let promises = [];
for (let i = 0; i < SAVE_ORDER_SIZE; i++) {
let coursePath = path.resolve(`${this.pathToSave}/course${i.pad(3)}/`);
promises.push(new Promise(async (resolve) => {
let exists = false;
await new Promise((resolve) => {
fs.access(coursePath, fs.constants.R_OK | fs.constants.W_OK, (err) => {
exists = !err;
resolve();
});
});
if (exists) {
await Promise.all([
new Promise(async (resolve) => {
try {
let jpeg = new Tnl(coursePath + "/thumbnail0.jpg");
let tnl = await jpeg.fromJpeg(true);
fs.writeFile(coursePath + "/thumbnail0.tnl", tnl, null, () => {
resolve();
})
} catch (err) {
resolve();
}
}),
new Promise(async (resolve) => {
try {
let jpeg = new Tnl(coursePath + "/thumbnail1.jpg");
let tnl = await jpeg.fromJpeg(false);
fs.writeFile(coursePath + "/thumbnail1.tnl", tnl, null, () => {
resolve();
});
} catch (err) {
resolve();
}
})
]);
}
resolve();
}));
}
await Promise.all(promises);
},
loadCourses: async function () {
let promises = [];
for (let i = 0; i < SAVE_ORDER_SIZE; i++) {
let course = `course${i.pad(3)}`;
let coursePath = path.resolve(`${this.pathToSave}/${course}/`);
promises.push(new Promise(async (resolve) => {
let exists = false;
await new Promise((resolve) => {
fs.access(coursePath, fs.constants.R_OK | fs.constants.W_OK, (err) => {
exists = !err;
resolve();
});
});
if (exists) {
fs.readFile(path.resolve(`${coursePath}/course_data.cdt`), (err, data) => {
if (err) throw err;
let titleBuf = data.slice(COURSE_SAVE_NAME_OFFSET, COURSE_SAVE_NAME_OFFSET + COURSE_SAVE_NAME_LENGTH);
let title = "";
for (let i = 0; i < COURSE_SAVE_NAME_LENGTH; i++) {
let charBuf = titleBuf.slice(i, i+1);
if (charBuf.readUInt8(0) !== 0) {
title += charBuf.toString();
}
}
let makerBuf = data.slice(COURSE_SAVE_MAKER_OFFSET, COURSE_SAVE_MAKER_OFFSET + COURSE_SAVE_MAKER_LENGTH);
let maker = "";
let doBreak = false;
for (let i = 0; i < COURSE_SAVE_MAKER_LENGTH; i++) {
let charBuf = makerBuf.slice(i, i+1);
if (charBuf.readUInt8(0) === 0) {
if (doBreak) break;
doBreak = true;
} else {
doBreak = false;
maker += charBuf.toString();
}
}
let type = data.slice(COURSE_SAVE_TYPE_OFFSET, COURSE_SAVE_TYPE_OFFSET + 2).toString();
this.courses[course] = {
title: title,
maker: maker,
type: type,
type_readable: COURSE_SAVE_TYPE_READABLE[type]
};
resolve();
});
} else {
resolve();
}
}));
}
await Promise.all(promises);
return this.courses;
}

@@ -218,43 +339,49 @@

// image pre-processing
let sizeOK = false;
let data = await new Promise((resolve) => {
fs.readFile(this.pathToFile, (err, data) => {
if (err) throw err;
resolve(data);
});
});
if (data.length <= TNL_JPEG_MAX_SIZE) {
sizeOK = true;
}
let image = await jimp.read(this.pathToFile);
let skipPreprocessing = false;
if (sizeOK && (image.bitmap.width === TNL_DIMENSION[0][0] && image.bitmap.height === TNL_DIMENSION[0][1] ||
image.bitmap.width === TNL_DIMENSION[1][0] && image.bitmap.height === TNL_DIMENSION[1][1])) {
skipPreprocessing = true;
}
if (isWide === null) {
let aspectRatio = image.bitmap.width / image.bitmap.height;
if (aspectRatio > TNL_ASPECT_RATIO[0] - TNL_ASPECT_RATIO_THRESHOLD[0] && aspectRatio < TNL_ASPECT_RATIO[0] + TNL_ASPECT_RATIO_THRESHOLD[0]) {
isWide = true;
} else if (aspectRatio > TNL_ASPECT_RATIO[1] - TNL_ASPECT_RATIO_THRESHOLD[1] && aspectRatio < TNL_ASPECT_RATIO[1] + TNL_ASPECT_RATIO_THRESHOLD[1]) {
isWide = false;
}
// image pre-processing
if (!skipPreprocessing) {
if (isWide === null) {
isWide = TNL_ASPECT_RATIO[0] - TNL_ASPECT_RATIO_THRESHOLD[0] - aspectRatio <= TNL_ASPECT_RATIO[1] + TNL_ASPECT_RATIO_THRESHOLD[1] + aspectRatio;
let aspectRatio = image.bitmap.width / image.bitmap.height;
if (aspectRatio > TNL_ASPECT_RATIO[0] - TNL_ASPECT_RATIO_THRESHOLD[0] && aspectRatio < TNL_ASPECT_RATIO[0] + TNL_ASPECT_RATIO_THRESHOLD[0]) {
isWide = true;
} else if (aspectRatio > TNL_ASPECT_RATIO[1] - TNL_ASPECT_RATIO_THRESHOLD[1] && aspectRatio < TNL_ASPECT_RATIO[1] + TNL_ASPECT_RATIO_THRESHOLD[1]) {
isWide = false;
}
if (isWide === null) {
isWide = TNL_ASPECT_RATIO[0] - TNL_ASPECT_RATIO_THRESHOLD[0] - aspectRatio <= TNL_ASPECT_RATIO[1] + TNL_ASPECT_RATIO_THRESHOLD[1] + aspectRatio;
}
}
}
if (isWide) {
if (doClip) {
image.cover(TNL_DIMENSION[0][0], TNL_DIMENSION[0][1]);
if (isWide) {
if (doClip) {
image.cover(TNL_DIMENSION[0][0], TNL_DIMENSION[0][1]);
} else {
image.contain(TNL_DIMENSION[0][0], TNL_DIMENSION[0][1]);
}
} else {
image.contain(TNL_DIMENSION[0][0], TNL_DIMENSION[0][1]);
if (doClip) {
image.cover(TNL_DIMENSION[1][0], TNL_DIMENSION[1][1]);
} else {
image.contain(TNL_DIMENSION[1][0], TNL_DIMENSION[1][1]);
}
}
} else {
if (doClip) {
image.cover(TNL_DIMENSION[1][0], TNL_DIMENSION[1][1]);
} else {
image.contain(TNL_DIMENSION[1][0], TNL_DIMENSION[1][1]);
}
}
// wrap tnl data around jpeg
let data = await new Promise((resolve) => {
image.getBuffer(jimp.MIME_JPEG, (err, buffer) => { resolve(buffer); });
});
// lower quality until it fits
let quality = 100;
while (data.length > TNL_JPEG_MAX_SIZE) {
quality -= 5;
if (quality < 0) {
reject("File could not be transformed into jpeg with lowest quality setting.");
}
let quality = 80;
data = await new Promise((resolve) => {

@@ -264,4 +391,17 @@ image.quality(quality);

});
// lower quality until it fits
while (data.length > TNL_JPEG_MAX_SIZE) {
quality -= 5;
if (quality < 0) {
reject("File could not be transformed into jpeg with lowest quality setting.");
}
data = await new Promise((resolve) => {
image.quality(quality);
image.getBuffer(jimp.MIME_JPEG, (err, buffer) => { resolve(buffer); });
});
}
}
// wrap tnl data around jpeg
let length = Buffer.alloc(4);

@@ -268,0 +408,0 @@ length.writeUInt32BE(data.length, 0);

3

package.json
{
"name": "cemu-smm",
"version": "1.0.4",
"version": "1.0.5",
"description": "This is a module to simplify all kinds of tasks with Loadiine Super Mario Maker save files and respectively Cemu",

@@ -12,2 +12,3 @@ "main": "index.js",

"dependencies": {
"bluebird": "^3.5.0",
"buffer-crc32": "latest",

@@ -14,0 +15,0 @@ "jimp": "^0.2.27"

@@ -19,3 +19,3 @@ # cemu-smm

let fs = require("fs");
(async () => {

@@ -33,2 +33,5 @@ // let us load our SMM save file

// import all jpg files and create tnl files in their respective course folder
save.importJpeg();
// extract all tnl files to jpeg in their respective course folder

@@ -88,3 +91,3 @@ save.exportJpeg();

```js
let jpeg = await jpeg.fromJpeg([isWide, [doCrop = false]]);
let jpeg = await tnl.toJpeg();
```

@@ -129,2 +132,12 @@ Save your file

### JPEG mass import
To convert all jpeg files inside your save to tnl, call
```js
save.importJpeg();
```
Files inside course folders must be named ```thumbnail0.jpg``` or ```thumbnail1.jpg````.
Refer to [this](https://github.com/Tarnadas/cemu-smm/blob/master//tutorial/import_thumbnail.md) tutorial.
## License

@@ -131,0 +144,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc