用于《星际之剑》(Stars!) 4X 游戏的自定义虚拟机
A custom virtual machine for the Stars 4X game

原始链接: https://nullprogram.com/blog/2026/09/17/

1995年的4X经典游戏《Stars!》在现代64位Windows系统上变得极其难以运行。为了解决这一问题,开发者nullprogram创建了**Stars!VM**,这是一个自定义虚拟机,将原版的16位游戏封装成现代的独立32位Windows可执行程序。 该方案提供了无缝的“开箱即用”体验,支持4K缩放、现代文件处理以及经过修正的防拷贝保护机制。通过嵌入80286模拟器和Win16转Win32的桥接器,该项目无需依赖旧硬件或第三方模拟器即可原生运行游戏。得益于优化的回合生成程序和缓冲I/O,游戏性能得到了显著提升,同时保留了响应迅速且原汁原味的UI界面。 除了可玩性之外,Stars!VM还通过模型上下文协议(MCP)公开了游戏的内部状态,使人工智能代理能够“观察”并与UI进行交互。该项目还移除了与旧硬件挂钩的防拷贝保护,并为潜在的MOD开发提供了稳定的环境。Stars!VM通过将底层模拟与现代工程相结合,成功保存了这段游戏历史,使其对怀旧老玩家和新玩家都触手可及。

Hacker News 社区正在庆祝一个新项目,该项目通过定制虚拟机,让 1995 年的经典 4X 太空策略游戏《Stars!》能够在现代系统上运行。 评论区用户分享了对这款游戏的怀旧之情,并指出其深邃的战略性——如自定义种族设计、复杂的舰船建造以及广阔空间的自由移动——许多人认为其水准堪比甚至超越了现代游戏。用户们称赞原版游戏响应迅速、极简主义的界面,并将其与当代软件中常见臃肿、“粗糙”的界面进行了对比,认为前者表现更优。 在讨论这款游戏独特历史(包括其共享软件的起源以及缺乏成功的续作)的同时,也有不少人对该虚拟机方案所带来的便捷性表示兴奋。该项目为运行常在现代操作系统中出现兼容性问题的旧软件提供了一种技术解决方案,使新一代玩家和老玩家们都能有机会体验这部备受推崇的小众杰作。
相关文章

原文

nullprogram.com/blog/2026/09/17/

Stars! is a 1995 4X game (explore, expand, exploit, exterminate) for 16-bit Windows 3.1 that I first played ~28 years ago. While Windows is famously backwards compatible, it’s notoriously difficult to play Stars! today. Windows x64 cannot run 16-bit applications, and playing requires either retro hardware or emulation (otvdm, DOSBox), sometimes paired with Wine. My new, exciting solution, Stars!VM, or Stars! Virtual Machine, embeds a custom 80286 emulator and a Win16 to Win32 bridge. As native Win32, the game looks and feels exactly as it did originally, except sporting a modern file chooser and 4k scaling. It’s indistinguishable from a genuine 32-bit or 64-bit port of the game, especially with the original 16-bit game embedded inside the VM executable.

The signed releases on GitHub embed a compressed copy of the original 16-bit game, so that single EXE is ready to play out-of-the-box with no further setup or downloads. I’m distributing 32-bit builds (but requires SSE2) because there’s no advantage to 64-bit here, and these builds work (almost) everywhere except 16-bit Windows. 32-bit Windows could run the original 16-bit game, but the VM-encapsulated version is better behaved. It doesn’t dump a Stars.ini under C:\WINDOWS, it interacts properly with the task bar, and copy protection is neutralized via the OS bridge.

If you ever been curious about Stars!, now’s the time to try it. The game has a thorough, built-in tutorial, but also check out the wiki, the official strategy guide, and AutoHost (play-by-email service). The game predates the modern search engine concept, otherwise they might have chosen a better name. I suggest using “stars 4x” in your searches.

If you want to build from source and hack on the VM yourself, the best tool for the job is w64devkit, of course, because it comes with everything you’ll need. Plus the game itself: stars.exe from stars27jrc3.zip.

Implementation details

The emulator itself requires x86 or x86-64 because it does not implement x87 (80-bit floating point) in software, but instead runs these operation directly on the host’s x87 hardware. This is simple, fast, and precise. The project validates the emulation as a whole with a differential fuzzer against the host. The fuzzer randomly generates a 16-bit instruction, emulates it, then runs it with JIT on the host and compares the results.

Handles on Windows are pointer-sized, and so the Win16-to-Win32 bridge maps 16-bit handles to host handles. It marshals between different struct layouts when translating these calls, services the DOS interrupts the game requires, an copies data in and out of guest memory. It’s rather like running a Wasm instance, which of course makes sense in retrospect.

The Win32 bridge is also monitorable and manipulatable using the Model Context Protocol (MCP). AI agents can “see” the UI “DOM” as it’s built, and can drive it by injecting synthetic events into the event pump, all without going through the usual desktop control. The MCP can also read and write guest memory. Opus 5 played a complete game through MCP — which is quite fun to watch — requesting my assistance at just two points when it got stuck in the UI. A foundation for a new Stars!Bench?

Targeting old 16-bit computers, the authors couldn’t afford to build a sloppy, wasteful UI, and so by modern standards the game UI is remarkably fast and responsive. They don’t make ‘em like they used to. Computing the next turn, or “turn generation,” is the computational bottleneck, and so that’s where I focused my optimization efforts. The emulator can trace executed instructions, so I gathered traces of turn generation, then had Fable 5.1 identify and reverse engineer the hottest common routines (e.g. the game’s L’Ecuyer MCG PRNG) and basic blocks. Each was re-written in C and mapped into the instruction decoder as new 80286 instructions. On load the emulator identifies these routines and patches them with the new instruction. This resulted in a nearly ~2x speedup of turn generation. By exploiting local conditions, emulating a particular known program, I get JIT performance without JIT complexity.

The original game doesn’t use buffered I/O, and instead issues many small reads and writes. Passing these small reads/writes straight to Win32 made I/O take ~5% turn generation time, probably worse today than it was back then. Plus it’s just rude. The emulator buffers the game’s I/O calls, further speeding up turn generation.

The game has some sound effects in the “battle VCR” and the final version of the game shipped with Microsoft’s WaveMix.dll. Rather than load and link this DLL, the emulator implements the DLL’s interfaces natively, and these routines are dynamically linked into the 16-bit process. You will not need this DLL with the emulator, nor is it embedded in releases.

The game also has art assets embedded uncompressed in the original EXE, forming the bulk of its ~3MB. Stars!VM uses a custom LZ-based compression algorithm tailored to compressing the original game. It’s compressed when embedded in releases. So the 32-bit version of the game is half the size of the original, at ~1.5MB.

The original game requires a serial code, serving as its copy protection. A code is 8 alpha-numeric characters that must pass two checks. Failing the first is loud, but failing the second will sabotage your game with penalties. You’ll know because it will announce that your people suspect you are a usurper. Most codes you’ll find online are such “usurper” codes. Play-by-email (PBEM) saves embed a hardware signature derived from C and D drive configuration. People playing on different machines using the same serial code recieve the usurper penalty.

I bought a serial code back in the day, but it hasn’t been possible to purchase one a for at least decade now. So the emulator injects a fixed serial code on first run (disable with --prompt-serial), and you won’t need to worry about it. The VM also produces a fixed hardware signature (same as any other emulator), so it looks like everyone running Stars!VM is sharing the a machine, meaning no penalty for key reuse. I cracked the serial code checks anyway, allowing me discover interesting ones. My favorites: CLONEMUM, CROSSNUT, EGGSWAIN, GHOSTKIN, GONKSHOW, GRIPMIME, SEEKCAPS, SIFTBOLD, SIRBUOYS, SLIMFAZE, SLOTMOPS, SPAWNELK, SUNBLOND, WANTNEAR, and WRONGPOX. These look like some of my passwords.

Endless possibilities

I’m quite pleased and excited with the results, especially for a weekend project. It’s breathed life back into the game for me, not only having a better experience running it, but also that I can trivially bend the game to my will in the ways I dreamed about. A few hooks in the right places should open the game to easy modding, but I’m more engineer than modder.

联系我们 contact @ memedata.com