# D2R Mobile
**An open-source compatibility layer for Diablo II: Resurrected with the Reign of the Warlock expansion, for iOS, macOS, Android and HarmonyOS.** It brings the Nintendo Switch release you bought, expansion included, to iPhone, iPad and Mac in full: the original game code runs natively, every control is rebuilt for touch, the frame rate holds at 60 fps, and you are in a game one second after the main menu. There is now a native macOS version as well (first version): on an Apple silicon Mac it starts on double-click and works with keyboard, mouse and gamepad. **Since v2.0 there is an Android version** (community port): the same game program executes natively on ARM64 Android phones, with the graphics reimplemented on Vulkan; on a Snapdragon 8+ Gen 1 phone the camp and the Den of Evil and Cow Level fights all run at a median 60 fps (see "Android" below); a HarmonyOS version runs on the same engine (community port: an unsigned shell from the Releases page that you re-sign yourself, nothing to build; see "HarmonyOS"). Apple TV 4K (3rd generation, A15) has a community port (developer preview) that has reached the character-selection screen only on its author's device; see the device table below.
This is not a tech demo that "sort of runs". It is a mobile version polished for daily play, from your first character all the way through the endgame.
Platforms: iPhone / iPad (iOS 26 and later; iOS 18 – 25 with the older-API build) · Mac (Apple silicon, macOS 26 or later; macOS 15 – 25 with the older-API build) · Apple TV 4K (3rd generation, A15; community port, developer preview) · Android phones (ARM64, Android 12 or later, Vulkan 1.1; community port) · HarmonyOS phones (HarmonyOS NEXT; community port, unsigned shell from the Releases page that you re-sign yourself) · Game version: Switch release with Reign of the Warlock, 1.0.34.0 (corresponds to PC version 3.3.94012) · English / 中文 / Español / Русский / 한국어 · License: MIT · **Bring your own game files**
中文: [README.zh-CN.md](README.zh-CN.md) · Español: [README.es.md](README.es.md)
| 100% | 60 fps | about 1 s | about 3.8 W |
|:---:|:---:|:---:|:---:|
| The original gameplay, because it is the original program | Steady, with no drops once the device warms up | From the main menu into a game | Whole-device power draw at 60 fps |
## What it is, and what it is not
**It is:**
- The game's own aarch64 program, **executing directly on the device**, with no emulated CPU. iPhone and Switch use the same class of processor; only the handful of instructions that cannot run unchanged under Apple's kernel are rewritten, and every other byte of the program is left exactly as shipped. Every class, every Runeword, Terror Zones, bosses, drop rules and quest flow are identical to the original.
- The platform services the game expects — system calls, the file system, the graphics API, audio, input — provided by a small host written for Apple platforms. The graphics API is reimplemented entirely — on Metal on Apple devices, on Vulkan on Android — with no emulation layer in between, and the shaders are translated offline from the game's originals.
- A port built for phones, and taken all the way: a complete touch control scheme, edge-to-edge iPhone and true full-screen iPad display, controller support, a power saver mode, save sync, five languages (English, Chinese, Spanish, Russian and Korean), and a whole set of endgame modes and quality-of-life features the original never had.
**It is not:**
- An emulator, cloud gaming, or streaming.
- **A source of game content. It contains none and distributes none.** There is no game program, art, text, data table or shader in this repository; all of that is generated on your own machine from your own files (see [docs/GAME_FILES.md](docs/GAME_FILES.md)). What the repository does carry is the interface information we recorded to make the port work — shader interface descriptions, the graphics API function table, addresses inside the program and the like — listed item by item in [docs/DERIVED.md](docs/DERIVED.md).
- Online. There is no multiplayer; the game runs fully offline and needs no online account.
## Battle-tested
All **44** iPhones and iPads in the closed beta — 35 devices registered for direct install (25 iPhones and 10 iPads), plus 9 TestFlight accounts with one device each — **completed Normal, Nightmare and Hell with multiple characters**, and the experience was excellent. From an iPhone 14 Pro Max with 6 GB of memory to the latest iPad Pro, not one device fell behind.
| | Models |
|---|---|
| iPhone | 14 Pro Max, 15, 15 Pro, 15 Pro Max, 16 Plus, 16 Pro, 16 Pro Max, 17 Pro Max and more |
| iPad | iPad Air, iPad mini, iPad Pro 11-inch and 12.9 / 13-inch (including M2 and M4) and more |
| Lowest model tested | **iPhone 14 Pro Max (A16, 6 GB): a flawless 60 fps** |
iPhone and iPad share a single install package.
## Fast, smooth, and easy on the battery
Measured on a real device (iPhone 17 Pro Max):
| Item | Reading |
|---|---|
| In-game frame rate | **60 fps**, steady, with no drops once the device warms up |
| App launch | 0.15 s |
| To the main menu | about 1 s |
| From the main menu into a game | **about 1 s** |
| Quick Restart, back in a game | about 1.2 s |
| Longest frame when changing acts | about 0.1 s |
| Whole-device power, 60 fps | **about 3.8 W** (in camp, 50% brightness): nearly 5 hours of continuous play on a full charge |
| Whole-device power, power saver mode at 30 fps | **about 1.85 W**, about half the 60 fps figure, for about twice the battery life |
Measurement conditions: power is whole-device power measured on 2026-10-10 on an iPhone 17 Pro Max, standing in the Act I camp at 50% brightness, with 60 fps and power saver mode measured in the same scene; battery life is calculated from the measured power and the battery capacity, not by playing from full to empty. Launch and game-entry times were measured on the same model in 2026-10; frame rate and act-change readings were taken on the same model on 2026-10-12 while moving through areas and changing acts after entering a game.
The install package is only a little over 100 MB. The game resources (about 5.6 GB) are placed on the phone separately, and updating the app touches neither your saves nor the resources.
Why it is this fast: the program executes natively, and not a single instruction goes through emulation; graphics go straight to Metal; every shader is translated offline and compiled ahead of time, so nothing is compiled when you enter a new scene. Older chips (A16 and earlier, such as the iPhone 14 family and iPhone 15) do not support the game's original compressed texture format; they need an extra texture pack made from your own game files, and then run at full frame rate too — see [docs/LEGACY_DEVICES.md](docs/LEGACY_DEVICES.md).
## Redesigned for fingers
This is not a gamepad pasted onto the screen. Every panel and every action was rebuilt for fingers under one design principle: **keep the original interface language, and use gestures instead of adding buttons to the screen**. Text sizes and tap targets are sized for fingers. You know how to play the moment you pick it up, and it stays comfortable over long sessions.
- **Move**: a virtual stick with precise diagonals; tap an NPC or the ground to path there automatically; doors, portals and cave entrances are tappable across their whole surface.
- **Fight**: press a skill button to cast, hold to keep casting, **drag to aim at any angle**; nearby monsters are targeted automatically. Two skill sets. Skills on your secondary weapons cast with one tap — the game swaps weapons, casts, and swaps back — and the button shows the charges remaining.
- **Boss health bar**: pinned to the top of the screen, showing the percentage remaining.
- **Items**: tap, double-tap, long-press and drag and drop all track your finger. Double-tap gear to equip or unequip it; drag an item anywhere onto the vendor panel to sell it; on a stack, double-tap takes 1 and long-press takes 3; long-press an empty inventory slot to sort everything.
- **Text**: typed with the system keyboard. Character names can be in Chinese; leave the name blank for a random one.
- **Screen**: on iPhone the 19.5:9 display is filled edge to edge, clear of the notch and rounded corners; on iPad the game fills the entire screen, and the interface centers itself when you open a panel; the 3D picture can be brightened.
### Controller
Connect a controller and press any button: the interface switches to the original controller layout, with button prompts at the bottom of every panel. Touch the screen and you are back in the touch interface instantly. Inventory, stash, skill tree, Chronicle and settings are fully controller-navigable, with the same button mapping as on Switch. With an Xbox controller the layout switches automatically to the PC / Xbox one (bottom confirms, right goes back) and the prompts show Xbox button icons; there is nothing to turn on. With a PlayStation controller (DualSense or DualShock 4) the prompts switch to the game's own PlayStation button icons (✕ confirms, ○ goes back), contributed by [@Ti800](https://github.com/Ti800) ([#119](https://github.com/jhaizhou-ops/d2r-mobile/pull/119)).
## New ways to play, on top of the original
Finishing the original game is only the beginning. Without touching the original rules, we added a full set of endgame content that keeps you farming.
### Greater Rift
Enter through the red portal in Harrogath after completing Hell. There are 100 levels, and the monsters grow stronger with each one; fill the progress bar and slay the Rift Guardian within 15 minutes to clear a level. Every 2 levels cleared grants +1 Skill Point and +5 Stat Points, and the skill level cap rises from 20 to 40. Every 10 levels has a first-clear reward, and clearing level 10 unlocks six new equipment slots for your mercenary.
### Endgame Boss Rush, Elysium mode, and the Kill Board
- **Endgame Boss Rush**: unlocks after completing Hell, with 12 stages; stage 11 is Diablo Clone, and stage 12 is the three Uber bosses.
- **Elysium mode** (chosen at character creation): Unique ×5, Set ×3, Runes ×5; the "no drop" chance is cut to a tenth, and bosses always drop as on a first kill.
- **Kill Board**: for every boss, the number of kills, the time of the first kill, how many Unique and Set items it has dropped, and your best and average kill times.
### Storage: a collector's paradise
- **Chronicle stash**: every identified Unique and Set item has its own fixed slot, shared by all characters, searchable, with deposit and withdraw; the Deposit button sends the Unique and Set items in your inventory and Horadric Cube there in one tap.
- **Stash**: widened to 14 columns, with 5 personal pages and 5 shared pages.
- **Trove**: the gem, rune and material pages merged into one, with the Horadric Cube's crafting grid in the middle, so finding things and crafting no longer means flipping between pages. Runes, gems and materials you put into the personal or shared pages are filed here automatically.
- **Pouch**: an extended inventory. Runes and gems found in the field go into it automatically and take up no inventory space.
### Effortless farming
| | |
|---|---|
| Auto-recast buffs | Buff skills you have learned do not need a slot on the skill bar: when a buff runs out, it is recast the moment you stand still; buffs that come from your secondary weapons (such as Battle Orders from Call to Arms) swap weapons, recast and swap back on their own |
| Potions and belt | Auto-drink has two tiers: a healing potion below 50% Life, a rejuvenation potion below 30%; **your mercenary is fed automatically by the same rule**. Potions on the ground are picked up automatically when the belt has room; double-tap an empty belt slot to refill the whole belt |
| Loot filter | From Nightmare on, the original loot filter is switched on automatically to hide clutter: light filtering in Nightmare, heavy in Hell |
| Auto-pickup | Low runes and gems go straight into the Pouch; the high ones are left for you to pick up yourself |
| Valuable drop alerts | High runes and Unique items raise a light beam and land with a different drop sound; the phone vibrates at one of three strengths — light, medium or heavy — according to value |
| Runeword helper | Long-press a socketed base to list the Runewords it can make and their stats; once you have the runes, socket them all in one tap |
| Minimap guidance | Every map marks its Waypoint and exits; every quest goal is on the map; when a target is off screen, its name is written along the screen edge |
| Chores removed | Free identification, free Town Portal with no scrolls needed, spawning right beside the Waypoint, Quick Restart, refreshable vendor stock |
| Saves | Saved immediately when you switch apps, swipe the app away or quit; iCloud sync across devices (requires signing with a paid developer account) |
Most features can be toggled one by one in game under Options → Custom.
### English, Chinese, Spanish, Russian and Korean
The whole game switches between English, Chinese, Spanish, Russian and Korean under Options → Custom; after a restart, the interface is in the language you chose. On first launch it follows your device language (Spanish from Spain uses the game's esES text, other Spanish regions use the Latin American esMX text). In English, Spanish, Russian and Korean, items, skills and monsters use the original Diablo II wording, and everything we added — Greater Rift, Chronicle, the settings page, gesture prompts, map name plates — is translated too (item notes are translated for Chinese and Spanish only). Russian is the game's single ruRU text and Korean its koKR text, with no regional variants. Voice acting: Chinese UI gets Chinese voices; Russian and Korean get the original Russian or Korean voices when your game files include them (a package built from the complete game data does), otherwise English; everything else is English. Korean was contributed by [@soulsakura](https://github.com/soulsakura) ([#118](https://github.com/jhaizhou-ops/d2r-mobile/pull/118)).
## How it works
```mermaid
flowchart LR
G["Your game files
(program + resources)"] --> P["Rewriter
changes only a few instructions"]
G --> S["Shader translation
original → Metal"]
P --> H["Host
system services"]
S --> X["Graphics layer
the graphics API on Metal"]
H --> A["iOS app
touch and interface"]
X --> A
```
| Part | Where | What it does |
|---|---|---|
| Program rewriter | `dm/tools/patch_nso.py` | Rewrites only the few instructions that cannot run unchanged under Apple's kernel (thread-pointer registers, system calls, timers) and leaves the rest of the program byte-for-byte as shipped |
| Host | `dm/host` | Loads the rewritten program and provides the platform services it calls |
| Graphics | `dm/gfx` | Implements the game's graphics API on Metal; shaders are translated offline from the game's originals |
| iOS app | `dm/ios` | The app shell, touch controls and interface |
| Android app | `dm/android` | The Android shell, touch overlay and Vulkan presentation |
| HarmonyOS app | `dm/harmony` | The HarmonyOS shell (ArkTS + N-API), sharing the host and the Vulkan engine with Android |
| Vulkan graphics | `dm/gfx/vulkan` | The same graphics API on Vulkan (shared by Android and HarmonyOS; the engine comes from the HarmonyOS port) |
| Verification | `dm/verify` | Checks that the rewritten code behaves exactly like the original, plus the regression gates every change goes through |
**Why you can trust it:** the stability is not luck. The test and verification tooling is part of the project — unit tests for the host and graphics layers, an equivalence check for every rewritten instruction, scripted walkthrough regression for the touch interface, and on-device smoke tests. Start with `make -C dm/host/tests run`, `make -C dm/gfx/tests run` and `dm/verify/regress.sh` (run them inside the Python environment prepared in step 2 below; `regress.sh` also needs `brew install llvm`). How to contribute is in [CONTRIBUTING.md](CONTRIBUTING.md).
## Android (new in v2.0)
Android phones use ARM64 processors just like the Switch, so, as on Apple devices, the game's own program executes directly on the phone with no CPU emulation. This release brings the whole host — system calls, file system, audio, input, saves — to Android unchanged and swaps the graphics layer for Vulkan: the NVN-to-Vulkan replay engine comes from [@biglawine](https://github.com/biglawine)'s HarmonyOS port, and the Android app, touch controls, Vulkan presentation and a full round of performance work, each step measured on a phone, are by [@yyan160](https://github.com/yyan160) ([#113](https://github.com/jhaizhou-ops/d2r-mobile/pull/113)). The Apple and Android versions share the same host code, so future changes benefit both.
Measured by the port's authors on their phones (product defaults: 3D render scale capped at 0.85 and lowered dynamically when frames drop):
| Phone | Result |
|---|---|
| Redmi K50 Ultra (Snapdragon 8+ Gen 1, Adreno 730, Android 15) | Camp, Den of Evil fight, Cow Level fight: **median 60 fps**, GPU about 14–15 ms a frame |
| OnePlus 13 (Adreno 830) | Playable; when one particular light effect appears in the camp, small black squares occasionally flash for an instant (under investigation) |
Minimum: ARM64, Android 12 (API 31) or later, and a GPU with Vulkan 1.1.
**How to use it today**: install `D2RMobile-android.apk` from the release page (it contains no game content). On a computer, run `python3 dm/tools/d2rm_android.py