<p>This tool lets you alter the button mappings for the SF2000 hand-held console; it can generate per-game mappings, as well as alter the global mappings defined in the device's <code>bisrv.asd</code> BIOS file. As the SF2000 supports multiplayer gaming via an optional wireless controller (sold separately), mappings for both Player 1 and Player 2 are possible. 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 was originally written by nikita.burnashev (email) gmail.com; it was re-written (mostly just re-styled) by myself upon their request.</p>
<hr>
<sectionid="fileSection">
<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. If you're choosing your <code>bisrv.asd</code> file, you should probably make a backup of it first, just in case! You can find the <code>bisrv.asd</code> file in the <code>bios</code> folder on your device's microSD card.</p>
<formid="fileForm"action="#">
<label>Open <code>bisrv.asd</code> or game ROM: <inputid="fileSelector"type="file"onchange="fileLoad(event.target.files[0])"></label>
</form>
<divid="fileOutput"></div>
</section>
<hr>
<sectionid="mappingSection">
<h2>Step 2: Choose your button mappings</h2>
<pid="mappingInstructions">Instructions for Step 2 will appear here when you have chosen a file in Step 1 above.</p>
<divid="mappingControls"></div>
</section>
<hr>
<sectionid="saveSection">
<h2>Step 3: Save your mapping changes</h2>
<pid="saveInstructions">Instructions for Step 3 will appear here when you have chosen a file in Step 1 above.</p>
<divid="saveControls"></div>
</section>
<script>
// Global variables...
var mappingTableOffset; // Will contain the offset of the button mappings within the bisrv.asd file
var mappingConsoles; // Will contain a list of the specific game consoles we'll be setting up mappings for
var mappingData; // Used to store the binary data that will eventually be written to the downloadable file
var fileName; // Will hold the name of the selected file, used for naming ROM .kmp files
// Utility function: getButtonMap(int index)
// =========================================
// This function returns data about how given buttons on the SF2000
// map to controls provided by the device's emulators.
document.getElementById("fileOutput").innerHTML = "<pclass=\"infoMessage\">INFO: April 20th <code>bisrv.asd</code> detected</p>";
}
else if (data.length == 12656068) {
// That's the correct length for the May 15th version of the file
// However this firmware version is not currently supported by this tool
// Report this to the user to help avoid confusion in the meantime...
document.getElementById("fileOutput").innerHTML = "<pclass=\"errorMessage\">ERROR: May 15th <code>bisrv.asd</code> detected, however this version of the firmware is not currently supported. Please use the SF2000's new built-in button mapping feature in the meantime.</p>";
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 bisrv.asd file, or a game ROM with a known extension!</p>";
return;
}
// If we're here, then we got some kind of 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 bisrv.asd and we'll set
// mappingData to it's full contents instead...
if (mappingConsoles.length == 1) {
mappingData = new Uint8Array(48);
mappingTableOffset = 0;
fileName = file.name;
}
else {
mappingData = data;
}
// Go ahead call our Step Two function...
stepTwo();
}
}
function stepTwo() {
// We're going to be creating a bunch of HTML here; we want to display banks of mapping
// controls to the user, one bank per console. Each bank will have a heading specifying
// which console it's for, and then a section each for Player 1 and Player 2. Each
// player section will have a list of the six SF2000 buttons that are available to be
// mapped, and for each a selection box of the target console's buttons for the mapping.
// There'll also be a checkbox per button, which can be checked to enable "autofire" on
// that button.
// First, we need to update Step 2's instructions, depending on whether or not the user
// supplied a bisrv.asd file (multiple consoles) or a ROM (one console)...
if (mappingConsoles.length > 1) {
// They provided a bisrv.asd file!
document.getElementById("mappingInstructions").innerHTML = "Below you will see the current global button mappings for the <code>bisrv.asd</code> bios 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.";
}
else {
// They provided a ROM file!
document.getElementById("mappingInstructions").innerHTML = "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.";
}
// Next we'll be looping through all of the consoles we'll be setting up mappings for...
for (var currentConsole = 0; currentConsole <mappingConsoles.length;currentConsole++){
// This console's bank of mapping controls will be stored in a <div>, and we'll add
// a <h3> header for good measure as well...
var currentConsoleNode = document.createElement("div");
// More HTML in this function! We'll display the appropriate instructions to the
// user (either how to replace the bisrv.asd file, or where to put the .kmp file),
// as well as generate a button that (when clicked) will download the appropriate
// file to their device...
// First up, instructions! These will depend on whether they provided a bisrv.asd
// or a game ROM...
if (mappingConsoles.length > 1) {
// They provided a bisrv.asd file!
document.getElementById("saveInstructions").innerHTML = "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.";
}
else {
// They provided a ROM file! To make the instructions clearer, let's calculate
// the name of the keymap file we're generating...
var kmpFileName = fileName.replace(/($|\.[^.]*$)/, function(m, p1) {return p1.toUpperCase() + '.kmp';});
// Now the instructions themselves...
document.getElementById("saveInstructions").innerHTML = "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.";
}
// Now let's add the Download button with it's event...