JSFiddle - React, Tailwind, and code Playground
by arian_
HTML
<div class="character-container">
<div id="speech-bubble">
<span class="message" id="message-default" style="display: initial;">
Hello! It's-a me, Mario!<br>
I will tell you when your Mii™ was created if you give me its data below!<br>
Cons include... you'll find out! Wahoo!<br>
</span>
<span class="message" id="message-invalid">Mamma Mia, that is not valid Mii™ data!</span>
<span class="message" id="message-version-1">
Wii data detected!<br>
CreateID Hex: <span id="createid-result-v1"></span><br>
Flags: <span id="createid-flags-v1"></span><br>
MAC Address: <span id="createid-base-v1"></span><br>
Created On(?): <span id="createid-date-v1"></span>
</span>
<span class="message" id="message-version-3">
3DS/Wii U data detected!<br>
CreateID: <span id="createid-result-v3"></span><br>
<!--Flags: <span id="createid-flags-v3"></span><br>-->
<span id="createid-base-v3"></span><br>
<b>Created On: <span id="createid-date-v3"></span></b>
</span>
<span class="message" id="message-version-4">Switch data detected! CreateID (Hex): <span id="createid-result-v4"></span>
Switch data does not have date information in the CreateID. Therefore, this information is Lost Media. Mamma Mia.
</span>
<span class="message" id="message-studio">
Mamma Mia... Mii Studio data lacks a CreateID field, so you will never ever know when it this Mii™ was made.
</span>
<span class="message" id="message-miic">
Mamma Mia... the <a target="_blank" href="https://mii.nxw.pw/">Mii Creator app</a> doesn't include a date in the CreateID field.
</span>
<span class="message" id="message-exception">
<span id="exception-message"></span>
</span>
</div>
<img id="character-normal"...
CSS
body {
font-family: Arial, sans-serif;
text-align: center;
margin: 50px;
}
.character-container {
position: relative;
display: inline-block;
}
#character-normal, #character-sad {
margin-right: 200px;
width: 249px;
height: 290px;
}
#character-sad {
padding-right: 2px;
}
#speech-bubble {
position: absolute;
top: -20px;
left: 190px;
width: 300px;
padding: 10px;
border: 2px solid black;
background: white;
border-radius: 10px;
}
input {
margin-top: 20px;
padding: 10px;
width: 80%;
max-width: 400px;
}
button {
margin-top: 10px;
padding: 10px 20px;
}
.message {
display: none;
}
JavaScript
const messageElements = document.querySelectorAll('.message');
function showMessage(messageId) {
messageElements.forEach(el => el.style.display = 'none');
document.getElementById(messageId).style.display = 'initial';
}
function toggleCharacter(happy) {
document.getElementById('character-normal').style.display = happy ? 'initial' : 'none';
document.getElementById('character-sad').style.display = happy ? 'none' : 'initial';
}
// Updated byte conversion utilities
const stripSpaces = str => str.replace(/\s+/g, '');
const hexToUint8Array = hex =>
new Uint8Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
const base64ToUint8Array = base64 => {
const normalizedBase64 = base64.replace(/-/g, '+').replace(/_/g, '/');
const paddedBase64 = normalizedBase64.padEnd(normalizedBase64.length + (4 - (normalizedBase64.length % 4)) % 4, '=');
return Uint8Array.from(atob(paddedBase64), c => c.charCodeAt(0));
};
const uint8ArrayToHex = uint8Array =>
Array.from(uint8Array).map(byte => byte.toString(16).padStart(2, '0')).join('').toUpperCase();
const parseHexOrB64TextStringToUint8Array = text => {
const cleanedData = stripSpaces(text);
return /^[0-9a-fA-F]+$/.test(cleanedData) ? hexToUint8Array(cleanedData) : base64ToUint8Array(cleanedData);
};
function formatMacAddress(input) {
// Convert Uint8Array to hex if needed
const hexArray = typeof input === "string"
? input.match(/.{1,2}/g) // Split string into pairs
: Array.from(input).map(byte => byte.toString(16).padStart(2, '0')); // Format Uint8Array to hex
return hexArray.join(':').toUpperCase();
}
// Centralized Mii data table with fixed extraction
const miiDataTable = [
{
lengths: [72, 92, 96],
version: 3,
extractCreateID: (data) => data.slice(12, 22),
birthPlatform: (data) => data[3] >> 4 & 7
},
{
lengths: [74, 76],
version: 1,
extractCreateID: (data) => data.slice(24, 34),
...