mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Emscripten progress (#206)
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
onmessage = async (event) => {
|
||||
const data = event.data;
|
||||
if (data.message == "run") {
|
||||
runEmulation(data.data);
|
||||
const payload = data.data;
|
||||
runEmulation(payload.filesystem, payload.file);
|
||||
}
|
||||
};
|
||||
|
||||
function logLine(text) {
|
||||
postMessage(text);
|
||||
postMessage({ message: "log", data: text });
|
||||
}
|
||||
|
||||
function runEmulation(filesystem) {
|
||||
function runEmulation(filesystem, file) {
|
||||
globalThis.Module = {
|
||||
arguments: ["-b", "-c", "-e", "./root", "c:/test-sample.exe",],
|
||||
arguments: ["-b", /*"-c",*/ "-e", "./root", file],
|
||||
onRuntimeInitialized: function () {
|
||||
filesystem.forEach(e => {
|
||||
if (e.name.endsWith("/")) {
|
||||
@@ -20,6 +21,9 @@ function runEmulation(filesystem) {
|
||||
const dirs = e.name.split("/")
|
||||
const file = dirs.pop();
|
||||
const buffer = new Uint8Array(e.data);
|
||||
if (FS.analyzePath(e.name).exists) {
|
||||
FS.unlink(e.name);
|
||||
}
|
||||
FS.createDataFile("/" + dirs.join('/'), file, buffer, true, true);
|
||||
}
|
||||
})
|
||||
@@ -27,6 +31,7 @@ function runEmulation(filesystem) {
|
||||
print: logLine,
|
||||
printErr: logLine,
|
||||
postRun: () => {
|
||||
postMessage({ message: "end", data: null });
|
||||
self.close();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -343,6 +343,40 @@
|
||||
return cacheAndUseData("emulator-filesystem-2", fetchFilesystem);
|
||||
}
|
||||
|
||||
function selectAndReadFile() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fileInput = document.createElement('input');
|
||||
fileInput.type = 'file';
|
||||
fileInput.accept = '.exe';
|
||||
|
||||
fileInput.addEventListener('change', function (event) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = function (e) {
|
||||
const arrayBuffer = e.target.result;
|
||||
resolve({
|
||||
name: file.name,
|
||||
data: arrayBuffer
|
||||
});
|
||||
};
|
||||
|
||||
reader.onerror = function (e) {
|
||||
reject(new Error('Error reading file: ' + e.target.error));
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(file);
|
||||
} else {
|
||||
reject(new Error('No file selected'));
|
||||
}
|
||||
});
|
||||
|
||||
// Programmatically click the file input element to open the file picker
|
||||
fileInput.click();
|
||||
});
|
||||
}
|
||||
|
||||
function printText(lines) {
|
||||
if (lines.length == 0) {
|
||||
return;
|
||||
@@ -362,6 +396,13 @@
|
||||
outputDiv.scrollTop = outputDiv.scrollHeight;
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
var outputDiv = document.getElementById('output');
|
||||
if (outputDiv) {
|
||||
outputDiv.innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
function flushLines() {
|
||||
const lines = globalThis.logLines;
|
||||
globalThis.logLines = [];
|
||||
@@ -373,24 +414,59 @@
|
||||
globalThis.logLines.push(text);
|
||||
}
|
||||
|
||||
async function startEmulation() {
|
||||
if (window.emulationStarted) {
|
||||
function stopEmulation() {
|
||||
if (window.emulator) {
|
||||
window.emulator.terminate();
|
||||
window.emulator = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async function selectAndStartEmulation() {
|
||||
const file = await selectAndReadFile();
|
||||
return await startEmulation(file);
|
||||
}
|
||||
|
||||
async function startEmulation(fileData) {
|
||||
if (window.emulator) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.emulationStarted = true;
|
||||
clearLog();
|
||||
|
||||
const worker = new Worker("./emulator.js");
|
||||
window.emulator = worker;
|
||||
|
||||
const filesystem = await getFilesystem();
|
||||
|
||||
logLine("Starting emulation...");
|
||||
|
||||
const worker = new Worker("./emulator.js?4");
|
||||
var file = "c:/test-sample.exe";
|
||||
if (fileData) {
|
||||
const filename = fileData.name.split("/").pop().split("\\").pop();
|
||||
const canonicalName = filename.toLowerCase()
|
||||
file = "c:/" + canonicalName;
|
||||
filesystem.push({
|
||||
name: "root/filesys/c/" + canonicalName,
|
||||
data: fileData.data,
|
||||
});
|
||||
}
|
||||
|
||||
worker.onmessage = (event) => {
|
||||
logLine(event.data);
|
||||
if (event.data.message == "log") {
|
||||
logLine(event.data.data);
|
||||
}
|
||||
|
||||
if (event.data.message == "end") {
|
||||
window.emulator = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
worker.postMessage({
|
||||
message: "run",
|
||||
data: filesystem,
|
||||
data: {
|
||||
filesystem,
|
||||
file,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -423,8 +499,9 @@
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<a class="button" href="#" onclick="startEmulation()">Start Emulation</a>
|
||||
<!--<a class="button" href="#" onclick="startEmulation()">Select .exe</a>-->
|
||||
<a class="button" href="#" onclick="startEmulation()">Run Sample</a>
|
||||
<a class="button" href="#" onclick="selectAndStartEmulation()">Run your .exe</a>
|
||||
<a class="button" href="#" onclick="stopEmulation()">Stop Emulation</a>
|
||||
<a class="button" href="https://github.com/momo5502/emulator" target="_blank">GitHub</a>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -153,26 +153,32 @@ namespace
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
win_emu.log.print(color::red, "Emulation failed at: 0x%" PRIx64 " - %s\n",
|
||||
win_emu.emu().read_instruction_pointer(), e.what());
|
||||
win_emu.log.error("Emulation failed at: 0x%" PRIx64 " - %s\n", win_emu.emu().read_instruction_pointer(),
|
||||
e.what());
|
||||
throw;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
win_emu.log.print(color::red, "Emulation failed at: 0x%" PRIx64 "\n",
|
||||
win_emu.emu().read_instruction_pointer());
|
||||
win_emu.log.error("Emulation failed at: 0x%" PRIx64 "\n", win_emu.emu().read_instruction_pointer());
|
||||
throw;
|
||||
}
|
||||
|
||||
const auto exit_status = win_emu.process.exit_status;
|
||||
if (!exit_status.has_value())
|
||||
{
|
||||
win_emu.log.print(color::red, "Emulation terminated without status!\n");
|
||||
win_emu.log.error("Emulation terminated without status!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto success = *exit_status == STATUS_SUCCESS;
|
||||
win_emu.log.print(success ? color::green : color::red, "Emulation terminated with status: %X\n", *exit_status);
|
||||
|
||||
if (!options.silent)
|
||||
{
|
||||
win_emu.log.disable_output(false);
|
||||
win_emu.log.print(success ? color::green : color::red, "Emulation terminated with status: %X\n",
|
||||
*exit_status);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ namespace
|
||||
catch (...)
|
||||
{
|
||||
win_emu.log.disable_output(false);
|
||||
win_emu.log.print(color::red, "Emulation failed at: 0x%" PRIx64 "\n",
|
||||
win_emu.emu().read_instruction_pointer());
|
||||
win_emu.log.error("Emulation failed at: 0x%" PRIx64 "\n", win_emu.emu().read_instruction_pointer());
|
||||
throw;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace
|
||||
va_list ap; \
|
||||
va_start(ap, msg); \
|
||||
const auto str = format(&ap, msg); \
|
||||
va_end(ap);
|
||||
va_end(ap)
|
||||
|
||||
void print_colored(const std::string_view& line, const color_type base_color)
|
||||
{
|
||||
@@ -106,9 +106,9 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void logger::print(const color c, const std::string_view message) const
|
||||
void logger::print_message(const color c, const std::string_view message, const bool force) const
|
||||
{
|
||||
if (this->disable_output_)
|
||||
if (!force && this->disable_output_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -120,40 +120,40 @@ void logger::print(const color c, const std::string_view message) const
|
||||
void logger::print(const color c, const char* message, ...) const
|
||||
{
|
||||
format_to_string(message, data);
|
||||
this->print(c, data);
|
||||
this->print_message(c, data);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(cert-dcl50-cpp)
|
||||
void logger::info(const char* message, ...) const
|
||||
{
|
||||
format_to_string(message, data);
|
||||
this->print(color::cyan, data);
|
||||
this->print_message(color::cyan, data);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(cert-dcl50-cpp)
|
||||
void logger::warn(const char* message, ...) const
|
||||
{
|
||||
format_to_string(message, data);
|
||||
this->print(color::yellow, data);
|
||||
this->print_message(color::yellow, data);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(cert-dcl50-cpp)
|
||||
void logger::error(const char* message, ...) const
|
||||
{
|
||||
format_to_string(message, data);
|
||||
this->print(color::red, data);
|
||||
this->print_message(color::red, data, true);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(cert-dcl50-cpp)
|
||||
void logger::success(const char* message, ...) const
|
||||
{
|
||||
format_to_string(message, data);
|
||||
this->print(color::green, data);
|
||||
this->print_message(color::green, data);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(cert-dcl50-cpp)
|
||||
void logger::log(const char* message, ...) const
|
||||
{
|
||||
format_to_string(message, data);
|
||||
this->print(color::gray, data);
|
||||
this->print_message(color::gray, data);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ enum class color
|
||||
class logger
|
||||
{
|
||||
public:
|
||||
void print(color c, std::string_view message) const;
|
||||
void print(color c, const char* message, ...) const FORMAT_ATTRIBUTE(3, 4);
|
||||
void info(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3);
|
||||
void warn(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3);
|
||||
@@ -43,4 +42,5 @@ class logger
|
||||
|
||||
private:
|
||||
bool disable_output_{false};
|
||||
void print_message(color c, std::string_view message, bool force = false) const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user