
SMAPI on other platforms
Pathoschild opened this issue · 31 comments
SMAPI officially runs on Linux, macOS, Windows, and Steam Deck (see player guide).
I don't plan to port it to mobile/consoles myself, but I'm happy to provide any help needed if someone familiar with those wants to figure it out.
Current status:
group | platform | status |
---|---|---|
PC | Linux | ✓ fully supported. |
macOS | ✓ fully supported. | |
Windows | ✓ fully supported. | |
Mobile | Android | ✓ unofficial support, many mods compatible. |
iOS | ☐ no current support. | |
Console | PS4 | ☐ no current support. |
PS Vita | ☐ no current support. | |
Steam Deck | ✓ supported, equivalent to Linux. May increase power usage. | |
Switch | ☐ no current support. | |
Xbox One | ☐ no current support. |
Brief introduction
I'm new to Stardew Valley modding, but in no way new to modding C# games in general (having worked on tConfig, a modding API for Terraria 1.1.x and being one of the main developers of tAPI, a modding API for Terraria 1.2.x; also dabbling in some tModLoader modding for Terraria 1.3+).
I've been an iOS developer for several years now, both commercially and as a hobby.
I also do a lot of Kotlin/Java work, which would normally be unrelated, but I'll get to it later below.
iOS/iPadOS support
TL;DR: It's possible, but we will most likely lose all mods we already have.
I'll just call it "iOS" from now on, it's literally the same thing, I don't get why Apple had to split those names...
The iOS port of Stardew Valley is built using Xamarin. So is the Android port, I believe. Disclaimer: I've never worked with Xamarin myself, all I'm saying is reading research and conjecture.
Xamarin has two ways of compiling your CIL into something applicable for its platforms:
- JIT, or "just in time",
- AOT, or "ahead of time".
By default, the Android builds use JIT, but they can also use AOT if preferred. Unfortunately, Apple does not allow code compilation to be done on their iOS devices, nor dynamically loading from an external resource -- all code has to be precompiled and included in the app before submitting to the App Store. Interpreting code may sometimes be allowed, but is usually frowned upon. So, the iOS port uses the AOT method.
Harmony
SMAPI uses Harmony (or MonoMod RuntimeDetour for the unofficial Android port) for hooking into the methods in the game, via IL editing. Unfortunately, IL is not a thing in AOT builds -- at this point we're way past that.
To achieve similar results, one could engineer a process in which the IL gets modified before it gets AOT compiled... but that requires actual source code for the iOS port. More details in a section below.
Editing assemblies before compilation
Harmony is a runtime hooking framework. It doesn't have the capability to edit an assembly and save it back to a file for later use. This is a problem, because this is something we need to make an iOS port possible.
Switching to using MonoMod could be a way out, as if I'm not mistaken it has the capability to hook both at runtime AND to edit assemblies and write modified ones to disk, but that comes at a cost...
All mods nowadays use Harmony. I don't know how compatible the APIs for Harmony and MonoMod are (@0x0ade would probably be able to answer that) and whether it would be possible to do some automatic code rewriting, but if they aren't... All of the current mods would have to be deprecated and rewritten to use a new hooking framework, which I believe is too big of a cost -- there are hundreds (thousands?) of SMAPI mods out there. Sure, some would port over... but a lot of them would be abandoned for good. It's also likely the community would also split into two -- one using the Harmony SMAPI, the other using MonoMod SMAPI.
Obtaining the source code
There are two ways iOS source code could be obtained.
1. Just... ask the developers
I don't see this happening, but you never know. The community could just... ask the developers.
The source code itself is not enough to play the game. You still need to obtain all of its content. This means piracy shouldn't be much of a concern.
There may be some legal problems. I'm in no way a lawyer, but sharing the source code may make it so ConcernedApe & co. could no longer do anything if someone were to steal the code and publish their own game (I may be completely in the wrong here, please tell me so if I am).
2. Decompiling the Android port
Because the Android build doesn't AOT compile the code, we can just extract it. This would give us a mobile Stardew Valley to work with, but there's still a lot to do. Android and iOS are two different beasts. OS-specific things would need to be reimplemented for iOS. I didn't think too much about it, but keyboard input and safe area (notch, home screen indicator) handling come to mind, not to mention just getting the thing to compile and work without problems game-engine-wise.
As we cannot just share this extracted/decompiled code, the user would have to acquire an APK file for the Android version by himself, but I don't think you can get APKs directly from the Google Play Store in a legal way, so unfortunately that would basically be piracy on the user's part.
At this point, a tool could be written which would take an Android APK, extract it, patch the assembly IL with iOS-specific changes (or decompile the assemblies, patch the C# code with iOS-specific changes and recompile it back to assemblies), patch those assemblies with the mods of the user's choosing and finally compile the whole thing back into an iOS app. Changing the mod list would require running this process again. Some of those steps could be cached between re-runs, so further changing of mods would be much faster.
Also... you know... this is just hilarious that you would need an Android version of the game to install mods on your iPhone.
Reflection
There were some concerns, that due to the AOT nature of iOS builds reflection would no longer be something that could be used in mods. Here comes the part where my Java world knowledge gets useful!
Back in the day I used to do some cross-platform Java game development, with the libGDX library. The desktop and Android platforms aren't anything special, but... The iOS build used a tool called RoboVM, which is very similar to what Xamarin AOT compiling does. It finds all of the types used by your project and compiles all of them as native code. It also supports reflection. Any code that is directly referenced will work right away, but if any type is only used at runtime (for example via Class.forName("com.example.MyClass")
), you would need to specify it in RoboVM's configuration file.
Xamarin AOT does support System.Reflection
. I may be completely in the wrong here, but I don't see why Xamarin would be any different from RoboVM, it's a no-brainer to allow specifying types to compile manually, but I can't find any information regarding that. The only unsupported part in Xamarin AOT is System.Reflection.Emit
-- no code can be generated at runtime, but we wouldn't need that.
Source: https://docs.microsoft.com/en-us/xamarin/ios/internals/limitations
Building the game
To build any iOS app, you need to use a Mac(Book) (well, technically, macOS -- hackintoshing is a thing). So, anyone who would like to install modded Stardew on their iOS devices would also need to have access to a macOS device.
...or they could get a pre-modded built IPA from the internet. Hopefully this does not turn into people installing malicious apps on their iPhones...
Signing the build
To actually run the game on your own iOS device, you need to either download it from the App Store (which is a no-go here) or sign it for your own device.
Signing for yourself
Recently (2-3 years ago? I can't remember) Apple made it so you can develop iOS apps for free. Apps signed with free developer accounts are valid for 7 days, after which you have to sign them and install them again. An app built with a paid developer account ($99/year) are valid for 1 year.
Alternatively, if the iOS device is jailbroken, the AppSync tweak can be installed which allows installing any IPA, without the need of signing it.
A tool like Cydia Impactor can be used to sign an IPA for your own device. Impactor works on Windows, Linux and macOS, so if you already have a pre-modded IPA, you no longer need a Mac to install it on your iPhone/iPad.
Enterprise signing
Apple also offers enterprise certificates and provisioning profiles, which don't require the actual device to be specified. There are (were?) (paid) web services out there, which allowed you to upload any IPA and they would sign it for you with their enterprise profile. With such a signed IPA, you could install it on any device.
Benefits for other platforms
Switching to generating patched assemblies could also have the benefit of speeding up the game startup process, as patching would only need to be done whenever any mods are changed. Just today I've seen someone say they're using 800+ mods at once (JESUS, BUT WHY) and they've already been waiting for 11 minutes and it still didn't launch. I don't know about you, but 11 minutes to launch a game, only to play it for an hour (no, actually 49 minutes, you lost the 11 minutes there) would certainly not make me want to play the game anymore.
hi. so a few months ago i wanted try this so i made an smapi-looking app that imports mod to your real game not to make another game. but i had no idea that how much the base code is different. and the app was running on my pc not on my other i phone. so i just wanted to say. you are a genius pathoschild.
Just a few updates on Harmony usage, since Stardew Valley 1.6 changed a lot.
SMAPI uses Harmony (or MonoMod RuntimeDetour for the unofficial Android port) for hooking into the methods in the game, via IL editing.
SMAPI doesn't need Harmony anymore after Stardew Valley 1.6. It only provides Harmony for mods to use, and patches Harmony to work in Stardew Valley.
All mods nowadays use Harmony.
That's not quite correct. Based on the latest stats:
- 49.9% of mods use Content Patcher, which doesn't use Harmony.
- 6.7% are XNB replacements, which have no code.
- 29.1% are content packs for other frameworks, so they can't use Harmony directly. (The framework mod might use it though.)
Which means:
- 14.3% of mods could use Harmony directly. We don't track Harmony usage, but I'd estimate much less than 40% of those do; so let's say <6% of mods use Harmony directly.
- 29.1% are content packs whose frameworks could use Harmony.
So at a very rough estimate, somewhere between 6% and 35% of mods use Harmony (directly or indirectly). The remaining 65 to 94% of mods would be unaffected by removing Harmony.
I think it's possible to make SMAPI run on WebGL with Stardew Valley game from GOG
here example game celeste-wasm: https://github.com/MercuryWorkshop/celeste-wasm
Brief introduction
I'm new to Stardew Valley modding, but in no way new to modding C# games in general (having worked on tConfig, a modding API for Terraria 1.1.x and being one of the main developers of tAPI, a modding API for Terraria 1.2.x; also dabbling in some tModLoader modding for Terraria 1.3+).
I've been an iOS developer for several years now, both commercially and as a hobby.
I also do a lot of Kotlin/Java work, which would normally be unrelated, but I'll get to it later below.
iOS/iPadOS support
TL;DR: It's possible, but we will most likely lose all mods we already have.
I'll just call it "iOS" from now on, it's literally the same thing, I don't get why Apple had to split those names...
The iOS port of Stardew Valley is built using Xamarin. So is the Android port, I believe. Disclaimer: I've never worked with Xamarin myself, all I'm saying is reading research and conjecture.
Xamarin has two ways of compiling your CIL into something applicable for its platforms:
- JIT, or "just in time",
- AOT, or "ahead of time".
By default, the Android builds use JIT, but they can also use AOT if preferred. Unfortunately, Apple does not allow code compilation to be done on their iOS devices, nor dynamically loading from an external resource -- all code has to be precompiled and included in the app before submitting to the App Store. Interpreting code may sometimes be allowed, but is usually frowned upon. So, the iOS port uses the AOT method.
Harmony
SMAPI uses Harmony (or MonoMod RuntimeDetour for the unofficial Android port) for hooking into the methods in the game, via IL editing. Unfortunately, IL is not a thing in AOT builds -- at this point we're way past that.
To achieve similar results, one could engineer a process in which the IL gets modified before it gets AOT compiled... but that requires actual source code for the iOS port. More details in a section below.
Editing assemblies before compilation
Harmony is a runtime hooking framework. It doesn't have the capability to edit an assembly and save it back to a file for later use. This is a problem, because this is something we need to make an iOS port possible.
Switching to using MonoMod could be a way out, as if I'm not mistaken it has the capability to hook both at runtime AND to edit assemblies and write modified ones to disk, but that comes at a cost...
All mods nowadays use Harmony. I don't know how compatible the APIs for Harmony and MonoMod are (@0x0ade would probably be able to answer that) and whether it would be possible to do some automatic code rewriting, but if they aren't... All of the current mods would have to be deprecated and rewritten to use a new hooking framework, which I believe is too big of a cost -- there are hundreds (thousands?) of SMAPI mods out there. Sure, some would port over... but a lot of them would be abandoned for good. It's also likely the community would also split into two -- one using the Harmony SMAPI, the other using MonoMod SMAPI.
Obtaining the source code
There are two ways iOS source code could be obtained.
1. Just... ask the developers
I don't see this happening, but you never know. The community could just... ask the developers.
The source code itself is not enough to play the game. You still need to obtain all of its content. This means piracy shouldn't be much of a concern.
There may be some legal problems. I'm in no way a lawyer, but sharing the source code may make it so ConcernedApe & co. could no longer do anything if someone were to steal the code and publish their own game (I may be completely in the wrong here, please tell me so if I am).
2. Decompiling the Android port
Because the Android build doesn't AOT compile the code, we can just extract it. This would give us a mobile Stardew Valley to work with, but there's still a lot to do. Android and iOS are two different beasts. OS-specific things would need to be reimplemented for iOS. I didn't think too much about it, but keyboard input and safe area (notch, home screen indicator) handling come to mind, not to mention just getting the thing to compile and work without problems game-engine-wise.
As we cannot just share this extracted/decompiled code, the user would have to acquire an APK file for the Android version by himself, but I don't think you can get APKs directly from the Google Play Store in a legal way, so unfortunately that would basically be piracy on the user's part.
At this point, a tool could be written which would take an Android APK, extract it, patch the assembly IL with iOS-specific changes (or decompile the assemblies, patch the C# code with iOS-specific changes and recompile it back to assemblies), patch those assemblies with the mods of the user's choosing and finally compile the whole thing back into an iOS app. Changing the mod list would require running this process again. Some of those steps could be cached between re-runs, so further changing of mods would be much faster.
Also... you know... this is just hilarious that you would need an Android version of the game to install mods on your iPhone.
Reflection
There were some concerns, that due to the AOT nature of iOS builds reflection would no longer be something that could be used in mods. Here comes the part where my Java world knowledge gets useful!
Back in the day I used to do some cross-platform Java game development, with the libGDX library. The desktop and Android platforms aren't anything special, but... The iOS build used a tool called RoboVM, which is very similar to what Xamarin AOT compiling does. It finds all of the types used by your project and compiles all of them as native code. It also supports reflection. Any code that is directly referenced will work right away, but if any type is only used at runtime (for example via
Class.forName("com.example.MyClass")
), you would need to specify it in RoboVM's configuration file.Xamarin AOT does support
System.Reflection
. I may be completely in the wrong here, but I don't see why Xamarin would be any different from RoboVM, it's a no-brainer to allow specifying types to compile manually, but I can't find any information regarding that. The only unsupported part in Xamarin AOT isSystem.Reflection.Emit
-- no code can be generated at runtime, but we wouldn't need that.Source: https://docs.microsoft.com/en-us/xamarin/ios/internals/limitations
Building the game
To build any iOS app, you need to use a Mac(Book) (well, technically, macOS -- hackintoshing is a thing). So, anyone who would like to install modded Stardew on their iOS devices would also need to have access to a macOS device.
...or they could get a pre-modded built IPA from the internet. Hopefully this does not turn into people installing malicious apps on their iPhones...
Signing the build
To actually run the game on your own iOS device, you need to either download it from the App Store (which is a no-go here) or sign it for your own device.
Signing for yourself
Recently (2-3 years ago? I can't remember) Apple made it so you can develop iOS apps for free. Apps signed with free developer accounts are valid for 7 days, after which you have to sign them and install them again. An app built with a paid developer account ($99/year) are valid for 1 year.
Alternatively, if the iOS device is jailbroken, the AppSync tweak can be installed which allows installing any IPA, without the need of signing it.
A tool like Cydia Impactor can be used to sign an IPA for your own device. Impactor works on Windows, Linux and macOS, so if you already have a pre-modded IPA, you no longer need a Mac to install it on your iPhone/iPad.
Enterprise signing
Apple also offers enterprise certificates and provisioning profiles, which don't require the actual device to be specified. There are (were?) (paid) web services out there, which allowed you to upload any IPA and they would sign it for you with their enterprise profile. With such a signed IPA, you could install it on any device.
Benefits for other platforms
Switching to generating patched assemblies could also have the benefit of speeding up the game startup process, as patching would only need to be done whenever any mods are changed. Just today I've seen someone say they're using 800+ mods at once (JESUS, BUT WHY) and they've already been waiting for 11 minutes and it still didn't launch. I don't know about you, but 11 minutes to launch a game, only to play it for an hour (no, actually 49 minutes, you lost the 11 minutes there) would certainly not make me want to play the game anymore.
Since mentioning JIT, I have learnt that there ere certain capable ways to enable JIT on iOS. For instance, it is paramount for playing Java Minecraft on higher iOS versions(iOS 17.4 and higher). The most convenient way is using nbtool on mobile devices, which avoid using Mac or windows PC. Other ways contain SideJIT and Trollstore(not available for 17.0.1 and higher). Therefore, SMAPI on iOS is not technically impossible. We are not anticipating modded Stardew Valley at any circumstances. It is acceptable to develop a JIT-required SMAPI.ipa although it will bring obstacles to those who have no knowledge of iOS jailbreak.
On my linux-arm64 laptop, I was able to build SMAPI just fine with a simple dotnet buid ./src/SMAPI.sln -c Release
, but it won't run due to requiring .NET 6.0, which (afaict) isn't available to download through any normal sources. The old version of .NET available through my (fedora) package manager is 8.0, and that also seems to be the oldest version available through the link the binary provides when running it (https://aka.ms/dotnet-core-applaunch?framework=Microsoft.NETCore.App&framework_version=6.0.0&arch=arm64&rid=fedora.42-arm64&os=fedora-asahi-remix.42)
I expect that updating to (at least) .NET 8.0 is necessary to get it functional for most people on arm linux (if I'm wrong and there's an easy way to provide .NET 6.0 for users or whatever, please let me know). I'm not a C# developer so I don't think I would know how to update this to .NET 8.0, but once someone else is able to do that, I could verify functionality and apply small fixes or whatever to get it working on arm linux.
I also think arm linux support would merit its own issue - there's a lot of different overlapping topics here, and having an issue just for arm linux would help to coordinate development on that specific topic without muddying the conversation on other topics here.
I expect that updating to (at least) .NET 8.0 is necessary to get it functional for most people on arm linux
Stardew Valley itself bundles .NET 6, and SMAPI just runs within that existing setup. In theory you could replace all the .NET files in the game folder with .NET 8 versions, though that'd be much more intrusive than the usual install (e.g. you'd need to reinstall the game to remove SMAPI).
I also think arm linux support would merit its own issue - there's a lot of different overlapping topics here
This is really just meant to be a high-level coordination thread. ARM64 won't be officially supported (unless we can build an ARM64 version on x64 or through a GitHub CI pipeline); so typically we'd have more specific discussions elsewhere (e.g. the Stardew Valley Discord or the unofficial port's repo), and summarize any high-level progress here.
On my linux-arm64 laptop, I was able to build SMAPI just fine with a simple
dotnet buid ./src/SMAPI.sln -c Release
, but it won't run due to requiring .NET 6.0, which (afaict) isn't available to download through any normal sources. The old version of .NET available through my (fedora) package manager is 8.0, and that also seems to be the oldest version available through the link the binary provides when running it (https://aka.ms/dotnet-core-applaunch?framework=Microsoft.NETCore.App&framework_version=6.0.0&arch=arm64&rid=fedora.42-arm64&os=fedora-asahi-remix.42)I expect that updating to (at least) .NET 8.0 is necessary to get it functional for most people on arm linux (if I'm wrong and there's an easy way to provide .NET 6.0 for users or whatever, please let me know). I'm not a C# developer so I don't think I would know how to update this to .NET 8.0, but once someone else is able to do that, I could verify functionality and apply small fixes or whatever to get it working on arm linux.
I also think arm linux support would merit its own issue - there's a lot of different overlapping topics here, and having an issue just for arm linux would help to coordinate development on that specific topic without muddying the conversation on other topics here.
Thanks on such effort. The problem would be that on arm64 linux we rely on x86 builds that are not supported, yet, at the end we use mono (6.8 by default on ubuntu noble, yet we could use much newer ones with a few clicks).. I have no idea how would that work out.
Looks like there's another person working on SMAPI for Android.
Guess wiki need to be updated(?)
Is SMAPI supported on ARM64 somehow? I am trying to run it on a Raspberry Pi?
root@561bb0313701:/data/nexus/SMAPI 4.2.1 installer# bash install\ on\ Linux.sh
install on Linux.sh: line 19: ./internal/linux/SMAPI.Installer: cannot execute binary file: Exec format error
Is SMAPI supported on ARM64 somehow? I am trying to run it on a Raspberry Pi?
root@561bb0313701:/data/nexus/SMAPI 4.2.1 installer# bash install\ on\ Linux.sh install on Linux.sh: line 19: ./internal/linux/SMAPI.Installer: cannot execute binary file: Exec format error
That's clearly saying otherwise. Sadly, SMAPI is x86_64 linux only. We could emulate it, tho, it would be wonderful if we would be able to run it natively, tho, running stardew valley natively, as it runs natively on cheap arm linux handhelds since long time ago (Check portmaster). Here a pic running natively with mono on ARM64 Linux with a beta compat x86 linux game copy that I got from steamcmd.
Just commenting to say I would also be interested in an ARM64 port if possible. I also want to ask @salvalie how exactly you managed to set up SMAPI with mono, and what the performance impact of that compared to native is.
How nono, I didn't. Stardew valley, up to the latest version runs just fine on mono. SMAPI isn't aupported on arm64 linux. That's why we are crying so hard here. SMAPI x86_64 linux could be used if you emulate the whole thing with box64 or fex, but the overhead is insane high
Btw @KaylathePianist , the mono arm64 SV approach is native.
I don't develop on ARM64 myself, but pull requests are welcome for whatever changes are needed to support it.
I don't develop on ARM64 myself, but pull requests are welcome for whatever changes are needed to support it.
We do understand the situation! I don't think it would be an easy chabge tbh bc we do use the legacy x86 version.. that one runs on mono. The x86_64 releases will not do, and those are the only supported releases by SMAPI, so, not an easy thing to support. It will probably came down to an ARM Linux ninja on an SMAPI fork. Thanks fort your concerns anyway. I am playing it on vanilla for now :)
I'm working on supporting Xbox One since a few days. It's currently all experimental and reading/debugging a lots of stufft, but I'm willing to implement that until the end of 2019.
Android support is currently in the early stages of development. Further work won't be ready until I have time available.
Update on Progress: Found a way to run SMAPI on Android devices without touching the main StardewValley.dll. Currently sifting through SMAPI exceptions.
YAU(Yet Another Update): Commited source code for the project. Working on an installer. Now I have to look into making Harmony work (thanks @0x0ade)
Basic Harmony functionality can now be restored on Android without a fork of Harmony, by making use of MonoMod.RuntimeDetour as a replacement detouring backend.
Running HarmonyDetourBridge.Init();
before using Harmony patches it in memory to use RuntimeDetour instead of its own ASM jumps, while also applying a few other changes for compatibility. RD itself supports x86, x64 and ARM.
This is still experimental, currently part of a separate MonoMod branch (rd-harmonybridge
) and has yet to be tested in the real world (user mods).
The HarmonyDetourBridge
is now stable enough that some mods using Harmony are now working on Android. This has yet to be tested further though - who knows what weird edge cases are going to pop up.
Thanks to @MartyrPher for testing anything I threw at him and quickly reporting back afterwards, and for testing the mods themselves!
@ZaneYork Thanks! I'll update the documentation. Is this still a separate fork, or a continuation of MartyrPher's fork now?
@ZaneYork Thanks! I'll update the documentation. Is this still a separate fork, or a continuation of MartyrPher's fork now?
Installer project is a separately fork, using same patch logic(a little improvement), but all code was rewrote.
SMAPI project is a continuation of MartyrPher's fork, forked from his 3.2 update.
@ZaneYork I updated the install guide on the wiki, and updated the summary here to link to that. Let me know if anything is incorrect, or feel free to edit the page!
I made a new SMAPI Installer for Android at here.Provides environment check feature and config editor(with JSON format check), launch button in Installer can check whether the mod's dependencies is satisfied or not.Also released to Play Store
Latest Update: I have released an experimental prototype found on my "SMAPI-Android-Installer" GitHub. Which can be found here. There is more info on that release page. Also, there is a little more to do regarding debris and other things before it hits 1.0. Cheers!
hey so If anyone is interested in looking into Ps4 Smapi development I have a jailbroken ps4, access to the decrypted rom and a file redirector tool to test modded files on my ps4. Let me know if anyone’s looking to try to develop on ps4!
It looks like @ZaneYork stopped updating their fork and responding to support requests in June, so currently @MartyrPher's fork seems to be the de facto version for Android.