mirror of
https://github.com/marcrobledo/savegame-editors.git
synced 2025-04-24 16:35:10 +00:00
Merge pull request #447 from magiczocker10/patch-2
Add "The Lego Movie Videogame"
This commit is contained in:
commit
5a0977597b
@ -118,6 +118,7 @@ h6 a:hover{
|
||||
<a class="four columns game" href="streetpass-mii-plaza/"><img src="thumb.png" id="thumb-streetpass-mii-plaza" /><div>StreetPass Mii Plaza</div></a>
|
||||
<a class="four columns game" href="picross-3d-round-2/"><img src="thumb.png" id="thumb-picross-3d-round-2" /><div>Picross 3D: Round 2</div></a>
|
||||
<a class="four columns game" href="rhythm-paradise-megamix/"><img src="thumb.png" id="thumb-rhythm-paradise-megamix" /><div>Rhythm Paradise Megamix</div></a>
|
||||
<a class="four columns game" href="the-lego-movie-videogame/"><img src="thumb.png" id="thumb-the-lego-movie-videogame" /><div>The Lego Movie Videogame</div></a>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
82
the-lego-movie-videogame/_cache_service_worker.js
Normal file
82
the-lego-movie-videogame/_cache_service_worker.js
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Cache Service Worker template by mrc 2019
|
||||
mostly based in:
|
||||
https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/basic/service-worker.js
|
||||
https://github.com/chriscoyier/Simple-Offline-Site/blob/master/js/service-worker.js
|
||||
https://gist.github.com/kosamari/7c5d1e8449b2fbc97d372675f16b566e
|
||||
|
||||
Note for GitHub Pages:
|
||||
there can be an unexpected behaviour (cache not updating) when site is accessed from
|
||||
https://user.github.io/repo/ (without index.html) in some browsers (Firefox)
|
||||
use absolute paths if hosted in GitHub Pages in order to avoid it
|
||||
also invoke sw with an absolute path:
|
||||
navigator.serviceWorker.register('/repo/_cache_service_worker.js', {scope: '/repo/'})
|
||||
*/
|
||||
|
||||
|
||||
/* MOD: fix old caches for mrc */
|
||||
caches.keys().then(function(cacheNames){
|
||||
for(var i=0; i<cacheNames.length; i++){
|
||||
if(
|
||||
cacheNames[i]==='runtime' ||
|
||||
/^precache-\w+$/.test(cacheNames[i]) ||
|
||||
/^precache-editor-([\w\+]+)-\w+$/.test(cacheNames[i]) ||
|
||||
/^v?\d+\w?$/.test(cacheNames[i])
|
||||
){
|
||||
console.log('deleting old cache: '+cacheNames[i]);
|
||||
caches.delete(cacheNames[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var PRECACHE_ID='the-lego-movie-videogame-editor';
|
||||
var PRECACHE_VERSION='v1';
|
||||
var PRECACHE_URLS=[
|
||||
'/savegame-editors/the-lego-movie-videogame/','/savegame-editors/the-lego-movie-videogame/index.html',
|
||||
'/savegame-editors/the-lego-movie-videogame/favicon.png',
|
||||
'/savegame-editors/the-lego-movie-videogame/the-lego-movie-videogame.js',
|
||||
'/savegame-editors/savegame-editor.js',
|
||||
'/savegame-editors/savegame-editor.css'
|
||||
];
|
||||
|
||||
|
||||
|
||||
// install event (fired when sw is first installed): opens a new cache
|
||||
self.addEventListener('install', evt => {
|
||||
evt.waitUntil(
|
||||
caches.open('precache-'+PRECACHE_ID+'-'+PRECACHE_VERSION)
|
||||
.then(cache => cache.addAll(PRECACHE_URLS))
|
||||
.then(self.skipWaiting())
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// activate event (fired when sw is has been successfully installed): cleans up old outdated caches
|
||||
self.addEventListener('activate', evt => {
|
||||
evt.waitUntil(
|
||||
caches.keys().then(cacheNames => {
|
||||
return cacheNames.filter(cacheName => (cacheName.startsWith('precache-'+PRECACHE_ID+'-') && !cacheName.endsWith('-'+PRECACHE_VERSION)));
|
||||
}).then(cachesToDelete => {
|
||||
return Promise.all(cachesToDelete.map(cacheToDelete => {
|
||||
console.log('delete '+cacheToDelete);
|
||||
return caches.delete(cacheToDelete);
|
||||
}));
|
||||
}).then(() => self.clients.claim())
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// fetch event (fired when requesting a resource): returns cached resource when possible
|
||||
self.addEventListener('fetch', evt => {
|
||||
if(evt.request.url.startsWith(self.location.origin)){ //skip cross-origin requests
|
||||
evt.respondWith(
|
||||
caches.match(evt.request).then(cachedResource => {
|
||||
if (cachedResource) {
|
||||
return cachedResource;
|
||||
}else{
|
||||
return fetch(evt.request);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
180
the-lego-movie-videogame/data.js
Normal file
180
the-lego-movie-videogame/data.js
Normal file
@ -0,0 +1,180 @@
|
||||
window.SavegameEditor.Constants.CHARACTERS=[
|
||||
'Abraham Lincoln',
|
||||
'Bad Cop',
|
||||
'Bandit',
|
||||
'Batman',
|
||||
|
||||
'Benny',
|
||||
'Blaze Firefighter',
|
||||
'Bruce Wayne',
|
||||
'Calamity Drone',
|
||||
|
||||
'Cardio Carrie',
|
||||
'Cavalry',
|
||||
'Caveman',
|
||||
'Cleopatra',
|
||||
|
||||
'Deputron',
|
||||
'Dr McScrubs',
|
||||
'El Macho Wrestler',
|
||||
'Emmet (Piece of Resistance)',
|
||||
|
||||
'Emmet (Clown)',
|
||||
'Emmet (Construction)',
|
||||
'Emmet (Lizard)',
|
||||
'Emmet (Magician)',
|
||||
|
||||
'Emmet (Master Builder)',
|
||||
'Emmet (PJs)',
|
||||
'Emmet (Robin Hood)',
|
||||
'Emmet (Robot)',
|
||||
|
||||
'Emmet (Shower)',
|
||||
'Emmet (Surgeon)',
|
||||
'Emmet (Old West)',
|
||||
'Foreman Frank',
|
||||
|
||||
'Gail',
|
||||
'Gallant Guard',
|
||||
'Gandalf',
|
||||
'Garbage Man Dan',
|
||||
|
||||
'Good Cop',
|
||||
'Good Cop (Scribble Face)',
|
||||
'Gordon Zola',
|
||||
'Green Lantern',
|
||||
|
||||
'Green Ninja',
|
||||
'Hank Haystack',
|
||||
'Ice Cream Jo',
|
||||
'Johnny Thunder',
|
||||
|
||||
'Kabob Bob',
|
||||
'Lady Liberty',
|
||||
'Larry the Barrista',
|
||||
'Swamp Creature',
|
||||
|
||||
'Lord Business',
|
||||
'Lord Vampyre',
|
||||
'Ma Cop',
|
||||
'Michelangelo',
|
||||
|
||||
'Mrs Scratchen-Post',
|
||||
'Mummy',
|
||||
'Native Chief',
|
||||
'Natitve Warrior',
|
||||
|
||||
'Outlaw',
|
||||
'Pa Cop',
|
||||
'Panda Guy',
|
||||
'Plumber Joe',
|
||||
|
||||
'President Business',
|
||||
'Prospector',
|
||||
'Robo Construction',
|
||||
'Robo Cowboy',
|
||||
|
||||
'Robo Demolition',
|
||||
'Robo Agent',
|
||||
'Robo Pilot',
|
||||
'Robo Receptionist',
|
||||
|
||||
'Rootbeer Belle',
|
||||
'S.S.P Officer',
|
||||
'S.S.P Officer (Beanie)',
|
||||
'S.S.P Officer (Heavy)',
|
||||
|
||||
'S.S.P Officer (SWAT)',
|
||||
'Sharon Shoehorn',
|
||||
'Sheriff Not-A-Robot',
|
||||
'Sir Stackabrick',
|
||||
|
||||
'Sudds Backwash',
|
||||
'Superman',
|
||||
'Taco Tuesday Guy',
|
||||
'Test Dummy',
|
||||
|
||||
'Unikitty',
|
||||
'Unikitty (Business)',
|
||||
'Unikitty (Queasy)',
|
||||
'Unikitty (Space)',
|
||||
|
||||
'Velma Staplebot',
|
||||
'Vitruvius',
|
||||
'Vitruvius (Young)',
|
||||
'"Where Are My Pants?" Guy',
|
||||
|
||||
'Wiley Fusebot',
|
||||
'William Shakespeare',
|
||||
'Wonder Woman',
|
||||
'Wyldstyle',
|
||||
|
||||
'Wyldstyle (Hooded)',
|
||||
'Wyldstyle (Robot)',
|
||||
'Wyldstyle (Space)',
|
||||
'Wyldstyle (Old West)'
|
||||
];
|
||||
window.SavegameEditor.Constants.LEVELS=[
|
||||
{value:0, name:'Prologue - The Prophecy'},
|
||||
{value:1, name:'Prologue - Building Site'},
|
||||
{value:2, name:'Prologue - The Piece'},
|
||||
{value:3, name:'Police Station - Melting Chamber'},
|
||||
{value:4, name:'Police Station - Alley Escape'},
|
||||
{value:5, name:'Police Station - Bike Chase'},
|
||||
{value:6, name:'Flatbush Gulch - The Portal'},
|
||||
{value:7, name:'Flatbush Gulch - Hillside Slide'},
|
||||
{value:8, name:'Flatbush Gulch - Desert Path'},
|
||||
{value:9, name:'Flatbush Town - Town Outskirts'},
|
||||
{value:10, name:'Flatbush Town - Town Entrance'},
|
||||
{value:11, name:'Flatbush Town - Saloon Showdown'},
|
||||
{value:12, name:'Flatbush Rooftops - Rooftop Ambush'},
|
||||
{value:13, name:'Flatbush Rooftops - Rooftop Escape'},
|
||||
{value:14, name:'Flatbush Rooftops - Rooftop Brawl'},
|
||||
{value:15, name:'Flatbush Chase - Flatbush Canyon'},
|
||||
{value:16, name:'Flatbush Chase - Train Escape'},
|
||||
{value:17, name:'Flatbush Chase - Train Engine'},
|
||||
{value:18, name:'Cloud Cuckoo Land - Middle Zealand'},
|
||||
{value:19, name:'Cloud Cuckoo Land - Cloud Entrance'},
|
||||
{value:20, name:'Cloud Cuckoo Land - Dance Street'},
|
||||
{value:21, name:'Cloud Under Attack - Cloud Escape'},
|
||||
{value:22, name:'Cloud Under Attack - Cuckoo Castle'},
|
||||
{value:23, name:'Cloud Under Attack - Dropship Chase'},
|
||||
{value:24, name:'Submarine - Submarine Attack'},
|
||||
{value:25, name:'Submarine - Submarine Interior'},
|
||||
{value:26, name:'Submarine - MetalBeard\'s Ship'},
|
||||
{value:27, name:'Business HQ - Octan Airlock'},
|
||||
{value:28, name:'Business HQ - Octan Hangar'},
|
||||
{value:29, name:'Business HQ - The Relic Room'},
|
||||
{value:30, name:'The Kragle - Assembly Room'},
|
||||
{value:31, name:'The Kragle - Kragle Shutdown'},
|
||||
{value:32, name:'The Kragle - Think Tank'},
|
||||
{value:33, name:'TV Station - Office Corridors'},
|
||||
{value:34, name:'TV Station - Server Room'},
|
||||
{value:35, name:'TV Station - TV Broadcast'},
|
||||
{value:36, name:'Spaceship Escape - TV Prop Room'},
|
||||
{value:37, name:'Spaceship Escape - Middle Zealand Canyons'},
|
||||
{value:38, name:'Spaceship Escape - Bricksburg Skies'},
|
||||
{value:39, name:'Attack on Bricksburg - Return to Bricksburg'},
|
||||
{value:40, name:'Attack on Bricksburg - Bricksburg Streets'},
|
||||
{value:41, name:'Attack on Bricksburg - Bricksburg Assault'},
|
||||
{value:42, name:'The Cube Ship - Battle for Bricksburg'},
|
||||
{value:43, name:'The Cube Ship - Cube Ship Approach'},
|
||||
{value:44, name:'The Cube Ship - Business Time'}
|
||||
];
|
||||
window.SavegameEditor.Constants.UPGRADES=[
|
||||
'Always Charged',
|
||||
'Fast Use',
|
||||
'Collectable Detector',
|
||||
'Fast Builder',
|
||||
'Mini Game Master',
|
||||
'Invicibility',
|
||||
'Health Regeneration',
|
||||
'Stud Magnet',
|
||||
'Confetti Effects',
|
||||
'Bubble Effects',
|
||||
'Extra Heart',
|
||||
'X8 Stud Multiplier',
|
||||
'X6 Stud Multiplier',
|
||||
'X4 Stud Multiplier',
|
||||
'X2 Stud Multiplier'
|
||||
];
|
142
the-lego-movie-videogame/index.html
Normal file
142
the-lego-movie-videogame/index.html
Normal file
@ -0,0 +1,142 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Savegame Editor – The Lego Movie Videogame</title>
|
||||
<meta http-equiv="content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="description" content="A savegame editor for The Lego Movie Videogame."/>
|
||||
<meta name="keywords" content="html5, savegame, save, editor, hack, exploit, 3ds, the lego movie videogame"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
||||
<link rel="shortcut icon" href="favicon.png"/>
|
||||
<link type="text/css" rel="stylesheet" href="../savegame-editor.css" media="all"/>
|
||||
<script type="text/javascript" src="../savegame-editor.js"></script>
|
||||
<script type="text/javascript" src="./the-lego-movie-videogame.js"></script>
|
||||
<script type="text/javascript" src="./data.js"></script>
|
||||
<script type="text/javascript"><!--
|
||||
/* service worker */
|
||||
var FORCE_HTTPS=true;
|
||||
window.addEventListener('load',function(){
|
||||
if(location.protocol==='http:' && FORCE_HTTPS)
|
||||
location.replace(window.location.href.replace('http:','https:'));
|
||||
else if(location.protocol==='https:' && 'serviceWorker' in navigator)
|
||||
navigator.serviceWorker.register('/savegame-editors/the-lego-movie-videogame/_cache_service_worker.js', {scope: '/savegame-editors/the-lego-movie-videogame/'});
|
||||
}, false);
|
||||
--></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<div id="header">
|
||||
<div id="header-top">
|
||||
<div class="row wrapper">
|
||||
<h1 class="six columns text-left"><img src="favicon.png" /> Savegame Editor <small>for The Lego Movie Videogame</small></h1>
|
||||
<div class="six columns header-buttons text-right">
|
||||
by <a href="/">Marc Robledo</a>
|
||||
<i class="icon github"></i> <a href="https://github.com/marcrobledo/savegame-editors/tree/master/the-lego-movie-videogame" target="_blank">See on GitHub</a>
|
||||
<i class="icon heart"></i> <a href="https://www.paypal.me/marcrobledo/5" target="_blank" rel="nofollow">Donate</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden row wrapper" id="toolbar">
|
||||
<div class="twelve columns text-center">
|
||||
<button class="close" onclick="closeFile()"><i class="icon close"></i> Close file</button>
|
||||
<button class="colored" onclick="saveChanges()"><i class="icon accept"></i> Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- THE EDITOR -->
|
||||
<div id="the-editor" class="wrapper hidden">
|
||||
<!-- Global Settings -->
|
||||
<h3 class="orange">Global settings</h3>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="columns c8">Language</div><div class="columns c4" id="container-language"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c8"><label for="input-savegame">Last used save game</label></div>
|
||||
<div class="columns c4"><input id="input-savegame" type="text" class="fw" disabled/></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c4"><label for="checkbox-music">Music</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-music" type="checkbox" class="fw" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c4"><label for="checkbox-microphone">Microphone</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-microphone" type="checkbox" class="fw" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Player Info -->
|
||||
<h3 class="orange">Account</h3>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="columns c8"><label for="input-blue-stones">Blue Stones</label></div>
|
||||
<div class="columns c4"><input id="input-blue-stones" type="text" class="fw" /></div>
|
||||
<div class="columns c8"><span>Last Played</span></div>
|
||||
<div class="columns c4" id="container-last-played"></div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="orange">Characters</h3>
|
||||
<div class="container">
|
||||
<div class="row" id="character-list">
|
||||
<!-- Content is generated with the-lego-movie-videogame.js -->
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="orange">Levels</h3>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="columns c8">Select level</div>
|
||||
<div class="columns c4" id="container-levelselection"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c8"><label for="input-level-stones">Collected Stones</label></div>
|
||||
<div class="columns c4"><input id="input-level-stones" type="text" class="fw" /></div>
|
||||
</div>
|
||||
<h3 class="orange">Challenges</h3>
|
||||
<div class="row">
|
||||
<div class="columns c4"><label for="checkbox-challenge-1-unlocked">Challenge 1</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-1-unlocked" type="checkbox" class="fw" data-challenge="0" /></div>
|
||||
<div class="columns c4"><label for="checkbox-challenge-6-unlocked">Challenge 6</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-6-unlocked" type="checkbox" class="fw" data-challenge="5" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c4"><label for="checkbox-challenge-2-unlocked">Challenge 2</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-2-unlocked" type="checkbox" class="fw" data-challenge="1" /></div>
|
||||
<div class="columns c4"><label for="checkbox-challenge-7-unlocked">Challenge 7</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-7-unlocked" type="checkbox" class="fw" data-challenge="6" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c4"><label for="checkbox-challenge-3-unlocked">Challenge 3</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-3-unlocked" type="checkbox" class="fw" data-challenge="2" /></div>
|
||||
<div class="columns c4"><label for="checkbox-challenge-8-unlocked">Challenge 8</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-8-unlocked" type="checkbox" class="fw" data-challenge="7" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c4"><label for="checkbox-challenge-4-unlocked">Challenge 4</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-4-unlocked" type="checkbox" class="fw" data-challenge="3" /></div>
|
||||
<div class="columns c4"><label for="checkbox-challenge-9-unlocked">Challenge 9</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-9-unlocked" type="checkbox" class="fw" data-challenge="8" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns c4"><label for="checkbox-challenge-5-unlocked">Challenge 5</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-5-unlocked" type="checkbox" class="fw" data-challenge="4" /></div>
|
||||
<div class="columns c4"><label for="checkbox-challenge-10-unlocked">Challenge 10</label></div>
|
||||
<div class="columns c2 text-right"><input id="checkbox-challenge-10-unlocked" type="checkbox" class="fw" data-challenge="9" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="orange">Sections</h3>
|
||||
<div class="container">
|
||||
<div class="row" id="sections-list">
|
||||
<!-- Content is generated with the-lego-movie-videogame.js -->
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="orange">Upgrades</h3>
|
||||
<div class="container">
|
||||
<div class="row" id="upgrades-list">
|
||||
<!-- Content is generated with the-lego-movie-videogame.js -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
the-lego-movie-videogame/savegame.dat
Normal file
BIN
the-lego-movie-videogame/savegame.dat
Normal file
Binary file not shown.
288
the-lego-movie-videogame/the-lego-movie-videogame.js
Normal file
288
the-lego-movie-videogame/the-lego-movie-videogame.js
Normal file
@ -0,0 +1,288 @@
|
||||
/*
|
||||
Picross 3D round 2 for HTML5 Save Editor v20160704
|
||||
by Marc Robledo 2016
|
||||
*/
|
||||
function convert_to_bit(d, l){
|
||||
return ('0000000000000000' + (d >>> 0).toString(2)).slice(0-l).split('');
|
||||
}
|
||||
SavegameEditor={
|
||||
Name:'The Lego Movie Videogame',
|
||||
Filename:'savegame.dat',
|
||||
|
||||
/* Constants */
|
||||
Constants:{
|
||||
BLUE_STONES_OFFSET:0x228, // 552
|
||||
CHALLENGE_OFFSET:0x8,
|
||||
CHARACTER_OFFSET:0x47C, // 1148
|
||||
CHARACTER_OPTIONS:[
|
||||
{value:0, name:'Locked'},
|
||||
{value:1, name:'Unlocked'},
|
||||
{value:2, name:'Unlocked+Bought'}
|
||||
],
|
||||
SETTINGS_MUSIC_MICROPHONE_OFFSET:0x18, // 00=All OFF, A0=Music ON, 0A=Microphone ON, AA=All ON
|
||||
LANGUAGE_OFFSET:0x19,
|
||||
LANGUAGES:[
|
||||
{value:1, name:'English'},
|
||||
{value:2, name:'French'},
|
||||
{value:3, name:'Italian'},
|
||||
{value:4, name:'German'},
|
||||
{value:5, name:'Spanish'},
|
||||
{value:6, name:'Dutch'},
|
||||
{value:7, name:'Danish'}
|
||||
],
|
||||
LEVEL_LAST_PLAYED_OFFSET: 0x6, // 6
|
||||
LEVEL_LAST_PLAYED_OFFSET2: 0x454, // 1108
|
||||
PROFILES:[
|
||||
{value:1, name:'Save slot 1', offset:0x1c}, // 28
|
||||
{value:2, name:'Save slot 2', offset:0x4fc} // 1276
|
||||
],
|
||||
PROFILE_SELECTION_OFFSET:0x1A,
|
||||
SECTION_UNLOCK_OFFSET:0x4A4, // 1188
|
||||
SECTION_UNLOCK_STATUS:[
|
||||
{value:0, name:'Locked, Locked, Locked'},
|
||||
{value:1, name:'Unlocked - Locked - Locked'},
|
||||
{value:21, name:'Played - Unlocked - Locked'},
|
||||
{value:341, name:'Player - Played - Unlocked'},
|
||||
{value:1911, name:'Player - Played - Played'}
|
||||
],
|
||||
UPGRADES_OFFSET:0x475, // 1141
|
||||
YELLOW_STONE_OFFSET:0x238, // 568
|
||||
},
|
||||
/* CRC32 - from Alex - https://stackoverflow.com/a/18639999 */
|
||||
/* Combined with CRC32-Version by Slattz (https://github.com/Slattz/POTC3D_Rehash) */
|
||||
CRC32_TABLE:(function(){
|
||||
var c,crcTable=[];
|
||||
for(var n=0;n<256;n++){
|
||||
c=n;
|
||||
for(var k=0;k<8;k++)
|
||||
c=((c&1)?(0xedb88320^(c>>>1)):(c>>>1));
|
||||
crcTable[n]=(c>>>0);
|
||||
}
|
||||
return crcTable;
|
||||
}()),
|
||||
crc32:function(file, len, offset){
|
||||
var data=file.readBytes(offset, len-offset);
|
||||
var checksum=0xFF;
|
||||
var byte= 0b0;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
[byte]=new Int8Array([data[i]]);
|
||||
var [cs_] = new Int8Array([checksum]);
|
||||
byte^=cs_;
|
||||
byte&=0xff;
|
||||
var cs___ = (i===0 ? cs_ : checksum);
|
||||
var a = SavegameEditor.CRC32_TABLE[byte];
|
||||
checksum = a ^ (cs___>>>8);
|
||||
}
|
||||
return ((checksum>>>0)<<0);
|
||||
},
|
||||
_getProfileOffset:function(){
|
||||
return this.Constants.PROFILES[Number(getValue('profile-selector')) - 1].offset;
|
||||
},
|
||||
_get_section_status:function(s) {
|
||||
var offset = SavegameEditor._getProfileOffset() + SavegameEditor.Constants.SECTION_UNLOCK_OFFSET;
|
||||
var amount = Math.ceil(1.5*s);
|
||||
var result = '';
|
||||
for (var i = 0; i < amount; i++) {
|
||||
result = convert_to_bit(tempFile.readU8(offset + i), 8).join('') + result;
|
||||
}
|
||||
result = result.substring(0, result.length-12*(s-1)).slice(-12);
|
||||
return parseInt(result, 2);
|
||||
},
|
||||
_write_section_status:function(e) {
|
||||
var s = e.target.dataset.section;
|
||||
var status = getValue('section-status-'+s);
|
||||
var offset = SavegameEditor._getProfileOffset() + SavegameEditor.Constants.SECTION_UNLOCK_OFFSET;
|
||||
var to_write = [];
|
||||
var amount = Math.ceil(1.5*s);
|
||||
var result = '';
|
||||
for (var i = 0; i < amount; i++) {
|
||||
result = convert_to_bit(tempFile.readU8(offset + i), 8).join('') + result;
|
||||
}
|
||||
result = result.substring(0, result.length-12*(s)) + convert_to_bit(status, 12).join('') + result.substring(result.length-12*(s-1), result.length);
|
||||
for (var j = 0; j < result.length; j+=8){
|
||||
to_write.unshift(result.substring(j, j+8));
|
||||
}
|
||||
for (var k = 0; k < to_write.length; k++) {
|
||||
tempFile.writeU8(
|
||||
offset + k,
|
||||
parseInt(to_write[k], 2)
|
||||
);
|
||||
}
|
||||
},
|
||||
_write_language:function(){
|
||||
tempFile.writeU8(
|
||||
SavegameEditor.Constants.LANGUAGE_OFFSET,
|
||||
getValue('language')
|
||||
);
|
||||
},
|
||||
_get_level_stone_offset:function(){
|
||||
var profileStartOffset = SavegameEditor._getProfileOffset();
|
||||
return profileStartOffset + SavegameEditor.Constants.YELLOW_STONE_OFFSET + Number(getValue('levels')) * 8;
|
||||
},
|
||||
_write_level_stones:function(){
|
||||
tempFile.writeU24(
|
||||
SavegameEditor._get_level_stone_offset(),
|
||||
getValue('level-stones')
|
||||
);
|
||||
},
|
||||
_write_blue_stones:function(){
|
||||
var profileStartOffset = SavegameEditor._getProfileOffset();
|
||||
tempFile.writeU24(
|
||||
profileStartOffset + SavegameEditor.Constants.BLUE_STONES_OFFSET,
|
||||
getValue('blue-stones')
|
||||
);
|
||||
},
|
||||
_write_sound_settings:function(){
|
||||
tempFile.writeU8(
|
||||
SavegameEditor.Constants.SETTINGS_MUSIC_MICROPHONE_OFFSET,
|
||||
(getField('checkbox-microphone').checked ? 10 : 0) + (getField('checkbox-music').checked ? 160 : 0)
|
||||
);
|
||||
},
|
||||
_write_last_played:function(){
|
||||
tempFile.writeU8(
|
||||
SavegameEditor.Constants.LEVEL_LAST_PLAYED_OFFSET,
|
||||
getValue('last-played')
|
||||
);
|
||||
tempFile.writeU8(
|
||||
SavegameEditor.Constants.LEVEL_LAST_PLAYED_OFFSET2,
|
||||
getValue('last-played')
|
||||
);
|
||||
},
|
||||
_write_character:function(e){
|
||||
var profileStartOffset = SavegameEditor._getProfileOffset();
|
||||
var offset = profileStartOffset + SavegameEditor.Constants.CHARACTER_OFFSET + Number(e.target.dataset.offset);
|
||||
var bits = convert_to_bit(tempFile.readU8(offset), 8);
|
||||
var val = getValue(e.target.id);
|
||||
bits[e.target.dataset.offset_*2]=(val==='2' ? '1' : '0');
|
||||
bits[e.target.dataset.offset_*2+1]=(val!=='0' ? '1' : '0');
|
||||
tempFile.writeU8(
|
||||
offset,
|
||||
parseInt(bits.join(''), 2)
|
||||
);
|
||||
},
|
||||
_write_challenge:function(e){
|
||||
var lvl = Number(getValue('levels'));
|
||||
tempFile.writeU8(
|
||||
SavegameEditor._getProfileOffset()+SavegameEditor.Constants.CHALLENGE_OFFSET+(lvl)*10+Number(e.target.dataset.challenge),
|
||||
e.target.checked === true ? '1' : '0'
|
||||
);
|
||||
},
|
||||
_write_upgrade:function(e){
|
||||
var profileStartOffset = SavegameEditor._getProfileOffset();
|
||||
var offset = profileStartOffset + SavegameEditor.Constants.UPGRADES_OFFSET;
|
||||
var bitsUnlocked = convert_to_bit(tempFile.readU16(offset), 16);
|
||||
var bitsBought = convert_to_bit(tempFile.readU16(offset+2), 16);
|
||||
var val = getValue(e.target.id);
|
||||
bitsBought[e.target.dataset.offset]=(val==='2' ? '1' : '0');
|
||||
bitsUnlocked[e.target.dataset.offset]=(val!=='0' ? '1' : '0');
|
||||
tempFile.writeU16(
|
||||
offset,
|
||||
parseInt(bitsUnlocked.join(''), 2)
|
||||
);
|
||||
tempFile.writeU16(
|
||||
offset+2,
|
||||
parseInt(bitsBought.join(''), 2)
|
||||
);
|
||||
},
|
||||
_load_level:function(){
|
||||
var profileStartOffset = SavegameEditor._getProfileOffset();
|
||||
var lvl = Number(getValue('levels'));
|
||||
setValue('level-stones', tempFile.readU24(SavegameEditor._get_level_stone_offset()));
|
||||
for (var i = 0; i < 10; i++) {
|
||||
getField('challenge-' + (i + 1) + '-unlocked').checked = tempFile.readU8(profileStartOffset + SavegameEditor.Constants.CHALLENGE_OFFSET + (lvl - 1) * 10 + i) === 1;
|
||||
}
|
||||
},
|
||||
_load_profile:function(){
|
||||
var profileStartOffset = SavegameEditor._getProfileOffset();
|
||||
|
||||
setValue('blue-stones', tempFile.readU24(profileStartOffset + SavegameEditor.Constants.BLUE_STONES_OFFSET));
|
||||
setValue('levels', '1');
|
||||
var field, a, b, c;
|
||||
for (c = 0; c < SavegameEditor.Constants.CHARACTERS.length; c++) {
|
||||
field = getField('select-character-'+c);
|
||||
a = convert_to_bit(tempFile.readU8(profileStartOffset + SavegameEditor.Constants.CHARACTER_OFFSET + Number(field.dataset.offset)), 8);
|
||||
b = (a[field.dataset.offset_*2]==='1') ? '2' : ((a[field.dataset.offset_*2+1]==='1') ? '1' : '0');
|
||||
setValue('character-'+c, Number(b));
|
||||
}
|
||||
var unlocked = convert_to_bit(tempFile.readU16(profileStartOffset + SavegameEditor.Constants.UPGRADES_OFFSET), 16);
|
||||
var bought = convert_to_bit(tempFile.readU16(profileStartOffset + SavegameEditor.Constants.UPGRADES_OFFSET+2), 16);
|
||||
for (c = 0; c < SavegameEditor.Constants.UPGRADES.length; c++) {
|
||||
field = getField('select-upgrade-'+c);
|
||||
b = (bought[field.dataset.offset]==='1') ? '2' : ((unlocked[field.dataset.offset]==='1') ? '1' : '0');
|
||||
setValue('upgrade-'+c, Number(b));
|
||||
}
|
||||
setValue('last-played', tempFile.readU8(profileStartOffset + SavegameEditor.Constants.LEVEL_LAST_PLAYED_OFFSET));
|
||||
SavegameEditor._load_level();
|
||||
for (var l = 1; l < 16; l++) {
|
||||
setValue('section-status-'+l, SavegameEditor._get_section_status(l));
|
||||
}
|
||||
},
|
||||
|
||||
/* check if savegame is valid */
|
||||
checkValidSavegame:function(){
|
||||
return (tempFile.fileSize==2524);
|
||||
},
|
||||
|
||||
preload:function() {
|
||||
get('toolbar').children[0].appendChild(select('profile-selector', this.Constants.PROFILES, this._load_profile));
|
||||
get('container-language').appendChild(select('language', SavegameEditor.Constants.LANGUAGES, SavegameEditor._write_language));
|
||||
get('container-levelselection').appendChild(select('levels', SavegameEditor.Constants.LEVELS, SavegameEditor._load_level));
|
||||
for (var i = 0; i < 10; i++) {
|
||||
getField('challenge-' + (i + 1) + '-unlocked').addEventListener('change', SavegameEditor._write_challenge);
|
||||
}
|
||||
get('container-last-played').appendChild(select('last-played', SavegameEditor.Constants.LEVELS, SavegameEditor._write_last_played));
|
||||
get('input-level-stones').addEventListener('change', SavegameEditor._write_level_stones);
|
||||
get('input-blue-stones').addEventListener('change', SavegameEditor._write_blue_stones);
|
||||
getField('checkbox-microphone').addEventListener('change', SavegameEditor._write_sound_settings);
|
||||
getField('checkbox-music').addEventListener('change', SavegameEditor._write_sound_settings);
|
||||
setNumericRange('blue-stones', 0, 16777215);
|
||||
var tmp1 = get('character-list');
|
||||
for (var j = 0; j < SavegameEditor.Constants.CHARACTERS.length; j++) {
|
||||
tmp1.appendChild(col(2,span(SavegameEditor.Constants.CHARACTERS[j])));
|
||||
var sel=select('character-'+j,SavegameEditor.Constants.CHARACTER_OPTIONS, SavegameEditor._write_character);
|
||||
sel.dataset.offset=Math.floor(j*0.25);
|
||||
sel.dataset.offset_=3-(j-sel.dataset.offset*4);
|
||||
tmp1.appendChild(col(4,sel));
|
||||
}
|
||||
var tmp2 = get('upgrades-list');
|
||||
for (var k = 0; k < SavegameEditor.Constants.UPGRADES.length; k++) {
|
||||
tmp2.appendChild(col(2,span(SavegameEditor.Constants.UPGRADES[k])));
|
||||
var sel_=select('upgrade-'+k,SavegameEditor.Constants.CHARACTER_OPTIONS, SavegameEditor._write_upgrade);
|
||||
sel_.dataset.offset=k;
|
||||
tmp2.appendChild(col(4,sel_));
|
||||
}
|
||||
var tmp3 = get('sections-list');
|
||||
for (var l = 1; l < 16; l++) {
|
||||
var sel__ = select('section-status-' + l, SavegameEditor.Constants.SECTION_UNLOCK_STATUS, SavegameEditor._write_section_status);
|
||||
sel__.dataset.section = l;
|
||||
tmp3.append(
|
||||
col(2, span('S' + l + ' (Level ' + ((l-1)*3+1) + '-' + (l*3) + ')')),
|
||||
col(4, sel__)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/* load function */
|
||||
load:function(){
|
||||
tempFile.fileName='savegame.dat';
|
||||
tempFile.littleEndian=true;
|
||||
console.log("Old CRC32 ", tempFile.readU32(0));
|
||||
console.log("Calced CRC32 ", SavegameEditor.crc32(tempFile, tempFile.fileSize, 24));
|
||||
|
||||
setValue('language', tempFile.readU8(SavegameEditor.Constants.LANGUAGE_OFFSET));
|
||||
setValue('savegame', 'Save game #' + (tempFile.readU8(SavegameEditor.Constants.PROFILE_SELECTION_OFFSET) + 1));
|
||||
getField('checkbox-microphone').checked = tempFile.readU8(SavegameEditor.Constants.SETTINGS_MUSIC_MICROPHONE_OFFSET)>0;
|
||||
getField('checkbox-music').checked = tempFile.readU8(SavegameEditor.Constants.SETTINGS_MUSIC_MICROPHONE_OFFSET)>100;
|
||||
this._load_profile();
|
||||
},
|
||||
|
||||
|
||||
/* save function */
|
||||
save:function(){
|
||||
console.log("New CRC32 ", SavegameEditor.crc32(tempFile, tempFile.fileSize, 24));
|
||||
tempFile.writeU32(
|
||||
0,
|
||||
SavegameEditor.crc32(tempFile, tempFile.fileSize, 24)
|
||||
);
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user