/* 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 . */ JSNES.DummyUI = function(nes) { this.nes = nes; this.enable = function() {}; this.updateStatus = function() {}; this.writeAudio = function() {}; this.writeFrame = function() {}; }; if (typeof jQuery !== 'undefined') { (function($) { $.fn.JSNESUI = function(roms) { var parent = this; var UI = function(nes) { var self = this; self.nes = nes; /* * Create UI */ self.root = $('
'); self.screen = $('').appendTo(self.root); if (!self.screen[0].getContext) { parent.html("Your browser doesn't support the <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; } }, /* * * nes.ui.screenshot() --> return element :) */ screenshot: function() { var data = this.screen[0].toDataURL("image/png"), img = new Image(); img.src = data; return img; }, /* * 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); }