# emupc

> **Tool `tools/live/emupc.py`** (program, The running game). Write the files that run the original in an emulated x86-64 PC: QEMU, a Debian cloud image, cloud-init, Wine with 32-bit libraries, Xvfb and a window manager, and the game's disc as a CD-ROM drive.

Run it with `./gameframe run emupc ARGS` or `python3 tools/live/emupc.py`. [Source on GitHub](https://github.com/tanepiper/game-frame/blob/main/tools/live/emupc.py).

## Its own help

This is the help text in the tool itself, as `./gameframe tool emupc` prints it.

```text
Write the files that run the original in an emulated x86-64 PC: QEMU, a Debian cloud image,
cloud-init, Wine with 32-bit libraries, Xvfb and a window manager, and the game's disc as a
CD-ROM drive.

Usage: emupc.py init DIR --image QCOW2 --key PUBKEY [--disc ISO] [--memory 4G] [--cpus 4]
                        [--ssh-port 2222] [--disk 20G] [--name gf-vm-PROJECT]
       emupc.py image                 print where to download the Debian cloud image

  DIR        the VM's folder, which git ignores (derived/vm)
  --image    the Debian cloud image (a .qcow2 you downloaded; see `emupc.py image`). It is
             never changed: the VM writes to an overlay, DIR/disk.qcow2
  --key      your SSH public key (~/.ssh/id_ed25519.pub), for the VM's user `gf`
  --disc     the game's disc as an ISO (tools/disc/discinfo.py IMAGE --iso FILE cuts the data
             track out of a BIN/CUE), attached as a CD-ROM drive
  --ssh-port the port on this machine that reaches the VM's SSH (default 2222). Each game has
             its own VM, so each needs its own port: init refuses a port that something else
             already listens on
  --name     the VM's host name and SSH alias (default gf-vm-PROJECT, from the project folder
             in GAMEFRAME_PROJECT, which ./gameframe sets; gf-vm without one)

It writes:

  DIR/cloud-init/user-data   the user, the key, and the first-boot steps: the i386
                             architecture, Wine, Xvfb, openbox, xdotool, rsync, 32-bit Mesa,
                             and a udev rule that makes the CD-ROM readable by everyone
  DIR/cloud-init/meta-data   the instance id and host name
  DIR/ssh_config             `ssh -F DIR/ssh_config NAME`, with IdentitiesOnly
  DIR/start.sh               makes the cloud-init seed, the overlay disk, then starts QEMU in the
                             background (serial log in DIR/serial.log, pid in DIR/qemu.pid)
  DIR/stop.sh                stops it

Why: when Wine on the host fails in ways no patch fixes (Wine under Rosetta on Apple silicon,
docs/knowhow/wine-wow64-rosetta-fault.md), an emulated x86-64 Linux with Wine runs the game
as Wine on a PC would. Each choice here fixed a failure (docs/knowhow/context-emulated-pc.md).
Files go over rsync and SSH because the cloud kernel has no 9p. The disc is a real CD-ROM
device because Wine on Linux reads the drive type and label from the device. Xvfb runs with a
window manager because without one no window becomes the foreground. Then DirectInput reads
no keys.

One VM per game: give each game project its own DIR (its derived/vm), port and name, and
never run one game in another game's VM. A shared VM ties a game to another project's
machine, its load and its changes, and puts one game's files inside the other's.

It does not download anything, install QEMU or copy the game. Copy the install folder in with
rsync over SSH. It needs qemu-system-x86_64 and qemu-img, and one of cloud-localds,
genisoimage, mkisofs, xorriso or hdiutil to make the seed. Standard library only.
```
