Design
This article is a living document that details the design and development process of jabara.
This article does not intend to be a reference source for Nintendo Switch emulation, nor does it detail the complete operation and function of jabara (the only comprehensive resource on jabara's internals is its source code); rather, it is written in the hope that it proves useful as a general outline for the development process of a Switch emulator. As the lack of any other such detailed resources at the time led to the design and development of jabara being difficult and time-consuming, this article was written with the intent of being a helpful starting point for others seeking to develop Switch emulation software.
Purpose
jabara is a Nintendo Switch (codename NX) emulator designed to provide robust tool-assisted speedrun and superplay (generally, TAS) functionality for Switch games. Its use case differs from existing NX emulators (e.g. Eden, Ryujinx) in that it is designed primarily for TAS creation and playback with optimized real-time gameplay as a secondary target.
jabara is not a cheating tool and is not intended to give unfair advantages to real-time attack (RTA) speedrunners. jabara is not a tool for piracy or copyright violation and may only be used with legally extracted ("dumped") copies of owned NX software.
Scope
jabara cannot be used to emulate the Nintendo Switch 2.
jabara can be used on x86-64 and AArch64 machines running any modern version of most Linux distributions or Windows. Support for mobile devices is not planned.
jabara aims to provide a wide variety of tools for creating and replaying TASes. Among others, tools offered for TAS developers (TASers) include frame advance, savestates, input manipulation, memory viewing, system state and random number generation (RNG) manipulation, and debugging. All information that constitutes a particular TAS may be recorded to a movie file that can be used to deterministically replay the TAS on any instance of jabara, assuming all necessary game data are present and unchanged.
Support for physical input devices such as controllers or keyboards is an eventual goal to make jabara viable for real-time gameplay.
Foundations
Implementing TAS functionality in a fork of an existing NX emulator, such as, at the time, suyu[note 1] or Ryujinx, was considered. However, the complex and outdated buildsystem of yuzu, and, by extension, that of forks such as suyu, made forking suyu unviable, and the use of C# and .NET by Ryujinx made forking Ryujinx undesirable. To avoid having to work with such codebases, jabara became an entirely separate emulation project.
To best benefit users and developers, jabara was chosen to be a free and open source software project in order to allow free modification and redistribution and encourage community contribution. jabara is licensed under the GNU GPLv3 and can be used under the terms of any later version of the GPL. Nintendo has a history of issuing DMCA takedown requests to emulation projects,[1] especially to public GitHub repositories, so the decision was made to selfhost the relevant Git repositories on an instance of Forgejo. The public Git forge can be accessed at https://git.zelda.sr.
Due to the high performance required to efficiently emulate NX software and the portability desired of the project, the use of a low-level, compiled programming language to develop jabara was imperative. Rust was chosen for its efficiency, memory safety, portability, and robust feature set. Following initial branding, a basic Rust crate (package) structure was created and the main project repository was set up on git.zelda.sr at jabara/jabara.
This wiki, an instance of MediaWiki, was created during development to organize project design on this article. By release, this wiki will also document emulator features and provide various emulator setup and TASing guides.
Emulation
Overview
The primary goal of NX emulation is to implement enough of the NX's system on a chip (SoC), the Tegra X1, and the NX operating system, Horizon OS (HOS), to allow userland NX applications to run.
Two general approaches exist to system emulation: low-level emulation (LLE) and high-level emulation (HLE). In the simplest sense, the emulated ("guest") machine transforms input data into output data. LLE and HLE differ in that LLE emulators emulate the processes by which input data are transformed, while HLE emulators only emulate the visible results (i.e. corresponding output to given input). Many modern emulators are combinations of both LLE and HLE.
All existing NX emulators are at least in part HLE. However, unlike existing NX emulators, which contain aspects of LLE in that they generally attempt to recreate kernel classes and their functionality with relative accuracy, jabara takes an approach much closer to pure HLE, implementing kernel functionality only accurately enough such that its behavior as exposed by the HOS supervisor calls (SVCs) is accurate to what is expected by their userland callers.[note 2] This approach avoids codebase clutter and allows kernel methods and SVCs to be implemented in an optimally performant matter.
CPU
The Tegra X1 contains four ARM Cortex-A57 cores used by the NX, as well as four unused ARM Cortex-A53 cores. The Cortex-A57 implements the Armv8-A instruction set architecture (ISA). Only its 64-bit mode (AArch64) is used by HOS, so the target of jabara's CPU emulation is to emulate an AArch64 core. The instruction set used by AArch64 is known as A64.
AArch64 implements privilege as exception levels (ELs) numbered EL0 through EL3. In this exception model, exceptions may only be raised to an EL identical to or higher than that of the caller, and may only be returned from to an EL identical to or lower than that of the callee. The NX mostly follows the typical AArch64 EL software model in which userland code runs at EL0, the OS at EL1, the hypervisor at EL2, and the Secure Monitor at EL3, though the NX lacks a hypervisor. so exceptions raised by EL1 are taken directly to EL3. Because jabara emulates HOS itself, its implementation of HOS functionality can be thought of as EL1 code—however, as this code is entirely invisible to the guest system, it is not actually running at any EL. Exceptions raised to EL1 must hence be handled by jabara, and higher ELs—of which only EL3 is used by the NX—can be ignored.
In AArch64, SVCs are implemented as exceptions raised to EL1 by the SVC A64 instruction. As raising execution to EL1 is required for userland (EL0) applications to call kernel (EL1) functionality, SVCs are used for all userland calls to kernel code, and hence must be implemented in jabara in order to run userland NX applications.