newest versions from Fabrice Bellard
This commit is contained in:
parent
5e4018a0c0
commit
53ccdd71af
3
Makefile
3
Makefile
|
@ -5,3 +5,6 @@ wget-javascript:
|
|||
rm -f *.js
|
||||
wget -c https://bellard.org/jslinux/term.js
|
||||
wget -c https://bellard.org/jslinux/jslinux.js
|
||||
wget -c https://bellard.org/jslinux/x86emu-wasm.js
|
||||
wget -c https://bellard.org/jslinux/riscvemu64-wasm.js
|
||||
wget -c https://bellard.org/jslinux/riscvemu32-wasm.js
|
||||
|
|
727
jslinux.js
727
jslinux.js
|
@ -1,126 +1,661 @@
|
|||
/*
|
||||
Linux launcher
|
||||
|
||||
Copyright (c) 2011-2012 Fabrice Bellard
|
||||
|
||||
Redistribution or commercial use is prohibited without the author's
|
||||
permission.
|
||||
*/
|
||||
/*
|
||||
* JS Linux main
|
||||
*
|
||||
* Copyright (c) 2017 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
var term, pc, boot_start_time, init_state;
|
||||
var term, console_write1, console_resize_event;
|
||||
var graphic_display, display_key_event, display_mouse_event;
|
||||
var net_state, net_write_packet, net_set_carrier;
|
||||
var display_wheel_event;
|
||||
var fs_import_file;
|
||||
var Module = {};
|
||||
var downloading_timer_pending = false;
|
||||
var downloading_timer;
|
||||
|
||||
function term_start()
|
||||
function on_update_file(f)
|
||||
{
|
||||
term = new Term(80, 30, term_handler);
|
||||
|
||||
term.open();
|
||||
var f, reader;
|
||||
reader = new FileReader();
|
||||
reader.onload = function (ev) {
|
||||
var buf, buf_addr, buf_len;
|
||||
buf = new Uint8Array(reader.result);
|
||||
buf_len = buf.length;
|
||||
buf_addr = _malloc(buf_len);
|
||||
HEAPU8.set(buf, buf_addr);
|
||||
/* the buffer is freed by the function */
|
||||
fs_import_file(f.name, buf_addr, buf_len);
|
||||
};
|
||||
reader.readAsArrayBuffer(f);
|
||||
}
|
||||
|
||||
function on_update_files(files)
|
||||
{
|
||||
var i, n;
|
||||
n = files.length;
|
||||
for(i = 0; i < n; i++) {
|
||||
on_update_file(files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* send chars to the serial port */
|
||||
function term_handler(str)
|
||||
{
|
||||
pc.serial.send_chars(str);
|
||||
var i;
|
||||
for(i = 0; i < str.length; i++) {
|
||||
console_write1(str.charCodeAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
function clipboard_set(val)
|
||||
function downloading_timer_cb()
|
||||
{
|
||||
var el = document.getElementById("net_progress");
|
||||
el.style.visibility = "hidden";
|
||||
downloading_timer_pending = false;
|
||||
}
|
||||
|
||||
function update_downloading(flag)
|
||||
{
|
||||
var el;
|
||||
el = document.getElementById("text_clipboard");
|
||||
el.value = val;
|
||||
if (flag) {
|
||||
if (downloading_timer_pending) {
|
||||
clearTimeout(downloading_timer);
|
||||
downloading_timer_pending = false;
|
||||
} else {
|
||||
el = document.getElementById("net_progress");
|
||||
el.style.visibility = "visible";
|
||||
}
|
||||
} else {
|
||||
downloading_timer_pending = true;
|
||||
downloading_timer = setTimeout(downloading_timer_cb, 500);
|
||||
}
|
||||
}
|
||||
|
||||
function clipboard_get()
|
||||
function get_params()
|
||||
{
|
||||
var el;
|
||||
el = document.getElementById("text_clipboard");
|
||||
return el.value;
|
||||
var url, query_str, p, tab, i, params, tab2;
|
||||
query_str = window.location.href;
|
||||
p = query_str.indexOf("?");
|
||||
if (p < 0)
|
||||
return {};
|
||||
query_str = query_str.substr(p + 1);
|
||||
tab = query_str.split("&");
|
||||
params = {};
|
||||
for(i = 0; i < tab.length; i++) {
|
||||
tab2 = tab[i].split("=");
|
||||
params[decodeURIComponent(tab2[0])] = decodeURIComponent(tab2[1]);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
function clear_clipboard()
|
||||
function get_absolute_url(fname)
|
||||
{
|
||||
var el;
|
||||
el = document.getElementById("text_clipboard");
|
||||
el.value = "";
|
||||
}
|
||||
|
||||
/* just used to display the boot time in the VM */
|
||||
function get_boot_time()
|
||||
{
|
||||
return (+new Date()) - boot_start_time;
|
||||
}
|
||||
|
||||
function start()
|
||||
{
|
||||
var params;
|
||||
var path, p;
|
||||
|
||||
init_state = new Object();
|
||||
|
||||
params = new Object();
|
||||
|
||||
/* serial output chars */
|
||||
params.serial_write = term.write.bind(term);
|
||||
|
||||
/* memory size (in bytes) */
|
||||
params.mem_size = 31 * 1024 * 1024;
|
||||
|
||||
/* clipboard I/O */
|
||||
params.clipboard_get = clipboard_get;
|
||||
params.clipboard_set = clipboard_set;
|
||||
|
||||
params.get_boot_time = get_boot_time;
|
||||
|
||||
/* IDE drive. The raw disk image is split into files of
|
||||
* 'block_size' KB.
|
||||
*/
|
||||
//params.hda = { url: "hda%d.bin", block_size: 64, nb_blocks: 912 };
|
||||
params.hda = { url: "bin/hda%d.bin", block_size: 64, nb_blocks: 912 };
|
||||
//modify by hao
|
||||
pc = new PCEmulator(params);
|
||||
|
||||
init_state.params = params;
|
||||
|
||||
pc.load_binary("vmlinux-2.6.20.bin", 0x00100000, start2);
|
||||
if (fname.indexOf(":") >= 0)
|
||||
return fname;
|
||||
path = window.location.pathname;
|
||||
p = path.lastIndexOf("/");
|
||||
if (p < 0)
|
||||
return fname;
|
||||
return window.location.origin + path.slice(0, p + 1) + fname;
|
||||
}
|
||||
|
||||
function start2(ret)
|
||||
function GraphicDisplay(parent_el, width, height)
|
||||
{
|
||||
if (ret < 0)
|
||||
return;
|
||||
init_state.start_addr = 0x10000;
|
||||
pc.load_binary("linuxstart.bin", init_state.start_addr, start3);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.canvas_el = document.createElement("canvas");
|
||||
this.canvas_el.width = width; /* logical width */
|
||||
this.canvas_el.height = height; /* logical width */
|
||||
/* displayed size */
|
||||
this.canvas_el.style.width = width + "px";
|
||||
this.canvas_el.style.height = height + "px";
|
||||
this.canvas_el.style.cursor = "none";
|
||||
|
||||
parent_el.appendChild(this.canvas_el);
|
||||
|
||||
this.ctx = this.canvas_el.getContext("2d");
|
||||
/* clear the display */
|
||||
this.ctx.fillStyle = "#000000";
|
||||
this.ctx.fillRect(0, 0, width, height);
|
||||
|
||||
this.image = this.ctx.createImageData(width, height);
|
||||
|
||||
this.key_pressed = new Uint8Array(128);
|
||||
|
||||
document.addEventListener("keydown",
|
||||
this.keyDownHandler.bind(this), false);
|
||||
document.addEventListener("keyup",
|
||||
this.keyUpHandler.bind(this), false);
|
||||
document.addEventListener("blur",
|
||||
this.blurHandler.bind(this), false);
|
||||
|
||||
this.canvas_el.onmousedown = this.mouseMoveHandler.bind(this);
|
||||
this.canvas_el.onmouseup = this.mouseMoveHandler.bind(this);
|
||||
this.canvas_el.onmousemove = this.mouseMoveHandler.bind(this);
|
||||
this.canvas_el.oncontextmenu = this.onContextMenuHandler.bind(this);
|
||||
this.canvas_el.onwheel = this.wheelHandler.bind(this);
|
||||
}
|
||||
|
||||
function start3(ret)
|
||||
GraphicDisplay.code_to_input_map = {
|
||||
"Escape": 0x01,
|
||||
"Digit1": 0x02,
|
||||
"Digit2": 0x03,
|
||||
"Digit3": 0x04,
|
||||
"Digit4": 0x05,
|
||||
"Digit5": 0x06,
|
||||
"Digit6": 0x07,
|
||||
"Digit7": 0x08,
|
||||
"Digit8": 0x09,
|
||||
"Digit9": 0x0a,
|
||||
"Digit0": 0x0b,
|
||||
"Minus": 0x0c,
|
||||
"Equal": 0x0d,
|
||||
"Backspace": 0x0e,
|
||||
"Tab": 0x0f,
|
||||
"KeyQ": 0x10,
|
||||
"KeyW": 0x11,
|
||||
"KeyE": 0x12,
|
||||
"KeyR": 0x13,
|
||||
"KeyT": 0x14,
|
||||
"KeyY": 0x15,
|
||||
"KeyU": 0x16,
|
||||
"KeyI": 0x17,
|
||||
"KeyO": 0x18,
|
||||
"KeyP": 0x19,
|
||||
"BracketLeft": 0x1a,
|
||||
"BracketRight": 0x1b,
|
||||
"Enter": 0x1c,
|
||||
"ControlLeft": 0x1d,
|
||||
"KeyA": 0x1e,
|
||||
"KeyS": 0x1f,
|
||||
"KeyD": 0x20,
|
||||
"KeyF": 0x21,
|
||||
"KeyG": 0x22,
|
||||
"KeyH": 0x23,
|
||||
"KeyJ": 0x24,
|
||||
"KeyK": 0x25,
|
||||
"KeyL": 0x26,
|
||||
"Semicolon": 0x27,
|
||||
"Quote": 0x28,
|
||||
"Backquote": 0x29,
|
||||
"ShiftLeft": 0x2a,
|
||||
"Backslash": 0x2b,
|
||||
"KeyZ": 0x2c,
|
||||
"KeyX": 0x2d,
|
||||
"KeyC": 0x2e,
|
||||
"KeyV": 0x2f,
|
||||
"KeyB": 0x30,
|
||||
"KeyN": 0x31,
|
||||
"KeyM": 0x32,
|
||||
"Comma": 0x33,
|
||||
"Period": 0x34,
|
||||
"Slash": 0x35,
|
||||
"ShiftRight": 0x36,
|
||||
"NumpadMultiply": 0x37,
|
||||
"AltLeft": 0x38,
|
||||
"Space": 0x39,
|
||||
"CapsLock": 0x3a,
|
||||
"F1": 0x3b,
|
||||
"F2": 0x3c,
|
||||
"F3": 0x3d,
|
||||
"F4": 0x3e,
|
||||
"F5": 0x3f,
|
||||
"F6": 0x40,
|
||||
"F7": 0x41,
|
||||
"F8": 0x42,
|
||||
"F9": 0x43,
|
||||
"F10": 0x44,
|
||||
"NumLock": 0x45,
|
||||
"ScrollLock": 0x46,
|
||||
"Numpad7": 0x47,
|
||||
"Numpad8": 0x48,
|
||||
"Numpad9": 0x49,
|
||||
"NumpadSubtract": 0x4a,
|
||||
"Numpad4": 0x4b,
|
||||
"Numpad5": 0x4c,
|
||||
"Numpad6": 0x4d,
|
||||
"NumpadAdd": 0x4e,
|
||||
"Numpad1": 0x4f,
|
||||
"Numpad2": 0x50,
|
||||
"Numpad3": 0x51,
|
||||
"Numpad0": 0x52,
|
||||
"NumpadDecimal": 0x53,
|
||||
"IntlBackslash": 0x56,
|
||||
"F11": 0x57,
|
||||
"F12": 0x58,
|
||||
|
||||
"NumpadEnter": 96,
|
||||
"ControlRight": 97,
|
||||
"NumpadDivide": 98,
|
||||
"AltRight": 100,
|
||||
"Home": 102,
|
||||
"ArrowUp": 103,
|
||||
"PageUp": 104,
|
||||
"ArrowLeft": 105,
|
||||
"ArrowRight": 106,
|
||||
"End": 107,
|
||||
"ArrowDown": 108,
|
||||
"PageDown": 109,
|
||||
"Insert": 110,
|
||||
"Delete": 111,
|
||||
"OSLeft": 125,
|
||||
"OSRight": 126,
|
||||
"ContextMenu": 127,
|
||||
};
|
||||
|
||||
GraphicDisplay.key_code_to_input_map = new Uint8Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x0E, 0x0F, 0, 0, 0, 0x1C, 0, 0,
|
||||
0x2A, 0x1D, 0x38, 0, 0x3A, 0, 0, 0, /* 0x10 */
|
||||
0, 0, 0, 0x01, 0, 0, 0, 0,
|
||||
0x39, 104, 109, 107, 102, 105, 103, 106, /* 0x20 */
|
||||
0x50, 0, 0, 0, 0, 0x52, 0x53, 0,
|
||||
0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* 0x30 */
|
||||
0x09, 0x0A, 0, 0x27, 0, 0x0D, 0, 0,
|
||||
0, 0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21, 0x22, /* 0x40 */
|
||||
0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,
|
||||
0x19, 0x10, 0x13, 0x1F, 0x14, 0x16, 0x2F, 0x11, /* 0x50 */
|
||||
0x2D, 0x15, 0x2C, 125, 126, 127, 0, 0,
|
||||
0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, /* 0x60 */
|
||||
0x48, 0x49, 0x37, 0x4e, 0, 0x4a, 0x53, 98,
|
||||
0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, /* 0x70 */
|
||||
0x43, 0x44, 0x57, 0x58, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x45, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
|
||||
0, 0, 0, 0, 0, 0x0C, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
|
||||
0, 0, 0x27, 0x0D, 0x33, 0x0C, 0x34, 0x35,
|
||||
0x29, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
|
||||
0, 0, 0, 0x1A, 0x2B, 0x1B, 0x28, 0,
|
||||
125, 100, 0, 0, 0, 0, 0, 0, /* 0xe0 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
]);
|
||||
|
||||
GraphicDisplay.prototype.keyHandler = function keyHandler(ev, isDown)
|
||||
{
|
||||
var block_list;
|
||||
if (ret < 0)
|
||||
return;
|
||||
/* Preload blocks so that the boot time does not depend on the
|
||||
* time to load the required disk data (optional) */
|
||||
block_list = [ 0, 7, 3, 643, 720, 256, 336, 644, 781, 387, 464, 475, 131, 589, 468, 472, 474, 776, 777, 778, 779, 465, 466, 473, 467, 469, 470, 512, 592, 471, 691, 697, 708, 792, 775, 769 ];
|
||||
pc.ide0.drives[0].bs.preload(block_list, start4);
|
||||
var code, input_key_code;
|
||||
|
||||
/* At least avoid exiting the navigator if Ctrl-Q or Ctrl-W are
|
||||
* pressed */
|
||||
if (ev.ctrlKey) {
|
||||
window.onbeforeunload = function() {
|
||||
window.onbeforeunload = null;
|
||||
return "CTRL-W or Ctrl-Q cannot be sent to the emulator.";
|
||||
};
|
||||
} else {
|
||||
window.onbeforeunload = null;
|
||||
}
|
||||
|
||||
if (typeof ev.code != "undefined") {
|
||||
code = ev.code;
|
||||
input_key_code = GraphicDisplay.code_to_input_map[code];
|
||||
if (typeof input_key_code != "undefined") {
|
||||
// console.log("code=" + code + " isDown=" + isDown + " input_key_code=" + input_key_code);
|
||||
this.key_pressed[input_key_code] = isDown;
|
||||
display_key_event(isDown, input_key_code);
|
||||
|
||||
if (ev.stopPropagation)
|
||||
ev.stopPropagation();
|
||||
if (ev.preventDefault)
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* fallback using keyCodes. Works only with an US keyboard */
|
||||
code = ev.keyCode;
|
||||
if (code < 256) {
|
||||
input_key_code = GraphicDisplay.key_code_to_input_map[code];
|
||||
// console.log("keyCode=" + code + " isDown=" + isDown + " input_key_code=" + input_key_code);
|
||||
if (input_key_code) {
|
||||
this.key_pressed[input_key_code] = isDown;
|
||||
display_key_event(isDown, input_key_code);
|
||||
|
||||
if (ev.stopPropagation)
|
||||
ev.stopPropagation();
|
||||
if (ev.preventDefault)
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function start4(ret)
|
||||
GraphicDisplay.prototype.keyDownHandler = function keyDownHandler(ev)
|
||||
{
|
||||
var cmdline_addr;
|
||||
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
/* set the Linux kernel command line */
|
||||
cmdline_addr = 0xf800;
|
||||
pc.cpu.write_string(cmdline_addr, "console=ttyS0 root=/dev/hda ro init=/sbin/init notsc=1 hdb=none");
|
||||
|
||||
pc.cpu.set_reg(8, init_state.start_addr); /* eip */
|
||||
pc.cpu.set_reg(0, init_state.params.mem_size); /* eax */
|
||||
pc.cpu.set_reg(3, 0); /* ebx = initrd_size (no longer used) */
|
||||
pc.cpu.set_reg(1, cmdline_addr); /* ecx */
|
||||
|
||||
boot_start_time = (+new Date());
|
||||
|
||||
pc.start();
|
||||
return this.keyHandler(ev, 1);
|
||||
}
|
||||
|
||||
term_start();
|
||||
GraphicDisplay.prototype.keyUpHandler = function keyUpHandler(ev)
|
||||
{
|
||||
return this.keyHandler(ev, 0);
|
||||
}
|
||||
|
||||
GraphicDisplay.prototype.blurHandler = function blurHandler(ev, isDown)
|
||||
{
|
||||
var i, n, key_pressed;
|
||||
/* allow unloading the page */
|
||||
window.onbeforeunload = null;
|
||||
/* release all keys */
|
||||
key_pressed = this.key_pressed;
|
||||
for(i = 0; i < key_pressed.length; i++) {
|
||||
if (key_pressed[i]) {
|
||||
display_key_event(0, i);
|
||||
key_pressed[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GraphicDisplay.prototype.mouseMoveHandler = function (ev)
|
||||
{
|
||||
var x, y, rect, buttons;
|
||||
rect = this.canvas_el.getBoundingClientRect();
|
||||
x = ev.clientX - rect.left;
|
||||
y = ev.clientY - rect.top;
|
||||
buttons = ev.buttons & 7;
|
||||
// console.log("mouse: x=" + x + " y=" + y + " buttons=" + buttons);
|
||||
display_mouse_event(x, y, buttons);
|
||||
if (ev.stopPropagation)
|
||||
ev.stopPropagation();
|
||||
if (ev.preventDefault)
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
GraphicDisplay.prototype.wheelHandler = function (ev)
|
||||
{
|
||||
if (ev.deltaY < 0) {
|
||||
display_wheel_event(1);
|
||||
} else if (ev.deltaY > 0) {
|
||||
display_wheel_event(-1);
|
||||
}
|
||||
if (ev.stopPropagation)
|
||||
ev.stopPropagation();
|
||||
if (ev.preventDefault)
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
/* disable contextual menu */
|
||||
GraphicDisplay.prototype.onContextMenuHandler = function (ev)
|
||||
{
|
||||
if (ev.stopPropagation)
|
||||
ev.stopPropagation();
|
||||
if (ev.preventDefault)
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Network support */
|
||||
|
||||
function Ethernet(url)
|
||||
{
|
||||
try {
|
||||
this.socket = new WebSocket(url);
|
||||
} catch(err) {
|
||||
this.socket = null;
|
||||
console.log("Could not open websocket url=" + url);
|
||||
return;
|
||||
}
|
||||
this.socket.binaryType = 'arraybuffer';
|
||||
this.socket.onmessage = this.messageHandler.bind(this);
|
||||
this.socket.onclose = this.closeHandler.bind(this);
|
||||
this.socket.onopen = this.openHandler.bind(this);
|
||||
this.socket.onerror = this.errorHandler.bind(this);
|
||||
}
|
||||
|
||||
Ethernet.prototype.openHandler = function(e)
|
||||
{
|
||||
net_set_carrier(1);
|
||||
}
|
||||
|
||||
Ethernet.prototype.closeHandler = function(e)
|
||||
{
|
||||
net_set_carrier(0);
|
||||
}
|
||||
|
||||
Ethernet.prototype.errorHandler = function(e)
|
||||
{
|
||||
console.log("Websocket error=" + e);
|
||||
}
|
||||
|
||||
Ethernet.prototype.messageHandler = function(e)
|
||||
{
|
||||
var str, buf_len, buf_addr, buf;
|
||||
if (e.data instanceof ArrayBuffer) {
|
||||
buf_len = e.data.byteLength;
|
||||
buf = new Uint8Array(e.data);
|
||||
buf_addr = _malloc(buf_len);
|
||||
HEAPU8.set(buf, buf_addr);
|
||||
net_write_packet(buf_addr, buf_len);
|
||||
_free(buf_addr);
|
||||
} else {
|
||||
str = e.data.toString();
|
||||
if (str.substring(0, 5) == "ping:") {
|
||||
try {
|
||||
this.socket.send('pong:' + str.substring(5));
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ethernet.prototype.recv_packet = function(buf)
|
||||
{
|
||||
if (this.socket) {
|
||||
try {
|
||||
this.socket.send(buf);
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function start_vm(user, pwd)
|
||||
{
|
||||
var url, mem_size, cpu, params, vm_url, cmdline, cols, rows, guest_url;
|
||||
var font_size, graphic_enable, width, height, net_url, alloc_size;
|
||||
var drive_url, vm_file;
|
||||
|
||||
function loadScript(src, f) {
|
||||
var head = document.getElementsByTagName("head")[0];
|
||||
var script = document.createElement("script");
|
||||
script.src = src;
|
||||
var done = false;
|
||||
script.onload = script.onreadystatechange = function() {
|
||||
// attach to both events for cross browser finish detection:
|
||||
if ( !done && (!this.readyState ||
|
||||
this.readyState == "loaded" || this.readyState == "complete") ) {
|
||||
done = true;
|
||||
if (f) {
|
||||
f();
|
||||
}
|
||||
script.onload = script.onreadystatechange = null;
|
||||
head.removeChild(script);
|
||||
}
|
||||
};
|
||||
head.appendChild(script);
|
||||
}
|
||||
|
||||
function start()
|
||||
{
|
||||
/* C functions called from javascript */
|
||||
console_write1 = Module.cwrap('console_queue_char', null, ['number']);
|
||||
console_resize_event = Module.cwrap('console_resize_event', null, []);
|
||||
fs_import_file = Module.cwrap('fs_import_file', null, ['string', 'number', 'number']);
|
||||
display_key_event = Module.cwrap('display_key_event', null, ['number', 'number']);
|
||||
display_mouse_event = Module.cwrap('display_mouse_event', null, ['number', 'number', 'number']);
|
||||
display_wheel_event = Module.cwrap('display_wheel_event', null, ['number']);
|
||||
net_write_packet = Module.cwrap('net_write_packet', null, ['number', 'number']);
|
||||
net_set_carrier = Module.cwrap('net_set_carrier', null, ['number']);
|
||||
|
||||
net_state = null;
|
||||
if (net_url != "") {
|
||||
net_state = new Ethernet(net_url);
|
||||
}
|
||||
|
||||
Module.ccall("vm_start", null, ["string", "number", "string", "string", "number", "number", "number", "string"], [url, mem_size, cmdline, pwd, width, height, (net_state != null) | 0, drive_url]);
|
||||
pwd = null;
|
||||
}
|
||||
|
||||
function term_wrap_onclick_handler()
|
||||
{
|
||||
var term_wrap_el, w, h, term_bar_el, bar_h;
|
||||
term_wrap_el = document.getElementById("term_wrap");
|
||||
term_bar_el = document.getElementById("term_bar");
|
||||
w = term_wrap_el.clientWidth;
|
||||
h = term_wrap_el.clientHeight;
|
||||
bar_h = term_bar_el.clientHeight;
|
||||
if (term.resizePixel(w, h - bar_h)) {
|
||||
console_resize_event();
|
||||
}
|
||||
}
|
||||
|
||||
/* read the parameters */
|
||||
|
||||
params = get_params();
|
||||
cpu = params["cpu"] || "x86";
|
||||
url = params["url"];
|
||||
url = get_absolute_url(url);
|
||||
mem_size = (params["mem"] | 0) || 128; /* in mb */
|
||||
cmdline = params["cmdline"] || "";
|
||||
cols = (params["cols"] | 0) || 80;
|
||||
rows = (params["rows"] | 0) || 30;
|
||||
font_size = (params["font_size"] | 0) || 15;
|
||||
guest_url = params["guest_url"] || "";
|
||||
width = (params["w"] | 0) || 1024;
|
||||
height = (params["h"] | 0) || 640;
|
||||
graphic_enable = params["graphic"] | 0;
|
||||
net_url = params["net_url"]; /* empty string means no network */
|
||||
if (typeof net_url == "undefined")
|
||||
net_url = "wss://relay.widgetry.org/";
|
||||
drive_url = params["drive_url"] || "";
|
||||
|
||||
if (user) {
|
||||
cmdline += " LOGIN_USER=" + user;
|
||||
} else if (guest_url) {
|
||||
cmdline += " GUEST_URL=" + guest_url;
|
||||
}
|
||||
|
||||
if (graphic_enable) {
|
||||
graphic_display = new GraphicDisplay(document.getElementById("term_container"), width, height);
|
||||
} else {
|
||||
var term_wrap_el;
|
||||
width = 0;
|
||||
height = 0;
|
||||
|
||||
/* start the terminal */
|
||||
term = new Term({ cols: cols, rows: rows, scrollback: 10000, fontSize: font_size });
|
||||
term.setKeyHandler(term_handler);
|
||||
term.open(document.getElementById("term_container"),
|
||||
document.getElementById("term_paste"));
|
||||
|
||||
term_wrap_el = document.getElementById("term_wrap")
|
||||
term_wrap_el.style.width = term.term_el.style.width;
|
||||
term_wrap_el.onclick = term_wrap_onclick_handler;
|
||||
|
||||
term.write("Loading...\r\n");
|
||||
}
|
||||
|
||||
// console.log("cpu=" + cpu + " url=" + url + " mem=" + mem_size);
|
||||
|
||||
switch(cpu) {
|
||||
case "x86":
|
||||
vm_file = "x86emu";
|
||||
break;
|
||||
case "riscv64":
|
||||
case "riscv":
|
||||
vm_file = "riscvemu64";
|
||||
break;
|
||||
case "riscv32":
|
||||
vm_file = "riscvemu32";
|
||||
break;
|
||||
default:
|
||||
term.writeln("Unknown cpu=" + cpu);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof WebAssembly === "object") {
|
||||
/* wasm support : the memory grows automatically */
|
||||
vm_url = vm_file + "-wasm.js";
|
||||
} else {
|
||||
/* set the total memory */
|
||||
alloc_size = mem_size;
|
||||
if (cpu == "x86")
|
||||
alloc_size += 16;
|
||||
if (graphic_enable) {
|
||||
/* frame buffer memory */
|
||||
alloc_size += (width * height * 4 + 1048576 - 1) >> 20;
|
||||
}
|
||||
alloc_size += 32; /* extra space (XXX: reduce it ?) */
|
||||
alloc_size = (alloc_size + 15) & -16; /* align to 16 MB */
|
||||
Module.TOTAL_MEMORY = alloc_size << 20;
|
||||
vm_url = vm_file + ".js";
|
||||
}
|
||||
Module.preRun = start;
|
||||
|
||||
loadScript(vm_url, null);
|
||||
}
|
||||
|
||||
function on_login()
|
||||
{
|
||||
var login_wrap_el = document.getElementById("wrap");
|
||||
var term_wrap_el = document.getElementById("term_wrap");
|
||||
var form = document.getElementById("form");
|
||||
var status = document.getElementById("status");
|
||||
var user = form.user.value;
|
||||
var pwd = form.password.value;
|
||||
|
||||
if (user.length <= 1) {
|
||||
status.innerHTML = "User name must be provided";
|
||||
return false;
|
||||
}
|
||||
|
||||
login_wrap_el.style.display = "none";
|
||||
term_wrap_el.style.display = "block";
|
||||
form.password.value = "";
|
||||
form.user.value = "";
|
||||
|
||||
start_vm(user, pwd);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
(function() {
|
||||
var login, params;
|
||||
|
||||
params = get_params();
|
||||
login = params["login"] || 0;
|
||||
if (login) {
|
||||
var login_wrap_el = document.getElementById("wrap");
|
||||
login_wrap_el.style.display = "block";
|
||||
} else {
|
||||
var term_wrap_el = document.getElementById("term_wrap");
|
||||
term_wrap_el.style.display = "block";
|
||||
start_vm(null, null);
|
||||
}
|
||||
})();
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue