void* startMainMethod(void *data) { void* mainLibHandler = dlopen((const char*)getGoLibPath(), 0); if (mainLibHandler == NULL) { LOG_FATAL("dlopen failed"); return NULL; } uintptr_t mainPC = (uintptr_t)dlsym(mainLibHandler, "main.main"); if (!mainPC) { LOG_FATAL("missing main.main"); } else { callMain(mainPC); } /* if (mainLibHandler) { int res = dlclose(mainLibHandler); if (res < 0) LOG_FATAL("dlclose failed"); } //TODO: quit java app if (globalVm != NULL) (*globalVm)->DetachCurrentThread(globalEnv); */ return NULL; }
// ANativeActivity_onCreate implements the application's entry point. // // This is the function that must be in the native code to instantiate // the application's native activity. It is called with the activity // instance; if the code is being instantiated from a // previously saved instance, the savedState will be non-NULL and // point to the saved data. You must make any copy of this data you // need – it will be released after you return from this function. // // See https://developer.android.com/ndk/reference/group___native_activity.html // // The Activity may be created and destroyed multiple times throughout // the life of a single process. Each time, onCreate is called. void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) { if (!main_running) { // Call the Go main.main. uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main"); if (!mainPC) { LOG_FATAL("missing main.main"); } callMain(mainPC); main_running = 1; } // Set the native activity callbacks, see: // https://developer.android.com/ndk/reference/struct_a_native_activity_callbacks.html activity->callbacks->onStart = onStart; activity->callbacks->onResume = onResume; activity->callbacks->onSaveInstanceState = onSaveInstanceState; activity->callbacks->onPause = onPause; activity->callbacks->onStop = onStop; activity->callbacks->onDestroy = onDestroy; activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; activity->callbacks->onInputQueueCreated = onInputQueueCreated; activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; activity->callbacks->onConfigurationChanged = onConfigurationChanged; activity->callbacks->onLowMemory = onLowMemory; onCreate(activity); }
// Entry point from our subclassed NativeActivity. // // By here, the Go runtime has been initialized (as we are running in // -buildmode=c-shared) but the first time it is called, Go's main.main // hasn't been called yet. // // The Activity may be created and destroyed multiple times throughout // the life of a single process. Each time, onCreate is called. void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) { if (!main_running) { JNIEnv* env = activity->env; // Note that activity->clazz is mis-named. JavaVM* current_vm = activity->vm; jobject current_ctx = activity->clazz; setCurrentContext(current_vm, (*env)->NewGlobalRef(env, current_ctx)); // Set TMPDIR. jmethodID gettmpdir = find_method(env, current_ctx_clazz, "getTmpdir", "()Ljava/lang/String;"); jstring jpath = (jstring)(*env)->CallObjectMethod(env, current_ctx, gettmpdir, NULL); const char* tmpdir = (*env)->GetStringUTFChars(env, jpath, NULL); if (setenv("TMPDIR", tmpdir, 1) != 0) { LOG_INFO("setenv(\"TMPDIR\", \"%s\", 1) failed: %d", tmpdir, errno); } (*env)->ReleaseStringUTFChars(env, jpath, tmpdir); // Call the Go main.main. uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main"); if (!mainPC) { LOG_FATAL("missing main.main"); } callMain(mainPC); main_running = 1; } // These functions match the methods on Activity, described at // http://developer.android.com/reference/android/app/Activity.html // // Note that onNativeWindowResized is not called on resize. Avoid it. // https://code.google.com/p/android/issues/detail?id=180645 activity->callbacks->onStart = onStart; activity->callbacks->onResume = onResume; activity->callbacks->onSaveInstanceState = onSaveInstanceState; activity->callbacks->onPause = onPause; activity->callbacks->onStop = onStop; activity->callbacks->onDestroy = onDestroy; activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; activity->callbacks->onInputQueueCreated = onInputQueueCreated; activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; activity->callbacks->onConfigurationChanged = onConfigurationChanged; activity->callbacks->onLowMemory = onLowMemory; onCreate(activity); }
static void processMain(uint32_t cyclesPerScreen, uint32_t startTime, int32_t timeout) { // the current impl may cause the interrupt routines to burn more cycles than would be normally possible (e.g. if // they use busy-wait for some condition which does not materialize in our emulator env. Consequently our // "timeout" may be completely off the target... if ((_mainProgStatus >0) && (timeout >0)) { // might be the rest of some "init" logic... or some loop playing samples sidResetVolumeChangeCount(); uint16_t originalDigiCount= digiGetCount(); uint16_t originalDigiOverflowCount= digiGetOverflowCount(); _mainProgStatus= callMain(0, 0, startTime, timeout); // continue where interrupted digiTagOrigin(MAIN_OFFSET_MASK, startTime, originalDigiCount, originalDigiOverflowCount); _volUpdates+= sidGetNumberOfVolumeChanges(); // number of updates to the volume } }
static int EMSCRIPTEN_KEEPALIVE playTune(int selectedTrack) { sActualSubsong= selectedTrack; reInitEngine(); synth_init(sSampleRate); initClockSpeed(); initSampleBuffer(); initC64Rom(); // reset & init memcpy(memory, sMemorySnapshot, MEMORY_SIZE); // restore original mem content.. previous "sInitAddr" run may have corrupted the state // CIA 1 defaults (by default C64 is configured with CIA1 timer / not raster irq) setIO(0xdc0d, 0x81); // interrupt control (interrupt through timer A) setIO(0xdc0e, 0x01); // control timer A: start - must already be started (e.g. Phobia, GianaSisters, etc expect it) setIO(0xdc0f, 0x08); // control timer B (start/stop) means auto-restart setIO(0xdc04, sTotalCyclesPerScreen&0xff); // timer A (1x pro screen refresh) setIO(0xdc05, sTotalCyclesPerScreen>>8); if (isRsid()) { // by default C64 is configured with CIA1 timer / not raster irq setIO(0xd01a, 0x00); // raster irq not active setIO(0xd011, 0x1B); setIO(0xd012, 0x00); // raster at line x // CIA 2 defaults setIO(0xdd0e, 0x08); // control timer 2A (start/stop) setIO(0xdd0f, 0x08); // control timer 2B (start/stop) } setupInitMemoryBank(); initCia(); initVic(); sOverflowDigiCount=0; sDigiCount=0; hackIfNeeded(); sMainProgStatus= callMain(sInitAddr, sActualSubsong, 0, CYCLELIMIT); // if it does not complete then it is likely in an endless loop / maybe digi player initBuffers(); setupPsidPlayMemoryBank(); return 0; }