-
Notifications
You must be signed in to change notification settings - Fork 0
Development
By hooking certain functions, remotePad makes the game believe that additional controllers are connected to your console. It simulates the behavior of real controllers by transmitting controller data via WebSocket or USB.
---
config:
look: handDrawn
---
flowchart TB
subgraph s1["Clients"]
n6["Web"]
n7["..."]
end
n2["Game"] <--> n3["RemotePad"]
n3 <--> n1["PS4 System"] & s1
n6@{ shape: rounded}
n7@{ shape: rounded}
n2@{ shape: rounded}
n3@{ shape: rounded}
n1@{ shape: rounded}
style n2 stroke:#000000,fill:transparent
style n1 fill:transparent,stroke:#000000
remotePad uses JSON-RPC over WebSocket as its communication protocol and provides a simple webpage by default to simulate a controller.
Here is an example of a WebSocket message. You can use any WebSocket-enabled client to send this message to simulate a controller:
{"method":"u","params":[0,0,128,128,128,128,0,0,0]}The 9 numbers in the params array represent:
| No. | Item | Description |
|---|---|---|
| 1 | Controller Index | 0, 1, 2, 3 |
| 2 | Controller Button Values | Refer to orbis/_types/pad.h. If multiple buttons are pressed simultaneously, add their values together. |
| 3 | Left Stick's X Coordinate | Range: 0~255, with 0 representing the left position. |
| 4 | Left Stick's Y Coordinate | Range: 0~255, with 0 representing the top position. |
| 5 | Right Stick's X Coordinate | Range: 0~255, with 0 representing the left position. |
| 6 | Right Stick's Y Coordinate | Range: 0~255, with 0 representing the top position. |
| 7 | L2 Button Pressing State | Range: 0~255, with 0 representing not pressed and 255 representing fully pressed. |
| 8 | R2 Button Pressing State | Range: 0~255, with 0 representing not pressed and 255 representing fully pressed. |
| 9 | Touch Data Count | Range: 0~2. When the count is 0, it indicates no touch. When the count is N, it is followed by N sets of touch data. Each set of touch data consists of three numbers: touch ID (0~127), X coordinate (0~1919), and Y coordinate (0~941). |
Note: When pressing trigger buttons (L2/R2), you need to set the controller button values simultaneously; otherwise, the game might not recognize it correctly.
Display a system notification on the PS4.
{"method":"notify","params":["hello world"]}To obtain information about the plugin, you can retrieve details such as the current plugin version after establishing the connection.
- sent to server
{"id": 1, "method":"info","params":[]}- received from server
{"id": 1, "result": {"version": "1.2.0"} }It is recommended to set a timeout for each data to avoid the inability to stop the vibration due to packet loss.
- received from server
{"method":"v","params":[0, 0, 0]}The three numbers in the params array represent:
Controller index (0,1,2,3), Vibration for the large motor (0-255), Vibration for the small motor (0-255)
- received from server
{"method":"l","params":[0, 0, 0, 0]}The four numbers in the params array represent:
Controller index (0,1,2,3), R, G, B
- received from server
{"method":"rl","params":[0]}The number in the params array represent:
Controller index (0,1,2,3)
When a request to reset the controller's light bar color is received, restore the light bar to its default color. 0 for Blue, 1 for Red, 2 for Green, and 3 for Pink
Now you can easily create a RemotePad client on devices like the Switch, PS Vita, 3DS, etc., or modify the existing web client to implement some interesting control methods. Feel free to submit an issue to share your creations with the community.
remotePad separates the protocol part into what it calls a "driver." You can easily implement a new driver to adapt to other protocols. Here's an example:
For instance, if you want to implement a UDP-based protocol to minimize controller latency as much as possible:
- Copy
src/pad/dummy.ctosrc/pad/udp.c. - Rename the
dummyDrivervariable toudpDriver. Similarly, change other function names to have audpprefix. - Implement your UDP service in the
udpInitfunction. (Note that you need to create a new thread to run the UDP service.) - Refer to
ws.cto implement the remaining functions. - Add your
udpDriverto thepadDriverslist inpad.c. - Configure
remote_pad.inito use your driver.
Note1: You don't need to implement every function. All unimplemented functions will default to calling the corresponding functions in the dummy driver. For example, you don't need to implement read and readState, but simply call pushPadData(...) when gamepad data comes. This makes the implementation of the new driver much simpler. Basically, you only need to write the code related to communication.
Note2: All functions that need to be implemented may be called by different threads, but other parts of remotePad ensure that they are mutually exclusive. You don't need to set up mutexes yourself.