> For the complete documentation index, see [llms.txt](https://docs.kouch.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kouch.dev/docs/controller_types_plan.md).

# Controller types per game, and automatic graphics (2026-09-29)

An addendum to `PLAN_V2.md`, `GAME_MENU_EXPORT_PLAN.md` (G5, G6) and `PROFILE_AUTHORING.md`. It doesn't replace them.

## What the owner asked for

> "a profile also needs to put a thing for different controller types for that console", with a default per console and changeable inside Kouch, "with games and emulator defaults".

* **The pointer console:**
  * the remote held sideways;
  * the remote held upright;
  * the remote with its attachment, **the default**;
  * the classic-style pad.
* **The hybrid console:**
  * the pro-style pad, **the default**;
  * both halves of the split pair;
  * a single half.

Some games don't support a controller type. For those, the game's default must be one it supports.

> Before launching, the game page "could show which controller profile is using, and able to be changed, it has to be nice icons". The icons can ship with or inside the `.kod`.

> The emulator's first-time setup for graphics (resolution, anti-aliasing, and so on) gets an **automatic** and a **manual** mode. Automatic checks the system and adjusts the settings: on a Deck no more than 800p, and handheld vs docked for the hybrid console.

## Decisions

* **A controller type is an option.** Options already give per-emulator values, per-game overrides, a `controls` tab and `config_edit` application (PROFILE\_AUTHORING "Launch options"). The new option type is `controller`:
  * each value is one controller type, with a `label`, an `icon`, the `edits` it writes (the emulator's own controller bindings), and what it `needs`: `motion`, `pointer`, or a second piece;
  * `default` is the console's usual controller;
  * a game's own value beats the emulator's, which beats `default`, as for every option.
* **Per-game defaults come from the profile's data, keyed by game id.** A new `game_defaults` map, `{ "<title id>": { "<option id>": value } }`, uses the ids from G8.
  * It lets a community `.kod` say "this game doesn't support the attachment", without the user doing anything.
  * Kouch's own repo never commits per-title rules (ground rule 2). They come only from third-party `.kod` files and the user's own settings.
* **Where it shows:**
  * the game page, above Play: the current type's icon and name, and A or click opens a picker of large icon cards;
  * the Options tab;
  * the Quick Menu's Controls page, where a change is "Restart game to apply", like graphics.
* **Icons:**
  * **Kouch ships a neutral in-house set for the generic classes:** standard pad, pro-style pad, remote sideways, remote upright, remote with attachment, classic-style pad, split pair (both halves), single half. It's made the same way as the connect screen's silhouettes (`gen-silhouettes.mjs`), brand-free.
  * **A `.kod` may carry its own icons** (ADR 0024): under `icons/` in the zip, PNG or WebP only, size-capped, referenced by relative path, validated like theme assets (no SVG, no scripts, no remote URLs).
  * An icon a `.kod` carries is third-party content, like a Workshop theme's imagery under ADR 0009. Kouch's own code, assets and docs stay brand-free.
* **Automatic graphics (G5) is the default for a new emulator.** The first time an emulator is set up, its Graphics sheet offers **Automatic** (the default) or **Manual**.
  * **Automatic reads the device:**
    * the display's resolution and refresh;
    * whether it's a handheld (the Deck or another handheld class) and whether it's docked (an external display is the active one);
    * the GPU class and its memory (DXGI on Windows, the DRM/sysfs info on Linux);
    * the CPU thread count.
  * **It picks settings by each option's `role`:**
    * `internal_resolution`: the highest value whose output height is no more than the display's, capped at 800p on a handheld;
    * `docked_mode`: handheld undocked, docked on an external display;
    * `anti_aliasing` and `anisotropic`: by GPU class;
    * `renderer`: the profile's recommended one;
    * V-Sync off, as the default already is.
  * **The profile can steer it** with `auto` hints, e.g. `"auto": { "internal_resolution": { "max_height": "{display_height}", "handheld_max_height": 800 } }`, or presets keyed by device class (`handheld`, `laptop`, `desktop`) as G5 planned.
  * **Automatic re-evaluates at each launch.** A Deck docked to a TV gets docked settings; back in the hand, it gets handheld ones.
  * **Manual keeps exactly what the user set.**
  * Changing any setting by hand switches that emulator to Manual, with an easy way back to Automatic.
  * A game's own values still win in both modes.

## Later: the owner's metadata server and performance reports

The owner (2026-09-29): "i could link it to a server that has many metadatas for configs, also automatic performance submission in emulators to the cloud (my server) for analysis".

* **A metadata source.** Kouch could read per-game defaults (controller types, graphics and `auto` hints) from the owner's server instead of, or on top of, the `.kod`'s `game_defaults`.
  * The feed would be signed JSON keyed by emulator id and title id, cached locally, and never required. Offline, Kouch uses the `.kod` and the user's own settings.
  * It carries settings only. No game files, BIOS, keys or firmware, and no links to them (ground rule 2).
* **Performance reports.** After a session, Kouch could send what it knows:

  * the emulator and version;
  * the profile;
  * the title id;
  * the option values in effect;
  * the device class from T5;
  * the session length;
  * the emulator's own speed figures where the profile says how to read them (from its log or stats file).

  The server can then suggest better defaults per device.

  The owner, 2026-09-30, on what the reports carry: "track how a game runs in a emulator for better settings, grab info from controllers and upload it to a server pretty much, the fps data, system, ram, etc". That adds controller info (class, connection, motion or not; never names or serials) and RAM to the list above. The public promise becomes "No tracking without your permission".

  * **Opt-in**, asked once and changeable in Settings, with a readable preview of exactly what's sent.
  * **Anonymous:** a random install id; no Steam or Discord id, no names, no paths, no file hashes beyond the title id.
  * Kouch never sends file contents.
  * Before any code: an ADR (privacy, what's sent, retention, how to delete) and the server's API contract from the owner (base URL, auth, signing key). Valve's rules for data a Steam app collects apply.
* **Status:** waiting on the owner's server and API. T1–T7 don't depend on it: the local `.kod` data and the automatic rules work without a server.

## Work

| Item                  | Who                     | What                                                                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| T1 schema             | B                       | The `controller` option type (values with `label`, `icon`, `edits`, `needs`) and `game_defaults` keyed by title id. Validation: icons are relative paths inside the `.kod`, `edits` follow `config_edit` rules, and every value's needs are sane. Tests. PROFILE\_AUTHORING "Controller types". Also `payloads.rs` ↔ `types.ts`. |
| T2 `.kod` icons       | B                       | `icons/` in the `.kod` zip: PNG/WebP only, capped at 256 KB per file and 64 icons, extracted to the profile's data, served through `kmedia` (ADR 0024).                                                                                                                                                                          |
| T3 neutral icon set   | C                       | The eight generic classes as in-house line icons that match the silhouettes. Profiles can name them (`"icon": "kouch:remote-attachment"`) instead of carrying their own.                                                                                                                                                         |
| T4 UI                 | A                       | The game page's controller type above Play (icon + name) with the picker sheet of icon cards; the Options/Controls tab; the Quick Menu's Controls page with restart-to-apply. Every size, 150 %, Black and White, keyboard, mouse and pad.                                                                                       |
| T5 device probe       | B                       | `device_info` (display size/refresh, handheld, docked, GPU class and memory, threads) on Windows and Linux, and the `auto` hints in the schema.                                                                                                                                                                                  |
| T6 automatic graphics | A (UI) + B (resolution) | The first-time Automatic/Manual choice, the re-evaluation at launch, "Manual" on a hand change, and back to Automatic.                                                                                                                                                                                                           |
| T7 test profiles      | C                       | The four test profiles get their controller types (with icons) and `auto` hints, verified live: each type's bindings set in Kouch, the emulator's rewritten config read back, and a real game played with the default type.                                                                                                      |
| T8 ADR 0024           | central                 | `.kod`-bundled icons.                                                                                                                                                                                                                                                                                                            |

## Status

| Item                        | Status                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| T1                          | built (B, `c1d598e`): the `controller` option type and `game_defaults` by title id                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| T2                          | built (B, 2026-09-30): `app/src-tauri/src/kod_icons.rs`. On `kod_import`, each profile's referenced `icons/...` entries are read capped (`KodArchive::icon_bytes`), sniffed (PNG/WebP, matching the extension), ≤256 KB each, ≤64, and copied to `<data>/profile_icons/<id>/` (replaced on re-import, removed with the emulator). `kmedia` serves them from the data dir. `EmulatorProfile.icon_urls` and `GameOptions.icon_urls` map reference → URL. Exports pack them back (`KodExtras.icons_root`); two profiles naming the same file with different pictures keep the first. The legacy `profiles_import_bundle` path (profiles already parsed, no archive) carries none.                                                                                                                                                                                                                                                             |
| T3                          | built (C): Kenney's CC0 controller icons, tinted per player, with a Simple setting (`3f3edb5`, `eab5d3b`; ADR 0025 and its amendments)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| T5                          | built (B, `01472ae`): `device_info` gives the display (size, refresh), handheld/docked, device class, GPU class/tier/VRAM and CPU threads. Windows reads DXGI inside the existing `kouch-launch/src/windows.rs` island; Linux reads DMI/DRM sysfs, with docked meaning a connected external connector. Checked read-only on the owner's PC; the Deck (in the hand and docked) is pending                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| T6                          | built: B's picks and A's UI (rows below). Verified on the Deck in the hand: `device_info` gives 1280×800 @ 90 Hz, handheld, integrated, low tier; Automatic chooses 1× (720p), handheld mode and no AA for the hybrid console, and 1280×720 for the tablet console. Still to check: docked (the owner docks the Deck to a TV once), and the picks written into the real emulators' configs on Windows (B's live run)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| T7                          | built and verified live (C, 2026-09-30): the four test profiles have controller types with Kouch's icons. Pointer console: remote with attachment (default), remote, remote held sideways, classic pad; a per-game default of the sideways remote for a party game that doesn't support the attachment. Tablet console: pad with a screen (default) or pro-style pad for player 1. Hybrid console: pro-style pad (default) or split pair. Handheld: one type. Every type's bindings were read back from the emulator's own config after a real launch (EARLY\_TESTS "Controller types, live"); the `auto` hints came with B's T6 (`06c417e`)                                                                                                                                                                                                                                                                                               |
| T4                          | built (A, 2026-09-29): the chip above Play and `screens/game/ControllerTypeSheet.svelte` (one card per type: picture, name, needs, In use; a reset row names the game default or the emulator setting it returns to), the Options tab row with its picture (`OptionControl`), and the Quick Menu Controller tools row with "Restart game to apply". Pictures come from T3 (`ControllerTypeIcon` → `lib/controllerPictures`, realistic or simple); a `.kod` picture shows once T2 serves it (the standard pad until then). Sweep cells `game-controller`, `game-controller-sheet`, `quick-menu-controller-type`.                                                                                                                                                                                                                                                                                                                            |
| T5                          | built (B, 2026-09-30): `kouch_launch::device` + the `device_info` command → `DeviceInfo {display {width, height, refresh_hz}, handheld, docked, device_class, gpu_name, gpu_class, vram_mb, gpu_tier, cpu_threads}`, read fresh on each call. Windows: DXGI adapters, the current display mode, and QueryDisplayConfig for an active external output (docked), in `kouch-launch/src/windows.rs`. Linux: DRM sysfs (cards, amdgpu VRAM, connected non-eDP/DSI/LVDS connectors). Handhelds come from one firmware table (`window.rs` `HANDHELDS`). Mock: a handheld; `?mock=docked` and `?mock=desktop`. The `auto` hints and `device:changed` come with T6.                                                                                                                                                                                                                                                                                 |
| T6 (B, the resolution side) | built (B, 2026-09-30): `kouch_profiles::auto_graphics` picks by role at every launch (internal resolution ≤ the display, 800 in the hand; docked mode; anti-aliasing and anisotropic by GPU tier; the recommended renderer; a device preset wins), steered by the profile's `auto` hints (PROFILE\_AUTHORING "Automatic graphics"). Contract: `EmulatorProfile.graphics_mode` (absent = not chosen; Manual in effect when a graphics value was set by hand), `GameOptions.graphics_mode` / `graphics_mode_chosen` / `auto_values`, `emulators_set_graphics_mode {id, mode}`, `emulators_auto_values {id}`, and `device:changed {before, after}` at a launch when docking or the display changed. A graphics value changed through `emulators_set_option_values` switches to Manual; exports never carry the mode. The mock's `mockAutoValues` is checked against the shell's picks (`rust-defaults.json` `auto_graphics`). A's UI is next. |
| T6 (A, the UI)              | built (A, 2026-09-30): `GraphicsOptions` (the game's Graphics sheet, Settings › Emulators › Graphics, the Quick Menu's Graphics page) opens with the Automatic / Manual pair for the emulator ("Kouch sets them for this handheld (1280×800), again at every launch" / "Exactly what you set, on every device"; a first-time note until one is chosen; on a game's page "For every game on …"). In Automatic the rows show Automatic's picks, marked "Set by Automatic"; changing one at the emulator's level writes what was on screen plus the change, and the shell switches it to Manual; Automatic is one row away. A game's values still win ("Changed · Automatic: …"). At a launch that changed docking or the display, `device:changed` gives one info toast when the launching emulator is in Automatic. A `.kod`'s own controller pictures (T2 `icon_urls`) show in the chip, the picker, the Options rows and the Quick Menu.  |
| T8                          | written with this plan                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kouch.dev/docs/controller_types_plan.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
