/*
JSNES, based on Jamie Sanders' vNES
Copyright (C) 2010 Ben Firshman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
<canvas>
tag. Try Google Chrome, Safari, Opera or Firefox!");
return;
}
self.romContainer = $('').appendTo(self.root);
self.romSelect = $('').appendTo(self.romContainer);
self.controls = $('').appendTo(self.root);
self.buttons = {
pause: $('').appendTo(self.controls),
restart: $('').appendTo(self.controls),
sound: $('').appendTo(self.controls),
zoom: $('').appendTo(self.controls)
};
self.status = $('Booting up...
').appendTo(self.root); self.root.appendTo(parent); /* * ROM loading */ self.romSelect.change(function() { self.loadROM(); }); /* * Buttons */ self.buttons.pause.click(function() { if (self.nes.isRunning) { self.nes.stop(); self.updateStatus("Paused"); self.buttons.pause.attr("value", "resume"); } else { self.nes.start(); self.buttons.pause.attr("value", "pause"); } }); self.buttons.restart.click(function() { self.nes.reloadRom(); self.nes.start(); }); self.buttons.sound.click(function() { if (self.nes.opts.emulateSound) { self.nes.opts.emulateSound = false; self.buttons.sound.attr("value", "enable sound"); } else { self.nes.opts.emulateSound = true; self.buttons.sound.attr("value", "disable sound"); } }); self.zoomed = false; self.buttons.zoom.click(function() { if (self.zoomed) { self.screen.animate({ width: '256px', height: '240px' }); self.buttons.zoom.attr("value", "zoom in"); self.zoomed = false; } else { self.screen.animate({ width: '512px', height: '480px' }); self.buttons.zoom.attr("value", "zoom out"); self.zoomed = true; } }); /* * Lightgun experiments with mouse * (Requires jquery.dimensions.js) */ if ($.offset) { self.screen.mousedown(function(e) { if (self.nes.mmap) { self.nes.mmap.mousePressed = true; // FIXME: does not take into account zoom self.nes.mmap.mouseX = e.pageX - self.screen.offset().left; self.nes.mmap.mouseY = e.pageY - self.screen.offset().top; } }).mouseup(function() { setTimeout(function() { if (self.nes.mmap) { self.nes.mmap.mousePressed = false; self.nes.mmap.mouseX = 0; self.nes.mmap.mouseY = 0; } }, 500); }); } if (typeof roms != 'undefined') { self.setRoms(roms); } /* * Canvas */ self.canvasContext = self.screen[0].getContext('2d'); if (!self.canvasContext.getImageData) { parent.html("Your browser doesn't support writing pixels directly to the<canvas>
tag. Try the latest versions of Google Chrome, Safari, Opera or Firefox!");
return;
}
self.canvasImageData = self.canvasContext.getImageData(0, 0, 256, 240);
self.resetCanvas();
/*
* Keyboard
*/
$(document).
bind('keydown', function(evt) {
self.nes.keyboard.keyDown(evt);
}).
bind('keyup', function(evt) {
self.nes.keyboard.keyUp(evt);
}).
bind('keypress', function(evt) {
self.nes.keyboard.keyPress(evt);
});
/*
* Sound
*/
self.dynamicaudio = new DynamicAudio({
swf: nes.opts.swfPath+'dynamicaudio.swf'
});
};
UI.prototype = {
loadROM: function() {
var self = this;
self.updateStatus("Downloading...");
$.ajax({
url: escape(self.romSelect.val()),
xhr: function() {
var xhr = $.ajaxSettings.xhr();
if (typeof xhr.overrideMimeType !== 'undefined') {
// Download as binary
xhr.overrideMimeType('text/plain; charset=x-user-defined');
}
self.xhr = xhr;
return xhr;
},
complete: function(xhr, status) {
var i, data;
if (JSNES.Utils.isIE()) {
var charCodes = JSNESBinaryToArray(
xhr.responseBody
).toArray();
data = String.fromCharCode.apply(
undefined,
charCodes
);
}
else {
data = xhr.responseText;
}
self.nes.loadRom(data);
self.nes.start();
self.enable();
}
});
},
resetCanvas: function() {
this.canvasContext.fillStyle = 'black';
// set alpha to opaque
this.canvasContext.fillRect(0, 0, 256, 240);
// Set alpha
for (var i = 3; i < this.canvasImageData.data.length-3; i += 4) {
this.canvasImageData.data[i] = 0xFF;
}
},
/*
* Enable and reset UI elements
*/
enable: function() {
this.buttons.pause.attr("disabled", null);
if (this.nes.isRunning) {
this.buttons.pause.attr("value", "pause");
}
else {
this.buttons.pause.attr("value", "resume");
}
this.buttons.restart.attr("disabled", null);
if (this.nes.opts.emulateSound) {
this.buttons.sound.attr("value", "disable sound");
}
else {
this.buttons.sound.attr("value", "enable sound");
}
},
updateStatus: function(s) {
this.status.text(s);
},
setRoms: function(roms) {
this.romSelect.children().remove();
$("").appendTo(this.romSelect);
for (var groupName in roms) {
if (roms.hasOwnProperty(groupName)) {
var optgroup = $('').
attr("label", groupName);
for (var i = 0; i < roms[groupName].length; i++) {
$('')
.attr("value", roms[groupName][i][1])
.appendTo(optgroup);
}
this.romSelect.append(optgroup);
}
}
},
writeAudio: function(samples) {
return this.dynamicaudio.writeInt(samples);
},
writeFrame: function(buffer, prevBuffer) {
var imageData = this.canvasImageData.data;
var pixel, i, j;
for (i=0; i<256*240; i++) {
pixel = buffer[i];
if (pixel != prevBuffer[i]) {
j = i*4;
imageData[j] = pixel & 0xFF;
imageData[j+1] = (pixel >> 8) & 0xFF;
imageData[j+2] = (pixel >> 16) & 0xFF;
prevBuffer[i] = pixel;
}
}
this.canvasContext.putImageData(this.canvasImageData, 0, 0);
}
};
return UI;
};
})(jQuery);
}