A browser-based retro emulator for playing legally owned NES and Game Boy Advance ROMs directly from a web page. It is built as a static GitHub Pages project with a clean desktop layout, mobile touch controls for NES, and selectable GBA engine support.
browser-emulator nes-emulator gba-emulator retro-gaming javascript html5-canvas webassembly emulatorjs mgba jsnes iodinegba github-pages
Suggested GitHub repository topics:
browser-emulator, nes-emulator, gba-emulator, retro-gaming, javascript, html5-canvas, webassembly, emulatorjs, mgba, jsnes, iodinegba, github-pages
Play here:
https://x1n-q.github.io/Web-Based-Emulator/
- NES support using jsNES.
- GBA support using EmulatorJS with the mGBA core by default.
- Optional standalone IodineGBA fallback from the GBA Engine selector.
- Local ROM loading from your device. No ROM files are hosted or included.
- Keyboard controls for NES with configurable mappings.
- Mobile NES touch controls below the game screen.
- EmulatorJS built-in saves, touch controls, and controller mapping for GBA.
- GBA browser-local progress saving with save/load state and save file export/import.
- Responsive layout for desktop, tablet, and phone screens.
- Static web app that can run on GitHub Pages.
| System | Status | ROM Extension | Main Engine |
|---|---|---|---|
| Nintendo Entertainment System | Working | .nes |
jsNES |
| Game Boy Advance | Working / experimental on mobile | .gba |
EmulatorJS with mGBA |
| Game Boy Advance fallback | Optional | Uses in-frame picker | IodineGBA standalone |
- jsNES: JavaScript NES emulator used for NES games. Upstream license: Apache-2.0.
- EmulatorJS: Browser emulator frontend used for GBA playback and built-in GBA controls. Upstream license: GPL-3.0.
- mGBA: GBA emulator core used by EmulatorJS. Upstream license: MPL-2.0.
- IodineGBA: Standalone JavaScript GBA emulator added as an optional fallback engine. Upstream license: MIT-style license.
- WebAssembly: Used by EmulatorJS/mGBA for better GBA performance.
- HTML5 Canvas: Used for NES rendering and the app display area.
- Web Audio API: Used by emulator engines for browser audio output.
- LocalStorage: Used to save local control settings.
- GitHub Pages: Hosts the static web app.
See THIRD_PARTY_NOTICES.md for attribution and license notes.
The default GBA option is EmulatorJS / mGBA. This is the recommended engine because it can use the ROM selected from the main file picker and includes its own touch/menu overlay.
For GBA progress after refreshing or closing the page, use EmulatorJS Save State and Load State. In-game battery saves are synced to browser storage about every 10 seconds. Saves are local to the current browser/device, so use Export Save File if you want a backup or want to move progress to another device.
The IodineGBA Standalone option is a fallback. Because it runs inside a separate embedded page, browser security does not allow this project to pass your local ROM file into it automatically. When using IodineGBA, use its own in-frame file picker to choose a game.
This repository is licensed under GPL-3.0 to stay compatible with the GPL-3.0 EmulatorJS code used by the GBA integration.
This project is not affiliated with Nintendo, EmulatorJS, mGBA, jsNES, IodineGBA, or any game publisher. It is a public web app that integrates and credits third-party emulator projects; it does not claim ownership of those upstream emulators.
If you fork or reuse this project:
- Keep the repository source public when distributing the project.
- Keep the GPL-3.0 license notice.
- Keep the third-party notices and credits.
- Do not remove upstream license notices from any copied or bundled third-party code.
- Do not include copyrighted ROMs.
- Open https://x1n-q.github.io/Web-Based-Emulator/
- Choose
Nintendo (NES)orGame Boy Advance (GBA). - Click
Choose File. - Select your legally owned
.nesor.gbaROM. - Play in the browser.
Browsers block some emulator features when opened with file://, so use a local web server.
git clone https://github.com/x1n-Q/Web-Based-Emulator.git
cd Web-Based-Emulator
python -m http.server 8000Then open:
http://localhost:8000
Other local server options:
npx http-server -p 8000
php -S localhost:8000| NES Button | Default Keys |
|---|---|
| D-Pad | Arrow keys or WASD |
| A | Z, J, or N |
| B | X, K, or M |
| Start | Enter or Space |
| Select | Shift or C |
NES controls can be changed in the built-in control settings panel. On phones and tablets, the NES touch pad appears below the screen.
GBA is handled by EmulatorJS by default. Use the in-game gear/menu overlay to configure controls, volume, fullscreen, save states, save files, and other EmulatorJS options.
Physical controllers/gamepads are handled by EmulatorJS. Connect the controller before loading a GBA ROM, then open the gamepad/settings menu if you need to remap buttons.
The custom lower touch pad is intentionally hidden for GBA so it does not conflict with EmulatorJS controls.
Web-Based-Emulator/
|-- index.html Main page and controls
|-- style.css Responsive layout and visual design
|-- main.js App startup and UI events
|-- emulator.js NES/GBA emulator manager
|-- controls.js Keyboard input handling
|-- touchControls.js NES mobile touch pad
|-- controlSettings.js Control remapping UI
|-- screenshot.png README screenshot
|-- CODE_OF_CONDUCT.md Community behavior rules
|-- CONTRIBUTING.md Contribution and fork guidelines
|-- THIRD_PARTY_NOTICES.md Third-party attribution and licenses
|-- LICENSE GPL-3.0 license
`-- README.md Project documentation
- Chrome / Edge recommended.
- Firefox supported.
- Safari supported, but mobile behavior may vary depending on iOS browser limits.
- For best GBA performance, use a modern browser with WebAssembly support.
- Make sure the selected system matches the ROM extension.
- NES expects
.nes. - GBA expects
.gba. - Try another legally owned ROM to confirm the file is not corrupted.
- Use the default EmulatorJS / mGBA engine first.
- Rotate the phone or scroll slightly if the screen needs more vertical space.
- If needed, try the IodineGBA standalone fallback from the GBA Engine selector.
- Use Save State before closing the page, then use Load State after loading the same ROM again.
- Quick Save and Quick Load are useful during the current play session, but Save State / Load State is the safer option for progress after refresh.
- For in-game saves, wait at least 10 seconds after saving so EmulatorJS can sync save data to browser storage.
- Do not clear browser site data unless you exported your save first.
- Use Export Save File for backups or moving progress to another browser/device.
- Connect the controller before loading the ROM.
- Press a button on the controller so the browser exposes it.
- Open the EmulatorJS gamepad/settings menu and remap buttons if needed.
- Try Chrome or Edge if the browser does not expose the controller correctly.
- Do not open the project with
file://. - Start a local server with
python -m http.server 8000. - Open
http://localhost:8000.
- Click or tap the game area once so the browser gives it focus.
- Check the browser's audio permission.
- For NES, review the control settings panel.
- For GBA, use the EmulatorJS gear/menu overlay.
This project does not include, host, or distribute ROM files. You must provide your own legally obtained ROMs.
- Do not upload or use copyrighted ROMs that you do not legally own.
- This project is intended for education, preservation, and personal use.
- Game copyrights belong to their respective owners.
- Emulator and library copyrights belong to their upstream authors.
- jsNES by Ben Firshman and contributors.
- EmulatorJS and its contributors.
- mGBA Team.
- IodineGBA by Grant Galitz and contributors.
- Emscripten/WebAssembly ecosystem.
- Browser APIs: HTML5 Canvas, Web Audio API, File API, and LocalStorage.
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.
Enjoy retro gaming in your browser.
