An interface for controlling emulation speed.

This commit is contained in:
James Sanford 2013-07-27 20:08:21 -07:00 committed by James Sanford
parent c0751f8421
commit fd3c79cdca
5 changed files with 84 additions and 39 deletions

View File

@ -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);

View File

@ -21,6 +21,7 @@
<item>1.0 megahertz</item>
<item>2.8 megahertz</item>
<item>8.0 megahertz</item>
<item>16.0 megahertz</item>
<item>Unlimited</item>
</string-array>

View File

@ -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() {

View File

@ -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();

View File

@ -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));
}
}
}