diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b0410fd1..732ec793e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -389,7 +389,6 @@ if(ENABLE_VULKAN) endif() if(ANDROID) - set(HEADER_FILES ${HEADER_FILES} include/jni_driver.hpp) set(ALL_SOURCES ${ALL_SOURCES} src/jni_driver.cpp) endif() diff --git a/include/emulator.hpp b/include/emulator.hpp index fcf933290..f45374253 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "PICA/gpu.hpp" #include "cheats.hpp" @@ -127,4 +128,6 @@ class Emulator { std::filesystem::path getConfigPath(); std::filesystem::path getAndroidAppPath(); + + std::span getSMDH(); }; diff --git a/include/jni_driver.hpp b/include/jni_driver.hpp deleted file mode 100644 index 94408db41..000000000 --- a/include/jni_driver.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#include "helpers.hpp" - -class Pandroid { - public: - static void onSmdhLoaded(const std::vector& smdh); -}; diff --git a/include/loader/ncch.hpp b/include/loader/ncch.hpp index 5e2ad1d85..c5ef24656 100644 --- a/include/loader/ncch.hpp +++ b/include/loader/ncch.hpp @@ -65,6 +65,7 @@ struct NCCH { std::vector saveData; // The cart region. Only the CXI's region matters to us. Necessary to get past region locking std::optional region = std::nullopt; + std::vector smdh; // Returns true on success, false on failure // Partition index/offset/size must have been set before this diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index a4dd6e546..1f534fa05 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -6,10 +6,6 @@ #include "loader/ncch.hpp" #include "memory.hpp" -#ifdef __ANDROID__ -#include "jni_driver.hpp" -#endif - #include bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSInfo &info) { @@ -30,6 +26,7 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn codeFile.clear(); saveData.clear(); + smdh.clear(); partitionInfo = info; size = u64(*(u32*)&header[0x104]) * mediaUnit; // TODO: Maybe don't type pun because big endian will break @@ -223,11 +220,10 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn } } else if (std::strcmp(name, "icon") == 0) { // Parse icon file to extract region info and more in the future (logo, etc) - std::vector tmp; - tmp.resize(fileSize); - readFromFile(file, exeFS, tmp.data(), fileOffset + exeFSHeaderSize, fileSize); + smdh.resize(fileSize); + readFromFile(file, exeFS, smdh.data(), fileOffset + exeFSHeaderSize, fileSize); - if (!parseSMDH(tmp)) { + if (!parseSMDH(smdh)) { printf("Failed to parse SMDH!\n"); } } @@ -259,11 +255,6 @@ bool NCCH::parseSMDH(const std::vector& smdh) { return false; } - // In the Android version, notify the application that we're loading an SMDH file, to extract data for the title list -#ifdef __ANDROID__ - Pandroid::onSmdhLoaded(smdh); -#endif - // Bitmask showing which regions are allowed. // https://www.3dbrew.org/wiki/SMDH#Region_Lockout const u32 regionMasks = *(u32*)&smdh[0x2018]; diff --git a/src/emulator.cpp b/src/emulator.cpp index 656aaebdb..e94170a28 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -252,6 +252,17 @@ bool Emulator::loadELF(std::ifstream& file) { return true; } +std::span Emulator::getSMDH() { + switch (romType) { + case ROMType::NCSD: + case ROMType::CXI: + return memory.getCXI()->smdh; + default: { + return std::span(); + } + } +} + #ifdef PANDA3DS_ENABLE_DISCORD_RPC void Emulator::updateDiscord() { if (config.discordRpcEnabled) { diff --git a/src/jni_driver.cpp b/src/jni_driver.cpp index c38359b42..cbc5a16e4 100644 --- a/src/jni_driver.cpp +++ b/src/jni_driver.cpp @@ -1,5 +1,3 @@ -#include "jni_driver.hpp" - #include #include #include @@ -15,7 +13,6 @@ HIDService* hidService = nullptr; RendererGL* renderer = nullptr; bool romLoaded = false; JavaVM* jvm = nullptr; -const char* alberClass = "com/panda3ds/pandroid/AlberDriver"; #define AlberFunction(type, name) JNIEXPORT type JNICALL Java_com_panda3ds_pandroid_AlberDriver_##name @@ -36,20 +33,6 @@ JNIEnv* jniEnv() { return env; } -void Pandroid::onSmdhLoaded(const std::vector& smdh) { - JNIEnv* env = jniEnv(); - int size = smdh.size(); - - jbyteArray result = env->NewByteArray(size); - env->SetByteArrayRegion(result, 0, size, (jbyte*)smdh.data()); - - auto classLoader = env->FindClass(alberClass); - auto method = env->GetStaticMethodID(classLoader, "OnSmdhLoaded", "([B)V"); - - env->CallStaticVoidMethod(classLoader, method, result); - env->DeleteLocalRef(result); -} - extern "C" { AlberFunction(void, Setup)(JNIEnv* env, jobject obj) { env->GetJavaVM(&jvm); } @@ -104,6 +87,15 @@ AlberFunction(void, SetCirclepadAxis)(JNIEnv* env, jobject obj, jint x, jint y) hidService->setCirclepadX((s16)x); hidService->setCirclepadY((s16)y); } + +AlberFunction(jbyteArray, GetSmdh)(JNIEnv* env, jobject obj) { + std::span smdh = emulator->getSMDH(); + + jbyteArray result = env->NewByteArray(smdh.size()); + env->SetByteArrayRegion(result, 0, smdh.size(), (jbyte*)smdh.data()); + + return result; +} } #undef AlberFunction diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java index 2a496693a..33438bb04 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java @@ -2,11 +2,6 @@ import android.util.Log; -import com.panda3ds.pandroid.data.SMDH; -import com.panda3ds.pandroid.data.game.GameMetadata; -import com.panda3ds.pandroid.utils.Constants; -import com.panda3ds.pandroid.utils.GameUtils; - public class AlberDriver { AlberDriver() { super(); } @@ -23,14 +18,7 @@ public class AlberDriver { public static native void TouchScreenUp(); public static native void TouchScreenDown(int x, int y); - public static void OnSmdhLoaded(byte[] buffer) { - SMDH smdh = new SMDH(buffer); - Log.i(Constants.LOG_TAG, "Loaded rom SDMH"); - Log.i(Constants.LOG_TAG, String.format("Are you playing '%s' published by '%s'", smdh.getTitle(), smdh.getPublisher())); - GameMetadata game = GameUtils.getCurrentGame(); - GameUtils.removeGame(game); - GameUtils.addGame(GameMetadata.applySMDH(game, smdh)); - } + public static native byte[] GetSmdh(); static { System.loadLibrary("Alber"); } } \ No newline at end of file diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java index 8dd350ced..52e609a33 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/PandaGlRenderer.java @@ -8,9 +8,12 @@ import android.util.Log; import com.panda3ds.pandroid.AlberDriver; import com.panda3ds.pandroid.utils.Constants; +import com.panda3ds.pandroid.utils.GameUtils; import com.panda3ds.pandroid.view.renderer.ConsoleRenderer; import com.panda3ds.pandroid.view.renderer.layout.ConsoleLayout; import com.panda3ds.pandroid.view.renderer.layout.DefaultScreenLayout; +import com.panda3ds.pandroid.data.SMDH; +import com.panda3ds.pandroid.data.game.GameMetadata; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; @@ -76,6 +79,19 @@ public void onSurfaceCreated(GL10 unused, EGLConfig config) { AlberDriver.Initialize(); AlberDriver.LoadRom(romPath); + + // Load the SMDH + byte[] smdhData = AlberDriver.GetSmdh(); + if (smdhData.length == 0) { + Log.w(Constants.LOG_TAG, "Failed to load SMDH"); + } else { + SMDH smdh = new SMDH(smdhData); + Log.i(Constants.LOG_TAG, "Loaded rom SDMH"); + Log.i(Constants.LOG_TAG, String.format("Are you playing '%s' published by '%s'", smdh.getTitle(), smdh.getPublisher())); + GameMetadata game = GameUtils.getCurrentGame(); + GameUtils.removeGame(game); + GameUtils.addGame(GameMetadata.applySMDH(game, smdh)); + } } public void onDrawFrame(GL10 unused) {