From 540ab5d43c8f9a1b02724390d488e611212cc7ae Mon Sep 17 00:00:00 2001
From: alexkar598 <25136265+alexkar598@users.noreply.github.com>
Date: Sun, 23 Jun 2024 01:14:09 -0400
Subject: [PATCH] Merges all per port emulator events into 1 event with a port
argument
---
.../editor-page/editor-page.component.html | 15 +-
.../editor-page/editor-page.component.ts | 27 ++--
src/utils/literalConstants.ts | 6 +
src/vm/commandQueue.service.ts | 7 +-
src/vm/emulator.service.ts | 30 ++--
src/vm/emulator.worker.ts | 131 ++++--------------
6 files changed, 70 insertions(+), 146 deletions(-)
diff --git a/src/app/pages/editor-page/editor-page.component.html b/src/app/pages/editor-page/editor-page.component.html
index 2e4795b..1086673 100644
--- a/src/app/pages/editor-page/editor-page.component.html
+++ b/src/app/pages/editor-page/editor-page.component.html
@@ -14,14 +14,17 @@
-
-
-
-
-
+
+
-
+
+
+
+
diff --git a/src/app/pages/editor-page/editor-page.component.ts b/src/app/pages/editor-page/editor-page.component.ts
index f6d3e19..bc4bb57 100644
--- a/src/app/pages/editor-page/editor-page.component.ts
+++ b/src/app/pages/editor-page/editor-page.component.ts
@@ -6,6 +6,7 @@ import { EmulatorService } from '../../../vm/emulator.service';
import { ExecutorService } from '../../../vm/executor.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { PanelComponent } from '../../components/panel/panel.component';
+import { Port } from '../../../utils/literalConstants';
@Component({
selector: 'app-editor-page',
@@ -36,21 +37,19 @@ export class EditorPageComponent {
executor.output.pipe(takeUntilDestroyed(destroyRef)).subscribe((value) => {
this.output += value;
});
- emulator.receivedOutputScreen
+ emulator.receivedOutput
.pipe(takeUntilDestroyed(destroyRef))
- .subscribe((value) => {
- this.screen.write(value);
- });
- emulator.receivedOutputController //TODO: need feature parity with the old version
- .pipe(takeUntilDestroyed(destroyRef))
- .subscribe((value) => {
- this.controller.write(value.replace(/[\u0000\n]/, '\r\n'));
- });
-
- emulator.receivedOutputConsole
- .pipe(takeUntilDestroyed(destroyRef))
- .subscribe((value) => {
- this.terminal.write(value);
+ .subscribe(([port, value]) => {
+ switch (port) {
+ case Port.Console:
+ return this.terminal.write(value);
+ case Port.Screen:
+ return this.screen.write(value);
+ case Port.Controller: //TODO: need feature parity with the old version for controller pretty print
+ return this.controller.write(value.replace(/[\u0000\n]/, '\r\n'));
+ }
});
}
+
+ protected readonly Port = Port;
}
diff --git a/src/utils/literalConstants.ts b/src/utils/literalConstants.ts
index c225df7..09eb1ec 100644
--- a/src/utils/literalConstants.ts
+++ b/src/utils/literalConstants.ts
@@ -1 +1,7 @@
export const vmRemoteUrlSearchParameter = 'vmRemoteUrl';
+
+export enum Port {
+ Console,
+ Screen,
+ Controller,
+}
diff --git a/src/vm/commandQueue.service.ts b/src/vm/commandQueue.service.ts
index 7ea4ac8..f4a3c91 100644
--- a/src/vm/commandQueue.service.ts
+++ b/src/vm/commandQueue.service.ts
@@ -1,6 +1,7 @@
import { Injectable } from '@angular/core';
import { EmulatorService } from './emulator.service';
import { Process } from './process';
+import { Port } from '../utils/literalConstants';
export interface CommandResultOK {
status: 'OK';
@@ -73,7 +74,9 @@ export class CommandQueueService {
public constructor(public emulator: EmulatorService) {
//It's called from window.setTimeout so this is window otherwise
this.tickQueue = this.tickQueue.bind(this);
- emulator.receivedOutputController.subscribe((data) => {
+ emulator.receivedOutput.subscribe(([port, data]) => {
+ if (port != Port.Controller) return;
+
for (const chr of data) {
//TODO: Rewrite the receive function to receive chunks instead of character by character
try {
@@ -172,7 +175,7 @@ export class CommandQueueService {
this.activeCommand = command;
- this.emulator.sendController(cmdStr + '\0');
+ this.emulator.sendPort(Port.Controller, cmdStr + '\0');
}
/**
diff --git a/src/vm/emulator.service.ts b/src/vm/emulator.service.ts
index 00e032e..0543aa1 100644
--- a/src/vm/emulator.service.ts
+++ b/src/vm/emulator.service.ts
@@ -1,7 +1,11 @@
import { EventEmitter, Injectable, Output } from '@angular/core';
-import type { WorkerMsgWithoutCID, WorkerResponseMsg } from './emulator.worker';
+import type {
+ MsgSendPort,
+ WorkerMsgWithoutCID,
+ WorkerResponseMsg,
+} from './emulator.worker';
import { environment } from '../environments/environment';
-import { vmRemoteUrlSearchParameter } from '../utils/literalConstants';
+import { Port, vmRemoteUrlSearchParameter } from '../utils/literalConstants';
const encoder = new TextEncoder();
@@ -12,11 +16,7 @@ export class EmulatorService {
@Output()
public resetOutputConsole = new EventEmitter();
@Output()
- public receivedOutputConsole = new EventEmitter();
- @Output()
- public receivedOutputScreen = new EventEmitter();
- @Output()
- public receivedOutputController = new EventEmitter();
+ public receivedOutput = new EventEmitter<[Port, string]>();
private worker;
@@ -38,7 +38,7 @@ export class EmulatorService {
if (e.event === 'resetOutputConsole')
return this.resetOutputConsole.emit();
- return this[e.event].emit(...(e.data ?? []));
+ return this[e.event].emit(e.data);
}
const callback = this.asyncCallbacks.get(e.commandID);
@@ -70,16 +70,9 @@ export class EmulatorService {
);
}
- public sendTerminal(data: string) {
- this.sendCommand({ command: 'sendTerminal', data });
- }
- public sendScreen(data: string) {
- this.sendCommand({ command: 'sendScreen', data });
+ public sendPort(...data: MsgSendPort['data']) {
+ this.sendCommand({ command: 'sendPort', data });
}
- public sendController(data: string) {
- this.sendCommand({ command: 'sendController', data });
- }
-
public pause() {
return this.sendCommandAsync({ command: 'pause' });
}
@@ -94,7 +87,4 @@ export class EmulatorService {
data: new Uint8Array(content),
});
}
- public resetTerminal() {
- this.sendCommand({ command: 'resetTerminal' });
- }
}
diff --git a/src/vm/emulator.worker.ts b/src/vm/emulator.worker.ts
index a8b8cd8..085a28d 100644
--- a/src/vm/emulator.worker.ts
+++ b/src/vm/emulator.worker.ts
@@ -1,46 +1,31 @@
///
-import { vmRemoteUrlSearchParameter } from '../utils/literalConstants';
+import { Port, vmRemoteUrlSearchParameter } from '../utils/literalConstants';
importScripts('./lib/libv86.js');
-interface MsgSendTerminal {
- command: 'sendTerminal';
- data: string;
+export interface MsgSendPort {
+ command: 'sendPort';
+ data: [Port, string];
}
-interface MsgSendScreen {
- command: 'sendScreen';
- data: string;
-}
-interface MsgSendController {
- command: 'sendController';
- data: string;
-}
-interface MsgStart {
+export interface MsgStart {
command: 'start';
data?: undefined;
}
-interface MsgPause {
+export interface MsgPause {
command: 'pause';
data?: undefined;
}
-interface MsgSendFile {
+export interface MsgSendFile {
command: 'sendFile';
name: string;
data: Uint8Array;
}
-interface MsgResetTerminal {
- command: 'resetTerminal';
- data?: undefined;
-}
export type WorkerMsgWithoutCID =
- | MsgSendTerminal
- | MsgSendScreen
- | MsgSendController
+ | MsgSendPort
| MsgStart
| MsgPause
- | MsgSendFile
- | MsgResetTerminal;
+ | MsgSendFile;
export type WorkerMsg = WorkerMsgWithoutCID & {
commandID: number;
@@ -55,16 +40,8 @@ export type WorkerResponseMsg =
export type WorkerEventResponseMsg =
| {
- event: 'receivedOutputConsole';
- data: [string];
- }
- | {
- event: 'receivedOutputScreen';
- data: [string];
- }
- | {
- event: 'receivedOutputController';
- data: [string];
+ event: 'receivedOutput';
+ data: [Port, string];
}
| {
event: 'resetOutputConsole';
@@ -152,41 +129,13 @@ const emulator = new V86({
virtio_console: true,
});
-//@ts-ignore
-self.emulator = emulator;
-
-let resetting = false;
-
-function sendTerminal(message: string) {
- emulator.bus.send(
- 'virtio-console0-input-bytes',
- [...message].map((x) => x.charCodeAt(0)),
- );
-}
-function sendScreen(message: string) {
- emulator.bus.send(
- 'virtio-console1-input-bytes',
- [...message].map((x) => x.charCodeAt(0)),
- );
-}
-function sendController(message: string) {
- emulator.bus.send(
- 'virtio-console2-input-bytes',
- [...message].map((x) => x.charCodeAt(0)),
- );
-}
onmessage = ({ data: e }: MessageEvent) => {
switch (e.command) {
- case 'sendTerminal': {
- sendTerminal(e.data);
- break;
- }
- case 'sendScreen': {
- sendScreen(e.data);
- break;
- }
- case 'sendController': {
- sendController(e.data);
+ case 'sendPort': {
+ emulator.bus.send(
+ `virtio-console${e.data[0]}-input-bytes`,
+ [...e.data[1]].map((x) => x.charCodeAt(0)),
+ );
break;
}
case 'start': {
@@ -216,43 +165,17 @@ onmessage = ({ data: e }: MessageEvent) => {
});
break;
}
- case 'resetTerminal': {
- if (!emulator.is_running()) return;
- if (resetting) return;
- resetting = true;
- const uart0: {
- lsr: number;
- } = emulator.v86.cpu.devices.uart0;
- uart0.lsr |= 0b00010000;
- setTimeout(() => {
- sendTerminal(' ');
- setTimeout(() => {
- uart0.lsr &= ~0b00010000;
- sendTerminal('k');
- postMessage({ event: 'resetOutputConsole' });
- sendTerminal('\n');
- resetting = false;
- }, 1);
- }, 1);
- }
}
};
-emulator.add_listener('virtio-console0-output-bytes', (bytes: Uint8Array) => {
- postMessage({
- event: 'receivedOutputConsole',
- data: [decoder.decode(bytes)],
- });
-});
-emulator.add_listener('virtio-console1-output-bytes', (bytes: Uint8Array) => {
- postMessage({
- event: 'receivedOutputScreen',
- data: [decoder.decode(bytes)],
- });
-});
-emulator.add_listener('virtio-console2-output-bytes', (bytes: Uint8Array) => {
- postMessage({
- event: 'receivedOutputController',
- data: [decoder.decode(bytes)],
- });
-});
+for (let i = 0; i < 3; i++) {
+ emulator.add_listener(
+ `virtio-console${i}-output-bytes`,
+ (bytes: Uint8Array) => {
+ postMessage({
+ event: 'receivedOutput',
+ data: [i, decoder.decode(bytes)],
+ });
+ },
+ );
+}