From 7599f71c1711d347abfed23f5c4a0092784dfddd Mon Sep 17 00:00:00 2001
From: Logan McNaughton <848146+loganmc10@users.noreply.github.com>
Date: Mon, 25 May 2026 19:07:56 +0200
Subject: [PATCH] add sdl for android
---
Cargo.lock | 1 +
Cargo.toml | 1 +
android-project/.gitignore | 2 ++
.../app/src/main/AndroidManifest.xml | 1 +
.../github/gopher64/gopher64/N64Activity.kt | 5 ++++
build.rs | 25 +++++++++++++++++++
src/ui/android.rs | 22 ++++++++++++++++
src/ui/gui.rs | 8 ++++++
8 files changed, 65 insertions(+)
create mode 100644 android-project/app/src/main/java/io/github/gopher64/gopher64/N64Activity.kt
diff --git a/Cargo.lock b/Cargo.lock
index c6e0d9eb..2af93b0f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2233,6 +2233,7 @@ dependencies = [
"reqwest",
"rfd",
"sdl3-image-sys",
+ "sdl3-src",
"sdl3-sys",
"sdl3-ttf-sys",
"semver",
diff --git a/Cargo.toml b/Cargo.toml
index a11ed3c2..13b2443b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -51,6 +51,7 @@ jni = "0.22"
[build-dependencies]
winresource = "0.1"
bindgen = "0.72"
+sdl3-src = "3.4"
slint-build = { version = "1.12", optional = true }
cc = { version = "1.2", features = ["parallel"] }
diff --git a/android-project/.gitignore b/android-project/.gitignore
index cca6ed61..6edf443d 100644
--- a/android-project/.gitignore
+++ b/android-project/.gitignore
@@ -34,3 +34,5 @@ google-services.json
# Android Profiling
*.hprof
+
+app/src/main/java/org/libsdl/app/
diff --git a/android-project/app/src/main/AndroidManifest.xml b/android-project/app/src/main/AndroidManifest.xml
index e3061a12..292d6682 100644
--- a/android-project/app/src/main/AndroidManifest.xml
+++ b/android-project/app/src/main/AndroidManifest.xml
@@ -18,6 +18,7 @@
+
\ No newline at end of file
diff --git a/android-project/app/src/main/java/io/github/gopher64/gopher64/N64Activity.kt b/android-project/app/src/main/java/io/github/gopher64/gopher64/N64Activity.kt
new file mode 100644
index 00000000..080251bb
--- /dev/null
+++ b/android-project/app/src/main/java/io/github/gopher64/gopher64/N64Activity.kt
@@ -0,0 +1,5 @@
+package io.github.gopher64.gopher64
+
+import org.libsdl.app.SDLActivity
+
+class N64Activity : SDLActivity() {}
diff --git a/build.rs b/build.rs
index 8b0138ff..fba69842 100644
--- a/build.rs
+++ b/build.rs
@@ -306,4 +306,29 @@ fn main() {
{
println!("cargo:rustc-cfg=ra_hardcore_enabled");
}
+ if os == "android" {
+ copy_dir_all(
+ std::path::Path::new(sdl3_src::SOURCE_DIR)
+ .join("android-project/app/src/main/java/org/libsdl/app"),
+ "android-project/app/src/main/java/org/libsdl/app",
+ )
+ .unwrap();
+ }
+}
+
+fn copy_dir_all(
+ src: impl AsRef,
+ dst: impl AsRef,
+) -> std::io::Result<()> {
+ std::fs::create_dir_all(&dst)?;
+ for entry in std::fs::read_dir(src)? {
+ let entry = entry?;
+ let ty = entry.file_type()?;
+ if ty.is_dir() {
+ copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
+ } else {
+ std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
+ }
+ }
+ Ok(())
}
diff --git a/src/ui/android.rs b/src/ui/android.rs
index a74a466a..4c49dc23 100644
--- a/src/ui/android.rs
+++ b/src/ui/android.rs
@@ -127,6 +127,28 @@ pub struct ControllerInfo {
pub descriptor: String,
}
+pub fn configure_input_profile(
+ _profile_name: slint::SharedString,
+ _dinput: bool,
+ _deadzone: i32,
+ _weak: slint::Weak,
+) {
+}
+
+pub fn run_rom(
+ _file_path: std::path::PathBuf,
+ _game_settings: ui::GameSettings,
+ netplay: Option,
+ _weak: slint::Weak,
+) {
+ if let Some(netplay) = netplay {
+ println!(
+ "Netplay peer addr: {} player number: {}",
+ netplay.peer_addr, netplay.player_number
+ );
+ }
+}
+
fn get_vm() -> Option {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
diff --git a/src/ui/gui.rs b/src/ui/gui.rs
index 347b8dcb..2ab734c3 100644
--- a/src/ui/gui.rs
+++ b/src/ui/gui.rs
@@ -353,6 +353,10 @@ fn controller_window(app: &AppWindow, config: &ui::config::Config) {
let deadzone = handle.get_input_deadzone();
handle.set_show_input_profile(false);
+ #[cfg(target_os = "android")]
+ ui::android::configure_input_profile(profile_name, dinput, deadzone, weak_app2);
+
+ #[cfg(not(target_os = "android"))]
tokio::spawn(async move {
let cli_path = std::env::current_exe()
.unwrap()
@@ -538,6 +542,10 @@ pub fn run_rom(
netplay: Option,
weak: slint::Weak,
) {
+ #[cfg(target_os = "android")]
+ ui::android::run_rom(file_path, game_settings, netplay, weak);
+
+ #[cfg(not(target_os = "android"))]
tokio::spawn(async move {
weak.upgrade_in_event_loop(move |handle| handle.set_game_running(true))
.unwrap();