From 252e26d2b7a4e5d48dcfa4101191c9dd63f27b2e Mon Sep 17 00:00:00 2001
From: MoHadiShibli <142665133+MoHadiShibli@users.noreply.github.com>
Date: Fri, 9 Oct 2026 21:13:37 +0300
Subject: [PATCH] Finalize Control4Free 1.2.0 fixes and release documentation
---
CHANGELOG.md | 31 ++++---
CONTRIBUTING.md | 16 ++--
README.md | 18 ++--
SECURITY.md | 9 +-
client/index.html | 30 +++++--
docs/gamepad-mapping.md | 80 ++++++++++++++---
docs/how-it-works.md | 10 ++-
docs/images/controller.png | Bin 1396662 -> 1398213 bytes
docs/images/desktop.png | Bin 550384 -> 516074 bytes
docs/images/home.png | Bin 1175357 -> 1218821 bytes
docs/images/launcher.png | Bin 860371 -> 860563 bytes
docs/images/mapping-inputs.png | Bin 0 -> 574453 bytes
docs/images/mapping.png | Bin 0 -> 506959 bytes
docs/installation.md | 5 +-
docs/playing.md | 10 ++-
docs/protocol.md | 14 ++-
docs/troubleshooting.md | 48 +++++++++-
include/c4f_sce.h | 5 ++
include/c4f_vda.h | 4 +
src/vda.c | 17 ++++
src/web.c | 63 ++++++++++++-
tests/browser_test.cjs | 160 ++++++++++++++++++++++++++++++++-
tests/fake_gamepads_test.cjs | 2 +-
tests/test_web.py | 115 ++++++++++++++++++++++++
tests/web_stub.c | 55 +++++++++++-
25 files changed, 627 insertions(+), 65 deletions(-)
create mode 100644 docs/images/mapping-inputs.png
create mode 100644 docs/images/mapping.png
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab35a87..e41e175 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,33 +3,38 @@
Versions follow [Semantic Versioning](https://semver.org): PATCH for fixes, MINOR for features that break
nothing, MAJOR for anything people rely on that changes.
-## 1.2.0 — 2026-10-08
+## 1.2.0 — 2026-10-09
Gamepad mapping.
-- Map a gamepad on a picture of a DualShock 4: each control shows what drives it and lights up when pressed.
- Click a control, then press the gamepad button for it. It works for gamepads the browser doesn't know, and
- for wheels, guitars, pedals and arcade sticks, as DualShock 4 buttons, sticks and triggers. Sticks and
- triggers show their position with a dead zone and a curve. **Everything it sends** shows every button and
+- Map a gamepad on a DualShock 4: each control shows what drives it and lights up when pressed.
+ Click a control, then press the gamepad button for it. Map browser-exposed inputs from gamepads, wheels,
+ guitars, pedals and arcade sticks to DualShock 4 buttons, sticks and triggers. Wheel and guitar model
+ compatibility remains unverified, and native accessory identity is not provided. Sticks and
+ triggers show their position with a dead zone and a curve. **Gamepad Controls** shows every button and
axis live, and sets an axis's range a step at a time. See [Gamepad mapping](docs/gamepad-mapping.md).
-- Keyboard keys are chosen on the same picture.
-- Mappings are saved as profiles in the browser, used for every gamepad of the same kind, and can be exported
- to a file and imported on another device.
+- Keyboard keys are chosen on the same screen.
+- Mappings are saved as named profiles in the browser. Save updates every connected gamepad using that
+ profile; Save as new gives the selected gamepad a separate profile. Profiles can be exported to a file
+ and imported on another device for review before saving.
- Several gamepads can play as the same controller, for example a wheel and its pedals.
-- A button still held when a gamepad starts playing does nothing until it's let go.
- A phone that drops off the network no longer keeps a connection to the PS4 open for ever. Before, enough of
those could stop new phones and computers from opening the page.
- When two people pick controllers at the same moment, one is asked to try again, instead of one taking the
other's controller.
- A controller the console refused input for recovers once it accepts input again.
-- The page only asks for the PS4's address when it was saved to the device and opened from there.
-- The address box takes a full address, such as `http://192.168.1.20:4264/`, and adds `:4264` when it's
- missing.
+- Signing out of a PS4 user disconnects their virtual controllers and clears their names and browser
+ selections. Other signed-in players stay connected.
+- The mapping header aligns its controls, and gamepad rows group the device name, controller choice and
+ Mapping button. The PS button uses the PlayStation mark and shows press feedback.
+- Documented a Windows GameInput workaround for Xbox buttons crossing gamepads in affected Chrome/Edge
+ builds. A two-controller Chrome/Windows 11 test confirmed it; it is not a general requirement. See
+ [Gamepad troubleshooting](docs/troubleshooting.md#gamepads).
- A touch on the touchpad that the browser cancels no longer clicks it.
- Keys with Ctrl, Alt or the Windows key can't be chosen any more: they never worked in play.
- The app on the PS4 says when the Control4Free running is a different version from the app, and how to switch.
It tells a missing auto-start copy apart from auto-start being off.
-- The service's log stays under 2 MB, however long it runs.
+- Active service logs are bounded to two 1 MiB files. The last segment of the previous run is kept separately.
- The diagnostic app says whether it managed to save its report.
## 1.1.1 — 2026-10-07
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index aefc964..308ad38 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,7 +11,7 @@ details:
- the phone or computer and browser you used;
- what you did and what happened;
- the service's log, if you can get it: `/data/control4free/control4free.log` on the PS4, over GoldHEN's FTP
- server (port 2121). The previous run is kept in `control4free.log.previous`.
+ server (port 2121). The last segment of the previous run is kept in `control4free.log.previous`.
The log contains your console's network address. Remove it before posting if you prefer.
@@ -78,10 +78,16 @@ Build without new warnings; the app is built with `-Werror`.
## Releasing
-1. Update `VERSION`, and add a section to `CHANGELOG.md`.
-2. Commit, tag `vX.Y.Z`, and push the tag.
-3. CI builds both images, runs the tests, and publishes the release with the ELF, the package and
- `SHA256SUMS`. It refuses a tag that doesn't match `VERSION`.
+1. Update `VERSION` and the changelog's release date and notes. Review mapping, compatibility and
+ diagnostic documentation; distinguish hardware reports from emulated-input tests.
+2. Run all five Docker host suites and the browser/editor and emulated-gamepad checks. Build normal and
+ diagnostic packages without new warnings. Inspect launcher previews and browser layouts.
+3. Validate standard controllers on real hardware: simultaneous devices, source mixing, rumble,
+ reconnect, logout and rest/wake. Recheck firmware 10.01 and a modern tested firmware, and record the
+ results. Wheel/guitar model compatibility remains unverified until device reports establish it.
+4. Commit, tag `vX.Y.Z`, and push the tag when the release gates pass.
+5. CI checks the tag against `VERSION` and publishes `control4free.elf`, the normal package, the diagnostic
+ package and `SHA256SUMS`. Release-note documentation links point to that tag.
## Reviewing AI-written code
diff --git a/README.md b/README.md
index a29db17..52edc03 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
d1V7`k+sn1K9vQ!E?|
z$X0|NkJW@7rt~_t1MsX&Xqm-Qx>51mA`u+E8sx`}M2niyRPsKmuW1i~udZC&OF{#o
zdSTp=XevZ05ZcKz$4l9ynAn0xiV&obC@w@r@xm*^jx6&9um-7uV@p!P@G&_KeGGGu
zI^7{v21b7djiE%~2sK8bBQ^60t)hyvb|De!bxe>^FdU(!Vs3Q LI4c&*
zqWG5nhsFFaNhr?m*^I5wT21I+{*qZz8#x<@93ZV)qAs1wN_~sx9y7wAS%BH|lcRBL
zDFWrsz3|HSe(+D8xc>O~%xbmz@aCNlKDY@2*0Wu1EmwX3btzBT(vO%fS2og&VVaFJ
z{g{CV<`7|>hrfF<#PdnYUqd #Rv_;)e~&!H_ddmc94%4jBl@t+SbWPEH3f(rFlv#|&g=fCm6PFwJ;nBYin$;F26Z`tIJ|
z?nYN+BmaLsGxwuPSknkk>Yj={ZAYd1dwZ|E`t{}Z{>=~G>n9UT%a~T@$CHsSx5(H4
z;1`W>_FZCmv!=fAQ7vqKBP3!q*9%I9{6*(|vjD16oT9O2@e>obsC!jUQsawa!P~_o
z6=Xn{l#)pdnfgNG2-9}V-4>EzseqPr<4(#FJ+&;K09G&X=@Syb()}-c#t=z@#
z6m=PFolj)8B(8PJSc_HUTAQoN;=4_F$$`5ut9ua~QCU5iTmrwV{o^~YdvyC@g19ai6{51x4DqQ5o^BI8EM0A+K*_Ml(56Np~^9
zTjBQ*HzEj?(%9Md0$zF?4q7}=7XD3j#M^4T*zzx%wI9OgF9YpR()^8rL4`NHVvS`y
zoI@>+Jk_>Moi*F_KfTEqhA&k?W=~b>fTOjw0rm7Vw2>-t59R-%pVbmt&?|@JJpRZD
z%)Uytl3%DUJj0XyD!dz!gi``x<$rKn)2nh(jZH?V!b>
z-BcjAvHYP5V{zUn3Im+P0+P&~g1}OoKe>9^c9%mcC%!Vdau(}6G}w3_vd=mjn`%UQ
z4UP70zkVX)c?KH={?UW3?0tiMP^sDZ;3yzQM@H
)d1Xx@*khh~!a;3i|UT
zU#M?fXNr2IHTefJO}@Q#x)mhUjb&XLd2jaXd!6wOMjI83yU*^1T&2_ji4w=e!O1df
zk&T?-c>SPQh~MxMLI~zIW4s2x-@f0y8&qjIbza`#2a>4E!QvExtuiq3TxwXDebvP$?!T^uY{O86rR0UTa@ThF|scxkQ*BXYuj!qOG7x^lTL9%^2m
z-&st@F*W*seXuym+BRTWnzWtl`9Y10A6aD07gZ#gFiVAFk`IU3KMFc?gi9pT(oTf4
zJU(4CldDCiCxMEAfG9AGr0x8~RC4^pzqnM1-QEu-m&Td|`wV6c|9JA*l+99+0-RXm
z3M#bAyw(Hm2VzoE0&oZ4y1VPZ!t?M#?<4