From e20551b9110ba056795348e5bad4e12296b09a60 Mon Sep 17 00:00:00 2001 From: izzy2lost Date: Thu, 8 Jan 2026 14:46:22 -0500 Subject: [PATCH] add view button and better audio defaults --- android/app/build.gradle.kts | 4 +- .../app/src/main/assets/Config/Supermodel.ini | 7 +- .../app/src/main/cpp/android_input_system.cpp | 11 ++++ .../app/src/main/cpp/android_input_system.h | 6 ++ android/app/src/main/cpp/native-lib.cpp | 13 +++- .../com/izzy2lost/super3/Super3Activity.kt | 64 +++++++++++++++++++ .../src/main/res/layout/overlay_controls.xml | 16 +++++ 7 files changed, 112 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 3aaa275..7235c8f 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -12,8 +12,8 @@ android { minSdk = 26 targetSdk = 36 - versionCode = 4 - versionName = "1.0.3" + versionCode = 5 + versionName = "1.0.4" ndkVersion = "29.0.14206865" diff --git a/android/app/src/main/assets/Config/Supermodel.ini b/android/app/src/main/assets/Config/Supermodel.ini index 4e346bf..7dc7af6 100644 --- a/android/app/src/main/assets/Config/Supermodel.ini +++ b/android/app/src/main/assets/Config/Supermodel.ini @@ -14,9 +14,8 @@ EmulateSound = 1 EmulateDSB = 1 NbSoundChannels = 4 SoundFreq = 57.6 -; Android audio uses "200" as a sane default (matches typical Supermodel configs). -SoundVolume = 200 -MusicVolume = 200 +SoundVolume = 100 +MusicVolume = 150 LegacySoundDSP = 0 ForceFeedback = 0 Network = 0 @@ -24,7 +23,7 @@ SimulateNet = 0 Outputs = none ; Rendering (Android GLES path) -New3DEngine = 0 +New3DEngine = 1 QuadRendering = 0 XResolution = 496 YResolution = 384 diff --git a/android/app/src/main/cpp/android_input_system.cpp b/android/app/src/main/cpp/android_input_system.cpp index f288d10..ce28672 100644 --- a/android/app/src/main/cpp/android_input_system.cpp +++ b/android/app/src/main/cpp/android_input_system.cpp @@ -166,6 +166,12 @@ void AndroidInputSystem::ApplyConfig(const Util::Config::Node& config) m_touchShift4.a = keySc(get("InputGearShift4", "KEY_0"), SDL_SCANCODE_0); m_touchShiftN.a = keySc(get("InputGearShiftN", "KEY_6"), SDL_SCANCODE_6); + m_touchViewChange.a = keySc(get("InputViewChange", "KEY_A"), SDL_SCANCODE_A); + m_touchVr1.a = keySc(get("InputVR1", "KEY_A"), SDL_SCANCODE_A); + m_touchVr2.a = keySc(get("InputVR2", "KEY_S"), SDL_SCANCODE_S); + m_touchVr3.a = keySc(get("InputVR3", "KEY_D"), SDL_SCANCODE_D); + m_touchVr4.a = keySc(get("InputVR4", "KEY_F"), SDL_SCANCODE_F); + m_touchPunch.a = keySc(get("InputPunch", "KEY_A"), SDL_SCANCODE_A); m_touchKick.a = keySc(get("InputKick", "KEY_S"), SDL_SCANCODE_S); m_touchGuard.a = keySc(get("InputGuard", "KEY_D"), SDL_SCANCODE_D); @@ -351,6 +357,11 @@ void AndroidInputSystem::HandleTouch(const SDL_TouchFingerEvent& tf, bool down) // Fighting game action buttons (fingerId encoded from Java). switch (tf.fingerId) { + case 1152: SetKeys(m_touchViewChange, down); return; + case 1153: SetKeys(m_touchVr1, down); return; + case 1154: SetKeys(m_touchVr2, down); return; + case 1155: SetKeys(m_touchVr3, down); return; + case 1156: SetKeys(m_touchVr4, down); return; case 1110: SetKeys(m_touchPunch, down); return; case 1111: SetKeys(m_touchKick, down); return; case 1112: SetKeys(m_touchGuard, down); return; diff --git a/android/app/src/main/cpp/android_input_system.h b/android/app/src/main/cpp/android_input_system.h index eb949c1..090a5bb 100644 --- a/android/app/src/main/cpp/android_input_system.h +++ b/android/app/src/main/cpp/android_input_system.h @@ -131,6 +131,12 @@ private: DualScancode m_touchShift4{SDL_SCANCODE_0, SDL_SCANCODE_UNKNOWN}; DualScancode m_touchShiftN{SDL_SCANCODE_6, SDL_SCANCODE_UNKNOWN}; + DualScancode m_touchViewChange{SDL_SCANCODE_A, SDL_SCANCODE_UNKNOWN}; + DualScancode m_touchVr1{SDL_SCANCODE_A, SDL_SCANCODE_UNKNOWN}; + DualScancode m_touchVr2{SDL_SCANCODE_S, SDL_SCANCODE_UNKNOWN}; + DualScancode m_touchVr3{SDL_SCANCODE_D, SDL_SCANCODE_UNKNOWN}; + DualScancode m_touchVr4{SDL_SCANCODE_F, SDL_SCANCODE_UNKNOWN}; + DualScancode m_touchPunch{SDL_SCANCODE_A, SDL_SCANCODE_UNKNOWN}; DualScancode m_touchKick{SDL_SCANCODE_S, SDL_SCANCODE_UNKNOWN}; DualScancode m_touchGuard{SDL_SCANCODE_D, SDL_SCANCODE_UNKNOWN}; diff --git a/android/app/src/main/cpp/native-lib.cpp b/android/app/src/main/cpp/native-lib.cpp index 93d5c1c..e641d1d 100644 --- a/android/app/src/main/cpp/native-lib.cpp +++ b/android/app/src/main/cpp/native-lib.cpp @@ -170,10 +170,10 @@ struct Super3Host { config.Set("NbSoundChannels", "4"); config.Set("SoundFreq", "57.6"); // Supermodel.ini commonly uses 200 as "100%". - config.Set("SoundVolume", "200"); - config.Set("MusicVolume", "200"); + config.Set("SoundVolume", "100"); + config.Set("MusicVolume", "150"); config.Set("LegacySoundDSP", false); - config.Set("New3DEngine", false); + config.Set("New3DEngine", true); config.Set("New3DAccurate", false); config.Set("QuadRendering", false); config.Set("FlipStereo", false); @@ -276,6 +276,13 @@ struct Super3Host { ensureKeyboardFallback("InputCharge", "KEY_D"); ensureKeyboardFallback("InputJump", "KEY_F"); + // Racing view buttons. + ensureKeyboardFallback("InputViewChange", "KEY_A"); + ensureKeyboardFallback("InputVR1", "KEY_A"); + ensureKeyboardFallback("InputVR2", "KEY_S"); + ensureKeyboardFallback("InputVR3", "KEY_D"); + ensureKeyboardFallback("InputVR4", "KEY_F"); + // Virtual-On (twin joystick) macros/buttons: keep keyboard fallbacks so touch controls work even // if the user remaps to joystick-only. ensureKeyboardFallback("InputTwinJoyTurnLeft", "KEY_Q"); diff --git a/android/app/src/main/java/com/izzy2lost/super3/Super3Activity.kt b/android/app/src/main/java/com/izzy2lost/super3/Super3Activity.kt index c5384c8..ed229e2 100644 --- a/android/app/src/main/java/com/izzy2lost/super3/Super3Activity.kt +++ b/android/app/src/main/java/com/izzy2lost/super3/Super3Activity.kt @@ -135,6 +135,16 @@ class Super3Activity : SDLActivity() { gamesXml.isNotBlank() && GameInputsIndex.hasAnyInputType(gamesXml, game, setOf("shiftupdown")) + val hasViewChange = + game.isNotBlank() && + gamesXml.isNotBlank() && + GameInputsIndex.hasAnyInputType(gamesXml, game, setOf("viewchange")) + + val hasVr4 = + game.isNotBlank() && + gamesXml.isNotBlank() && + GameInputsIndex.hasAnyInputType(gamesXml, game, setOf("vr4")) + val isGunGame = game.isNotBlank() && gamesXml.isNotBlank() && @@ -191,6 +201,9 @@ class Super3Activity : SDLActivity() { overlay.findViewById(R.id.overlay_shifter)?.visibility = if (isRacing && showShifter) View.VISIBLE else View.GONE + overlay.findViewById(R.id.overlay_view)?.visibility = + if (isRacing && (hasViewChange || hasVr4)) View.VISIBLE else View.GONE + overlay.findViewById(R.id.overlay_reload)?.visibility = if (isGunGame) View.VISIBLE else View.GONE @@ -255,6 +268,37 @@ class Super3Activity : SDLActivity() { } } + fun bindDynamicMomentary(viewId: Int, fingerIdProvider: () -> Int, x: Float, y: Float) { + val v = overlay.findViewById(viewId) ?: return + var activeFingerId: Int? = null + v.setOnTouchListener { _, ev -> + when (ev.actionMasked) { + MotionEvent.ACTION_DOWN -> { + v.alpha = 0.75f + val id = fingerIdProvider() + activeFingerId = id + nativeTouch(MotionEvent.ACTION_DOWN, id, x, y) + true + } + MotionEvent.ACTION_UP -> { + v.alpha = 1.0f + val id = activeFingerId ?: fingerIdProvider() + nativeTouch(MotionEvent.ACTION_UP, id, x, y) + activeFingerId = null + true + } + MotionEvent.ACTION_CANCEL -> { + v.alpha = 1.0f + val id = activeFingerId ?: fingerIdProvider() + nativeTouch(MotionEvent.ACTION_UP, id, x, y) + activeFingerId = null + true + } + else -> true + } + } + } + // Use synthetic touch IDs that won't collide with real pointer IDs. bindMomentary(R.id.overlay_coin, fingerId = 1101, x = 0.10f, y = 0.90f) bindMomentary(R.id.overlay_start, fingerId = 1102, x = 0.50f, y = 0.90f) @@ -344,6 +388,26 @@ class Super3Activity : SDLActivity() { bindHeld(R.id.overlay_gas, fingerId = gasId, x = 0.85f, y = 0.35f) bindHeld(R.id.overlay_brake, fingerId = brakeId, x = 0.85f, y = 0.80f) + if (hasViewChange || hasVr4) { + var vrIndex = 0 + bindDynamicMomentary( + R.id.overlay_view, + fingerIdProvider = { + if (hasVr4) { + val id = 1153 + (vrIndex % 4) + vrIndex = (vrIndex + 1) % 4 + id + } else { + 1152 + } + }, + x = 0.90f, + y = 0.50f, + ) + } else { + overlay.findViewById(R.id.overlay_view)?.setOnTouchListener(null) + } + val wheel = overlay.findViewById(R.id.overlay_wheel) if (isRacing) { wheel?.setOnTouchListener { v, ev -> diff --git a/android/app/src/main/res/layout/overlay_controls.xml b/android/app/src/main/res/layout/overlay_controls.xml index f167882..5dec23f 100644 --- a/android/app/src/main/res/layout/overlay_controls.xml +++ b/android/app/src/main/res/layout/overlay_controls.xml @@ -150,6 +150,22 @@ android:orientation="vertical" android:visibility="gone"> + +