|
|
@@ -0,0 +1,220 @@ |
|
|
|
+++ |
|
|
|
title = "Stardew Valley on aarch64" |
|
|
|
date = "2020-01-15" |
|
|
|
tags = ["PBP", "hacking"] |
|
|
|
+++ |
|
|
|
|
|
|
|
#### Stardew Valley on aarch64 |
|
|
|
|
|
|
|
At the end of last year I got a [Pinebook Pro](https://pine64.org/pinebook-pro) - |
|
|
|
mostly for reasons of paranoia. So far, it's been pretty good, but there was |
|
|
|
one thing that I couldn't get working: [Stardew Valley](https://stardewvalley.com/) |
|
|
|
|
|
|
|
You could call me a little bit addicted to this game, but it's proprietary, |
|
|
|
closed-source, and the authors don't release binaries compiled for aarch64 - |
|
|
|
although they do very kindly release x86_32 and x86_64 Linux binaries, which |
|
|
|
is more than most companies do. |
|
|
|
|
|
|
|
I [left a message on the forum](https://community.playstarbound.com/threads/arm-arm64-aarch64-linux-support.158840/) |
|
|
|
and moved on, confident that it wouldn't ever happen. I vaguely knew it was |
|
|
|
written in C#, but it's not an ecosystem I have any experience in. I figured it |
|
|
|
was going to be the kind of thing that comes under "possible, but not trivial" - |
|
|
|
and aarch64 + linux is super-niche. |
|
|
|
|
|
|
|
Fast forward a few weeks, I mentioned it in passing on the `#pinebook` IRC |
|
|
|
channel, which went a little like: |
|
|
|
|
|
|
|
``` |
|
|
|
<lupine> stardew valley never got back to me *sob* |
|
|
|
<halosghost> lupine: trying to get Stardew Valley on the pbp as well? |
|
|
|
<Nadia> The game itself is written in C# so runs through Mono |
|
|
|
<lupine> they don't distribute aarch64-linux executables |
|
|
|
<Nadia> You just need to build the libraries it needs and it should run |
|
|
|
<lupine> it's closed source, so "just need to build" is rather an issue |
|
|
|
``` |
|
|
|
|
|
|
|
They rather roundly assured me that it wasn't an issue at all, and literally |
|
|
|
10 minutes later I had a working Stardew Valley setup. This is incredible. |
|
|
|
|
|
|
|
I'm documenting the steps I took so I can come back to this in the future, but |
|
|
|
maybe it'll be useful for others too. |
|
|
|
|
|
|
|
First, you need a copy of the game. I was working with v1.4 as shipppd by |
|
|
|
[GOG Games](https://www.gog.com/game/stardew_valley). It comes as one of those |
|
|
|
`.sh` files that contains an archive. That doesn't have aarch64 support, and |
|
|
|
doesn't run on the PBP. Fortunately, I'd already installed it on an amd64 laptop |
|
|
|
so I just rsynced that over: |
|
|
|
|
|
|
|
``` |
|
|
|
lupine@pbp:~$ rsync -avzP '10.0.1.104:GOG Games' . |
|
|
|
|
|
|
|
# Might as well grab my savegames at the same time |
|
|
|
lupine@pbp:~$ rsync -avzP 10.0.1.104:.config/StardewValley .config/StardewValley |
|
|
|
``` |
|
|
|
|
|
|
|
I'm sure it's possible to make it run, I'm just being lazy. I'll update this in |
|
|
|
the future if I work out how to go from the `.sh` file. |
|
|
|
|
|
|
|
What does this give us?: |
|
|
|
|
|
|
|
``` |
|
|
|
lupine@pbp:~/GOG Games/Stardew Valley/game$ ls -lh |
|
|
|
total 438M |
|
|
|
-rwxrwxr-x 1 lupine lupine 12K Dec 8 23:58 BmFont.dll |
|
|
|
drwx--x--x 17 lupine lupine 4.0K Dec 8 23:58 Content |
|
|
|
-rwxrwxr-x 1 lupine lupine 330K Dec 8 23:58 GalaxyCSharp.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 336 Dec 8 23:58 GalaxyCSharp.dll.config |
|
|
|
-rwxrwxr-x 1 lupine lupine 91K Dec 8 23:58 goggame-1453375253.hashdb |
|
|
|
-rwxrwxr-x 1 lupine lupine 782 Dec 8 23:58 goggame-1453375253.info |
|
|
|
drwx--x--x 2 lupine lupine 4.0K Dec 8 23:58 lib |
|
|
|
drwx--x--x 2 lupine lupine 4.0K Dec 8 23:58 lib64 |
|
|
|
-rwxrwxr-x 1 lupine lupine 197M Dec 8 23:59 libGalaxyPeer64.so |
|
|
|
-rwxrwxr-x 1 lupine lupine 177M Dec 8 23:59 libGalaxyPeer.so |
|
|
|
-rwxrwxr-x 1 lupine lupine 5.3M Dec 8 23:59 libSkiaSharp.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 119K Dec 8 23:58 Lidgren.Network.dll |
|
|
|
lrwxrwxrwx 1 lupine lupine 14 Dec 9 00:00 mcs -> mcs.bin.x86_64 |
|
|
|
-rwxrwxr-x 1 lupine lupine 17M Dec 8 23:59 mcs.bin.x86 |
|
|
|
-rwxrwxr-x 1 lupine lupine 16M Dec 8 23:59 mcs.bin.x86_64 |
|
|
|
drwx--x--x 3 lupine lupine 4.0K Dec 8 23:59 mono |
|
|
|
-rwxrwxr-x 1 lupine lupine 2.5K Dec 8 23:59 monoconfig |
|
|
|
-rwxrwxr-x 1 lupine lupine 1.3M Dec 8 23:58 MonoGame.Framework.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 527 Dec 8 23:58 MonoGame.Framework.dll.config |
|
|
|
-rwxrwxr-x 1 lupine lupine 203K Dec 8 23:58 Mono.Posix.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 328K Dec 8 23:58 Mono.Security.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 3.6M Dec 8 23:59 mscorlib.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 267K Dec 8 23:58 SkiaSharp.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 1.2K Dec 8 23:58 StardewValley |
|
|
|
-rwxrwxr-x 1 lupine lupine 4.0M Dec 8 23:58 StardewValley.bin.x86 |
|
|
|
-rwxrwxr-x 1 lupine lupine 3.8M Dec 8 23:58 StardewValley.bin.x86_64 |
|
|
|
-rwxrwxr-x 1 lupine lupine 4.1M Dec 8 23:58 StardewValley.exe |
|
|
|
-rwxrwxr-x 1 lupine lupine 6.5K Dec 8 23:58 StardewValley.GameData.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 127K Dec 8 23:58 System.Configuration.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 879K Dec 8 23:58 System.Core.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 2.0M Dec 8 23:58 System.Data.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 2.2M Dec 8 23:58 System.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 442K Dec 8 23:58 System.Drawing.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 966K Dec 8 23:58 System.Runtime.Serialization.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 130K Dec 8 23:58 System.Security.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 3.1M Dec 8 23:58 System.Xml.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 131K Dec 8 23:58 System.Xml.Linq.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 161K Dec 8 23:58 WindowsBase.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 48K Dec 8 23:59 xTile.dll |
|
|
|
-rwxrwxr-x 1 lupine lupine 9.0K Dec 8 23:59 xTilePipeline.dll |
|
|
|
``` |
|
|
|
|
|
|
|
The magic here is that not all the `.dll` and `.exe` files here are **Windows** |
|
|
|
object files. Instead, many of the are just Mono bytecode, which is analogous to |
|
|
|
JVM bytecode: |
|
|
|
|
|
|
|
``` |
|
|
|
lupine@pbp:~/GOG Games/Stardew Valley/game$ file StardewValley* |
|
|
|
StardewValley: Bourne-Again shell script, ASCII text executable |
|
|
|
StardewValley.bin.x86: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=4801f8881feefa8aa515f9fadc02c01598c44131, not stripped |
|
|
|
StardewValley.bin.x86_64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=04fe4f2c2ca8b4dc7faf70c643417bf0df632a9e, not stripped |
|
|
|
StardewValley.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows |
|
|
|
StardewValley.GameData.dll: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows |
|
|
|
``` |
|
|
|
|
|
|
|
We need Mono to run these assemblies. I guess the `StardewVelly.bin.*` files are |
|
|
|
just stripped-down Mono runtimes that invoke `StardewValley.exe`! |
|
|
|
|
|
|
|
The `mcs.*` binaries are "Mono C Sharp" - I don't know C#, but I assume it's |
|
|
|
another essential part of the runtime. |
|
|
|
|
|
|
|
Debian has Mono + MCS already, so... |
|
|
|
|
|
|
|
``` |
|
|
|
lupine@pbp~/GOG Games/Stardew Valley/game$ sudo apt install mono-runtime mono-rcs |
|
|
|
lupine@pbp~/GOG Games/Stardew Valley/game$ ln -sf `which mcs` |
|
|
|
``` |
|
|
|
|
|
|
|
We can then try to run the game: |
|
|
|
|
|
|
|
``` |
|
|
|
lupine@pbp~/GOG Games/Stardew Valley/game$ mono StardewValley.exe |
|
|
|
``` |
|
|
|
|
|
|
|
Amazingly, that's **almost sufficient**, all by itself, to get a fully working |
|
|
|
game, at least for me. It starts up, and the only obviously broken thing is |
|
|
|
sound. There are some complaints on the comamnd line that don't seem to get in |
|
|
|
the way of actually playing it. |
|
|
|
|
|
|
|
Wat. |
|
|
|
|
|
|
|
No sound is annoying though, how about we fix that? |
|
|
|
|
|
|
|
Turns out Stardew Valley only **requires** two external libraries: SDL and |
|
|
|
libasound. I've no idea if the graphics is working even though it can't find |
|
|
|
SDL, or if it can find my native SDL libary but not the libasound one, or what, |
|
|
|
but it's trivial to fix. Edit `MonoGame.Framework.dll.config` and add these |
|
|
|
two lines: |
|
|
|
|
|
|
|
``` |
|
|
|
<dllmap dll="SDL2.dll" os="linux" cpu="armv8" target="./libaarch64/libSDL2-2.0.so.0"/> |
|
|
|
<dllmap dll="soft_oal.dll" os="linux" cpu="armv8" target="./libaarch64/libopenal.so.1" /> |
|
|
|
``` |
|
|
|
|
|
|
|
Now you just need to put those two .so files into that directory locally, and |
|
|
|
sound begins to work! |
|
|
|
|
|
|
|
(I just symlinked `/usr/lib/aarch64-linux-gnu` into place, which does the same |
|
|
|
job). |
|
|
|
|
|
|
|
At this point the game works perfectly, including LAN multiplayer - which is |
|
|
|
ridiculous - and despite worries about endianness, it can load and run my saves |
|
|
|
as well. |
|
|
|
|
|
|
|
There are a few complaints on the console though. Let's see what we can do |
|
|
|
about them. |
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
|
Your mono runtime and class libraries are out of sync. |
|
|
|
The out of sync library is: /home/lupine/GOG Games/Stardew Valley/game/System.dll |
|
|
|
``` |
|
|
|
|
|
|
|
OK, these are shipped with `mono-runtime` (actually in `libmono-system4.0-cil`) |
|
|
|
anyway. The complaint is that these assemblies were compiled with a different |
|
|
|
version of Mono, but it's falling back to the main ones anyway, so we can just |
|
|
|
move these out of the way. |
|
|
|
|
|
|
|
The only `System.*.dll` file we need to keep is `System.Runtime.Serialization.dll` - |
|
|
|
the rest can be moved out of the way. |
|
|
|
|
|
|
|
``` |
|
|
|
System.TypeInitializationException: The type initializer for 'Galaxy.Api.GalaxyInstance' threw an exception. ---> System.TypeInitializationException: The type initializer for 'CustomExceptionHelper' threw an exception. ---> System.DllNotFoundException: GalaxyCSharpGlue |
|
|
|
at (wrapper managed-to-native) Galaxy.Api.GalaxyInstance+CustomExceptionHelper.CustomExceptionRegisterCallback(Galaxy.Api.GalaxyInstance/CustomExceptionHelper/CustomExceptionDelegate) |
|
|
|
at Galaxy.Api.GalaxyInstance+CustomExceptionHelper..cctor () [0x00011] in <22373852dcce42128dc7e065ea92368d>:0 |
|
|
|
--- End of inner exception stack trace --- |
|
|
|
at (wrapper managed-to-native) System.Object.__icall_wrapper_mono_generic_class_init(intptr) |
|
|
|
at Galaxy.Api.GalaxyInstance..cctor () [0x00000] in <22373852dcce42128dc7e065ea92368d>:0 |
|
|
|
--- End of inner exception stack trace --- |
|
|
|
at StardewValley.SDKs.GalaxyHelper.Initialize () [0x00000] in <1ed49e648be548bcae8e4508597c9f4c>:0 |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
I am **astonished** that this one isn't a fatal error - but the game runs fine |
|
|
|
even though it can't find an external library. Ridiculous. |
|
|
|
|
|
|
|
Galaxy is GOG's multiplayer gubbins. If you've got a Steam game, it's different, |
|
|
|
I'm sure, but the functionality this stuff is *for* is to negotiate multiplayer |
|
|
|
games with strangers. |
|
|
|
|
|
|
|
I have no use for this myself, but `libGalaxyCSharpGlue.so` is looked up via |
|
|
|
another dllmap in `GalaxyCSharp.dll.config` - it's not packaged by Debian, and |
|
|
|
it may even be proprietary GOG code, but if we can get an aarch64 version of it, |
|
|
|
making it work should be as simple as adding an entry there. |
|
|
|
|
|
|
|
If this did become a fatal error at some point, the minimum work would be a stub |
|
|
|
implementation that meets the ABI but always says "no games available" or some |
|
|
|
such. |
|
|
|
|
|
|
|
And... that's all the errors. Despite a different architecture, despite being |
|
|
|
short some libraries, and despite running reverse-engineered (Panfrost) graphics |
|
|
|
drivers with only a bare whisper of OpenGL support, my favourite game is running |
|
|
|
at normal speed on an architecture its authors and publishers didn't even think |
|
|
|
about. |
|
|
|
|
|
|
|
Again I say: ridiculous |
|
|
|
|
|
|
|
...maybe I should learn some CSharp? |