New publicly usable interface called V86Starter, refactor browser/main.js using it
This commit is contained in:
parent
ac7ca3cb4c
commit
1032ef3ef2
18
Makefile
18
Makefile
|
@ -19,7 +19,8 @@ build/cpu.js: src/*.macro.js
|
|||
|
||||
# Used for nodejs builds and in order to profile code.
|
||||
# `debug` gives identifiers a readable name, make sure it doesn't have any side effects.
|
||||
CLOSURE_READABLE=--formatting PRETTY_PRINT --debug
|
||||
#CLOSURE_READABLE=--formatting PRETTY_PRINT --debug
|
||||
CLOSURE_READABLE=--formatting PRETTY_PRINT
|
||||
|
||||
CLOSURE_SOURCE_MAP=\
|
||||
--source_map_format V3\
|
||||
|
@ -39,9 +40,9 @@ CORE_FILES=const.js io.js main.js lib.js fpu.js ide.js pci.js floppy.js memory.j
|
|||
dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js hpet.js acpi.js\
|
||||
state.js ne2k.js virtio.js bus.js log.js
|
||||
LIB_FILES=../lib/9p.js ../lib/filesystem.js ../lib/jor1k.js ../lib/marshall.js ../lib/utf8.js
|
||||
BROWSER_FILES=browser/main.js browser/screen.js\
|
||||
BROWSER_FILES=browser/screen.js\
|
||||
browser/keyboard.js browser/mouse.js browser/serial.js\
|
||||
browser/network.js browser/lib.js
|
||||
browser/network.js browser/lib.js browser/starter.js
|
||||
|
||||
build/v86_all.js: src/*.js src/browser/*.js build/cpu.js lib/*.js
|
||||
-ls -lh build/v86_all.js
|
||||
|
@ -57,21 +58,26 @@ build/v86_all.js: src/*.js src/browser/*.js build/cpu.js lib/*.js
|
|||
--js $(CORE_FILES)\
|
||||
--js $(LIB_FILES)\
|
||||
--js $(BROWSER_FILES)\
|
||||
--js ../build/cpu.js
|
||||
--js ../build/cpu.js\
|
||||
--js browser/main.js
|
||||
|
||||
echo "//# sourceMappingURL=v86_all.js.map" >> build/v86_all.js
|
||||
ls -lh build/v86_all.js
|
||||
|
||||
|
||||
build/libv86.js: src/*.js build/cpu.js lib/*.js
|
||||
build/libv86.js: src/*.js build/cpu.js lib/*.js src/browser/*.js
|
||||
cd src &&\
|
||||
java -jar $(CLOSURE) \
|
||||
--js_output_file "../build/libv86.js"\
|
||||
--define=DEBUG=false\
|
||||
--externs adapter-externs.js\
|
||||
--define=IN_NODE=false\
|
||||
--define=IN_BROWSER=true\
|
||||
--define=IN_WORKER=false\
|
||||
$(CLOSURE_FLAGS)\
|
||||
$(CLOSURE_READABLE)\
|
||||
--output_wrapper ';(function(){%output%})();'\
|
||||
--js $(CORE_FILES)\
|
||||
--js $(BROWSER_FILES)\
|
||||
--js $(LIB_FILES)\
|
||||
--js ../build/cpu.js
|
||||
|
||||
|
|
|
@ -1,96 +1,25 @@
|
|||
<!doctype html>
|
||||
<title>Basic Emulator</title><!-- not BASIC! -->
|
||||
|
||||
|
||||
<!-- defines ScreenAdapter -->
|
||||
<script src="../../src/browser/screen.js"></script>
|
||||
|
||||
<!-- defines KeyboardAdapter -->
|
||||
<script src="../../src/browser/keyboard.js"></script>
|
||||
|
||||
<!-- defines v86, SyncBuffer, Bus -->
|
||||
<script src="../../build/libv86.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
// Load a file using XHR as an ArrayBuffer.
|
||||
// If you want to use this, add some error handling
|
||||
function load_file(filename, done)
|
||||
{
|
||||
var http = new XMLHttpRequest();
|
||||
|
||||
http.open("get", filename, true);
|
||||
http.responseType = "arraybuffer";
|
||||
|
||||
http.onload = function(e) {
|
||||
if(http.readyState === 4 && http.response) {
|
||||
done(http.response);
|
||||
}
|
||||
};
|
||||
http.send(null);
|
||||
}
|
||||
|
||||
window.onload = function()
|
||||
{
|
||||
// For a minimal boot, we need at least 2 images: A bios and a disk image
|
||||
// (CD, HD or floppy). For non-serial output, a vgabios has to be specified
|
||||
var images = {};
|
||||
|
||||
load_file("../../bios/seabios.bin", function(buffer) {
|
||||
images.seabios = buffer;
|
||||
cont(images);
|
||||
var emulator = new V86Starter({
|
||||
memory_size: 32 * 1024 * 1024,
|
||||
vga_memory_size: 2 * 1024 * 1024,
|
||||
screen_container: document.getElementById("screen_container"),
|
||||
bios: {
|
||||
url: "../../bios/seabios.bin",
|
||||
},
|
||||
vga_bios: {
|
||||
url: "../../bios/vgabios.bin",
|
||||
},
|
||||
cdrom: {
|
||||
url: "../../images/linux.iso",
|
||||
},
|
||||
autostart: true,
|
||||
});
|
||||
|
||||
load_file("../../bios/vgabios.bin", function(buffer) {
|
||||
images.vga_bios = buffer;
|
||||
cont(images);
|
||||
});
|
||||
|
||||
load_file("../../images/linux.iso", function(buffer) {
|
||||
images.cdrom = buffer;
|
||||
cont(images);
|
||||
});
|
||||
};
|
||||
|
||||
function cont(images)
|
||||
{
|
||||
if(!images.seabios || !images.vga_bios || !images.cdrom) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bus = Bus.create();
|
||||
|
||||
var container = document.getElementById("screen_container");
|
||||
var cpu = new v86(bus[0]);
|
||||
|
||||
// Adapters implement the communication from or to the emulator. These
|
||||
// default adapters (defined in browser/*.js) implement what you see
|
||||
// on copy.sh/v86. You could change them to programatically control the emulator
|
||||
var keyboard = new KeyboardAdapter(bus[1]);
|
||||
var screen = new ScreenAdapter(container, bus[1]);
|
||||
|
||||
cpu.init({
|
||||
// load_devices has to be set to true, otherwise no OS can run
|
||||
load_devices: true,
|
||||
|
||||
// The CD image. All disk images have to be wrapped in SyncBuffer or an
|
||||
// object, that exports the same interface. A few examples are available
|
||||
// in browser/lib.js
|
||||
cdrom: new SyncBuffer(images.cdrom),
|
||||
|
||||
//hda: images.hd, // a hard disk image
|
||||
//fda: images.floppy, // a floppy disk image
|
||||
|
||||
// The bioses. If you don't need the vgabios, just leave it out.
|
||||
// Only pass ArrayBuffers here
|
||||
bios: images.seabios,
|
||||
vga_bios: images.vga_bios,
|
||||
|
||||
vga_memory_size: 2 * 1024 * 1024, // default 8M
|
||||
memory_size: 32 * 1024 * 1024, // default 64M
|
||||
});
|
||||
|
||||
cpu.run();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
var CORE_FILES = "const.js io.js main.js lib.js ide.js fpu.js pci.js floppy.js " +
|
||||
"memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js acpi.js hpet.js " +
|
||||
"ne2k.js state.js virtio.js bus.js log.js";
|
||||
var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js serial.js lib.js network.js";
|
||||
var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js serial.js lib.js network.js starter.js";
|
||||
var LIB_FILES = "esprima.js walk.js";
|
||||
|
||||
// jor1k stuff
|
||||
|
|
|
@ -2,38 +2,6 @@
|
|||
|
||||
(function()
|
||||
{
|
||||
// based on https://github.com/Raynos/after
|
||||
// All the flow control you'll ever need
|
||||
function after(count, callback)
|
||||
{
|
||||
proxy.count = count;
|
||||
var result = {};
|
||||
|
||||
return (count === 0) ? callback() : proxy;
|
||||
|
||||
function proxy(data) {
|
||||
if(proxy.count <= 0)
|
||||
{
|
||||
throw new Error("after called too many times");
|
||||
}
|
||||
proxy.count--;
|
||||
|
||||
if(data)
|
||||
{
|
||||
var keys = Object.keys(data);
|
||||
for(var i = 0; i < keys.length; i++)
|
||||
{
|
||||
result[keys[i]] = data[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
if(proxy.count === 0)
|
||||
{
|
||||
callback(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dump_file(ab, name)
|
||||
{
|
||||
var blob = new Blob([ab]);
|
||||
|
@ -95,18 +63,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
function lock_mouse(elem)
|
||||
{
|
||||
var fn = elem["requestPointerLock"] ||
|
||||
elem["mozRequestPointerLock"] ||
|
||||
elem["webkitRequestPointerLock"];
|
||||
|
||||
if(fn)
|
||||
{
|
||||
fn.call(elem);
|
||||
}
|
||||
}
|
||||
|
||||
function chr_repeat(chr, count)
|
||||
{
|
||||
var result = "";
|
||||
|
@ -119,28 +75,37 @@
|
|||
return result;
|
||||
}
|
||||
|
||||
function show_progress(info, e)
|
||||
var progress_ticks = 0;
|
||||
|
||||
function show_progress(message, e)
|
||||
{
|
||||
var el = $("loading");
|
||||
el.style.display = "block";
|
||||
|
||||
if(e.lengthComputable || (info.total && typeof e.loaded === "number"))
|
||||
{
|
||||
var per100 = e.loaded / (e.total || info.total) * 100 | 0;
|
||||
var line = message + " ";
|
||||
|
||||
if(typeof e.file_index === "number" && e.file_count)
|
||||
{
|
||||
line += "[" + (e.file_index + 1) + "/" + e.file_count + "] ";
|
||||
}
|
||||
|
||||
if(e.total && typeof e.loaded === "number")
|
||||
{
|
||||
var per100 = Math.floor(e.loaded / e.total * 100);
|
||||
per100 = Math.min(100, Math.max(0, per100));
|
||||
|
||||
el.textContent = info.msg + " " + per100 + "% [" +
|
||||
chr_repeat("#", per100 >> 1) +
|
||||
chr_repeat(" ", 50 - (per100 >> 1)) + "]";
|
||||
var per50 = Math.floor(per100 / 2);
|
||||
|
||||
line += per100 + "% [";
|
||||
line += chr_repeat("#", per50);
|
||||
line += chr_repeat(" ", 50 - per50) + "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!info.ticks)
|
||||
info.ticks = 0;
|
||||
|
||||
el.textContent = info.msg + " " + chr_repeat(".", info.ticks++ % 50);
|
||||
line += chr_repeat(".", progress_ticks++ % 50);
|
||||
}
|
||||
|
||||
el.textContent = line;
|
||||
}
|
||||
|
||||
function $(id)
|
||||
|
@ -163,137 +128,47 @@
|
|||
return;
|
||||
}
|
||||
|
||||
var settings = {
|
||||
load_devices: true
|
||||
};
|
||||
|
||||
function load_local(file, type, cb)
|
||||
{
|
||||
set_title(file.name);
|
||||
|
||||
// SyncFileBuffer:
|
||||
// - loads the whole disk image into memory, impossible for large files (more than 1GB)
|
||||
// - can later serve get/set operations fast and synchronously
|
||||
// - takes some time for first load, neglectable for small files (up to 100Mb)
|
||||
//
|
||||
// AsyncFileBuffer:
|
||||
// - loads slices of the file asynchronously as requested
|
||||
// - slower get/set
|
||||
|
||||
// Heuristics: If file is smaller than 64M, use SyncFileBuffer
|
||||
if(file.size < 64 * 1024 * 1024)
|
||||
{
|
||||
var loader = new v86util.SyncFileBuffer(file);
|
||||
loader.onprogress = show_progress.bind(this, { msg: "Loading disk image into memory" });
|
||||
}
|
||||
else
|
||||
{
|
||||
var loader = new v86util.AsyncFileBuffer(file);
|
||||
}
|
||||
|
||||
loader.onload = function()
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case "floppy":
|
||||
settings.fda = loader;
|
||||
break;
|
||||
case "hd":
|
||||
settings.hda = loader;
|
||||
break;
|
||||
case "cdrom":
|
||||
settings.cdrom = loader;
|
||||
break;
|
||||
}
|
||||
cb();
|
||||
}
|
||||
|
||||
loader.load();
|
||||
}
|
||||
|
||||
$("toggle_mouse").onclick = function()
|
||||
{
|
||||
var mouse_adapter = settings.mouse_adapter;
|
||||
|
||||
if(mouse_adapter)
|
||||
{
|
||||
var state = mouse_adapter.emu_enabled = !mouse_adapter.emu_enabled;
|
||||
|
||||
$("toggle_mouse").value = (state ? "Dis" : "En") + "able mouse";
|
||||
}
|
||||
};
|
||||
|
||||
$("lock_mouse").onclick = function()
|
||||
{
|
||||
var mouse_adapter = settings.mouse_adapter;
|
||||
|
||||
if(mouse_adapter && !mouse_adapter.emu_enabled)
|
||||
{
|
||||
$("toggle_mouse").onclick();
|
||||
}
|
||||
|
||||
lock_mouse(document.body);
|
||||
$("lock_mouse").blur();
|
||||
};
|
||||
|
||||
var biosfile = DEBUG ? "seabios-debug.bin" : "seabios.bin";
|
||||
var vgabiosfile = DEBUG ? "vgabios-0.7a.debug.bin" : "bochs-vgabios-0.7a.bin";
|
||||
|
||||
v86util.load_file("bios/" + biosfile, function(img)
|
||||
{
|
||||
settings.bios = img;
|
||||
start_emulation();
|
||||
});
|
||||
|
||||
v86util.load_file("bios/" + vgabiosfile, function(img)
|
||||
{
|
||||
settings.vga_bios = img;
|
||||
start_emulation();
|
||||
});
|
||||
var settings = {};
|
||||
|
||||
$("start_emulation").onclick = function()
|
||||
{
|
||||
$("boot_options").style.display = "none";
|
||||
set_profile("custom");
|
||||
|
||||
var images = [];
|
||||
var last_file;
|
||||
|
||||
if($("floppy_image").files.length)
|
||||
var floppy_file = $("floppy_image").files[0];
|
||||
if(floppy_file)
|
||||
{
|
||||
images.push({
|
||||
file: $("floppy_image").files[0],
|
||||
type: "floppy",
|
||||
});
|
||||
last_file = floppy_file;
|
||||
settings.fda = { buffer: floppy_file };
|
||||
}
|
||||
|
||||
if($("cd_image").files.length)
|
||||
var cd_file = $("cd_image").files[0];
|
||||
if(cd_file)
|
||||
{
|
||||
images.push({
|
||||
file: $("cd_image").files[0],
|
||||
type: "cdrom",
|
||||
});
|
||||
last_file = cd_file;
|
||||
settings.cdrom = { buffer: cd_file };
|
||||
}
|
||||
|
||||
if($("hd_image").files.length)
|
||||
var hd_file = $("hd_image").files[0];
|
||||
if(hd_file)
|
||||
{
|
||||
images.push({
|
||||
file: $("hd_image").files[0],
|
||||
type: "hd",
|
||||
});
|
||||
last_file = hd_file;
|
||||
settings.hda = { buffer: hd_file };
|
||||
}
|
||||
|
||||
var cont = after(images.length, function(result)
|
||||
if(last_file)
|
||||
{
|
||||
set_profile("custom");
|
||||
set_title(last_file.name);
|
||||
}
|
||||
|
||||
start_emulation({
|
||||
settings: settings,
|
||||
done: function(e) { e.run(); },
|
||||
});
|
||||
});
|
||||
|
||||
images.forEach(function(image)
|
||||
{
|
||||
load_local(image.file, image.type, cont);
|
||||
start_emulation({
|
||||
settings: settings,
|
||||
done: function(emulator) {
|
||||
emulator.run();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -303,21 +178,27 @@
|
|||
}
|
||||
|
||||
var oses = [
|
||||
//{
|
||||
// id: "archlinux",
|
||||
// state: "http://localhost/v86-images/v86state.bin",
|
||||
// //size: 137 * 1024 * 1024,
|
||||
// size: 75550474,
|
||||
// name: "Arch Linux",
|
||||
// memory_size: 64 * 1024 * 1024,
|
||||
// vga_memory_size: 8 * 1024 * 1024,
|
||||
// async_hda: "http://localhost/v86-images/arch3.img",
|
||||
// async_hda_size: 8 * 1024 * 1024 * 1024,
|
||||
// filesystem: {
|
||||
// basefs: "http://localhost/v86-images/fs.json",
|
||||
// baseurl: "http://localhost/v86-images/arch/",
|
||||
// },
|
||||
//},
|
||||
{
|
||||
id: "archlinux",
|
||||
state: "http://localhost/v86-images/v86state.bin",
|
||||
//state: "http://104.131.53.7:8086/v86state.bin",
|
||||
//size: 137 * 1024 * 1024,
|
||||
size: 75550474,
|
||||
name: "Arch Linux",
|
||||
memory_size: 64 * 1024 * 1024,
|
||||
vga_memory_size: 8 * 1024 * 1024,
|
||||
async_hda: "http://localhost/v86-images/arch3.img",
|
||||
//async_hda: "https://dl.dropboxusercontent.com/u/61029208/arch3.img",
|
||||
//async_hda: "http://104.131.53.7:8086/arch3.img",
|
||||
async_hda_size: 8 * 1024 * 1024 * 1024,
|
||||
|
||||
filesystem: {
|
||||
basefs: "http://localhost/v86-images/fs.json",
|
||||
baseurl: "http://localhost/v86-images/arch/",
|
||||
//basefs: "http://104.131.53.7:8086/fs.json",
|
||||
//baseurl: "http://104.131.53.7:8086/arch/",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "freedos",
|
||||
fda: "images/freedos722.img",
|
||||
|
@ -387,88 +268,62 @@
|
|||
|
||||
function start_profile(infos)
|
||||
{
|
||||
var message = { msg: "Downloading image", total: infos.size };
|
||||
var image = infos.state || infos.fda || infos.cdrom;
|
||||
$("boot_options").style.display = "none";
|
||||
set_title(infos.name);
|
||||
|
||||
var start = after(1, function(result)
|
||||
settings.filesystem = infos.filesystem;
|
||||
|
||||
if(infos.state)
|
||||
{
|
||||
loaded(infos, settings, result.buffer);
|
||||
});
|
||||
|
||||
v86util.load_file(
|
||||
image,
|
||||
function(buffer)
|
||||
{
|
||||
start({ buffer: buffer });
|
||||
},
|
||||
show_progress.bind(this, message)
|
||||
);
|
||||
|
||||
if(infos.filesystem)
|
||||
{
|
||||
settings.fs9p = new FS(infos.filesystem.baseurl);
|
||||
|
||||
if(infos.filesystem.basefs)
|
||||
{
|
||||
start.count++;
|
||||
settings.fs9p.OnLoaded = start;
|
||||
|
||||
settings.fs9p.LoadFilesystem({
|
||||
lazyloadimages: [],
|
||||
earlyload: [],
|
||||
basefsURL: infos.filesystem.basefs,
|
||||
});
|
||||
}
|
||||
$("reset").style.display = "none";
|
||||
settings.initial_state = {
|
||||
url: infos.state,
|
||||
};
|
||||
}
|
||||
|
||||
set_title(infos.name);
|
||||
$("boot_options").style.display = "none";
|
||||
}
|
||||
settings.fda = {
|
||||
url: infos.fda,
|
||||
};
|
||||
settings.cdrom = {
|
||||
url: infos.cdrom,
|
||||
};
|
||||
|
||||
if(infos.hda)
|
||||
{
|
||||
settings.hda = {
|
||||
url: infos.hda,
|
||||
};
|
||||
}
|
||||
else if(infos.async_hda)
|
||||
{
|
||||
settings.hda = {
|
||||
url: infos.async_hda,
|
||||
async: true,
|
||||
size: infos.async_hda_size,
|
||||
};
|
||||
}
|
||||
|
||||
function loaded(infos, settings, buffer)
|
||||
{
|
||||
settings.memory_size = infos.memory_size;
|
||||
settings.vga_memory_size = infos.vga_memory_size;
|
||||
|
||||
if(infos.async_hda)
|
||||
{
|
||||
settings.hda = new v86util.AsyncXHRBuffer(
|
||||
infos.async_hda,
|
||||
512,
|
||||
infos.async_hda_size
|
||||
);
|
||||
}
|
||||
|
||||
if(infos.fda)
|
||||
{
|
||||
settings.fda = new SyncBuffer(buffer);
|
||||
}
|
||||
else if(infos.cdrom)
|
||||
{
|
||||
settings.cdrom = new SyncBuffer(buffer);
|
||||
}
|
||||
//if(infos.async_hda)
|
||||
//{
|
||||
// settings.hda = new v86util.AsyncXHRBuffer(
|
||||
// infos.async_hda,
|
||||
// 512,
|
||||
// infos.async_hda_size
|
||||
// );
|
||||
//}
|
||||
|
||||
start_emulation({
|
||||
settings: settings,
|
||||
done: function(emulator)
|
||||
{
|
||||
if(infos.state)
|
||||
{
|
||||
$("reset").style.display = "none";
|
||||
emulator.restore_state(buffer);
|
||||
}
|
||||
|
||||
//emulator.send("cpu-run");
|
||||
emulator.run();
|
||||
|
||||
if(query_args["c"])
|
||||
{
|
||||
var cmd = query_args["c"] + "\n";
|
||||
|
||||
for(var i = 0; i < cmd.length; i++)
|
||||
{
|
||||
settings.serial_adapter.send_char(cmd.charCodeAt(i));
|
||||
}
|
||||
emulator.serial0_send(query_args["c"] + "\n");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -479,12 +334,10 @@
|
|||
{
|
||||
// called on window.onload, in debug mode
|
||||
|
||||
//settings.fs9p = new FS("http://localhost/v86-images/arch/");
|
||||
//settings.fs9p.LoadFilesystem({
|
||||
// lazyloadimages: [],
|
||||
// earlyload: [],
|
||||
// basefsURL: "http://localhost/v86-images/fs.json",
|
||||
//});
|
||||
settings.filesystem = {
|
||||
baseurl: "http://localhost/v86-images/arch/",
|
||||
basefs: "http://localhost/v86-images/fs.json",
|
||||
};
|
||||
|
||||
$("restore_state").onchange = function()
|
||||
{
|
||||
|
@ -556,78 +409,87 @@
|
|||
onload();
|
||||
}
|
||||
|
||||
var start_emulation = after(3, function(result)
|
||||
function start_emulation(result)
|
||||
{
|
||||
/** @const */
|
||||
var MB = 1024 * 1024;
|
||||
|
||||
var settings = result.settings;
|
||||
dbg_assert(settings.bios && settings.vga_bios);
|
||||
var memory_size = settings.memory_size;
|
||||
|
||||
//var worker = new Worker("src/browser/worker.js");
|
||||
//var adapter_bus = WorkerBus.init(worker);
|
||||
var bus = Bus.create();
|
||||
var adapter_bus = bus[0];
|
||||
var device_bus = bus[1];
|
||||
|
||||
var emulator = new v86(device_bus);
|
||||
|
||||
if(DEBUG)
|
||||
if(!memory_size)
|
||||
{
|
||||
debug_start(emulator);
|
||||
}
|
||||
memory_size = parseInt($("memory_size").value, 10) * MB;
|
||||
|
||||
// avoid warnings
|
||||
settings.fdb = undefined;
|
||||
|
||||
settings.screen_adapter = new ScreenAdapter($("screen_container"), adapter_bus);;
|
||||
settings.keyboard_adapter = new KeyboardAdapter(adapter_bus);
|
||||
settings.mouse_adapter = new MouseAdapter(adapter_bus);
|
||||
|
||||
settings.boot_order = parseInt($("boot_order").value, 16);
|
||||
settings.serial_adapter = new SerialAdapter($("serial"), adapter_bus);
|
||||
//settings.serial_adapter = new ModemAdapter();
|
||||
//settings.network_adapter = new NetworkAdapter("ws://localhost:8001/", adapter_bus);
|
||||
//settings.network_adapter = new NetworkAdapter("ws://relay.widgetry.org/", adapter_bus);
|
||||
|
||||
if(!settings.memory_size)
|
||||
{
|
||||
var memory_size = parseInt($("memory_size").value, 10) * 1024 * 1024;
|
||||
if(memory_size >= 16 * 1024 * 1024 && memory_size < 2048 * 1024 * 1024)
|
||||
{
|
||||
settings.memory_size = memory_size;
|
||||
}
|
||||
else
|
||||
if(memory_size < 16 * MB || memory_size >= 2048 * MB)
|
||||
{
|
||||
alert("Invalid memory size - ignored.");
|
||||
settings.memory_size = 32 * 1024 * 1024;
|
||||
memory_size = 32 * MB;
|
||||
}
|
||||
}
|
||||
|
||||
var vga_memory_size = settings.vga_memory_size;
|
||||
|
||||
if(!settings.vga_memory_size)
|
||||
if(!vga_memory_size)
|
||||
{
|
||||
var video_memory_size = parseInt($("video_memory_size").value, 10) * 1024 * 1024;
|
||||
if(video_memory_size > 64 * 1024 && video_memory_size < 2048 * 1024 * 1024)
|
||||
{
|
||||
settings.vga_memory_size = video_memory_size;
|
||||
}
|
||||
else
|
||||
vga_memory_size = parseInt($("video_memory_size").value, 10) * MB;
|
||||
|
||||
if(vga_memory_size <= 64 * 1024 || vga_memory_size >= 2048 * MB)
|
||||
{
|
||||
alert("Invalid video memory size - ignored.");
|
||||
settings.vga_memory_size = 8 * 1024 * 1024;
|
||||
vga_memory_size = 8 * MB;
|
||||
}
|
||||
}
|
||||
|
||||
init_ui(settings, emulator);
|
||||
var BIOSPATH = "bios/";
|
||||
var biosfile = DEBUG ? "seabios-debug.bin" : "seabios.bin";
|
||||
var vgabiosfile = DEBUG ? "vgabios-0.7a.debug.bin" : "bochs-vgabios-0.7a.bin";
|
||||
|
||||
emulator.init(settings);
|
||||
|
||||
//settings.fs9p = undefined;
|
||||
//settings.fda = undefined;
|
||||
//adapter_bus.send("cpu-init", settings);
|
||||
var emulator = new V86Starter({
|
||||
memory_size: memory_size,
|
||||
vga_memory_size: vga_memory_size,
|
||||
|
||||
screen_container: $("screen_container"),
|
||||
serial_container: $("serial"),
|
||||
|
||||
boot_order: parseInt($("boot_order").value, 16) || 0,
|
||||
|
||||
network_relay_url: "ws://relay.widgetry.org/",
|
||||
//network_relay_url: "ws://localhost:8001/",
|
||||
|
||||
bios: {
|
||||
url: BIOSPATH + biosfile,
|
||||
},
|
||||
vga_bios: {
|
||||
url: BIOSPATH + vgabiosfile,
|
||||
},
|
||||
|
||||
fda: settings.fda,
|
||||
hda: settings.hda,
|
||||
cdrom: settings.cdrom,
|
||||
|
||||
initial_state: settings.initial_state,
|
||||
filesystem: settings.filesystem,
|
||||
});
|
||||
|
||||
emulator.add_listener("emulator-ready", function()
|
||||
{
|
||||
if(DEBUG)
|
||||
{
|
||||
debug_start(emulator);
|
||||
}
|
||||
|
||||
init_ui({}, emulator);
|
||||
|
||||
//setTimeout(function()
|
||||
//{
|
||||
result.done(emulator);
|
||||
//}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
emulator.add_listener("download-progress", function(e)
|
||||
{
|
||||
show_progress("Downloading images", e);
|
||||
});
|
||||
};
|
||||
|
||||
function init_ui(settings, emulator)
|
||||
{
|
||||
|
@ -637,16 +499,15 @@
|
|||
$("runtime_infos").style.display = "block";
|
||||
document.getElementsByClassName("phone_keyboard")[0].style.display = "block";
|
||||
|
||||
if($("news"))
|
||||
var news_element = $("news");
|
||||
if(news_element)
|
||||
{
|
||||
$("news").style.display = "none";
|
||||
news_element.style.display = "none";
|
||||
}
|
||||
|
||||
var running = true;
|
||||
|
||||
$("run").onclick = function()
|
||||
{
|
||||
if(running)
|
||||
if(emulator.is_running())
|
||||
{
|
||||
running_time += Date.now() - last_tick;
|
||||
$("run").value = "Run";
|
||||
|
@ -659,7 +520,6 @@
|
|||
last_tick = Date.now();
|
||||
}
|
||||
|
||||
running = !running;
|
||||
$("run").blur();
|
||||
};
|
||||
|
||||
|
@ -668,6 +528,29 @@
|
|||
location.href = location.pathname;
|
||||
};
|
||||
|
||||
$("lock_mouse").onclick = function()
|
||||
{
|
||||
if(!mouse_is_enabled)
|
||||
{
|
||||
$("toggle_mouse").onclick();
|
||||
}
|
||||
|
||||
emulator.lock_mouse();
|
||||
$("lock_mouse").blur();
|
||||
};
|
||||
|
||||
var mouse_is_enabled = true;
|
||||
|
||||
$("toggle_mouse").onclick = function()
|
||||
{
|
||||
mouse_is_enabled = !mouse_is_enabled;
|
||||
|
||||
emulator.mouse_set_status(mouse_is_enabled);
|
||||
$("toggle_mouse").value = (mouse_is_enabled ? "Dis" : "En") + "able mouse";
|
||||
$("toggle_mouse").blur();
|
||||
};
|
||||
|
||||
|
||||
var time = $("running_time"),
|
||||
ips = $("speed"),
|
||||
avg_ips = $("avg_speed"),
|
||||
|
@ -678,91 +561,83 @@
|
|||
|
||||
function update_info()
|
||||
{
|
||||
if(!running)
|
||||
if(!emulator.is_running())
|
||||
{
|
||||
setTimeout(update_info, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
var now = Date.now(),
|
||||
last_ips = (emulator.cpu.timestamp_counter - last_instr_counter) / 1000 | 0;
|
||||
var stats = emulator.get_statistics();
|
||||
|
||||
summed_ips += last_ips
|
||||
var now = Date.now();
|
||||
var last_ips = stats.cpu.instruction_counter - last_instr_counter;
|
||||
|
||||
summed_ips += last_ips;
|
||||
running_time += now - last_tick;
|
||||
last_tick = now;
|
||||
|
||||
ips.textContent = last_ips;
|
||||
avg_ips.textContent = summed_ips / running_time * 1000 | 0;
|
||||
ips.textContent = last_ips / 1000 | 0;
|
||||
avg_ips.textContent = summed_ips / running_time | 0;
|
||||
time.textContent = time2str(running_time / 1000 | 0);
|
||||
|
||||
last_instr_counter = emulator.cpu.timestamp_counter;
|
||||
last_instr_counter = stats.cpu.instruction_counter;
|
||||
|
||||
setTimeout(update_info, 1000);
|
||||
}
|
||||
$("info_mouse_enabled").textContent = stats.mouse.enabled ? "Yes" : "No";
|
||||
|
||||
function update_other_info()
|
||||
{
|
||||
if(!running)
|
||||
if(stats.hda)
|
||||
{
|
||||
setTimeout(update_other_info, 1000);
|
||||
return;
|
||||
}
|
||||
$("info_hda_sectors_read").textContent = stats.hda.sectors_read;
|
||||
$("info_hda_bytes_read").textContent = stats.hda.bytes_read;
|
||||
|
||||
var devices = emulator.cpu.devices;
|
||||
var vga_stats = devices.vga.stats;
|
||||
|
||||
if(vga_stats.is_graphical)
|
||||
{
|
||||
$("info_vga_mode").textContent = "graphical";
|
||||
$("info_res").textContent = vga_stats.res_x + "x" + vga_stats.res_y;
|
||||
$("info_bpp").textContent = vga_stats.bpp;
|
||||
}
|
||||
else
|
||||
{
|
||||
$("info_vga_mode").textContent = "text";
|
||||
$("info_res").textContent = "-";
|
||||
$("info_bpp").textContent = "-";
|
||||
}
|
||||
|
||||
if(settings.mouse_adapter)
|
||||
{
|
||||
$("info_mouse_enabled").textContent = settings.mouse_adapter.enabled ? "Yes" : "No";
|
||||
}
|
||||
|
||||
if(devices.hda)
|
||||
{
|
||||
var hda_stats = devices.hda.stats;
|
||||
|
||||
$("info_hda_sectors_read").textContent = hda_stats.sectors_read;
|
||||
$("info_hda_bytes_read").textContent = hda_stats.bytes_read;
|
||||
|
||||
$("info_hda_sectors_written").textContent = hda_stats.sectors_written;
|
||||
$("info_hda_bytes_written").textContent = hda_stats.bytes_written;
|
||||
$("info_hda_status").textContent = hda_stats.loading ? "Loading ..." : "Idle";
|
||||
$("info_hda_sectors_written").textContent = stats.hda.sectors_written;
|
||||
$("info_hda_bytes_written").textContent = stats.hda.bytes_written;
|
||||
$("info_hda_status").textContent = stats.hda.loading ? "Loading ..." : "Idle";
|
||||
}
|
||||
else
|
||||
{
|
||||
$("info_hda").style.display = "none";
|
||||
}
|
||||
|
||||
if(devices.cdrom)
|
||||
if(stats.cdrom)
|
||||
{
|
||||
var cdrom_stats = devices.cdrom.stats;
|
||||
|
||||
$("info_cdrom_sectors_read").textContent = cdrom_stats.sectors_read;
|
||||
$("info_cdrom_bytes_read").textContent = cdrom_stats.bytes_read;
|
||||
$("info_cdrom_status").textContent = cdrom_stats.loading ? "Loading ..." : "Idle";
|
||||
$("info_cdrom_sectors_read").textContent = stats.cdrom.sectors_read;
|
||||
$("info_cdrom_bytes_read").textContent = stats.cdrom.bytes_read;
|
||||
$("info_cdrom_status").textContent = stats.cdrom.loading ? "Loading ..." : "Idle";
|
||||
}
|
||||
else
|
||||
{
|
||||
$("info_cdrom").style.display = "none";
|
||||
}
|
||||
|
||||
setTimeout(update_other_info, 1000);
|
||||
if(stats.vga.is_graphical)
|
||||
{
|
||||
$("info_vga_mode").textContent = "Graphical";
|
||||
$("info_res").textContent = stats.vga.res_x + "x" + stats.vga.res_y;
|
||||
$("info_bpp").textContent = stats.vga.bpp;
|
||||
}
|
||||
else
|
||||
{
|
||||
$("info_vga_mode").textContent = "Text";
|
||||
$("info_res").textContent = "-";
|
||||
$("info_bpp").textContent = "-";
|
||||
}
|
||||
|
||||
setTimeout(update_info, 1000);
|
||||
}
|
||||
|
||||
setTimeout(update_info, 1000);
|
||||
setTimeout(update_other_info, 0);
|
||||
|
||||
var stats = emulator.get_statistics();
|
||||
|
||||
if(!stats.cdrom)
|
||||
{
|
||||
$("info_cdrom").style.display = "none";
|
||||
}
|
||||
if(!stats.hda)
|
||||
{
|
||||
$("info_hda").style.display = "none";
|
||||
}
|
||||
|
||||
|
||||
$("reset").onclick = function()
|
||||
{
|
||||
|
@ -799,28 +674,28 @@
|
|||
|
||||
$("ctrlaltdel").onclick = function()
|
||||
{
|
||||
var ps2 = emulator.cpu.devices.ps2;
|
||||
emulator.keyboard_send_scancodes([
|
||||
0x1D, // ctrl
|
||||
0x38, // alt
|
||||
0x53, // delete
|
||||
|
||||
ps2.kbd_send_code(0x1D); // ctrl
|
||||
ps2.kbd_send_code(0x38); // alt
|
||||
ps2.kbd_send_code(0x53); // delete
|
||||
|
||||
// break codes
|
||||
ps2.kbd_send_code(0x1D | 0x80);
|
||||
ps2.kbd_send_code(0x38 | 0x80);
|
||||
ps2.kbd_send_code(0x53 | 0x80);
|
||||
// break codes
|
||||
0x1D | 0x80,
|
||||
0x38 | 0x80,
|
||||
0x53 | 0x80,
|
||||
]);
|
||||
|
||||
$("ctrlaltdel").blur();
|
||||
};
|
||||
|
||||
$("alttab").onclick = function()
|
||||
{
|
||||
var ps2 = emulator.cpu.devices.ps2;
|
||||
|
||||
ps2.kbd_send_code(0x38); // alt
|
||||
ps2.kbd_send_code(0x0F); // tab
|
||||
ps2.kbd_send_code(0x38 | 0x80);
|
||||
ps2.kbd_send_code(0x0F | 0x80);
|
||||
emulator.keyboard_send_scancodes([
|
||||
0x38, // alt
|
||||
0x0F, // tab
|
||||
0x38 | 0x80,
|
||||
0x0F | 0x80,
|
||||
]);
|
||||
|
||||
$("alttab").blur();
|
||||
};
|
||||
|
@ -831,30 +706,13 @@
|
|||
|
||||
if(n || n > 0)
|
||||
{
|
||||
settings.screen_adapter.set_scale(n, n);
|
||||
emulator.screen_set_scale(n, n);
|
||||
}
|
||||
};
|
||||
|
||||
$("fullscreen").onclick = function()
|
||||
{
|
||||
var elem = document.getElementById("screen_container"),
|
||||
|
||||
// bracket notation because otherwise they get renamed by closure compiler
|
||||
fn = elem["requestFullScreen"] ||
|
||||
elem["webkitRequestFullscreen"] ||
|
||||
elem["mozRequestFullScreen"] ||
|
||||
elem["msRequestFullScreen"];
|
||||
|
||||
if(fn)
|
||||
{
|
||||
fn.call(elem);
|
||||
|
||||
// This is necessary, because otherwise chromium keyboard doesn't work anymore.
|
||||
// Might (but doesn't seem to) break something else
|
||||
document.getElementsByClassName("phone_keyboard")[0].focus();
|
||||
}
|
||||
|
||||
lock_mouse(elem);
|
||||
emulator.screen_go_fullscreen();
|
||||
};
|
||||
|
||||
$("screen_container").onclick = function()
|
||||
|
@ -868,15 +726,12 @@
|
|||
|
||||
$("take_screenshot").onclick = function()
|
||||
{
|
||||
settings.screen_adapter.make_screenshot();
|
||||
emulator.screen_make_screenshot();
|
||||
|
||||
$("take_screenshot").blur();
|
||||
};
|
||||
|
||||
if(settings.serial_adapter)
|
||||
{
|
||||
$("serial").style.display = "block";
|
||||
}
|
||||
$("serial").style.display = "block";
|
||||
|
||||
window.addEventListener("keydown", ctrl_w_rescue, false);
|
||||
window.addEventListener("keyup", ctrl_w_rescue, false);
|
||||
|
@ -902,7 +757,7 @@
|
|||
function debug_start(emulator)
|
||||
{
|
||||
// called as soon as soon as emulation is started, in debug mode
|
||||
var debug = emulator.cpu.debug;
|
||||
var debug = emulator.v86.cpu.debug;
|
||||
|
||||
$("step").onclick = debug.step.bind(debug);
|
||||
$("run_until").onclick = debug.run_until.bind(debug);
|
||||
|
@ -912,6 +767,7 @@
|
|||
$("dump_regs").onclick = debug.dump_regs.bind(debug);
|
||||
$("dump_pt").onclick = debug.dump_page_directory.bind(debug);
|
||||
$("dump_instructions").onclick = debug.dump_instructions.bind(debug);
|
||||
|
||||
$("dump_instructions_file").onclick = function()
|
||||
{
|
||||
var ins = debug.get_instructions();
|
||||
|
@ -930,11 +786,24 @@
|
|||
|
||||
$("save_state").onclick = function()
|
||||
{
|
||||
dump_file(emulator.save_state(), "v86-state.bin");
|
||||
emulator.save_state(function(error, result)
|
||||
{
|
||||
if(error)
|
||||
{
|
||||
console.log("Couldn't save state: ", error);
|
||||
}
|
||||
else
|
||||
{
|
||||
dump_file(result, "v86state.bin");
|
||||
}
|
||||
});
|
||||
|
||||
$("save_state").blur();
|
||||
};
|
||||
|
||||
// helps debugging
|
||||
window.emulator = emulator;
|
||||
window.cpu = emulator.v86.cpu;
|
||||
}
|
||||
|
||||
function onpopstate(e)
|
||||
|
@ -950,4 +819,5 @@
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
474
src/browser/starter.js
Normal file
474
src/browser/starter.js
Normal file
|
@ -0,0 +1,474 @@
|
|||
"use strict";
|
||||
|
||||
/** @constructor */
|
||||
function V86Starter(options)
|
||||
{
|
||||
this.screen_adapter = undefined;
|
||||
|
||||
var bus = Bus.create();
|
||||
var adapter_bus = this.bus = bus[0];
|
||||
|
||||
this.emulator_bus = bus[1];
|
||||
|
||||
var emulator = this.v86 = new v86(bus[1]);
|
||||
|
||||
var settings = {};
|
||||
|
||||
settings.load_devices = true;
|
||||
settings.memory_size = options["memory_size"];
|
||||
settings.vga_memory_size = options["vga_memory_size"];
|
||||
settings.boot_order = options["boot_order"] || 0x213;
|
||||
settings.fda = undefined;
|
||||
settings.fdb = undefined;
|
||||
|
||||
if(options["network_relay_url"])
|
||||
{
|
||||
settings.network_adapter = new NetworkAdapter(options["network_relay_url"], adapter_bus);
|
||||
}
|
||||
|
||||
if(!options["disable_keyboard"])
|
||||
{
|
||||
this.keyboard_adapter = new KeyboardAdapter(adapter_bus);
|
||||
}
|
||||
if(!options["disable_mouse"])
|
||||
{
|
||||
this.mouse_adapter = new MouseAdapter(adapter_bus);
|
||||
}
|
||||
|
||||
if(options["screen_container"])
|
||||
{
|
||||
this.screen_adapter = new ScreenAdapter(options["screen_container"], adapter_bus);
|
||||
}
|
||||
|
||||
if(options["serial_container"])
|
||||
{
|
||||
this.serial_adapter = new SerialAdapter(options["serial_container"], adapter_bus);
|
||||
}
|
||||
//settings.serial_adapter = new ModemAdapter();
|
||||
|
||||
var files_to_load = [];
|
||||
|
||||
function add_file(file, handler)
|
||||
{
|
||||
if(!file)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(file.buffer)
|
||||
{
|
||||
console.assert(file.buffer instanceof ArrayBuffer || file.buffer instanceof File);
|
||||
handler(file.buffer);
|
||||
}
|
||||
else if(file.url)
|
||||
{
|
||||
if(file.async)
|
||||
{
|
||||
handler(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
files_to_load.push({
|
||||
url: file.url,
|
||||
handler: handler,
|
||||
size: file.size,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function put_on_settings(name, buffer)
|
||||
{
|
||||
switch(name)
|
||||
{
|
||||
case "hda":
|
||||
settings.hda = buffer;
|
||||
break;
|
||||
case "hdb":
|
||||
settings.hdb = buffer;
|
||||
break;
|
||||
case "cdrom":
|
||||
settings.cdrom = buffer;
|
||||
break;
|
||||
case "fda":
|
||||
settings.fda = buffer;
|
||||
break;
|
||||
case "fdb":
|
||||
settings.fdb = buffer;
|
||||
break;
|
||||
case "bios":
|
||||
settings.bios = buffer;
|
||||
break;
|
||||
case "vga_bios":
|
||||
settings.vga_bios = buffer;
|
||||
break;
|
||||
default:
|
||||
dbg_assert(false, name);
|
||||
}
|
||||
}
|
||||
|
||||
function make_sync_buffer(name, buffer)
|
||||
{
|
||||
if(buffer instanceof ArrayBuffer)
|
||||
{
|
||||
var result = new SyncBuffer(buffer);
|
||||
}
|
||||
else if(buffer instanceof File)
|
||||
{
|
||||
// SyncFileBuffer:
|
||||
// - loads the whole disk image into memory, impossible for large files (more than 1GB)
|
||||
// - can later serve get/set operations fast and synchronously
|
||||
// - takes some time for first load, neglectable for small files (up to 100Mb)
|
||||
//
|
||||
// AsyncFileBuffer:
|
||||
// - loads slices of the file asynchronously as requested
|
||||
// - slower get/set
|
||||
|
||||
// Heuristics: If file is smaller than 64M, use SyncFileBuffer
|
||||
//if(file.size < 64 * 1024 * 1024)
|
||||
|
||||
var result = new v86util.AsyncFileBuffer(buffer);
|
||||
//settings[name] = new SyncFileBuffer(buffer);
|
||||
}
|
||||
else if(buffer.async)
|
||||
{
|
||||
var result = new v86util.AsyncXHRBuffer(buffer.url, 512, buffer.size);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.assert(false);
|
||||
}
|
||||
|
||||
put_on_settings(name, result);
|
||||
}
|
||||
|
||||
add_file(options["bios"], put_on_settings.bind(this, "bios"));
|
||||
add_file(options["vga_bios"], put_on_settings.bind(this, "vga_bios"));
|
||||
|
||||
add_file(options["cdrom"], make_sync_buffer.bind(this, "cdrom"));
|
||||
add_file(options["hda"], make_sync_buffer.bind(this, "hda"));
|
||||
add_file(options["hdb"], make_sync_buffer.bind(this, "hdb"));
|
||||
add_file(options["fda"], make_sync_buffer.bind(this, "fda"));
|
||||
add_file(options["fdb"], make_sync_buffer.bind(this, "fdb"));
|
||||
|
||||
if(options.filesystem)
|
||||
{
|
||||
var fs9p = new FS(options.filesystem.baseurl);
|
||||
|
||||
settings.fs9p = fs9p;
|
||||
|
||||
//add_file(infos.filesystem.basefs, function()
|
||||
//{
|
||||
fs9p.LoadFilesystem({
|
||||
basefsURL: options.filesystem.basefs,
|
||||
});
|
||||
//});
|
||||
}
|
||||
|
||||
var initial_state_buffer;
|
||||
if(options["initial_state"])
|
||||
{
|
||||
add_file(options["initial_state"], function(buffer)
|
||||
{
|
||||
console.log(options["initial_state"], buffer);
|
||||
initial_state_buffer = buffer;
|
||||
});
|
||||
}
|
||||
|
||||
var starter = this;
|
||||
cont(0);
|
||||
|
||||
function cont(index)
|
||||
{
|
||||
var total = files_to_load.length;
|
||||
|
||||
if(index < total)
|
||||
{
|
||||
var f = files_to_load[index];
|
||||
|
||||
v86util.load_file(f.url, function done(result)
|
||||
{
|
||||
f.handler(result);
|
||||
cont(index + 1);
|
||||
}, function progress(e)
|
||||
{
|
||||
starter.emulator_bus.send("download-progress", {
|
||||
file_index: index,
|
||||
file_count: total,
|
||||
|
||||
lengthComputable: e.lengthComputable,
|
||||
total: f.size || e.total,
|
||||
loaded: e.loaded,
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
emulator.init(settings);
|
||||
|
||||
if(initial_state_buffer)
|
||||
{
|
||||
emulator.restore_state(initial_state_buffer);
|
||||
}
|
||||
|
||||
if(options["autostart"])
|
||||
{
|
||||
emulator.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start emulation. Do nothing if emulator is running already.
|
||||
*/
|
||||
V86Starter.prototype.run = function()
|
||||
{
|
||||
this.v86.run();
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop emulation. Do nothing if emulator is not running.
|
||||
*/
|
||||
V86Starter.prototype.stop = function()
|
||||
{
|
||||
this.v86.stop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Restart (force a reboot).
|
||||
*/
|
||||
V86Starter.prototype.restart = function()
|
||||
{
|
||||
this.v86.restart();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} event
|
||||
* @param {function(*)} listener
|
||||
*/
|
||||
V86Starter.prototype.add_listener = function(event, listener)
|
||||
{
|
||||
this.bus.register(event, listener, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} event
|
||||
* @param {function(*)} listener
|
||||
*/
|
||||
V86Starter.prototype.remove_listener = function(event, listener)
|
||||
{
|
||||
this.bus.unregister(event, listener);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} state
|
||||
*/
|
||||
V86Starter.prototype.restore_state = function(state)
|
||||
{
|
||||
this.v86.restore_state(state);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {function(Object, ArrayBuffer)} callback
|
||||
*/
|
||||
V86Starter.prototype.save_state = function(callback)
|
||||
{
|
||||
// Might become asynchronous at some point
|
||||
|
||||
var emulator = this;
|
||||
|
||||
setTimeout(function()
|
||||
{
|
||||
callback(null, emulator.v86.save_state());
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Object}
|
||||
*/
|
||||
V86Starter.prototype.get_statistics = function()
|
||||
{
|
||||
var stats = {
|
||||
cpu: {
|
||||
instruction_counter: this.v86.cpu.timestamp_counter,
|
||||
},
|
||||
};
|
||||
|
||||
var devices = this.v86.cpu.devices;
|
||||
|
||||
if(devices.hda)
|
||||
{
|
||||
stats.hda = devices.hda.stats;
|
||||
}
|
||||
|
||||
if(devices.cdrom)
|
||||
{
|
||||
stats.cdrom = devices.cdrom.stats;
|
||||
}
|
||||
|
||||
if(devices.ps2)
|
||||
{
|
||||
stats.mouse = {
|
||||
enabled: devices.ps2.enable_mouse,
|
||||
};
|
||||
}
|
||||
|
||||
if(devices.vga)
|
||||
{
|
||||
stats.vga = devices.vga.stats;
|
||||
}
|
||||
|
||||
return stats;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
V86Starter.prototype.is_running = function()
|
||||
{
|
||||
return this.v86.running;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} codes
|
||||
*/
|
||||
V86Starter.prototype.keyboard_send_scancodes = function(codes)
|
||||
{
|
||||
var ps2 = this.v86.cpu.devices.ps2;
|
||||
|
||||
for(var i = 0; i < codes.length; i++)
|
||||
{
|
||||
ps2.kbd_send_code(codes[i]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Download a screenshot
|
||||
*/
|
||||
V86Starter.prototype.screen_make_screenshot = function()
|
||||
{
|
||||
if(this.screen_adapter)
|
||||
{
|
||||
this.screen_adapter.make_screenshot();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the scaling level of the emulated screen
|
||||
*
|
||||
* @param {number} sx
|
||||
* @param {number} sy
|
||||
*/
|
||||
V86Starter.prototype.screen_set_scale = function(sx, sy)
|
||||
{
|
||||
if(this.screen_adapter)
|
||||
{
|
||||
this.screen_adapter.set_scale(sx, sy);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the browser go fullscreen
|
||||
*/
|
||||
V86Starter.prototype.screen_go_fullscreen = function()
|
||||
{
|
||||
if(!this.screen_adapter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var elem = document.getElementById("screen_container");
|
||||
|
||||
if(!elem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// bracket notation because otherwise they get renamed by closure compiler
|
||||
var fn = elem["requestFullScreen"] ||
|
||||
elem["webkitRequestFullscreen"] ||
|
||||
elem["mozRequestFullScreen"] ||
|
||||
elem["msRequestFullScreen"];
|
||||
|
||||
if(fn)
|
||||
{
|
||||
fn.call(elem);
|
||||
|
||||
// This is necessary, because otherwise chromium keyboard doesn't work anymore.
|
||||
// Might (but doesn't seem to) break something else
|
||||
var focus_element = document.getElementsByClassName("phone_keyboard")[0];
|
||||
focus_element && focus_element.focus();
|
||||
}
|
||||
|
||||
//this.lock_mouse(elem);
|
||||
this.lock_mouse();
|
||||
};
|
||||
|
||||
/**
|
||||
* Lock the mouse button (it is inivisble and movements are only registered in
|
||||
* the emulator
|
||||
*/
|
||||
V86Starter.prototype.lock_mouse = function()
|
||||
{
|
||||
var elem = document.body;
|
||||
|
||||
var fn = elem["requestPointerLock"] ||
|
||||
elem["mozRequestPointerLock"] ||
|
||||
elem["webkitRequestPointerLock"];
|
||||
|
||||
if(fn)
|
||||
{
|
||||
fn.call(elem);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable or disable sending mouse events to the emulated PS2 controller
|
||||
*
|
||||
* @param {boolean} enabled
|
||||
*/
|
||||
V86Starter.prototype.mouse_set_status = function(enabled)
|
||||
{
|
||||
if(this.mouse_adapter)
|
||||
{
|
||||
this.mouse_adapter.emu_enabled = enabled;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send a string to the first emulated serial terminal
|
||||
*
|
||||
* @param {string} data
|
||||
*/
|
||||
V86Starter.prototype.serial0_send = function(data)
|
||||
{
|
||||
for(var i = 0; i < data.length; i++)
|
||||
{
|
||||
this.serial_adapter.send_char(data.charCodeAt(i));
|
||||
}
|
||||
};
|
||||
|
||||
// Closure Compiler's way of exporting
|
||||
if(typeof window !== "undefined")
|
||||
{
|
||||
window["V86Starter"] = V86Starter;
|
||||
|
||||
V86Starter.prototype["run"] = V86Starter.prototype.run;
|
||||
V86Starter.prototype["stop"] = V86Starter.prototype.stop;
|
||||
V86Starter.prototype["restart"] = V86Starter.prototype.restart;
|
||||
V86Starter.prototype["add_listener"] = V86Starter.prototype.add_listener;
|
||||
V86Starter.prototype["remove_listener"] = V86Starter.prototype.remove_listener;
|
||||
V86Starter.prototype["restore_state"] = V86Starter.prototype.restore_state;
|
||||
V86Starter.prototype["save_state"] = V86Starter.prototype.save_state;
|
||||
V86Starter.prototype["get_statistics"] = V86Starter.prototype.get_statistics;
|
||||
V86Starter.prototype["is_running"] = V86Starter.prototype.is_running;
|
||||
V86Starter.prototype["keyboard_send_scancodes"] = V86Starter.prototype.keyboard_send_scancodes;
|
||||
V86Starter.prototype["screen_make_screenshot"] = V86Starter.prototype.screen_make_screenshot;
|
||||
V86Starter.prototype["screen_set_scale"] = V86Starter.prototype.screen_set_scale;
|
||||
V86Starter.prototype["screen_go_fullscreen"] = V86Starter.prototype.screen_go_fullscreen;
|
||||
V86Starter.prototype["lock_mouse"] = V86Starter.prototype.lock_mouse;
|
||||
V86Starter.prototype["mouse_set_status"] = V86Starter.prototype.mouse_set_status;
|
||||
V86Starter.prototype["serial0_send"] = V86Starter.prototype.serial0_send;
|
||||
}
|
|
@ -48,11 +48,6 @@ function h(n, len)
|
|||
}
|
||||
}
|
||||
|
||||
if(typeof window === "object")
|
||||
{
|
||||
window["SyncBuffer"] = SyncBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous access to ArrayBuffer
|
||||
* @constructor
|
||||
|
|
|
@ -84,6 +84,7 @@ v86.prototype.init = function(settings)
|
|||
}
|
||||
|
||||
this.cpu.init(settings, this.bus);
|
||||
this.bus.send_async("emulator-ready");
|
||||
};
|
||||
|
||||
// initialization that only needs to be once
|
||||
|
@ -157,11 +158,13 @@ v86.prototype.lazy_init = function()
|
|||
|
||||
v86.prototype.save_state = function()
|
||||
{
|
||||
// TODO: Should be implemented here, not on cpu
|
||||
return this.cpu.save_state();
|
||||
};
|
||||
|
||||
v86.prototype.restore_state = function(state)
|
||||
{
|
||||
// TODO: Should be implemented here, not on cpu
|
||||
return this.cpu.restore_state(state);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue