added key_extendr, removed msc dir, split src into multiple files

This commit is contained in:
2026-06-05 12:40:50 +02:00
parent 31a15dbd51
commit 86d92680ed
12 changed files with 171 additions and 35 deletions
+1 -2
View File
@@ -1,2 +1 @@
msc_payload/SML.gb
msc_payload/MGBA.appimage
build
+27 -5
View File
@@ -6,10 +6,32 @@ HID_PATH = /usr/local/P4wnP1/HIDScripts/
PASSWD = toor
## Sync HID script to P4wnP1
sync:
@sshpass -p "$(PASSWD)" scp "./$(NAME)" "$(TARGET):$(HID_PATH)$(NAME)" > /dev/null 2>&1
@echo "Sync done!"
all:
@rm build/00-config.js -f
@cp $(PWD)/config.js src/00-config.js
@mkdir build -p
@rm build/* -f
@touch build/$(NAME)
@cat src/* > build/$(NAME)
@rm src/00-config.js -f
@echo "[!] javascript source built!"
sync: all
@sshpass -p "$(PASSWD)" scp "./build/$(NAME)" "$(TARGET):$(HID_PATH)$(NAME)" > /dev/null 2>&1
@echo "[!] Sync done!"
## Execute HID script remotely
run: sync
@sshpass -p "$(PASSWD)" ssh "$(TARGET)" "P4wnP1_cli hid run -n $(NAME)" > /dev/null 2>&1
exec:
@echo "[!] Executing..."
@sshpass -p "$(PASSWD)" ssh "$(TARGET)" "P4wnP1_cli hid run -n $(NAME)" ## > /dev/null 2>&1
stop:
-@sshpass -p "$(PASSWD)" ssh "$(TARGET)" 'for i in {0..25}; do P4wnP1_cli hid job cancel $$i; done' > /dev/null 2>&1 || true
@echo "[i] Stopped all running jobs"
## Sync and execute
run: sync exec
+3
View File
@@ -0,0 +1,3 @@
MOUNT_LABEL = "MARIO"
KEYB_LAYOUT = "DE"
OPEN_TERM_K = "GUI RETURN"
+16
View File
@@ -0,0 +1,16 @@
.PHONY: all
SRC=key_extendr.py
LIBSUINPUT := $(shell find / -name '_libsuinput*.so' 2>/dev/null | head -1)
all:
@test -n "$(LIBSUINPUT)" || (echo "Error: _libsuinput*.so not found"; exit 1)
@mkdir -p ./build
@rm -f build/key_extendr
pyinstaller --onefile $(SRC) --collect-all uinput --add-binary "$(LIBSUINPUT):." --distpath build/key_extendr
@rm -f key_extendr.spec
@mv build/key_extendr/key_extendr build/key_extendr.bin
@rm -f build/key_extendr -r
@mv build/key_extendr.bin build/key_extendr
+3
View File
@@ -0,0 +1,3 @@
# Key extendr
Because the P4wnP1 aloa doesnt expose an api for holding down keys and the default is at 1ms - way to short to be detected consistently by an input polling emulator - we need this script to detect inputs and replicate them.
+64
View File
@@ -0,0 +1,64 @@
#!/bin/python3
import evdev
import uinput
import time
import threading
import os, signal
HOLD_DURATION = 0.1 # 100ms
DEV_NAME_FRAG = "just an usb stick"
if os.geteuid() != 0:
raise SystemExit("Error: run as root (sudo)")
def find_device(name_fragment, exclude="Mouse"):
for path in evdev.list_devices():
dev = evdev.InputDevice(path)
name = dev.name.lower()
if name_fragment.lower() in name:
if exclude and exclude.lower() in name:
continue
return dev
raise RuntimeError(f"No device matching '{name_fragment}' found")
def hold_key(key, dev):
dev.emit((evdev.ecodes.EV_KEY, key), 1) # key down
time.sleep(HOLD_DURATION)
dev.emit((evdev.ecodes.EV_KEY, key), 0) # key up
def handle_exit(sig, frame):
print("\nExiting...")
raise SystemExit(0)
keyboard = uinput.Device([
uinput.KEY_UP,
uinput.KEY_DOWN,
uinput.KEY_LEFT,
uinput.KEY_RIGHT,
uinput.KEY_ENTER,
uinput.KEY_X,
uinput.KEY_Z,
uinput.KEY_A,
uinput.KEY_S,
])
source = find_device(DEV_NAME_FRAG)
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
print(f"Listening on '{source.name}' ...")
for event in source.read_loop():
if event.type == evdev.ecodes.EV_KEY:
if event.value == 1: # key down only
threading.Thread(
target=hold_key,
args=(
event.code,
keyboard
),
daemon=True
).start()
View File
View File
+10 -28
View File
@@ -1,12 +1,8 @@
// <== === SETTINGS === ==>
MOUNT_LABEL = "WORKFILES"
// === === === === === ===
function setup(delay_after) {
delay_after = delay_after || 0;
layout("DE");
layout(KEYB_LAYOUT);
typingSpeed(0,0);
delay(delay_after);
}
@@ -17,7 +13,7 @@ function cmd(text) {
function open_term(delay_after) {
delay_after = delay_after || 0;
press("GUI RETURN");
press(OPEN_TERM_K);
delay(delay_after);
}
@@ -27,30 +23,16 @@ function launch_game() {
// copy files to /tmp to be able to make them executable
cmd("mkdir /tmp/mgba_cpy");
cmd("cp * /tmp/mgba_cpy");
cmd("cp -r * /tmp/mgba_cpy");
cmd("cd /tmp/mgba_cpy");
cmd("chmod +x MGBA.appimage");
// launch mgba and close the shell
cmd("nohup ./MGBA.appimage SML.gb &>/dev/null & disown && exit");
// launch sameboy and close the shell
cmd("set SDL_VIDEODRIVER x11");
cmd("nohup ./MGBA.appimage POKY.gb &>/dev/null & disown && exit");
}
function ent(delay_after) {
delay_after = delay_after || 0;
type("x");
delay(delay_after);
function cleanup() {
//close sameboy
//cleanup
}
// <== === MAIN FUNCTION === ==>
function main() {
setup();
open_term(500);
launch_game();
}
main()
// === === === === === === === ===
+15
View File
@@ -0,0 +1,15 @@
function start(delay_after) {
delay_after = delay_after || 0;
press("RETURN");
delay(delay_after);
}
function pr(key, times) {
times = times || 0;
for (var i = 0; i < times; i++) {
console.log("RETURN");
press(key);
delay(10);
}
}
+18
View File
@@ -0,0 +1,18 @@
function play_game() {
typingSpeed(10,10);
// wait for bootrom
delay(16000);
press("GUI x");
delay(100);
// start game
press("RETURN");
delay(1000);
press("RETURN");
delay(2000);
press("RETURN");
for (var x=0;x<30;x+=1) {
press("x");
delay(1000);
}
}
+14
View File
@@ -0,0 +1,14 @@
// <== === MAIN FUNCTION === ==>
function main() {
setup();
open_term(500);
launch_game();
play_game();
delay(100);
cleanup();
}
main()
// === === === === === === === ===