From RPG Maker XP to Kirin: evolving the engine without leaving its games behind
Compatibility does not require technology to stand still. It requires knowing what must be preserved and what can move forward.
An application from 2026 can open a game created for a 2004 architecture. The interesting part is not merely that it works, but everything that had to change so the game would not have to.
Kirin was not created to preserve an old engine unchanged and force it to run on Android. It starts with a more useful question: which parts of that design define the game's identity and behavior, which must remain for compatibility, and which can evolve by taking advantage of modern Ruby, JIT compilation, ARM64 and a current graphics stack?
The answer does not begin with Android. It begins with RPG Maker XP, continues through mkxp and mkxp-z, and reaches Kirin as one technological history. Each stage preserves a contract with the games while reducing their dependence on the platform for which they were built.
RPG Maker XP: the starting point
RPG Maker XP was built around Windows and RGSS, its Ruby-based scripting system. A project was not just a collection of maps, graphics and sounds: it also carried code that expected the classes, timing, inputs and conventions of the original runtime.
In that context, Ruby 1.8 was not a legacy that needed support. It was contemporary technology. Screen resolution, window management, keyboard input and the path to the GPU all reflected the early-2000s PC. The design made sense in its own time.
The problem appears when that context becomes a permanent requirement. Keeping the executable, runtime and all their dependencies literally unchanged would also preserve their limitations: an abandoned platform, Windows-specific assumptions and an interpreter unable to benefit from two decades of subsequent work.
mkxp: separating the game from Windows
The first decisive change was conceptual. mkxp set out to implement RGSS as independent open-source software, able to run games without modifying their files. The game no longer had to travel with RPG Maker XP's original executable.
That separation turned RGSS into a contract. On one side were the project's scripts and assets; on the other, an implementation that could answer what those scripts expected. As long as the observable behavior stayed compatible, the internal technology could change.
Portability begins by preserving the interface a game knows—not necessarily the machine that created it.
This opened the door to other operating systems, new libraries and newer Ruby versions. It also revealed the real difficulty: an API can be documented, but a game ecosystem eventually depends on details, tolerances and historical behavior that are discovered only by running real projects.
mkxp-z: when projects demand more
mkxp-z continued that line as a fork of mkxp focused on broader compatibility. One of its original goals was running Pokémon Essentials, an especially demanding case because of the amount of Ruby it adds and its reliance on Windows APIs far beyond those of a basic project.
Over time, Essentials, its plugins and the fangames built on top of it formed ecosystems of their own. There is no single representative “RPG Maker XP game”: some remain close to standard RGSS, while others add battle systems, interfaces, data layers, animations and entire libraries.
mkxp-z accumulated solutions for that real world. Its heritage is essential to Kirin, but inheriting does not mean stopping in the same place.
Kirin changes direction
A port normally brings an application to another platform while keeping its architecture recognizable. Kirin needs something deeper. Android changes the application lifecycle, input model, file access, audio, available memory and the path to the GPU. Phones use ARM64 and respond differently to sustained load, pauses and thermal pressure.
Kirin therefore does not simply add Android to the end of mkxp-z as another box beside Windows, Linux and macOS. It examines the entire chain with mobile devices in mind: it integrates Ruby runtimes, adapts bindings, translates touch controls, connects to the system lifecycle and uses a native renderer for Android's graphics stack.
The goal remains for the project to keep its maps, events, scripts and resources. What changes is the machinery that interprets those decisions and turns them into audio, images and response.
Leaving Ruby 1.8 without leaving its games
Freezing Ruby at the version associated with the original engine may look safest, but it carries all historical debt into the future. Kirin follows another strategy: retain compatible profiles where needed while moving projects that can support it toward modern CRuby.
- Historical code
- Compatibility layer
- Modern Ruby
- YJIT / ZJIT experiments
- ARM64
The compatibility layer absorbs differences in syntax, encoding, methods and behavior. It is a delicate boundary: it must reproduce what the game needs without turning every old peculiarity into a permanent constraint on the entire engine.
Above that boundary, Ruby can continue to advance. A modern runtime brings fixes, virtual-machine improvements and the ability to compile frequently used paths. YJIT is already part of one Kirin profile. ZJIT, whose official documentation describes a method-based, profile-driven compiler, remains experimental integration work: it is not currently a production Kirin runtime, nor a promise to accelerate every game.
The distinction matters. Compatibility lives below, close to historical code. The platform keeps moving above, where it can use the phone's ARM64 processor. Preserving a game does not require preserving forever the cost of the interpreter that accompanied it in 2004.
The same evolution happens in graphics
Ruby is only half the story. The other half begins with the objects the game sees—sprites, bitmaps, tilemaps, planes, windows, viewports and transitions—and ends at a mobile GPU. Compatibility without stagnation is needed between those two ends as well.
Scripting
- Ruby 1.8
- Compatibility
- Modern Ruby
- YJIT / ZJIT
- ARM64
Graphics
- Historical OpenGL
- RGSS semantics
- Modern renderer
- OpenGL ES 3 / future backend
- Mobile GPU
To Ruby, a sprite remains a sprite. A script can assign a bitmap, change x and y, alter opacity or move the object between viewports without knowing which graphics API sits below. Bindings and the renderer abstraction transform those RGSS semantics into operations the modern platform understands.
Kirin's current production path uses OpenGL ES 3. Vulkan is an architectural possibility for the future, not a backend this article claims is implemented. A clean boundary makes it possible to investigate other paths without asking games to change their code.
The game does not need to know which graphics API exists underneath. Abstraction lets the renderer evolve without forcing every project to evolve with it.
OpenGL, Vulkan, Mesa, drivers and GPUs are not synonyms
A graphics API is a language for describing work; a renderer decides what work to produce; a driver translates commands for specific hardware; and the GPU executes them. Mesa is an open collection of graphics API implementations and drivers. It is useful for understanding how the layers are separated, but it is not a mandatory stage in Kirin's current Android path.
On many phones, OpenGL ES reaches the GPU through the driver supplied by the device vendor. In other environments, an implementation such as Mesa can occupy part of that layer. Vulkan offers a different, more explicit API model, but it does not eliminate the driver or automatically make a 2D workload faster.
This precision avoids an easy conclusion: “Vulkan is new, therefore OpenGL is bad.” OpenGL ES remains a sensible solution for a 2D engine like Kirin. The primary challenge is not drawing millions of triangles with physically based lighting or ray tracing. It is presenting many 2D images with the right order, clipping, blending and stable timing.
The real costs of a 2D renderer
A visually simple scene can produce a complicated path. A tilemap contains layers and autotiles; an interface combines many windows; an animation replaces texture regions; a menu may regenerate bitmaps; and dozens of sprites change tone, origin, zoom or viewport within the same frame.
- Texture changes
- Image uploads
- Resource creation and destruction
- Small draw calls
- CPU/GPU synchronization
- Format conversions
- Sprite ordering and clipping
- Repeated work between frames
Reducing those costs can matter more than changing the API's name. If the renderer detects that a bitmap has not changed, it can avoid a transfer. If it keeps resources alive, groups compatible operations or minimizes state changes, it sends less work to the driver. If it avoids waiting unnecessarily for the GPU, Ruby can begin the next frame sooner.
Real modernization happens in those decisions. OpenGL ES 3 currently offers a known, available foundation on Android; a well-designed abstraction leaves room for another backend when there is a measurable advantage. The criterion is not novelty, but behavior measured in actual games.
Preserve the contract, transform the machine
Seen from a script, continuity looks almost trivial:
sprite.bitmap = bitmapsprite.x = 120sprite.y = 80
Beneath those three lines is a chain that can change completely: the Ruby version, the way the method executes, the object's native representation, the rendering queue, the graphics API and the driver. The semantics remain; the implementation evolves.
This principle also makes cautious progress possible. Not every game tolerates the same runtime or benefits from the same optimization. Kirin can retain different paths, measure real projects and move the compatibility boundary without presenting every experiment as a finished feature.
One evolutionary line, not four isolated engines
RPG Maker XP defined the language the games know. mkxp showed that language could be separated from Windows. mkxp-z broadened compatibility for much more complex projects. Kirin carries that history into Android, where modern Ruby, JIT, ARM64 and a mobile graphics stack can coexist with content created twenty years earlier.
Evolution does not erase what came before. It turns it into a stable layer on which to build. Whenever a map opens, an event responds or a battle keeps its logic, compatibility is doing its job. Whenever the runtime avoids repeated work or the renderer delivers a frame more efficiently to the GPU, the platform advances.
That is Kirin's technical ambition: games should not have to choose between their history and today's hardware.
Try Kirin on Android
Read the installation guide and add a compatible project to your library.
View installation guide