Pokemon Gen3 Savedata Parse

http://topia.wikidot.com/pokemon-gen3-savedata-parse/code/1


https://m.bulbapedia.bulbagarden.net/wiki/Save_data_structure_(Generation_III)

<head>
  <link rel="stylesheet" href="./3">
</head>
<body>
  <label class="fLabel">.sav
    <input type="file" id="savefile" />
  </label>
  <script src="./2"></script>
</body>
var Sav2Binary = file => new Promise(r => {
  var reader = new FileReader();
  reader.onload = _ => {
    var u = new Uint8Array(reader.result), a = new Array(u.length), i = u.length;
    while (i--) (a[i] = (u[i] < 16 ? '0' : '') + u[i].toString(16));
    r(a);
  };
  reader.readAsArrayBuffer(file);
});
 
// label, offset, size
var FS_OFFSET = [
  ['SaveData_A',     0x00000, 0x0E000],
  ['SaveData_B',     0x0E000, 0x0E000],
  ['HallOfFame',     0x1C000, 0x02000],
  ['MysteryGift',    0x1E000, 0x01000],
  ['RecordedBattle', 0x1F000, 0x01000]
];
var SAVEDATA_SECTION_OFFSET = [
  ['Data',           0x00000, 0x00F80],
  ['SectionId',      0x00FF4, 0x00002],
  ['CheckSum',       0x00FF6, 0x00002],
  ['SaveIndex',      0x00FFC, 0x00004]
];
 
var Binary2RawData = bin => {
  var obj = {}, clone = [...bin];
  FS_OFFSET.forEach(off => {
    obj[off[0]] = clone.slice(off[1], off[1] + off[2]);
    ['SaveData_A', 'SaveData_B'].includes(off[0])
      && (
        obj[off[0]] = [...Array(14)]
          .map(_ => obj[off[0]].splice(0, 0x1000)),
 
        obj[off[0]] = obj[off[0]].map(o => {
          var i, n, _ = SAVEDATA_SECTION_OFFSET
            .reduce((p, v) => {
              n && (p[`${n}_buffer`] = o.slice(i, v[1]));
              p[v[0]] = o.slice(v[1], v[1] + v[2]);
              n = v[0], i = v[1] + v[2];
              return p;
            }, {});
          _[`${n}_buffer`] = o.slice(i);
          return _;
        })
      );
  });
  obj.__all__ = [...bin];
  return obj;
}
var Binary2Data = bin => {
  var rd = Binary2RawData(bin);
  var h = field => parseInt(rd[field][0]['SaveIndex'].join(''), 16);
  rd.__nextsave__ = h('SaveData_A') > h('SaveData_B') ? 'SaveData_B' : 'SaveData_A';
  return rd;
}
 
var temp;
(async() => {
  document.querySelector('#savefile').onchange = async _ => {
    var b = await Sav2Binary(_.target.files[0]);
    var rd = Binary2Data(b);
    console.log(rd);
 
    temp = rd;
  };
})();
.fLabel {
    background: #fff;
    box-shadow: 0 0 3px #aaa;
    color: #888;
    cursor: pointer;
    font-family: Courier, monospace;
    padding: .5em 1em;
    text-shadow: 0 0 2px #aaa;
    transition: all .25s;
}
.fLabel:active,
.fLabel:hover {
    background: #6767a9;
    color: #fff;
    text-shadow: 0 0 2px #fff;
}
.fLabel > input {
    display: none;
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License