Jump to content

Mii Studio Local Storage

From Mii Technical Wiki
Revision as of 14:53, 24 September 2025 by Arian (talk | contribs) (add c struct, obfuscation details)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

A format. Used in Mii Studio (nintendo.com).

The struct name for this is unknown, as it's implemented in minified JS. However, it resembles a part of nn::mii::CharInfo, with CreateID and names removes, and fields in alphabetical order.

The JS contains field names that are minified/obfuscated ($$_19, $$_1a...), but some aren't: height, build, gender, and interestingly fontRegion, regionMove which are from CharInfo but not included in the format.

Data format

[edit | edit source]
typedef struct {
    u8 beard_color;       // Beard color
    u8 beard_type;        // Beard (goatee) type
    u8 build;             // Body weight
    u8 eye_aspect;        // Eye stretch
    u8 eye_color;         // Eye color
    u8 eye_rotate;        // Eye rotation
    u8 eye_scale;         // Eye size
    u8 eye_type;          // Eye type
    u8 eye_x;             // Eye X (horizontal) distance
    u8 eye_y;             // Eye Y (vertical) position
    u8 eyebrow_aspect;    // Eyebrow stretch
    u8 eyebrow_color;     // Eyebrow color
    u8 eyebrow_rotate;    // Eyebrow rotation
    u8 eyebrow_scale;     // Eyebrow size
    u8 eyebrow_type;      // Eyebrow type
    u8 eyebrow_x;         // Eyebrow X (horizontal) distance
    u8 eyebrow_y;         // Eyebrow Y (vertical) distance
    u8 faceline_color;    // Skin color
    u8 faceline_make;     // Face makeup
    u8 faceline_type;     // Face shape
    u8 faceline_wrinkle;  // Face wrinkles
    u8 favorite_color;    // Favorite color
    u8 gender;            // Mii gender
    u8 glass_color;       // Glasses color
    u8 glass_scale;       // Glasses size
    u8 glass_type;        // Glasses type
    u8 glass_y;           // Glasses Y (vertical) position
    u8 hair_color;        // Hair color
    u8 hair_flip;         // Flip hair
    u8 hair_type;         // Hair type
    u8 height;            // Body height
    u8 mole_scale;        // Beauty mark size
    u8 mole_type;         // Enable beauty mark
    u8 mole_x;            // Beauty mark X (horizontal) position
    u8 mole_y;            // Beauty mark Y (vertical) position
    u8 mouth_aspect;      // Mouth stretch
    u8 mouth_color;       // Mouth color
    u8 mouth_scale;       // Mouth size
    u8 mouth_type;        // Mouth type
    u8 mouth_y;           // Mouth Y (vertical) position
    u8 mustache_scale;    // Mustache size
    u8 mustache_type;     // Mustache type
    u8 mustache_y;        // Mustache Y (vertical) position
    u8 nose_scale;        // Nose size
    u8 nose_type;         // Nose type
    u8 nose_y;            // Nose Y (vertical) position
} charInfoStudio;

(TODO: Need ksy that isn't from mii2studio/HEYimHeroic/Larsenv due to AGPL license.)

Obfuscation

[edit | edit source]

When used in a URL (as opposed to local storage), there is light XOR obfuscation applied with a one byte key at the beginning. This code can be located in the website's "editor.pc.*.js" file:

function(t, e, r) {
    "use strict";
    function i(t) {
        for (var e = (t % 256).toString(16); e.length < 2;)
            e = "0" + e;
        return e
    }
    Object.defineProperty(e, "__esModule", {
        value: !0
    });
    var a = ["$$_1r", "$$_1q", "build", "$$_1p", "$$_1o", "$$_1n", "$$_1m", "$$_1l", "$$_1k", "$$_1j", "$$_1i", "$$_1h", "$$_1g", "$$_1f", "$$_1e", "$$_1d", "$$_1c", "$$_1b", "$$_1a", "$$_19", "$$_18", "$$_17", "gender", "$$_16", "$$_15", "$$_14", "$$_13", "$$_12", "$$_11", "$$_10", "height", "$$_e", "$$_d", "$$_c", "$$_b", "$$_a", "$$_9", "$$_8", "$$_7", "$$_6", "$$_5", "$$_4", "$$_3", "$$_2", "$$_1", "$$_0"],
        n = function() {
            function t() {}
            return t.prototype.encode = function(t) {
                for (var e = a.map(function(e) {
                        return t[e]
                    }), r = Math.floor(256 * Math.random()), n = r, o = 0, s = e.length; o < s; o++) {
                    var l = e[o];
                    e[o] = (7 + (l ^ n)) % 256,
                    n = e[o]
                }
                return [r].concat(e).map(function(t) {
                    return i(t)
                }).join("")
            }, t.prototype.decode = function(t) {
                for (var e = [], r = 0, i = a.length + 1; r < i; r++) {
                    var n = parseInt(t.substr(2 * r, 2), 16);
                    e[r] = n
                }
                var o = e.shift();
                if (void 0 === o)
                    throw new Error("invalid data");
                for (var r = 0, i = e.length; r < i; r++) {
                    var s = e[r];
                    e[r] = (256 + s - 7) % 256 ^ o,
                    o = s
                }
                for (var l = {}, r = 0, i = a.length; r < i; r++)
                    l[a[r]] = e[r];
                return l
            }, t
        }();
    e.default = n
}

In codebases

[edit | edit source]
  1. mii_ext_MiiPort.h from FFL-Testing renderer server

References

[edit | edit source]