mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-27 15:11:01 +00:00
269 lines
8.3 KiB
TypeScript
269 lines
8.3 KiB
TypeScript
import React from "react";
|
|
import { Checkbox } from "./ui/checkbox";
|
|
import { Label } from "./ui/label";
|
|
|
|
import { Settings } from "@/settings";
|
|
import { TextTooltip } from "./text-tooltip";
|
|
import { ItemList } from "./item-list";
|
|
|
|
import {
|
|
Popover,
|
|
PopoverContent,
|
|
PopoverTrigger,
|
|
} from "@/components/ui/popover";
|
|
import { ChevronDown } from "react-bootstrap-icons";
|
|
import { Input } from "./ui/input";
|
|
import { RadioGroup, RadioGroupItem } from "./ui/radio-group";
|
|
|
|
interface SettingsMenuProps {
|
|
settings: Settings;
|
|
allowWasm64: boolean;
|
|
onChange: (settings: Settings) => void;
|
|
}
|
|
|
|
interface SettingsLabelProps {
|
|
htmlFor?: string | undefined;
|
|
text: React.ReactNode;
|
|
tooltip: React.ReactNode;
|
|
}
|
|
|
|
function SettingsLabel(props: SettingsLabelProps) {
|
|
return (
|
|
<Label htmlFor={props.htmlFor}>
|
|
<TextTooltip tooltip={props.tooltip}>{props.text}</TextTooltip>
|
|
</Label>
|
|
);
|
|
}
|
|
|
|
export class SettingsMenu extends React.Component<SettingsMenuProps, Settings> {
|
|
constructor(props: SettingsMenuProps) {
|
|
super(props);
|
|
this.getSettings = this.getSettings.bind(this);
|
|
this.state = props.settings;
|
|
}
|
|
|
|
getSettings() {
|
|
return this.state;
|
|
}
|
|
|
|
updateSettings(settings: Settings) {
|
|
this.setState(() => settings);
|
|
}
|
|
|
|
componentDidUpdate(_: SettingsMenuProps, oldSettings: Settings) {
|
|
if (JSON.stringify(oldSettings) !== JSON.stringify(this.state)) {
|
|
this.props.onChange(this.state);
|
|
}
|
|
}
|
|
|
|
updateArgv(commandLine: string) {
|
|
this.setState({ commandLine });
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<div className="grid gap-3">
|
|
<div className="space-y-2 mb-1">
|
|
<h4 className="font-medium leading-none">Settings</h4>
|
|
<p className="text-sm text-muted-foreground">
|
|
Set the settings for the emulation.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex gap-6 mb-2">
|
|
<RadioGroup
|
|
defaultValue="regular"
|
|
value={this.state.logging}
|
|
onValueChange={(value) => this.setState({ logging: value })}
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<RadioGroupItem value="regular" id="settings-regular" />
|
|
<SettingsLabel
|
|
htmlFor="settings-regular"
|
|
text={"Regular Logging"}
|
|
tooltip={
|
|
"Default logging behaviour, not too verbose, but also not very concise"
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center gap-4">
|
|
<RadioGroupItem value="verbose" id="settings-verbose" />
|
|
<SettingsLabel
|
|
htmlFor="settings-verbose"
|
|
text={"Verbose Logging"}
|
|
tooltip={
|
|
"Very detailed logging of all function calls and accesses"
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center gap-4">
|
|
<RadioGroupItem value="concise" id="settings-concise" />
|
|
<SettingsLabel
|
|
htmlFor="settings-concise"
|
|
text={"Concise Logging"}
|
|
tooltip={"Suppress logging until the application code runs"}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center gap-4">
|
|
<RadioGroupItem value="silent" id="settings-silent" />
|
|
<SettingsLabel
|
|
htmlFor="settings-silent"
|
|
text={"Silent Logging"}
|
|
tooltip={"Suppress all logging except for stdout"}
|
|
/>
|
|
</div>
|
|
</RadioGroup>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<Checkbox
|
|
id="settings-buffer"
|
|
checked={this.state.bufferStdout}
|
|
onCheckedChange={(checked: boolean) => {
|
|
this.setState({ bufferStdout: checked });
|
|
}}
|
|
/>
|
|
<SettingsLabel
|
|
htmlFor="settings-buffer"
|
|
text={"Buffer stdout"}
|
|
tooltip={
|
|
"Group stdout and print everything when the emulation ends"
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<Checkbox
|
|
id="settings-exec"
|
|
checked={this.state.execAccess}
|
|
onCheckedChange={(checked: boolean) => {
|
|
this.setState({ execAccess: checked });
|
|
}}
|
|
/>
|
|
<SettingsLabel
|
|
htmlFor="settings-exec"
|
|
text={"Log exec Memory Access"}
|
|
tooltip={"Log when the application reads/writes executable memory"}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<Checkbox
|
|
id="settings-foreign"
|
|
checked={this.state.foreignAccess}
|
|
onCheckedChange={(checked: boolean) => {
|
|
this.setState({ foreignAccess: checked });
|
|
}}
|
|
/>
|
|
<SettingsLabel
|
|
htmlFor="settings-foreign"
|
|
text={"Log Foreign Access"}
|
|
tooltip={
|
|
"Log when the application reads/writes memory of other modules"
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<Checkbox
|
|
id="settings-summary"
|
|
checked={this.state.instructionSummary}
|
|
onCheckedChange={(checked: boolean) => {
|
|
this.setState({ instructionSummary: checked });
|
|
}}
|
|
/>
|
|
<SettingsLabel
|
|
htmlFor="settings-summary"
|
|
text={"Print Instruction Summary"}
|
|
tooltip={"Print summary of executed instructions"}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<Checkbox
|
|
id="settings-persist"
|
|
checked={this.state.persist}
|
|
onCheckedChange={(checked: boolean) => {
|
|
this.setState({ persist: checked });
|
|
}}
|
|
/>
|
|
<SettingsLabel
|
|
htmlFor="settings-persist"
|
|
text={"Persist Filesystem"}
|
|
tooltip={
|
|
"Persist files and folders that were created, modified or deleted during the emulation"
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<Checkbox
|
|
id="settings-mem64"
|
|
disabled={!this.props.allowWasm64}
|
|
checked={this.state.wasm64}
|
|
onCheckedChange={(checked: boolean) => {
|
|
this.setState({ wasm64: checked });
|
|
}}
|
|
/>
|
|
<SettingsLabel
|
|
htmlFor="settings-mem64"
|
|
text={"64-Bit WebAssembly"}
|
|
tooltip={
|
|
"Use 64-bit WebAssembly which supports emulating applications that require more than 2gb of memory"
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-6 my-2">
|
|
<Input
|
|
id="settings-argv"
|
|
placeholder="Command-Line Arguments"
|
|
value={this.state.commandLine}
|
|
onChange={(e) => this.updateArgv(e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<Popover>
|
|
<PopoverTrigger>
|
|
<TextTooltip tooltip="Don't log executions of listed functions">
|
|
<div className="flex items-center mb-2">
|
|
<Label className="flex-1 text-left cursor-pointer">
|
|
Ignored Functions
|
|
</Label>
|
|
<ChevronDown />
|
|
</div>
|
|
</TextTooltip>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="shadow-2xl">
|
|
<ItemList
|
|
title="Ignored Functions"
|
|
items={this.state.ignoredFunctions}
|
|
onChange={(items) => this.setState({ ignoredFunctions: items })}
|
|
/>
|
|
</PopoverContent>
|
|
</Popover>
|
|
|
|
<Popover>
|
|
<PopoverTrigger>
|
|
<TextTooltip tooltip="Log interactions of additional modules">
|
|
<div className="flex items-center mb-1">
|
|
<Label className="flex-1 text-left cursor-pointer">
|
|
Interesting Modules
|
|
</Label>
|
|
<ChevronDown />
|
|
</div>
|
|
</TextTooltip>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="shadow-2xl">
|
|
<ItemList
|
|
title="Interesting Modules"
|
|
items={this.state.interestingModules}
|
|
onChange={(items) => this.setState({ interestingModules: items })}
|
|
/>
|
|
</PopoverContent>
|
|
</Popover>
|
|
</div>
|
|
);
|
|
}
|
|
}
|