int libbdplus_init(BD_BDPLUS *p, const char *root, void *file_open_handle, void *file_open_fp, const uint8_t *vid, const uint8_t *mk) { fptr_p_void bdplus_init; fptr_void set_fopen; _libbdplus_close(p); *(void **)(&bdplus_init) = dl_dlsym(p->h_libbdplus, "bdplus_init"); *(void **)(&set_fopen) = dl_dlsym(p->h_libbdplus, "bdplus_set_fopen"); if (!bdplus_init) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "libbdplus dlsym(bdplus_init) failed! (%p)\n", p->h_libbdplus); return -1; } if (set_fopen) { p->bdplus = bdplus_init(NULL, NULL, vid); set_fopen(p->bdplus, file_open_handle, file_open_fp); } else { p->bdplus = bdplus_init(root, NULL, vid); } if (!p->bdplus) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bdplus_init() failed! (%p)\n", p->h_libbdplus); return -1; } DL_CALL(p->h_libbdplus, bdplus_set_mk, p->bdplus, mk); return 0; }
BD_AACS *libaacs_load(void) { BD_AACS *p = calloc(1, sizeof(BD_AACS)); p->h_libaacs = _open_libaacs(); if (!p->h_libaacs) { X_FREE(p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loading aacs library (%p)\n", p->h_libaacs); *(void **)(&p->decrypt_unit) = dl_dlsym(p->h_libaacs, "aacs_decrypt_unit"); *(void **)(&p->get_vid) = dl_dlsym(p->h_libaacs, "aacs_get_vid"); *(void **)(&p->get_pmsn) = dl_dlsym(p->h_libaacs, "aacs_get_pmsn"); *(void **)(&p->get_device_binding_id) = dl_dlsym(p->h_libaacs, "aacs_get_device_binding_id"); *(void **)(&p->get_device_nonce) = dl_dlsym(p->h_libaacs, "aacs_get_device_nonce"); if (!p->decrypt_unit) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "libaacs dlsym failed! (%p)\n", p->h_libaacs); libaacs_unload(&p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loaded libaacs (%p)\n", p->h_libaacs); if (file_open != file_open_default()) { BD_DEBUG(DBG_BLURAY, "Registering libaacs filesystem handler %p (%p)\n", (void *)(intptr_t)file_open, p->h_libaacs); DL_CALL(p->h_libaacs, aacs_register_file, file_open); } return p; }
static BD_AACS *_load(int impl_id) { BD_AACS *p = calloc(1, sizeof(BD_AACS)); if (!p) { return NULL; } p->impl_id = impl_id; p->h_libaacs = _open_libaacs(&p->impl_id); if (!p->h_libaacs) { X_FREE(p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loading aacs library (%p)\n", p->h_libaacs); *(void **)(&p->decrypt_unit) = dl_dlsym(p->h_libaacs, "aacs_decrypt_unit"); *(void **)(&p->decrypt_bus) = dl_dlsym(p->h_libaacs, "aacs_decrypt_bus"); if (!p->decrypt_unit) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "libaacs dlsym failed! (%p)\n", p->h_libaacs); libaacs_unload(&p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loaded libaacs (%p)\n", p->h_libaacs); if (file_open != file_open_default()) { BD_DEBUG(DBG_BLURAY, "Registering libaacs filesystem handler %p (%p)\n", (void *)(intptr_t)file_open, p->h_libaacs); DL_CALL(p->h_libaacs, aacs_register_file, file_open); } return p; }
static uint32_t _bdplus_get(BD_BDPLUS *p, const char *func) { if (p && p->bdplus) { fptr_int32 fp; *(void **)(&fp) = dl_dlsym(p->h_libbdplus, func); if (fp) { return fp(p->bdplus); } } return 0; }
static const uint8_t *_get_data(BD_AACS *p, const char *func) { fptr_p_void fp; *(void **)(&fp) = dl_dlsym(p->h_libaacs, func); if (!fp) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "%s() dlsym failed!\n", func); return NULL; } return (const uint8_t*)fp(p->aacs); }
int libaacs_open(BD_AACS *p, const char *device_path, const char *keyfile_path) { int error_code = 0; fptr_p_void open; fptr_p_void open2; fptr_int aacs_get_mkb_version; fptr_p_void aacs_get_disc_id; _libaacs_close(p); *(void **)(&open) = dl_dlsym(p->h_libaacs, "aacs_open"); *(void **)(&open2) = dl_dlsym(p->h_libaacs, "aacs_open2"); *(void **)(&aacs_get_mkb_version) = dl_dlsym(p->h_libaacs, "aacs_get_mkb_version"); *(void **)(&aacs_get_disc_id) = dl_dlsym(p->h_libaacs, "aacs_get_disc_id"); if (open2) { p->aacs = open2(device_path, keyfile_path, &error_code); } else if (open) { BD_DEBUG(DBG_BLURAY, "Using old aacs_open(), no verbose error reporting available\n"); p->aacs = open(device_path, keyfile_path); } else { BD_DEBUG(DBG_BLURAY, "aacs_open() not found\n"); } if (p->aacs) { if (aacs_get_mkb_version) { p->mkbv = aacs_get_mkb_version(p->aacs); } if (aacs_get_disc_id) { p->disc_id = (const uint8_t *)aacs_get_disc_id(p->aacs); } return error_code; } return error_code ? error_code : 1; }
int libaacs_get_bec_enabled(BD_AACS *p) { fptr_int get_bec; if (!p || !p->h_libaacs) { return 0; } *(void **)(&get_bec) = dl_dlsym(p->h_libaacs, "aacs_get_bus_encryption"); if (!get_bec) { BD_DEBUG(DBG_BLURAY, "aacs_get_bus_encryption() dlsym failed!\n"); return 0; } return get_bec(p->aacs) == 3; }
int libaacs_open(BD_AACS *p, const char *device, void *file_open_handle, void *file_open_fp, const char *keyfile_path) { int error_code = 0; fptr_p_void open; fptr_p_void open2; fptr_p_void init; fptr_int open_device; fptr_int aacs_get_mkb_version; fptr_p_void aacs_get_disc_id; _libaacs_close(p); *(void **)(&open) = dl_dlsym(p->h_libaacs, "aacs_open"); *(void **)(&open2) = dl_dlsym(p->h_libaacs, "aacs_open2"); *(void **)(&init) = dl_dlsym(p->h_libaacs, "aacs_init"); *(void **)(&aacs_get_mkb_version) = dl_dlsym(p->h_libaacs, "aacs_get_mkb_version"); *(void **)(&aacs_get_disc_id) = dl_dlsym(p->h_libaacs, "aacs_get_disc_id"); *(void **)(&open_device) = dl_dlsym(p->h_libaacs, "aacs_open_device"); if (init && open_device) { p->aacs = init(); DL_CALL(p->h_libaacs, aacs_set_fopen, p->aacs, file_open_handle, file_open_fp); error_code = open_device(p->aacs, device, keyfile_path); } else if (open2) { BD_DEBUG(DBG_BLURAY, "Using old aacs_open2(), no UDF support available\n"); p->aacs = open2(device, keyfile_path, &error_code); } else if (open) { BD_DEBUG(DBG_BLURAY, "Using old aacs_open(), no verbose error reporting available\n"); p->aacs = open(device, keyfile_path); } else { BD_DEBUG(DBG_BLURAY, "aacs_open() not found\n"); } if (p->aacs) { if (aacs_get_mkb_version) { p->mkbv = aacs_get_mkb_version(p->aacs); } if (aacs_get_disc_id) { p->disc_id = (const uint8_t *)aacs_get_disc_id(p->aacs); } return error_code; } return error_code ? error_code : 1; }
int libbdplus_init(BD_BDPLUS *p, const char *device_path, const uint8_t *vid) { fptr_p_void bdplus_init; _libbdplus_close(p); *(void **)(&bdplus_init) = dl_dlsym(p->h_libbdplus, "bdplus_init"); if (!bdplus_init) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "libbdplus dlsym(bdplus_init) failed! (%p)\n", p->h_libbdplus); return -1; } p->bdplus = bdplus_init(device_path, NULL, vid); if (!p->bdplus) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bdplus_init() failed! (%p)\n", p->h_libbdplus); return -1; } return 0; }
BD_BDPLUS *libbdplus_load(void) { BD_BDPLUS *p = calloc(1, sizeof(BD_BDPLUS)); BD_DEBUG(DBG_BDPLUS, "attempting to load libbdplus\n"); p->h_libbdplus = _libbdplus_open(); if (!p->h_libbdplus) { X_FREE(p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loading libbdplus (%p)\n", p->h_libbdplus); *(void **)(&p->event) = dl_dlsym(p->h_libbdplus, "bdplus_event"); *(void **)(&p->m2ts) = dl_dlsym(p->h_libbdplus, "bdplus_m2ts"); *(void **)(&p->seek) = dl_dlsym(p->h_libbdplus, "bdplus_seek"); *(void **)(&p->fixup) = dl_dlsym(p->h_libbdplus, "bdplus_fixup"); *(void **)(&p->m2ts_close) = dl_dlsym(p->h_libbdplus, "bdplus_m2ts_close"); if (!p->m2ts) { /* Old API */ *(void **)(&p->title) = dl_dlsym(p->h_libbdplus, "bdplus_set_title"); if (!p->title) { *(void **)(&p->title) = dl_dlsym(p->h_libbdplus, "bdplus_set_m2ts"); } } if (!p->seek || !p->fixup || !((p->m2ts && p->m2ts_close) || p->title)) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "libbdplus dlsym failed! (%p)\n", p->h_libbdplus); libbdplus_unload(&p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loaded libbdplus (%p)\n", p->h_libbdplus); if (file_open != file_open_default()) { BD_DEBUG(DBG_BLURAY, "Registering libbdplus filesystem handler %p (%p)\n", (void *)(intptr_t)file_open, p->h_libbdplus); DL_CALL(p->h_libbdplus, bdplus_register_file, file_open); } return p; }
static int _find_jvm(void *jvm_lib, JNIEnv **env, JavaVM **jvm) { fptr_JNI_GetCreatedJavaVMs JNI_GetCreatedJavaVMs_fp; *(void **)(&JNI_GetCreatedJavaVMs_fp) = dl_dlsym(jvm_lib, "JNI_GetCreatedJavaVMs"); if (JNI_GetCreatedJavaVMs_fp == NULL) { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't find symbol JNI_GetCreatedJavaVMs.\n"); return 0; } jsize nVMs = 0; JavaVM* javavm = NULL; int result = JNI_GetCreatedJavaVMs_fp(&javavm, 1, &nVMs); if (result == JNI_OK && nVMs > 0) { *jvm = javavm; (**jvm)->AttachCurrentThread(*jvm, (void**)env, NULL); return 1; } return 0; }
BD_BDPLUS *libbdplus_load(void) { BD_BDPLUS *p = calloc(1, sizeof(BD_BDPLUS)); BD_DEBUG(DBG_BDPLUS, "attempting to load libbdplus\n"); p->h_libbdplus = _libbdplus_open(); if (!p->h_libbdplus) { X_FREE(p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loading libbdplus (%p)\n", p->h_libbdplus); *(void **)(&p->event) = dl_dlsym(p->h_libbdplus, "bdplus_event"); *(void **)(&p->m2ts) = dl_dlsym(p->h_libbdplus, "bdplus_m2ts"); *(void **)(&p->seek) = dl_dlsym(p->h_libbdplus, "bdplus_seek"); *(void **)(&p->fixup) = dl_dlsym(p->h_libbdplus, "bdplus_fixup"); *(void **)(&p->m2ts_close) = dl_dlsym(p->h_libbdplus, "bdplus_m2ts_close"); if (!p->m2ts) { /* Old API */ *(void **)(&p->title) = dl_dlsym(p->h_libbdplus, "bdplus_set_title"); if (!p->title) { *(void **)(&p->title) = dl_dlsym(p->h_libbdplus, "bdplus_set_m2ts"); } } if (!p->seek || !p->fixup || !((p->m2ts && p->m2ts_close) || p->title)) { BD_DEBUG(DBG_BLURAY | DBG_CRIT, "libbdplus dlsym failed! (%p)\n", p->h_libbdplus); libbdplus_unload(&p); return NULL; } BD_DEBUG(DBG_BLURAY, "Loaded libbdplus (%p)\n", p->h_libbdplus); return p; }
static int _create_jvm(void *jvm_lib, const char *java_home, const char *jar_file, JNIEnv **env, JavaVM **jvm) { (void)java_home; /* used only with J2ME */ fptr_JNI_CreateJavaVM JNI_CreateJavaVM_fp = (fptr_JNI_CreateJavaVM)(intptr_t)dl_dlsym(jvm_lib, "JNI_CreateJavaVM"); if (JNI_CreateJavaVM_fp == NULL) { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't find symbol JNI_CreateJavaVM.\n"); return 0; } JavaVMOption* option = calloc(1, sizeof(JavaVMOption) * 20); int n = 0; JavaVMInitArgs args; option[n++].optionString = str_dup ("-Dawt.toolkit=java.awt.BDToolkit"); option[n++].optionString = str_dup ("-Djava.awt.graphicsenv=java.awt.BDGraphicsEnvironment"); option[n++].optionString = str_printf("-Xbootclasspath/p:%s", jar_file); option[n++].optionString = str_dup ("-Xms256M"); option[n++].optionString = str_dup ("-Xmx256M"); option[n++].optionString = str_dup ("-Xss2048k"); #ifdef HAVE_BDJ_J2ME option[n++].optionString = str_printf("-Djava.home=%s", java_home); option[n++].optionString = str_printf("-Xbootclasspath/a:%s/lib/xmlparser.jar", java_home); option[n++].optionString = str_dup ("-XfullShutdown"); #endif /* JVM debug options */ if (getenv("BDJ_JVM_DEBUG")) { option[n++].optionString = str_dup("-ea"); //option[n++].optionString = str_dup("-verbose"); //option[n++].optionString = str_dup("-verbose:class,gc,jni"); option[n++].optionString = str_dup("-Xdebug"); option[n++].optionString = str_dup("-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"); } #ifdef HAVE_BDJ_J2ME /* see: http://docs.oracle.com/javame/config/cdc/cdc-opt-impl/ojmeec/1.0/runtime/html/cvm.htm#CACBHBJB trace method execution: BDJ_JVM_TRACE=0x0002 trace exceptions: BDJ_JVM_TRACE=0x4000 */ if (getenv("BDJ_JVM_TRACE")) { option[n++].optionString = str_printf("-Xtrace:%s", getenv("BDJ_JVM_TRACE")); } #endif args.version = JNI_VERSION_1_4; args.nOptions = n; args.options = option; args.ignoreUnrecognized = JNI_FALSE; // don't ignore unrecognized options int result = JNI_CreateJavaVM_fp(jvm, (void**) env, &args); while (--n >= 0) { X_FREE(option[n].optionString); } X_FREE(option); if (result != JNI_OK || !*env) { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to create new Java VM. JNI_CreateJavaVM result: %d\n", result); return 0; } return 1; }
BDJAVA* bdj_open(const char *path, struct bluray *bd, struct bd_registers_s *registers, struct indx_root_s *index) { // first load the jvm using dlopen void* jvm_lib = _load_jvm(); if (!jvm_lib) { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Wasn't able to load libjvm.so\n"); return NULL; } fptr_JNI_CreateJavaVM JNI_CreateJavaVM_fp = (fptr_JNI_CreateJavaVM)dl_dlsym(jvm_lib, "JNI_CreateJavaVM"); if (JNI_CreateJavaVM_fp == NULL) { dl_dlclose(jvm_lib); BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't find symbol JNI_CreateJavaVM.\n"); return NULL; } BDJAVA* bdjava = calloc(1, sizeof(BDJAVA)); bdjava->bd = bd; bdjava->reg = registers; bdjava->index = index; bdjava->path = path; bdjava->h_libjvm = jvm_lib; JavaVMInitArgs args; // check if overriding the classpath const char* classpath = getenv("LIBBLURAY_CP"); if (classpath == NULL) classpath = BDJ_CLASSPATH; // determine classpath char* classpath_opt = str_printf("-Djava.class.path=%s", classpath); // determine bluray.vfs.root char* vfs_opt; vfs_opt = str_printf("-Dbluray.vfs.root=%s", path); JavaVMOption* option = calloc(1, sizeof(JavaVMOption) * 9); int n = 0; option[n++].optionString = classpath_opt; option[n++].optionString = vfs_opt; args.version = JNI_VERSION_1_6; args.nOptions = n; args.options = option; args.ignoreUnrecognized = JNI_FALSE; // don't ignore unrecognized options JNIEnv* env = NULL; int result = JNI_CreateJavaVM_fp(&bdjava->jvm, (void**) &env, &args); free(option); free(classpath_opt); free(vfs_opt); if (result != JNI_OK || !env) { bdj_close(bdjava); BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to create new Java VM.\n"); return NULL; } if (!_bdj_init(bdjava, env)) { bdj_close(bdjava); return NULL; } return bdjava; }
static int _create_jvm(void *jvm_lib, const char *java_home, const char *jar_file, JNIEnv **env, JavaVM **jvm) { (void)java_home; /* used only with J2ME */ fptr_JNI_CreateJavaVM JNI_CreateJavaVM_fp; *(void **)(&JNI_CreateJavaVM_fp) = dl_dlsym(jvm_lib, "JNI_CreateJavaVM"); if (JNI_CreateJavaVM_fp == NULL) { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't find symbol JNI_CreateJavaVM.\n"); return 0; } JavaVMOption* option = calloc(1, sizeof(JavaVMOption) * 20); if (!option) { BD_DEBUG(DBG_CRIT, "out of memory\n"); return 0; } int n = 0; JavaVMInitArgs args; option[n++].optionString = str_dup ("-Dawt.toolkit=java.awt.BDToolkit"); option[n++].optionString = str_dup ("-Djava.awt.graphicsenv=java.awt.BDGraphicsEnvironment"); option[n++].optionString = str_dup ("-Djavax.accessibility.assistive_technologies= "); option[n++].optionString = str_printf("-Xbootclasspath/p:%s", jar_file); option[n++].optionString = str_dup ("-Xms256M"); option[n++].optionString = str_dup ("-Xmx256M"); option[n++].optionString = str_dup ("-Xss2048k"); #ifdef HAVE_BDJ_J2ME option[n++].optionString = str_printf("-Djava.home=%s", java_home); option[n++].optionString = str_printf("-Xbootclasspath/a:%s/lib/xmlparser.jar", java_home); option[n++].optionString = str_dup ("-XfullShutdown"); #endif /* JVM debug options */ if (getenv("BDJ_JVM_DEBUG")) { option[n++].optionString = str_dup("-ea"); //option[n++].optionString = str_dup("-verbose"); //option[n++].optionString = str_dup("-verbose:class,gc,jni"); option[n++].optionString = str_dup("-Xdebug"); option[n++].optionString = str_dup("-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"); } #ifdef HAVE_BDJ_J2ME /* see: http://docs.oracle.com/javame/config/cdc/cdc-opt-impl/ojmeec/1.0/runtime/html/cvm.htm#CACBHBJB trace method execution: BDJ_JVM_TRACE=0x0002 trace exceptions: BDJ_JVM_TRACE=0x4000 */ if (getenv("BDJ_JVM_TRACE")) { option[n++].optionString = str_printf("-Xtrace:%s", getenv("BDJ_JVM_TRACE")); } #endif args.version = JNI_VERSION_1_4; args.nOptions = n; args.options = option; args.ignoreUnrecognized = JNI_FALSE; // don't ignore unrecognized options #ifdef _WIN32 /* ... in windows, JVM options are not UTF8 but current system code page ... */ /* luckily, most BD-J options can be passed in as java strings later. But, not class path. */ int ii; for (ii = 0; ii < n; ii++) { char *tmp = _utf8_to_cp(option[ii].optionString); if (tmp) { X_FREE(option[ii].optionString); option[ii].optionString = tmp; } else { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to convert %s\n", option[ii].optionString); } } #endif int result = JNI_CreateJavaVM_fp(jvm, (void**) env, &args); while (--n >= 0) { X_FREE(option[n].optionString); } X_FREE(option); if (result != JNI_OK || !*env) { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to create new Java VM. JNI_CreateJavaVM result: %d\n", result); return 0; } return 1; }
int libaacs_open(BD_AACS *p, const char *device, void *file_open_handle, void *file_open_fp, const char *keyfile_path) { int error_code = 0; fptr_p_void open; fptr_p_void open2; fptr_p_void init; fptr_int open_device; fptr_int aacs_get_mkb_version; fptr_p_void aacs_get_disc_id; _libaacs_close(p); *(void **)(&open) = dl_dlsym(p->h_libaacs, "aacs_open"); *(void **)(&open2) = dl_dlsym(p->h_libaacs, "aacs_open2"); *(void **)(&init) = dl_dlsym(p->h_libaacs, "aacs_init"); *(void **)(&aacs_get_mkb_version) = dl_dlsym(p->h_libaacs, "aacs_get_mkb_version"); *(void **)(&aacs_get_disc_id) = dl_dlsym(p->h_libaacs, "aacs_get_disc_id"); *(void **)(&open_device) = dl_dlsym(p->h_libaacs, "aacs_open_device"); if (init && open_device) { p->aacs = init(); DL_CALL(p->h_libaacs, aacs_set_fopen, p->aacs, file_open_handle, file_open_fp); error_code = open_device(p->aacs, device, keyfile_path); } else if (open2) { BD_DEBUG(DBG_BLURAY, "Using old aacs_open2(), no UDF support available\n"); p->aacs = open2(device, keyfile_path, &error_code); /* libmmbd needs dev: for devices */ if (!p->aacs && p->impl_id == IMPL_LIBMMBD && !strncmp(device, "/dev/", 5)) { char *tmp_device = str_printf("dev:%s", device); if (tmp_device) { p->aacs = open2(tmp_device, keyfile_path, &error_code); X_FREE(tmp_device); } } } else if (open) { BD_DEBUG(DBG_BLURAY, "Using old aacs_open(), no verbose error reporting available\n"); p->aacs = open(device, keyfile_path); } else { BD_DEBUG(DBG_BLURAY, "aacs_open() not found\n"); } if (error_code) { /* failed. try next aacs implementation if available. */ BD_AACS *p2 = _load(p->impl_id + 1); if (p2) { if (!libaacs_open(p2, device, file_open_handle, file_open_fp, keyfile_path)) { /* succeed - swap implementations */ _unload(p); *p = *p2; X_FREE(p2); return 0; } /* failed - report original errors */ libaacs_unload(&p2); } } if (p->aacs) { if (aacs_get_mkb_version) { p->mkbv = aacs_get_mkb_version(p->aacs); } if (aacs_get_disc_id) { p->disc_id = (const uint8_t *)aacs_get_disc_id(p->aacs); } return error_code; } return error_code ? error_code : 1; }
BDJAVA* bdj_open(const char *path, const char* start, void* bd, void* registers) { // first load the jvm using dlopen void* jvm_lib = load_jvm(); if (!jvm_lib) { BD_DEBUG(DBG_BDJ | DBG_CRIT, "Wasn't able to load libjvm.so\n"); return NULL; } BDJAVA* bdjava = malloc(sizeof(BDJAVA)); bdjava->bd = bd; bdjava->reg = registers; JavaVMInitArgs args; // check if overriding the classpath const char* classpath = getenv("LIBBLURAY_CP"); if (classpath == NULL) classpath = BDJ_CLASSPATH; // determine classpath char* classpath_opt = str_printf("-Djava.class.path=%s", classpath); JavaVMOption* option = malloc(sizeof(JavaVMOption) * 1); option[0].optionString = classpath_opt; args.version = JNI_VERSION_1_6; args.nOptions = 1; args.options = option; args.ignoreUnrecognized = JNI_FALSE; // don't ignore unrecognized options fptr_JNI_CreateJavaVM JNI_CreateJavaVM_fp = (fptr_JNI_CreateJavaVM)dl_dlsym(jvm_lib, "JNI_CreateJavaVM"); if (JNI_CreateJavaVM_fp == NULL) { free(bdjava); free(option); free(classpath_opt); BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't find symbol JNI_CreateJavaVM.\n"); return NULL; } int result = JNI_CreateJavaVM_fp(&bdjava->jvm, (void**) &bdjava->env, &args); free(option); free(classpath_opt); if (result != JNI_OK || !bdjava->env) { free(bdjava); BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to create new Java VM.\n"); return NULL; } // determine path of bdjo file to load char* bdjo_path = str_printf("%s%s/%s.bdjo", path, BDJ_BDJO_PATH, start); jobject bdjo = bdjo_read(bdjava->env, bdjo_path); free(bdjo_path); if (!bdjo) { free(bdjava); BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to load BDJO file.\n"); return NULL; } if (start_xlet(bdjava->env, path, bdjo, bdjava) == BDJ_ERROR) { free(bdjava); BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to start BDJ program.\n"); return NULL; } return bdjava; }