Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ at a time:
6. put a game in it — its own installer, the one you downloaded, runs inside the bottle

After that the library is where you live. A bottle holds titles you added; a title is a
program in that bottle, its name, and the arguments it starts with. Picking a program that
program in that bottle, its name, the arguments it starts with and any environment of its
own. Picking a program that
carries `libcef.dll` fills those arguments in with what a Chromium client needs, because
that is the one thing this stack is known to require and easy to forget. A title's name and
arguments can be changed afterwards, a bottle can be renamed or thrown away, and the app
Expand Down
8 changes: 7 additions & 1 deletion docs/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ after `~/.wine`, kills nothing of the user's and exits 0.
### Which is why the titles added by hand live in the prefix

`sake-titles.json`, at the root of the bottle, holds what somebody added to the library
themselves — a name, the arguments, and the executable **relative to `drive_c`**. Nothing
themselves — a name, the arguments, the environment, and the executable **relative to
`drive_c`**. Nothing
in it names the prefix, so it inherits everything the section above measured: a rename
stays a `moveItem`, and throwing the bottle away takes its titles with it. Keeping the
list under `~/Library/Sake` instead would make both of those an operation on two places
Expand All @@ -106,6 +107,11 @@ Wine ignores what it does not recognise at a prefix's root — it keeps its own
`.update-timestamp` there — and a bottle nobody has added anything to has no
`sake-titles.json` at all.

**A field added to that file has to be optional going in.** `TitleStore.load()` turns any
decoding failure into an empty list rather than an error, so a required field would empty
the library of every bottle written before it existed, with nothing said. `environment`
was added that way on 2026-09-21 and the tests pin it.

**This file is the whole of it.** sake has no titles of its own to merge with: a bottle
shows what somebody added to it and nothing else, so the file is the answer rather than one
half of it.
Expand Down
16 changes: 14 additions & 2 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ patches in `patches/`. `runtime.md` has the measurement and what to look for.
What the second title taught about profiles: Steam needed **nothing** per-title once the
engine could host a swapchain across processes — no flags, no environment, no registry. The
three Chromium flags sake offers are Battle.net's, measured on its 32-bit CEF, and Steam's
client cannot even take them. So a title profile is still name, executable and arguments,
client cannot even take them. So a title profile was name, executable and arguments until
2026-09-21, when it gained an environment of its own — `runtime.md` has what that may and
may not set —
and the argument suggestion is a heuristic for one launcher rather than a rule for Chromium.
Nothing yet knows that starting Diablo IV directly fails on the token — `runtime.md` says
so, the app does not.
Expand Down Expand Up @@ -252,7 +254,17 @@ easier to read than it was interleaved with `configure` flags.
after an uninstall are all judgements, and all in the app target — `scripts/test.sh` only
reaches `SakeKit`. `CLAUDE.md` says logic in a view stops being tested; this is the same
thing one layer down. Either these move behind types that do not know about SwiftUI, or
the app target gets tests of its own.
the app target gets tests of its own. `typedEnvironment()`, added 2026-09-21, is another
of these: which variable names a title may not set is a judgement, and it lives in the app
target where the tests cannot reach it.
- **Two buttons say "Check Again" in the setup wizard.** The bottom bar adds one when the
step is the machine step, and `primary` adds another because that step is not done, so
both render the same verb. The comment above the first says it is there for the step
"worth repeating after it has passed" — which is the condition the code does not check.
Found 2026-09-21, not fixed.
- **Editing a title moves it to the end of the sidebar.** `TitleStore.add()` filters the id
out and appends, so saving Options reorders the library. Harmless and confusing, and it
cost a measurement on 2026-09-21: a row addressed by index was no longer the row it was.
- **Where the CrossOver version lives.** It is a knob users may need — a newer CrossOver may
fix or break a given game — but exposing it invites them to pick a combination nobody has
run. Steam gave the knob a concrete reason on 2026-09-20: two of sake's patches are
Expand Down
8 changes: 8 additions & 0 deletions docs/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@ about the token.
Implication for sake: a "launch the game directly" button cannot work for this title on its
own. The launcher's own flow has to be driven at least once per session.

**There is a third way in that nobody here has tried.** Blizzard installs its own
`Diablo IV Launcher.exe` beside the game, and the desktop shortcut the installer leaves
points at that with no arguments at all — read out of
`drive_c/users/Public/Desktop/Diablo IV.lnk` on 2026-09-21, 250 bytes, target and working
directory and nothing else. So "start Diablo IV" as a title in sake need not mean starting
`Diablo IV.exe`: it can mean starting the launcher Blizzard ships, which talks to the
client the way the Play button does. **Untested** — the shortcut was read, not run.

## Controllers need SDL2

`winebus.sys` has two backends. **IOHID** is built either way and handles anything behaving
Expand Down