From 947ba44245fa36144f8074fc324e43b18f661a0f Mon Sep 17 00:00:00 2001 From: megboyzz Date: Sun, 15 Dec 2024 21:21:44 +0300 Subject: [PATCH] comeback commit! --- app/build.gradle.kts | 1 + .../java/com/ea/ironmonkey/GameActivity.kt | 2 + app/src/main/jniLibs/armeabi-v7a/libapp.so | Bin 14477132 -> 14477132 bytes .../devmenu/domain/entities/GameLang.kt | 2 +- .../usecases/settings/GetGameLangUseCase.kt | 14 ++ .../settings/GetTrackingStateUseCase.kt | 13 ++ .../java/com/megboyzz/devmenu/MainActivity.kt | 5 +- .../di/components/SettingsUseCaseComponent.kt | 6 + .../repositories/SettingsRepositoryImpl.kt | 4 +- .../repositories/TrackingRepositoryImpl.kt | 2 +- .../java/com/megboyzz/devmenu/ui/Utlil.kt | 40 +++- .../megboyzz/devmenu/ui/components/Files.kt | 8 +- .../devmenu/ui/components/FolderStatusBar.kt | 15 +- .../devmenu/ui/components/HomeScaffold.kt | 17 +- .../devmenu/ui/models/GameLangModel.kt | 8 +- .../ui/screenmodels/HomeScreenModel.kt | 125 +++++++++++ .../ui/screenmodels/SettingsScreenModel.kt | 62 ++++++ .../ui/screens/FileContextMenuScreen.kt | 4 +- .../megboyzz/devmenu/ui/screens/HomeScreen.kt | 96 +++++++-- .../devmenu/ui/screens/SettingsScreen.kt | 32 ++- mpcore/build.gradle.kts | 6 +- mpcore/src/main/cpp/CMakeLists.txt | 4 +- mpcore/src/main/cpp/main.cpp | 73 +++++++ mpcore/src/main/cpp/main.h | 6 + mpcore/src/main/cpp/mpcore.cpp | 10 - mpcore/src/main/cpp/util/armhook.cpp | 198 ++++++++++++++++++ mpcore/src/main/cpp/util/armhook.h | 35 ++++ mpcore/src/main/cpp/util/util.cpp | 52 +++++ mpcore/src/main/cpp/util/util.h | 5 + .../main/java/ru/megboyzz/mpcore/NativeLib.kt | 5 +- 30 files changed, 793 insertions(+), 57 deletions(-) create mode 100644 devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetGameLangUseCase.kt create mode 100644 devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetTrackingStateUseCase.kt create mode 100644 devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/HomeScreenModel.kt create mode 100644 devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/SettingsScreenModel.kt create mode 100644 mpcore/src/main/cpp/main.cpp create mode 100644 mpcore/src/main/cpp/main.h delete mode 100644 mpcore/src/main/cpp/mpcore.cpp create mode 100644 mpcore/src/main/cpp/util/armhook.cpp create mode 100644 mpcore/src/main/cpp/util/armhook.h create mode 100644 mpcore/src/main/cpp/util/util.cpp create mode 100644 mpcore/src/main/cpp/util/util.h diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5ab6347..f59bde2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -96,6 +96,7 @@ dependencies { implementation(libs.ui.graphics) implementation(libs.ui.tooling.preview) implementation(libs.material3) + implementation(project(mapOf("path" to ":mpcore"))) testImplementation(libs.junit.v412) //testImplementation(libs.junit) androidTestImplementation(libs.androidx.test.ext.junit) diff --git a/app/src/main/java/com/ea/ironmonkey/GameActivity.kt b/app/src/main/java/com/ea/ironmonkey/GameActivity.kt index 0098c8f..940dab5 100644 --- a/app/src/main/java/com/ea/ironmonkey/GameActivity.kt +++ b/app/src/main/java/com/ea/ironmonkey/GameActivity.kt @@ -24,6 +24,7 @@ import com.ea.EAMIO.StorageDirectory import com.ea.easp.EASPHandler import com.ea.games.nfs13_na.BuildConfig import com.ea.nimble.ApplicationLifecycle +import ru.megboyzz.mpcore.NativeLib import java.io.BufferedReader import java.io.File import java.io.FileReader @@ -42,6 +43,7 @@ class GameActivity : ComponentActivity(), DrawFrameListener { init { System.loadLibrary("nimble") System.loadLibrary("app") + System.loadLibrary("mpcore") } private var splashDelay: Long = 0 diff --git a/app/src/main/jniLibs/armeabi-v7a/libapp.so b/app/src/main/jniLibs/armeabi-v7a/libapp.so index d674c641e64f4e0a941450cf40fa09533cba7706..a9fe392bf21d0ca2b39877a2c939b183bbeaf6f7 100644 GIT binary patch delta 658 zcmWN=1$ztt0Dxf|CMPCN8%~?}a>$Rs8+g{e$qIy0EbEM_x@xy)le z3s}e^7PEw>H+ze>dYiXf^KqZ>NuToRXe5xHk{F+y6pjVcea2^f&gXr>7k$Z> zeZ^OO&DVXyH=W^IzU`>*_^$8yz90CZANjGL_^C7f%+LM8Fa64|{l;(o&N07tmOuET aKl!u2_^ZG9yMOqnfBConL}S6fq0Ij>Yb~(= delta 658 zcmWN=b$bi|0KnnrhRJD8=V{ZO)7{76<6rwOiC`vJk6Ql$sDMe|@P?mC(rveqJL}fx$ zp(@p=P7P{Oi`pbohq~0GJ`HF{BO23$rZl5DEoezATGNKMB+-ucbf6=h=u8*7(v9x) zpeMcPO&|KwkNyl`AcGjp5QZ|0;f!D;qZrK?#xjoaOkg6Dn9LNWGL7lXU?#Je%^c=3 zkNGTMA&Xed5|*-z<*Z<3dU8rI5Qs#B$zJ8v4ttH)dY$olZ*asLy~&%s#aq42+r7g( zz0143$9uic`+dL%eaMG>#3_#YsE;|-$9=*leJUdwOiN6NOZ^*(h0=W5XMEP@eBKv) z(U*MLSA5mieBC#k?wh{l4Bz%0-}OD;_X9ulBR}>NXZoq1`MF>CrC<5A-}tR#e&;N| d_XmIUCx7-AfAu$i_YeQ{FaOSnh5m#y{{vrHF9QGo diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/GameLang.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/GameLang.kt index be09998..1c5aa26 100644 --- a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/GameLang.kt +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/GameLang.kt @@ -1,6 +1,6 @@ package com.megboyzz.devmenu.domain.entities -enum class GameLang(private val lang: String) { +enum class GameLang(val lang: String) { System("sys"), Chinese("cn"), Dutch("nl"), diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetGameLangUseCase.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetGameLangUseCase.kt new file mode 100644 index 0000000..99e4964 --- /dev/null +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetGameLangUseCase.kt @@ -0,0 +1,14 @@ +package com.megboyzz.devmenu.domain.usecases.settings + +import com.megboyzz.devmenu.domain.entities.GameLang +import com.megboyzz.devmenu.domain.repository.SettingsRepository +import javax.inject.Inject + +class GetGameLangUseCase @Inject constructor( + private val settingsRepository: SettingsRepository +) { + + operator fun invoke() = settingsRepository.gameLang + +} + diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetTrackingStateUseCase.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetTrackingStateUseCase.kt new file mode 100644 index 0000000..b987811 --- /dev/null +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/GetTrackingStateUseCase.kt @@ -0,0 +1,13 @@ +package com.megboyzz.devmenu.domain.usecases.settings + +import com.megboyzz.devmenu.domain.entities.TrackingData +import com.megboyzz.devmenu.domain.repository.TrackingRepository +import javax.inject.Inject + +class GetTrackingStateUseCase @Inject constructor( + private val trackingRepository: TrackingRepository +) { + + operator fun invoke() = trackingRepository.trackingData + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt b/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt index f862884..c613ed1 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.ui.unit.dp import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator +import cafe.adriel.voyager.transitions.SlideTransition import com.megboyzz.devmenu.ui.components.MainScaffold import com.megboyzz.devmenu.ui.screens.HomeScreen @@ -39,7 +40,9 @@ class MainActivity : ComponentActivity() { BottomSheetNavigator( sheetShape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp) ) { - Navigator(HomeScreen(::runGame)) + Navigator(HomeScreen(::runGame)) { + SlideTransition(it) + } } } } diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/SettingsUseCaseComponent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/SettingsUseCaseComponent.kt index fb090ed..6a025d1 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/SettingsUseCaseComponent.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/SettingsUseCaseComponent.kt @@ -3,6 +3,8 @@ package com.megboyzz.devmenu.di.components import android.content.Context import com.megboyzz.devmenu.di.modules.DatabaseModule import com.megboyzz.devmenu.di.modules.RepositoryModule +import com.megboyzz.devmenu.domain.usecases.settings.GetGameLangUseCase +import com.megboyzz.devmenu.domain.usecases.settings.GetTrackingStateUseCase import com.megboyzz.devmenu.domain.usecases.settings.RemoveGameDataUseCase import com.megboyzz.devmenu.domain.usecases.settings.SetGameLangUseCase import com.megboyzz.devmenu.domain.usecases.settings.SetTrackingSaveFileUseCase @@ -24,8 +26,12 @@ interface SettingsUseCaseComponent { val setGameLangUseCase: SetGameLangUseCase + val getGameLangUseCase: GetGameLangUseCase + val setTrackingSaveFileUseCase: SetTrackingSaveFileUseCase + val getTrackingStateUseCase: GetTrackingStateUseCase + val turnOffDevMenuUseCase: TurnOffDevMenuUseCase @Component.Builder diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SettingsRepositoryImpl.kt b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SettingsRepositoryImpl.kt index b9ef077..6406554 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SettingsRepositoryImpl.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SettingsRepositoryImpl.kt @@ -29,7 +29,7 @@ class SettingsRepositoryImpl @Inject constructor( if(!localeFile.exists()){ localeFile.createNewFile() - localeFile.writeBytes(byteArrayOf(0x02, 0x0) + systemLang.name.toByteArray()) + localeFile.writeBytes(byteArrayOf(0x02, 0x0) + systemLang.lang.toByteArray()) return systemLang } @@ -40,7 +40,7 @@ class SettingsRepositoryImpl @Inject constructor( if(!localeFile.exists()) localeFile.createNewFile() - localeFile.writeBytes(byteArrayOf(0x02, 0x0) + value.name.toByteArray()) + localeFile.writeBytes(byteArrayOf(0x02, 0x0) + value.lang.toByteArray()) } diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/TrackingRepositoryImpl.kt b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/TrackingRepositoryImpl.kt index 7359006..374a1e2 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/TrackingRepositoryImpl.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/TrackingRepositoryImpl.kt @@ -29,7 +29,7 @@ class TrackingRepositoryImpl @Inject constructor( override var trackingData: TrackingData get() { val enabled = sharedPreferences.getBoolean(trackingStateKey, false) - val path = sharedPreferences.getString(trackingStateKey, defaultPathToSave)?: defaultPathToSave + val path = sharedPreferences.getString(trackingSavePath, defaultPathToSave)?: defaultPathToSave return TrackingData( enabled = enabled, diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt index 34d25d6..3ba6d3c 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt @@ -1,14 +1,19 @@ package com.megboyzz.devmenu.ui import android.annotation.SuppressLint +import android.content.Context +import androidx.activity.ComponentActivity +import androidx.activity.OnBackPressedCallback import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp +import com.megboyzz.devmenu.MainActivity import java.text.CharacterIterator import java.text.SimpleDateFormat import java.text.StringCharacterIterator @@ -46,7 +51,39 @@ fun humanReadableByteCountSI(bytes: Long): String { fun formatDate(date: Date) = SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(date) +fun Context.getInternalAppDataDirectory() = "/data/data/${packageName}" + +fun Context.getExternalAppDataDirectory(): String { + val externalDir = getExternalFilesDir(null) + return externalDir?.absolutePath ?: "" +} + +@Composable +fun Context.registerOnBackPressedAction( + action: () -> Unit +) { + val context = this + DisposableEffect(this) { + val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + + action() + } + + } + (context as ComponentActivity).onBackPressedDispatcher.addCallback(callback) + + // Отменяем обратный вызов при уничтожении DisposableEffect + onDispose { + callback.remove() + } + } + +} + /** + * ## Неработает(( + * * Возвращает лямбду того типа которая требуется в Composable контексте
* например есть функция * @@ -62,5 +99,4 @@ fun formatDate(date: Date) = SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(date * * example(a = SomeType().asComposableLambda) */ -val T.asComposableLambda: @Composable () -> T - get() = { this } \ No newline at end of file +val T.asComposableLambda: @Composable () -> T get() = { this } \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt index 051a869..f5a1019 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt @@ -6,6 +6,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.megboyzz.devmenu.ui.models.FsElementModel @@ -13,7 +14,7 @@ import com.megboyzz.devmenu.ui.models.FsElementModel fun FsElement( fsElementEntity: FsElementModel, onClick: () -> Unit, - onLongPressClick: () -> Unit + onLongPressClick: () -> Unit = {} ) { Column( @@ -25,6 +26,9 @@ fun FsElement( ) ) { FsElementIcon(type = fsElementEntity.type) - Text(text = fsElementEntity.name) + Text( + text = fsElementEntity.name, + textAlign = TextAlign.Center + ) } } \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/FolderStatusBar.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/FolderStatusBar.kt index 0fd4519..f065914 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/FolderStatusBar.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/FolderStatusBar.kt @@ -1,7 +1,6 @@ package com.megboyzz.devmenu.ui.components import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyRow @@ -39,10 +38,20 @@ fun CoreBar(folders: List) { @Composable fun StatusBarInCurFolder( - path: String + path: String, + internalPath: String = "", + externalPath: String = "" ) { if(path.isEmpty()) return - val pathAsArray = path.split("/").filter { it.isNotEmpty() } + var pathProcess = path + + if(internalPath.isNotEmpty() && pathProcess.contains(internalPath)) + pathProcess = path.replace(internalPath, "Внутренее хранилище") + + if(externalPath.isNotEmpty() && pathProcess.contains(externalPath)) + pathProcess = path.replace(externalPath, "Внешнее хранилище") + + val pathAsArray = pathProcess.split("/").filter { it.isNotEmpty() } CoreBar(folders = pathAsArray) } diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/HomeScaffold.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/HomeScaffold.kt index 3b628d3..1a6729f 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/HomeScaffold.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/HomeScaffold.kt @@ -4,6 +4,8 @@ import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -33,6 +35,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.megboyzz.devmenu.ui.SpacerHeight import com.megboyzz.devmenu.ui.theme.DevMenuTheme @OptIn(ExperimentalMaterial3Api::class) @@ -42,7 +45,7 @@ fun MainScaffold( searchValue: String, onSearchValueChanged: (String) -> Unit, onFloatingButtonClick: () -> Unit, - content: @Composable (PaddingValues) -> Unit + content: @Composable ColumnScope.() -> Unit ) { var searchValue by remember { mutableStateOf(searchValue) } @@ -66,11 +69,13 @@ fun MainScaffold( shape = CircleShape, content = {Icon(imageVector = Icons.Default.PlayArrow, contentDescription = null)} ) - }, - - content = content - - ) + } + ){ + Column { + SpacerHeight(height = it.calculateTopPadding()) + content() + } + } } diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/GameLangModel.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/GameLangModel.kt index f270738..e07a8be 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/GameLangModel.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/GameLangModel.kt @@ -1,5 +1,7 @@ package com.megboyzz.devmenu.ui.models +import com.megboyzz.devmenu.domain.entities.GameLang + enum class GameLangModel(private val lang: String) { System("sys"), Chinese("cn"), @@ -16,4 +18,8 @@ enum class GameLangModel(private val lang: String) { override fun toString() = lang -} \ No newline at end of file + fun toDomain() = GameLang.values()[ordinal] + +} + +fun GameLang.toModel() = GameLangModel.values()[ordinal] \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/HomeScreenModel.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/HomeScreenModel.kt new file mode 100644 index 0000000..33954c1 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/HomeScreenModel.kt @@ -0,0 +1,125 @@ +package com.megboyzz.devmenu.ui.screenmodels + +import android.content.Context +import android.util.Log +import cafe.adriel.voyager.core.model.ScreenModel +import cafe.adriel.voyager.core.model.screenModelScope +import com.megboyzz.devmenu.ui.components.ElementType +import com.megboyzz.devmenu.ui.getExternalAppDataDirectory +import com.megboyzz.devmenu.ui.getInternalAppDataDirectory +import com.megboyzz.devmenu.ui.models.FsElementModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import java.io.File +import java.util.Date + +class HomeScreenModel( + private val context: Context +): ScreenModel { + + private val TAG = this::class.simpleName + + private val internalRef = FsElementModel( + "Внутренне хранилище", + ElementType.isDir, + 0, + Date() + ) + + private val externalRef = FsElementModel( + "Внешнее хранилище", + ElementType.isDir, + 0, + Date() + ) + + private val rootFs = listOf( + internalRef, + externalRef + ) + + val currentFolder = MutableStateFlow("") + + val folderFiles = MutableStateFlow(listOf(internalRef, externalRef)) + + + private fun isRoot() = currentFolder.value.isEmpty() + + private fun getElements(path: String): List{ + val here = File(path) + return if(here.exists()){ + here.listFiles()!!.map { + FsElementModel( + name = it.name, + type = if(it.isFile) ElementType.isFile else ElementType.isDir, + size = it.length(), + date = Date(it.lastModified()) + ) + } + }else listOf() + } + + fun enterRoot(){ + screenModelScope.launch(Dispatchers.IO) { + currentFolder.emit("") + folderFiles.emit(rootFs) + } + } + + fun enterFolder(elementModel: FsElementModel) { + if(isRoot()){ + when(elementModel){ + externalRef -> enterTheExternal() + internalRef -> enterTheInternal() + else -> Log.e(TAG, "enterFolder: error path! ${elementModel.name}") + } + }else{ + screenModelScope.launch(Dispatchers.IO) { + currentFolder.emit(currentFolder.value + "/" + elementModel.name) + folderFiles.emit(getElements(currentFolder.value)) + } + } + } + + fun backFolder(){ + + val path = File(currentFolder.value) + + val internal = context.getInternalAppDataDirectory() + val external = context.getExternalAppDataDirectory() + + if(path.exists()){ + screenModelScope.launch(Dispatchers.IO) { + when(currentFolder.value){ + + context.getInternalAppDataDirectory(), context.getExternalAppDataDirectory() -> enterRoot() + else -> { + currentFolder.emit(path.parentFile.absolutePath) + folderFiles.emit(getElements(currentFolder.value)) + } + } + } + } + + + } + + + private fun enterTheInternal(){ + screenModelScope.launch(Dispatchers.IO) { + currentFolder.emit(context.getInternalAppDataDirectory()) + folderFiles.emit(getElements(currentFolder.value)) + } + } + + private fun enterTheExternal(){ + screenModelScope.launch(Dispatchers.IO) { + currentFolder.emit(context.getExternalAppDataDirectory()) + folderFiles.emit(getElements(currentFolder.value)) + } + } + + + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/SettingsScreenModel.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/SettingsScreenModel.kt new file mode 100644 index 0000000..a075ba8 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screenmodels/SettingsScreenModel.kt @@ -0,0 +1,62 @@ +package com.megboyzz.devmenu.ui.screenmodels + +import android.content.Context +import cafe.adriel.voyager.core.model.ScreenModel +import cafe.adriel.voyager.core.model.screenModelScope +import com.megboyzz.devmenu.App +import com.megboyzz.devmenu.MainActivity +import com.megboyzz.devmenu.ui.models.GameLangModel +import com.megboyzz.devmenu.ui.models.toModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch + +class SettingsScreenModel( + context: Context +): ScreenModel { + + private val settingsUseCaseComponent = (((context as MainActivity).application) as App).settingsUseCaseComponent + + val gameLangModel = MutableStateFlow(settingsUseCaseComponent.getGameLangUseCase().toModel()) + + val trackingIsEnabled = MutableStateFlow(false) + + init { + + screenModelScope.launch(Dispatchers.IO) { + update() + } + + } + + private suspend fun update() { + gameLangModel.emit(settingsUseCaseComponent.getGameLangUseCase().toModel()) + trackingIsEnabled.emit(settingsUseCaseComponent.getTrackingStateUseCase().enabled) + } + + fun changeLang(gameLangModel: GameLangModel){ + screenModelScope.launch(Dispatchers.IO) { + settingsUseCaseComponent.setGameLangUseCase(gameLangModel.toDomain()) + update() + } + } + + fun changeTrackingState(state: Boolean) { + screenModelScope.launch(Dispatchers.IO) { + val trackingData = settingsUseCaseComponent.getTrackingStateUseCase() + trackingData.copy(enabled = state) + settingsUseCaseComponent.setTrackingSaveFileUseCase(trackingData.enabled, trackingData.pathToSave) + update() + } + } + + fun changeTrackingPath(path: String) { + screenModelScope.launch(Dispatchers.IO) { + val state = settingsUseCaseComponent.getTrackingStateUseCase() + state.copy(pathToSave = path) + settingsUseCaseComponent.setTrackingSaveFileUseCase(state.enabled, state.pathToSave) + update() + } + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt index ef84bb6..da34929 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt @@ -2,17 +2,19 @@ package com.megboyzz.devmenu.ui.screens import androidx.compose.runtime.Composable import cafe.adriel.voyager.core.screen.Screen +import com.megboyzz.devmenu.ui.components.ElementType import com.megboyzz.devmenu.ui.components.FileContextMenu import com.megboyzz.devmenu.ui.models.FsElementModel class FileContextMenuScreen( private val fsElementModel: FsElementModel, private val onRemoveFile: () -> Unit, + private val onUpdateType: (ElementType) -> ElementType? ) : Screen { @Composable override fun Content() = FileContextMenu( fsElementEntity = fsElementModel, onRemoveElement = onRemoveFile, - onUpdateType = {null} + onUpdateType = onUpdateType ) } \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt index 25fd2c0..57924a2 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt @@ -1,61 +1,115 @@ package com.megboyzz.devmenu.ui.screens +import android.annotation.SuppressLint +import androidx.activity.OnBackPressedCallback +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.material3.Button +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.bottomSheet.LocalBottomSheetNavigator +import com.megboyzz.devmenu.MainActivity import com.megboyzz.devmenu.ui.SpacerHeight import com.megboyzz.devmenu.ui.components.ElementType import com.megboyzz.devmenu.ui.components.FsElement import com.megboyzz.devmenu.ui.components.MainScaffold +import com.megboyzz.devmenu.ui.components.StatusBarInCurFolder +import com.megboyzz.devmenu.ui.getExternalAppDataDirectory +import com.megboyzz.devmenu.ui.getInternalAppDataDirectory import com.megboyzz.devmenu.ui.models.FsElementModel +import com.megboyzz.devmenu.ui.registerOnBackPressedAction +import com.megboyzz.devmenu.ui.screenmodels.HomeScreenModel import java.util.Date class HomeScreen( private val onFloatingButtonClick: () -> Unit ): Screen { + @SuppressLint("StateFlowValueCalledInComposition") @Composable override fun Content() { + val context = LocalContext.current + val bottomSheetNavigator = LocalBottomSheetNavigator.current - var searchValue by remember{ mutableStateOf("") } + val navigator = LocalNavigator.current - val fsElementModel = FsElementModel( - name = "my_txt.txt", - type = ElementType.isHidden, - size = 123, - date = Date() - ) + var searchValue by remember { mutableStateOf("") } + val homeScreenModel = rememberScreenModel { HomeScreenModel(context) } + val fsState by homeScreenModel.folderFiles.collectAsState() + + val currentFolder by homeScreenModel.currentFolder.collectAsState() + + context.registerOnBackPressedAction { + homeScreenModel.backFolder() + } MainScaffold( - onSettingsClick = { /*TODO Переход к настройкам */ }, + onSettingsClick = { navigator?.push(SettingsScreen()) }, onSearchValueChanged = { searchValue = it }, searchValue = searchValue, onFloatingButtonClick = onFloatingButtonClick ) { - Column { - SpacerHeight(height = it.calculateTopPadding()) - FsElement( - fsElementEntity = fsElementModel, - onClick = { /*TODO*/ }, - onLongPressClick = { - bottomSheetNavigator.show( - FileContextMenuScreen( - fsElementModel = fsElementModel, - onRemoveFile = {} - ) - ) - } + + Column( + modifier = Modifier.padding(horizontal = 20.dp) + ) { + + StatusBarInCurFolder( + path = currentFolder, + externalPath = context.getExternalAppDataDirectory(), + internalPath = context.getInternalAppDataDirectory() ) } + val filteredList by remember(searchValue, fsState) { + derivedStateOf { + fsState.filter { it.name.contains(searchValue, ignoreCase = true) } + } + } + + LazyVerticalGrid( + columns = GridCells.Adaptive(80.dp), + horizontalArrangement = Arrangement.spacedBy(40.dp), + verticalArrangement = Arrangement.spacedBy(40.dp), + contentPadding = PaddingValues(20.dp) + ){ + + items(filteredList){ + FsElement( + fsElementEntity = it, + onClick = { homeScreenModel.enterFolder(it) }, + onLongPressClick = { + bottomSheetNavigator.show(FileContextMenuScreen( + fsElementModel = it, + onRemoveFile = {}, + onUpdateType = {null} + )) + } + ) + } + } + } } diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/SettingsScreen.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/SettingsScreen.kt index 1f0da10..e930b38 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/SettingsScreen.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/SettingsScreen.kt @@ -1,11 +1,41 @@ package com.megboyzz.devmenu.ui.screens import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalContext +import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import com.megboyzz.devmenu.ui.components.SettingsScreenContent +import com.megboyzz.devmenu.ui.models.GameLangModel +import com.megboyzz.devmenu.ui.screenmodels.SettingsScreenModel class SettingsScreen : Screen { @Composable override fun Content() { - TODO("Not yet implemented") + + val navigator = LocalNavigator.current + + val context = LocalContext.current + + val settingsScreenModel = rememberScreenModel { SettingsScreenModel(context) } + + val curLang by settingsScreenModel.gameLangModel.collectAsState() + + val trackingEnabled by settingsScreenModel.trackingIsEnabled.collectAsState() + + SettingsScreenContent( + onBackClick = { navigator?.pop() }, + langModel = curLang, + onUpdateLanguage = { settingsScreenModel.changeLang(it) }, + isTrackingSaveFile = trackingEnabled, + onUpdateTrackingSaveFileState = { settingsScreenModel.changeTrackingState(it) }, + onChooseTrackingPathToSave = { }, + onUploadSaveFile = { /*TODO*/ }, + onDownloadSaveFile = { /*TODO*/ }, + onDevMenuOff = { + + }) } } \ No newline at end of file diff --git a/mpcore/build.gradle.kts b/mpcore/build.gradle.kts index 2146e56..bcb033c 100644 --- a/mpcore/build.gradle.kts +++ b/mpcore/build.gradle.kts @@ -6,11 +6,15 @@ plugins { android { namespace = "ru.megboyzz.mpcore" - compileSdk = 33 + compileSdk = 34 defaultConfig { minSdk = 21 + ndk { + abiFilters.add("armeabi-v7a") + } + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") externalNativeBuild { diff --git a/mpcore/src/main/cpp/CMakeLists.txt b/mpcore/src/main/cpp/CMakeLists.txt index f125423..a710fa2 100644 --- a/mpcore/src/main/cpp/CMakeLists.txt +++ b/mpcore/src/main/cpp/CMakeLists.txt @@ -3,7 +3,9 @@ cmake_minimum_required(VERSION 3.22.1) project("mpcore") add_library(${CMAKE_PROJECT_NAME} SHARED - mpcore.cpp) + main.cpp + util/util.cpp + util/armhook.cpp) target_link_libraries(${CMAKE_PROJECT_NAME} android diff --git a/mpcore/src/main/cpp/main.cpp b/mpcore/src/main/cpp/main.cpp new file mode 100644 index 0000000..d581ada --- /dev/null +++ b/mpcore/src/main/cpp/main.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include "main.h" +#include "util/util.h" + +#include "util/armhook.h" + +uintptr_t libapp = 0; + +int (*print_internal_log)(int a1, const char *a2, ...); + +void pending_thread(){ + + Log("Hello from thread!"); + std::this_thread::sleep_for(std::chrono::milliseconds(10000)); + + + int unk = APP_ADDR(0x00E4B8EC); + print_internal_log(unk, "Hello!"); + + unProtect(APP_ADDR(0x00E4A738)); + + +} + + +jint JNI_OnLoad(JavaVM *vm, void *reserved){ + + libapp = FindLibrary("libapp.so"); + Log("Hello! my base addr is 0x%08x", libapp); + + //InitHookStuff(); + + //unProtect(APP_ADDR(0x00A522C4)); + //*(int *)APP_ADDR(0x00A522C4) = 0xE320F000; + + //WriteMemory(APP_ADDR(0x00E4BA94), (uintptr_t)"my_tag", 6); + raise(SIGSTOP); + + return JNI_VERSION_1_6; +} + +/* + +Log("Hello! my base addr is 0x%08x", libapp); + Log("Address i wanna to get 0x%08x", APP_ADDR(0xC8C9D8)); + + const char* str = (char *)APP_ADDR(0xC8C9D8); + + Log("i found it! %s", str); + + unProtect(APP_ADDR(0xC8C9D8)); + + WriteMemory(APP_ADDR(0xC8C9D8), (uintptr_t)"APPLICATION_NO", 14); + + str = (char *)APP_ADDR(0xC8C9D8); + + Log("i change it! %s", str); + + //makeNOP(APP_ADDR(0x00652EB4), 2); + //makeNOP(APP_ADDR(0x00652E3C), 2); + + unProtect(APP_ADDR(0x00652EB4)); + *(char *)APP_ADDR(0x00652EB4) = 0xE320F000; + + unProtect(APP_ADDR(0x00652E3C)); + *(char *)APP_ADDR(0x00652E3C) = 0xE320F000; + + */ diff --git a/mpcore/src/main/cpp/main.h b/mpcore/src/main/cpp/main.h new file mode 100644 index 0000000..f5ac598 --- /dev/null +++ b/mpcore/src/main/cpp/main.h @@ -0,0 +1,6 @@ + +//Основная ссылка на начало основного процесса - libapp.so +extern uintptr_t libapp; + +//Макрос для ссылок внутри памяти процесса +#define APP_ADDR(addr) (libapp + (addr)) diff --git a/mpcore/src/main/cpp/mpcore.cpp b/mpcore/src/main/cpp/mpcore.cpp deleted file mode 100644 index be67627..0000000 --- a/mpcore/src/main/cpp/mpcore.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -extern "C" JNIEXPORT jstring JNICALL -Java_ru_megboyzz_mpcore_NativeLib_stringFromJNI( - JNIEnv* env, - jobject /* this */) { - std::string hello = "Hello from C++"; - return env->NewStringUTF(hello.c_str()); -} \ No newline at end of file diff --git a/mpcore/src/main/cpp/util/armhook.cpp b/mpcore/src/main/cpp/util/armhook.cpp new file mode 100644 index 0000000..9477908 --- /dev/null +++ b/mpcore/src/main/cpp/util/armhook.cpp @@ -0,0 +1,198 @@ +#include // system api +#include // assert() +#include // dlopen +#include +#include +#include +#include "armhook.h" +#include "util.h" +#include "../main.h" + +uintptr_t mmap_start = 0; +uintptr_t mmap_end = 0; +uintptr_t memlib_start = 0; +uintptr_t memlib_end = 0; + +//#define PAGE_SIZE 0x8124 + +#define HOOK_PROC "\x01\xB4\x01\xB4\x01\x48\x01\x90\x01\xBD\x00\xBF\x00\x00\x00\x00" + + +void unProtect(uintptr_t ptr, size_t dwSize) +{ + if(mprotect(reinterpret_cast(ptr & 0xFFFFF000), PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC) == -1) + { + const auto err = errno; + + if(err == EACCES) + { + mprotect(reinterpret_cast(ptr & 0xFFFFF000), PAGE_SIZE, PROT_WRITE | PROT_READ); + return; + } + } +} + + +void makeNOP(uintptr_t addr, unsigned int count) +{ + Log("Hello from makeNOP!"); + unProtect(addr); + + for(uintptr_t ptr = addr; ptr != (addr+(count * 2)); ptr += 2) + { + Log("Hello from loop makeNOP!"); + *(char*)ptr = 0x00; + *(char*)(ptr+1) = 0x46; + } + + cacheflush(addr, (uintptr_t)(addr + count * 2), 0); +} + +void WriteMemory(uintptr_t dest, uintptr_t src, size_t size) +{ + unProtect(dest); + memcpy((void*)dest, (void*)src, size); + cacheflush(dest, dest+size, 0); +} +void WriteMemory(uintptr_t dest, void* src, size_t size) +{ + unProtect(dest); + memcpy((void*)dest, src, size); + cacheflush(dest, dest+size, 0); +} +void SetPointer(uintptr_t addr, void* value) +{ + WriteMemory(addr, &value, sizeof(value)); +} +void ReadMemory(uintptr_t dest, uintptr_t src, size_t size) +{ + unProtect(src); + memcpy((void*)dest, (void*)src, size); +} + + +void InitHookStuff() +{ + memlib_start = APP_ADDR(0x000A1B44); + memlib_end = memlib_start + 0x1A36; + + mmap_start = (uintptr_t)mmap(0, PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + int code = mprotect((void*)(mmap_start & 0xFFFFF000), PAGE_SIZE, PROT_READ | PROT_EXEC | PROT_WRITE); + mmap_end = (mmap_start + PAGE_SIZE); + + /*const auto err = errno; + + Log("Status is %d && %d", err, code); + + Log("mmap_stat = 0x%08x", mmap_start); + Log("mmap_end = 0x%08x", mmap_end); + + Log("memlib_start = 0x%08x", memlib_start); + Log("memlib_end = 0x%08x", memlib_end);*/ + + //unProtect(APP_ADDR(0x1800AC)); + +} + +void makeJMP(uintptr_t func, uintptr_t addr) +{ + uint32_t code = ((addr - func - 4) >> 12) & 0x7FF | 0xF000 | ((((addr - func - 4) >> 1) & 0x7FF | 0xB800) << 16); + WriteMemory(func, (uintptr_t)&code, 4); +} + +void makeBLX(uintptr_t func, uintptr_t addr) +{ + uint32_t code = ((addr - func - 4) >> 12) & 0x7FF | ((addr - func - 4) << 15) | 0xF800F000; + WriteMemory(func, (uintptr_t)&code, 4); +} + +void WriteHookProc(uintptr_t addr, uintptr_t func) +{ + char code[16]; + + memcpy(code, HOOK_PROC, 16); + *(uint32_t*)&code[12] = (func | 1); + + WriteMemory(addr, (uintptr_t)code, 16); +} + +void InstallBLXHook(uintptr_t addr, uintptr_t func) +{ + // memlib_start = 0 + // memlib_end = 10 + + if(memlib_end < (memlib_start + 0x10) || mmap_end < (mmap_start + 0x20)) + { + std::terminate(); + } + + makeBLX(addr, func); + WriteHookProc(addr, func); + + memlib_start += 16; +} + +void InstallJMPHook(uintptr_t addr, uintptr_t func) +{ + + if(memlib_end < (memlib_start + 0x10) || mmap_end < (mmap_start + 0x20)) + { + std::terminate(); + } + + makeJMP(addr, func); + WriteHookProc(addr, func); + + memlib_start += 16; +} + +void InstallHook(uintptr_t addr, uintptr_t func, uintptr_t *orig) +{ + + if(memlib_end < (memlib_start + 0x10) || mmap_end < (mmap_start + 0x20)) + { + Log("FAILED!"); + std::terminate(); + } + + ReadMemory(mmap_start, addr, 4); + WriteHookProc(mmap_start+4, addr+4); + *orig = mmap_start+1; + mmap_start += 32; + + makeJMP(addr, memlib_start); + WriteHookProc(memlib_start, func); + memlib_start += 16; +} + +void RedirectCall(uintptr_t addr, uintptr_t func) +{ + makeJMP(addr, memlib_start); + WriteHookProc(memlib_start, func); + memlib_start += 16; +} + +void InstallMethodHook(uintptr_t addr, uintptr_t func) +{ + unProtect(addr); + *(uintptr_t*)addr = func; +} + +void CodeInject(uintptr_t addr, uintptr_t func, int reg) +{ + + char injectCode[12]; + + injectCode[0] = 0x01; + injectCode[1] = 0xA0 + reg; + injectCode[2] = (0x08 * reg) + reg; + injectCode[3] = 0x68; + injectCode[4] = 0x87 + (0x08 * reg); + injectCode[5] = 0x46; + injectCode[6] = injectCode[4]; + injectCode[7] = injectCode[5]; + + *(uintptr_t*)&injectCode[8] = func; + + WriteMemory(addr, (uintptr_t)injectCode, 12); +} \ No newline at end of file diff --git a/mpcore/src/main/cpp/util/armhook.h b/mpcore/src/main/cpp/util/armhook.h new file mode 100644 index 0000000..f32db9c --- /dev/null +++ b/mpcore/src/main/cpp/util/armhook.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +extern uintptr_t mmap_start; +extern uintptr_t mmap_end; +extern uintptr_t memlib_start; +extern uintptr_t memlib_end; + +void unProtect(uintptr_t ptr, size_t dwSize = 100); + +void WriteMemory(uintptr_t dest, uintptr_t src, size_t size); +void ReadMemory(uintptr_t dest, uintptr_t src, size_t size); + +void makeNOP(uintptr_t addr, unsigned int count); +void makeJMP(uintptr_t func, uintptr_t addr); +void makeBLX(uintptr_t func, uintptr_t addr); + +void InitHookStuff(); + +void InstallHook(uintptr_t addr, uintptr_t func, uintptr_t *orig); +void InstallMethodHook(uintptr_t addr, uintptr_t func); +void InstallJMPHook(uintptr_t addr, uintptr_t func); +void InstallBLXHook(uintptr_t addr, uintptr_t func); + +void CodeInject(uintptr_t addr, uintptr_t func, int reg); + +void WriteMemory(uintptr_t dest, void* src, size_t size); +void SetPointer(uintptr_t addr, void* value); + +template +static Ret CallFunction(unsigned int address, Args... args) +{ + return reinterpret_cast(address)(args...); +} \ No newline at end of file diff --git a/mpcore/src/main/cpp/util/util.cpp b/mpcore/src/main/cpp/util/util.cpp new file mode 100644 index 0000000..b805cc9 --- /dev/null +++ b/mpcore/src/main/cpp/util/util.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include "util.h" + +uintptr_t FindLibrary(const char *lib_name) { + char filename[0xFF] = {0}, + buffer[2048] = {0}; + FILE *fp = 0; + uintptr_t address = 0; + + sprintf(filename, "/proc/%d/maps", getpid()); + + fp = fopen(filename, "rt"); + if (fp == nullptr) { + Log("ERROR: can't open file %s", filename); + goto done; + } + + + while (fgets(buffer, sizeof(buffer), fp)) { + if (strstr(buffer, lib_name)) { + address = (uintptr_t) strtoul(buffer, 0, 16); + break; + } + } + done: + + if (fp) + fclose(fp); + + return address; +} + +void Log(const char *fmt, ...) { + char buffer[0xFF]; + static FILE *flLog = nullptr; + + memset(buffer, 0, sizeof(buffer)); + + va_list arg; + va_start(arg, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, arg); + va_end(arg); + + __android_log_write(ANDROID_LOG_INFO, "mpcore_log", buffer); + + if (flLog == nullptr) return; + fprintf(flLog, "%s\n", buffer); + fflush(flLog); +} \ No newline at end of file diff --git a/mpcore/src/main/cpp/util/util.h b/mpcore/src/main/cpp/util/util.h new file mode 100644 index 0000000..899b21c --- /dev/null +++ b/mpcore/src/main/cpp/util/util.h @@ -0,0 +1,5 @@ +#pragma once + +uintptr_t FindLibrary(const char* lib_name); + +void Log(const char *fmt, ...); \ No newline at end of file diff --git a/mpcore/src/main/java/ru/megboyzz/mpcore/NativeLib.kt b/mpcore/src/main/java/ru/megboyzz/mpcore/NativeLib.kt index 9afb60d..8e3991e 100644 --- a/mpcore/src/main/java/ru/megboyzz/mpcore/NativeLib.kt +++ b/mpcore/src/main/java/ru/megboyzz/mpcore/NativeLib.kt @@ -2,11 +2,10 @@ package ru.megboyzz.mpcore class NativeLib { - external fun stringFromJNI(): String - companion object { init { - System.loadLibrary("mpcore") + //System.loadLibrary("mpcore") } } + } \ No newline at end of file