The following content is a rough translation by Github Copilot of the original post in Chinese.
The goal of Retrohos is to serve as the implementation of the RetroArch Frontend on OpenHarmony/HarmonyOS and to complete the porting of emulator cores from various communities, while also supporting the vision of distributed applications in the Harmony framework (e.g., experiences such as using a large screen display while the phone functions as a controller).
Since I previously only have rudimentary experience in Android mobile development (controlling Android screen casting via NDK), this log is merely a record of the application development exploration process, not the best implementation, and is for reference only.
What is Libretro
RetroArch is a very popular retro gaming console solution. It doesn’t provide any emulator functionality itself but acts as an aggregator for community emulators (Emulator Core) and provides a common interface definition, Libretro. The following introduction is generated by ChatGPT:
Libretro is a lightweight game console emulator core framework. Through the Libretro API, game cores (Core) can be separated from the frontend (Frontend), enabling cross-platform porting of cores and supporting multiple frontends such as RetroArch, Lakka, etc. The Libretro core is a dynamic link library that, through the Libretro API, can initialize game cores, handle input/output, and render audio and video.
Libretro effectively separates the components of the emulator, allowing us to ignore the implementation of existing frontends (and their different GUI technology stacks) and focus on porting the core and integrating it with the system. Therefore, the goal of the Retrohos project is to implement a frontend compatible with the Libretro API while porting community Emulator Cores, rather than a complete port of RetroArch.
Preparing the NDK Environment
For OpenHarmony development, I recommend using the HarmonyOS commercial release and the developer beta SDK provided by Huawei, rather than the community open-source version of OpenHarmony. Although the two currently have little difference (HarmonyOS Next Beta1 is based on OpenHarmony 5.0.0.xx), the only available and mature ecosystem is HarmonyOS. This is an unavoidable reality.
Fortunately, OpenHarmony NDK development is similar to Android and does not require the official IDE (DevEco Studio). The following development content will be based on command-line tools and performed on a Linux platform (Ubuntu 22.04.3 LTS).
Taking the latest official Linux version SDK (5.0.0.800
) as an example, let’s assume the commandline-tools.zip
archive has been downloaded and extracted to the $HOME
directory. To differentiate version numbers, rename the extracted directory to command-line-tools/5.0.0.800
and create an env.sh
file with the following content:
|
|
Afterward, when using it, simply execute source env.sh
. This file mainly serves the following purposes:
- Sets SDK-related environment variables. The variable names here are not specific requirements, just for easy reference.
$NDK_ROOT
points to the root directory of the NDK, making it easy to reference the compilation chain tools and link thesysroot
.- Prepend the paths of
cmake
andllvm
to$PATH
, overriding the system’s default compilation toolchain to ensure the use of the NDK-provided toolchain.
According to the official NDK development documentation, when calling the NDK-provided cmake
compiler, the following parameters need to be passed (using aarch64-linux-ohos
as an example):
|
|
Among them, CMAKE_TOOLCHAIN_FILE
is the most important, specifying the configuration file of the compilation chain, which will automatically link the sysroot
provided by the NDK.
Porting Libretro Cores
Attempting to Port libretro-super
The libretro/libretro-super
repository is a project for managing Libretro cores and RetroArch compilation scripts on different platforms, organized according to the target triplet identifier. Initially, I thought that OpenHarmony’s underlying system was just the Linux kernel’s aarch64
architecture, and the dynamic libraries in the toolchain were quite common, unrelated to the SDK. Therefore, I attempted to directly port this super project. Unfortunately, due to the fact that the ohos
/ OHOS
identifiers are not supported by many upstream dependencies and it will not automatically downgrade to the aarch64 Linux build process, a brute-force port would only lead to endless dependency resolution.
Therefore, the most appropriate solution is to use only the Libretro Core build process (forking repositories one by one for modification 😓) and abandon the overall porting of libretro-super
, which is too messy. At the start of this project, we focused on porting the ppsspp core: it provides the option to build the ppsspp-libretro
dynamic library with few third-party dependencies and was the first core to be successfully built.
Compiling the ppsspp-libretro
Core
Building the ppsspp-ffmpeg
Static Library
The hrydgard/ppsspp
repository introduces multiple third-party dependencies through .gitmodules
, among which only the hrydgard/ppsspp-ffmpeg
maintained by itself requires additional handling to add the OHOS
architecture string. Refer to android_arm64_v8a.sh
and correspondingly add the content of the ohos_arm64-v8a.sh
file as follows:
|
|
After preparing the NDK environment with source env.sh
, execute the build script to generate static library files such as libavcodec.a
under ohos/arm64
, as well as header files under the include
directory. After submitting the relevant changes, you can point the submodule in ppsspp-libretro
to our modified repository Retrohos/ppsspp-ffmpeg
.
Building ppsspp
The porting of ppsspp-libretro
itself is relatively simple, only requiring the addition of OHOS architecture judgment in CMakeLists.txt
and modification of the compilation options in CMakeLists.txt
. The patch content is as follows:
|
|
After modifying, execute the following command to build the ppsspp-libretro
core:
|
|
which will generate the build
directory, and execute make -j4
within it to generate the lib/ppsspp_libretro.so
file.
Future Plans
As the project’s initial stage, the completion of a core port is sufficient for subsequent frontend development. The next step is to design a simple Libretro frontend and bind it through ArkTS NAPI to quickly implement framebuffer output. As for more important GUI design, we can wait for the improvement of the DevEco Studio development suite (~oï¿£3ï¿£)~