Mips2cs is a project that I worked on some time around 2010–2011. It converts MIPS machine code into an equivalent C# program.
Some people suggested to me that I should port Knights to the Xbox 360. (This was back when "Xbox Live Indie Games" was popular.) In theory, this could have been achieved by converting the game to use Microsoft's "XNA" framework. In practice, there is a problem: XNA games must be written in C#, but Knights is written in C++. This naturally leads us to the question: is there an easy (preferably automatic) way to convert a C++ program into a C# program?
Mips2cs was my answer to that question.
The main idea is that we use GCC (built as a cross-compiler) to compile our C++ program into MIPS machine code. We then use Mips2cs to convert the MIPS code into an equivalent C# program. Finally, we use Visual Studio (or another C# compiler) to convert the C# program into an executable.
The end result is a C# program that behaves identically to the original C++ program, but runs on the .NET platform instead of as native code.
One certainly could write a tool to parse C++ code and convert it to C#. However, the complexity of the C++ language, and the differences in semantics between it and C#, make this somewhat difficult. Therefore, while there are some existing tools that can do it (e.g. this one), none of them are fully automatic; the user is required to edit the generated C# files by hand afterwards. This is somewhat unsatisfactory, especially if one wishes to maintain parallel C++ and C# versions of the same project.
Machine code, by contrast, is much lower level than C++, and therefore more suited to automatic processing. Indeed, translating machine code into C# is straightforward (if one is happy with a "literal" translation) and can be done completely automatically.
One way to look at this is to say that we are re-using an existing compiler to do the hard work of parsing the C++ and converting it to a lower level representation; and then writing a relatively simple tool to convert that low level representation to C#.
Unfortunately, yes. Although the generated C# files have the same behaviour as the original program, they are virtually unreadable to humans. They read like disassembly listings.
Whether this is a problem or not depends on one's intentions. If one wishes to do a "one time" translation of a C++ project to C#, with all future development being done in C#, Mips2cs would not be suitable. However, if one simply wishes to make a .NET executable from a C++ codebase, while retaining C++ as the primary development language, then it isn't really an issue – the C# files are just intermediate products in a build process, and one does not really need to read or edit them at all.
Since we are using GCC to compile our C++ code, we can pick any CPU architecture that GCC supports. We don't have to stick with x86. Choosing the MIPS architecture has several advantages:
(Note: nowadays one might also consider RISC-V, which has many of the same advantages as MIPS, but without some of the annoyances e.g. branch delay slots. However, RISC-V didn't exist at the time when I wrote Mips2cs.)
In fact not. There are two other projects that came up with the idea before me. However, they are targetting Java rather than C#. Here are the links:
There is also Mips2Java which is an earlier version of NestedVM.
See also: "Related Work" at the bottom of this page.
It certainly is. Visual Studio offers two settings, /CLR:SAFE and /CLR:PURE, that do exactly that. However, there are some issues:
There was also a CLI backend for GCC at one point. However, it appears that this supports only C (and not C++), and also it hasn't been updated in a long time. (Although nor has Mips2cs, to be fair!)
Due to the above issues, I haven't looked any further into the "compiling C++ to bytecode" approach. I decided to use the Mips2cs approach instead.
It probably would be better. However, that would increase complexity: we would need to know details of CIL assembly language, CLR bytecode formats, etc. For now I have taken the simpler route and generated C# code as output. However, working directly with bytecode might be an interesting option in future.
Mips2cs cannot translate code that makes calls to the operating system. This means that things like file I/O, or calls to DirectX or OpenGL for example, will not work without modification.
Instead, Mips2cs provides a mechanism for the C++ program to call arbitrary C# code at runtime. Therefore, if you need to draw graphics (for example), you would write the required functionality in C#, and then arrange for your C# code to be called from the C++ program as required.
Mips2cs comes with two ready-made libraries which illustrate this process. These are:
Mips2cs performs a few optimization passes (such as constant folding and dead variable elimination) in order to improve the quality of the generated C# code. Also, of course, the .NET runtime is performing JIT optimizations of its own. So, the performance isn't as bad as one might think.
I haven't done much performance testing yet, but initial testing showed that the generated C# code is (very roughly) 50% slower than the native code, when doing integer operations.
Floating point operations will be a lot slower, because Mips2cs doesn't support the MIPS floating point instructions yet (so all floating point calculations are using software emulation).
As a demo I have written a very simple Arkanoid-like game.
The starting point was to write the game code in C++. This came to about 500 lines of code (not counting the code for the "graphical library" – see above – which provides the interface between the C++ code and XNA). A source code listing can be found here: bouncy_ball_game.cpp.
This was then compiled to MIPS machine code with GCC, and converted to C# source code using Mips2cs. If you are interested in seeing what the generated C# looks like, see: bouncy_ball_game.cs.
Finally the C# was compiled with Visual Studio / XNA to a Windows executable. It can be downloaded here: BouncyBallGame.exe. (Note: to run this you may need to install "XNA Framework Redistributable 4.0" from Microsoft.)
The process worked perfectly well and the game plays without any problems on Windows. In theory a 360 version could be made as well (but the code would have to be modified to use an Xbox controller instead of a mouse).
Mips2cs is written in Haskell. The source code can be downloaded here: mips2cs.tar.gz.
The download includes instructions on how to build the required GCC cross compiler, as well as how to build and use Mips2cs.
If you are interested in the technical details of how Mips2cs works, then the following documents are available:
The project is now at a "proof of concept" stage, i.e., the basic concept of converting C++ code to C#, via MIPS machine code, has been proven to work.
To make it into a more "production-ready" tool, the following improvements could be made:
It is also fair to say that the main original use case of Mips2cs (porting C++ games to Xbox Live Indie Games) is no longer applicable, because Xbox Live Indie Games no longer exists. For that reason, I have no plans to continue working on Mips2cs at this time. However, perhaps other use cases will be found, so I will leave the code available here, in case it turns out to be useful at any point.
It has been pointed out to me that there are two existing projects that do similar things to Mips2cs:
If the target language is not C#, but instead Java or Javascript or WebAssembly, then one can also point to Cibyl and NestedVM (which were mentioned above) and also Emscripten.