From 0970e155c3bff29dd4cf830ef49a8dbe9a765aa6 Mon Sep 17 00:00:00 2001 From: MisterGatto Date: Wed, 25 Feb 2026 00:46:47 +0100 Subject: [PATCH 1/7] Canvas 1.7.1 --- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 1 + app/src/main/cpp/main.cpp | 42 +-- .../main/java/com/tgc/sky/BuildConfig.java | 2 +- .../artdeell/skymodloader/MainActivity.java | 45 ++- .../artdeell/skymodloader/auth/Google.java | 2 +- .../artdeell/skymodloader/auth/WebLogin.java | 2 +- .../elfmod/ModManagerActivity.java | 93 +++++-- app/src/main/res/layout/mod_list_element.xml | 230 +++++++--------- app/src/main/res/layout/mod_manager.xml | 260 +++++++++--------- app/src/main/res/layout/setting_layout.xml | 185 ++++++------- 11 files changed, 455 insertions(+), 413 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2afb26f..c5ec78d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,8 +23,8 @@ android { applicationId "git.artdeell.skymodloader" minSdk 26 targetSdk 34 - versionCode 55 - versionName "1.7.0" + versionCode 56 + versionName "1.7.1" externalNativeBuild { cmake { @@ -82,4 +82,4 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout-core:1.0.4' implementation 'com.bytedance.android:shadowhook:1.0.9' -} +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 68a0ee0..279bf09 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -116,6 +116,7 @@ + diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp index a36571f..6c00ea0 100644 --- a/app/src/main/cpp/main.cpp +++ b/app/src/main/cpp/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "include/misc/Logger.h" #include "main.h" #include "Core/imgui/imgui.h" @@ -22,7 +23,7 @@ extern "C" { #include "Core/ceserver/ceserver.h" } - +static std::string g_skyBuildKey; void do_scroll(); void fsel_setup(JNIEnv*); @@ -117,13 +118,13 @@ PRIVATE_API void DrawMods() { #include std::string formatUserLibInfo(const Canvas::UserLib& _userLib) { std::ostringstream oss; - oss << _userLib.Name << ": " << _userLib.Version << "\n"; + oss << _userLib.Name << ": " << _userLib.Version << "\\n"; if (!_userLib.Author.empty()) { - oss << "Author: " << _userLib.Author << "\n"; + oss << "Author: " << _userLib.Author << "\\n"; } if (!_userLib.Description.empty()) { - oss << "---------\nDescription:\n" << _userLib.Description << "\n"; + oss << "---------\\nDescription:\\n" << _userLib.Description << "\\n"; } return oss.str(); } @@ -210,10 +211,9 @@ Java_git_artdeell_skymodloader_MainActivity_settle( jboolean _ceserver_enabled, jboolean _hideCanvasMenu ) { - //env->GetJavaVM(&Canvas::javaVM); fsel_setup(env); Canvas::MainActivity = clazz; - Canvas::CeserverEnabled = _ceserver_enabled; // This config is set in case it would ever be needed + Canvas::CeserverEnabled = _ceserver_enabled; Canvas::hideCanvasMenu = _hideCanvasMenu; Canvas::gameVersion = _gameVersion; Canvas::gameType = _gameType; @@ -233,7 +233,6 @@ Java_git_artdeell_skymodloader_MainActivity_settle( typedef void (*func)(); PRIVATE_API void *UserThread(Canvas::UserLib *pUserLib){ - // Canvas::UserLib *pUserLib = (Canvas::UserLib *)Ulib; func (*Start)() = (func(*)())pUserLib->Start; pUserLib->Draw = (void (*)(bool *))Start(); if(Canvas::hideCanvasMenu) { @@ -243,7 +242,6 @@ PRIVATE_API void *UserThread(Canvas::UserLib *pUserLib){ Canvas::pushUserLib(*pUserLib); } delete pUserLib; - // pthread_exit(nullptr); return nullptr; } @@ -295,11 +293,6 @@ Java_git_artdeell_skymodloader_LibrarySelectorListener_onModLibrary( func (*InitLate)() = (func (*)()) dlsym( dl_entry, "InitLate"); pUserLib->InitLate = (void (*)(void))InitLate; - // pthread_t pid; - // pthread_create(&pid, nullptr, UserThread, (void *)pUserLib); - - // Do NOT run in a separate thread. - // Initialize mods BEFORE sky initializes bootloader UserThread(pUserLib); } @@ -334,6 +327,7 @@ Java_git_artdeell_skymodloader_MainActivity_setDeviceInfoNative( Canvas::deviceInfo.deviceManufacturer = env->GetStringUTFChars(_manufacturer, nullptr); Canvas::deviceInfo.deviceModel = env->GetStringUTFChars(_model, nullptr); } + extern "C" JNIEXPORT void JNICALL Java_git_artdeell_skymodloader_MainActivity_lateInitUserLibs(JNIEnv *env, jclass clazz) { @@ -349,13 +343,12 @@ Java_git_artdeell_skymodloader_MainActivity_lateInitUserLibs(JNIEnv *env, jclass }); lateInitThread.detach(); } + extern "C" JNIEXPORT void JNICALL Java_git_artdeell_skymodloader_MainActivity_customServer(JNIEnv *env, jclass clazz, jstring url) { - //?? ?? ?? 52 E2 03 1F AA ?? ?? ?? 94 ?? ?? ?? F9 ?? ?? ?? 52 - uintptr_t ssl = (new CipherUtils())->CipherScan("\x00\x00\x00\x52\xE2\x03\x1F\xAA\x00\x00\x00\x94\x00\x00\x00\xF9\x00\x00\x00\x52", "???xxxxx???x???x???x"); + uintptr_t ssl = (new CipherUtils())->CipherScan("\\x00\\x00\\x00\\x52\\xE2\\x03\\x1F\\xAA\\x00\\x00\\x00\\x94\\x00\\x00\\x00\\xF9\\x00\\x00\\x00\\x52", "???xxxxx???x???x???x"); LOGD("scanner %p", ssl); - // (new CipherPatch())->set_Opcode("01008052")->set_Address(ssl, false)->Fire(); } extern "C" @@ -366,4 +359,19 @@ Java_git_artdeell_skymodloader_MainActivity_getSysetemUI( jobject systemUI ) { Canvas::systemUI = env->NewGlobalRef(systemUI); -} \ No newline at end of file +} + +extern "C" +JNIEXPORT void JNICALL +Java_git_artdeell_skymodloader_MainActivity_nativeSetSkyBuildKey( + JNIEnv *env, + jclass clazz, + jstring key +) { + const char* keyStr = env->GetStringUTFChars(key, nullptr); + if (keyStr) { + g_skyBuildKey = std::string(keyStr); + env->ReleaseStringUTFChars(key, keyStr); + LOGI("SkyBuildKey set: %s", g_skyBuildKey.c_str()); + } +} diff --git a/app/src/main/java/com/tgc/sky/BuildConfig.java b/app/src/main/java/com/tgc/sky/BuildConfig.java index cc4e035..e155102 100644 --- a/app/src/main/java/com/tgc/sky/BuildConfig.java +++ b/app/src/main/java/com/tgc/sky/BuildConfig.java @@ -6,7 +6,7 @@ public class BuildConfig { public static String SKY_STAGE_NAME = "Live"; public static String SKY_SERVER_HOSTNAME = "live.radiance.thatgamecompany.com"; public static String SKY_VERSION = "0.17.5"; - public static String SKY_BUILD_ACCESS_KEY = "1743442606-3de96bd2ce8644c9d7144775e38bb8de13b3ac9b15e2984b0304445c5bbe0174"; + public static String SKY_BUILD_ACCESS_KEY = "0"; public static int VERSION_CODE = 192395; } diff --git a/app/src/main/java/git/artdeell/skymodloader/MainActivity.java b/app/src/main/java/git/artdeell/skymodloader/MainActivity.java index d22f84a..d50627a 100644 --- a/app/src/main/java/git/artdeell/skymodloader/MainActivity.java +++ b/app/src/main/java/git/artdeell/skymodloader/MainActivity.java @@ -26,10 +26,12 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import dalvik.system.DexClassLoader; import git.artdeell.skymodloader.elfmod.ElfRefcountLoader; import git.artdeell.skymodloader.iconloader.IconLoader; @@ -57,17 +59,10 @@ protected void onCreate(Bundle savedInstanceState) { ceserverEnabled = sharedPreferences.getBoolean("ceserver", false); hideCanvasMenu = sharedPreferences.getBoolean("hide_canvas_menu", false); - if (sharedPreferences.getBoolean("custom_build_key", false)) { - String buildKey = sharedPreferences.getString("build_access_key", ""); - if (!buildKey.isEmpty()) { - BuildConfig.SKY_BUILD_ACCESS_KEY = buildKey; - Log.i("MainActivity", "Applied custom build key: " + buildKey.substring(0, Math.min(20, buildKey.length())) + "..."); - } - } - sharedPreferences.edit().putString("sky_package_name", SKY_PACKAGE_NAME).apply(); skyPackages = new HashMap<>(); skyPackages.put("com.tgc.sky.android", 0); + skyPackages.put("com.tgc.sky.vn.android", 0); skyPackages.put("com.tgc.sky.android.huawei", 1); loadGame(); } @@ -86,6 +81,29 @@ private void startLogcatMonitoring() { } } + private String getSkyBuildAccessKey() { + try { + ApplicationInfo skyInfo = getPackageManager().getApplicationInfo( + SKY_PACKAGE_NAME, PackageManager.GET_META_DATA + ); + DexClassLoader skyLoader = new DexClassLoader( + skyInfo.sourceDir, + getCacheDir().getAbsolutePath(), + skyInfo.nativeLibraryDir, + ClassLoader.getSystemClassLoader() + ); + Class buildConfig = skyLoader.loadClass("com.tgc.sky.BuildConfig"); + Field field = buildConfig.getDeclaredField("SKY_BUILD_ACCESS_KEY"); + field.setAccessible(true); + String key = (String) field.get(null); + Log.i("MainActivity", "SkyBuildKey loaded from Sky BuildConfig"); + return key; + } catch (Exception e) { + Log.e("MainActivity", "getSkyBuildAccessKey failed: " + e.getMessage()); + return null; + } + } + private void loadGame() { PackageManager pm = getPackageManager(); try { @@ -144,6 +162,16 @@ private void loadGame() { ElfLoader loader = new ElfLoader(libPath + ":/system/lib64"); loader.loadLib("libBootloader.so"); System.loadLibrary("ciphered"); + + String buildKey = getSkyBuildAccessKey(); + if (buildKey != null) { + BuildConfig.SKY_BUILD_ACCESS_KEY = buildKey; + nativeSetSkyBuildKey(buildKey); + Log.i("MainActivity", "BuildKey applied: " + buildKey.substring(0, Math.min(20, buildKey.length())) + "..."); + } else { + Log.w("MainActivity", "NOT FOUND, DEFAULT INSTEAD: " + BuildConfig.SKY_BUILD_ACCESS_KEY); + } + setDeviceInfoNative( deviceInfo.xdpi, deviceInfo.ydpi, @@ -325,4 +353,5 @@ public static native void setDeviceInfoNative( public static native void customServer(String url); public static native void lateInitUserLibs(); public static native void getSysetemUI(Object systemUI); + private static native void nativeSetSkyBuildKey(String key); } \ No newline at end of file diff --git a/app/src/main/java/git/artdeell/skymodloader/auth/Google.java b/app/src/main/java/git/artdeell/skymodloader/auth/Google.java index faf2d60..b105e99 100644 --- a/app/src/main/java/git/artdeell/skymodloader/auth/Google.java +++ b/app/src/main/java/git/artdeell/skymodloader/auth/Google.java @@ -7,4 +7,4 @@ public class Google extends WebLogin { public Google() { super("Google", SystemAccountType.kSystemAccountType_Google); } -} +} \ No newline at end of file diff --git a/app/src/main/java/git/artdeell/skymodloader/auth/WebLogin.java b/app/src/main/java/git/artdeell/skymodloader/auth/WebLogin.java index 5c2246f..2e056a9 100644 --- a/app/src/main/java/git/artdeell/skymodloader/auth/WebLogin.java +++ b/app/src/main/java/git/artdeell/skymodloader/auth/WebLogin.java @@ -195,4 +195,4 @@ public void onPageFinished(WebView view, String url) { if(url.startsWith("https://"+BuildConfig.SKY_SERVER_HOSTNAME)) return; showWebView(); } -} +} \ No newline at end of file diff --git a/app/src/main/java/git/artdeell/skymodloader/elfmod/ModManagerActivity.java b/app/src/main/java/git/artdeell/skymodloader/elfmod/ModManagerActivity.java index 48a48ed..3910e8e 100644 --- a/app/src/main/java/git/artdeell/skymodloader/elfmod/ModManagerActivity.java +++ b/app/src/main/java/git/artdeell/skymodloader/elfmod/ModManagerActivity.java @@ -7,10 +7,13 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.URLSpan; import android.util.Log; import android.view.View; import android.widget.Button; @@ -23,8 +26,6 @@ import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.switchmaterial.SwitchMaterial; -import com.google.android.material.textfield.TextInputEditText; -import android.view.inputmethod.EditorInfo; import java.io.File; import java.io.FileNotFoundException; @@ -55,6 +56,7 @@ public class ModManagerActivity extends Activity implements LoadingListener, Mod private View loadingBar; private Button btnLaunchLive; private Button btnLaunchHuawei; + private Button btnLaunchChplay; private String skyPackageName; private SharedPreferences sharedPreferences; private ArrayList skyPackages; @@ -70,6 +72,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { loadingBar = findViewById(R.id.mm_loadBar); btnLaunchLive = findViewById(R.id.mm_launch_live); btnLaunchHuawei = findViewById(R.id.mm_launch_huawei); + btnLaunchChplay = findViewById(R.id.mm_launch_chplay); ((TextView) findViewById(R.id.mm_versionName)).setText(getString(R.string.mod_canvas_version, BuildConfig.VERSION_NAME)); initializeSkyPackages(); sharedPreferences = getSharedPreferences("package_configs", Context.MODE_PRIVATE); @@ -89,7 +92,7 @@ private void initializeModUpdater() { public void startModUpdater(ElfModUIMetadata metadata) { Log.i("MMA", "Starting mod update..."); - if(mDialogManager.isConnected()) { + if (mDialogManager.isConnected()) { Toast.makeText(this, R.string.updater_busy, Toast.LENGTH_SHORT).show(); return; } @@ -107,6 +110,7 @@ public void startModUpdater(ElfModUIMetadata metadata) { private void initializeSkyPackages() { skyPackages = new ArrayList<>(); skyPackages.add("com.tgc.sky.android"); + skyPackages.add("com.tgc.sky.vn.android"); skyPackages.add("com.tgc.sky.android.huawei"); SMLApplication.skyPName = skyPackages.get(0); } @@ -119,7 +123,8 @@ private void updateButtonTextColor() { } setButtonTextColor(btnLaunchLive, skyPackages.get(0)); - setButtonTextColor(btnLaunchHuawei, skyPackages.get(1)); + setButtonTextColor(btnLaunchChplay, skyPackages.get(1)); + setButtonTextColor(btnLaunchHuawei, skyPackages.get(2)); } private void setButtonTextColor(Button button, String packageName) { @@ -149,10 +154,14 @@ private void setButtonClickListeners() { skyPackageName = skyPackages.get(0); launchGame(); }); - btnLaunchHuawei.setOnClickListener(view -> { + btnLaunchChplay.setOnClickListener(view -> { skyPackageName = skyPackages.get(1); launchGame(); }); + btnLaunchHuawei.setOnClickListener(view -> { + skyPackageName = skyPackages.get(2); + launchGame(); + }); } private void setButtonLongClickListeners() { @@ -160,10 +169,14 @@ private void setButtonLongClickListeners() { setSkyPackageName(skyPackages.get(0)); return true; }); - btnLaunchHuawei.setOnLongClickListener(view -> { + btnLaunchChplay.setOnLongClickListener(view -> { setSkyPackageName(skyPackages.get(1)); return true; }); + btnLaunchHuawei.setOnLongClickListener(view -> { + setSkyPackageName(skyPackages.get(2)); + return true; + }); } public void setSkyPackageName(String pkg) { @@ -221,6 +234,51 @@ public void onAddMod(View v) { startActivityForResult(intent, REQUEST_MOD); } + public void onModInfo(View v) { + SpannableString message = new SpannableString( + "How to add a mod:\n\n" + + "① Download a compatible .so file\n\n" + + "② Tap on \"Add Mod\" and select the file\n\n" + + "③ You can activate or disable the mod with the toggle\n\n" + + "④ Start the game\n\n" + + "⚠︎ Sometimes mods are broken/need to be updated!\n\n" + + "───────────────────\n\n" + + "Community\n\n" + + "Discord | Telegram" + ); + + String full = message.toString(); + + int discordStart = full.indexOf("Discord"); + int discordEnd = discordStart + "Discord".length(); + int telegramStart = full.indexOf("Telegram"); + int telegramEnd = telegramStart + "Telegram".length(); + + message.setSpan(new URLSpan("https://discord.gg/ekpUFWcCFN") { + @Override + public void onClick(View widget) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://discord.gg/ekpUFWcCFN"))); + } + }, discordStart, discordEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + message.setSpan(new URLSpan("https://t.me/skyautowax") { + @Override + public void onClick(View widget) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/skyautowax"))); + } + }, telegramStart, telegramEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + AlertDialog dialog = new AlertDialog.Builder(this) + .setTitle("Info & Community") + .setMessage(message) + .setPositiveButton("OK", null) + .create(); + + dialog.show(); + ((TextView) dialog.findViewById(android.R.id.message)) + .setMovementMethod(LinkMovementMethod.getInstance()); + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); @@ -238,6 +296,7 @@ private void setLoadingStatus(boolean enable) { loadingBar.setVisibility(enable ? View.VISIBLE : View.GONE); addModButton.setEnabled(!enable); btnLaunchLive.setEnabled(!enable); + btnLaunchChplay.setEnabled(!enable); btnLaunchHuawei.setEnabled(!enable); modListView.setClickable(!enable); } @@ -325,7 +384,7 @@ private void handleException() { dialogY.positiveButton.setVisibility(View.GONE); dialogY.title.setText(R.string.mod_add_unable); dialogY.content.setText(message); - dialogY.negativeButton.setOnClickListener((v)->dialogY.dialog.dismiss()); + dialogY.negativeButton.setOnClickListener((view) -> dialogY.dialog.dismiss()); dialogY.dialog.setCancelable(true); dialogY.dialog.show(); } @@ -389,11 +448,6 @@ public void runUpdater() { bindService(updaterService, new CanvasUpdaterConnection(this), BIND_AUTO_CREATE); } - private int dpToPixels(int dp) { - float scale = getResources().getDisplayMetrics().density; - return (int) (dp * scale + 0.5f); - } - public void onClearAppData(View view) { clearAppDataSelective(); } @@ -410,8 +464,7 @@ private void clearAppDataSelective() { .setPositiveButton("Clear", (dialog, which) -> { new Thread(() -> { try { - boolean isEmulator = getPackageName().equals("com.tgc.sky.android.sml"); - String packageName = isEmulator ? "com.tgc.sky.android.sml" : "git.artdeell.skymodloader"; + String packageName = getPackageName(); File dataDir = new File("/data/data/" + packageName); File filesDir = getFilesDir(); File externalDataDir = new File("/sdcard/Android/data/" + packageName); @@ -476,9 +529,9 @@ private void clearAppDataSelective() { }); } catch (Exception e) { Log.e("ClearData", "Error clearing data", e); - runOnUiThread(() -> { - Toast.makeText(this, "Error clearing data: " + e.getMessage(), Toast.LENGTH_LONG).show(); - }); + runOnUiThread(() -> + Toast.makeText(this, "Error clearing data: " + e.getMessage(), Toast.LENGTH_LONG).show() + ); } }).start(); }) @@ -532,4 +585,4 @@ private void deleteRecursive(File fileOrDirectory) { } fileOrDirectory.delete(); } -} \ No newline at end of file +} diff --git a/app/src/main/res/layout/mod_list_element.xml b/app/src/main/res/layout/mod_list_element.xml index a6db357..aef53c3 100644 --- a/app/src/main/res/layout/mod_list_element.xml +++ b/app/src/main/res/layout/mod_list_element.xml @@ -1,11 +1,8 @@ - - - @@ -14,30 +11,30 @@ - + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="12dp"> - + android:orientation="horizontal" + android:gravity="center_vertical"> + android:alpha="0.35" + android:textSize="22sp" /> - + - + + tools:text="Author: Someone" /> - + tools:text="Version: 1.0.0" /> - - - + tools:text="Description of the mod" /> - - - - - - - - + android:layout_marginBottom="2dp" /> + android:orientation="horizontal" + android:layout_marginTop="6dp"> - - - - + + + + + + + + + android:clickable="true" + android:focusable="true" + android:gravity="center_vertical" + android:padding="4dp" + android:onClick="@{() -> _item.remove()}" + android:orientation="horizontal"> + + + + + + - - - + - - diff --git a/app/src/main/res/layout/mod_manager.xml b/app/src/main/res/layout/mod_manager.xml index 14deb19..9c12064 100644 --- a/app/src/main/res/layout/mod_manager.xml +++ b/app/src/main/res/layout/mod_manager.xml @@ -54,6 +54,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" + android:textSize="11sp" + android:alpha="0.6" app:layout_constraintBottom_toTopOf="@+id/mm_loadBar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> @@ -72,21 +74,21 @@ android:id="@+id/box_header" android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="center_horizontal|center_vertical" + android:gravity="center_vertical" android:orientation="horizontal" - android:paddingLeft="10dp" - android:paddingTop="5dp" - android:paddingRight="10dp" - android:paddingBottom="5dp"> + android:paddingLeft="12dp" + android:paddingTop="10dp" + android:paddingRight="12dp" + android:paddingBottom="10dp"> @@ -96,195 +98,197 @@ android:id="@+id/title_header_separator" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingLeft="3dp" - android:paddingRight="3dp" + android:paddingLeft="8dp" + android:paddingRight="8dp" android:text="|" android:textColor="@color/text" - android:textSize="16sp" - android:textStyle="bold" /> - - + android:alpha="0.4" + android:textSize="18sp" /> + android:layout_weight="1" + android:orientation="vertical"> + + + + + + + + - + android:background="@drawable/separator" /> - - - - + android:paddingLeft="12dp" + android:paddingRight="12dp" + android:text="@string/play" + android:textColor="@color/text" + android:textSize="13sp" + android:textStyle="bold" /> - + android:background="@drawable/separator" /> + + android:orientation="vertical" + android:layout_marginStart="14dp" + android:layout_marginEnd="14dp" + android:layout_marginTop="8dp">