Ryujinx can't (couldn't?) be compiled
Jul 29th, 2025 - scudoAfter Nintendo successfully managed to close down the Ryujinx project, out of curiosity I tried to compile its source code, as the repo had been backed up and reuploaded both on GitHub and the Internet Archive.
There still were (and are) builds for Windows and Linux, and my notes from back then say the Flatpak version was still available on Flathub.
Also, back then I was experimenting with C#/.NET and Ryujinx is written in C#, so I figured I could give it a try.
What I found is that the project did not build, and for quite complicated reasons.
Analyzing the build logs, I found there were a lot of errors saying things like:
error CS0535: 'UnregistrationNotifier' does not implement interface method 'IServiceObject.GetCommandHandlers()'
Generally speaking, all of these errors referred to classes and project related to managing HorizonOS system calls.
I took a look into it; I loaded the repo into VSCodium and I let it crunch through all the files until it started giving out errors; I then grabbed a random class that errored out, that referenced an interface.
I was then welcomed with the sight of a completely empty interface:
interface IReceiverService : IServiceObject { }
Great. An empty interface that extends another interface. What an amazing start.
But what does
IServiceObject
contain? Not much, actually:interface IServiceObject { IReadOnlyDictionary<int, CommandHandler> GetCommandHandlers(); }
Great. Another (almost) empty interface. But see that
GetCommandHandlers()
? That is the method that gave all those build errors before!
So I searched all references to that method; it was called only once in the whole project, inside
ServiceDispatchTables
, a class that should deal with command handlers relative to HorizonOS syscalls:public static ServiceDispatchTableBase Create(IServiceObject instance) { if (instance is DomainServiceObject) { return new DomainServiceObjectDispatchTable(); } return new ServiceDispatchTable(instance.GetType().Name, instance.GetCommandHandlers()); }
Wow, we even land on a constructor! And we have our
GetCommandHandlers
call, invoked on the
instance
object, which is... (drum roll)... an instance of
IServiceObject
! Yay! We closed the circle!Or did we?
Let's concentrate on that call to
GetCommandHandlers
. Since that call is invoked on a
IServiceObject
object, we need to look into
IServiceObject
to see if there are any methods called
GetCommandHandlers
.There is indeed a method with that name, which is the only thing inside of that interface. What does that method do?
GetCommandHandlers
returns a
IReadOnlyDictionary
collection; that is, a key-value pair where the key is an integer and the value is a
CommandHandler
object, which is what we want to have. The problem is that this definition of
GetCommandHandlers
is defined inside of an interface, so it is the job of any class that implements that interface to also implement its methods; this means all the classes that implement all the HorizonOS syscalls have to implement
GetCommandHandlers
.The problem is that no class in the whole project ever implements GetCommandHandlers. Oopsie. No wonder it didn't compile!