Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ jobs:
# `--locked` was the gap: the release workflow and the PKGBUILD both
# build locked, so a Cargo.lock that no longer agreed with Cargo.toml
# passed every check and then failed the release, where it is expensive
# and public. It is asserted here rather than by a second, fat-LTO
# release build, which would cost minutes to learn the same thing.
# and public. It is asserted here rather than by a second release build
# with LTO, which would cost minutes to learn the same thing.
- name: Test
run: cargo test --verbose --locked

Expand Down
67 changes: 34 additions & 33 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 10 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,20 @@ regf = "0.1.0"
rustix = "1.1.5"
serde = "1.0.229"
thiserror = "2.0.21"
tokio = "1.53.2"
tokio = "1.53.3"
toml = "1.1.8"

# Two binaries share this profile now, and they are paid for by different
# people. `raven` runs once per .exe launch, so start-up and size are all that
# matter, and both were measured before and after (numbers in the commit that
# added this). `raven-gui` gains nothing measurable from either setting - it is
# opened by hand, once, and then stays open - and pays for them in compile
# time, since it links wgpu and iced under one codegen unit. The settings are
# kept anyway: they are here for the launcher, which is the binary on the hot
# path, and a second profile for the window would buy a faster build at the
# cost of two release binaries built two different ways.
# The organisation's release profile (Project-Colony-Resources,
# design/releases.md, "Release profile"), shared by both binaries so they are
# built one way. `raven` runs once per .exe launch, so start-up and size are
# what it pays for. Against the default profile, the first measured profile (fat
# LTO) took it from 1.9 MB to 1.2 MB and left start-up unchanged within noise
# (numbers in docs/project/consolidation.md, 3.1). Fat LTO bought no start-up,
# so Raven uses the organisation's thin LTO, which also links `raven-gui` (wgpu
# and iced under one codegen unit) faster.
# `panic = "abort"` is deliberately not set: it trades backtraces away for
# little, and that decision is recorded in docs/project/consolidation.md.
[profile.release]
lto = "fat"
lto = "thin"
codegen-units = 1
strip = "symbols"
30 changes: 16 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<img src="assets/brand/png/raven-logo-light-1024.png" alt="Raven" width="360">
</picture>

**A real Windows installation, mounted as C:, with its programs launched from Linux.**
**A real Windows installation, mounted as C:, with its programs launched from Linux: for Linux users whose Windows software needs a genuine Windows, not Wine's reconstruction of one.**

</div>

Expand All @@ -15,14 +15,11 @@

Wine and Proton run Windows programs against a *synthetic* Windows: a prefix Wine
created, a registry Wine wrote as a text file, and reimplementations of the
libraries a program expects to find. It works remarkably well, and it is why the
prefix is disposable. It also means the program's whole world is a reconstruction.

Raven keeps Wine where Wine is irreplaceable - translating NT calls into Linux
syscalls - and replaces everything above it with a genuine Windows installation
that you deploy, mount read-only, and write to through an overlay. The registry
comes from real hives. The libraries are Microsoft's, except for the precise set
that physically cannot be.
libraries a program expects to find. It works remarkably well, but the program's
whole world is a reconstruction. Raven keeps Wine only where it is
irreplaceable, translating NT calls into Linux syscalls, and replaces everything
above it with a genuine Windows installation that you deploy, mount read-only,
and write to through an overlay.

> **Status:** the end-to-end story exists. A real Windows 11 Pro deploys from
> an official ISO, mounts as C:, a real installer wrote 256 MB into an
Expand All @@ -47,10 +44,11 @@ that physically cannot be.

What you would otherwise reach for, and where it stops:

- **Wine / Proton** - the program runs at native speed, but inside an invented
Windows. Software that reads its own installation state, resolves COM servers
it registered at install time, or expects a library Wine has only partly
reimplemented, finds an environment that does not quite add up.
- **Wine / Proton** - the program runs at native speed, in a prefix that is
cheap to throw away, but inside an invented Windows. Software that reads its
own installation state, resolves COM servers it registered at install time,
or expects a library Wine has only partly reimplemented, finds an environment
that does not quite add up.
- **A virtual machine** - perfect fidelity, because it is really Windows. It is
also a second computer: its own RAM, its own filesystem, its own GPU story, and
a window that is a screen rather than an application. That is isolation, which
Expand All @@ -73,6 +71,10 @@ Raven's position is the one nobody occupies:
NT → Linux syscalls → Wine, in every case; no alternative
```

Above that bottom line, Raven's C: is the real thing: the registry comes from
real hives, and the libraries are Microsoft's, except for the precise set that
physically cannot be.

## What it does

- **Deploys a real Windows without a VM and without booting it.** An official
Expand Down Expand Up @@ -223,7 +225,7 @@ to any server.
| Windows bases | stored | `~/.local/share/Colony/Raven/bases/`: the installations deployed from images you supply |
| Environments | stored | `~/.local/share/Colony/Raven/environments/`: each environment's overlay layer, Wine prefix, registry rules and projected registry |
| DXVK and vkd3d archives | stored briefly | `~/.cache/Colony/Raven/unpack/`: unpacked in a private directory, copied into the environment, then removed |
| Mount points | while running | `$XDG_RUNTIME_DIR/raven/<environment>/c`: where an environment's C: is mounted; runtime state, gone at reboot |
| Mount points and sessions | while running | `$XDG_RUNTIME_DIR/raven/<environment>/`: `c` is where an environment's C: is mounted, `session.pid` names the process holding that mount so later launches join it, and `session.lock` exists while a session starts; runtime state, gone at reboot |
| Windows registry | read | the hives of the Windows image you supply; only the allow-listed subtrees are copied into the environment's prefix, nothing leaves the machine |

The `~/.config`, `~/.local/share` and `~/.cache` paths follow `XDG_CONFIG_HOME`,
Expand Down
15 changes: 11 additions & 4 deletions crates/raven-gui/src/preferences.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,17 @@ fn lenient_language<'de, D: Deserializer<'de>>(d: D) -> Result<Language, D::Erro
})
}

/// The file, under Raven's config directory.
fn file_in(config: PathBuf) -> PathBuf {
config.join("preferences").join("preferences.toml")
}

impl Preferences {
/// Where the file lives, without creating anything.
pub fn path() -> io::Result<PathBuf> {
Ok(colony_ui::paths::locate::config_dir(crate::PROGRAM)?
.join("preferences")
.join("preferences.toml"))
Ok(file_in(colony_ui::paths::locate::config_dir(
crate::PROGRAM,
)?))
}

/// The saved preferences, or the defaults when there are none or they
Expand All @@ -87,7 +92,9 @@ impl Preferences {
/// crash mid-write leaves the previous preferences rather than half of
/// these.
pub fn save(&self) -> io::Result<()> {
let path = Self::path()?;
// `config_dir` creates Colony/Raven/ the way every Colony program
// does; the preferences/ folder under it is Raven's own.
let path = file_in(colony_ui::paths::config_dir(crate::PROGRAM)?);
let dir = path.parent().expect("the file has a directory");
std::fs::create_dir_all(dir)?;
let text = toml::to_string(self).map_err(io::Error::other)?;
Expand Down
Loading
Loading