Full blown example.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -40,4 +40,6 @@ yarn-error.log*
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
*.gbc
|
||||
*.gbc
|
||||
|
||||
/data
|
@ -66,7 +66,7 @@
|
||||
};
|
||||
|
||||
const emulatorInit = data => {
|
||||
EJS_gameUrl = data.game;
|
||||
EJS_gameUrl = `/api/v1/rom?id=${data.gameId}`;
|
||||
EJS_core = data.core;
|
||||
EJS_gameName = data.gameName;
|
||||
|
||||
@ -88,34 +88,35 @@
|
||||
}
|
||||
|
||||
const { message } = data;
|
||||
|
||||
switch(message) {
|
||||
case 'init':
|
||||
emulatorInit(data);
|
||||
break;
|
||||
|
||||
case 'volume':
|
||||
EJS_emulator.setVolume(data.volume);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error('Unknown message', message);
|
||||
}
|
||||
};
|
||||
|
||||
EJS_ready = (...args) => {
|
||||
send({ message: 'ready', data: args });
|
||||
EJS_ready = () => {
|
||||
send({ message: 'ready' });
|
||||
}
|
||||
|
||||
EJS_onSaveState = (...args) => {
|
||||
send({ message: 'save', data: args });
|
||||
EJS_onSaveState = () => {
|
||||
send({ message: 'save' });
|
||||
}
|
||||
|
||||
EJS_onLoadState = (...args) => {
|
||||
send({ message: 'load', data: args });
|
||||
EJS_onLoadState = () => {
|
||||
send({ message: 'load' });
|
||||
}
|
||||
|
||||
EJS_onGameStart = (...args) => {
|
||||
send({ message: 'start', data: args });
|
||||
EJS_onGameStart = () => {
|
||||
send({ message: 'start' });
|
||||
}
|
||||
|
||||
</script>
|
||||
<!-- <script src="https://cdn.emulatorjs.org/stable/data/loader.js"></script> -->
|
||||
</body>
|
||||
</html>
|
@ -9,35 +9,40 @@ type EmulatorCore = (
|
||||
'gambatte' | 'mgba'
|
||||
);
|
||||
|
||||
const EMULATOR_SYSTEM_CORES:{ [key in EmulatorSystem]:EmulatorCore } = {
|
||||
'gb': 'gambatte',
|
||||
'gbc': 'gambatte',
|
||||
'gba': 'mgba'
|
||||
type SendEmulatorMessageInit = {
|
||||
message:'init';
|
||||
core:EmulatorCore;
|
||||
system:EmulatorSystem;
|
||||
gameId:string;
|
||||
gameName:string;
|
||||
}
|
||||
|
||||
type SendEmulatorMessageVolume = {
|
||||
message:'volume';
|
||||
volume:number;
|
||||
};
|
||||
|
||||
type SendEmulatorMessage = (
|
||||
SendEmulatorMessageInit |
|
||||
SendEmulatorMessageVolume
|
||||
);
|
||||
|
||||
type ReceiveEmulatorMessage = (
|
||||
{ message: 'start' } |
|
||||
{ message: 'ready' } |
|
||||
{ message: 'save' } |
|
||||
{ message: 'load' }
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
const EMULATOR_SYSTEM_CORES:{ [key in EmulatorSystem]:EmulatorCore } = {
|
||||
'gb': 'gambatte',
|
||||
'gbc': 'gambatte',
|
||||
'gba': 'mgba'
|
||||
};
|
||||
|
||||
export const Emulator:React.FC<EmulatorProps> = props => {
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
@ -55,7 +60,7 @@ export const Emulator:React.FC<EmulatorProps> = props => {
|
||||
message: 'init',
|
||||
core: EMULATOR_SYSTEM_CORES[props.system],
|
||||
system: props.system,
|
||||
game: '/test.gbc',
|
||||
gameId: '0',
|
||||
gameName: 'Pokemon - Crystal Version'
|
||||
});
|
||||
|
||||
@ -66,12 +71,12 @@ export const Emulator:React.FC<EmulatorProps> = props => {
|
||||
}
|
||||
|
||||
const msg = e.data as ReceiveEmulatorMessage;
|
||||
console.log('recv', msg);
|
||||
switch(msg.message) {
|
||||
case 'start':
|
||||
console.log('Game started!');
|
||||
break
|
||||
|
||||
case 'ready':
|
||||
case 'load':
|
||||
case 'save':
|
||||
break;
|
||||
default:
|
||||
console.error('Invalid message received:', msg);
|
||||
break
|
||||
|
44
src/pages/api/v1/rom.ts
Normal file
44
src/pages/api/v1/rom.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { NextApiHandler } from "next";
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const PATH_ROMS = path.resolve('.', 'data', 'games');
|
||||
|
||||
const handler:NextApiHandler = async (req, res) => {
|
||||
if (req.method !== 'GET') {
|
||||
res.setHeader('Allow', ['GET']);
|
||||
res.status(405).end(`Method Not Allowed`);
|
||||
return;
|
||||
}
|
||||
|
||||
// ID query param
|
||||
if(!req.query.id || typeof req.query.id !== 'string') {
|
||||
res.status(404).end(`Not Found`);
|
||||
return;
|
||||
}
|
||||
|
||||
const { id } = req.query;
|
||||
if(!id) {
|
||||
res.status(404).end(`Not Found`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Does rom exist?
|
||||
const pathRom = path.resolve(PATH_ROMS, `${id}.bin`);
|
||||
if(!fs.existsSync(pathRom)) {
|
||||
res.status(404).end(`Not Found`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read rom
|
||||
try {
|
||||
const romStream = fs.createReadStream(pathRom);
|
||||
res.setHeader('Content-Type', 'application/octet-stream');
|
||||
res.setHeader('Content-Disposition', `attachment; filename="${id}.bin"`);
|
||||
romStream.pipe(res);
|
||||
} catch (error) {
|
||||
res.status(500).end(`Internal Server Error`);
|
||||
}
|
||||
};
|
||||
|
||||
export default handler;
|
@ -26,7 +26,9 @@ export const Page:React.FC<PageProps> = ({ id }) => {
|
||||
<h1>Playing Game ID: {id}</h1>
|
||||
|
||||
<div className={styles.play__emulator}>
|
||||
<Emulator system='gbc' />
|
||||
<Emulator
|
||||
system='gbc'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
Reference in New Issue
Block a user