Skip to content

Commit

Permalink
Add V86.set_fda, V86.eject_fda + a test for floppy insertion/ejection
Browse files Browse the repository at this point in the history
  • Loading branch information
copy committed Aug 26, 2023
1 parent 9790592 commit eaae139
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 63 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ api-tests: all-debug
./tests/api/clean-shutdown.js
./tests/api/state.js
./tests/api/reset.js
./tests/api/floppy-insert-eject.js

all-tests: jshint kvm-unit-test qemutests qemutests-release jitpagingtests api-tests nasmtests nasmtests-force-jit tests expect-tests
# Skipping:
Expand Down
105 changes: 42 additions & 63 deletions src/browser/starter.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,78 +395,21 @@ V86Starter.prototype.continue_init = async function(emulator, options)
file.async = false;
}

if(file.buffer instanceof ArrayBuffer)
if(file.url && !file.async)
{
var buffer = new v86util.SyncBuffer(file.buffer);
files_to_load.push({
name: name,
loadable: buffer,
url: file.url,
size: file.size,
});
}
else if(typeof File !== "undefined" && file.buffer instanceof File)
else
{
// 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 larger than or equal to 256M, use AsyncFileBuffer
if(file.async === undefined)
{
file.async = file.buffer.size >= 256 * 1024 * 1024;
}

if(file.async)
{
var buffer = new v86util.AsyncFileBuffer(file.buffer);
}
else
{
var buffer = new v86util.SyncFileBuffer(file.buffer);
}

files_to_load.push({
name: name,
loadable: buffer,
name,
loadable: v86util.buffer_from_object(file),
});
}
else if(file.url)
{
if(file.async)
{
let buffer;

if(file.use_parts)
{
buffer = new v86util.AsyncXHRPartfileBuffer(file.url, file.size, file.fixed_chunk_size, false, this.zstd_decompress_worker.bind(this));
}
else
{
buffer = new v86util.AsyncXHRBuffer(file.url, file.size, file.fixed_chunk_size);
}

files_to_load.push({
name: name,
loadable: buffer,
});
}
else
{
files_to_load.push({
name: name,
url: file.url,
size: file.size,
});
}
}
else
{
dbg_log("Ignored file: url=" + file.url + " buffer=" + file.buffer);
}
};

if(options["state"])
Expand Down Expand Up @@ -1023,6 +966,42 @@ V86Starter.prototype.is_running = function()
return this.cpu_is_running;
};

/**
* Set the image inserted in the floppy drive. Can be changed at runtime, as
* when physically changing the floppy disk.
* @export
*/
V86Starter.prototype.set_fda = async function(file)
{
if(file.url && !file.async)
{
v86util.load_file(file.url, {
done: result =>
{
this.v86.cpu.devices.fdc.set_fda(new v86util.SyncBuffer(result));
},
});
}
else
{
const image = v86util.buffer_from_object(file);
image.onload = () =>
{
this.v86.cpu.devices.fdc.set_fda(image);
};
image.load();
}
};

/**
* Eject the floppy drive.
* @export
*/
V86Starter.prototype.eject_fda = function()
{
this.v86.cpu.devices.fdc.eject_fda();
};

/**
* Send a sequence of scan codes to the emulated PS2 controller. A list of
* codes can be found at http://stanislavs.org/helppc/make_codes.html.
Expand Down
57 changes: 57 additions & 0 deletions src/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
v86util.AsyncFileBuffer = AsyncFileBuffer;
v86util.SyncFileBuffer = SyncFileBuffer;

v86util.buffer_from_object = buffer_from_object;

// The smallest size the emulated hardware can emit
const BLOCK_SIZE = 256;

Expand Down Expand Up @@ -744,4 +746,59 @@
});
};
}

function buffer_from_object(obj)
{
// TODO: accept Uint8Array, ArrayBuffer, File, url rather than { url }

if(obj.buffer instanceof ArrayBuffer)
{
return new v86util.SyncBuffer(obj.buffer);
}
else if(typeof File !== "undefined" && obj.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 larger than or equal to 256M, use AsyncFileBuffer
let is_async = obj.async;
if(is_async === undefined)
{
is_async = obj.buffer.size >= 256 * 1024 * 1024;
}

if(is_async)
{
return new v86util.AsyncFileBuffer(obj.buffer);
}
else
{
return new v86util.SyncFileBuffer(obj.buffer);
}
}
else if(obj.url)
{
// Note: Only async for now

if(obj.use_parts)
{
const zstd_decompress = null; // TODO
return new v86util.AsyncXHRPartfileBuffer(obj.url, obj.size, obj.fixed_chunk_size, false, zstd_decompress);
}
else
{
return new v86util.AsyncXHRBuffer(obj.url, obj.size, obj.fixed_chunk_size);
}
}
else
{
dbg_log("Ignored file: url=" + obj.url + " buffer=" + obj.buffer);
}
}
})();
41 changes: 41 additions & 0 deletions tests/api/floppy-insert-eject.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env node
"use strict";

const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;

const fs = require("fs");
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;

process.on("unhandledRejection", exn => { throw exn; });

const emulator = new V86({
bios: { url: __dirname + "/../../bios/seabios.bin" },
vga_bios: { url: __dirname + "/../../bios/vgabios.bin" },
hda: { url: __dirname + "/../../images/msdos.img" },
network_relay_url: "<UNUSED>",
autostart: true,
memory_size: 32 * 1024 * 1024,
filesystem: {},
log_level: 0,
screen_dummy: true,
});

emulator.automatically([
{ sleep: 1 },
{ vga_text: "C:\\> " },
{ keyboard_send: "dir A:\n" },
{ vga_text: "Abort, Retry, Fail?" },
{ keyboard_send: "F" },
{ call: () => {
emulator.set_fda({ url: __dirname + "/../../images/freedos722.img" });
},
},
{ keyboard_send: "dir A:\n" },
{ sleep: 1 },
{ vga_text: "FDOS <DIR>" },
{ call: () => {
console.log("Passed");
emulator.stop();
}
},
]);

0 comments on commit eaae139

Please sign in to comment.