Full blown example.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -40,4 +40,6 @@ yarn-error.log*
|
|||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
*.gbc
|
*.gbc
|
||||||
|
|
||||||
|
/data
|
@ -66,7 +66,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const emulatorInit = data => {
|
const emulatorInit = data => {
|
||||||
EJS_gameUrl = data.game;
|
EJS_gameUrl = `/api/v1/rom?id=${data.gameId}`;
|
||||||
EJS_core = data.core;
|
EJS_core = data.core;
|
||||||
EJS_gameName = data.gameName;
|
EJS_gameName = data.gameName;
|
||||||
|
|
||||||
@ -88,34 +88,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { message } = data;
|
const { message } = data;
|
||||||
|
|
||||||
switch(message) {
|
switch(message) {
|
||||||
case 'init':
|
case 'init':
|
||||||
emulatorInit(data);
|
emulatorInit(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'volume':
|
||||||
|
EJS_emulator.setVolume(data.volume);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.error('Unknown message', message);
|
console.error('Unknown message', message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EJS_ready = (...args) => {
|
EJS_ready = () => {
|
||||||
send({ message: 'ready', data: args });
|
send({ message: 'ready' });
|
||||||
}
|
}
|
||||||
|
|
||||||
EJS_onSaveState = (...args) => {
|
EJS_onSaveState = () => {
|
||||||
send({ message: 'save', data: args });
|
send({ message: 'save' });
|
||||||
}
|
}
|
||||||
|
|
||||||
EJS_onLoadState = (...args) => {
|
EJS_onLoadState = () => {
|
||||||
send({ message: 'load', data: args });
|
send({ message: 'load' });
|
||||||
}
|
}
|
||||||
|
|
||||||
EJS_onGameStart = (...args) => {
|
EJS_onGameStart = () => {
|
||||||
send({ message: 'start', data: args });
|
send({ message: 'start' });
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<!-- <script src="https://cdn.emulatorjs.org/stable/data/loader.js"></script> -->
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -9,35 +9,40 @@ type EmulatorCore = (
|
|||||||
'gambatte' | 'mgba'
|
'gambatte' | 'mgba'
|
||||||
);
|
);
|
||||||
|
|
||||||
const EMULATOR_SYSTEM_CORES:{ [key in EmulatorSystem]:EmulatorCore } = {
|
type SendEmulatorMessageInit = {
|
||||||
'gb': 'gambatte',
|
message:'init';
|
||||||
'gbc': 'gambatte',
|
core:EmulatorCore;
|
||||||
'gba': 'mgba'
|
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 = {
|
export type EmulatorProps = {
|
||||||
system:EmulatorSystem;
|
system:EmulatorSystem;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SendEmulatorMessageInit = {
|
const EMULATOR_SYSTEM_CORES:{ [key in EmulatorSystem]:EmulatorCore } = {
|
||||||
message:'init';
|
'gb': 'gambatte',
|
||||||
core:EmulatorCore;
|
'gbc': 'gambatte',
|
||||||
system:EmulatorSystem;
|
'gba': 'mgba'
|
||||||
game:string;
|
};
|
||||||
gameName:string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type SendEmulatorMessage = (
|
|
||||||
SendEmulatorMessageInit
|
|
||||||
);
|
|
||||||
|
|
||||||
type ReceiveEmulatorOnGameStart = {
|
|
||||||
message:'start'
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReceiveEmulatorMessage = (
|
|
||||||
ReceiveEmulatorOnGameStart
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Emulator:React.FC<EmulatorProps> = props => {
|
export const Emulator:React.FC<EmulatorProps> = props => {
|
||||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||||
@ -55,7 +60,7 @@ export const Emulator:React.FC<EmulatorProps> = props => {
|
|||||||
message: 'init',
|
message: 'init',
|
||||||
core: EMULATOR_SYSTEM_CORES[props.system],
|
core: EMULATOR_SYSTEM_CORES[props.system],
|
||||||
system: props.system,
|
system: props.system,
|
||||||
game: '/test.gbc',
|
gameId: '0',
|
||||||
gameName: 'Pokemon - Crystal Version'
|
gameName: 'Pokemon - Crystal Version'
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -66,12 +71,12 @@ export const Emulator:React.FC<EmulatorProps> = props => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const msg = e.data as ReceiveEmulatorMessage;
|
const msg = e.data as ReceiveEmulatorMessage;
|
||||||
console.log('recv', msg);
|
|
||||||
switch(msg.message) {
|
switch(msg.message) {
|
||||||
case 'start':
|
case 'start':
|
||||||
console.log('Game started!');
|
case 'ready':
|
||||||
break
|
case 'load':
|
||||||
|
case 'save':
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('Invalid message received:', msg);
|
console.error('Invalid message received:', msg);
|
||||||
break
|
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>
|
<h1>Playing Game ID: {id}</h1>
|
||||||
|
|
||||||
<div className={styles.play__emulator}>
|
<div className={styles.play__emulator}>
|
||||||
<Emulator system='gbc' />
|
<Emulator
|
||||||
|
system='gbc'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user