Skip to content

Commit

Permalink
Merges all per port emulator events into 1 event with a port argument
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkar598 committed Jun 23, 2024
1 parent ba63d05 commit 540ab5d
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 146 deletions.
15 changes: 9 additions & 6 deletions src/app/pages/editor-page/editor-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@
</as-split-area>
<as-split-area size="45">
<as-split>
<app-panel title="Terminal" as-split-area>
<app-terminal #terminal (input)="emulator.sendTerminal($event)" />
</app-panel>
<app-panel title="Controller log" as-split-area>
<app-terminal #controller (input)="emulator.sendTerminal($event)" />
<app-panel title="Console" as-split-area>
<app-terminal
#terminal
(input)="emulator.sendPort(Port.Console, $event)"
/>
</app-panel>
<app-panel title="Screen log" as-split-area>
<app-terminal #screen (input)="emulator.sendTerminal($event)" />
<app-terminal #screen />
</app-panel>
<app-panel title="Controller log" as-split-area>
<app-terminal #controller />
</app-panel>
</as-split>
</as-split-area>
Expand Down
27 changes: 13 additions & 14 deletions src/app/pages/editor-page/editor-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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;
}
6 changes: 6 additions & 0 deletions src/utils/literalConstants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export const vmRemoteUrlSearchParameter = 'vmRemoteUrl';

export enum Port {
Console,
Screen,
Controller,
}
7 changes: 5 additions & 2 deletions src/vm/commandQueue.service.ts
Original file line number Diff line number Diff line change
@@ -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<C extends Command> {
status: 'OK';
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -172,7 +175,7 @@ export class CommandQueueService {

this.activeCommand = command;

this.emulator.sendController(cmdStr + '\0');
this.emulator.sendPort(Port.Controller, cmdStr + '\0');
}

/**
Expand Down
30 changes: 10 additions & 20 deletions src/vm/emulator.service.ts
Original file line number Diff line number Diff line change
@@ -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();

Expand All @@ -12,11 +16,7 @@ export class EmulatorService {
@Output()
public resetOutputConsole = new EventEmitter<void>();
@Output()
public receivedOutputConsole = new EventEmitter<string>();
@Output()
public receivedOutputScreen = new EventEmitter<string>();
@Output()
public receivedOutputController = new EventEmitter<string>();
public receivedOutput = new EventEmitter<[Port, string]>();

private worker;

Expand All @@ -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);
Expand Down Expand Up @@ -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' });
}
Expand All @@ -94,7 +87,4 @@ export class EmulatorService {
data: new Uint8Array(content),
});
}
public resetTerminal() {
this.sendCommand({ command: 'resetTerminal' });
}
}
131 changes: 27 additions & 104 deletions src/vm/emulator.worker.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,31 @@
/// <reference lib="webworker" />
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;
Expand All @@ -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';
Expand Down Expand Up @@ -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<WorkerMsg>) => {
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': {
Expand Down Expand Up @@ -216,43 +165,17 @@ onmessage = ({ data: e }: MessageEvent<WorkerMsg>) => {
});
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)],
});
},
);
}

0 comments on commit 540ab5d

Please sign in to comment.