<p align="center">
  <img src="SchwertUndMagieOnPebbleCompanionApp/res/app-icon-round.png" width="290" alt="App icon">
</p>

# Schwert und Magie on Pebble

A port of the classic German C64 text-adventure RPG series **Schwert und Magie**
(German Design Group, 1989–1992) to the Pebble Time 2 smartwatch.

## Architecture

The phone runs VICE 3.8 as a companion app and streams the C64 text screen to
the watch. Button presses on the watch flow back to VICE via Bluetooth.

![System overview](docs/diagrams/system-overview.png)

## The game

*Schwert und Magie* is an 8-episode text-adventure / RPG series for the
Commodore 64, published in German by boeder-Verlag. Two episodes share one
disk:

| Disk | Episodes |
|------|----------|
| I   | Folge 1: Das geheimnisvolle Kraut · Folge 2: Der unheimliche Tempel |
| II  | Folge 3: Das Piratenhaus · Folge 4: Die Burg des Magiers |
| III | Folge 5: Das Haus des Vampirs · Folge 6: Der Turm des Todes |
| IV  | Folge 7: Unter Wasser · Folge 8: Insel der Wunder |

The copy-protection scheme asks for a word from the printed *Anleitung*
(manual). The app includes the full manual text with a look-up button (📖) so
you can answer the prompt without keeping the paper around.

## Repository layout

```
SchwertUndMagieOnPebbleWatchApp/      Pebble watchapp (C + PebbleKit JS)
SchwertUndMagieOnPebbleCompanionApp/  Android companion app (Kotlin + NDK)
versions/                             Original .d64 disk images (4 disks)
docs/                                 Architecture notes and diagrams
build-image/                          Dockerfile for the release build environment
dist/                                 Build artifacts (gitignored) — see dist.sh
```

Run `./dist.sh` to build release artifacts for both apps in one step:
`dist/schwert-und-magie-<version>.{aab,apk,pbw}` — the signed Android AAB
(Play Store), APK (sideload), and Pebble `.pbw` (Rebble / direct install).
Requires the Android release keystore to already be configured
(`docs/publish.md` §2.1-2.3). The version comes from the current git tag by
default (`git tag v1.2.3`); see `docs/publish.md` §4 for pushing that tag to
trigger an automated, containerized build via Gitea Actions instead.

## How it works

Three processes cooperate across two devices:

```
Pebble watch
  │  Bluetooth AppMessage
  ▼
Core for Pebble (on phone) — PebbleKit JS bridge
  │  HTTP on 127.0.0.1:8888
  ▼
Android companion app — NanoHTTPD server
  │  JNI
  ▼
VICE 3.8 (C64 emulator, cross-compiled for ARM64/x86_64)
```

The watch displays the C64 text screen (40×25 cells) in a scroll view and
provides a key wheel for the number keys most used by the game. The companion
app renders VICE's 320×200 framebuffer on-screen and also provides a virtual
C64 keyboard for direct input.

See [`docs/architecture.md`](docs/architecture.md) for the full design.

## Requirements

- **Android phone** running Android 7.0+ (API 24)
- **Pebble Time 2** (or any Pebble running firmware 3.x — the `.pbw` targets
  all SDK 3 platforms)
- **Core for Pebble** installed on the phone (the community Pebble app)
- **C64 ROM files** — `kernal`, `basic`, `chargen`, `1541` — legally obtained
  from your own C64 or from Cloanto's C64 Forever. The app prompts you to
  import them on first launch; they are never bundled.
- **Disk images** — `.d64` or `.g64` files for the four game disks. You can
  import your own or use the in-app **Fetch Disks** button to download
  community-preserved dumps from the Internet Archive's C64 Preservation
  Project (requires nibtools, which is cross-compiled automatically).

## Building

### Android companion app

```bash
cd SchwertUndMagieOnPebbleCompanionApp
./gradlew assembleDebug        # debug build
./gradlew assembleRelease      # signed release build (requires keystore.properties)
./gradlew installDebug         # build + install on connected device
```

VICE 3.8 and nibtools are cross-compiled automatically the first time — the
Gradle `buildVice` and `buildNibtools` tasks unpack the source tarballs from
`res/` and build `libvice.a` / `libnibtools.a` for ARM64 and x86_64. The NDK
must be installed (Android Studio → SDK Manager → SDK Tools → NDK (Side by
side)).

### Pebble watch app

```bash
cd SchwertUndMagieOnPebbleWatchApp
pebble build
pebble install --phone <phone-ip>
```

In headless / CI environments add `--vnc` to every emulator command.

## Getting disk images onto the device

**Option A — Fetch Disks button** (in-app)  
Opens a dialog, downloads all 8 episode disks as `.nbz` files from the
Internet Archive C64 Preservation Project, and converts them to G64 using
nibtools. Requires a network connection; conversion runs on-device.

**Option B — manual copy**  
Copy `.d64` or `.g64` files to the app's external files directory via USB or
`adb push`, matching the names expected by the drawer (e.g. `SCHWUM1A.D64`).

## Hero saves

Hero characters are stored on separate hero disks (up to 3 slots). The app
manages these from the drawer — create a new hero disk, load an episode disk,
then swap to the hero disk when the game asks for it. A built-in stat editor
lets you inspect and edit a saved hero's attributes directly.

## Save states

The 💾 button saves or restores a full VICE snapshot (CPU registers, RAM,
VICII, SID, CIA) to one of three slots. Snapshots go through a CPU trap to
ensure register consistency — see `docs/architecture.md §4.4`.

## Publishing

See [`docs/publish.md`](docs/publish.md) for keystore setup, Google Play,
F-Droid, and Rebble submission.

### Automated releases (Gitea Actions)

Pushing a tag `vX.Y.Z` builds both apps in a containerized runner and
publishes a Gitea Release with the versioned artifacts attached — see
`docs/publish.md` §4. One-time setup:

1. Build the build environment image locally and push it (`./build-image.sh`
   then `./upload-image.sh`, needs `registry.env` — copy from
   `registry.env.example`). Use `./run-image.sh` in between to sanity-check
   the image before pushing.
2. Register a self-hosted `act_runner` with a Docker executor.
3. Add repo secrets under **Settings → Actions → Secrets**:

   | Secret | Value |
   |---|---|
   | `RELEASE_KEYSTORE_B64` | `base64 -w0 SchwertUndMagieOnPebbleCompanionApp/release.keystore` |
   | `RELEASE_KEYSTORE_PROPERTIES` | full contents of `SchwertUndMagieOnPebbleCompanionApp/keystore.properties` |
   | `REGISTRY_USER` / `REGISTRY_PASSWORD` | same as in `registry.env`, so the runner can pull the private build image |

   `GITEA_TOKEN` is injected automatically per job — nothing to add for it.
4. `git tag v1.2.3 && git push origin v1.2.3`.

Full details, including runner registration commands, are in
`docs/publish.md` §4.

## License

The watch app and companion app source code in this repository are released
under the **MIT License**.

The *Schwert und Magie* game content (disk images, manual text) remains the
property of its original authors and is not part of this license. VICE and
nibtools are GPLv2 and are built from source at compile time; their source
tarballs in `res/` are not covered by this repository's MIT license.
