mirror of
https://github.com/vonmillhausen/sf2000.git
synced 2025-02-02 03:52:36 +01:00
Updated boot logo tool to support May 22nd firmware
Should also theoretically be easier to add support for future BIOS versions... theoretically 🤷
This commit is contained in:
parent
ef30a8aa6e
commit
b2c2566de9
@ -65,7 +65,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>Data Frog SF2000 Boot Logo Changer</h1>
|
<h1>Data Frog SF2000 Boot Logo Changer</h1>
|
||||||
<p>This tool can be used to alter the boot logo on an SF2000 handheld gaming console. Please note this tool is provided as-is, and no support will be given if this corrupts your device's bios; make sure you have backups of anything you care about before messing with your device's critical files! 🙂</p>
|
<p>This tool can be used to alter the boot logo on an SF2000 handheld gaming console. Please note this tool is provided as-is, and no support will be given if this corrupts your device's bios; make sure you have backups of anything you care about before messing with your device's critical files! 🙂</p>
|
||||||
<h1>NOTE: THIS TOOL IS CURRENTLY INCOMPATIBLE WITH THE MAY 22ND FIRMWARE - DO NOT USE IF YOU ARE ON THAT FIRMWARE. UPDATE WILL COME SOON.</h1>
|
|
||||||
<hr>
|
<hr>
|
||||||
<section id="bisrvSection">
|
<section id="bisrvSection">
|
||||||
<h2>Step 1: Select Original <code>bisrv.asd</code></h2>
|
<h2>Step 1: Select Original <code>bisrv.asd</code></h2>
|
||||||
@ -99,47 +98,174 @@
|
|||||||
var logoOffset; // Will contain the offset of the boot logo within the bisrv.asd file
|
var logoOffset; // Will contain the offset of the boot logo within the bisrv.asd file
|
||||||
var newLogoData; // Used to store the little-endian RGB565 binary data of the new boot logo
|
var newLogoData; // Used to store the little-endian RGB565 binary data of the new boot logo
|
||||||
|
|
||||||
|
// Define a function that takes a Uint8Array and an optional offset and returns the index
|
||||||
|
// of the first match or -1 if not found...
|
||||||
|
function findSequence(needle, haystack, offset) {
|
||||||
|
|
||||||
|
// If offset is not provided, default to 0
|
||||||
|
offset = offset || 0;
|
||||||
|
|
||||||
|
// Loop through the data array starting from the offset
|
||||||
|
for (var i = offset; i < haystack.length - needle.length + 1; i++) {
|
||||||
|
|
||||||
|
// Assume a match until proven otherwise
|
||||||
|
var match = true;
|
||||||
|
|
||||||
|
// Loop through the target sequence and compare each byte
|
||||||
|
for (var j = 0; j < needle.length; j++) {
|
||||||
|
|
||||||
|
if (haystack[i + j] !== needle[j]) {
|
||||||
|
// Mismatch found, break the inner loop and continue the outer loop
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If match is still true after the inner loop, we have found a match
|
||||||
|
if (match) {
|
||||||
|
|
||||||
|
// Return the index of the first byte of the match
|
||||||
|
return i;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach this point, no match was found
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an SHA-256 hash of a given firmware (ignoring common user changes), or returns
|
||||||
|
// false on failure...
|
||||||
|
function getFirmwareHash(data) {
|
||||||
|
|
||||||
|
// Data should be a Uint8Array, which as an object is passed by reference... we're going
|
||||||
|
// to be manipulating that data before generating our hash, but we don't want to modify
|
||||||
|
// the original object at all... so we'll create a copy, and work only on the copy...
|
||||||
|
var dataCopy = data.slice();
|
||||||
|
|
||||||
|
// Only really worthwhile doing this for big bisrv.asd files...
|
||||||
|
if (dataCopy.length > 12640000) {
|
||||||
|
// First, replace CRC32 bits with 00...
|
||||||
|
dataCopy[396] = 0x00;
|
||||||
|
dataCopy[397] = 0x00;
|
||||||
|
dataCopy[398] = 0x00;
|
||||||
|
dataCopy[399] = 0x00;
|
||||||
|
|
||||||
|
// Next identify the boot logo position, and blank it out too...
|
||||||
|
var badExceptionOffset = findSequence([0x62, 0x61, 0x64, 0x5F, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x00, 0x00], dataCopy);
|
||||||
|
if (badExceptionOffset > -1) {
|
||||||
|
var bootLogoStart = badExceptionOffset + 16;
|
||||||
|
for (var i = bootLogoStart; i < (bootLogoStart + 204800); i++) {
|
||||||
|
dataCopy[i] = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next identify the emulator button mappings (if they exist), and blank them out too...
|
||||||
|
var preButtonMapOffset = findSequence([0x00, 0x00, 0x00, 0x71, 0xDB, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], dataCopy);
|
||||||
|
if (preButtonMapOffset > -1) {
|
||||||
|
var postButtonMapOffset = findSequence([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00], dataCopy, preButtonMapOffset);
|
||||||
|
if (postButtonMapOffset > -1) {
|
||||||
|
for (var i = preButtonMapOffset + 16; i < postButtonMapOffset; i++) {
|
||||||
|
dataCopy[i] = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here, we've zeroed-out all of the bits of the firmware that are
|
||||||
|
// semi-user modifiable (boot logo, button mappings and the CRC32 bits); now
|
||||||
|
// we can generate a hash of what's left and compare it against some known
|
||||||
|
// values...
|
||||||
|
return crypto.subtle.digest("SHA-256", dataCopy.buffer)
|
||||||
|
.then(function(digest) {
|
||||||
|
var array = Array.from(new Uint8Array(digest));
|
||||||
|
var hash = array.map(byte => ("00" + byte.toString(16)).slice(-2)).join("");
|
||||||
|
return hash;
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function bisrvLoad(file) {
|
function bisrvLoad(file) {
|
||||||
var frBisrv = new FileReader();
|
var frBisrv = new FileReader();
|
||||||
|
frBisrv.readAsArrayBuffer(file);
|
||||||
|
|
||||||
frBisrv.onload = function(event) {
|
frBisrv.onload = function(event) {
|
||||||
|
|
||||||
// Read the provided file's data into an array...
|
// Read the provided file's data into an array...
|
||||||
var data = new Uint8Array(event.target.result);
|
var data = new Uint8Array(event.target.result);
|
||||||
|
|
||||||
// Let's check the data to see if it looks like one of the known bisrv.asd versions...
|
// We'll do a hash-check against it...
|
||||||
if (data.length == 12647452) {
|
hashResult = getFirmwareHash(data);
|
||||||
// That's the correct length for the original March 28th version of the file
|
|
||||||
|
// The result could be either a Promise if it had a bisrv.asd-like structure and we got
|
||||||
|
// a hash, or false otherwise... let's check!
|
||||||
|
if (hashResult instanceof Promise) {
|
||||||
|
// We got a Promise! Wait for it to finish so we get our bisrv.asd hash...
|
||||||
|
hashResult.then(function(dataHash) {
|
||||||
|
// Check the hash against all the known good ones...
|
||||||
|
switch (dataHash) {
|
||||||
|
// Mid-March BIOS...
|
||||||
|
case "4411143d3030adc442e99f7ac4e7772f300c844bbe10d639702fb3ba049a4ee1":
|
||||||
logoOffset = 0x9B9030;
|
logoOffset = 0x9B9030;
|
||||||
bisrvData = data;
|
bisrvData = data;
|
||||||
document.getElementById("bisrvOutput").innerHTML = "<p class=\"infoMessage\">INFO: March 28th bisrv.asd detected</p>";
|
document.getElementById("bisrvOutput").innerHTML = "<p class=\"infoMessage\">INFO: Mid-March <code>bisrv.asd</code> detected</p>";
|
||||||
}
|
break;
|
||||||
else if (data.length == 12648068) {
|
|
||||||
// That's the correct length for the April 20th version of the file
|
// April 20th BIOS...
|
||||||
|
case "b50e50aa4b1b1d41489586e989f09d47c4e2bc27c072cb0112f83e6bc04e2cca":
|
||||||
logoOffset = 0x9B91D8;
|
logoOffset = 0x9B91D8;
|
||||||
bisrvData = data;
|
bisrvData = data;
|
||||||
document.getElementById("bisrvOutput").innerHTML = "<p class=\"infoMessage\">INFO: April 20th bisrv.asd detected</p>";
|
document.getElementById("bisrvOutput").innerHTML = "<p class=\"infoMessage\">INFO: April 20th <code>bisrv.asd</code> detected</p>";
|
||||||
}
|
break;
|
||||||
else if (data.length == 12656068) {
|
|
||||||
// That's the correct length for the May 15th version of the file
|
// May 15th BIOS...
|
||||||
|
case "d878a99d26242836178b452814e916bef532d05acfcc24d71baa31b8b6f38ffd":
|
||||||
logoOffset = 0x9BB0B8;
|
logoOffset = 0x9BB0B8;
|
||||||
bisrvData = data;
|
bisrvData = data;
|
||||||
document.getElementById("bisrvOutput").innerHTML = "<p class=\"infoMessage\">INFO: May 15th bisrv.asd detected</p>";
|
document.getElementById("bisrvOutput").innerHTML = "<p class=\"infoMessage\">INFO: May 15th bisrv.asd detected</p>";
|
||||||
}
|
break;
|
||||||
else {
|
|
||||||
document.getElementById("bisrvOutput").innerHTML = "<p class=\"errorMessage\">ERROR: The selected file does not appear to be a known bisrv.asd file!</p>";
|
// May 22nd BIOS...
|
||||||
document.getElementById("imageSelector").setAttribute("disabled", "");
|
case "6aebab0e4da39e0a997df255ad6a1bd12fdd356cdf51a85c614d47109a0d7d07":
|
||||||
document.getElementById("downloadButton").setAttribute("disabled", "");
|
logoOffset = 0x9BB098;
|
||||||
bisrvData = undefined;
|
bisrvData = data;
|
||||||
logoOffset = undefined;
|
document.getElementById("bisrvOutput").innerHTML = "<p class=\"infoMessage\">INFO: May 22nd bisrv.asd detected</p>";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Huh... wasn't false so had bisrv.asd structure, but didn't return
|
||||||
|
// a known hash... a new BIOS version? Unknown anyway!
|
||||||
|
console.log(dataHash);
|
||||||
|
document.getElementById("bisrvOutput").innerHTML = "<p class=\"errorMessage\">ERROR: While the file you've selected does appear to be generally structured like the SF2000's <code>bisrv.asd</code> BIOS file, the specifics of your file don't match any known SF2000 BIOS version. As such, this tool cannot modify the selected file.</p>";
|
||||||
return;
|
return;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're here we've got a good file, so enable the input for step 2 (image selection)...
|
// If we're here we've got a good file, so enable the input for step 2 (image selection)...
|
||||||
document.getElementById("imageSelector").removeAttribute("disabled");
|
document.getElementById("imageSelector").removeAttribute("disabled");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We got false, so whatever it was, it wasn't a bisrv.asd...
|
||||||
|
document.getElementById("bisrvOutput").innerHTML = "<p class=\"errorMessage\">ERROR: The file you've selected doesn't appear to have the same data structure as expected for a <code>bisrv.asd</code> file.</p>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
frBisrv.readAsArrayBuffer(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function imageLoad(file) {
|
function imageLoad(file) {
|
||||||
@ -271,6 +397,6 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<hr>
|
<hr>
|
||||||
<p><a rel="license" href="http://creativecommons.org/publicdomain/zero/1.0/">CC0</a>: public domain. Version 1.1, 20230516.1</p>
|
<p><a rel="license" href="http://creativecommons.org/publicdomain/zero/1.0/">CC0</a>: public domain. Version 1.2, 20230522.1</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user