First cut at translating Android keys to Emulator keys

This commit is contained in:
Aaron Culliney 2015-02-28 21:48:08 -08:00
parent 1d6e9cd0d5
commit 2cb26b089f
5 changed files with 379 additions and 4 deletions

231
Android/jni/androidkeys.c Normal file
View File

@ -0,0 +1,231 @@
/*
* Apple // emulator for *nix
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include "common.h"
#include "androidkeys.h"
static inline bool _is_shifted(int metaState) {
return (metaState & META_SHIFT_MASK);
}
void android_keycode_to_emulator(int keyCode, int metaState, bool pressed) {
int key = -1;
bool isASCII = true;
do {
if ((keyCode >= KEYCODE_NUMPAD_0) && (keyCode <= KEYCODE_NUMPAD_9)) {
key = keyCode - ASCII_NUMPAD_0_OFFSET;
break;
} else if ((keyCode >= KEYCODE_A) && (keyCode <= KEYCODE_Z)) {
key = caps_lock || _is_shifted(metaState) ? (keyCode + ASCII_UCASE_OFFSET) : (keyCode + ASCII_LCASE_OFFSET);
break;
} else if ((keyCode >= KEYCODE_F1) && (keyCode <= KEYCODE_F12)) {
isASCII = false;
key = keyCode - FN_OFFSET;
break;
}
switch (keyCode) {
case KEYCODE_0:
key = _is_shifted(metaState) ? ')' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_1:
key = _is_shifted(metaState) ? '!' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_2:
key = _is_shifted(metaState) ? '@' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_3:
key = _is_shifted(metaState) ? '#' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_4:
key = _is_shifted(metaState) ? '$' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_5:
key = _is_shifted(metaState) ? '%' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_6:
key = _is_shifted(metaState) ? '^' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_7:
key = _is_shifted(metaState) ? '&' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_8:
key = _is_shifted(metaState) ? '*' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_9:
key = _is_shifted(metaState) ? '(' : keyCode + ASCII_0_OFFSET;
break;
case KEYCODE_APOSTROPHE:
key = _is_shifted(metaState) ? '"' : '\'';
break;
case KEYCODE_AT:
key = '@';
break;
case KEYCODE_BACKSLASH:
key = _is_shifted(metaState) ? '|' : '\\';
break;
case KEYCODE_COMMA:
key = _is_shifted(metaState) ? '<' : ',';
break;
case KEYCODE_EQUALS:
key = _is_shifted(metaState) ? '+' : '=';
break;
case KEYCODE_GRAVE:
key = _is_shifted(metaState) ? '~' : '`';
break;
case KEYCODE_LEFT_BRACKET:
key = _is_shifted(metaState) ? '{' : '[';
break;
case KEYCODE_MINUS:
key = _is_shifted(metaState) ? '_' : '-';
break;
case KEYCODE_NUMPAD_ADD:
key = '+';
break;
case KEYCODE_NUMPAD_COMMA:
key = ',';
break;
case KEYCODE_NUMPAD_DIVIDE:
key = '/';
break;
case KEYCODE_NUMPAD_DOT:
key = '.';
break;
case KEYCODE_NUMPAD_EQUALS:
key = '=';
break;
case KEYCODE_NUMPAD_LEFT_PAREN:
key = '(';
break;
case KEYCODE_NUMPAD_RIGHT_PAREN:
key = ')';
break;
case KEYCODE_NUMPAD_MULTIPLY:
key = '*';
break;
case KEYCODE_NUMPAD_SUBTRACT:
key = '-';
break;
case KEYCODE_PERIOD:
key = _is_shifted(metaState) ? '>' : '.';
break;
case KEYCODE_PLUS:
key = '+';
break;
case KEYCODE_POUND:
key = '#';
break;
case KEYCODE_RIGHT_BRACKET:
key = _is_shifted(metaState) ? '}' : ']';
break;
case KEYCODE_SEMICOLON:
key = _is_shifted(metaState) ? ':' : ';';
break;
case KEYCODE_SLASH:
key = _is_shifted(metaState) ? '?' : '/';
break;
case KEYCODE_SPACE:
key = ' ';
break;
case KEYCODE_STAR:
key = '*';
break;
default:
break;
}
if (key != -1) {
break;
}
// META
isASCII = false;
switch (keyCode) {
case KEYCODE_DPAD_LEFT:
key = SCODE_L;
break;
case KEYCODE_DPAD_RIGHT:
key = SCODE_R;
break;
case KEYCODE_DPAD_DOWN:
key = SCODE_D;
break;
case KEYCODE_DPAD_UP:
key = SCODE_U;
break;
case KEYCODE_DPAD_CENTER:
key = SCODE_HOME;
break;
case KEYCODE_PAGE_UP:
key = SCODE_PGUP;
break;
case KEYCODE_PAGE_DOWN:
key = SCODE_PGDN;
break;
case KEYCODE_INSERT:
key = SCODE_INS;
break;
case KEYCODE_SHIFT_LEFT:
key = SCODE_L_SHIFT;
break;
case KEYCODE_SHIFT_RIGHT:
key = SCODE_R_SHIFT;
break;
case KEYCODE_CTRL_LEFT:
key = SCODE_L_CTRL;
break;
case KEYCODE_CTRL_RIGHT:
key = SCODE_R_CTRL;
break;
case KEYCODE_ALT_LEFT:
case KEYCODE_META_LEFT:
key = SCODE_L_ALT;
break;
case KEYCODE_ALT_RIGHT:
case KEYCODE_META_RIGHT:
key = SCODE_R_ALT;
break;
case KEYCODE_BREAKPAUSE:
key = SCODE_BRK;
break;
case KEYCODE_CAPS_LOCK:
caps_lock = (metaState & META_CAPS_LOCK_ON);
return;
case KEYCODE_DEL:
key = SCODE_DEL;
break;
case KEYCODE_ENTER:
key = SCODE_RET;
break;
case KEYCODE_TAB:
key = SCODE_TAB;
break;
case KEYCODE_ESC:
key = SCODE_ESC;
break;
default:
break;
}
} while (0);
LOG("keyCode:%08x -> key:%02x ('%c') metaState:%08x", keyCode, key, key, metaState);
assert(key < 0x80);
c_keys_handle_input(key, pressed, isASCII);
}

113
Android/jni/androidkeys.h Normal file
View File

@ -0,0 +1,113 @@
/*
* Apple // emulator for *nix
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#define ASCII_UCASE_OFFSET 0x24
#define ASCII_LCASE_OFFSET 0x44
#define ASCII_0_OFFSET 0x29
#define ASCII_NUMPAD_0_OFFSET 0x60
#define FN_OFFSET 0x48
#define KEYCODE_0 0x07
#define KEYCODE_1 0x08
#define KEYCODE_2 0x09
#define KEYCODE_3 0x0a
#define KEYCODE_4 0x0b
#define KEYCODE_5 0x0c
#define KEYCODE_6 0x0d
#define KEYCODE_7 0x0e
#define KEYCODE_8 0x0f
#define KEYCODE_9 0x10
#define KEYCODE_A 0x1d
#define KEYCODE_Z 0x36
#define KEYCODE_APOSTROPHE 0x4b
#define KEYCODE_AT 0x4d
#define KEYCODE_BACKSLASH 0x49
#define KEYCODE_COMMA 0x37
#define KEYCODE_EQUALS 0x46
#define KEYCODE_GRAVE 0x44
#define KEYCODE_LEFT_BRACKET 0x47
#define KEYCODE_MINUS 0x45
#define KEYCODE_PERIOD 0x38
#define KEYCODE_PLUS 0x51
#define KEYCODE_POUND 0x12
#define KEYCODE_RIGHT_BRACKET 0x48
#define KEYCODE_SEMICOLON 0x4a
#define KEYCODE_SLASH 0x4c
#define KEYCODE_SPACE 0x3e
#define KEYCODE_STAR 0x11
// numpad
#define KEYCODE_NUMPAD_0 0x90
#define KEYCODE_NUMPAD_9 0x99
#define KEYCODE_NUMPAD_ADD 0x9d
#define KEYCODE_NUMPAD_COMMA 0x9f
#define KEYCODE_NUMPAD_DIVIDE 0x9a
#define KEYCODE_NUMPAD_DOT 0x9e
#define KEYCODE_NUMPAD_EQUALS 0xa1
#define KEYCODE_NUMPAD_LEFT_PAREN 0xa2
#define KEYCODE_NUMPAD_RIGHT_PAREN 0xa3
#define KEYCODE_NUMPAD_MULTIPLY 0x9b
#define KEYCODE_NUMPAD_SUBTRACT 0x9c
// various meta keys
#define KEYCODE_ALT_LEFT 0x39
#define KEYCODE_ALT_RIGHT 0x3a
#define KEYCODE_BREAKPAUSE 0x79
#define KEYCODE_CAPS_LOCK 0x73
#define KEYCODE_CTRL_LEFT 0x71
#define KEYCODE_CTRL_RIGHT 0x72
#define KEYCODE_DEL 0x43
#define KEYCODE_ENTER 0x42
#define KEYCODE_ESC 0x6f
#define KEYCODE_INSERT 0x7c
#define KEYCODE_META_LEFT 0x75
#define KEYCODE_META_RIGHT 0x76
#define KEYCODE_PAGE_DOWN 0x5d
#define KEYCODE_PAGE_UP 0x5c
#define KEYCODE_SHIFT_LEFT 0x3b
#define KEYCODE_SHIFT_RIGHT 0x3c
#define KEYCODE_TAB 0x3d
// F1-F12
#define KEYCODE_F1 0x83
#define KEYCODE_F12 0x8e
// Directional pad movements
#define KEYCODE_DPAD_CENTER 0x17
#define KEYCODE_DPAD_DOWN 0x14
#define KEYCODE_DPAD_LEFT 0x15
#define KEYCODE_DPAD_RIGHT 0x16
#define KEYCODE_DPAD_UP 0x13
// Game pad buttons
#define KEYCODE_BUTTON_1 0xbc
#define KEYCODE_BUTTON_16 0xcb
#define KEYCODE_BUTTON_A 0x60
#define KEYCODE_BUTTON_B 0x61
#define KEYCODE_BUTTON_C 0x62
#define KEYCODE_BUTTON_L1 0x66
#define KEYCODE_BUTTON_L2 0x68
#define KEYCODE_BUTTON_R1 0x67
#define KEYCODE_BUTTON_R2 0x69
#define META_ALT_LEFT_ON 0x00000010
#define META_ALT_RIGHT_ON 0x00000020
#define META_CAPS_LOCK_ON 0x00100000
#define META_CTRL_LEFT_ON 0x00002000
#define META_CTRL_RIGHT_ON 0x00004000
#define META_SHIFT_MASK 0x000000c1
#define META_SHIFT_ON 0x00000040
#define META_SHIFT_LEFT_ON 0x00000040
#define META_SHIFT_RIGHT_ON 0x00000080
void android_keycode_to_emulator(int keyCode, int metaState, bool pressed);

View File

@ -4,14 +4,14 @@ include $(CLEAR_VARS)
PACKAGE_IDENTIFIER := "org.deadc0de.apple2" PACKAGE_IDENTIFIER := "org.deadc0de.apple2"
PACKAGE_NAME := "apple2ix" PACKAGE_NAME := "apple2ix"
COMMON_SOURCES_MK := sources.mk COMMON_SOURCES_MK := $(LOCAL_PATH)/sources.mk
include $(COMMON_SOURCES_MK) include $(COMMON_SOURCES_MK)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Android build config # Android build config
LOCAL_MODULE := libapple2ix LOCAL_MODULE := libapple2ix
LOCAL_SRC_FILES := jnihooks.c LOCAL_SRC_FILES := jnihooks.c androidkeys.c
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DHEADLESS=0 LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DHEADLESS=0
LOCAL_LDLIBS := -llog -landroid -lGLESv2 -lz LOCAL_LDLIBS := -llog -landroid -lGLESv2 -lz

View File

@ -12,6 +12,7 @@
#include <jni.h> #include <jni.h>
#include "common.h" #include "common.h"
#include "video/renderer.h" #include "video/renderer.h"
#include "androidkeys.h"
void Java_org_deadc0de_apple2_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir) { void Java_org_deadc0de_apple2_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir) {
const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0); const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0);
@ -24,8 +25,8 @@ void Java_org_deadc0de_apple2_Apple2Activity_nativeGraphicsInitialized(JNIEnv *e
LOG("%s", "native graphicsInitialized..."); LOG("%s", "native graphicsInitialized...");
video_driver_reshape(width, height); video_driver_reshape(width, height);
#if !TESTING #if !TESTING
#warning FIXME TODO ... c_initialize_firsttime();
// TODO ... pthread_create(&cpu_thread_id, NULL, (void *) &cpu_thread, (void *)NULL);
#else #else
char *local_argv[] = { char *local_argv[] = {
"-f", "-f",
@ -81,6 +82,20 @@ void Java_org_deadc0de_apple2_Apple2Activity_nativeRender(JNIEnv *env, jobject o
} }
#endif #endif
extern volatile bool _vid_dirty;
_vid_dirty = true;
video_driver_render(); video_driver_render();
} }
void Java_org_deadc0de_apple2_Apple2Activity_nativeOnKeyDown(JNIEnv *env, jobject obj, jint keyCode, jint metaState) {
#if !TESTING
android_keycode_to_emulator(keyCode, metaState, true);
#endif
}
void Java_org_deadc0de_apple2_Apple2Activity_nativeOnKeyUp(JNIEnv *env, jobject obj, jint keyCode, jint metaState) {
#if !TESTING
android_keycode_to_emulator(keyCode, metaState, false);
#endif
}

View File

@ -19,6 +19,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@ -44,6 +45,8 @@ public class Apple2Activity extends Activity {
private native void nativeOnPause(); private native void nativeOnPause();
public native void nativeGraphicsInitialized(int width, int height); public native void nativeGraphicsInitialized(int width, int height);
public native void nativeRender(); public native void nativeRender();
private native void nativeOnKeyDown(int keyCode, int metaState);
private native void nativeOnKeyUp(int keyCode, int metaState);
// HACK NOTE 2015/02/22 : Apparently native code cannot easily access stuff in the APK ... so copy various resources // HACK NOTE 2015/02/22 : Apparently native code cannot easily access stuff in the APK ... so copy various resources
// out of the APK and into the /data/data/... for ease of access. Because this is FOSS software we don't care about // out of the APK and into the /data/data/... for ease of access. Because this is FOSS software we don't care about
@ -145,4 +148,17 @@ public class Apple2Activity extends Activity {
mView.onPause(); mView.onPause();
nativeOnPause(); nativeOnPause();
} }
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
nativeOnKeyDown(keyCode, event.getMetaState());
return true;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
nativeOnKeyUp(keyCode, event.getMetaState());
return true;
}
} }