mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
Add data files
This commit is contained in:
@@ -13,3 +13,4 @@
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
app/src/main/assets/hash.txt
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import com.android.build.gradle.internal.tasks.factory.dependsOn
|
||||
import java.io.IOException
|
||||
import java.security.MessageDigest
|
||||
import java.util.regex.Pattern
|
||||
import javax.xml.bind.DatatypeConverter
|
||||
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
@@ -35,6 +40,8 @@ fun getVersionName(): String {
|
||||
|
||||
fun getVersionCode(): Int = System.getenv("VERSION_CODE")?.toIntOrNull() ?: 1
|
||||
|
||||
val cemuDataFilesFolder = "../../../bin"
|
||||
|
||||
android {
|
||||
namespace = "info.cemu.cemu"
|
||||
compileSdk = 35
|
||||
@@ -47,6 +54,17 @@ android {
|
||||
versionName = getVersionName()
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
androidResources {
|
||||
ignoreAssetsPattern = "!*cemu.mo:"
|
||||
}
|
||||
|
||||
sourceSets.getByName("main") {
|
||||
assets {
|
||||
srcDir(cemuDataFilesFolder)
|
||||
}
|
||||
}
|
||||
|
||||
packaging {
|
||||
jniLibs.useLegacyPackaging = true
|
||||
}
|
||||
@@ -139,6 +157,58 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ComputeCemuDataFilesHashTask : DefaultTask() {
|
||||
private val ignoreFilePatterns = arrayOf(
|
||||
Pattern.compile(".*cemu\\.mo"),
|
||||
Pattern.compile(".*Cemu_(?:debug|release)"),
|
||||
)
|
||||
|
||||
@get:Input
|
||||
abstract val cemuDataFolder: Property<String>
|
||||
|
||||
private fun isFileIgnored(file: File): Boolean {
|
||||
return ignoreFilePatterns.any { pattern -> pattern.matcher(file.path).matches() }
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun computeCemuDataFilesHash() {
|
||||
val assetDir = File(project.projectDir, "src/main/assets")
|
||||
if (!assetDir.exists()) {
|
||||
assetDir.mkdirs()
|
||||
}
|
||||
|
||||
val cemuDataFilesFile = File(project.projectDir, cemuDataFolder.get())
|
||||
val hashFile = File(assetDir, "hash.txt")
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
|
||||
if (!cemuDataFilesFile.isDirectory) {
|
||||
hashFile.writeText("invalid")
|
||||
return
|
||||
}
|
||||
|
||||
val fileHashes = cemuDataFilesFile.walkTopDown()
|
||||
.filter { it.isFile && !isFileIgnored(it) }
|
||||
.sortedBy { it.path }
|
||||
.map {
|
||||
md.reset()
|
||||
md.update(it.path.toByteArray())
|
||||
md.update(it.readBytes())
|
||||
md.digest()
|
||||
}
|
||||
.toList()
|
||||
|
||||
md.reset()
|
||||
fileHashes.forEach { md.update(it) }
|
||||
|
||||
hashFile.writeText(DatatypeConverter.printHexBinary(md.digest()))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<ComputeCemuDataFilesHashTask>("computeCemuDataFilesHash") {
|
||||
cemuDataFolder = cemuDataFilesFolder
|
||||
}
|
||||
tasks.preBuild.dependsOn("computeCemuDataFilesHash")
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
|
||||
@@ -14,12 +14,13 @@ Java_info_cemu_cemu_nativeinterface_NativeActiveSettings_getUserDataPath(JNIEnv*
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
Java_info_cemu_cemu_nativeinterface_NativeActiveSettings_initializeActiveSettings(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring data_path, jstring cache_path)
|
||||
Java_info_cemu_cemu_nativeinterface_NativeActiveSettings_initializeActiveSettings(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring user_data_path, jstring data_path, jstring cache_path)
|
||||
{
|
||||
std::string userDataPath = JNIUtils::toString(env, user_data_path);
|
||||
std::string dataPath = JNIUtils::toString(env, data_path);
|
||||
std::string cachePath = JNIUtils::toString(env, cache_path);
|
||||
std::set<fs::path> failedWriteAccess;
|
||||
ActiveSettings::SetPaths(false, {}, dataPath, dataPath, cachePath, dataPath, failedWriteAccess);
|
||||
ActiveSettings::SetPaths(false, {}, userDataPath, userDataPath, cachePath, dataPath, failedWriteAccess);
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] JNIEXPORT void JNICALL
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package info.cemu.cemu
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import info.cemu.cemu.nativeinterface.NativeActiveSettings.initializeActiveSettings
|
||||
import info.cemu.cemu.nativeinterface.NativeActiveSettings.setInternalDir
|
||||
import info.cemu.cemu.nativeinterface.NativeActiveSettings.setNativeLibDir
|
||||
@@ -11,8 +10,10 @@ import info.cemu.cemu.nativeinterface.NativeGraphicPacks.refreshGraphicPacks
|
||||
import info.cemu.cemu.nativeinterface.NativeLogging.crashLog
|
||||
import info.cemu.cemu.nativeinterface.NativeSwkbd.initializeSwkbd
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class CemuApplication : Application() {
|
||||
init {
|
||||
@@ -30,6 +31,78 @@ class CemuApplication : Application() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
configureExceptionHandler()
|
||||
initializeCemu()
|
||||
saveDataFiles()
|
||||
}
|
||||
|
||||
private fun saveDataFiles() {
|
||||
val dataFolder = File(internalCemuDataFolder)
|
||||
|
||||
if (!dataFolder.exists() && !dataFolder.mkdirs()) {
|
||||
return
|
||||
}
|
||||
|
||||
val hashFileName = "hash.txt"
|
||||
val hashFile = dataFolder.resolve(hashFileName)
|
||||
val oldHash = if (hashFile.isFile) hashFile.readText() else "invalid"
|
||||
|
||||
val assetsFileStream = try {
|
||||
assets.open(hashFileName)
|
||||
} catch (_: IOException) {
|
||||
null
|
||||
}
|
||||
|
||||
if (assetsFileStream == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val newHash = assetsFileStream.reader().readText()
|
||||
|
||||
if (oldHash == newHash) {
|
||||
return
|
||||
}
|
||||
|
||||
dataFolder.deleteRecursively()
|
||||
dataFolder.mkdirs()
|
||||
dataFolder.resolve(hashFileName).writeText(newHash)
|
||||
|
||||
fun traverseAssets(path: String = ""): Iterator<String> = iterator {
|
||||
val assetFiles = assets.list(path) ?: return@iterator
|
||||
|
||||
if (assetFiles.isEmpty()) {
|
||||
yield(path)
|
||||
}
|
||||
|
||||
for (assetFile in assetFiles) {
|
||||
val assetPath = path + (if (path == "") "" else "/") + assetFile
|
||||
for (file in traverseAssets(assetPath)) {
|
||||
yield(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val filePatterns = arrayOf(
|
||||
Pattern.compile("gameProfiles/.*"),
|
||||
Pattern.compile("resources/.*"),
|
||||
)
|
||||
|
||||
fun isFileValid(file: String): Boolean {
|
||||
return filePatterns.any { pattern -> pattern.matcher(file).matches() }
|
||||
}
|
||||
|
||||
for (assetFile in traverseAssets()) {
|
||||
if (!isFileValid(assetFile)) {
|
||||
continue
|
||||
}
|
||||
|
||||
val outFile = dataFolder.resolve(assetFile)
|
||||
outFile.parentFile?.mkdirs()
|
||||
assets.open(assetFile).copyTo(outFile.outputStream())
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureExceptionHandler() {
|
||||
if (DefaultUncaughtExceptionHandler == null) {
|
||||
DefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
|
||||
}
|
||||
@@ -44,9 +117,16 @@ class CemuApplication : Application() {
|
||||
exception
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeCemu() {
|
||||
val displayMetrics = resources.displayMetrics
|
||||
setDPI(displayMetrics.density)
|
||||
initializeActiveSettings(internalFolder.toString(), internalFolder.toString())
|
||||
initializeActiveSettings(
|
||||
userDataPath = internalCemuUserFolder,
|
||||
dataPath = internalCemuDataFolder,
|
||||
cachePath = internalCemuUserFolder,
|
||||
)
|
||||
setNativeLibDir(applicationInfo.nativeLibraryDir)
|
||||
setInternalDir(dataDir.absolutePath)
|
||||
initializeEmulation()
|
||||
@@ -54,6 +134,12 @@ class CemuApplication : Application() {
|
||||
refreshGraphicPacks()
|
||||
}
|
||||
|
||||
private val internalCemuDataFolder: String
|
||||
get() = internalFolder.resolve("data").toString()
|
||||
|
||||
private val internalCemuUserFolder: String
|
||||
get() = internalFolder.toString()
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("CemuAndroid")
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package info.cemu.cemu.nativeinterface
|
||||
|
||||
object NativeActiveSettings {
|
||||
@JvmStatic
|
||||
external fun initializeActiveSettings(dataPath: String, cachePath: String)
|
||||
external fun initializeActiveSettings(userDataPath: String, dataPath: String, cachePath: String)
|
||||
|
||||
@JvmStatic
|
||||
external fun setNativeLibDir(nativeLibDir: String)
|
||||
|
||||
Reference in New Issue
Block a user