import { h } from 'preact'; import cs from 'classnames'; import { useEffect, useMemo, useRef, useState } from 'preact/hooks'; import { Apple2 as Apple2Impl } from '../apple2'; import Apple2IO from '../apple2io'; import CPU6502 from '../cpu6502'; import { ControlStrip } from './ControlStrip'; import { ErrorModal } from './ErrorModal'; import { Inset } from './Inset'; import { Keyboard } from './Keyboard'; import { Mouse } from './Mouse'; import { Screen } from './Screen'; import { Drives } from './Drives'; import { Slinky } from './Slinky'; import { ThunderClock } from './ThunderClock'; import { noAwait, Ready } from './util/promises'; import styles from './css/Apple2.module.css'; /** * Interface for the Apple2 component. */ export interface Apple2Props { characterRom: string; enhanced: boolean; e: boolean; gl: boolean; rom: string; sectors: number; } /** * Component to bind various UI components together to form * the application layout. Includes the screen, drives, * emulator controls and keyboard. Bootstraps the core * Apple2 emulator. * * @param props Apple2 initialization props * @returns */ export const Apple2 = (props: Apple2Props) => { const { e, enhanced, sectors } = props; const screen = useRef(null); const [apple2, setApple2] = useState(); const [io, setIO] = useState(); const [cpu, setCPU] = useState(); const [error, setError] = useState(); const drivesReady = useMemo(() => new Ready(setError), []); useEffect(() => { if (screen.current) { const options = { canvas: screen.current, tick: () => { /* do nothing */ }, ...props, }; const apple2 = new Apple2Impl(options); noAwait((async () => { try { await apple2.ready; setApple2(apple2); setIO(apple2.getIO()); setCPU(apple2.getCPU()); await drivesReady.ready; apple2.reset(); apple2.run(); } catch (e) { setError(e); } }))(); } }, [props, drivesReady]); return (
); };