diff --git a/.gitignore b/.gitignore index f46d981..4dfb44f 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,6 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts -*.gbc \ No newline at end of file +*.gbc + +/data \ No newline at end of file diff --git a/public/emulator.html b/public/emulator.html index c7a1028..b7af0d7 100644 --- a/public/emulator.html +++ b/public/emulator.html @@ -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' }); } - - \ No newline at end of file diff --git a/src/components/Emulator.tsx b/src/components/Emulator.tsx index 0cebdc2..25bb5cf 100644 --- a/src/components/Emulator.tsx +++ b/src/components/Emulator.tsx @@ -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 = props => { const iframeRef = useRef(null); @@ -55,7 +60,7 @@ export const Emulator:React.FC = 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 = 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 diff --git a/src/pages/api/v1/rom.ts b/src/pages/api/v1/rom.ts new file mode 100644 index 0000000..d5d487d --- /dev/null +++ b/src/pages/api/v1/rom.ts @@ -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; \ No newline at end of file diff --git a/src/pages/games/[id]/play.tsx b/src/pages/games/[id]/play.tsx index 81b7ef0..6148a43 100644 --- a/src/pages/games/[id]/play.tsx +++ b/src/pages/games/[id]/play.tsx @@ -26,7 +26,9 @@ export const Page:React.FC = ({ id }) => {

Playing Game ID: {id}

- +
);