/* * 6502 Based Virtual Computer * Copyright (C) 2011 Scott C. Duensing * * 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 2 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, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Our keyboard object. function keyboard() { // OMFGWTFBBQ - http://unixpapa.com/js/key.html // --- Private variables. // Memory location for keyboard status. var MEMORY = null; var MEMORY_START = 0; var CHARACTER_ADDRESS = 0; var META_ADDRESS = 0; // Keymaps. Swiped from http://jonathan.tang.name/code/js_keycode var KEY_MAP = {}; var SHIFTED_SYMBOLS = { 58: 59, // : -> ; 43: 61, // = -> + 60: 44, // < -> , 95: 45, // _ -> - 62: 46, // > -> . 63: 47, // ? -> / 96: 192, // ` -> ~ 124: 92, // | -> \ 39: 222, // ' -> 222 34: 222, // " -> 222 33: 49, // ! -> 1 64: 50, // @ -> 2 35: 51, // # -> 3 36: 52, // $ -> 4 37: 53, // % -> 5 94: 54, // ^ -> 6 38: 55, // & -> 7 42: 56, // * -> 8 40: 57, // ( -> 9 41: 58, // ) -> 0 123: 91, // { -> [ 125: 93 // } -> ] }; var GECKO_IE_KEYMAP = { 186: 59, // ;: in IE 187: 61, // =+ in IE 188: 44, // ,< 109: 95, // -_ in Mozilla 107: 61, // =+ in Mozilla 189: 95, // -_ in IE 190: 62, // .> 191: 47, // /? 192: 126, // `~ 219: 91, // {[ 220: 92, // \| 221: 93 // }] }; var OPERA_KEYMAP = {}; // Browser detection taken from quirksmode.org var IS_WINDOWS = navigator.platform.indexOf('Win') != -1; var IS_OPERA = window.opera && window.opera.version() < '9.5'; var IS_KONQUEROR = navigator.vendor && navigator.vendor.indexOf('KDE') != -1; var IS_ICAB = navigator.vendor && navigator.vendor.indexOf('iCab') != -1; // --- Public methods. // Attach keyboard to DOM. this.attach = function(newMemory, newStartPosition) { MEMORY = newMemory; MEMORY_START = newStartPosition; CHARACTER_ADDRESS = MEMORY_START; META_ADDRESS = MEMORY_START + 1; // Determine key map. if (IS_OPERA && IS_WINDOWS) { KEY_MAP = OPERA_KEYMAP; } else if (IS_OPERA || IS_KONQUEROR || IS_ICAB) { var unshift = [33, 64, 35, 36, 37, 94, 38, 42, 40, 41, 58, 43, 60, 95, 62, 63, 124, 34]; KEY_MAP = OPERA_KEYMAP; for (var i = 0; i < unshift.length; ++i) { KEY_MAP[unshift[i]] = SHIFTED_SYMBOLS[unshift[i]]; } } else { // IE and Gecko are close enough that we can use the same map for both, // and the rest of the world (eg. Opera 9.50) seems to be standardizing // on them KEY_MAP = GECKO_IE_KEYMAP; } if (IS_KONQUEROR) { KEY_MAP[0] = 45; KEY_MAP[127] = 46; KEY_MAP[45] = 95; } // Hook browser for keydown events. document.onkeydown = function(e){ e = e || window.event; // Process the key press. var code = e.which || e.keyCode; var k = { code: KEY_MAP[code] || code, shift: e.shiftKey, alt: e.altKey, ctrl: e.ctrlKey }; // Un-funk the input. if (k.shift) { // Fix shifted characters. var oldC = "1234567890,/=[]\\';"; var newC = "!@#$%^&*()= 0) k.code = newC.charCodeAt(x); if (k.code == 222) k.code = 34; // " } else { // Fix unshifted characters. var oldC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ~_>"; var newC = "abcdefghijklmnopqrstuvwxyz`-."; var x = oldC.indexOf(String.fromCharCode(k.code)); if (x >= 0) k.code = newC.charCodeAt(x); if (k.code == 222) k.code = 39; // ' } // Write meta first. Then we can process on the character being written. MEMORY.writeByte(META_ADDRESS, (k.alt * 4) + (k.ctrl * 2) + k.shift); // Ignore "naked" meta keys in the character address. if ((k.code != 16) && (k.code != 17) && (k.code != 18) && (k.code != 145) && (k.code != 146)) { MEMORY.writeByte(CHARACTER_ADDRESS, k.code); } }; }; // Fetch how much RAM the current settings will require. this.getMemoryNeeded = function() { return 2; // Complicated, huh? }; }