Files
MoHadiShibli 200e2bfc0b Show who's signed in on each controller, and an Invite QR code
When the PS4 reports a user signed in on a controller, the service asks for
the user's name and adds it to the status as `user`. The PS4 may not have
finished signing the user in by then, so a failed look-up is retried every
half second for five seconds. The tile shows the name in place of
"Controller N" (the ring keeps the number), and the controller screen reads
"Controller 1 · Alex". Names are kept out of the log, since people post logs
in bug reports, and they go out cleaned: quotes and backslashes escaped, and
control characters or anything that isn't valid UTF-8 replaced, because a
browser drops the whole WebSocket on a text frame that isn't valid UTF-8.

An Invite panel, opened from a button next to the settings or from the menu,
shows the page's address as a QR code for friends to scan. The console makes
the code with the QR encoder the app already ships, from the address the page
reached it on, and sends the module grid; the page draws it as SVG, so it still
needs no libraries.

The gamepad picker's tooltip had the same "Controller 1 · Controller 1" doubling
the controller screen had; it now names the user too.
2026-10-06 01:05:33 +03:00

77 lines
2.4 KiB
Makefile

# Control4Free -- system-wide virtual controllers for the PS4 (GoldHEN payload).
#
# Build:
# make # build/control4free.elf
# make C4F_PROBE=1 # plus the rumble/light-bar research probe (dev only)
# make clean
#
# A build needs the ps4-payload-sdk; docker/Dockerfile has it, and
# tools/build.ps1 runs this inside the container.
ifdef PS4_PAYLOAD_SDK
include $(PS4_PAYLOAD_SDK)/toolchain/orbis.mk
else
$(error PS4_PAYLOAD_SDK is undefined -- build in Docker, or point it at an SDK)
endif
VERSION := $(shell cat VERSION)
NAME := control4free
ELF := build/$(NAME).elf
OBJDIR := build/payload
SOURCES := src/main.c src/log.c src/vda.c src/klog_line.c src/feedback.c src/web.c src/net.c
# Research build: logs what scePadVirtualDeviceGetRemoteSetting returns. Its ELF
# gets its own name, so it can never be mistaken for a release.
ifdef C4F_PROBE
EXTRA_CFLAGS := -DC4F_PROBE_SETTING
ELF := build/$(NAME)-probe.elf
OBJDIR := build/probe
endif
OBJECTS := $(SOURCES:src/%.c=$(OBJDIR)/%.o) $(OBJDIR)/client.o $(OBJDIR)/assets.o $(OBJDIR)/qrcodegen.o
CFLAGS += -std=gnu11 -Wall -Wextra -Wpointer-arith -g -O2
CFLAGS += -MMD -MP
CFLAGS += -Iinclude -Ivendor/jsmn -Ivendor/qrcodegen -DC4F_VERSION='"$(VERSION)"' $(EXTRA_CFLAGS)
LDFLAGS += -lScePad -lSceUserService -ldl -lpthread
.PHONY: all clean
.DEFAULT_GOAL := all
-include $(OBJECTS:.o=.d)
all: $(ELF)
$(OBJDIR) build:
mkdir -p $@
# VERSION is compiled into the objects, and make doesn't notice a changed flag,
# so a new version has to rebuild them.
$(OBJDIR)/%.o: src/%.c VERSION | $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
build/client.c: client/index.html tools/embed_client.py | build
python3 tools/embed_client.py $< $@
# The page's Invite QR code (MIT, the same copy the app uses).
$(OBJDIR)/qrcodegen.o: vendor/qrcodegen/qrcodegen.c | $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/client.o: build/client.c | $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
# The manifest and icon the page points at, so it can live on a home screen.
build/assets.c: client/manifest.webmanifest client/icon-192.png tools/embed_file.py | build
python3 tools/embed_file.py $@ c4fManifest=client/manifest.webmanifest c4fIcon=client/icon-192.png
$(OBJDIR)/assets.o: build/assets.c | $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
$(ELF): $(OBJECTS) | build
$(CC) -o $@ $(OBJECTS) $(LDFLAGS)
@echo "built $@ ($(VERSION))"
clean:
rm -rf build