diff --git a/jni/android_driver.c b/jni/android_driver.c index 4b0b30a..2b31eb2 100644 --- a/jni/android_driver.c +++ b/jni/android_driver.c @@ -49,6 +49,7 @@ extern Kimage g_mainwin_kimage; extern int g_config_kegs_update_needed; extern int g_limit_speed; +extern int g_zipgs_reg_c05a; extern word32 g_red_mask; extern word32 g_green_mask; @@ -505,17 +506,14 @@ int x_diskimage(jclass diskimage_class, jobject diskimage_event) { void x_key_special(int key_id) { key_id = key_id & 0x7f; // only use lower 7 bits - switch(key_id) { - case 0: - case 1: - case 2: - case 3: - g_limit_speed = key_id; - g_config_kegs_update_needed = 1; - break; - case 120: - set_halt(HALT_WANTTOQUIT); // request kegsmain to exit - break; + if (key_id >= 0 && key_id <= 3) { + g_limit_speed = key_id; + g_config_kegs_update_needed = 1; + } else if (key_id >= 0x10 && key_id <= 0x1f) { + // run_prog() will see the change and call setup_zip_speeds() + g_zipgs_reg_c05a = ((key_id & 0x0f) << 4) | 0x0f; + } else if (key_id == 120) { + set_halt(HALT_WANTTOQUIT); // request kegsmain to exit } } @@ -566,12 +564,12 @@ check_input_events() // check if paused, first jclass cls = (*g_env)->GetObjectClass(g_env, g_thiz); - jmethodID mid = (*g_env)->GetMethodID(g_env, cls, "checkForPause", "(I)V"); + jmethodID mid = (*g_env)->GetMethodID(g_env, cls, "checkForPause", "(II)V"); (*g_env)->DeleteLocalRef(g_env, cls); if (mid == NULL) { return; } - (*g_env)->CallVoidMethod(g_env, g_thiz, mid, g_limit_speed); + (*g_env)->CallVoidMethod(g_env, g_thiz, mid, g_limit_speed, g_zipgs_reg_c05a); do { cls = (*g_env)->GetObjectClass(g_env, g_eventqueue); diff --git a/res/values/strings.xml b/res/values/strings.xml index e13d77b..b535c7b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -21,6 +21,7 @@ 1.0 megahertz 2.8 megahertz 8.0 megahertz + 16.0 megahertz Unlimited diff --git a/src/com/froop/app/kegs/KegsThread.java b/src/com/froop/app/kegs/KegsThread.java index ddea821..5832071 100644 --- a/src/com/froop/app/kegs/KegsThread.java +++ b/src/com/froop/app/kegs/KegsThread.java @@ -16,7 +16,8 @@ class KegsThread extends Thread { private String mConfigFile; // full path to config_kegs private Bitmap mBitmap; - private final AtomicInteger mCurrentSpeed = new AtomicInteger(0); + private final AtomicInteger mCurrentSpeedLimit = new AtomicInteger(0); + private final AtomicInteger mCurrentSpeedZip = new AtomicInteger(0); private final ReentrantLock mPauseLock = new ReentrantLock(); private final ReentrantLock mPowerWait = new ReentrantLock(); @@ -50,8 +51,9 @@ class KegsThread extends Thread { } // Called by native thread. - private void checkForPause(int currentEmulationSpeed) { - mCurrentSpeed.set(currentEmulationSpeed); // NOTE: This is a hack. + private void checkForPause(int currentEmulationSpeed, int currentZipSpeed) { + mCurrentSpeedLimit.set(currentEmulationSpeed); // g_limit_speed + mCurrentSpeedZip.set(currentZipSpeed); // g_zipgs_reg_c05a if (mPaused.get()) { mPauseLock.lock(); // deadlock here until onResume. Maybe not efficient. @@ -147,16 +149,9 @@ class KegsThread extends Thread { return mPowerWait.hasQueuedThreads(); } - public void setEmulationSpeed(int speed) { - // Speed matches g_limit_speed inside KEGS. - // Instead of a separate "control" event, key ids with bit 8 high are - // special events. See android_driver.c:x_key_special() - getEventQueue().add(new Event.KeyKegsEvent(speed + 0x80, true)); - } - - public int getEmulationSpeed() { - // Equal to g_limit_speed inside KEGS. - return mCurrentSpeed.get(); + public SpeedSetting getEmulationSpeed() { + return new SpeedSetting(getEventQueue(), + mCurrentSpeedLimit.get(), mCurrentSpeedZip.get()); } public void doWarmReset() { diff --git a/src/com/froop/app/kegs/SpeedFragment.java b/src/com/froop/app/kegs/SpeedFragment.java index dc3f340..f382a19 100644 --- a/src/com/froop/app/kegs/SpeedFragment.java +++ b/src/com/froop/app/kegs/SpeedFragment.java @@ -13,24 +13,15 @@ public class SpeedFragment extends SherlockDialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - int currentSpeed = ((KegsMain)getActivity()).getThread().getEmulationSpeed(); - // Adjust g_limit_speed to match default item number. - currentSpeed--; - if (currentSpeed < 0) { - currentSpeed = 3; - } + final SpeedSetting currentSpeed = ((KegsMain)getActivity()).getThread().getEmulationSpeed(); builder.setTitle(R.string.speed_title); - builder.setSingleChoiceItems(R.array.speed_choices, currentSpeed, + builder.setSingleChoiceItems(R.array.speed_choices, + currentSpeed.getMenuItem(), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { dismiss(); - // Adjust selected item number to match g_limit_speed. - item++; - if (item > 3) { - item = 0; - } - ((KegsMain)getActivity()).getThread().setEmulationSpeed(item); + currentSpeed.setFromMenuItem(item); } }); return builder.create(); diff --git a/src/com/froop/app/kegs/SpeedSetting.java b/src/com/froop/app/kegs/SpeedSetting.java new file mode 100644 index 0000000..b428af1 --- /dev/null +++ b/src/com/froop/app/kegs/SpeedSetting.java @@ -0,0 +1,60 @@ +package com.froop.app.kegs; + +import android.util.Log; +import java.util.concurrent.ConcurrentLinkedQueue; + +// Ugh. + +class SpeedSetting { + private ConcurrentLinkedQueue mEventQueue; + private int mSpeedLimit; // 0 = unlimited, 1=1mhz, 2=2.8mhz, 3=zipgs + private int mSpeedZip; // 0-15, zipgs, 0=16/16ths, 8=8/16th, 15=1/16th + + public SpeedSetting(ConcurrentLinkedQueue q, + int g_limit_speed, int g_zipgs_reg_c05a) { + mEventQueue = q; + mSpeedLimit = g_limit_speed; + mSpeedZip = (g_zipgs_reg_c05a & 0xf0) >> 4; + } + + public int getMenuItem() { + // Map g_limit_speed to R.array.speed_choices + int item = mSpeedLimit - 1; + if (item < 0) { + item = 5; + } + + if (mSpeedLimit == 3 && mSpeedZip < 0x08) { + item++; // Bump from 8mhz item to 16mhz item + } + + return item; + } + + public void setFromMenuItem(int item) { + // Map R.array.speed_choices to g_limit_speed + if (item == 2) { + mSpeedZip = 0x08; // limit zip to 8/16ths (8mhz) + } else { + mSpeedZip = 0x00; // default no zip limit + } + + mSpeedLimit = item + 1; + if (mSpeedLimit >= 5) { + mSpeedLimit = 0; + } else if (mSpeedLimit == 4) { + mSpeedLimit = 3; // turn 16mhz setting into "zipgs" speed + } + sendUpdateEvent(); + } + + private void sendUpdateEvent() { + if (mEventQueue != null) { + // Instead of a separate "control" event, key ids with bit 8 high are + // special events. See android_driver.c:x_key_special() + Log.w("kegs", "updating limit to " + mSpeedLimit + " " + mSpeedZip); + mEventQueue.add(new Event.KeyKegsEvent(0x80 + mSpeedLimit, true)); + mEventQueue.add(new Event.KeyKegsEvent(0x80 + 0x10 + mSpeedZip, true)); + } + } +}