embedded-porting-patterns
Skill2 starsChanged 2 months agoMITView on GitHub
Porting C/C++ CMake+SDL2 applications to new embedded/handheld platforms (PSP, Vita, 3DS, etc.) by following existing fork patterns without touching core game logic.
- Commits and pushes
In this repository58 other files it gives its agents.
- ad-hoc-script-verificationSkill
- architecture-diagramSkill
- blocked-page-recoverySkill
- cadquery-enclosure-designSkill
- canonical-thumbnailSkill
- circuit-designSkill
- competitor-news-monitorSkill
- component-alternativesSkill
- debugging-hermes-tui-commandsSkill
- docker-container-update-checkSkill
- document-to-action-itemsSkill
- docxSkill
- email-inbox-triageSkill
- ephemeral-file-sharingSkill
- excalidrawSkill
- flash-game-researchSkill
- flutter-android-buildSkill
- flutter-content-renderingSkill
- github-code-reviewSkill
- githubSkill
- goatcounter-analyticsSkill
- google-oauth-file-pollSkill
- grounded-citationsSkill
- hermes-agent-skill-authoringSkill
- hermes-gateway-slash-commandSkill
- hermes-gateway-supervisionSkill
- jellyseerr-watch-suggestionsSkill
- maintained-fork-publishingSkill
- meeting-action-itemsSkill
- native-mcpSkill
- obsidian-mapsSkill
- pdf-flattenSkill
- pdfSkill
- pdf-surgical-editsSkill
- planSkill
- product-price-monitorSkill
- psp-developmentSkill
- psp-homebrew-testingSkill
- psp-prx-plugin-maintenanceSkill
- python-debugpySkill
- python-webapp-patternsSkill
- reddit-readingSkill
- retro-fansiteSkill
- reverse-proxy-websocket-debuggingSkill
- rss-feedsSkill
- simplify-codeSkill
- sketchSkill
- skit-thumbnailSkill
- spikeSkill
- subagent-driven-developmentSkill
- test-driven-developmentSkill
- usb-device-enumerationSkill
- weekly-review-planningSkill
- wiki-media-asset-pipelineSkill
- windows-c-build-toolchainSkill
- windows-crash-forensicsSkill
- writing-plansSkill
- yt-dlp-anti-botSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 4 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 33
Verify with a stand-alone "hello world" SDL2 CMake project BEFORE touching the game repo
- Very specific: line 37
Add an if(<PLATFORM>) block in CMakeLists.txt that:
- Distinctive: line 63
Commit, push to GitHub
- Distinctive: line 66
Run emulator, capture screenshots or log output
- Very specific: line 69
Use ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null if host key caching causes connection hangs (common with …
- Very specific: line 74
Do NOT modify SDL_HINT_RENDER_DRIVER="opengl" or SDL_WINDOW_OPENGL — the PSP SDL2 backend ignores these gracefully.
- Distinctive: line 75
Do NOT change the internal resolution from 640×480 to 480×272 — the engine coordinates depend on 640×480.
- Very specific: line 94
PSPDEV env var must be set: before running cmake: export PSPDEV=/usr/local/pspdev && export PATH=$PSPDEV/bin:$PATH
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Embedded / Game-Engine Platform Porting Patterns
Class of work: taking an existing C/C++ application (CMake + SDL2) that ships for desktop/mobile and adding support for a new embedded/handheld platform. The canonical example is porting fallout1-ce (or similar) to PSP/Vita/3DS by adding a platform branch — never modifying core game logic.
Guiding Principles
- Platform branch, not fork of logic. The upstream repo's game engine, render path, and asset pipeline are untouched. New files go under
os/<platform>/. Conditionals go in shared files under#ifdef __<PLATFORM>__. - Copy the pattern of an existing platform fork. For PSP, use the Vita fork (
Northfear/fallout1-ce-vita) as the structural reference. Diff it against upstream to see what a complete platform block looks like in CMakeLists.txt. - One platform branch per commit series — never mix unrelated port work.
Workflow
1. Setup
- Fork the upstream repo with a
-psp/-vitaetc. suffix in the clone name - Clone the reference fork (e.g.
Northfear/fallout1-ce-vita) alongside for quickdiffaccess - Initialize a build directory on the cross-compilation host
2. Toolchain
- Install or locate the platform toolchain (e.g.
pspdevfor PSP) - Verify with a stand-alone "hello world" SDL2 CMake project BEFORE touching the game repo
- Key verification:
find_package(SDL2)resolves against the toolchain's packaged SDL2 (not building from source)
3. CMake Integration
Add an if(<PLATFORM>) block in CMakeLists.txt that:
- Sets platform compiler flags (architecture-specific, not copied verbatim from other platforms)
- Routes SDL2 lookup through
find_package(SDL2)(skipthird_party/sdl2source build) - Links platform-native libraries (e.g.
pspctrl,pspgu,pspdebugfor PSP) - Includes
os/<platform>/<platform>.cmakefor packaging (EBOOT/PBP, icon, metadata)
4. Platform Scaffold (files to create)
os/<platform>/<platform>.cmake— packaging rules (EBOOT, icon, PARAM.SFO, title)os/<platform>/icon.png— placeholder icon (replaceable later)- Modify
src/plib/gnw/winmain.cc— platform init block (chdir, controller init, debug screen) - Modify
src/plib/gnw/dxinput.cc— input source (game controller, analog sticks) - Modify
src/plib/gnw/input.cc— cursor mapping (stick → mouse) - Include
<pspkernel.h>/<pspdebug.h>etc. in the PSP init in the file, not in headers
5. Debug Output (critical — C printf doesn't work on many embedded systems)
On PSP specifically:
- C
printf()goes through newlib →write(1,...)→sceIoWrite(1,...). This is NOT captured by PPSSPP's log (which capturessceKernelPrintfsyscalls). - C
fopen()needs the fullms0:/device prefix — bare/paths may point to unwritable flash. - Working channels (PSP):
- Native file API:
sceIoOpen("ms0:/debug.txt", PSP_O_WRONLY|PSP_O_CREAT, 0777)+sceIoWrite()+sceIoClose()— requires<pspiofilemgr.h> - On-screen:
pspDebugScreenInit()+pspDebugScreenPrintf()— writes to VRAM. Must be called BEFORE SDL2 takes over the display; the text may be overwritten by GPU rendering. - Kernel printf:
sceKernelPrintf()captured by PPSSPP, but NOT directly callable from user-space. Install viapspDebugInstallKprintfHandler().
- Native file API:
- Verify the debug channel works with a known marker string before trusting it for diagnostic data.
- For other platforms (Vita, 3DS), check the reference fork for their equivalent debug channel.
6. Build & Deploy Loop
- Commit, push to GitHub
- SSH to cross-compilation host, pull, build
- Deploy EBOOT.PBP to emulator memstick
- Run emulator, capture screenshots or log output
- Iterate
Use ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null if host key caching causes connection hangs (common with Tailscale/residential proxies).
7. Rendering Pitfalls (PSP-specific)
- The PSP SDL2 backend uses a 16-bit RGB565 framebuffer via
sceGu. The game engine creates an 8-bit paletted surface (SDL_CreateRGBSurface(depth=8, ...)) and callsSDL_SetPaletteColors(). The INDEX8 → RGB565 conversion duringSDL_BlitSurfacemay silently fail or produce wrong colors. - Direct pixel writes to
gSdlTextureSurface->pixelsmay NOT reach the screen — the PSP SDL2 backend uses GPU-managed texture memory. - Do NOT modify
SDL_HINT_RENDER_DRIVER="opengl"orSDL_WINDOW_OPENGL— the PSP SDL2 backend ignores these gracefully. Removing them causes regressions. - Do NOT change the internal resolution from 640×480 to 480×272 — the engine coordinates depend on 640×480.
- To diagnose palette issues, use
sceIoWriteto dump palette entries to a file — on-screen debug may be overwritten by GPU.
Platform-Specific Libraries to Link
PSP (pspdev toolchain)
pspctrl — controller input
pspdebug — pspDebugScreenInit/Printf (link explicitly)
pspgu — graphics engine
pspgum — matrix utilities
pspvfpu — vector FPU
pspiofilemgr — file I/O (header only for sceIoOpen/Write/Close)Reference Files
references/psp-debug-output.md— full transcript of which debug channels work on PSP and PPSSPP
Pitfalls
- PSPDEV env var must be set before running cmake:
export PSPDEV=/usr/local/pspdev && export PATH=$PSPDEV/bin:$PATH - pspdebug library is NOT auto-linked by pspdev.cmake — must be added to
target_link_libraries()explicitly (unlike pspctrl/pspgu which come through the toolchain default libs) - fopen("ms0:/...") may still work, but sceIoOpen is more reliable. If fopen returns NULL, try sceIoOpen — don't assume the path is wrong.
- SSH connectivity to the cross-compilation host may appear intermittent because of host key verification mismatches. Use the flags above to avoid false "host unreachable" conclusions.
- Force-push never — always
git push origin mainwithout--force. The user has explicitly rejected force-push.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

