Initial commit.
This commit is contained in:
96
src/components/Emulator.tsx
Normal file
96
src/components/Emulator.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import styles from './Emulator.module.scss';
|
||||
|
||||
type EmulatorSystem = (
|
||||
'gb' | 'gbc' | 'gba'
|
||||
);
|
||||
|
||||
type EmulatorCore = (
|
||||
'gambatte' | 'mgba'
|
||||
);
|
||||
|
||||
const EMULATOR_SYSTEM_CORES:{ [key in EmulatorSystem]:EmulatorCore } = {
|
||||
'gb': 'gambatte',
|
||||
'gbc': 'gambatte',
|
||||
'gba': 'mgba'
|
||||
}
|
||||
|
||||
export type EmulatorProps = {
|
||||
system:EmulatorSystem;
|
||||
};
|
||||
|
||||
type SendEmulatorMessageInit = {
|
||||
message:'init';
|
||||
core:EmulatorCore;
|
||||
system:EmulatorSystem;
|
||||
game:string;
|
||||
gameName:string;
|
||||
}
|
||||
|
||||
type SendEmulatorMessage = (
|
||||
SendEmulatorMessageInit
|
||||
);
|
||||
|
||||
type ReceiveEmulatorOnGameStart = {
|
||||
message:'start'
|
||||
}
|
||||
|
||||
type ReceiveEmulatorMessage = (
|
||||
ReceiveEmulatorOnGameStart
|
||||
);
|
||||
|
||||
export const Emulator:React.FC<EmulatorProps> = props => {
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
const [ hasInit, setHasInit ] = useState(false);
|
||||
|
||||
const send = (msg:SendEmulatorMessage) => {
|
||||
iframeRef.current?.contentWindow?.postMessage(msg, '*');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if(hasInit) return;
|
||||
setHasInit(true);
|
||||
|
||||
send({
|
||||
message: 'init',
|
||||
core: EMULATOR_SYSTEM_CORES[props.system],
|
||||
system: props.system,
|
||||
game: '/test.gbc',
|
||||
gameName: 'Pokemon - Crystal Version'
|
||||
});
|
||||
|
||||
window.onmessage = (e) => {
|
||||
if(!e.data) {
|
||||
console.error('Invalid message received:', e.data);
|
||||
return;
|
||||
}
|
||||
|
||||
const msg = e.data as ReceiveEmulatorMessage;
|
||||
console.log('recv', msg);
|
||||
switch(msg.message) {
|
||||
case 'start':
|
||||
console.log('Game started!');
|
||||
break
|
||||
|
||||
default:
|
||||
console.error('Invalid message received:', msg);
|
||||
break
|
||||
}
|
||||
};
|
||||
}, [ iframeRef ]);
|
||||
|
||||
return (
|
||||
<div className={styles.emulator}>
|
||||
<div className={[
|
||||
styles.emulator__box,
|
||||
styles[`emulator__box--${props.system}`]
|
||||
].join(' ')} />
|
||||
|
||||
<iframe
|
||||
src="/emulator.html"
|
||||
className={styles.emulator__iframe}
|
||||
ref={iframeRef}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user