Add ability to hot swap disks.

This commit is contained in:
James Sanford 2012-11-02 22:39:21 -07:00
parent 3fe3583506
commit 66ea28c3c6
6 changed files with 167 additions and 6 deletions

View File

@ -458,6 +458,45 @@ int x_mouse_update(jclass mouse_class, jobject mouse_event) {
return 1;
}
int x_diskimage(jclass diskimage_class, jobject diskimage_event) {
jfieldID fid = (*g_env)->GetFieldID(g_env, diskimage_class, "slot", "I");
if (fid == NULL) {
LOGE("NO FID");
return 0;
}
jint slot = (*g_env)->GetIntField(g_env, diskimage_event, fid);
fid = (*g_env)->GetFieldID(g_env, diskimage_class, "drive", "I");
if (fid == NULL) {
LOGE("NO FID");
return 0;
}
jint drive = (*g_env)->GetIntField(g_env, diskimage_event, fid);
// s6d1 is 'slot 6 drive 0' according to KEGS.
drive--;
fid = (*g_env)->GetFieldID(g_env, diskimage_class, "filename", "Ljava/lang/String;");
if (fid == NULL) {
LOGE("NO FID");
return 0;
}
jstring name = (*g_env)->GetObjectField(g_env, diskimage_event, fid);
char *nativeString = NULL;
if (name != NULL) {
nativeString = (char *)(*g_env)->GetStringUTFChars(g_env, name, 0);
}
// KEGS makes its own copy of the string.
int eject = nativeString == NULL ? 1 : 0;
insert_disk(slot, drive, nativeString, eject, 0, 0, -1);
(*g_env)->ReleaseStringUTFChars(g_env, name, nativeString);
(*g_env)->DeleteLocalRef(g_env, name);
return 1;
}
void x_key_special(int key_id) {
key_id = key_id & 0x7f; // only use lower 7 bits
switch(key_id) {
@ -556,6 +595,7 @@ check_input_events()
jclass mouse_class = (*g_env)->FindClass(g_env, "com/froop/app/kegs/Event$MouseKegsEvent");
jclass joystick_class = (*g_env)->FindClass(g_env, "com/froop/app/kegs/Event$JoystickKegsEvent");
jclass key_class = (*g_env)->FindClass(g_env, "com/froop/app/kegs/Event$KeyKegsEvent");
jclass diskimage_class = (*g_env)->FindClass(g_env, "com/froop/app/kegs/Event$DiskImageEvent");
if (mouse_class != NULL && (*g_env)->IsInstanceOf(g_env, event_item, mouse_class)) {
keep_going = x_mouse_update(mouse_class, event_item);
@ -563,10 +603,13 @@ check_input_events()
keep_going = x_joystick_update(joystick_class, event_item);
} else if (key_class != NULL && (*g_env)->IsInstanceOf(g_env, event_item, key_class)) {
keep_going = x_key_update(key_class, event_item);
} else if (diskimage_class != NULL && (*g_env)->IsInstanceOf(g_env, event_item, diskimage_class)) {
keep_going = x_diskimage(diskimage_class, event_item);
}
(*g_env)->DeleteLocalRef(g_env, mouse_class);
(*g_env)->DeleteLocalRef(g_env, joystick_class);
(*g_env)->DeleteLocalRef(g_env, key_class);
(*g_env)->DeleteLocalRef(g_env, diskimage_class);
(*g_env)->DeleteLocalRef(g_env, event_item);
}
} while(event_item != NULL && keep_going);

View File

@ -23,6 +23,12 @@
<string name="diskimage_title">Choose a disk</string>
<string name="asset_loading">Preparing disk image...</string>
<string-array name="swapdisk_choices">
<item>Ignore this disk</item>
<item>Swap to this disk</item>
<item>Boot this disk</item>
</string-array>
<!-- R.menu.actions -->
<string name="input_joystick">Use Joystick</string>
<string name="input_mouse">Use Mouse</string>

View File

@ -38,4 +38,15 @@ class Event {
public int y; // absolute Y, -32767 to 32767
public int buttons;
}
static class DiskImageEvent extends KegsEvent {
public DiskImageEvent(String filename, int slot, int drive) {
this.filename = filename; // when null, eject only.
this.slot = slot;
this.drive = drive;
}
public String filename;
public int slot;
public int drive;
}
}

View File

@ -33,6 +33,7 @@ public class KegsMain extends SherlockFragmentActivity implements KegsKeyboard.S
private static final String FRAGMENT_SPEED = "speed";
private static final String FRAGMENT_DISKIMAGE = "diskimage";
private static final String FRAGMENT_ASSET = "asset";
private static final String FRAGMENT_SWAPDISK = "swapdisk";
private ConfigFile mConfigFile;
private KegsThread mKegsThread;
@ -50,6 +51,7 @@ public class KegsMain extends SherlockFragmentActivity implements KegsKeyboard.S
private boolean mDownloadAborted = false;
private boolean mModeMouse = true;
private boolean mHaveNewIntent = false;
private long mScreenSizeTime = 0;
@ -164,7 +166,7 @@ public class KegsMain extends SherlockFragmentActivity implements KegsKeyboard.S
mConfigFile.setConfig(image);
getThread().allowPowerOn();
} else {
// TODO FIXME: eject/insert the new disk.
getThread().getEventQueue().add(image.getDiskImageEvent());
}
}
}
@ -430,13 +432,37 @@ public class KegsMain extends SherlockFragmentActivity implements KegsKeyboard.S
return false;
}
private boolean dismissFragment(String tag) {
final SherlockDialogFragment frag = (SherlockDialogFragment)getSupportFragmentManager().findFragmentByTag(tag);
if (frag == null) {
return false;
} else {
frag.dismiss();
return true;
}
}
private void handleNewIntent(Intent intent) {
final DiskImage image = getBootDiskImage(intent);
if (image == null) {
return; // Nothing to do.
}
dismissFragment(FRAGMENT_ROM); // Note: should probably bail if visible.
dismissFragment(FRAGMENT_SPEED);
dismissFragment(FRAGMENT_DISKIMAGE);
dismissFragment(FRAGMENT_SWAPDISK);
// Ask the user what to do with this new disk image.
new SwapDiskFragment(image).show(getSupportFragmentManager(),
FRAGMENT_SWAPDISK);
}
@Override
protected void onNewIntent(Intent intent) {
// TODO: consider asking user whether to swap disks or reboot
final DiskImage image = getBootDiskImage(intent);
if (image != null) {
loadDiskImage(image);
}
// "An activity will always be paused before receiving a new intent."
// Being paused means we can't show a dialog here. Tell onResume to do it.
setIntent(intent);
mHaveNewIntent = true;
}
@Override
@ -527,6 +553,10 @@ public class KegsMain extends SherlockFragmentActivity implements KegsKeyboard.S
if (mKegsView instanceof KegsViewGL) {
mKegsView.onResume();
}
if (mHaveNewIntent) {
mHaveNewIntent = false;
handleNewIntent(getIntent());
}
}
@Override

View File

@ -0,0 +1,40 @@
package com.froop.app.kegs;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import com.actionbarsherlock.app.SherlockDialogFragment;
public class SwapDiskFragment extends SherlockDialogFragment {
private DiskImage mImage;
public SwapDiskFragment(DiskImage image) {
super();
mImage = image;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(mImage.getTitle());
builder.setIcon(mImage.getIconId());
builder.setItems(R.array.swapdisk_choices,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
dismiss();
if (item == 0) {
// ignore this image
} else if (item == 1) {
mImage.primary = false; // just a disk insert
((KegsMain)getActivity()).loadDiskImage(mImage);
} else if (item == 2) {
((KegsMain)getActivity()).loadDiskImage(mImage);
}
}
});
return builder.create();
}
}

View File

@ -1,5 +1,7 @@
package com.froop.app.kegs;
import android.util.Log;
import java.lang.Integer;
import java.io.File;
class DiskImage {
@ -39,4 +41,33 @@ class DiskImage {
return null;
}
}
public String getTitle() {
int pos = this.filename.lastIndexOf("/") + 1;
return this.filename.substring(pos);
}
public int getIconId() {
if (this.template.equals(BOOT_SLOT_7)) {
return (R.drawable.ic_menu_save); // FIXME should be hard disk icon
} else if (this.template.equals(BOOT_SLOT_5)) {
return (R.drawable.ic_menu_save);
} else if (this.template.equals(BOOT_SLOT_6)) {
return (R.drawable.ic_menu_save); // FIXME should be 5.25 disk icon
} else {
return (R.drawable.ic_menu_save); // FIXME should be question mark icon
}
}
public Event.DiskImageEvent getDiskImageEvent() {
if (this.drive.substring(0, 1).equals("s") &&
this.drive.substring(2, 3).equals("d")) {
int slot = Integer.parseInt(this.drive.substring(1, 2));
int drive = Integer.parseInt(this.drive.substring(3));
return new Event.DiskImageEvent(this.filename, slot, drive);
} else {
Log.e("kegs", "disk image " + this.filename + " has bad drive " + this.drive);
return null;
}
}
}