Astral

astral running minecraft

Being able to play games on your homebrew operating system is a great milestone to strive for. It shows that the system is implemented well enough to run graphical applications and receive input, that it is fast enough to be playable and that it is stable enough to play games. Generally, the game of choice is Doom, as it has the reputation of porting everything under the sun, plus it is an FPS game that can demonstrate all of the above points about your operating system.

Astral currently has a few working game ports, including Doom and Quake. However, as the capabilities of operating systems increase, so will the complexity of the games that can be played. I’ve been thinking about adding a new game port for quite some time now, and I finally decided on a game I played a lot as a kid: Minecraft.

Challenges of running Minecraft

Minecraft is not an easy game to play. It is written in Java, so you need a working JVM. It uses OpenGL, so you also need a working OpenGL implementation. Additionally, it depends on many different Java libraries that you have to port as well. Astral has been porting OpenJDK 17 and Mesa for some time. The Mesa port works perfectly, but the OpenJDK port got a bit buggy and eventually stopped working due to a bug in MLIBC.

Choosing a version to run

The first step in the process was to choose which Minecraft version Astral would run and then figure out the Java command used to launch it. I needed something simple and with as few dependencies as possible, so I chose the alpha 1.2.0 version. This version has only one dependency, LWJGL2, reducing porting time and making debugging later easier.

get the jvm working again

The next step was to get OpenJDK working again in Astral. As I mentioned earlier, it had rotted a bit and was now suffering from segmentation fault when starting up. The OpenJDK stack trace gave some important information: this was what was happening libc.so Called after OpenJDK sscanf(3) with a big %[] Specifier which had almost every value from 0 to 255.

I finally figured it out thanks to using the MLIBC code char Values ​​from the format string, values ​​above 127 passed by OpenJDK will be handled as negative integers, which will eventually lead to negative array index accesses and stack corruption. With this fixed, javac Was able to run without any problems, and I was ready to move on to the next part of the project.

Porting LWJGL2

LWJGL (Lightweight Java Game Library) is a Java library used to create cross-platform games in Java, providing access to OpenGL-like APIs and abstractions for things like input. Until Minecraft release 1.12, LWJGL 2 was used, which is no longer maintained since LWJGL 3 was released. The version of Minecraft that will be played is Alpha 1.2.0, so LWJGL 2 will need to be ported.

The process of porting LWJGL2 was quite painful. This mostly involved adding instructions for Astral to cross-compile native libraries. LWJGL uses Apache Ant as the build system, which I have found to be very hostile to cross-compilation. Most of the patching effort was in the build system, as I didn’t need to modify any native C code and the only modification to the Java code was to add Astral to the list of known OSes. If you are interested, you can find the patch file here.

Running and debugging Minecraft

Once the LWJGL was ported, all that remained was to boot Astral and debug any issues. During this process, I was joined by Denis Bonnke, who maintains Managram’s port collection. We worked together so that we could finally run Minecraft on Managarm as well.

I created a simple shell script to start Minecraft. It switches to the directory where LWJGL is installed and calls Java with all the necessary arguments to start it. This is the version of the script that first got a working Minecraft:
cd /usr/share/lwjgl
/usr/lib/jvm/java-17/bin/java -Xint -Xmx1g -Djava.library.path="/usr/share/lwjgl" -cp "lwjgl.jar:lwjgl_util.jar:/home/astral/minecraft.jar" net.minecraft.client.Minecraft

On the first attempt, Java will run for a while and then exit and MLIBC will log about a missing AWTFontMinByte1 Sign. This is a symbol that needs libfontmanager.so and defined by libawt_xawt.soLooking at the RTLD log, libawt_xawt.so loaded by dlopen(3) (twice!), which means there must have been a bug in MLIBC. Ultimately, we boiled it down to the fact that OpenJDK runs first dlopen(3) For libawt_xawt.so with RTLD_LOCAL and then together again RTLD_GLOBALAnd for this case the MLIBC shared object promotion code was broken. After fixing it, we actually got a window from Minecraft!

Astral getting a window from Minecraft

However, it is clear that it is still not working. The crash is a LWJGL error talking about an unknown platform. This was a missing piece of code in the LWJGL patch and was quickly fixed. Next time, it went ahead but crashed with another missing symbol, SUNWprivate_1.1We discovered that this was a symbol that does not exist in modern OpenJDK versions, so it was clearly an issue with cross-compilation, This was a simple but annoying solution, I had to add specific variables to it astral_ant XML in LWJGL to make cross compilation easier and use proper headers, as it was still trying to use the host OpenJDK 8 headers. Now, LWJGL has really taken off! Running it again, we encounter another problem: a ArrayIndexOutOfBoundsException When starting the display.

Astral Running Minecraft (ArrayIndexOutOfBoundsException)

Diving into the LWJGL source code, we finally discovered that the problem was XRandR Class populate() act as an exception Seek not possible (ESPIPE) Was happening while populating the screen hashmap. After adding a print to get the backtrace, we reached the native OpenJDK function handleAvailable()Which returns the number of bytes left to read in the file. The issue here was that Astral did not implement FIONREAD to the pipe object, causing it to fall back into the find. Since it is not possible to seek on the pipe, ESPIPE The error has returned. After applying it, the Minecraft menu appeared on the screen!

Astral Running Minecraft (menu screen)

playing minecraft

After that, it was running smoothly. We were able to load in a world and verify that the game was working, from breaking blocks to saving. To my knowledge, this was the first time an amateur OS ran Minecraft, which is a huge milestone not only for Astral but for the entire OSDev community, as it not only proves it’s possible, but also paves the way for others to do the same with open-source patches and mlibc fixes.

astral running minecraft

astral running minecraft

What’s next for Astral?

Much of Astral’s recent work has been towards self-hosting, speed, stability, and general usability. There is now a working package manager (xbps) and all the necessary tools for a network install on disk. This work will probably continue for the foreseeable future, and, after more improvements, I plan to eventually release a variant micro scratch A guide to creating an Astral Distribution from within another Astral Distribution. There are also plans to revive the Wine port (which is still not fully functional) with Dennis for both Astral and Managram, as well as a possible future WebKitGTK port.

Thanks for reading!



Leave a Comment