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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ nvram.bin
Cargo.lock
iris.toml
screenshot_*.png
IRIS.app/
*.log
.DS_Store
19 changes: 19 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Privacy Policy

_Last updated: June 10, 2026_

IRIS is an emulator of the SGI Indy workstation. It does **not** collect, store, transmit, or share any personal information.

**No data collection.** IRIS contains no analytics, telemetry, advertising, or tracking. It creates no accounts and sends no information about you or your usage to the developer or any third party.

**Camera.** If you enable the IndyCam (Video-In) feature, IRIS uses your Mac's camera only to feed a live signal to the emulated Indy video-input device. The video is processed on your device and is never recorded, stored, or transmitted by IRIS.

**Networking.** IRIS does not contact any server of its own. Its emulated Ethernet is handled by an on-device userspace NAT; any network traffic originates from the guest operating system you choose to run and connects only where you direct it.

**Your files.** Disk images, PROM files, and other files you open stay on your device. IRIS accesses only the files you explicitly select and never uploads them.

**Children's privacy.** IRIS collects no data from anyone, including children.

**Changes.** Any updates to this policy will be posted on this page.

**Contact.** Questions about this policy: https://github.com/danifunker/iris/issues
43 changes: 43 additions & 0 deletions installer/iris-gui.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- App identity — must match the embedded provisioning profile
(<TeamID>.<bundle id>). Without these the signature lacks an
application-identifier and the build can't be used with TestFlight. -->
<key>com.apple.application-identifier</key>
<string>Q4F2GZ34R5.io.github.danifunker.iris</string>
<key>com.apple.developer.team-identifier</key>
<string>Q4F2GZ34R5</string>

<!-- Required for Mac App Store -->
<key>com.apple.security.app-sandbox</key>
<true/>

<!-- Cranelift JIT compilation (lightning build).
Must also be enabled in the App ID on developer.apple.com. -->
<key>com.apple.security.cs.allow-jit</key>
<true/>

<!-- IndyCam / VINO emulation -->
<key>com.apple.security.device.camera</key>
<true/>

<!-- Disk image files (.raw, .img, .chd) selected by the user -->
<key>com.apple.security.files.user-selected.read-write</key>
<true/>

<!-- Persist access to user-selected disk images / PROMs / ISOs across
launches via app-scoped security-scoped bookmarks (see
iris-gui/src/macos_sandbox.rs). Required for the bookmark create/resolve
to succeed under the sandbox; without it they fail silently. -->
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>

<!-- Ethernet emulation (SEEQ 8003) -->
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>
72 changes: 72 additions & 0 deletions installer/iris-gui.iss
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
; Inno Setup script for IRIS (Windows, per-user install).
; Produces a per-user Setup.exe that installs into %LocalAppData% — no admin required.
;
; Build:
; iscc /DMyAppVersion=2025-06-09-02-00 /DSourceDir=path\to\build /DAssetsDir=path\to\icons installer\iris-gui.iss

#ifndef MyAppVersion
#define MyAppVersion "0.0.0-dev"
#endif

; Directory containing iris-gui.exe.
#ifndef SourceDir
#define SourceDir "..\target\release"
#endif

; Directory containing icon.ico.
#ifndef AssetsDir
#define AssetsDir "..\iris-gui\assets\icons"
#endif

; Combined BSD-3 + GPL-3 license file (generated by CI, or pass manually).
#ifndef LicenseFile
#define LicenseFile "..\COMBINED-LICENSE.txt"
#endif

#define MyAppName "IRIS"
#define MyAppPublisher "Dani Sarfati"
#define MyAppURL "https://github.com/danifunker/iris"
#define MyAppExeName "iris-gui.exe"

[Setup]
; Stable AppId — do not change across releases.
AppId={{A7F2C91E-3D8B-4F5A-8E2C-1B9D6A3E8F42}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}/releases
LicenseFile={#LicenseFile}
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
DefaultDirName={localappdata}\Programs\IRIS
DisableProgramGroupPage=yes
DefaultGroupName={#MyAppName}
DisableDirPage=no
AllowNoIcons=yes
UninstallDisplayIcon={app}\{#MyAppExeName}
OutputBaseFilename=IRIS-Setup
Compression=lzma2
SolidCompression=yes
WizardStyle=modern

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "Create a &desktop shortcut"; GroupDescription: "Additional shortcuts:"; Flags: unchecked

[Files]
Source: "{#SourceDir}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AssetsDir}\icon.ico"; DestDir: "{app}"; Flags: ignoreversion skipifsourcedoesntexist
; Both licenses ship with the installed app so users can read them post-install.
Source: "{#LicenseFile}"; DestDir: "{app}"; DestName: "LICENSE.txt"; Flags: ignoreversion skipifsourcedoesntexist

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\Uninstall {#MyAppName}"; Filename: "{uninstallexe}"
Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "Launch {#MyAppName}"; Flags: nowait postinstall skipifsilent
45 changes: 45 additions & 0 deletions iris-gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,41 @@
name = "iris-gui"
version = "0.1.0"
edition = "2021"
description = "SGI Indy (MIPS R4400) emulator"
license = "BSD-3-Clause"

[package.metadata.deb]
maintainer = "Dani Sarfati <dani@funkervogt.com>"
copyright = "2025 Dani Sarfati"
license-file = "../LICENSE"
extended-description = "IRIS emulates an SGI Indy workstation (MIPS R4400) and boots IRIX 6.5 and 5.3 to a usable system with shell, networking, and X11."
depends = "$auto"
section = "games"
priority = "optional"
# Asset source paths are resolved relative to this package dir (iris-gui/),
# NOT the workspace root — so they must not carry an `iris-gui/` prefix or it
# doubles to iris-gui/iris-gui/... The `target/...` binary path is special-cased
# by cargo-deb (rewritten to target/<triple>/release with --target).
assets = [
["target/release/iris-gui", "usr/bin/iris-gui", "755"],
["assets/icons/icon-256.png", "usr/share/icons/hicolor/256x256/apps/iris-gui.png", "644"],
["assets/icons/icon-128.png", "usr/share/icons/hicolor/128x128/apps/iris-gui.png", "644"],
["assets/icons/icon-64.png", "usr/share/icons/hicolor/64x64/apps/iris-gui.png", "644"],
["iris-gui.desktop", "usr/share/applications/iris-gui.desktop", "644"],
]

[package.metadata.generate-rpm]
assets = [
{ source = "target/release/iris-gui", dest = "/usr/bin/iris-gui", mode = "755" },
{ source = "assets/icons/icon-256.png", dest = "/usr/share/icons/hicolor/256x256/apps/iris-gui.png", mode = "644" },
{ source = "iris-gui.desktop", dest = "/usr/share/applications/iris-gui.desktop", mode = "644" },
]

[features]
# Mac App Store distribution build. Hides the CI/Automation config tab (the
# iris-ci socket is a developer automation feature unusable in the sandbox)
# and any other developer-only affordances. Set by .github/workflows/appstore.yml.
appstore = []

[dependencies]
# Group A (additive) features are always on for iris-gui so the user can
Expand All @@ -25,6 +60,16 @@ dirs = "5"
log = "0.4"
env_logger = "0.10"

# macOS App Sandbox: NSURL security-scoped bookmarks let the App Store build
# reopen user-selected disk images / PROMs / ISOs across launches. These crates
# are already in the build graph (eframe/winit/rfd pull them in); we enable a
# few extra type features and use them only under `feature = "appstore"`.
[target.'cfg(target_os = "macos")'.dependencies]
objc2 = "0.6"
objc2-foundation = { version = "0.3", features = [
"NSURL", "NSData", "NSError", "NSString", "NSArray",
] }

[[bin]]
name = "iris-gui"
path = "src/main.rs"
9 changes: 9 additions & 0 deletions iris-gui/iris-gui.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Name=IRIS
Comment=SGI Indy (MIPS R4400) emulator
Exec=iris-gui
Icon=iris-gui
Categories=Emulator;Game;
Terminal=false
StartupNotify=true
22 changes: 18 additions & 4 deletions iris-gui/src/config_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,24 @@ pub enum Tab {
}

impl Tab {
pub const ALL: &'static [Tab] = &[
Tab::General, Tab::Disks, Tab::Network, Tab::Memory,
Tab::Display, Tab::VideoIn, Tab::Debug, Tab::Ci,
];
/// Tabs to show for the active build. The Debug/JIT tab is hidden in
/// lightning builds (the JIT debug paths it drives are compiled out), and
/// the CI/Automation tab is hidden in App Store builds (the iris-ci socket
/// is a developer automation feature, not something a sandboxed end user
/// can use). Both fall back to the full set for ordinary builds.
pub fn visible() -> Vec<Tab> {
let mut tabs = vec![
Tab::General, Tab::Disks, Tab::Network, Tab::Memory,
Tab::Display, Tab::VideoIn,
];
if !build_features::LIGHTNING {
tabs.push(Tab::Debug);
}
if !cfg!(feature = "appstore") {
tabs.push(Tab::Ci);
}
tabs
}
pub fn label(self) -> &'static str {
match self {
Tab::General => "General",
Expand Down
Loading
Loading