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)], + }); + }, + ); +}