151 lines
4.7 KiB
JavaScript
151 lines
4.7 KiB
JavaScript
/*
|
|
* 6502 Based Virtual Computer
|
|
* Copyright (C) 2011 Scott C. Duensing <scott@jaegertech.com>
|
|
*
|
|
* 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 = "!@#$%^&*()<?+{}|\":";
|
|
var x = oldC.indexOf(String.fromCharCode(k.code));
|
|
if (x >= 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?
|
|
};
|
|
}
|