uConsole의 Joystick Keys 와 물리키보드를 이용해 Pebble QEMU Emulator에 직접 버튼/터치/가속도데이터 등을 전송하여 개발/디버깅 하겠다는 것이다.
왼쪽 이미지에 보이는 Pebble앱은 한국어(한글) 모르스부호 연습기 앱인데, 단순히 한글 자모를 출력하는게 아니라 한글 오토마타를 내장해서 모르스부호를 입력하면 한국어 문장이 조립된다. 죽도록 버튼을 누르지 않고 화면 터치만 사용하게 했기 때문에, 제대로 동작하는지 확인하려면 Pebble Time 2 실물기기에서 테스트하는 것이 가장 정확하겠지만, 심각한 배터리 사용이 걱정스러웠다. 실제 기기를 오래쓰려면 이런 개발 과정을 Emulator에서 실행해야하지만, macOS 상태에서 테스트하는 것보다, 벽에 달려 놀고있는 uConsole을 활용하자는 생각이 떠올랐다.
구현 아이디어
GamePad 키를 QEMU로 전송하는 방식은 오래전에 이미 사용했던 방법이 있다. RetroPie Joy2Key 방식이다. 그때는 AI가 없어서 직접 코드를 내가 원하는 방향으로 쓰기위해 시간을 제법 쏟아 부었던 적이 있으나, 지금은 뭐 AI 도움을 받아 거의 막힘이 없다. 구현 제한 사항은, 반드시 페블 앱에서 발생하는 Audio를 QEMU를 통해 들을 수 있어야 한다는 점이다. 그게 아니면, 이딴 건 의미 없다.
삽질로 드러난 아이디어 구현의 걸림돌
① 실제 Touch 처럼 자유롭게 입력을 넣는 건 좀 더 시간이 걸리듯.
Touch 인식은 QEMU 앱 소관이라서 외부에서는 Virtual Touch Event Signal 정도만 날릴 수 있다.
QEMU 화면이 resize 되면 touch 위치 인식 불능. Pebble Firmware를 수정하거나 페블 앱을 작성할 때 상대크기로 작성해야 한다.
Ctrl+마우스 움직임 또는 Ctrl+Drag 등의 키 조합을 가상 이벤트로 날릴 수 밖에 없다.
② 입력 종류마다 다른 방식으로 처리해야 함.
QEMU와 통신 방식이 4가지: pypkjs, WebSocket, QMP(unix socket), raw_tcp
포트는 두가지: 포트마다 적절한 시그널을 보내는게 제한된다. 올바르지 않은 채널에 시그널 부어버리면 페블앱을 전환할 때 마다 WebSocket이 죽어버릴 수 있음.
③ pypkjs는 Settings 때문 필수.
따라서 실질적으로 QEMU와 통신수단으로써 남은 선택지는 WebSocket 또는 raw_tcp 채널을 써야 한다.
pypkjs process의 생존 여부 + QEMU process 생존여부 + WebSocket server process 생존여부가 조합된 상태에 따라 강제 재 기동 혹은 멈춤을 결정해야 함. 이게 뭥미;;
raw_tcp를 사용할 경우 포트 충돌.
④ Audio 품질이 개 구림.
PebbleSDK에 포함된 emulator.py 스크립트에 audio 드라이버가 아예 누락됨. 수정해서 써야하는데, 현재로써는 SDK 업데이트마다 배포된 emulator.py 파일을 수정해서 사용해야 한다.
찌그러짐, 늦게 반응, 버퍼 밀림 등의 이상 증상을 보임.
Gemini-3.8-Flash High + gpt-5.5 High 조합으로 12시간 넘게 추적 결과 어이없게도 QEMU RTC 모듈의 말도 안되는 시간처리 코드 때문인 것으로 드러남.
같은 맥락으로 Firmware speaker_service.c 에서도 time_ms() 가 개판이라 buffer underrun 및 지터링 발생할 수 밖에 없는 코드로 확인됨.
PebbleOS speaker stream과 QEMU pebble-audio 장치의 시작 시퀀스가 맞지 않고, SDL audio driver 대신 PipeWire PulseAudio(pa)로 전환해야 했음.
Audio 문제 원인 파악을 위해 사용한 접근법
아래와 같이 문제를 발생시키는 원인을 특정하거나 좁혀가는 방법을 적용했다.
① 추측 금지
Local macOS에 PebbleOS 소스를 clone 받아두고 Pebble Firmware 및 QEMU 동작관련 코드를 확인케 했다.
실제 동작은 Remote uConsole 에서 확인해야 하므로 ssh로 접근하는 데서 많은 토큰 소모가 발생했다.
② 고치라고 요구하는 내용에 더해, 완료시 접하게될 상태를 더 했다
“이 요청이 계획에 따라 수행되면 사용자는 다음과 같은 상태를 기대한다” 라는 식으로, 어떤 상태를 기대하는지, 해야하는지를 기술했다. LLM모델이 학습한 방식을 적용한 것이다.
그치만, Gemini 병신은 단정적이고, GPT 고자놈은 뭘 어떻게 해도 멋대로 확장해서 해석한다. 오지게 패고싶다…