diff --git a/src/less/status.less b/src/less/status.less
index 425df3e..b19cd49 100644
--- a/src/less/status.less
+++ b/src/less/status.less
@@ -1,8 +1,19 @@
+#status-hotzone {
+ position: absolute;
+ z-index: 99;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 8px;
+}
+
#status {
user-select: none;
position: absolute;
z-index: 100;
- left: calc(50vw - 110px);
+ left: 50vw;
+ transform: translateX(-50%);
+ white-space: nowrap;
background: white;
font-size: 10px;
padding-bottom: 3px;
@@ -13,4 +24,14 @@
padding-right: 10px;
max-height: 18px;
top: 0;
+ transition: transform 0.12s ease-out;
+
+ &.hidden {
+ transform: translateX(-50%) translateY(-100%);
+ }
+}
+
+#status-hotzone:hover + #status.hidden,
+#status.hidden:hover {
+ transform: translateX(-50%) translateY(0);
}
diff --git a/src/renderer/emulator-info.tsx b/src/renderer/emulator-info.tsx
index 988dd08..e7d8535 100644
--- a/src/renderer/emulator-info.tsx
+++ b/src/renderer/emulator-info.tsx
@@ -3,11 +3,15 @@ import * as React from "react";
interface EmulatorInfoProps {
toggleInfo: () => void;
emulator: any;
+ hidden: boolean;
}
interface EmulatorInfoState {
cpu: number;
- disk: string;
+ diskRead: number;
+ diskWrite: number;
+ netRx: number;
+ netTx: number;
lastCounter: number;
lastTick: number;
}
@@ -16,33 +20,49 @@ export class EmulatorInfo extends React.Component<
EmulatorInfoProps,
EmulatorInfoState
> {
- private cpuInterval = -1;
+ private tickInterval = -1;
+ private diskReadBytes = 0;
+ private diskWriteBytes = 0;
+ private netRxBytes = 0;
+ private netTxBytes = 0;
constructor(props: EmulatorInfoProps) {
super(props);
- this.cpuCount = this.cpuCount.bind(this);
- this.onIDEReadStart = this.onIDEReadStart.bind(this);
- this.onIDEReadWriteEnd = this.onIDEReadWriteEnd.bind(this);
+ this.tick = this.tick.bind(this);
+ this.onIDEReadEnd = this.onIDEReadEnd.bind(this);
+ this.onIDEWriteEnd = this.onIDEWriteEnd.bind(this);
+ this.onEthReceiveEnd = this.onEthReceiveEnd.bind(this);
+ this.onEthTransmitEnd = this.onEthTransmitEnd.bind(this);
this.state = {
cpu: 0,
- disk: "Idle",
+ diskRead: 0,
+ diskWrite: 0,
+ netRx: 0,
+ netTx: 0,
lastCounter: 0,
lastTick: 0,
};
}
public render() {
- const { cpu, disk } = this.state;
+ const { cpu, diskRead, diskWrite, netRx, netTx } = this.state;
+ const { hidden, toggleInfo } = this.props;
return (
-
- Disk:
{disk} | CPU Speed:
{cpu} |{" "}
-
- Hide
-
-
+ <>
+
+
+ CPU:
{cpu}M/s | Disk:{" "}
+
R {this.rate(diskRead)}{" "}
+
W {this.rate(diskWrite)} | Net:{" "}
+
↓{this.rate(netRx)} ↑{this.rate(netTx)} |{" "}
+
+ {hidden ? "Pin" : "Hide"}
+
+
+ >
);
}
@@ -79,21 +99,17 @@ export class EmulatorInfo extends React.Component<
return;
}
- // CPU
- if (this.cpuInterval > -1) {
- clearInterval(this.cpuInterval);
+ if (this.tickInterval > -1) {
+ clearInterval(this.tickInterval);
}
// TypeScript think's we're using a Node.js setInterval. We're not.
- this.cpuInterval = setInterval(this.cpuCount, 500) as unknown as number;
+ this.tickInterval = setInterval(this.tick, 500) as unknown as number;
- // Disk
- emulator.add_listener("ide-read-start", this.onIDEReadStart);
- emulator.add_listener("ide-read-end", this.onIDEReadWriteEnd);
- emulator.add_listener("ide-write-end", this.onIDEReadWriteEnd);
-
- // Screen
- emulator.add_listener("screen-set-size-graphical", console.log);
+ emulator.add_listener("ide-read-end", this.onIDEReadEnd);
+ emulator.add_listener("ide-write-end", this.onIDEWriteEnd);
+ emulator.add_listener("eth-receive-end", this.onEthReceiveEnd);
+ emulator.add_listener("eth-transmit-end", this.onEthTransmitEnd);
}
/**
@@ -109,58 +125,67 @@ export class EmulatorInfo extends React.Component<
return;
}
- // CPU
- if (this.cpuInterval > -1) {
- clearInterval(this.cpuInterval);
+ if (this.tickInterval > -1) {
+ clearInterval(this.tickInterval);
}
- // Disk
- emulator.remove_listener("ide-read-start", this.onIDEReadStart);
- emulator.remove_listener("ide-read-end", this.onIDEReadWriteEnd);
- emulator.remove_listener("ide-write-end", this.onIDEReadWriteEnd);
+ emulator.remove_listener("ide-read-end", this.onIDEReadEnd);
+ emulator.remove_listener("ide-write-end", this.onIDEWriteEnd);
+ emulator.remove_listener("eth-receive-end", this.onEthReceiveEnd);
+ emulator.remove_listener("eth-transmit-end", this.onEthTransmitEnd);
+ }
- // Screen
- emulator.remove_listener("screen-set-size-graphical", console.log);
+ private onIDEReadEnd(args: number[]) {
+ this.diskReadBytes += args[1];
+ }
+
+ private onIDEWriteEnd(args: number[]) {
+ this.diskWriteBytes += args[1];
+ }
+
+ private onEthReceiveEnd(args: number[]) {
+ this.netRxBytes += args[0];
+ }
+
+ private onEthTransmitEnd(args: number[]) {
+ this.netTxBytes += args[0];
}
/**
- * The virtual IDE is handling read (start).
+ * Format bytes/sec into a compact human string.
*/
- private onIDEReadStart() {
- this.requestIdle(() => this.setState({ disk: "Read" }));
+ private rate(bytesPerSec: number) {
+ if (bytesPerSec <= 0) return "0";
+ if (bytesPerSec < 1024) return `${bytesPerSec}B/s`;
+ if (bytesPerSec < 1024 * 1024) return `${Math.round(bytesPerSec / 1024)}K/s`;
+ return `${(bytesPerSec / 1024 / 1024).toFixed(1)}M/s`;
}
/**
- * The virtual IDE is handling read/write (end).
+ * Once per interval, compute CPU speed and I/O throughput.
*/
- private onIDEReadWriteEnd() {
- this.requestIdle(() => this.setState({ disk: "Idle" }));
- }
-
- /**
- * Request an idle callback with a 3s timeout.
- *
- * @param fn
- */
- private requestIdle(fn: () => void) {
- (window as any).requestIdleCallback(fn, { timeout: 3000 });
- }
-
- /**
- * Calculates what's up with the virtual cpu.
- */
- private cpuCount() {
+ private tick() {
const { lastCounter, lastTick } = this.state;
const now = Date.now();
const instructionCounter = this.props.emulator.get_instruction_counter();
const ips = instructionCounter - lastCounter;
const deltaTime = now - lastTick;
+ const deltaSec = deltaTime / 1000;
this.setState({
lastTick: now,
lastCounter: instructionCounter,
- cpu: Math.round(ips / deltaTime),
+ cpu: Math.round(ips / deltaTime / 1000),
+ diskRead: Math.round(this.diskReadBytes / deltaSec),
+ diskWrite: Math.round(this.diskWriteBytes / deltaSec),
+ netRx: Math.round(this.netRxBytes / deltaSec),
+ netTx: Math.round(this.netTxBytes / deltaSec),
});
+
+ this.diskReadBytes = 0;
+ this.diskWriteBytes = 0;
+ this.netRxBytes = 0;
+ this.netTxBytes = 0;
}
}
diff --git a/src/renderer/emulator.tsx b/src/renderer/emulator.tsx
index ac24bec..e3ad3ad 100644
--- a/src/renderer/emulator.tsx
+++ b/src/renderer/emulator.tsx
@@ -271,13 +271,10 @@ export class Emulator extends React.Component<{}, EmulatorState> {
* Render the little info thingy
*/
public renderInfo() {
- if (!this.state.isInfoDisplayed) {
- return null;
- }
-
return (
{
this.setState({ isInfoDisplayed: !this.state.isInfoDisplayed });
}}