0
0
mirror of https://github.com/marcrobledo/savegame-editors.git synced 2025-04-28 09:05:10 +00:00

306 lines
10 KiB
JavaScript

/*
Streetpass Mii Plaza for HTML5 Save Editor v20170706
by Marc Robledo 2016-2017
*/
SavegameEditor={
Name:'Streetpass Mii Plaza',
Filename:'meet.dat',
/* Constants */
Constants:{
ALL_SPEECH_BUBBLES:[0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff],
ALL_SPEECH_BUBBLES2:[0xf8],
ALL_HATS2:[0xef,0xfb,0xff,0xff,0xff,0xff,0xff,0xff],
ALL_HATS3:[0xff,0xff,0xff,0x7f,0x00,0xfe,0x3f,0xfc,0x01],
HATS_GAMES:[
//Battleground Z?
//Mii Force?
//Flower Town?
//Warrior's Way?
//Market Crashers?
//Ninja Launcher?
[0x05b348, 0xc0],
[0x05b348, 0x30],
[0x05b348, 0x0c],
[0x05b348, 0x03],
[0x05b34a, 0xc0], //Monster Manor
[0x05b34b, 0x03], //Ultimate Angler
[0x05b34c, 0x06], //Slot Car Rivals
[0x05b34c, 0x18],
[0x05b34c, 0x60], //Feed Mii
[0x05b34c, 0x80, 0x05b34d,0x01], //Mii Trek
[0x05b34d, 0x06]
],
NO_PIECES_15:[0x00,0x00],
NO_PIECES_SPOTPASS_15:[0x00,0x00],
NO_PIECES_SPOTPASS_24:[0x00,0x00,0x00],
NO_PIECES_SPOTPASS_40:[0x00,0x00,0x00,0x00,0x00],
MOST_PIECES_15:[0xff,0x3f],
MOST_PIECES_SPOTPASS_15:[0xff,0xfc],
MOST_PIECES_SPOTPASS_24:[0xff,0xff,0xfe],
MOST_PIECES_SPOTPASS_40:[0xff,0xff,0xff,0xff,0xfe],
ALL_PIECES_15:[0xff,0x7f],
ALL_PIECES_SPOTPASS_15:[0xff,0xfe],
ALL_PIECES_SPOTPASS_24:[0xff,0xff,0xff],
ALL_PIECES_SPOTPASS_40:[0xff,0xff,0xff,0xff,0xff],
PANELS:[
{Size:15,Name:'Metroid: Other M'},
{Size:15,Name:'Mario and Bowser'},
{Size:15,Name:'Super Mario Galaxy 2'},
{Size:15,Name:'The Legend of Zelda'},
{Size:15,Name:'Kirby\'s Dream Land'},
{Size:15,Name:'Pikmin'},
{Size:15,Name:'New Super Mario Bros. Wii'},
{Size:24,Name:'The Legend of Zelda: Ocarina of Time 3D'},
{Size:24,Name:'Star Fox 64 3D'},
{Size:40,Name:'Super Mario 3D Land'},
{Size:40,Name:'Mario Kart 7'},
{Size:24,Name:'Rhythm Heaven Fever'},
{Size:24,Name:'Donkey Kong Country Returns'},
{Size:24,Name:'Pilotwings Resort'},
{Size:40,Name:'Kid Icarus: Uprising'},
{Size:40,Name:'Fire Emblem Awakening'},
{Size:40,Name:'Mario Tennis Open'},
{Size:40,Name:'Kirby\'s 20th Anniversary'},
{Size:24,Name:'Brain Age: Concentration Training'},
{Size:15,Name:'All Nippon Airways*'},
{Size:15,Name:'Mac de DS Big Mac*'},
{Size:40,Name:'New Super Mario Bros. 2'},
{Size:40,Name:'Kirby\'s Return to Dream Land'},
{Size:40,Name:'Animal Crossing: New Leaf'},
{Size:40,Name:'Luigi\'s Mansion: Dark Moon'},
{Size:40,Name:'Dillon\'s Rolling Western: The Last Ranger'},
{Size:40,Name:'Nintendo Starlets'},
{Size:40,Name:'Xenoblade Chronicles'},
{Size:40,Name:'New SUPER MARIO BROS. U + New SUPER LUIGI U'},
{Size:40,Name:'The Legend of Zelda: Skyward Sword'},
{Size:40,Name:'Mario & Luigi: Dream Team'},
{Size:40,Name:'Chibi-Robo! Photo Finder'},
{Size:24,Name:'Darumeshi Sports Store*'},
{Size:40,Name:'Pokémon X and Pokémon Y'},
{Size:40,Name:'MONSTER HUNTER'},
{Size:40,Name:'Kirby: Triple Deluxe'},
{Size:40,Name:'SUPER MARIO 3D WORLD'},
{Size:40,Name:'YOSHI\'S New ISLAND'},
{Size:24,Name:'Rusty\'s Real Deal Baseball'},
{Size:24,Name:'Dalgu ne seupocheu yagu pyeon*'},
{Size:15,Name:'Nintendo Pocket Football Club'},
{Size:40,Name:'Mega Man'},
{Size:24,Name:'Kirby Fighters Deluxe/DeDeDe\'s Drum Dash Deluxe'},
{Size:40,Name:'Daigasso! Band Brothers P*'},
{Size:40,Name:'FANTASY LIFE'},
{Size:15,Name:'PIKMIN Short Movies 3D: The Night Juicer'},
{Size:15,Name:'PIKMIN Short Movies 3D: Treasure in a Bottle'},
{Size:15,Name:'PIKMIN Short Movies 3D: Occupational Hazards'},
{Size:40,Name:'Sonic Boom'},
{Size:40,Name:'Captain Toad: Treasure Tracker'},
{Size:40,Name:'ULTIMATE NES REMIX'},
{Size:40,Name:'Super Smash Bros. for 3DS / Wii U'},
{Size:40,Name:'MONSTER HUNTER'},
{Size:24,Name:'Tomodachi Life Friendship Fiesta'},
{Size:24,Name:'Mario & Happy*'},
{Size:15,Name:'Picross 3D Round 2'},
{Size:40,Name:'YO-KAI WATCH'},
{Size:15,Name:'Mario & Luigi: Paper Jam'},
{Size:40,Name:'Animal Crossing: Happy Home Designer'},
{Size:40,Name:'FINAL FANTASY EXPLORERS'},
{Size:15,Name:'Kirby: Planet Robobot'},
{Size:15,Name:'Culdcept Revolt'},
{Size:15,Name:'METROID PRIME FEDERATION FORCE'}
]
},
Offsets:{
STREETPASS_TAGS: 0x043e70,
PANELS: 0x044bdc,
PANEL_SIZE: 0x02,
SPOTPASS_PANELS: 0x045578,
SPOTPASS_PANEL_SIZE: 0x44,
ACCOMPLISHMENTS: 0x04555a,
SHOP_UNLOCKED: 0x05b358,
TICKETS: 0x05b366,
FANTASTIC_RATINGS: 0x05b4d6,
SPEECH_BUBBLES: 0x05bfe9,
SPEECH_BUBBLES2: 0x05cec6,
HATS2: 0x05b314,
HATS3: 0x05b344
},
/* private functions */
_getPanelOffset:function(){
var panelOffset,panelSize,panelId;
if(get('select-panel').selectedIndex<=6){
panelOffset=SavegameEditor.Offsets.PANELS;
panelSize=SavegameEditor.Offsets.PANEL_SIZE;
panelId=getValue('panel');
}else{
panelOffset=SavegameEditor.Offsets.SPOTPASS_PANELS;
panelSize=SavegameEditor.Offsets.SPOTPASS_PANEL_SIZE;
panelId=getValue('panel')-7;
}
return panelOffset+parseInt(panelId)*panelSize;
},
_countCurrentPanelPieces:function(){
var panelSize=SavegameEditor.Constants.PANELS[getValue('panel')].Size;
var offset=SavegameEditor._getPanelOffset();
var usedBytes;
if(panelSize==15){
usedBytes=SavegameEditor.Constants.ALL_PIECES_SPOTPASS_15.length
}else if(panelSize==24){
usedBytes=SavegameEditor.Constants.ALL_PIECES_SPOTPASS_24.length
}else{
usedBytes=SavegameEditor.Constants.ALL_PIECES_SPOTPASS_40.length
}
var count=0;
for(var i=0; i<usedBytes; i++){
var myByte=tempFile.readU8(offset+i);
for(var j=0; j<8; j++){
var mask=Math.pow(2, (7-(j%8)));
if(myByte & mask){
count++;
}
}
}
var color;
if(count==panelSize){
color='green'
}else if(count>=panelSize){
color='red';
}else{
color='initial';
}
setValue('pieces',count);
getField('pieces').style.color=color;
},
_setPiecesFromCurrentPanel:function(status){
var arrayStr;
if(status===false){
arrayStr='NO_PIECES_';
}else if(status===-1){
arrayStr='MOST_PIECES_';
}else{
arrayStr='ALL_PIECES_';
}
if(get('select-panel').selectedIndex>=7){
arrayStr+='SPOTPASS_';
}
arrayStr+=SavegameEditor.Constants.PANELS[parseInt(getValue('panel'))].Size;
tempFile.writeBytes(SavegameEditor._getPanelOffset(), SavegameEditor.Constants[arrayStr]);
SavegameEditor._countCurrentPanelPieces();
},
_unlockTicketShop:function(){
var originalByte=tempFile.readU8(this.Offsets.SHOP_UNLOCKED);
if(!(originalByte & 0x01)){
tempFile.writeU8(this.Offsets.SHOP_UNLOCKED, originalByte+0x01);
getField('button-unlockticketshop').disabled=true;
MarcDialogs.alert('Ticket shop is open now.');
}
},
_unlockSpeechBubbles:function(){
tempFile.writeBytes(this.Offsets.SPEECH_BUBBLES, this.Constants.ALL_SPEECH_BUBBLES);
getField('button-unlockspeechbubbles').disabled=true;
MarcDialogs.alert('Speech bubbles 1-16 were unlocked.');
},
_unlockSpeechBubbles2:function(){
tempFile.writeBytes(this.Offsets.SPEECH_BUBBLES2, this.Constants.ALL_SPEECH_BUBBLES2);
getField('button-unlockspeechbubbles2').disabled=true;
MarcDialogs.alert('Speech bubbles 17-22 were unlocked.');
},
_unlockHats2:function(){
tempFile.writeBytes(this.Offsets.HATS2, this.Constants.ALL_HATS2);
getField('button-unlockhats2').disabled=true;
MarcDialogs.alert('All hats (pack 2) were unlocked.');
},
_unlockHats3:function(){
tempFile.writeBytes(this.Offsets.HATS3, this.Constants.ALL_HATS3);
getField('button-unlockhats3').disabled=true;
MarcDialogs.alert('All hats (pack 3) were unlocked.');
},
_unlockHatsGame:function(i){
for(var j=0; j<this.Constants.HATS_GAMES[i].length; j+=2){
var offset=this.Constants.HATS_GAMES[i][j];
var mask=this.Constants.HATS_GAMES[i][j+1];
var byteRead=tempFile.readU8(offset);
tempFile.writeU8(offset, (byteRead & ~mask)+mask);
}
getField('button-unlockhatsgame'+i).disabled=true;
MarcDialogs.alert('Game '+i+' hats were unlocked.');
},
/* check if savegame is valid */
checkValidSavegame:function(){
return (tempFile.fileSize==393216)
},
/* preload function */
preload:function(){
setNumericRange('sptags', 0, 65535);
setNumericRange('tickets', 0, 156);
setNumericRange('fantastic', 0, 65535);
},
/* load function */
load:function(){
tempFile.littleEndian=true;
setValue('sptags', tempFile.readU32(this.Offsets.STREETPASS_TAGS));
setValue('tickets', tempFile.readU16(this.Offsets.TICKETS));
setValue('fantastic', tempFile.readU16(this.Offsets.FANTASTIC_RATINGS));
var panels=[];
for(var i=0; i<this.Constants.PANELS.length; i++)
panels.push((i+1)+'. '+this.Constants.PANELS[i].Name);
var containerSelectPanel=get('container-select-panel');
var selectPanel=select('panel',panels,this._countCurrentPanelPieces);
selectPanel.style.width='auto';
containerSelectPanel.appendChild(selectPanel);
getField('button-unlockticketshop').disabled=(tempFile.readU8(this.Offsets.SHOP_UNLOCKED) & 0x01);
getField('button-unlockspeechbubbles').disabled=(compareBytes(this.Offsets.SPEECH_BUBBLES, this.Constants.ALL_SPEECH_BUBBLES));
getField('button-unlockspeechbubbles2').disabled=(compareBytes(this.Offsets.SPEECH_BUBBLES2, this.Constants.ALL_SPEECH_BUBBLES2));
getField('button-unlockhats2').disabled=(compareBytes(this.Offsets.HATS2, this.Constants.ALL_HATS2));
getField('button-unlockhats3').disabled=(compareBytes(this.Offsets.HATS3, this.Constants.ALL_HATS3));
/*for(var i=0; i<11; i++){
var enabled=this.Constants.HATS_GAMES[i].length/2;
for(var j=0; j<this.Constants.HATS_GAMES[i].length; j+=2){
var offset=this.Constants.HATS_GAMES[i][j];
var mask=this.Constants.HATS_GAMES[i][j+1];
var byteRead=tempFile.readByte(offset);
if((byteRead & mask) === mask)
enabled--;
}
m('#button-unlockhatsgame'+i).get().disabled=!enabled;
}*/
this._countCurrentPanelPieces();
},
/* save function */
save:function(){
tempFile.writeU32(this.Offsets.STREETPASS_TAGS, getValue('sptags'));
tempFile.writeU16(this.Offsets.TICKETS, getValue('tickets'));
tempFile.writeU16(this.Offsets.FANTASTIC_RATINGS, getValue('fantastic'));
}
}