If you've ever tried running PS1 games on EmulatorJS, you've probably noticed something… missing. Out of the box, EmulatorJS doesn't map L1/L2/R1/R2 in its touch overlay for the PSX core. That's fine for some titles, but the moment you boot anything like Resident Evil 2, those shoulders suddenly matter a lot. Google around and most posts say the same thing: "Use a Bluetooth gamepad." That's a great option—until you're on a phone, on the couch, with no controller in sight.
So I built a drop-in helper, psxcontrol.js
, to fix the overlay and make it pleasant to use on touch screens. No forks, no custom builds—just a tiny script that tells EmulatorJS how to draw the virtual pad for PSX and then cleans up the styling so it looks and feels right.
What psxcontrol.js does (under the hood)
1) Defines a full PSX touch layout (including shoulders).
Before EmulatorJS's loader runs, the script sets window.EJS_VirtualGamepadSettings
with a complete control map:
2) Makes the overlay look consistent across browsers.
Different devices render fonts differently, which can distort the face-button symbols. The script injects Google Fonts dynamically (no <link>
tags needed), then locks the overlay to "Noto Sans Symbols 2" for the icons and "Noto Sans" for labels. Result: △/○/✕/□ look crisp and uniform on iOS, Android, and desktop.
3) Styles the buttons so they're readable and thumb-friendly.
A small styling engine runs after the emulator draws the overlay and:
4) Survives fullscreen toggles, orientation changes, and re-renders.
EmulatorJS can redraw the virtual pad when you rotate, go fullscreen, or change states. psxcontrol.js
uses a MutationObserver plus resize
/orientationchange
listeners to re-apply styles and placement automatically, so you don't end up with drifting buttons after a rotation.
5) Leaves your page markup alone.
Everything is done in JS—no HTML edits, no extra CSS files. The script politely waits for the overlay to exist, then enhances what EmulatorJS already created. If a device doesn't render the touch overlay (e.g., desktop with a mouse), the script effectively no-ops.
Why map the left side to the D-Pad?
Resident Evil and tons of early PS1 titles were built around D-Pad movement, not feather-touch analog sticks. The left "stick" that psxcontrol.js
adds is actually a zone that emits Up/Down/Left/Right—which is exactly what those games expect—while still feeling like a thumbstick on touch. You get reliable, predictable movement and cleaner diagonals without fussing with sensitivity curves.
The result: a clean, familiar PSX overlay
After you drop the script in, you'll see:
It feels like playing PS1 on a modern phone UI—because that's exactly what it is.
How to use it
You don't need to modify your HTML beyond adding a single script tag. Place it near the end of your page, so it's available before the EmulatorJS loader initializes the core:
That's it. If you prefer to self-host, download that file and serve it from your own domain:
Notes:
window.EJS_VirtualGamepadSettings
is already set).<link>
tags—the script injects them and waits until they're available.If you've been told "just use a gamepad," totally fair—that's still the best tactile experience. But when you don't have one handy, psxcontrol.js
gives you a practical, polished touch layout with proper PSX shoulders and readable face buttons. And yes, it plays Resident Evil 2 beautifully.
Comments