<p>This tool lets you alter the button mappings for the SF2000 hand-held console; it can generate per-game mappings (NOTE: only possible on firmwares prior to the May 15th firmware), as well as alter the global mappings defined in the device's <code>bisrv.asd</code> BIOS file or in the <code>KeyMapInfo.kmp</code> file used by newer BIOS versions. As the SF2000 supports multiplayer gaming via an optional wireless controller (sold separately), mappings for both Player 1 and Player 2 are possible.</p>
<p> Please note this tool is provided as-is, and no support will be given if this corrupts your device's BIOS or keymap file; make sure you have backups of anything you care about before messing with your device's critical files! 🙂</p>
<h2>Step 1: Select <code>bisrv.asd</code> or a game ROM</h2>
<p>Select the <code>bisrv.asd</code> (for global device mappings) or game ROM file (for per-game mappings) whose button mappings you want to modify. You can find the <code>bisrv.asd</code> file in the <code>bios</code> folder on your device's microSD card.</p>
case "b50e50aa4b1b1d41489586e989f09d47c4e2bc27c072cb0112f83e6bc04e2cca":
mappingTableOffset = 0x8DBC9C;
mappingConsoles = ["Arcade", "Game Boy Advance", "Game Boy, Game Boy Color", "SNES", "Genesis/Mega Drive, Master System", "NES"];
document.getElementById("fileOutput").innerHTML = "<pclass=\"infoMessage\">INFO: April 20th <code>bisrv.asd</code> detected</p>";
break;
// May 15th BIOS...
case "d878a99d26242836178b452814e916bef532d05acfcc24d71baa31b8b6f38ffd":
mappingTableOffset = 0;
mappingConsoles = ["NES", "Genesis/Mega Drive, Master System", "SNES", "Game Boy, Game Boy Color", "Game Boy Advance", "Arcade"];
step1BRequired = true;
document.getElementById("fileOutput").innerHTML = "<pclass=\"infoMessage\">INFO: May 15th <code>bisrv.asd</code> detected</p>";
break;
// May 22nd BIOS...
case "6aebab0e4da39e0a997df255ad6a1bd12fdd356cdf51a85c614d47109a0d7d07":
mappingTableOffset = 0;
mappingConsoles = ["NES", "SNES", "Genesis/Mega Drive, Master System", "Game Boy, Game Boy Color", "Game Boy Advance", "Arcade"];
step1BRequired = true;
document.getElementById("fileOutput").innerHTML = "<pclass=\"infoMessage\">INFO: May 22nd <code>bisrv.asd</code> 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("fileOutput").innerHTML = "<pclass=\"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;
break;
}
// If we're here, then we got some kind bisrv.asd file we're happy with; we'll set
// We got false, so whatever it was, it wasn't a bisrv.asd... let's check some other
// possibilities...
if (data.length == 288) {
// That's the correct length for a KeyMapInfo.kmp file, however we must know the host
// BIOS version before we can correctly process those files. Let the user know...
document.getElementById("fileOutput").innerHTML = "<pclass=\"errorMessage\">ERROR: The file you've provided may be a <code>KeyMapInfo.kmp</code> button map file; however as the internal data structure of these files varies depending on the version of the host BIOS, you must select your device's <code>bisrv.asd</code> file first. You can find this file in the <code>bios</code> folder on your device's microSD card.";
return;
}
// If we're still checking, next test the file extensions for the individual console's ROMs...
else if (/\.(zfb|zip)$/i.exec(file.name)) {
// The file's name ends with .zfb or .zip - assume it's an arcade ROM!
mappingConsoles = ["Arcade"];
}
else if (/\.(zgb|gba|agb|gbz)$/i.exec(file.name)) {
// The file's name ends with .zgb, .gba, .agb or .gbz - assume it's a Game Boy Advance ROM!
mappingConsoles = ["Game Boy Advance"];
}
else if (/\.(gbc|gb|sgb)$/i.exec(file.name)) {
// The file's name ends with .gbc, .gb or .sgb - assume it's a Game Boy or Game Boy Color ROM!
mappingConsoles = ["Game Boy, Game Boy Color"];
}
else if (/\.(zsf|smc|fig|sfc|gd3|gd7|dx2|bsx|swc)$/i.exec(file.name)) {
// The file's name ends with .zsf, .smc, .fig, .sfc, .gd3, .gd7, .dx2, .bsx or .swc - assume it's a SNES ROM!
mappingConsoles = ["SNES"];
}
else if (/\.(zmd|bin|md|smd|gen|sms)$/i.exec(file.name)) {
// The file's name ends with .zmd, .bin, .md, .smd, .gen or .sms - assume it's a Genesis/Mega Drive or Master System ROM!
else if (/\.(zfc|nes|nfc|fds|unf)$/i.exec(file.name)) {
// The file's name ends with .zfc, .nes, .nfc, .fds or .unf - assume it's a NES ROM!
mappingConsoles = ["NES"];
}
else {
// Oh dear, the provided file didn't match any of the above rules! Display an error
// to the user...
document.getElementById("fileOutput").innerHTML = "<pclass=\"errorMessage\">ERROR: The selected file does not appear to be a known <code>bisrv.asd</code> file, a <code>KeyMapInfo.kmp</code> file, or a game ROM with a known extension!</p>";
return;
}
// If we're here, then we got some kind of non-bisrv.asd file we're happy with. If
// mappingConsoles only contains one entry, then it was a ROM file, and we'll want to
// initialise our mappingData array with 48 slots; otherwise, it was a KeyMapInfo.kmp
// and we'll set mappingData to it's full contents instead...
var html = "<sectionid=\"stepOneB\"><h2>Step 1b: Select <code>KeyMapInfo.kmp</code></h2><p>This version of the SF2000 BIOS reads its button mappings from an external file called <code>KeyMapInfo.kmp</code>, stored in the <code>Resources</code> folder on the microSD card. Please select your device's <code>KeyMapInfo.kmp</code> file now.</p><label>Open <code>KeyMapInfo.kmp</code>: <inputid=\"keyMapInfoSelector\"type=\"file\"></label><divid=\"stepOneBOutput\"></div></section>";
// Finally, add a <hr> separator after the last step, and append the new step...
document.getElementById("stepOneBOutput").innerHTML = "<pclass=\"errorMessage\">ERROR: The selected file does not appear to be a valid <code>KeyMapInfo.kmp</code> file.</p>";
return;
}
}
else {
// The file the user selected doesn't appear to be binary data, so
// highly unlikely to be a KeyMapInfo.kmp file...
document.getElementById("stepOneBOutput").innerHTML = "<pclass=\"errorMessage\">ERROR: The selected file does not appear to be a valid <code>KeyMapInfo.kmp</code> file.</p>";
html += "<p>Below you will see the current global button mappings for the file you provided. Each tile covers the button mappings for a different game console - the physical SF2000 buttons are on the left, and the virtual console buttons are in the middle. On the right are some \"autofire\" checkboxes - if the box for a button is checked, it means holding that button down will trigger multiple repeated button presses in the virtual console automatically. As the SF2000 supports local multiplayer via the use of a second wireless controller, there are <i>two</i> sets of button mappings per console - one for Player 1 and one for Player 2. When you have finished tweaking your button mappings, proceed to Step 3.</p>";
html += "<p>Below you will see an empty \"" + mappingConsoles[0] + "\" button mapping table, which will be used to create a unique button mapping profile for \"" + fileName + "\". In the table, the physical SF2000 buttons are on the left, and the virtual console buttons are in the middle. On the right are some \"autofire\" checkboxes - if the box for a button is checked, it means holding that button down will trigger multiple repeated button presses in the virtual console automatically. As the SF2000 supports local multiplayer via the use of a second wireless controller, there are <i>two</i> sets of button mappings per console - one for Player 1 and one for Player 2. When you have finished tweaking your button mappings, proceed to Step 3.</p>";
html += "<p>Click the Download button below to download a new <code>bisrv.asd</code> BIOS file for the SF2000, with your updated global button mappings baked into it. Use it to replace the existing <code>bisrv.asd</code> file in the <code>bios</code> folder on your device's microSD card.</p>";
html += "<p>Click the Download button below to download a new <code>KeyMapInfo.kmp</code> keymap file for the SF2000, with your updated global button mappings baked into it. Use it to replace the existing <code>KeyMapInfo.kmp</code> file in the <code>Resources</code> folder on your device's microSD card.</p>";
html += "<p>Click the Download button below to download an updated version of your file, with your updated global button mappings baked into it. Use it to replace the existing file on your device's microSD card.</p>";
html += "<p>Click the Download button below to download \"" + kmpFileName + "\", a game-specific keymap file for \"" + fileName + "\". Once downloaded, place it in the <code>save</code> subfolder of the folder where the ROM itself is stored. So for example, if \"" + fileName + "\" is in the <code>ROMS</code> folder on your SF2000's microSD card, place the \"" + kmpFileName + "\" file in <code>ROMS/save/</code>. If the <code>save</code> subfolder does not already exist, create it yourself first.</p>";