by OpenRAC contributors · v1.0.2 · 201 downloads
Gives a DualSense its own buttons as extra PlayStation 2 buttons, a light bar that shows Ratchet's health, and vibration when Ratchet is hit, hits something or picks something up.
Gives a PlayStation 5 DualSense what the PlayStation 2 never had, in OpenRAC's native port of Ratchet & Clank (PAL and NTSC-U).
The mod refuses to load when no DualSense is connected, and says so.
Install the mod from the launcher's Mods tab, switch it on, choose its settings and start the game.
Install the archive, not this folder. A native mod's library is named
by its manifest, and only the built manifest names it: the source folder
here has no plugin yet, because the library is not built until the
packaging. The port refuses a manifest with no library
("it has no library: data mods are packs"). Use either of:
dist/dualsense-1.0.0-linux-x86_64.zip;build/package/dualsense/;https://github.com/OpenRAC/rac1-mods, which
takes the release's archive.Connect a DualSense (a DualSense Edge works too) before the game starts. The mod looks for the controller when it loads and refuses without one.
On Linux the controller's raw device needs to be readable. If the port cannot see the controller at all, add a rule for it and reload the udev rules:
# /etc/udev/rules.d/70-dualsense.rules
KERNEL=="hidraw*", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0ce6", MODE="0660", TAG+="uaccess"
KERNEL=="hidraw*", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0df2", MODE="0660", TAG+="uaccess"
sudo udevadm control --reload-rules && sudo udevadm trigger
| Setting | Default | |
|---|---|---|
| Touchpad click | circle | What the touchpad's click does. Circle by default: the gadget fires, as it does with the button |
| Left paddle | triangle | What the DualSense Edge's left paddle does. Triangle by default: the Quick Select opens without lifting the thumb off the stick |
| Right paddle | square | What the DualSense Edge's right paddle does. Square by default: the wrench swings, and the hoverboard boosts |
| Microphone button | none | What the microphone button does. Nothing by default: L1 and R1 are read by the game as part of the free-look and crouch chords, so they are left alone |
| Vibration | on | Whether the controller vibrates |
| Vibration strength | 100 | How hard, in percent |
| Light bar | on | Whether the light bar shows the health |
Every button a setting can name: none, cross, square, circle,
triangle, l1, r1, l2, r2, select, start.
A binding adds to the button it names; it does not replace it. The touchpad is a second Circle, not the only one.
Each weapon has its own feel, and the mod gives it through the controller's motors. The game itself asks for no vibration at all — the retail program links no motor command — so all of this is the mod's own.
| Weapon | The feel |
|---|---|
| Walloper, Devastator | a heavy click: a stiff wall that snaps, then the shot |
| Bomb Glove, Visibomb Gun, Mine Glove, Glove of Doom, Decoy Glove | a lighter click |
| Blaster | a light rumble while it fires, and a kick with every shot |
| R.Y.N.O. | a heavy buzz through the whole seven-missile salvo, and a full rumble with every shot |
| Pyrocitor, Tesla Claw, Morph-o-Ray | a hum while it fires |
| Suck Cannon, Taunter, Drone Device | a steady low rumble while it fires |
The moments are the game's own, not the button's. The mod reads the hero's
fire-animation flag — set and cleared by nothing but the weapon code
(games/rac1/src/overlays/shared/help_0020CDF0.c:718 and :757) — so the
buzz runs exactly while the weapon is firing, and a kick lands on each shot
rather than on each press. The two weapons whose bodies are still assembly on
the PAL disc, the Visibomb Gun and the Taunter, are seen through the fire
button instead, and the Walloper through its own hero state.
The controller's right trigger is not used. Ratchet & Clank 1 fires with Circle, so the right trigger is free, and the mod leaves it alone: a pull there would disturb nothing the game reads.
Ratchet & Clank 1 asks for no vibration at all. The retail program links no
motor command: sceVibGetProfile is there, but the motor command beside it was
dead-stripped by the linker
(games/rac1/src/core/00125218.c: "sceVibSetActParam was dead-stripped").
The game keeps a waveform mixer that would have driven it
(games/rac1/src/game/actuator.c), but nothing calls it, and the in-game debug
menu still has an "Actuator" row that switches nothing on. The feature was
shelved before the game shipped.
So the port has nothing to restore, and the vibration here is made out of what the game does:
| What happened | Vibration |
|---|---|
| Ratchet was hit | a crack from the light motor, then a heavier thump under it |
| Ratchet hit something | a short thump |
| A crate broke, or a moby died | a soft thump |
| Ratchet picked something up | a short blip |
| Ratchet found a gold bolt | two blips, the second stronger |
| File | |
|---|---|
| src/dualsense.cpp | The mod: it finds the controller, takes the hooks, and writes the light bar and the vibration |
| src/ps2_pad.cpp, src/ps2_pad.hpp | The PlayStation 2's buttons and the report the game reads |
| src/rumble.cpp, src/rumble.hpp | The vibration: the envelope and the strengths the motors take |
| src/weapons.cpp, src/weapons.hpp | The weapons' feels, and what the game is doing with them |
| src/game_state.hpp | The hero's fields and where they are: the offsets, the PAL and NTSC-U bases, and the guard that keeps a pointer outside the game's RAM from being followed |
The controller is reached through SDL3, which the port already uses for
the pad. The mod links its own copy of SDL3, so it works with a port that has
SDL3 built in (the standalone preset, what the launcher ships) and with one
that uses the system's.
The mod reads the hero and the equipped weapon through the game's own
structure: the hero's base plus the offsets in hero.h, the same addresses the
port's host code and script binding use. The weapon slot's moby is a pointer
the game writes, so before following it to the weapon's counters the mod checks
that it — and the bytes after it — are inside the guest's 32 MB of RAM. A slot
the game has not filled yet is skipped, not followed: that is what the RAM
guard in src/game_state.hpp is for.
The extra buttons are written into the report the game reads, through the
port's pad report hook (rac1.pad.process_report). The report is active
low — a button that is held reads 0 — so the mod clears the bit of the
button it stands for.
The mod is built with the rest of this repository:
python3 tools/fetch_sdk.py # the SDK sdk.lock pins, into .sdk/
cmake -S . -B build -G Ninja
cmake --build build && ctest --test-dir build
It brings its own copy of SDL3, built static, so that it works with a port
that has SDL3 built in (the standalone preset, what the launcher ships) and
with one that uses the system's. SDL3 is fetched the first time, which takes a
few minutes; after that the build is quick.
For a quicker build, at the cost of the mod needing libSDL3 on the player's
machine:
cmake -S . -B build -G Ninja -DOPENRAC_DUALSENSE_SHARED_SDL=ON
ctest --test-dir build -R dualsense
Three more, for a machine that has a controller attached:
./build/dualsense/dualsense_probe # what the controller reports
./build/dualsense/dualsense_watch # the extra buttons, as they are pressed
./build/dualsense/dualsense_two_instances <the library> # two copies of SDL3, one controller
On a DualSense Wireless Controller (USB, 054c:0ce6, firmware 1584):
| SDL3 sees it | type PS5, vendor 054c, product 0ce6 |
| The touchpad's click | there, SDL reads it, and a press reached Circle in the game |
| The microphone button | there, and SDL reads it |
| The Edge's paddles | not on this controller, as expected: it is not an Edge. The binding then never fires, and nothing else changes |
| The light bar | the controller takes the colour (SDL_SetGamepadLED succeeds) |
| The motors | the controller takes the vibration (SDL_RumbleGamepad succeeds) |
| Two copies of SDL3 | the mod's own copy finds the controller while the port's copy holds it open, and the port's copy still works afterwards |
The touchpad's click was exercised in the game: with it bound to Circle, the press reached the game as Circle. The microphone button and the Edge's paddles were not pressed — there is no Edge on this machine, and the microphone button is bound to nothing by default. The wiring that carries any of them — the report the mod writes into, and the bit each button is read from — is covered by the logic test.
keyboard-mouse mod already turns the mouse into the camera.dualsenseNothing: it works on its own.
Built by the build workflow from 892c17401da544daf7efa229b5e672f892e2fe46, against the OpenRAC mod SDK 1.10.1.
Install: paste this repository's address in the OpenRAC launcher's Mods tab, or add a .zip there.
Built by the build workflow from 43f9c26b15074ccbf8db99851c93954e26cda211, against the OpenRAC mod SDK 1.3.0.
Install: paste this repository's address in the OpenRAC launcher's Mods tab, or add a .zip there.
Built by the build workflow from 04bb17e95718619219e4753af77ffc45a5b55515, against the OpenRAC mod SDK 1.3.0.
Install: paste this repository's address in the OpenRAC launcher's Mods tab, or add a .zip there.
DualSense · v1.0.2 · ⚠
Comments
No comments yet. Tried it? Say how it went.
Comment on GitHub