Compare commits
199 Commits
android-1.
...
android-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7eb467f4f | ||
|
|
0c77e4a659 | ||
|
|
e1adc07db0 | ||
|
|
144086c667 | ||
|
|
b2824e9145 | ||
|
|
a64941694f | ||
|
|
9bbfca3193 | ||
|
|
18c02d3673 | ||
|
|
659a338d26 | ||
|
|
4436b9b7ca | ||
|
|
3089b98a30 | ||
|
|
94882c48bc | ||
|
|
f7cb3da434 | ||
|
|
281fccb73b | ||
|
|
086f7d0da2 | ||
|
|
c5256dde85 | ||
|
|
1b2c6fff83 | ||
|
|
5f21ef14a4 | ||
|
|
4de4fa6685 | ||
|
|
680fbea853 | ||
|
|
29e6dcde2f | ||
|
|
0fee86bc3c | ||
|
|
b6a9f667ef | ||
|
|
7008d21fcf | ||
|
|
f05ce4d247 | ||
|
|
6445546ff9 | ||
|
|
672d824946 | ||
|
|
4d89d173f4 | ||
|
|
86064cf1c6 | ||
|
|
b60a697b86 | ||
|
|
3cea55cc40 | ||
|
|
f722725992 | ||
|
|
28875b5e76 | ||
|
|
a3040dfb05 | ||
|
|
d23b0593fb | ||
|
|
97700bbff6 | ||
|
|
b9a6f0060d | ||
|
|
4522fa98ac | ||
|
|
bf341731f0 | ||
|
|
b04e7760c2 | ||
|
|
f984bfc5b0 | ||
|
|
b251e122e2 | ||
|
|
4d1224ce29 | ||
|
|
746dcb2e3d | ||
|
|
5d86735a69 | ||
|
|
f4258ade45 | ||
|
|
40129d9a14 | ||
|
|
e7e6af1335 | ||
|
|
97f52ef2ff | ||
|
|
5737e89150 | ||
|
|
6af1309e2d | ||
|
|
042edd8bab | ||
|
|
0b7f3a75b5 | ||
|
|
0bb0df0960 | ||
|
|
64338d30c3 | ||
|
|
bda8efeb45 | ||
|
|
5a2529651c | ||
|
|
08a6d99334 | ||
|
|
c89ee87bd4 | ||
|
|
d8fc04ec2e | ||
|
|
42feeb1bd3 | ||
|
|
c2014e2cde | ||
|
|
29282dcac6 | ||
|
|
9219fa7053 | ||
|
|
2ec88ad433 | ||
|
|
691dbd5ac2 | ||
|
|
8b3f288018 | ||
|
|
7ca679350d | ||
|
|
b59672815f | ||
|
|
904d89aff8 | ||
|
|
39c654ae9d | ||
|
|
b1cbe44a05 | ||
|
|
f5bbda4c6e | ||
|
|
a54a69efcc | ||
|
|
abae59767c | ||
|
|
fce1f010b0 | ||
|
|
20278ca91e | ||
|
|
b996083a42 | ||
|
|
3e777477e2 | ||
|
|
4d9eda4862 | ||
|
|
4deedb2215 | ||
|
|
bf3ef3ae18 | ||
|
|
9fd288c0b9 | ||
|
|
abe1346051 | ||
|
|
145b6a6cef | ||
|
|
22b1bc9ad8 | ||
|
|
2f7f7bd359 | ||
|
|
7dd0f0b3cf | ||
|
|
3ff877d80c | ||
|
|
13de08f8cb | ||
|
|
1d248c5e22 | ||
|
|
e5e2f98835 | ||
|
|
1e573c34ad | ||
|
|
e165da72fc | ||
|
|
1c50d12963 | ||
|
|
d69b416c58 | ||
|
|
a1fbc63f98 | ||
|
|
c7c209907b | ||
|
|
5bd7ff2fe1 | ||
|
|
72fb577166 | ||
|
|
69b096ec14 | ||
|
|
f872e0c05c | ||
|
|
5211722d63 | ||
|
|
785577e252 | ||
|
|
3a20c96296 | ||
|
|
2c8284d41f | ||
|
|
9e5274ee18 | ||
|
|
26e452c3a3 | ||
|
|
870a24ced6 | ||
|
|
2dbd77e344 | ||
|
|
699746a743 | ||
|
|
74e97ccc97 | ||
|
|
1f0021667b | ||
|
|
836044c80b | ||
|
|
341885e233 | ||
|
|
87761df512 | ||
|
|
f34cf4c384 | ||
|
|
2a51a62127 | ||
|
|
b32a97b6fc | ||
|
|
6cef33b501 | ||
|
|
ac78e00afa | ||
|
|
b1b55006be | ||
|
|
a761c11382 | ||
|
|
d819220a07 | ||
|
|
22914de79c | ||
|
|
cdb0f7b06b | ||
|
|
edf42b81f9 | ||
|
|
0aed046b5e | ||
|
|
ef1963a175 | ||
|
|
651ac246e3 | ||
|
|
05cb322feb | ||
|
|
0f98a34e06 | ||
|
|
1147ce7cd7 | ||
|
|
02147f3d9a | ||
|
|
791bb91843 | ||
|
|
b48cfa2084 | ||
|
|
d96db51bd2 | ||
|
|
2e100c9b67 | ||
|
|
ad7902b41f | ||
|
|
943b8842f7 | ||
|
|
74c951f64f | ||
|
|
05698c6a5e | ||
|
|
c7250d860f | ||
|
|
0d74d21608 | ||
|
|
e1629095b6 | ||
|
|
5a9770829e | ||
|
|
ff204a4300 | ||
|
|
12b2103a56 | ||
|
|
b9d6d38b17 | ||
|
|
46c286719f | ||
|
|
c35122beb6 | ||
|
|
ee83ecb52c | ||
|
|
29fd1f5025 | ||
|
|
33160be9ac | ||
|
|
0aacdfa9e5 | ||
|
|
a61fd339a6 | ||
|
|
dc1845afe9 | ||
|
|
a41dc46eee | ||
|
|
ad5a6e8061 | ||
|
|
e4c669f016 | ||
|
|
3bdbe50f0f | ||
|
|
0cefd912b5 | ||
|
|
456f9a14e4 | ||
|
|
f06257b2c5 | ||
|
|
7a8c4dda63 | ||
|
|
63b6e0a29a | ||
|
|
f423c2dbe6 | ||
|
|
dd7727f757 | ||
|
|
e9bae19e9e | ||
|
|
bc96417091 | ||
|
|
fb4d6f466b | ||
|
|
a6ac111707 | ||
|
|
d0319bd2ff | ||
|
|
9b56050c1e | ||
|
|
871762975a | ||
|
|
ce974177b2 | ||
|
|
b524b5a068 | ||
|
|
646d64cd92 | ||
|
|
6de1cae478 | ||
|
|
4999471ade | ||
|
|
933e99c927 | ||
|
|
9a2044f75e | ||
|
|
3d634004cf | ||
|
|
bf54615198 | ||
|
|
521d1daccf | ||
|
|
cbe8a734d0 | ||
|
|
6c959a030c | ||
|
|
acdc8da64f | ||
|
|
e52f753bf3 | ||
|
|
d4adabda93 | ||
|
|
20f79dc5eb | ||
|
|
84fe0dd479 | ||
|
|
5c4ab06612 | ||
|
|
dcd77a4650 | ||
|
|
916a54fb4b | ||
|
|
616428a03f | ||
|
|
38dce3e212 | ||
|
|
844d8b815b | ||
|
|
997461318f |
1
Android/.idea/compiler.xml
generated
@@ -11,7 +11,6 @@
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
<entry name="!?*.aj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
|
||||
49
Android/.idea/misc.xml
generated
@@ -27,6 +27,25 @@
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectInspectionProfilesVisibleTreeState">
|
||||
<entry key="Project Default">
|
||||
<profile-state>
|
||||
<expanded-state>
|
||||
<State>
|
||||
<id />
|
||||
</State>
|
||||
<State>
|
||||
<id>Spelling</id>
|
||||
</State>
|
||||
</expanded-state>
|
||||
<selected-state>
|
||||
<State>
|
||||
<id>Spelling</id>
|
||||
</State>
|
||||
</selected-state>
|
||||
</profile-state>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
@@ -37,10 +56,38 @@
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="Copyright.UI">
|
||||
<settings>
|
||||
<last-edited>deadc0de.org</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
<state key="ProjectJDKs.UI">
|
||||
<settings>
|
||||
<last-edited>Android API 21 Platform</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
||||
@@ -27,8 +27,8 @@ android {
|
||||
applicationId "org.deadc0de.apple2ix.basic"
|
||||
minSdkVersion 10
|
||||
targetSdkVersion 23
|
||||
versionCode 3
|
||||
versionName "1.0.0"
|
||||
versionCode 15
|
||||
versionName "1.1.5"
|
||||
ndk {
|
||||
moduleName "apple2ix"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.inputmanagercompat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public interface InputManagerCompat {
|
||||
/**
|
||||
* Gets information about the input device with the specified id.
|
||||
*
|
||||
* @param id The device id
|
||||
* @return The input device or null if not found
|
||||
*/
|
||||
public InputDevice getInputDevice(int id);
|
||||
|
||||
/**
|
||||
* Gets the ids of all input devices in the system.
|
||||
*
|
||||
* @return The input device ids.
|
||||
*/
|
||||
public int[] getInputDeviceIds();
|
||||
|
||||
/**
|
||||
* Registers an input device listener to receive notifications about when
|
||||
* input devices are added, removed or changed.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
* @param handler The handler on which the listener should be invoked, or
|
||||
* null if the listener should be invoked on the calling thread's
|
||||
* looper.
|
||||
*/
|
||||
public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
|
||||
Handler handler);
|
||||
|
||||
/**
|
||||
* Unregisters an input device listener.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*/
|
||||
public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
|
||||
|
||||
/*
|
||||
* The following three calls are to simulate V16 behavior on pre-Jellybean
|
||||
* devices. If you don't call them, your callback will never be called
|
||||
* pre-API 16.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pass the motion events to the InputManagerCompat. This is used to
|
||||
* optimize for polling for controllers. If you do not pass these events in,
|
||||
* polling will cause regular object creation.
|
||||
*
|
||||
* @param event the motion event from the app
|
||||
*/
|
||||
public void onGenericMotionEvent(MotionEvent event);
|
||||
|
||||
/**
|
||||
* Tell the V9 input manager that it should stop polling for disconnected
|
||||
* devices. You can call this during onPause in your activity, although you
|
||||
* might want to call it whenever your game is not active (or whenever you
|
||||
* don't care about being notified of new input devices)
|
||||
*/
|
||||
public void onPause();
|
||||
|
||||
/**
|
||||
* Tell the V9 input manager that it should start polling for disconnected
|
||||
* devices. You can call this during onResume in your activity, although you
|
||||
* might want to call it less often (only when the gameplay is actually
|
||||
* active)
|
||||
*/
|
||||
public void onResume();
|
||||
|
||||
public interface InputDeviceListener {
|
||||
/**
|
||||
* Called whenever the input manager detects that a device has been
|
||||
* added. This will only be called in the V9 version when a motion event
|
||||
* is detected.
|
||||
*
|
||||
* @param deviceId The id of the input device that was added.
|
||||
*/
|
||||
void onInputDeviceAdded(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever the properties of an input device have changed since
|
||||
* they were last queried. This will not be called for the V9 version of
|
||||
* the API.
|
||||
*
|
||||
* @param deviceId The id of the input device that changed.
|
||||
*/
|
||||
void onInputDeviceChanged(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever the input manager detects that a device has been
|
||||
* removed. For the V9 version, this can take some time depending on the
|
||||
* poll rate.
|
||||
*
|
||||
* @param deviceId The id of the input device that was removed.
|
||||
*/
|
||||
void onInputDeviceRemoved(int deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to construct a compatible InputManager.
|
||||
*/
|
||||
public static class Factory {
|
||||
|
||||
/**
|
||||
* Constructs and returns a compatible InputManger
|
||||
*
|
||||
* @param context the Context that will be used to get the system
|
||||
* service from
|
||||
* @return a compatible implementation of InputManager
|
||||
*/
|
||||
public static InputManagerCompat getInputManager(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
return new InputManagerV16(context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.inputmanagercompat;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public class InputManagerV16 implements InputManagerCompat {
|
||||
|
||||
private final InputManager mInputManager;
|
||||
private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
|
||||
|
||||
public InputManagerV16(Context context) {
|
||||
mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
|
||||
mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputDevice getInputDevice(int id) {
|
||||
return mInputManager.getInputDevice(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInputDeviceIds() {
|
||||
return mInputManager.getInputDeviceIds();
|
||||
}
|
||||
|
||||
static class V16InputDeviceListener implements InputManager.InputDeviceListener {
|
||||
final InputManagerCompat.InputDeviceListener mIDL;
|
||||
|
||||
public V16InputDeviceListener(InputDeviceListener idl) {
|
||||
mIDL = idl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int deviceId) {
|
||||
mIDL.onInputDeviceAdded(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
mIDL.onInputDeviceChanged(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
mIDL.onInputDeviceRemoved(deviceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||
V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
|
||||
mInputManager.registerInputDeviceListener(v16Listener, handler);
|
||||
mListeners.put(listener, v16Listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||
V16InputDeviceListener curListener = mListeners.remove(listener);
|
||||
if (null != curListener)
|
||||
{
|
||||
mInputManager.unregisterInputDeviceListener(curListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericMotionEvent(MotionEvent event) {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public abstract class Apple2AbstractMenu implements Apple2MenuView {
|
||||
setup();
|
||||
}
|
||||
|
||||
public synchronized void show() {
|
||||
public void show() {
|
||||
if (isShowing()) {
|
||||
return;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public abstract class Apple2AbstractMenu implements Apple2MenuView {
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mSettingsView.isShown();
|
||||
return mSettingsView.getParent() != null;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
|
||||
@@ -11,26 +11,25 @@
|
||||
|
||||
package org.deadc0de.apple2ix;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.media.AudioManager;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -40,23 +39,20 @@ import org.deadc0de.apple2ix.basic.R;
|
||||
public class Apple2Activity extends Activity {
|
||||
|
||||
private final static String TAG = "Apple2Activity";
|
||||
private final static int MAX_FINGERS = 32;// HACK ...
|
||||
private static volatile boolean DEBUG_STRICT = false;
|
||||
|
||||
private Apple2View mView = null;
|
||||
private Runnable mGraphicsInitializedRunnable = null;
|
||||
private Apple2SplashScreen mSplashScreen = null;
|
||||
private Apple2MainMenu mMainMenu = null;
|
||||
private Apple2SettingsMenu mSettingsMenu = null;
|
||||
private Apple2DisksMenu mDisksMenu = null;
|
||||
|
||||
private ArrayList<Apple2MenuView> mMenuStack = new ArrayList<Apple2MenuView>();
|
||||
private ArrayList<AlertDialog> mAlertDialogs = new ArrayList<AlertDialog>();
|
||||
|
||||
private AtomicBoolean mPausing = new AtomicBoolean(false);
|
||||
|
||||
private int mWidth = 0;
|
||||
private int mHeight = 0;
|
||||
|
||||
private float[] mXCoords = new float[MAX_FINGERS];
|
||||
private float[] mYCoords = new float[MAX_FINGERS];
|
||||
|
||||
// non-null if we failed to load/link the native code ... likely we are running on some bizarre 'droid variant
|
||||
private static Throwable sNativeBarfedThrowable = null;
|
||||
private static boolean sNativeBarfed = false;
|
||||
@@ -70,50 +66,33 @@ public class Apple2Activity extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
public final static long NATIVE_TOUCH_HANDLED = (1 << 0);
|
||||
public final static long NATIVE_TOUCH_REQUEST_SHOW_MENU = (1 << 1);
|
||||
public final static int REQUEST_PERMISSION_RWSTORE = 42;
|
||||
|
||||
public final static long NATIVE_TOUCH_KEY_TAP = (1 << 4);
|
||||
public final static long NATIVE_TOUCH_KBD = (1 << 5);
|
||||
public final static long NATIVE_TOUCH_JOY = (1 << 6);
|
||||
public final static long NATIVE_TOUCH_MENU = (1 << 7);
|
||||
public final static long NATIVE_TOUCH_JOY_KPAD = (1 << 8);
|
||||
private static native void nativeOnCreate(String dataDir, int sampleRate, int monoBufferSize, int stereoBufferSize);
|
||||
|
||||
public final static long NATIVE_TOUCH_INPUT_DEVICE_CHANGED = (1 << 16);
|
||||
public final static long NATIVE_TOUCH_CPU_SPEED_DEC = (1 << 17);
|
||||
public final static long NATIVE_TOUCH_CPU_SPEED_INC = (1 << 18);
|
||||
private static native void nativeOnKeyDown(int keyCode, int metaState);
|
||||
|
||||
public final static long NATIVE_TOUCH_ASCII_SCANCODE_SHIFT = 32;
|
||||
public final static long NATIVE_TOUCH_ASCII_SCANCODE_MASK = 0xFFFFL;
|
||||
public final static long NATIVE_TOUCH_ASCII_MASK = 0xFF00L;
|
||||
public final static long NATIVE_TOUCH_SCANCODE_MASK = 0x00FFL;
|
||||
private static native void nativeOnKeyUp(int keyCode, int metaState);
|
||||
|
||||
private native void nativeOnCreate(String dataDir, int sampleRate, int monoBufferSize, int stereoBufferSize);
|
||||
private static native void nativeSaveState(String path);
|
||||
|
||||
private native void nativeGraphicsInitialized(int width, int height);
|
||||
private static native String nativeLoadState(String path);
|
||||
|
||||
private native void nativeGraphicsChanged(int width, int height);
|
||||
private static native void nativeEmulationResume();
|
||||
|
||||
private native void nativeOnKeyDown(int keyCode, int metaState);
|
||||
private static native void nativeEmulationPause();
|
||||
|
||||
private native void nativeOnKeyUp(int keyCode, int metaState);
|
||||
private static native void nativeOnQuit();
|
||||
|
||||
private native void nativeOnResume(boolean isSystemResume);
|
||||
private static native void nativeReboot();
|
||||
|
||||
public native void nativeOnPause(boolean isSystemPause);
|
||||
private static native void nativeChooseDisk(String path, boolean driveA, boolean readOnly);
|
||||
|
||||
public native void nativeOnQuit();
|
||||
|
||||
public native long nativeOnTouch(int action, int pointerCount, int pointerIndex, float[] xCoords, float[] yCoords);
|
||||
|
||||
public native void nativeReboot();
|
||||
|
||||
public native void nativeRender();
|
||||
|
||||
public native void nativeChooseDisk(String path, boolean driveA, boolean readOnly);
|
||||
|
||||
public native void nativeEjectDisk(boolean driveA);
|
||||
private static native void nativeEjectDisk(boolean driveA);
|
||||
|
||||
public final static boolean isNativeBarfed() {
|
||||
return sNativeBarfed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -135,22 +114,17 @@ public class Apple2Activity extends Activity {
|
||||
|
||||
Log.e(TAG, "onCreate()");
|
||||
|
||||
// placeholder view on initial launch
|
||||
if (mView == null) {
|
||||
setContentView(new View(this));
|
||||
}
|
||||
|
||||
Apple2CrashHandler.getInstance().initializeAndSetCustomExceptionHandler(this);
|
||||
if (sNativeBarfed) {
|
||||
Log.e(TAG, "NATIVE BARFED...", sNativeBarfedThrowable);
|
||||
View view = new View(this);
|
||||
setContentView(view);
|
||||
return;
|
||||
}
|
||||
|
||||
// run first-time initializations
|
||||
if (!Apple2Preferences.FIRST_TIME_CONFIGURED.booleanValue(this)) {
|
||||
Apple2DisksMenu.firstTime(this);
|
||||
Apple2Preferences.KeypadPreset.IJKM_SPACE.apply(this);
|
||||
}
|
||||
Apple2Preferences.FIRST_TIME_CONFIGURED.saveBoolean(this, true);
|
||||
|
||||
// get device audio parameters for native OpenSLES
|
||||
int sampleRate = DevicePropertyCalculator.getRecommendedSampleRate(this);
|
||||
int monoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(this, /*isStereo:*/false);
|
||||
int stereoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(this, /*isStereo:*/true);
|
||||
@@ -159,31 +133,97 @@ public class Apple2Activity extends Activity {
|
||||
String dataDir = Apple2DisksMenu.getDataDir(this);
|
||||
nativeOnCreate(dataDir, sampleRate, monoBufferSize, stereoBufferSize);
|
||||
|
||||
// NOTE: load preferences after nativeOnCreate ... native CPU thread should still be paused
|
||||
Apple2Preferences.loadPreferences(this);
|
||||
final boolean firstTime = (Apple2Preferences.EMULATOR_VERSION.intValue(this) != BuildConfig.VERSION_CODE);
|
||||
if (firstTime) {
|
||||
// allow for primitive migrations as needed
|
||||
Apple2Preferences.EMULATOR_VERSION.saveInt(this, BuildConfig.VERSION_CODE);
|
||||
Log.v(TAG, "Triggering migration to Apple2ix version : " + BuildConfig.VERSION_NAME);
|
||||
}
|
||||
|
||||
mView = new Apple2View(this);
|
||||
setContentView(mView);
|
||||
showSplashScreen(!firstTime);
|
||||
Apple2CrashHandler.getInstance().checkForCrashes(this);
|
||||
|
||||
// Another Android Annoyance ...
|
||||
// Even though we no longer use the system soft keyboard (which would definitely trigger width/height changes to our OpenGL canvas),
|
||||
// we still need to listen to dimension changes, because it seems on some janky devices you have an incorrect width/height set when
|
||||
// the initial OpenGL onSurfaceChanged() callback occurs. For now, include this defensive coding...
|
||||
mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
public void onGlobalLayout() {
|
||||
Rect rect = new Rect();
|
||||
mView.getWindowVisibleDisplayFrame(rect);
|
||||
int h = rect.height();
|
||||
int w = rect.width();
|
||||
if (w < h) {
|
||||
// assure landscape dimensions
|
||||
final int w_ = w;
|
||||
w = h;
|
||||
h = w_;
|
||||
}
|
||||
nativeGraphicsChanged(w, h);
|
||||
boolean extperm = true;
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// On Marshmallow+ specifically ask for permission to read/write storage
|
||||
String readPermission = Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
String writePermission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
int hasReadPermission = checkSelfPermission(readPermission);
|
||||
int hasWritePermission = checkSelfPermission(writePermission);
|
||||
ArrayList<String> permissions = new ArrayList<String>();
|
||||
if (hasReadPermission != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(readPermission);
|
||||
}
|
||||
});
|
||||
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
|
||||
permissions.add(writePermission);
|
||||
}
|
||||
if (!permissions.isEmpty()) {
|
||||
extperm = false;
|
||||
String[] params = permissions.toArray(new String[permissions.size()]);
|
||||
requestPermissions(params, REQUEST_PERMISSION_RWSTORE);
|
||||
}
|
||||
}
|
||||
|
||||
mGraphicsInitializedRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (firstTime) {
|
||||
Apple2Preferences.KeypadPreset.IJKM_SPACE.apply(Apple2Activity.this);
|
||||
}
|
||||
Apple2Preferences.loadPreferences(Apple2Activity.this);
|
||||
}
|
||||
};
|
||||
|
||||
// first-time initializations
|
||||
final boolean externalStoragePermission = extperm;
|
||||
if (firstTime) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Apple2DisksMenu.exposeAPKAssets(Apple2Activity.this);
|
||||
if (externalStoragePermission) {
|
||||
Apple2DisksMenu.exposeAPKAssetsToExternal(Apple2Activity.this);
|
||||
}
|
||||
mSplashScreen.setDismissable(true);
|
||||
Log.d(TAG, "Finished first time copying...");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
mSettingsMenu = new Apple2SettingsMenu(this);
|
||||
mDisksMenu = new Apple2DisksMenu(this);
|
||||
|
||||
Intent intent = getIntent();
|
||||
String path = null;
|
||||
if (intent != null) {
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
path = data.getPath();
|
||||
}
|
||||
}
|
||||
if (path != null && Apple2DisksMenu.hasDiskExtension(path)) {
|
||||
handleInsertDiskIntent(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
// We should already be gracefully handling the case where user denies access.
|
||||
if (requestCode == REQUEST_PERMISSION_RWSTORE) {
|
||||
boolean grantedPermissions = true;
|
||||
for (int grant : grantResults) {
|
||||
if (grant == PackageManager.PERMISSION_DENIED) {
|
||||
grantedPermissions = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (grantedPermissions) {
|
||||
// this will force copying APK files (now that we have permission
|
||||
Apple2DisksMenu.exposeAPKAssetsToExternal(Apple2Activity.this);
|
||||
} // else ... we keep nagging on app startup ...
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -195,8 +235,8 @@ public class Apple2Activity extends Activity {
|
||||
}
|
||||
|
||||
Log.d(TAG, "onResume()");
|
||||
mView.onResume();
|
||||
nativeOnResume(/*isSystemResume:*/true);
|
||||
showSplashScreen(/*dismissable:*/true);
|
||||
Apple2CrashHandler.getInstance().checkForCrashes(this); // NOTE : needs to be called again to clean-up
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,13 +252,15 @@ public class Apple2Activity extends Activity {
|
||||
}
|
||||
|
||||
Log.d(TAG, "onPause()");
|
||||
mView.onPause();
|
||||
if (mView != null) {
|
||||
mView.onPause();
|
||||
}
|
||||
|
||||
// Apparently not good to leave popup/dialog windows showing when backgrounding.
|
||||
// Dismiss these popups to avoid android.view.WindowLeaked issues
|
||||
synchronized (this) {
|
||||
dismissAllMenus();
|
||||
nativeOnPause(true);
|
||||
nativeEmulationPause();
|
||||
}
|
||||
|
||||
mPausing.set(false);
|
||||
@@ -226,21 +268,23 @@ public class Apple2Activity extends Activity {
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (sNativeBarfed) {
|
||||
return true;
|
||||
if (Apple2Activity.isNativeBarfed()) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) || (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) || (keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
|
||||
return false;
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
nativeOnKeyDown(keyCode, event.getMetaState());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (sNativeBarfed) {
|
||||
return true;
|
||||
if (Apple2Activity.isNativeBarfed()) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
Apple2MenuView apple2MenuView = peekApple2View();
|
||||
if (apple2MenuView == null) {
|
||||
@@ -253,185 +297,16 @@ public class Apple2Activity extends Activity {
|
||||
showMainMenu();
|
||||
return true;
|
||||
} else if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) || (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) || (keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
|
||||
return false;
|
||||
} else {
|
||||
nativeOnKeyUp(keyCode, event.getMetaState());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private String actionToString(int action) {
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
return "CANCEL:" + action;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
return "DOWN:" + action;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
return "MOVE:" + action;
|
||||
case MotionEvent.ACTION_UP:
|
||||
return "UP:" + action;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
return "PDOWN:" + action;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
return "PUP:" + action;
|
||||
default:
|
||||
return "UNK:" + action;
|
||||
}
|
||||
}
|
||||
|
||||
private void printSamples(MotionEvent ev) {
|
||||
final int historySize = ev.getHistorySize();
|
||||
final int pointerCount = ev.getPointerCount();
|
||||
|
||||
for (int h = 0; h < historySize; h++) {
|
||||
Log.d(TAG, "Event "+ev.getAction().toString()+" at historical time "+ev.getHistoricalEventTime(h)+" :");
|
||||
for (int p = 0; p < pointerCount; p++) {
|
||||
Log.d(TAG, " pointer "+ev.getPointerId(p)+": ("+ev.getHistoricalX(p, h)+","+ev.getHistoricalY(p, h)+")");
|
||||
}
|
||||
}
|
||||
int pointerIndex = ev.getActionIndex();
|
||||
|
||||
Log.d(TAG, "Event " + actionToString(ev.getActionMasked()) + " for " + pointerIndex + " at time " + ev.getEventTime() + " :");
|
||||
for (int p = 0; p < pointerCount; p++) {
|
||||
Log.d(TAG, " pointer " + ev.getPointerId(p) + ": (" + ev.getX(p) + "," + ev.getY(p) + ")");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
do {
|
||||
|
||||
if (sNativeBarfed) {
|
||||
break;
|
||||
}
|
||||
if (mMainMenu == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
Apple2MenuView apple2MenuView = peekApple2View();
|
||||
if ((apple2MenuView != null) && (!apple2MenuView.isCalibrating())) {
|
||||
break;
|
||||
}
|
||||
|
||||
//printSamples(event);
|
||||
int action = event.getActionMasked();
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int pointerCount = event.getPointerCount();
|
||||
for (int i = 0; i < pointerCount/* && i < MAX_FINGERS */; i++) {
|
||||
mXCoords[i] = event.getX(i);
|
||||
mYCoords[i] = event.getY(i);
|
||||
}
|
||||
|
||||
long nativeFlags = nativeOnTouch(action, pointerCount, pointerIndex, mXCoords, mYCoords);
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_HANDLED) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_REQUEST_SHOW_MENU) != 0) {
|
||||
mMainMenu.show();
|
||||
}
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_KEY_TAP) != 0) {
|
||||
if (Apple2Preferences.KEYBOARD_CLICK_ENABLED.booleanValue(this)) {
|
||||
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
|
||||
if (am != null) {
|
||||
am.playSoundEffect(AudioManager.FX_KEY_CLICK);
|
||||
}
|
||||
}
|
||||
|
||||
if ((apple2MenuView != null) && apple2MenuView.isCalibrating()) {
|
||||
long asciiScancodeLong = nativeFlags & (NATIVE_TOUCH_ASCII_SCANCODE_MASK << NATIVE_TOUCH_ASCII_SCANCODE_SHIFT);
|
||||
int asciiInt = (int) (asciiScancodeLong >> (NATIVE_TOUCH_ASCII_SCANCODE_SHIFT + 8));
|
||||
int scancode = (int) ((asciiScancodeLong >> NATIVE_TOUCH_ASCII_SCANCODE_SHIFT) & 0xFFL);
|
||||
char ascii = (char) asciiInt;
|
||||
apple2MenuView.onKeyTapCalibrationEvent(ascii, scancode);
|
||||
}
|
||||
}
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_MENU) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// handle menu-specific actions
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_INPUT_DEVICE_CHANGED) != 0) {
|
||||
Apple2Preferences.TouchDeviceVariant nextVariant;
|
||||
if ((nativeFlags & NATIVE_TOUCH_KBD) != 0) {
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.KEYBOARD;
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_JOY) != 0) {
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.JOYSTICK;
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_JOY_KPAD) != 0) {
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.JOYSTICK_KEYPAD;
|
||||
} else {
|
||||
int touchDevice = Apple2Preferences.nativeGetCurrentTouchDevice();
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.next(touchDevice);
|
||||
}
|
||||
Apple2Preferences.CURRENT_TOUCH_DEVICE.saveTouchDevice(this, nextVariant);
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_CPU_SPEED_DEC) != 0) {
|
||||
int percentSpeed = Apple2Preferences.nativeGetCPUSpeed();
|
||||
if (percentSpeed > 400) { // HACK: max value from native side
|
||||
percentSpeed = 375;
|
||||
} else if (percentSpeed > 100) {
|
||||
percentSpeed -= 25;
|
||||
} else {
|
||||
percentSpeed -= 5;
|
||||
}
|
||||
Apple2Preferences.CPU_SPEED_PERCENT.saveInt(this, percentSpeed);
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_CPU_SPEED_INC) != 0) {
|
||||
int percentSpeed = Apple2Preferences.nativeGetCPUSpeed();
|
||||
if (percentSpeed >= 100) {
|
||||
percentSpeed += 25;
|
||||
} else {
|
||||
percentSpeed += 5;
|
||||
}
|
||||
Apple2Preferences.CPU_SPEED_PERCENT.saveInt(this, percentSpeed);
|
||||
}
|
||||
} while (false);
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
void graphicsInitialized(int w, int h) {
|
||||
if (mMainMenu == null) {
|
||||
mMainMenu = new Apple2MainMenu(this, mView);
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
if (w < h) {
|
||||
// assure landscape dimensions
|
||||
final int w_ = w;
|
||||
w = h;
|
||||
h = w_;
|
||||
}
|
||||
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
|
||||
// tell native about this...
|
||||
nativeGraphicsInitialized(w, h);
|
||||
|
||||
showSplashScreen();
|
||||
|
||||
Intent intent = getIntent();
|
||||
String path = null;
|
||||
if (intent != null) {
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
path = data.getPath();
|
||||
}
|
||||
}
|
||||
if (path != null && Apple2DisksMenu.hasDiskExtension(path)) {
|
||||
handleInsertDiskIntent(path);
|
||||
}
|
||||
nativeOnKeyUp(keyCode, event.getMetaState());
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showMainMenu() {
|
||||
if (mMainMenu != null) {
|
||||
Apple2SettingsMenu settingsMenu = mMainMenu.getSettingsMenu();
|
||||
Apple2DisksMenu disksMenu = mMainMenu.getDisksMenu();
|
||||
if (!(settingsMenu.isShowing() || disksMenu.isShowing())) {
|
||||
if (!(mSettingsMenu.isShowing() || mDisksMenu.isShowing())) {
|
||||
mMainMenu.show();
|
||||
}
|
||||
}
|
||||
@@ -441,6 +316,14 @@ public class Apple2Activity extends Activity {
|
||||
return mMainMenu;
|
||||
}
|
||||
|
||||
public synchronized Apple2DisksMenu getDisksMenu() {
|
||||
return mDisksMenu;
|
||||
}
|
||||
|
||||
public synchronized Apple2SettingsMenu getSettingsMenu() {
|
||||
return mSettingsMenu;
|
||||
}
|
||||
|
||||
private void handleInsertDiskIntent(final String path) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -464,15 +347,17 @@ public class Apple2Activity extends Activity {
|
||||
}
|
||||
Apple2Preferences.CURRENT_DISK_A.saveString(Apple2Activity.this, diskPath);
|
||||
|
||||
Apple2DisksMenu disksMenu = mMainMenu.getDisksMenu();
|
||||
while (disksMenu.popPathStack() != null) {
|
||||
while (mDisksMenu.popPathStack() != null) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
String storageDir = Apple2DisksMenu.getExternalStorageDirectory().getAbsolutePath();
|
||||
if (diskPath.contains(storageDir)) {
|
||||
diskPath = diskPath.replace(storageDir + File.separator, "");
|
||||
disksMenu.pushPathStack(storageDir);
|
||||
File storageDir = Apple2DisksMenu.getExternalStorageDirectory(Apple2Activity.this);
|
||||
if (storageDir != null) {
|
||||
String storagePath = storageDir.getAbsolutePath();
|
||||
if (diskPath.contains(storagePath)) {
|
||||
diskPath = diskPath.replace(storagePath + File.separator, "");
|
||||
mDisksMenu.pushPathStack(storagePath);
|
||||
}
|
||||
}
|
||||
StringTokenizer tokenizer = new StringTokenizer(diskPath, File.separator);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
@@ -483,7 +368,7 @@ public class Apple2Activity extends Activity {
|
||||
if (Apple2DisksMenu.hasDiskExtension(token)) {
|
||||
continue;
|
||||
}
|
||||
disksMenu.pushPathStack(token);
|
||||
mDisksMenu.pushPathStack(token);
|
||||
}
|
||||
|
||||
Toast.makeText(Apple2Activity.this, Apple2Activity.this.getString(R.string.disk_insert_toast), Toast.LENGTH_SHORT).show();
|
||||
@@ -492,22 +377,34 @@ public class Apple2Activity extends Activity {
|
||||
});
|
||||
}
|
||||
|
||||
private void showSplashScreen() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (Apple2Activity.this) {
|
||||
if (mSplashScreen == null) {
|
||||
mSplashScreen = new Apple2SplashScreen(Apple2Activity.this);
|
||||
}
|
||||
if (mSplashScreen.isShowing()) {
|
||||
return;
|
||||
}
|
||||
mSplashScreen.show();
|
||||
Apple2CrashHandler.getInstance().checkForCrashes(Apple2Activity.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
public Apple2SplashScreen getSplashScreen() {
|
||||
return mSplashScreen;
|
||||
}
|
||||
|
||||
private void showSplashScreen(boolean dismissable) {
|
||||
if (mSplashScreen != null) {
|
||||
return;
|
||||
}
|
||||
mSplashScreen = new Apple2SplashScreen(this, dismissable);
|
||||
mSplashScreen.show();
|
||||
}
|
||||
|
||||
private void setupGLView() {
|
||||
|
||||
boolean glViewFirstTime = false;
|
||||
if (mView == null) {
|
||||
glViewFirstTime = true;
|
||||
mView = new Apple2View(this, mGraphicsInitializedRunnable);
|
||||
mGraphicsInitializedRunnable = null;
|
||||
mMainMenu = new Apple2MainMenu(this, mView);
|
||||
}
|
||||
|
||||
if (glViewFirstTime) {
|
||||
// HACK NOTE : do not blanket setContentView() ... it appears to wedge Gingerbread
|
||||
setContentView(mView);
|
||||
} else {
|
||||
mView.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerAndShowDialog(AlertDialog dialog) {
|
||||
@@ -516,21 +413,11 @@ public class Apple2Activity extends Activity {
|
||||
}
|
||||
|
||||
public synchronized void pushApple2View(Apple2MenuView apple2MenuView) {
|
||||
//
|
||||
mMenuStack.add(apple2MenuView);
|
||||
View menuView = apple2MenuView.getView();
|
||||
nativeOnPause(false);
|
||||
addContentView(menuView, new FrameLayout.LayoutParams(getWidth(), getHeight()));
|
||||
}
|
||||
|
||||
public synchronized Apple2MenuView popApple2View() {
|
||||
int lastIndex = mMenuStack.size() - 1;
|
||||
if (lastIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Apple2MenuView apple2MenuView = mMenuStack.remove(lastIndex);
|
||||
_disposeApple2View(apple2MenuView);
|
||||
return apple2MenuView;
|
||||
nativeEmulationPause();
|
||||
addContentView(menuView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
}
|
||||
|
||||
public synchronized Apple2MenuView peekApple2View() {
|
||||
@@ -566,13 +453,11 @@ public class Apple2Activity extends Activity {
|
||||
mAlertDialogs.clear();
|
||||
|
||||
// Get rid of the menu hierarchy
|
||||
Apple2MenuView apple2MenuView;
|
||||
do {
|
||||
apple2MenuView = popApple2View();
|
||||
if (apple2MenuView != null) {
|
||||
apple2MenuView.dismissAll();
|
||||
}
|
||||
} while (apple2MenuView != null);
|
||||
ArrayList<Apple2MenuView> menuHierarchy = new ArrayList<Apple2MenuView>(mMenuStack);
|
||||
Collections.reverse(menuHierarchy);
|
||||
for (Apple2MenuView view : menuHierarchy) {
|
||||
view.dismissAll();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Apple2MenuView popApple2View(Apple2MenuView apple2MenuView) {
|
||||
@@ -583,73 +468,83 @@ public class Apple2Activity extends Activity {
|
||||
|
||||
private void _disposeApple2View(Apple2MenuView apple2MenuView) {
|
||||
|
||||
boolean dismissedSplashScreen = false;
|
||||
|
||||
// Actually remove View from view hierarchy
|
||||
{
|
||||
View menuView = apple2MenuView.getView();
|
||||
if (menuView.isShown()) {
|
||||
((ViewGroup) menuView.getParent()).removeView(menuView);
|
||||
ViewGroup viewGroup = (ViewGroup) menuView.getParent();
|
||||
if (viewGroup != null) {
|
||||
viewGroup.removeView(menuView);
|
||||
}
|
||||
if (apple2MenuView instanceof Apple2SplashScreen) { // 20151101 HACK NOTE : use instanceof to avoid edge case where joystick calibration occurred (and thus the splash was already dismissed without proper mView initialization)
|
||||
mSplashScreen = null;
|
||||
dismissedSplashScreen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if no more views on menu stack, resume emulation
|
||||
if (mMenuStack.size() == 0) {
|
||||
dismissAllMenus();
|
||||
}
|
||||
if (mMenuStack.size() == 0 && !mPausing.get()) {
|
||||
nativeOnResume(/*isSystemResume:*/false);
|
||||
}
|
||||
}
|
||||
|
||||
void _mainMenuDismissed() {
|
||||
if (mMenuStack.size() == 0 && !mPausing.get()) {
|
||||
nativeOnResume(/*isSystemResume:*/false);
|
||||
}
|
||||
}
|
||||
|
||||
public Apple2View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
public void maybeQuitApp() {
|
||||
nativeOnPause(false);
|
||||
AlertDialog quitDialog = new AlertDialog.Builder(this).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(R.string.quit_really).setMessage(R.string.quit_warning).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
nativeOnQuit();
|
||||
Apple2Activity.this.finish();
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException ex) {
|
||||
// ...
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
}.run();
|
||||
dismissAllMenus(); // NOTE : at this point, this should not be re-entrant into mMenuStack, it should just dismiss lingering popups
|
||||
if (!mPausing.get()) {
|
||||
if (dismissedSplashScreen) {
|
||||
setupGLView();
|
||||
} else {
|
||||
nativeEmulationResume();
|
||||
}
|
||||
}
|
||||
}).setNegativeButton(R.string.no, null).create();
|
||||
registerAndShowDialog(quitDialog);
|
||||
}
|
||||
}
|
||||
|
||||
public void maybeReboot() {
|
||||
nativeOnPause(false);
|
||||
AlertDialog rebootDialog = new AlertDialog.Builder(this).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(R.string.reboot_really).setMessage(R.string.reboot_warning).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
public boolean isEmulationPaused() {
|
||||
boolean mainMenuShowing = (mMainMenu != null && mMainMenu.isShowing());
|
||||
boolean menusShowing = (mMenuStack.size() > 0);
|
||||
return mainMenuShowing || menusShowing;
|
||||
}
|
||||
|
||||
public void maybeResumeEmulation() {
|
||||
if (mMenuStack.size() == 0 && !mPausing.get()) {
|
||||
nativeEmulationResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void pauseEmulation() {
|
||||
nativeEmulationPause();
|
||||
}
|
||||
|
||||
public void rebootEmulation() {
|
||||
nativeReboot();
|
||||
}
|
||||
|
||||
public void saveState(String stateFile) {
|
||||
nativeSaveState(stateFile);
|
||||
}
|
||||
|
||||
public String loadState(String stateFile) {
|
||||
return Apple2Activity.nativeLoadState(stateFile);
|
||||
}
|
||||
|
||||
public void chooseDisk(String path, boolean driveA, boolean readOnly) {
|
||||
nativeChooseDisk(path, driveA, readOnly);
|
||||
}
|
||||
|
||||
public void ejectDisk(boolean driveA) {
|
||||
nativeEjectDisk(driveA);
|
||||
}
|
||||
|
||||
public void quitEmulator() {
|
||||
nativeOnQuit();
|
||||
finish();
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
nativeReboot();
|
||||
Apple2Activity.this.mMainMenu.dismiss();
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException ex) {
|
||||
// ...
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
}).setNegativeButton(R.string.no, null).create();
|
||||
registerAndShowDialog(rebootDialog);
|
||||
}.run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,25 +50,6 @@ public class Apple2AudioSettingsMenu extends Apple2AbstractMenu {
|
||||
}
|
||||
|
||||
enum SETTINGS implements Apple2AbstractMenu.IMenuEnum {
|
||||
SPEAKER_ENABLED {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.speaker_enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSummary(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.speaker_enable_summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final Apple2Activity activity, View convertView) {
|
||||
convertView = _basicView(activity, this, convertView);
|
||||
CheckBox cb = _addCheckbox(activity, this, convertView, true);
|
||||
cb.setEnabled(false);
|
||||
return convertView;
|
||||
}
|
||||
},
|
||||
SPEAKER_VOLUME {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
|
||||
@@ -14,6 +14,8 @@ package org.deadc0de.apple2ix;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
@@ -181,14 +183,12 @@ public class Apple2CrashHandler {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
|
||||
final Button startButton = (Button) activity.findViewById(R.id.startButton);
|
||||
final Button prefsButton = (Button) activity.findViewById(R.id.prefsButton);
|
||||
final Button disksButton = (Button) activity.findViewById(R.id.disksButton);
|
||||
final Apple2SplashScreen splashScreen = activity.getSplashScreen();
|
||||
if (splashScreen != null) {
|
||||
splashScreen.setDismissable(false);
|
||||
}
|
||||
final ProgressBar bar = (ProgressBar) activity.findViewById(R.id.crash_progressBar);
|
||||
try {
|
||||
startButton.setEnabled(false);
|
||||
prefsButton.setEnabled(false);
|
||||
disksButton.setEnabled(false);
|
||||
bar.setVisibility(View.VISIBLE);
|
||||
} catch (NullPointerException npe) {
|
||||
/* could happen on early lifecycle crashes */
|
||||
@@ -204,19 +204,30 @@ public class Apple2CrashHandler {
|
||||
final int monoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(activity, /*isStereo:*/false);
|
||||
final int stereoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(activity, /*isStereo:*/true);
|
||||
|
||||
StringBuilder summary = new StringBuilder();
|
||||
StringBuilder allCrashData = new StringBuilder();
|
||||
|
||||
// prepend information about this device
|
||||
allCrashData.append("BRAND: ").append(Build.BRAND).append("\n");
|
||||
allCrashData.append("MODEL: ").append(Build.MODEL).append("\n");
|
||||
allCrashData.append("MANUFACTURER: ").append(Build.MANUFACTURER).append("\n");
|
||||
allCrashData.append("DEVICE: ").append(Build.DEVICE).append("\n");
|
||||
allCrashData.append("SAMPLE RATE: ").append(sampleRate).append("\n");
|
||||
allCrashData.append("MONO BUFSIZE: ").append(monoBufferSize).append("\n");
|
||||
allCrashData.append("STEREO BUFSIZE: ").append(stereoBufferSize).append("\n");
|
||||
allCrashData.append("GPU VENDOR: ").append(Apple2Preferences.GL_VENDOR.stringValue(activity)).append("\n");
|
||||
allCrashData.append("GPU RENDERER: ").append(Apple2Preferences.GL_RENDERER.stringValue(activity)).append("\n");
|
||||
allCrashData.append("GPU VERSION: ").append(Apple2Preferences.GL_VERSION.stringValue(activity)).append("\n");
|
||||
summary.append("BRAND: ").append(Build.BRAND).append("\n");
|
||||
summary.append("MODEL: ").append(Build.MODEL).append("\n");
|
||||
summary.append("MANUFACTURER: ").append(Build.MANUFACTURER).append("\n");
|
||||
summary.append("DEVICE: ").append(Build.DEVICE).append("\n");
|
||||
summary.append("SDK: ").append(Build.VERSION.SDK_INT).append("\n");
|
||||
summary.append("SAMPLE RATE: ").append(sampleRate).append("\n");
|
||||
summary.append("MONO BUFSIZE: ").append(monoBufferSize).append("\n");
|
||||
summary.append("STEREO BUFSIZE: ").append(stereoBufferSize).append("\n");
|
||||
summary.append("GPU VENDOR: ").append(Apple2Preferences.GL_VENDOR.stringValue(activity)).append("\n");
|
||||
summary.append("GPU RENDERER: ").append(Apple2Preferences.GL_RENDERER.stringValue(activity)).append("\n");
|
||||
summary.append("GPU VERSION: ").append(Apple2Preferences.GL_VERSION.stringValue(activity)).append("\n");
|
||||
|
||||
try {
|
||||
PackageInfo pInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0);
|
||||
summary.append("APP VERSION: ").append(pInfo.versionName).append("\n");
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// ...
|
||||
}
|
||||
|
||||
allCrashData.append(summary);
|
||||
|
||||
File[] nativeCrashes = _nativeCrashFiles(activity);
|
||||
if (nativeCrashes == null) {
|
||||
@@ -247,6 +258,8 @@ public class Apple2CrashHandler {
|
||||
}
|
||||
});
|
||||
|
||||
boolean summarizedHeader = false;
|
||||
|
||||
// iteratively process native crashes
|
||||
for (File crash : nativeCrashes) {
|
||||
|
||||
@@ -266,6 +279,48 @@ public class Apple2CrashHandler {
|
||||
}
|
||||
allCrashData.append(">>>>>>> NATIVE CRASH [").append(crashPath).append("]\n");
|
||||
allCrashData.append(crashData);
|
||||
summary.append("NATIVE CRASH:\n");
|
||||
|
||||
// append succinct information about crashing thread
|
||||
String[] lines = crashData.toString().split("[\\n\\r][\\n\\r]*");
|
||||
for (int i = 0, j = 0; i < lines.length; i++) {
|
||||
|
||||
// 2 lines of minidump summary
|
||||
if (i < 2) {
|
||||
if (!summarizedHeader) {
|
||||
summary.append(lines[i]);
|
||||
summary.append("\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1 line of crashing thread and reason
|
||||
if (i == 2) {
|
||||
summarizedHeader = true;
|
||||
summary.append(lines[i]);
|
||||
summary.append("\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// whole lotta modules
|
||||
if (lines[i].startsWith("Module")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// one apparently empty line
|
||||
if (lines[i].matches("^[ \\t]*$")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// append crashing thread backtrace
|
||||
|
||||
summary.append(lines[i]);
|
||||
summary.append("\n");
|
||||
final int maxSummaryBacktrace = 8;
|
||||
if (j++ >= maxSummaryBacktrace) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -288,6 +343,10 @@ public class Apple2CrashHandler {
|
||||
|
||||
allCrashData.append(">>>>>>> JAVA CRASH DATA\n");
|
||||
allCrashData.append(javaCrashData);
|
||||
|
||||
summary.append("JAVA CRASH:\n");
|
||||
summary.append(javaCrashData);
|
||||
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -303,9 +362,7 @@ public class Apple2CrashHandler {
|
||||
public void run() {
|
||||
try {
|
||||
bar.setVisibility(View.INVISIBLE);
|
||||
startButton.setEnabled(true);
|
||||
prefsButton.setEnabled(true);
|
||||
disksButton.setEnabled(true);
|
||||
splashScreen.setDismissable(true);
|
||||
} catch (NullPointerException npe) {
|
||||
/* could happen on early lifecycle crashes */
|
||||
}
|
||||
@@ -313,7 +370,7 @@ public class Apple2CrashHandler {
|
||||
});
|
||||
|
||||
// send report with all the data
|
||||
_sendEmailToDeveloperWithCrashData(activity, allCrashData);
|
||||
_sendEmailToDeveloperWithCrashData(activity, summary, allCrashData);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -481,19 +538,25 @@ public class Apple2CrashHandler {
|
||||
return allCrashFile;
|
||||
}
|
||||
|
||||
private void _sendEmailToDeveloperWithCrashData(Apple2Activity activity, StringBuilder allCrashData) {
|
||||
private void _sendEmailToDeveloperWithCrashData(Apple2Activity activity, StringBuilder summary, StringBuilder allCrashData) {
|
||||
mAlreadySentReport.set(true);
|
||||
|
||||
// <sigh> ... the disaster that is early Android ... there does not appear to be a reliable way to start an
|
||||
// email Intent to send both text and an attachment, but we make a valiant (if futile) effort to do so here.
|
||||
// And the reason to send an attachment is that you trigger an android.os.TransactionTooLargeException with too
|
||||
// much text data in the EXTRA_TEXT ... </sigh>
|
||||
|
||||
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", "apple2ix_crash@deadcode.org"/*non-zero variant is correct endpoint at the moment*/, null));
|
||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Crasher");
|
||||
|
||||
File allCrashFile = _writeTempLogFile(activity, allCrashData);
|
||||
// Putting all the text data into the EXTRA_TEXT appears to trigger android.os.TransactionTooLargeException ...
|
||||
//emailIntent.putExtra(Intent.EXTRA_TEXT, allCrashData.toString());
|
||||
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(allCrashFile));
|
||||
final int maxCharsEmail = 4096;
|
||||
int len = summary.length();
|
||||
len = len < maxCharsEmail ? len : maxCharsEmail;
|
||||
String summaryData = summary.substring(0, len);
|
||||
emailIntent.putExtra(Intent.EXTRA_TEXT, "The app crashed, please help!\n\n"+summaryData);
|
||||
|
||||
// But we can put some text data
|
||||
emailIntent.putExtra(Intent.EXTRA_TEXT, "Greeting Apple2ix developers! The app crashed, please help!");
|
||||
File allCrashFile = _writeTempLogFile(activity, allCrashData);
|
||||
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(allCrashFile));
|
||||
|
||||
Log.d(TAG, "STARTING CHOOSER FOR EMAIL ...");
|
||||
activity.startActivity(Intent.createChooser(emailIntent, "Send email"));
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@@ -41,8 +42,10 @@ import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.deadc0de.apple2ix.basic.R;
|
||||
|
||||
@@ -74,28 +77,40 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
}
|
||||
});
|
||||
|
||||
getExternalStorageDirectory();
|
||||
getExternalStorageDirectory(activity);
|
||||
}
|
||||
|
||||
public static File getExternalStorageDirectory() {
|
||||
if (sExternalFilesDir == null) {
|
||||
public static File getExternalStorageDirectory(Apple2Activity activity) {
|
||||
|
||||
do {
|
||||
if (sExternalFilesDir != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
String storageState = Environment.getExternalStorageState();
|
||||
File externalDir = new File(Environment.getExternalStorageDirectory(), "apple2ix"); // /sdcard/apple2ix
|
||||
sExternalFilesDir = null;
|
||||
boolean externalStorageAvailable = storageState.equals(Environment.MEDIA_MOUNTED);
|
||||
if (externalStorageAvailable) {
|
||||
sExternalFilesDir = externalDir;
|
||||
boolean made = sExternalFilesDir.mkdirs();
|
||||
if (!storageState.equals(Environment.MEDIA_MOUNTED)) {
|
||||
// 2015/10/28 : do not expose sExternalFilesDir/sDownloadFilesDir unless they are writable
|
||||
break;
|
||||
}
|
||||
|
||||
File externalStorageDir = Environment.getExternalStorageDirectory();
|
||||
if (externalStorageDir == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
File externalDir = new File(externalStorageDir, "apple2ix"); // /sdcard/apple2ix
|
||||
if (!externalDir.exists()) {
|
||||
boolean made = externalDir.mkdirs();
|
||||
if (!made) {
|
||||
Log.d(TAG, "WARNING: could not make directory : " + sExternalFilesDir);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sExternalFilesDir = externalDir;
|
||||
}
|
||||
}
|
||||
if (sDownloadFilesDir == null) {
|
||||
|
||||
sExternalFilesDir = externalDir;
|
||||
sDownloadFilesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
}
|
||||
} while (false);
|
||||
|
||||
return sExternalFilesDir;
|
||||
}
|
||||
|
||||
@@ -122,23 +137,86 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
return sDataDir;
|
||||
}
|
||||
|
||||
public static void firstTime(Apple2Activity activity) {
|
||||
public static void exposeAPKAssetsToExternal(Apple2Activity activity) {
|
||||
getExternalStorageDirectory(activity);
|
||||
if (sExternalFilesDir == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ProgressBar bar = (ProgressBar) activity.findViewById(R.id.crash_progressBar);
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
bar.setVisibility(View.VISIBLE);
|
||||
bar.setIndeterminate(true);
|
||||
} catch (NullPointerException npe) {
|
||||
Log.v(TAG, "Avoid NPE in exposeAPKAssetsToExternal #1");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Log.v(TAG, "Overwriting system files in /sdcard/apple2ix/ (external storage) ...");
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/sExternalFilesDir.getAbsolutePath(), false);
|
||||
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
bar.setVisibility(View.INVISIBLE);
|
||||
bar.setIndeterminate(false);
|
||||
} catch (NullPointerException npe) {
|
||||
Log.v(TAG, "Avoid NPE in exposeAPKAssetsToExternal #2");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void exposeAPKAssets(Apple2Activity activity) {
|
||||
final ProgressBar bar = (ProgressBar) activity.findViewById(R.id.crash_progressBar);
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
bar.setVisibility(View.VISIBLE);
|
||||
bar.setIndeterminate(true);
|
||||
} catch (NullPointerException npe) {
|
||||
Log.v(TAG, "Avoid NPE in exposeAPKAssets #1");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getDataDir(activity);
|
||||
|
||||
// FIXME TODO : Heavy-handed migration to 1.1.3 ...
|
||||
recursivelyDelete(new File(new File(sDataDir, "disks").getAbsolutePath(), "blanks"));
|
||||
recursivelyDelete(new File(new File(sDataDir, "disks").getAbsolutePath(), "demo"));
|
||||
recursivelyDelete(new File(new File(sDataDir, "disks").getAbsolutePath(), "eamon"));
|
||||
recursivelyDelete(new File(new File(sDataDir, "disks").getAbsolutePath(), "logo"));
|
||||
recursivelyDelete(new File(new File(sDataDir, "disks").getAbsolutePath(), "miscgame"));
|
||||
|
||||
Log.d(TAG, "First time copying stuff-n-things out of APK for ease-of-NDK access...");
|
||||
|
||||
getExternalStorageDirectory();
|
||||
getExternalStorageDirectory(activity);
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"disks", /*to location:*/new File(sDataDir, "disks").getAbsolutePath(), true);
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/new File(sDataDir, "keyboards").getAbsolutePath(), false);
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"shaders", /*to location:*/new File(sDataDir, "shaders").getAbsolutePath(), false);
|
||||
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"disks", /*to location:*/new File(sDataDir, "disks").getAbsolutePath());
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/new File(sDataDir, "keyboards").getAbsolutePath());
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"shaders", /*to location:*/new File(sDataDir, "shaders").getAbsolutePath());
|
||||
|
||||
// expose keyboards to modding
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/sExternalFilesDir.getAbsolutePath());
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
bar.setVisibility(View.INVISIBLE);
|
||||
bar.setIndeterminate(false);
|
||||
} catch (NullPointerException npe) {
|
||||
Log.v(TAG, "Avoid NPE in exposeAPKAssets #1");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void exposeSymbols(Apple2Activity activity) {
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"symbols", /*to location:*/new File(sDataDir, "symbols").getAbsolutePath());
|
||||
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"symbols", /*to location:*/new File(sDataDir, "symbols").getAbsolutePath(), false);
|
||||
}
|
||||
|
||||
public static void unexposeSymbols(Apple2Activity activity) {
|
||||
@@ -184,7 +262,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mDisksView.isShown();
|
||||
return mDisksView.getParent() != null;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
@@ -282,6 +360,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
return pathBuffer.toString();
|
||||
}
|
||||
|
||||
// TODO FIXME : WARNING : this is super dangerous if there are symlinks !!!
|
||||
private static void recursivelyDelete(File file) {
|
||||
if (file.isDirectory()) {
|
||||
for (File f : file.listFiles()) {
|
||||
@@ -293,7 +372,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
}
|
||||
}
|
||||
|
||||
private static void recursivelyCopyAPKAssets(Apple2Activity activity, String srcFileOrDir, String dstFileOrDir) {
|
||||
private static void recursivelyCopyAPKAssets(Apple2Activity activity, String srcFileOrDir, String dstFileOrDir, boolean shouldGzip) {
|
||||
AssetManager assetManager = activity.getAssets();
|
||||
|
||||
final int maxAttempts = 5;
|
||||
@@ -333,19 +412,23 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
}
|
||||
for (String filename : files) {
|
||||
// iterate on files and subdirectories
|
||||
recursivelyCopyAPKAssets(activity, srcFileOrDir + File.separator + filename, dstFileOrDir + File.separator + filename);
|
||||
recursivelyCopyAPKAssets(activity, srcFileOrDir + File.separator + filename, dstFileOrDir + File.separator + filename, shouldGzip);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// presumably this is a file, not a subdirectory
|
||||
InputStream is = null;
|
||||
FileOutputStream os = null;
|
||||
OutputStream os = null;
|
||||
attempts = 0;
|
||||
do {
|
||||
try {
|
||||
is = assetManager.open(srcFileOrDir);
|
||||
os = new FileOutputStream(dstFileOrDir);
|
||||
if (shouldGzip) {
|
||||
os = new GZIPOutputStream(new FileOutputStream(dstFileOrDir + ".gz"));
|
||||
} else {
|
||||
os = new FileOutputStream(dstFileOrDir);
|
||||
}
|
||||
copyFile(is, os);
|
||||
break;
|
||||
} catch (InterruptedIOException e) {
|
||||
@@ -377,7 +460,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
} while (attempts < maxAttempts);
|
||||
}
|
||||
|
||||
private static void copyFile(InputStream is, FileOutputStream os) throws IOException {
|
||||
private static void copyFile(InputStream is, OutputStream os) throws IOException {
|
||||
final int BUF_SZ = 4096;
|
||||
byte[] buf = new byte[BUF_SZ];
|
||||
while (true) {
|
||||
@@ -428,7 +511,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
|
||||
Arrays.sort(files);
|
||||
|
||||
getExternalStorageDirectory();
|
||||
getExternalStorageDirectory(mActivity);
|
||||
final boolean includeExternalStoragePath = (sExternalFilesDir != null && isRootPath);
|
||||
final boolean includeDownloadsPath = (sDownloadFilesDir != null && isRootPath);
|
||||
final int offset = includeExternalStoragePath ? (includeDownloadsPath ? 2 : 1) : (includeDownloadsPath ? 1 : 0);
|
||||
@@ -437,7 +520,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
|
||||
int idx = 0;
|
||||
if (includeExternalStoragePath) {
|
||||
fileNames[idx] = sExternalFilesDir.getPath();
|
||||
fileNames[idx] = sExternalFilesDir.getAbsolutePath();
|
||||
isDirectory[idx] = true;
|
||||
++idx;
|
||||
}
|
||||
@@ -493,7 +576,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
ejectButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mActivity.nativeEjectDisk(/*driveA:*/true);
|
||||
mActivity.ejectDisk(/*driveA:*/true);
|
||||
Apple2Preferences.CURRENT_DISK_A.saveString(mActivity, "");
|
||||
dynamicSetup();
|
||||
}
|
||||
@@ -505,7 +588,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
ejectButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mActivity.nativeEjectDisk(/*driveA:*/false);
|
||||
mActivity.ejectDisk(/*driveA:*/false);
|
||||
Apple2Preferences.CURRENT_DISK_B.saveString(mActivity, "");
|
||||
dynamicSetup();
|
||||
}
|
||||
@@ -547,17 +630,16 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
final String imageName = str;
|
||||
|
||||
if (imageName.equals(Apple2Preferences.CURRENT_DISK_A.stringValue(mActivity))) {
|
||||
mActivity.nativeEjectDisk(/*driveA:*/true);
|
||||
mActivity.ejectDisk(/*driveA:*/true);
|
||||
Apple2Preferences.CURRENT_DISK_A.saveString(mActivity, "");
|
||||
dynamicSetup();
|
||||
return;
|
||||
}
|
||||
if (imageName.equals(Apple2Preferences.CURRENT_DISK_B.stringValue(mActivity))) {
|
||||
mActivity.nativeEjectDisk(/*driveA:*/false);
|
||||
mActivity.ejectDisk(/*driveA:*/false);
|
||||
Apple2Preferences.CURRENT_DISK_B.saveString(mActivity, "");
|
||||
dynamicSetup();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
String title = mActivity.getResources().getString(R.string.header_disks);
|
||||
@@ -601,8 +683,6 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
mActivity.dismissAllMenus();
|
||||
boolean isDriveA = diskA.isChecked();
|
||||
boolean diskReadOnly = readOnly.isChecked();
|
||||
if (isDriveA) {
|
||||
@@ -612,6 +692,8 @@ public class Apple2DisksMenu implements Apple2MenuView {
|
||||
Apple2Preferences.CURRENT_DISK_B_RO.saveBoolean(mActivity, diskReadOnly);
|
||||
Apple2Preferences.CURRENT_DISK_B.saveString(mActivity, imageName);
|
||||
}
|
||||
dialog.dismiss();
|
||||
mActivity.dismissAllMenus();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public class Apple2JoystickCalibration implements Apple2MenuView {
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mSettingsView.isShown();
|
||||
return mSettingsView.getParent() != null;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
|
||||
@@ -329,6 +329,30 @@ public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu {
|
||||
return convertView;
|
||||
}
|
||||
},
|
||||
JOYSTICK_AZIMUTH_VISIBILITY {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.joystick_azimuth_visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSummary(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.joystick_azimuth_visible_summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final Apple2Activity activity, View convertView) {
|
||||
convertView = _basicView(activity, this, convertView);
|
||||
CheckBox cb = _addCheckbox(activity, this, convertView, Apple2Preferences.JOYSTICK_AZIMUTH_VISIBILITY.booleanValue(activity));
|
||||
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
Apple2Preferences.JOYSTICK_AZIMUTH_VISIBILITY.saveBoolean(activity, isChecked);
|
||||
}
|
||||
});
|
||||
return convertView;
|
||||
}
|
||||
},
|
||||
JOYSTICK_AXIS_ON_LEFT {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
@@ -415,7 +439,7 @@ public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu {
|
||||
|
||||
@Override
|
||||
public void showValue(int progress, final TextView seekBarValue) {
|
||||
int threshold = progress * Apple2Preferences.JOYSTICK_BUTTON_THRESHOLD_STEP;
|
||||
int threshold = progress * Apple2Preferences.getJoystickButtonSwitchThresholdScale(activity);
|
||||
seekBarValue.setText("" + threshold + " pts");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -91,10 +91,34 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
|
||||
if (position < 0 || position >= SETTINGS.size) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return true;
|
||||
return (position != SETTINGS.KEYBOARD_VISIBILITY_INACTIVE.ordinal() && position != SETTINGS.KEYBOARD_VISIBILITY_ACTIVE.ordinal());
|
||||
}
|
||||
|
||||
protected enum SETTINGS implements Apple2AbstractMenu.IMenuEnum {
|
||||
TOUCH_MENU_ENABLED {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.touch_menu_enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSummary(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.touch_menu_enable_summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final Apple2Activity activity, View convertView) {
|
||||
convertView = _basicView(activity, this, convertView);
|
||||
CheckBox cb = _addCheckbox(activity, this, convertView, Apple2Preferences.TOUCH_MENU_ENABLED.booleanValue(activity));
|
||||
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
Apple2Preferences.TOUCH_MENU_ENABLED.saveBoolean(activity, isChecked);
|
||||
}
|
||||
});
|
||||
return convertView;
|
||||
}
|
||||
},
|
||||
KEYBOARD_VISIBILITY_INACTIVE {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
@@ -226,7 +250,7 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
|
||||
@Override
|
||||
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
|
||||
|
||||
File extKeyboardDir = Apple2DisksMenu.getExternalStorageDirectory();
|
||||
File extKeyboardDir = Apple2DisksMenu.getExternalStorageDirectory(activity);
|
||||
|
||||
FilenameFilter kbdJsonFilter = new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
@@ -249,7 +273,10 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
|
||||
}
|
||||
};
|
||||
|
||||
File[] files = extKeyboardDir.listFiles(kbdJsonFilter);
|
||||
File[] files = null;
|
||||
if (extKeyboardDir != null) {
|
||||
files = extKeyboardDir.listFiles(kbdJsonFilter);
|
||||
}
|
||||
if (files == null) {
|
||||
// read keyboard data from /data/data/...
|
||||
File keyboardDir = new File(Apple2DisksMenu.getDataDir(activity) + File.separator + "keyboards");
|
||||
@@ -270,7 +297,7 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
|
||||
++idx;
|
||||
}
|
||||
|
||||
final String keyboardDirName = extKeyboardDir.getPath();
|
||||
final String keyboardDirName = extKeyboardDir == null ? "Keyboards" : extKeyboardDir.getPath();
|
||||
|
||||
_alertDialogHandleSelection(activity, keyboardDirName, titles, new IPreferenceLoadSave() {
|
||||
@Override
|
||||
@@ -286,6 +313,31 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
KEYBOARD_GLYPH_SCALE {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.keyboard_glyph_scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSummary(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.keyboard_glyph_scale_summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final Apple2Activity activity, View convertView) {
|
||||
convertView = _basicView(activity, this, convertView);
|
||||
int glyphScale = Apple2Preferences.KEYBOARD_GLYPH_SCALE.intValue(activity);
|
||||
CheckBox cb = _addCheckbox(activity, this, convertView, glyphScale > 1);
|
||||
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
Apple2Preferences.KEYBOARD_GLYPH_SCALE.saveInt(activity, isChecked ? 2 : 1);
|
||||
}
|
||||
});
|
||||
return convertView;
|
||||
}
|
||||
};
|
||||
|
||||
public static final int size = SETTINGS.values().length;
|
||||
|
||||
@@ -65,18 +65,18 @@ public class Apple2KeypadChooser implements Apple2MenuView {
|
||||
mCurrentChoicePrompt.setText(getNextChoiceString() + asciiStr);
|
||||
switch (mChooserState) {
|
||||
case CHOOSE_TAP:
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_DOWN, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_UP, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_DOWN, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_UP, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
break;
|
||||
case CHOOSE_SWIPEDOWN:
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_DOWN, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_MOVE, 1, 0, new float[]{400.f}, new float[]{600.f});
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_UP, 1, 0, new float[]{400.f}, new float[]{600.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_DOWN, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_MOVE, 1, 0, new float[]{400.f}, new float[]{600.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_UP, 1, 0, new float[]{400.f}, new float[]{600.f});
|
||||
break;
|
||||
case CHOOSE_SWIPEUP:
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_DOWN, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_MOVE, 1, 0, new float[]{400.f}, new float[]{200.f});
|
||||
mActivity.nativeOnTouch(MotionEvent.ACTION_UP, 1, 0, new float[]{400.f}, new float[]{200.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_DOWN, 1, 0, new float[]{400.f}, new float[]{400.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_MOVE, 1, 0, new float[]{400.f}, new float[]{200.f});
|
||||
Apple2View.nativeOnTouch(MotionEvent.ACTION_UP, 1, 0, new float[]{400.f}, new float[]{200.f});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -119,7 +119,7 @@ public class Apple2KeypadChooser implements Apple2MenuView {
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mSettingsView.isShown();
|
||||
return mSettingsView.getParent() != null;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
|
||||
package org.deadc0de.apple2ix;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
@@ -27,17 +29,23 @@ import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.deadc0de.apple2ix.basic.R;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class Apple2MainMenu {
|
||||
|
||||
private final static int MENU_INSET = 20;
|
||||
private final static String SAVE_FILE = "emulator.state";
|
||||
private final static String TAG = "Apple2MainMenu";
|
||||
|
||||
private Apple2Activity mActivity = null;
|
||||
private Apple2View mParentView = null;
|
||||
private PopupWindow mMainMenuPopup = null;
|
||||
private Apple2SettingsMenu mSettingsMenu = null;
|
||||
private Apple2DisksMenu mDisksMenu = null;
|
||||
|
||||
private AtomicBoolean mShowingRebootQuit = new AtomicBoolean(false);
|
||||
private AtomicBoolean mShowingSaveRestore = new AtomicBoolean(false);
|
||||
|
||||
public Apple2MainMenu(Apple2Activity activity, Apple2View parent) {
|
||||
mActivity = activity;
|
||||
@@ -47,52 +55,82 @@ public class Apple2MainMenu {
|
||||
|
||||
enum SETTINGS {
|
||||
SHOW_SETTINGS {
|
||||
@Override public String getTitle(Context ctx) {
|
||||
@Override
|
||||
public String getTitle(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.menu_settings);
|
||||
}
|
||||
@Override public String getSummary(Context ctx) {
|
||||
|
||||
@Override
|
||||
public String getSummary(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.menu_settings_summary);
|
||||
}
|
||||
@Override public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
|
||||
@Override
|
||||
public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
mainMenu.showSettings();
|
||||
}
|
||||
},
|
||||
LOAD_DISK {
|
||||
@Override public String getTitle(Context ctx) {
|
||||
@Override
|
||||
public String getTitle(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.menu_disks);
|
||||
}
|
||||
@Override public String getSummary(Context ctx) {
|
||||
|
||||
@Override
|
||||
public String getSummary(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.menu_disks_summary);
|
||||
}
|
||||
@Override public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
|
||||
@Override
|
||||
public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
mainMenu.showDisksMenu();
|
||||
}
|
||||
},
|
||||
REBOOT_EMULATOR {
|
||||
@Override public String getTitle(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.reboot);
|
||||
SAVE_RESTORE {
|
||||
@Override
|
||||
public String getTitle(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.saverestore);
|
||||
}
|
||||
@Override public String getSummary(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.reboot_summary);
|
||||
|
||||
@Override
|
||||
public String getSummary(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.saverestore_summary);
|
||||
}
|
||||
@Override public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
mainMenu.mActivity.maybeReboot();
|
||||
|
||||
@Override
|
||||
public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
if (!mainMenu.mShowingSaveRestore.compareAndSet(false, true)) {
|
||||
Log.v(TAG, "OMG, avoiding nasty UI race around save/restore");
|
||||
return;
|
||||
}
|
||||
mainMenu.maybeSaveRestore();
|
||||
}
|
||||
},
|
||||
QUIT_EMULATOR {
|
||||
@Override public String getTitle(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.quit);
|
||||
REBOOT_QUIT_EMULATOR {
|
||||
@Override
|
||||
public String getTitle(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.quit_reboot);
|
||||
}
|
||||
@Override public String getSummary(Context ctx) {
|
||||
return ctx.getResources().getString(R.string.quit_summary);
|
||||
|
||||
@Override
|
||||
public String getSummary(Context ctx) {
|
||||
return "";
|
||||
}
|
||||
@Override public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
mainMenu.mActivity.maybeQuitApp();
|
||||
|
||||
@Override
|
||||
public void handleSelection(Apple2MainMenu mainMenu) {
|
||||
if (!mainMenu.mShowingRebootQuit.compareAndSet(false, true)) {
|
||||
Log.v(TAG, "OMG, avoiding nasty UI race around quit/reboot");
|
||||
return;
|
||||
}
|
||||
mainMenu.maybeRebootQuit();
|
||||
}
|
||||
};
|
||||
|
||||
public abstract String getTitle(Context ctx);
|
||||
|
||||
public abstract String getSummary(Context ctx);
|
||||
|
||||
public abstract void handleSelection(Apple2MainMenu mainMenu);
|
||||
|
||||
public static String[] titles(Context ctx) {
|
||||
@@ -107,11 +145,11 @@ public class Apple2MainMenu {
|
||||
|
||||
private void setup() {
|
||||
|
||||
LayoutInflater inflater = (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View listLayout=inflater.inflate(R.layout.activity_main_menu, null, false);
|
||||
ListView mainMenuView = (ListView)listLayout.findViewById(R.id.main_popup_menu);
|
||||
LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View listLayout = inflater.inflate(R.layout.activity_main_menu, null, false);
|
||||
ListView mainMenuView = (ListView) listLayout.findViewById(R.id.main_popup_menu);
|
||||
mainMenuView.setEnabled(true);
|
||||
LinearLayout mainPopupContainer = (LinearLayout)listLayout.findViewById(R.id.main_popup_container);
|
||||
LinearLayout mainPopupContainer = (LinearLayout) listLayout.findViewById(R.id.main_popup_container);
|
||||
|
||||
final String[] values = SETTINGS.titles(mActivity);
|
||||
|
||||
@@ -120,10 +158,11 @@ public class Apple2MainMenu {
|
||||
public boolean areAllItemsEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view = super.getView(position, convertView, parent);
|
||||
TextView tv = (TextView)view.findViewById(android.R.id.text2);
|
||||
TextView tv = (TextView) view.findViewById(android.R.id.text2);
|
||||
SETTINGS setting = SETTINGS.values()[position];
|
||||
tv.setText(setting.getSummary(mActivity));
|
||||
return view;
|
||||
@@ -133,7 +172,7 @@ public class Apple2MainMenu {
|
||||
mainMenuView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Log.d(TAG, "position:"+position+" tapped...");
|
||||
Log.d(TAG, "position:" + position + " tapped...");
|
||||
SETTINGS setting = SETTINGS.values()[position];
|
||||
setting.handleSelection(Apple2MainMenu.this);
|
||||
}
|
||||
@@ -155,7 +194,7 @@ public class Apple2MainMenu {
|
||||
maxWidth = width;
|
||||
}
|
||||
}
|
||||
mMainMenuPopup = new PopupWindow(mainPopupContainer, maxWidth+TOTAL_MARGINS, totalHeight, true);
|
||||
mMainMenuPopup = new PopupWindow(mainPopupContainer, maxWidth + TOTAL_MARGINS, totalHeight, true);
|
||||
}
|
||||
|
||||
// This kludgery allows touching the outside or back-buttoning to dismiss
|
||||
@@ -164,46 +203,32 @@ public class Apple2MainMenu {
|
||||
mMainMenuPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
boolean otherMenusShowing = (getSettingsMenu().isShowing() || getDisksMenu().isShowing());
|
||||
if (!otherMenusShowing) {
|
||||
Apple2MainMenu.this.mActivity._mainMenuDismissed();
|
||||
}
|
||||
Apple2MainMenu.this.mActivity.maybeResumeEmulation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showDisksMenu() {
|
||||
Apple2DisksMenu disksMenu = getDisksMenu();
|
||||
Apple2DisksMenu disksMenu = mActivity.getDisksMenu();
|
||||
disksMenu.show();
|
||||
mMainMenuPopup.dismiss();
|
||||
}
|
||||
|
||||
public void showSettings() {
|
||||
Apple2SettingsMenu settings = getSettingsMenu();
|
||||
Apple2SettingsMenu settings = mActivity.getSettingsMenu();
|
||||
settings.show();
|
||||
mMainMenuPopup.dismiss();
|
||||
}
|
||||
|
||||
public synchronized Apple2DisksMenu getDisksMenu() {
|
||||
if (mDisksMenu == null) {
|
||||
mDisksMenu = new Apple2DisksMenu(mActivity);
|
||||
}
|
||||
return mDisksMenu;
|
||||
}
|
||||
|
||||
public synchronized Apple2SettingsMenu getSettingsMenu() {
|
||||
if (mSettingsMenu == null) {
|
||||
mSettingsMenu = new Apple2SettingsMenu(mActivity);
|
||||
}
|
||||
return mSettingsMenu;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (mMainMenuPopup.isShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mActivity.nativeOnPause(false);
|
||||
mShowingRebootQuit.set(false);
|
||||
mShowingSaveRestore.set(false);
|
||||
|
||||
mActivity.pauseEmulation();
|
||||
|
||||
mMainMenuPopup.showAtLocation(mParentView, Gravity.CENTER, 0, 0);
|
||||
}
|
||||
@@ -218,4 +243,82 @@ public class Apple2MainMenu {
|
||||
public boolean isShowing() {
|
||||
return mMainMenuPopup.isShowing();
|
||||
}
|
||||
|
||||
|
||||
public void maybeRebootQuit() {
|
||||
mActivity.pauseEmulation();
|
||||
|
||||
final AtomicBoolean selectionAlreadyHandled = new AtomicBoolean(false);
|
||||
|
||||
AlertDialog rebootQuitDialog = new AlertDialog.Builder(mActivity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(R.string.quit_reboot).setMessage(R.string.quit_reboot_choice).setPositiveButton(R.string.reboot, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (!selectionAlreadyHandled.compareAndSet(false, true)) {
|
||||
Log.v(TAG, "OMG, avoiding nasty UI race in reboot/quit onClick()");
|
||||
return;
|
||||
}
|
||||
mActivity.rebootEmulation();
|
||||
Apple2MainMenu.this.dismiss();
|
||||
}
|
||||
}).setNeutralButton(R.string.quit, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (!selectionAlreadyHandled.compareAndSet(false, true)) {
|
||||
Log.v(TAG, "OMG, avoiding nasty UI race in reboot/quit onClick()");
|
||||
return;
|
||||
}
|
||||
mActivity.quitEmulator();
|
||||
}
|
||||
}).setNegativeButton(R.string.cancel, null).create();
|
||||
|
||||
mActivity.registerAndShowDialog(rebootQuitDialog);
|
||||
}
|
||||
|
||||
|
||||
public void maybeSaveRestore() {
|
||||
mActivity.pauseEmulation();
|
||||
|
||||
final String quickSavePath = Apple2DisksMenu.getDataDir(mActivity) + File.separator + SAVE_FILE;
|
||||
|
||||
final AtomicBoolean selectionAlreadyHandled = new AtomicBoolean(false);
|
||||
|
||||
AlertDialog saveRestoreDialog = new AlertDialog.Builder(mActivity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(R.string.saverestore).setMessage(R.string.saverestore_choice).setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (!selectionAlreadyHandled.compareAndSet(false, true)) {
|
||||
Log.v(TAG, "OMG, avoiding nasty UI race in save/restore onClick()");
|
||||
return;
|
||||
}
|
||||
mActivity.saveState(quickSavePath);
|
||||
Apple2MainMenu.this.dismiss();
|
||||
}
|
||||
}).setNeutralButton(R.string.restore, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (!selectionAlreadyHandled.compareAndSet(false, true)) {
|
||||
Log.v(TAG, "OMG, avoiding nasty UI race in save/restore onClick()");
|
||||
return;
|
||||
}
|
||||
|
||||
String jsonData = mActivity.loadState(quickSavePath);
|
||||
try {
|
||||
JSONObject map = new JSONObject(jsonData);
|
||||
String diskPath1 = map.getString("disk1");
|
||||
boolean readOnly1 = map.getBoolean("readOnly1");
|
||||
Apple2Preferences.CURRENT_DISK_A.setPath(mActivity, diskPath1);
|
||||
Apple2Preferences.CURRENT_DISK_A_RO.saveBoolean(mActivity, readOnly1);
|
||||
|
||||
String diskPath2 = map.getString("disk2");
|
||||
boolean readOnly2 = map.getBoolean("readOnly2");
|
||||
Apple2Preferences.CURRENT_DISK_B.setPath(mActivity, diskPath2);
|
||||
Apple2Preferences.CURRENT_DISK_B_RO.saveBoolean(mActivity, readOnly2);
|
||||
} catch (JSONException je) {
|
||||
Log.v(TAG, "OOPS : " + je);
|
||||
}
|
||||
Apple2MainMenu.this.dismiss();
|
||||
}
|
||||
}).setNegativeButton(R.string.cancel, null).create();
|
||||
|
||||
mActivity.registerAndShowDialog(saveRestoreDialog);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ package org.deadc0de.apple2ix;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
@@ -21,24 +22,21 @@ import java.io.File;
|
||||
import org.deadc0de.apple2ix.basic.R;
|
||||
|
||||
public enum Apple2Preferences {
|
||||
FIRST_TIME_CONFIGURED {
|
||||
EMULATOR_VERSION {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveBoolean(Apple2Activity activity, boolean ignored) {
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().putBoolean(toString(), true).apply();
|
||||
public void saveInt(Apple2Activity activity, int version) {
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().putInt(toString(), version).apply();
|
||||
}
|
||||
},
|
||||
CURRENT_DISK_PATH {
|
||||
@Override
|
||||
public void load(final Apple2Activity activity) {
|
||||
Apple2MainMenu mainMenu = activity.getMainMenu();
|
||||
if (mainMenu != null) {
|
||||
mainMenu.getDisksMenu().setPathStackJSON(stringValue(activity));
|
||||
}
|
||||
activity.getDisksMenu().setPathStackJSON(stringValue(activity));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,6 +100,11 @@ public enum Apple2Preferences {
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
|
||||
load(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPath(Apple2Activity activity, String str) {
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
|
||||
}
|
||||
},
|
||||
CURRENT_DISK_A_RO {
|
||||
@Override
|
||||
@@ -136,6 +139,11 @@ public enum Apple2Preferences {
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
|
||||
load(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPath(Apple2Activity activity, String str) {
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
|
||||
}
|
||||
},
|
||||
CURRENT_DISK_B_RO {
|
||||
@Override
|
||||
@@ -176,22 +184,6 @@ public enum Apple2Preferences {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), HiresColor.INTERPOLATED.ordinal());
|
||||
}
|
||||
},
|
||||
SPEAKER_ENABLED {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
boolean enabled = booleanValue(activity);
|
||||
boolean result = nativeSetSpeakerEnabled(enabled);
|
||||
if (enabled && !result) {
|
||||
warnError(activity, R.string.speaker_disabled_title, R.string.speaker_disabled_mesg);
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().putBoolean(toString(), false).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean booleanValue(Apple2Activity activity) {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
|
||||
}
|
||||
},
|
||||
SPEAKER_VOLUME {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
@@ -285,17 +277,16 @@ public enum Apple2Preferences {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
|
||||
}
|
||||
},
|
||||
TOUCH_MENU_VISIBILITY {
|
||||
SHOW_DISK_OPERATIONS {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
int setting = intValue(activity);
|
||||
float alpha = (float) setting / AUDIO_LATENCY_NUM_CHOICES;
|
||||
nativeSetTouchMenuVisibility(alpha);
|
||||
boolean enabled = booleanValue(activity);
|
||||
nativeSetShowDiskOperationAnimation(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue(Apple2Activity activity) {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 5);
|
||||
public boolean booleanValue(Apple2Activity activity) {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
|
||||
}
|
||||
},
|
||||
JOYSTICK_AXIS_SENSITIVIY {
|
||||
@@ -330,7 +321,8 @@ public enum Apple2Preferences {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
int tick = intValue(activity);
|
||||
nativeSetTouchJoystickButtonSwitchThreshold(tick * JOYSTICK_BUTTON_THRESHOLD_STEP);
|
||||
tick *= getJoystickButtonSwitchThresholdScale(activity);
|
||||
nativeSetTouchJoystickButtonSwitchThreshold(tick);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -358,7 +350,7 @@ public enum Apple2Preferences {
|
||||
|
||||
@Override
|
||||
public int intValue(Apple2Activity activity) {
|
||||
int defaultLatency = 3; // /TAPDELAY_NUM_CHOICES * TAPDELAY_SCALE -> 0.075f
|
||||
int defaultLatency = 8; // /TAPDELAY_NUM_CHOICES * TAPDELAY_SCALE -> 0.2f
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), defaultLatency);
|
||||
}
|
||||
},
|
||||
@@ -418,6 +410,17 @@ public enum Apple2Preferences {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
|
||||
}
|
||||
},
|
||||
JOYSTICK_AZIMUTH_VISIBILITY {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
nativeSetTouchJoystickAzimuthVisibility(booleanValue(activity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean booleanValue(Apple2Activity activity) {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
|
||||
}
|
||||
},
|
||||
KEYPAD_KEYS {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
@@ -585,6 +588,41 @@ public enum Apple2Preferences {
|
||||
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
|
||||
}
|
||||
},
|
||||
KEYBOARD_GLYPH_SCALE {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
int scale = intValue(activity);
|
||||
if (scale == 0) {
|
||||
scale = 1;
|
||||
}
|
||||
nativeSetTouchKeyboardGlyphScale(scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue(Apple2Activity activity) {
|
||||
int scale = activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 0);
|
||||
|
||||
if (scale == 0) {
|
||||
scale = 2;
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
|
||||
|
||||
/* calculating actual physical diagonal size appears to be problematic -- Samsung Galaxy Y reports 15" with this method
|
||||
double x = Math.pow(dm.widthPixels / dm.xdpi, 2);
|
||||
double y = Math.pow(dm.heightPixels / dm.ydpi, 2);
|
||||
double screenInches = Math.sqrt(x + y);
|
||||
Log.d(TAG, "Screen inches:" + screenInches + " w:" + dm.widthPixels + " h:" + dm.heightPixels);
|
||||
*/
|
||||
if (dm.widthPixels <= 480 || dm.heightPixels <= 480) {
|
||||
scale = 1;
|
||||
}
|
||||
|
||||
saveInt(activity, scale);
|
||||
}
|
||||
|
||||
return scale;
|
||||
}
|
||||
},
|
||||
CRASH_CHECK {
|
||||
@Override
|
||||
public void load(Apple2Activity activity) {
|
||||
@@ -856,7 +894,6 @@ public enum Apple2Preferences {
|
||||
public final static String TAG = "Apple2Preferences";
|
||||
|
||||
public final static int JOYSTICK_BUTTON_THRESHOLD_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES;
|
||||
public final static int JOYSTICK_BUTTON_THRESHOLD_STEP = 5;
|
||||
|
||||
public final static float JOYSTICK_AXIS_SENSITIVITY_MIN = 0.25f;
|
||||
public final static float JOYSTICK_AXIS_SENSITIVITY_DEFAULT = 1.f;
|
||||
@@ -914,6 +951,10 @@ public enum Apple2Preferences {
|
||||
load(activity);
|
||||
}
|
||||
|
||||
public void setPath(Apple2Activity activity, String path) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
// accessors
|
||||
|
||||
public boolean booleanValue(Apple2Activity activity) {
|
||||
@@ -944,13 +985,13 @@ public enum Apple2Preferences {
|
||||
for (Apple2Preferences pref : Apple2Preferences.values()) {
|
||||
pref.load(activity);
|
||||
}
|
||||
// HACK FIXME TODO 2015/12/13 : native GLTouchDevice is conflating various things ... forcefully reset the current touch device here for now
|
||||
Apple2Preferences.CURRENT_TOUCH_DEVICE.load(activity);
|
||||
}
|
||||
|
||||
public static void resetPreferences(Apple2Activity activity) {
|
||||
activity.getPreferences(Context.MODE_PRIVATE).edit().clear().commit();
|
||||
FIRST_TIME_CONFIGURED.saveBoolean(activity, true);
|
||||
KeypadPreset.IJKM_SPACE.apply(activity);
|
||||
loadPreferences(activity);
|
||||
activity.quitEmulator();
|
||||
}
|
||||
|
||||
public String asciiString() {
|
||||
@@ -961,6 +1002,18 @@ public enum Apple2Preferences {
|
||||
return toString() + "_SCAN";
|
||||
}
|
||||
|
||||
public static int getJoystickButtonSwitchThresholdScale(Apple2Activity activity) {
|
||||
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
|
||||
|
||||
int smallScreenAxis = dm.widthPixels < dm.heightPixels ? dm.widthPixels : dm.heightPixels;
|
||||
int oneThirdScreenAxis = smallScreenAxis/3;
|
||||
|
||||
// largest switch threshold value is 1/3 small dimension of screen
|
||||
return oneThirdScreenAxis/JOYSTICK_BUTTON_THRESHOLD_NUM_CHOICES;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// internals ...
|
||||
|
||||
@@ -1026,7 +1079,7 @@ public enum Apple2Preferences {
|
||||
file = new File(fullPath);
|
||||
}
|
||||
if (file.exists()) {
|
||||
activity.nativeChooseDisk(fullPath, isDriveA, isReadOnly);
|
||||
activity.chooseDisk(fullPath, isDriveA, isReadOnly);
|
||||
} else {
|
||||
Log.d(TAG, "Cannot insert: " + fullPath);
|
||||
}
|
||||
@@ -1058,14 +1111,18 @@ public enum Apple2Preferences {
|
||||
|
||||
private static native void nativeSetTouchJoystickVisibility(boolean visibility);
|
||||
|
||||
private static native void nativeSetTouchJoystickAzimuthVisibility(boolean visibility);
|
||||
|
||||
public static native void nativeSetTouchMenuEnabled(boolean enabled);
|
||||
|
||||
private static native void nativeSetTouchMenuVisibility(float alpha);
|
||||
public static native void nativeSetShowDiskOperationAnimation(boolean enabled);
|
||||
|
||||
private static native void nativeSetTouchKeyboardVisibility(float inactiveAlpha, float activeAlpha);
|
||||
|
||||
private static native void nativeSetTouchKeyboardLowercaseEnabled(boolean enabled);
|
||||
|
||||
private static native void nativeSetTouchKeyboardGlyphScale(int scale);
|
||||
|
||||
public static native int nativeGetCurrentTouchDevice();
|
||||
|
||||
public static native int nativeGetCPUSpeed();
|
||||
|
||||
@@ -52,7 +52,7 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
|
||||
if (position < 0 || position >= SETTINGS.size) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return position != SETTINGS.TOUCH_MENU_VISIBILITY.ordinal();
|
||||
return true;
|
||||
}
|
||||
|
||||
enum SETTINGS implements Apple2AbstractMenu.IMenuEnum {
|
||||
@@ -194,61 +194,30 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
|
||||
});
|
||||
}
|
||||
},
|
||||
TOUCH_MENU_ENABLED {
|
||||
SHOW_DISK_OPERATIONS {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.touch_menu_enable);
|
||||
return activity.getResources().getString(R.string.disk_show_operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSummary(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.touch_menu_enable_summary);
|
||||
return activity.getResources().getString(R.string.disk_show_operation_summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final Apple2Activity activity, View convertView) {
|
||||
convertView = _basicView(activity, this, convertView);
|
||||
CheckBox cb = _addCheckbox(activity, this, convertView, Apple2Preferences.TOUCH_MENU_ENABLED.booleanValue(activity));
|
||||
CheckBox cb = _addCheckbox(activity, this, convertView, Apple2Preferences.SHOW_DISK_OPERATIONS.booleanValue(activity));
|
||||
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
Apple2Preferences.TOUCH_MENU_ENABLED.saveBoolean(activity, isChecked);
|
||||
Apple2Preferences.SHOW_DISK_OPERATIONS.saveBoolean(activity, isChecked);
|
||||
}
|
||||
});
|
||||
return convertView;
|
||||
}
|
||||
},
|
||||
TOUCH_MENU_VISIBILITY {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.touch_menu_visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSummary(Apple2Activity activity) {
|
||||
return activity.getResources().getString(R.string.touch_menu_visibility_summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final Apple2Activity activity, View convertView) {
|
||||
return _sliderView(activity, this, Apple2Preferences.ALPHA_SLIDER_NUM_CHOICES, new IPreferenceSlider() {
|
||||
@Override
|
||||
public void saveInt(int progress) {
|
||||
Apple2Preferences.TOUCH_MENU_VISIBILITY.saveInt(activity, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return Apple2Preferences.TOUCH_MENU_VISIBILITY.intValue(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showValue(int progress, final TextView seekBarValue) {
|
||||
seekBarValue.setText("" + ((float) progress / Apple2Preferences.ALPHA_SLIDER_NUM_CHOICES));
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
ABOUT {
|
||||
@Override
|
||||
public final String getTitle(Apple2Activity activity) {
|
||||
|
||||
@@ -23,11 +23,13 @@ public class Apple2SplashScreen implements Apple2MenuView {
|
||||
private final static String TAG = "Apple2SplashScreen";
|
||||
|
||||
private Apple2Activity mActivity = null;
|
||||
private boolean mDismissable = true;
|
||||
private View mSettingsView = null;
|
||||
|
||||
public Apple2SplashScreen(Apple2Activity activity) {
|
||||
public Apple2SplashScreen(Apple2Activity activity, boolean dismissable) {
|
||||
mActivity = activity;
|
||||
setup();
|
||||
setDismissable(dismissable);
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
@@ -46,9 +48,8 @@ public class Apple2SplashScreen implements Apple2MenuView {
|
||||
prefsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Apple2SettingsMenu settingsMenu = mActivity.getMainMenu().getSettingsMenu();
|
||||
Apple2SettingsMenu settingsMenu = mActivity.getSettingsMenu();
|
||||
settingsMenu.show();
|
||||
Apple2SplashScreen.this.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -56,9 +57,23 @@ public class Apple2SplashScreen implements Apple2MenuView {
|
||||
disksButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Apple2DisksMenu disksMenu = mActivity.getMainMenu().getDisksMenu();
|
||||
Apple2DisksMenu disksMenu = mActivity.getDisksMenu();
|
||||
disksMenu.show();
|
||||
Apple2SplashScreen.this.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setDismissable(boolean dismissable) {
|
||||
mDismissable = dismissable;
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Button startButton = (Button) mSettingsView.findViewById(R.id.startButton);
|
||||
startButton.setEnabled(mDismissable);
|
||||
Button prefsButton = (Button) mSettingsView.findViewById(R.id.prefsButton);
|
||||
prefsButton.setEnabled(mDismissable);
|
||||
Button disksButton = (Button) mSettingsView.findViewById(R.id.disksButton);
|
||||
disksButton.setEnabled(mDismissable);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -71,7 +86,7 @@ public class Apple2SplashScreen implements Apple2MenuView {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
public synchronized void show() {
|
||||
public void show() {
|
||||
if (isShowing()) {
|
||||
return;
|
||||
}
|
||||
@@ -79,7 +94,9 @@ public class Apple2SplashScreen implements Apple2MenuView {
|
||||
}
|
||||
|
||||
public void dismiss() {
|
||||
mActivity.popApple2View(this);
|
||||
if (mDismissable) {
|
||||
mActivity.popApple2View(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void dismissAll() {
|
||||
@@ -87,7 +104,7 @@ public class Apple2SplashScreen implements Apple2MenuView {
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mSettingsView.isShown();
|
||||
return mSettingsView.getParent() != null;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
|
||||
@@ -15,10 +15,19 @@
|
||||
|
||||
package org.deadc0de.apple2ix;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.media.AudioManager;
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import com.example.inputmanagercompat.InputManagerCompat;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
@@ -26,37 +35,61 @@ import javax.microedition.khronos.egl.EGLContext;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
/**
|
||||
* A simple GLSurfaceView sub-class that demonstrate how to perform
|
||||
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
|
||||
* details:
|
||||
*
|
||||
* - The class must use a custom context factory to enable 2.0 rendering.
|
||||
* See ContextFactory class definition below.
|
||||
*
|
||||
* - The class must use a custom EGLConfigChooser to be able to select
|
||||
* an EGLConfig that supports 2.0. This is done by providing a config
|
||||
* specification to eglChooseConfig() that has the attribute
|
||||
* EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag
|
||||
* set. See ConfigChooser class definition below.
|
||||
*
|
||||
* - The class must select the surface's format, then choose an EGLConfig
|
||||
* that matches it exactly (with regards to red/green/blue/alpha channels
|
||||
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
|
||||
*/
|
||||
class Apple2View extends GLSurfaceView {
|
||||
class Apple2View extends GLSurfaceView implements InputManagerCompat.InputDeviceListener {
|
||||
private final static String TAG = "Apple2View";
|
||||
private final static boolean DEBUG = false;
|
||||
private final static int MAX_FINGERS = 32;// HACK ...
|
||||
|
||||
private Apple2Activity mActivity = null;
|
||||
public final static long NATIVE_TOUCH_HANDLED = (1 << 0);
|
||||
public final static long NATIVE_TOUCH_REQUEST_SHOW_MENU = (1 << 1);
|
||||
|
||||
public Apple2View(Apple2Activity activity) {
|
||||
public final static long NATIVE_TOUCH_KEY_TAP = (1 << 4);
|
||||
public final static long NATIVE_TOUCH_KBD = (1 << 5);
|
||||
public final static long NATIVE_TOUCH_JOY = (1 << 6);
|
||||
public final static long NATIVE_TOUCH_MENU = (1 << 7);
|
||||
public final static long NATIVE_TOUCH_JOY_KPAD = (1 << 8);
|
||||
|
||||
public final static long NATIVE_TOUCH_INPUT_DEVICE_CHANGED = (1 << 16);
|
||||
public final static long NATIVE_TOUCH_CPU_SPEED_DEC = (1 << 17);
|
||||
public final static long NATIVE_TOUCH_CPU_SPEED_INC = (1 << 18);
|
||||
|
||||
public final static long NATIVE_TOUCH_ASCII_SCANCODE_SHIFT = 32;
|
||||
public final static long NATIVE_TOUCH_ASCII_SCANCODE_MASK = 0xFFFFL;
|
||||
public final static long NATIVE_TOUCH_ASCII_MASK = 0xFF00L;
|
||||
public final static long NATIVE_TOUCH_SCANCODE_MASK = 0x00FFL;
|
||||
|
||||
|
||||
private Apple2Activity mActivity;
|
||||
private Runnable mGraphicsInitializedRunnable;
|
||||
private final InputManagerCompat mInputManager;
|
||||
|
||||
private float[] mXCoords = new float[MAX_FINGERS];
|
||||
private float[] mYCoords = new float[MAX_FINGERS];
|
||||
|
||||
|
||||
private static native void nativeGraphicsInitialized(int width, int height);
|
||||
|
||||
private static native void nativeGraphicsChanged(int width, int height);
|
||||
|
||||
private static native void nativeRender();
|
||||
|
||||
private static native void nativeOnJoystickMove(int x, int y);
|
||||
|
||||
public static native long nativeOnTouch(int action, int pointerCount, int pointerIndex, float[] xCoords, float[] yCoords);
|
||||
|
||||
|
||||
public Apple2View(Apple2Activity activity, Runnable graphicsInitializedRunnable) {
|
||||
super(activity.getApplication());
|
||||
mActivity = activity;
|
||||
setup(0, 0);
|
||||
}
|
||||
mGraphicsInitializedRunnable = graphicsInitializedRunnable;
|
||||
|
||||
private void setup(int depth, int stencil) {
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
|
||||
mInputManager = InputManagerCompat.Factory.getInputManager(this.getContext());
|
||||
if (mInputManager != null) {
|
||||
mInputManager.registerInputDeviceListener(this, null);
|
||||
}
|
||||
|
||||
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
|
||||
* If we want a translucent one, we should change the surface's
|
||||
@@ -75,18 +108,40 @@ class Apple2View extends GLSurfaceView {
|
||||
* custom config chooser. See ConfigChooser class definition
|
||||
* below.
|
||||
*/
|
||||
setEGLConfigChooser(new ConfigChooser(8, 8, 8, 8, depth, stencil));
|
||||
setEGLConfigChooser(new ConfigChooser(8, 8, 8, 8, /*depth:*/0, /*stencil:*/0));
|
||||
|
||||
/* Set the renderer responsible for frame rendering */
|
||||
setRenderer(new Renderer());
|
||||
|
||||
// Another Android Annoyance ...
|
||||
// Even though we no longer use the system soft keyboard (which would definitely trigger width/height changes to our OpenGL canvas),
|
||||
// we still need to listen to dimension changes, because it seems on some janky devices you have an incorrect width/height set when
|
||||
// the initial OpenGL onSurfaceChanged() callback occurs. For now, include this defensive coding...
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
public void onGlobalLayout() {
|
||||
Rect rect = new Rect();
|
||||
Apple2View.this.getWindowVisibleDisplayFrame(rect);
|
||||
int h = rect.height();
|
||||
int w = rect.width();
|
||||
if (w < h) {
|
||||
// assure landscape dimensions
|
||||
final int w_ = w;
|
||||
w = h;
|
||||
h = w_;
|
||||
}
|
||||
nativeGraphicsChanged(w, h);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
|
||||
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
|
||||
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
|
||||
Log.w(TAG, "creating OpenGL ES 2.0 context");
|
||||
checkEglError("Before eglCreateContext", egl);
|
||||
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
|
||||
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
|
||||
EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
|
||||
checkEglError("After eglCreateContext", egl);
|
||||
return context;
|
||||
@@ -121,12 +176,12 @@ class Apple2View extends GLSurfaceView {
|
||||
*/
|
||||
private static int EGL_OPENGL_ES2_BIT = 4;
|
||||
private static int[] s_configAttribs2 = {
|
||||
EGL10.EGL_RED_SIZE, 4,
|
||||
EGL10.EGL_GREEN_SIZE, 4,
|
||||
EGL10.EGL_BLUE_SIZE, 4,
|
||||
EGL10.EGL_ALPHA_SIZE, 4,
|
||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL10.EGL_NONE
|
||||
EGL10.EGL_RED_SIZE, 4,
|
||||
EGL10.EGL_GREEN_SIZE, 4,
|
||||
EGL10.EGL_BLUE_SIZE, 4,
|
||||
EGL10.EGL_ALPHA_SIZE, 4,
|
||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
||||
@@ -146,7 +201,7 @@ class Apple2View extends GLSurfaceView {
|
||||
egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
|
||||
|
||||
if (DEBUG) {
|
||||
printConfigs(egl, display, configs);
|
||||
printConfigs(egl, display, configs);
|
||||
}
|
||||
|
||||
// Now return the "best" one
|
||||
@@ -275,11 +330,11 @@ class Apple2View extends GLSurfaceView {
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
int attribute = attributes[i];
|
||||
String name = names[i];
|
||||
if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
|
||||
if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
|
||||
Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
|
||||
} else {
|
||||
// Log.w(TAG, String.format(" %s: failed\n", name));
|
||||
while (egl.eglGetError() != EGL10.EGL_SUCCESS);
|
||||
while (egl.eglGetError() != EGL10.EGL_SUCCESS) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,19 +350,229 @@ class Apple2View extends GLSurfaceView {
|
||||
}
|
||||
|
||||
private class Renderer implements GLSurfaceView.Renderer {
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(GL10 gl) {
|
||||
Apple2View.this.mActivity.nativeRender();
|
||||
nativeRender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||
Apple2Preferences.GL_VENDOR.saveString(mActivity, GLES20.glGetString(GLES20.GL_VENDOR));
|
||||
Apple2Preferences.GL_RENDERER.saveString(mActivity, GLES20.glGetString(GLES20.GL_RENDERER));
|
||||
Apple2Preferences.GL_VERSION.saveString(mActivity, GLES20.glGetString(GLES20.GL_VERSION));
|
||||
Apple2View.this.mActivity.graphicsInitialized(width, height);
|
||||
|
||||
Log.v(TAG, "graphicsInitialized(" + width + ", " + height + ")");
|
||||
|
||||
if (width < height) {
|
||||
// assure landscape dimensions
|
||||
final int w_ = width;
|
||||
width = height;
|
||||
height = w_;
|
||||
}
|
||||
|
||||
nativeGraphicsInitialized(width, height);
|
||||
|
||||
if (Apple2View.this.mGraphicsInitializedRunnable != null) {
|
||||
Apple2View.this.mGraphicsInitializedRunnable.run();
|
||||
Apple2View.this.mGraphicsInitializedRunnable = null;
|
||||
}
|
||||
|
||||
Apple2View.this.mActivity.maybeResumeEmulation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Event handling, touch, keyboard, gamepad
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int deviceId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
return super.onGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
if (mActivity.isEmulationPaused()) {
|
||||
return super.onGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
// Check that the event came from a joystick or gamepad since a generic
|
||||
// motion event could be almost anything.
|
||||
int eventSource = event.getSource();
|
||||
if ((event.getAction() == MotionEvent.ACTION_MOVE) && (((eventSource & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || ((eventSource & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK))) {
|
||||
int id = event.getDeviceId();
|
||||
if (id != -1) {
|
||||
|
||||
InputDevice device = event.getDevice();
|
||||
|
||||
float x = getCenteredAxis(event, device, MotionEvent.AXIS_X);
|
||||
if (x == 0) {
|
||||
x = getCenteredAxis(event, device, MotionEvent.AXIS_HAT_X);
|
||||
}
|
||||
if (x == 0) {
|
||||
x = getCenteredAxis(event, device, MotionEvent.AXIS_Z);
|
||||
}
|
||||
|
||||
float y = getCenteredAxis(event, device, MotionEvent.AXIS_Y);
|
||||
if (y == 0) {
|
||||
y = getCenteredAxis(event, device, MotionEvent.AXIS_HAT_Y);
|
||||
}
|
||||
if (y == 0) {
|
||||
y = getCenteredAxis(event, device, MotionEvent.AXIS_RZ);
|
||||
}
|
||||
|
||||
int normal_x = (int) ((x + 1.f) * 128.f);
|
||||
if (normal_x < 0) {
|
||||
normal_x = 0;
|
||||
}
|
||||
if (normal_x > 255) {
|
||||
normal_x = 255;
|
||||
}
|
||||
int normal_y = (int) ((y + 1.f) * 128.f);
|
||||
if (normal_y < 0) {
|
||||
normal_y = 0;
|
||||
}
|
||||
if (normal_y > 255) {
|
||||
normal_y = 255;
|
||||
}
|
||||
|
||||
nativeOnJoystickMove(normal_x, normal_y);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.onGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
private static float getCenteredAxis(MotionEvent event, InputDevice device, int axis) {
|
||||
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final InputDevice.MotionRange range = device.getMotionRange(axis, event.getSource());
|
||||
if (range != null) {
|
||||
final float flat = range.getFlat();
|
||||
final float value = event.getAxisValue(axis);
|
||||
|
||||
// Ignore axis values that are within the 'flat' region of the joystick axis center.
|
||||
// A joystick at rest does not always report an absolute position of (0,0).
|
||||
if (Math.abs(value) > flat) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
do {
|
||||
|
||||
if (Apple2Activity.isNativeBarfed()) {
|
||||
break;
|
||||
}
|
||||
if (mActivity.getMainMenu() == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
Apple2MenuView apple2MenuView = mActivity.peekApple2View();
|
||||
if ((apple2MenuView != null) && (!apple2MenuView.isCalibrating())) {
|
||||
break;
|
||||
}
|
||||
|
||||
//printSamples(event);
|
||||
int action = event.getActionMasked();
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int pointerCount = event.getPointerCount();
|
||||
for (int i = 0; i < pointerCount/* && i < MAX_FINGERS */; i++) {
|
||||
mXCoords[i] = event.getX(i);
|
||||
mYCoords[i] = event.getY(i);
|
||||
}
|
||||
|
||||
long nativeFlags = nativeOnTouch(action, pointerCount, pointerIndex, mXCoords, mYCoords);
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_HANDLED) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_REQUEST_SHOW_MENU) != 0) {
|
||||
mActivity.getMainMenu().show();
|
||||
}
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_KEY_TAP) != 0) {
|
||||
if (Apple2Preferences.KEYBOARD_CLICK_ENABLED.booleanValue(mActivity)) {
|
||||
AudioManager am = (AudioManager) mActivity.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (am != null) {
|
||||
am.playSoundEffect(AudioManager.FX_KEY_CLICK);
|
||||
}
|
||||
}
|
||||
|
||||
if ((apple2MenuView != null) && apple2MenuView.isCalibrating()) {
|
||||
long asciiScancodeLong = nativeFlags & (NATIVE_TOUCH_ASCII_SCANCODE_MASK << NATIVE_TOUCH_ASCII_SCANCODE_SHIFT);
|
||||
int asciiInt = (int) (asciiScancodeLong >> (NATIVE_TOUCH_ASCII_SCANCODE_SHIFT + 8));
|
||||
int scancode = (int) ((asciiScancodeLong >> NATIVE_TOUCH_ASCII_SCANCODE_SHIFT) & 0xFFL);
|
||||
char ascii = (char) asciiInt;
|
||||
apple2MenuView.onKeyTapCalibrationEvent(ascii, scancode);
|
||||
}
|
||||
}
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_MENU) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// handle menu-specific actions
|
||||
|
||||
if ((nativeFlags & NATIVE_TOUCH_INPUT_DEVICE_CHANGED) != 0) {
|
||||
Apple2Preferences.TouchDeviceVariant nextVariant;
|
||||
if ((nativeFlags & NATIVE_TOUCH_KBD) != 0) {
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.KEYBOARD;
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_JOY) != 0) {
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.JOYSTICK;
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_JOY_KPAD) != 0) {
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.JOYSTICK_KEYPAD;
|
||||
} else {
|
||||
int touchDevice = Apple2Preferences.nativeGetCurrentTouchDevice();
|
||||
nextVariant = Apple2Preferences.TouchDeviceVariant.next(touchDevice);
|
||||
}
|
||||
Apple2Preferences.CURRENT_TOUCH_DEVICE.saveTouchDevice(mActivity, nextVariant);
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_CPU_SPEED_DEC) != 0) {
|
||||
int percentSpeed = Apple2Preferences.nativeGetCPUSpeed();
|
||||
if (percentSpeed > 400) { // HACK: max value from native side
|
||||
percentSpeed = 375;
|
||||
} else if (percentSpeed > 100) {
|
||||
percentSpeed -= 25;
|
||||
} else {
|
||||
percentSpeed -= 5;
|
||||
}
|
||||
Apple2Preferences.CPU_SPEED_PERCENT.saveInt(mActivity, percentSpeed);
|
||||
} else if ((nativeFlags & NATIVE_TOUCH_CPU_SPEED_INC) != 0) {
|
||||
int percentSpeed = Apple2Preferences.nativeGetCPUSpeed();
|
||||
if (percentSpeed >= 100) {
|
||||
percentSpeed += 25;
|
||||
} else {
|
||||
percentSpeed += 5;
|
||||
}
|
||||
Apple2Preferences.CPU_SPEED_PERCENT.saveInt(mActivity, percentSpeed);
|
||||
}
|
||||
} while (false);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
162
Android/app/src/main/res/values-de/strings.xml
Normal file
@@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<color name="black">#000000</color>
|
||||
<color name="white">#ffffff</color>
|
||||
|
||||
<!-- developer-only options -->
|
||||
<string name="crasher_summary">Test crash generation</string>
|
||||
<string name="crasher_title">Crash emulator</string>
|
||||
<string name="crash_null">NULL-deref</string>
|
||||
<string name="crash_java_npe">Java NPE</string>
|
||||
<string name="crash_stackcall_overflow">stack call overflow</string>
|
||||
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
|
||||
|
||||
<!-- main options -->
|
||||
<string name="about_apple2ix">Über Apple2ix…</string>
|
||||
<string name="about_apple2ix_summary">Über diese Software</string>
|
||||
<string name="app_name">Apple2ix</string>
|
||||
<string name="audio_configure">Audio-Konfiguration…</string>
|
||||
<string name="audio_configure_summary">Lautstärke, Mockingboard, etc</string>
|
||||
<string name="audio_latency">Audio Latency</string>
|
||||
<string name="audio_latency_summary">Audio Latency in Sek.</string>
|
||||
<string name="cancel">Abbrechen</string>
|
||||
<string name="color_bw">Schwarz/Weiss</string>
|
||||
<string name="color_color">Farbe</string>
|
||||
<string name="color_interpolated">Interpolierte Farben</string>
|
||||
<string name="crasher">Abstürze</string>
|
||||
<string name="crasher_check_title">Prüfe auf Absturz-Berichte</string>
|
||||
<string name="crasher_check_summary">Prüfe auf Absturz-Berichte zum Versand an den Entwickler</string>
|
||||
<string name="crasher_send">Sende Absturz-Bericht?</string>
|
||||
<string name="crasher_send_message">Entschuldigung. es gab ein Problemm. Möchten Sie einen Absturz-Bericht an den Entwickler senden?</string>
|
||||
<string name="diskA">Laufwerk 1</string>
|
||||
<string name="diskB">Laufwerk 2</string>
|
||||
<string name="disk_eject">Auswerfen</string>
|
||||
<string name="disk_insert_toast">Die eingelegte Diskette ist schreibgeschützt</string>
|
||||
<string name="disk_insert_could_not_read">Entschuldigung, das Diskettenabbild konnte nicht gelesen werden!</string>
|
||||
<string name="disk_read_only">Schreibgeschützt</string>
|
||||
<string name="disk_read_write">Lesen/Schreiben</string>
|
||||
<string name="disk_show_operation">Zeige Disk ][ Aktivität</string>
|
||||
<string name="disk_show_operation_summary">Zeigt wenn die Laufwerke lesen oder schreiben</string>
|
||||
<string name="emulation_continue">Fortsetzen…</string>
|
||||
<string name="emulation_settings">Einstellungen…</string>
|
||||
<string name="emulation_disks">Lade Disk-Image…</string>
|
||||
<string name="header_disks">Diskette einlegen:</string>
|
||||
<string name="input_current">Aktuelles Touch Device</string>
|
||||
<string name="input_current_summary">Wähle ein aktuelles Touch Device</string>
|
||||
<string name="joystick">Joystick</string>
|
||||
<string name="joystick_axis_sensitivity_summary">Empfindlichkeiteinstellung der Joystickachsen (verlangsamen or beschleunigen)</string>
|
||||
<string name="joystick_button_button1">Button 1 (Offener Apfel)</string>
|
||||
<string name="joystick_button_button2">Button 2 (Geschlossener Apfel)</string>
|
||||
<string name="joystick_button_button_both">Beide</string>
|
||||
<string name="joystick_button_button_none">Keine</string>
|
||||
<string name="joystick_button_tap_button">Drücke den Feuerknopf</string>
|
||||
<string name="joystick_button_tap_button_summary">Ausgewählter Feuerknopf</string>
|
||||
<string name="joystick_button_tapdelay_summary">Joystickknopf-Zeitverzögerung in Sek.</string>
|
||||
<string name="joystick_button_swipe_up_button">Aufwärts wischen zum feuern</string>
|
||||
<string name="joystick_button_swipe_up_button_summary">Feuerknopf zum feuern beim aufwärts wischen</string>
|
||||
<string name="joystick_button_swipe_down_button">Abwärts wischen zum feuern</string>
|
||||
<string name="joystick_button_swipe_down_button_summary">Feuerknopf zum feuern beim abwärts wischen</string>
|
||||
<string name="joystick_button_threshold_summary">Joystick/Keypad Knopf Schaltschwellwert in pts</string>
|
||||
<string name="joystick_calibrate">Kalibrieren…</string>
|
||||
<string name="joystick_calibrate_summary">Konfiguriere und teste die aktuellen Einstellungen</string>
|
||||
<string name="joystick_configure">Joystickkonfiguration…</string>
|
||||
<string name="joystick_configure_summary">Achsen Touch, Knöpfe, etc</string>
|
||||
<string name="joystick_axisleft">Joystick/Keypad Achse links</string>
|
||||
<string name="joystick_axisleft_summary">Joystick/Keypad Achse links (Knöpfe rechts)</string>
|
||||
<string name="joystick_visible">Sichtbarkeit Joystick/Keypad</string>
|
||||
<string name="joystick_visible_summary">Zeige die Kontrollen als Overlay wenn aktiviert</string>
|
||||
<string name="key_closed_apple">[GeschlossenerApfel]</string>
|
||||
<string name="key_ctrl">[Strg]</string>
|
||||
<string name="key_down">↓</string>
|
||||
<string name="key_esc">[ESC]</string>
|
||||
<string name="key_left">←</string>
|
||||
<string name="key_none">[Keine]</string>
|
||||
<string name="key_open_apple">[OffenerApfel]</string>
|
||||
<string name="key_ret">[Return]</string>
|
||||
<string name="key_right">→</string>
|
||||
<string name="key_space">[Space]</string>
|
||||
<string name="key_up">↑</string>
|
||||
<string name="keyboard">Tastatur</string>
|
||||
<string name="keyboard_choose_alt">Wähle alternative Tastatur…</string>
|
||||
<string name="keyboard_choose_alt_summary">Wähle alternativ konfiguriertes Layout</string>
|
||||
<string name="keyboard_click_enabled">Tastenton einschalten</string>
|
||||
<string name="keyboard_click_enabled_summary">Aktiviert Tastenton wenn verfügbar</string>
|
||||
<string name="keyboard_configure">Tastatur-Konfiguration…</string>
|
||||
<string name="keyboard_configure_summary">Transparenz, Kleinbuchstaben, eigene Tasten</string>
|
||||
<string name="keyboard_glyph_scale">Tastatur-Glyphenskalierung 2x</string>
|
||||
<string name="keyboard_glyph_scale_summary">(Lässt die Tastaur weniger pixelig erscheinen auf grossen Bildschirmen)</string>
|
||||
<string name="keyboard_lowercase_enabled">Kleinbuchstaben aktivieren</string>
|
||||
<string name="keyboard_lowercase_enabled_summary">Aktiviren der Tasten für Kleinbuchstaben</string>
|
||||
<string name="keyboard_visibility_active">Sichtbarkeit wenn aktiviert</string>
|
||||
<string name="keyboard_visibility_active_summary">Sichtbarkeit des Keyboard und Touch Menüs wenn aktiviert</string>
|
||||
<string name="keyboard_visibility_inactive">Sichtbarkeit wenn deaktiviert</string>
|
||||
<string name="keyboard_visibility_inactive_summary">Sichtbarkeit des Keyboard und Touch Menüs wenn deaktiviert</string>
|
||||
<string name="keypad">Keypad Joystick</string>
|
||||
<string name="keypad_calibrate">@string/joystick_calibrate</string>
|
||||
<string name="keypad_calibrate_summary">@string/joystick_calibrate</string>
|
||||
<string name="keypad_choose">Auswahl der Keypad Tasten…</string>
|
||||
<string name="keypad_choose_summary">Auswahl der Achsen und Knopf Tasten</string>
|
||||
<string name="keypad_choose_title">Achse & Knöpfe</string>
|
||||
<string name="keypad_choose_current">Wähle XXX Taste: </string>
|
||||
<string name="keypad_configure">Konfiguration Joystick Keypad…</string>
|
||||
<string name="keypad_configure_summary">@string/joystick_configure_summary</string>
|
||||
<string name="keypad_key_axis_c">Mitte</string>
|
||||
<string name="keypad_key_axis_dn">Unten</string>
|
||||
<string name="keypad_key_axis_dl">Unten und Links</string>
|
||||
<string name="keypad_key_axis_dr">Unten und Rechts</string>
|
||||
<string name="keypad_key_axis_l">Links</string>
|
||||
<string name="keypad_key_axis_r">Rechts</string>
|
||||
<string name="keypad_key_axis_ul">Oben und Links</string>
|
||||
<string name="keypad_key_axis_up">Oben</string>
|
||||
<string name="keypad_key_axis_ur">Oben und Rechts</string>
|
||||
<string name="keypad_key_button_tap">antippen</string>
|
||||
<string name="keypad_key_button_swipeup">Nach oben wischen</string>
|
||||
<string name="keypad_key_button_swipedown">Nach unten wischen</string>
|
||||
<string name="keypad_preset_crazy_seafox">Seafox Tasten ;-)…</string>
|
||||
<string name="keypad_preset_custom">Auswahl einer Anpassung…</string>
|
||||
<string name="keypad_preset_arrows_space">↑,←,→,↓, tippe auf die Leerstaste</string>
|
||||
<string name="keypad_preset_az_left_right_space">A,Z,←,→, tippe auf die Leertaste</string>
|
||||
<string name="keypad_preset_ijkm_space">I,J,K,M, tippe auf die Leertaste</string>
|
||||
<string name="keypad_preset_left_right_space">←,→, tippe auf die Leertaste</string>
|
||||
<string name="keypad_preset_wadx_space">W,A,D,X, tippe auf die Leertaste</string>
|
||||
<string name="keypad_repeat_summary">Tastenwiederholungsschwellwert in Sek.</string>
|
||||
<string name="menu_disks">Lade Disk-Image…</string>
|
||||
<string name="menu_disks_summary">Einlegen eines Disk ][ Image</string>
|
||||
<string name="menu_settings">Emulator Einstellungen…</string>
|
||||
<string name="menu_settings_summary">Allgemeine Einstellungen, Joystick, Tastatur</string>
|
||||
<string name="mockingboard_disabled_title">Mockingboard deaktiviert</string>
|
||||
<string name="mockingboard_disabled_mesg">Mockingboard konnte nicht aktiviert werden</string>
|
||||
<string name="mockingboard_enable">Aktiviere Mockingboard</string>
|
||||
<string name="mockingboard_enable_summary">Revision C in Slot 4/5 (evtl. wird ein Restart benötigt)</string>
|
||||
<string name="mockingboard_volume">Mockingboard Lautstärke</string>
|
||||
<string name="mockingboard_volume_summary">Einstellen der Mockingboard Lautstärke</string>
|
||||
<string name="no">Nein</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preferences_reset_title">Einstellungen zurücksetzen</string>
|
||||
<string name="preferences_reset_summary">Einstellungen auf Standard zurücksetzen und Emulator beenden</string>
|
||||
<string name="preferences_reset_really">Wollen Sie wirklich resetten und beenden?</string>
|
||||
<string name="preferences_reset_warning">Sie werden alle Ihre Einstellungen verlieren</string>
|
||||
<string name="quit">Beenden</string>
|
||||
<string name="quit_reboot">Neustart oder beenden des Emulators…</string>
|
||||
<string name="quit_reboot_choice">Neustart oder beenden?</string>
|
||||
<string name="reboot">Neustart</string>
|
||||
<string name="restore">Schnelle Wiederherstellung</string>
|
||||
<string name="save">Schnelle Speicherung</string>
|
||||
<string name="saverestore">Speichern & wiederherstellen…</string>
|
||||
<string name="saverestore_choice">Aktuellen Status sichern oder vorherigen wiederherstellen?</string>
|
||||
<string name="saverestore_summary">Schnellspeicherung und Wiederherstellung</string>
|
||||
<string name="skip">Überspringen→</string>
|
||||
<string name="speaker_volume">Lautsprecherlautstärke</string>
|
||||
<string name="speaker_volume_summary">Lautsprecherlautstärke einstellen</string>
|
||||
<string name="settings">Apple2ix Emulator Einstellungen</string>
|
||||
<string name="settings_advanced">Erweiterte Einstellungen</string>
|
||||
<string name="settings_advanced_summary">Warnung: diese Einstellungen verschlechtern die Performance</string>
|
||||
<string name="settings_advanced_joystick">Erweiterte Joystick/Keypad Einstellungen</string>
|
||||
<string name="settings_advanced_joystick_summary">Erweiterte Einstellungen für das Performance-Tuning</string>
|
||||
<string name="touch_menu_enable">Aktiviere Touch Menüs</string>
|
||||
<string name="touch_menu_enable_summary">Aktiviere Softmenü Knöpfe in den oberen Ecken des Bildschirms</string>
|
||||
<string name="video_configure">Video-Konfiguration…</string>
|
||||
<string name="video_configure_summary">Farbeinstellungen</string>
|
||||
|
||||
</resources>
|
||||
160
Android/app/src/main/res/values-es/strings.xml
Normal file
@@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<color name="black">#000000</color>
|
||||
<color name="white">#ffffff</color>
|
||||
|
||||
<!-- developer-only options -->
|
||||
<string name="crasher_summary">Test crash generation</string>
|
||||
<string name="crasher_title">Crash emulator</string>
|
||||
<string name="crash_null">NULL-deref</string>
|
||||
<string name="crash_java_npe">Java NPE</string>
|
||||
<string name="crash_stackcall_overflow">stack call overflow</string>
|
||||
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
|
||||
|
||||
<!-- main options -->
|
||||
<string name="about_apple2ix">Acerca de Apple2ix…</string>
|
||||
<string name="about_apple2ix_summary">Acerca de este software</string>
|
||||
<string name="app_name">Apple2ix</string>
|
||||
<string name="audio_configure">Configurar audio…</string>
|
||||
<string name="audio_configure_summary">Ajustar el volumen del altavoz, "Mockingboard", etc</string>
|
||||
<string name="audio_latency">La latencia de audio</string>
|
||||
<string name="audio_latency_summary">La latencia de audio en segundos</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="color_bw">Blanco/negro</string>
|
||||
<string name="color_color">Color</string>
|
||||
<string name="color_interpolated">Color interpolado</string>
|
||||
<string name="crasher">Fallos del software</string>
|
||||
<string name="crasher_check_title">Fallos del software</string>
|
||||
<string name="crasher_check_summary">Verificar la presencia de fallos del software</string>
|
||||
<string name="crasher_send">¿Enviar informe de error?</string>
|
||||
<string name="crasher_send_message">Lo sentimos, ha habido un problema. ¿Desea enviar informe de error para el programador de software?</string>
|
||||
<string name="diskA">Disquetera 1</string>
|
||||
<string name="diskB">Disquetera 2</string>
|
||||
<string name="disk_eject">Eyectar</string>
|
||||
<string name="disk_insert_toast">Disco insertado en la disquetera de sólo lectura</string>
|
||||
<string name="disk_insert_could_not_read">Lo sentimos, no se puede leer la imagen de disquete!</string>
|
||||
<string name="disk_read_only">Sólo leer</string>
|
||||
<string name="disk_read_write">Leer y escribir</string>
|
||||
<string name="disk_show_operation">Mostrar las operaciones de "Disk ]["</string>
|
||||
<string name="disk_show_operation_summary">Shows when disk drives are reading or writing</string>
|
||||
<string name="emulation_continue">Continuar…</string>
|
||||
<string name="emulation_settings">Configuración…</string>
|
||||
<string name="emulation_disks">Insertar imagen de disquete…</string>
|
||||
<string name="header_disks">Insertar imagen de disquete:</string>
|
||||
<string name="input_current">Unidad de entrada actual</string>
|
||||
<string name="input_current_summary">Elija unidad de entrada</string>
|
||||
<string name="joystick">"Joystick"</string>
|
||||
<string name="joystick_axis_sensitivity_summary">Afinar la sensibilidad del eje del joystick (desacelerar o acelerar)</string>
|
||||
<string name="joystick_button_button1">Botón 1</string>
|
||||
<string name="joystick_button_button2">Botón 2</string>
|
||||
<string name="joystick_button_button_both">Los dos</string>
|
||||
<string name="joystick_button_button_none">Ninguno</string>
|
||||
<string name="joystick_button_tap_button">Toque para disparar</string>
|
||||
<string name="joystick_button_tap_button_summary">Botón para disparar sobre toque abajo</string>
|
||||
<string name="joystick_button_tapdelay_summary">Toque retardo del joystick en segundos</string>
|
||||
<string name="joystick_button_swipe_up_button">Pase hacia arriba</string>
|
||||
<string name="joystick_button_swipe_up_button_summary">Botón para disparar sobre pase el dedo hacia arriba</string>
|
||||
<string name="joystick_button_swipe_down_button">Pase hacia abajo</string>
|
||||
<string name="joystick_button_swipe_down_button_summary">Botón para disparar sobre pase el dedo hacia abajo</string>
|
||||
<string name="joystick_button_threshold_summary">Umbral del joystick en puntos</string>
|
||||
<string name="joystick_calibrate">Calibrar…</string>
|
||||
<string name="joystick_calibrate_summary">Calibrar el joystick</string>
|
||||
<string name="joystick_configure">Configurar el joystick…</string>
|
||||
<string name="joystick_configure_summary">Eje táctil, los botónes, etc</string>
|
||||
<string name="joystick_axisleft">Eje del joystick a la izquierda</string>
|
||||
<string name="joystick_axisleft_summary">Eje del joystick a la izquierda (los botónes de la derecha)</string>
|
||||
<string name="joystick_visible">Visibilidad del joystick</string>
|
||||
<string name="joystick_visible_summary">Mostrar controles cuando se utiliza</string>
|
||||
<string name="key_closed_apple">[Botón 2]</string>
|
||||
<string name="key_ctrl">[Ctrl]</string>
|
||||
<string name="key_down">↓</string>
|
||||
<string name="key_esc">[ESC]</string>
|
||||
<string name="key_left">←</string>
|
||||
<string name="key_none">[Ninguno]</string>
|
||||
<string name="key_open_apple">[Botón 1]</string>
|
||||
<string name="key_ret">[Retorno]</string>
|
||||
<string name="key_right">→</string>
|
||||
<string name="key_space">[Espaciadora]</string>
|
||||
<string name="key_up">↑</string>
|
||||
<string name="keyboard">Teclado</string>
|
||||
<string name="keyboard_choose_alt">Elija teclado alternativo…</string>
|
||||
<string name="keyboard_choose_alt_summary">Elija el diseño de teclado alternativo</string>
|
||||
<string name="keyboard_click_enabled">Habilitar la tecla de sonido de clic</string>
|
||||
<string name="keyboard_click_enabled_summary">Haga clic en sonido de clave permite si está disponible</string>
|
||||
<string name="keyboard_configure">Configurar el teclado…</string>
|
||||
<string name="keyboard_configure_summary">Transparencia, minúsculas, teclado personalizado</string>
|
||||
<string name="keyboard_lowercase_enabled">Habilitar minúsculas</string>
|
||||
<string name="keyboard_lowercase_enabled_summary">Utilice las teclas minúsculas</string>
|
||||
<string name="keyboard_visibility_active">Visibilidad cuando está activo</string>
|
||||
<string name="keyboard_visibility_active_summary">Visibilidad del teclado y menú cuando está activo</string>
|
||||
<string name="keyboard_visibility_inactive">Visibilidad cuando está inactivo</string>
|
||||
<string name="keyboard_visibility_inactive_summary">Visibilidad del teclado y menú cuando está inactivo</string>
|
||||
<string name="keypad">Joystick como teclado numérico</string>
|
||||
<string name="keypad_calibrate">@string/joystick_calibrate</string>
|
||||
<string name="keypad_calibrate_summary">@string/joystick_calibrate</string>
|
||||
<string name="keypad_choose">Teclas del teclado numérico…</string>
|
||||
<string name="keypad_choose_summary">Elegir las teclas del joystick del teclado numérico</string>
|
||||
<string name="keypad_choose_title">Ejes y botones</string>
|
||||
<string name="keypad_choose_current">Elija [XXX] tecla del teclado: </string>
|
||||
<string name="keypad_configure">Configurar el joystick del teclado numérico…</string>
|
||||
<string name="keypad_configure_summary">@string/joystick_configure_summary</string>
|
||||
<string name="keypad_key_axis_c">Centro</string>
|
||||
<string name="keypad_key_axis_dn">Abajo</string>
|
||||
<string name="keypad_key_axis_dl">Abajo y a la izquierda</string>
|
||||
<string name="keypad_key_axis_dr">Abajo y a la derecha</string>
|
||||
<string name="keypad_key_axis_l">Izquierda</string>
|
||||
<string name="keypad_key_axis_r">Derecha</string>
|
||||
<string name="keypad_key_axis_ul">Arriba y a la izquierda</string>
|
||||
<string name="keypad_key_axis_up">Arriba</string>
|
||||
<string name="keypad_key_axis_ur">Arriba y a la derecha</string>
|
||||
<string name="keypad_key_button_tap">Toque</string>
|
||||
<string name="keypad_key_button_swipeup">Desliza el dedo hacia arriba</string>
|
||||
<string name="keypad_key_button_swipedown"> Desliza el dedo hacia abajo</string>
|
||||
<string name="keypad_preset_crazy_seafox">Seafox keys ;-)…</string>
|
||||
<string name="keypad_preset_custom">Elija personalizado…</string>
|
||||
<string name="keypad_preset_arrows_space">↑,←,→,↓, pulse espaciadora</string>
|
||||
<string name="keypad_preset_az_left_right_space">A,Z,←,→, pulse espaciadora</string>
|
||||
<string name="keypad_preset_ijkm_space">I,J,K,M, pulse espaciadora</string>
|
||||
<string name="keypad_preset_left_right_space">←,→, pulse espaciadora</string>
|
||||
<string name="keypad_preset_wadx_space">W,A,D,X, pulse espaciadora</string>
|
||||
<string name="keypad_repeat_summary">Umbral de repetición de teclas en segundos</string>
|
||||
<string name="menu_disks">Insertar imagen de disco…</string>
|
||||
<string name="menu_disks_summary">Insertar imagen de "Disk ]["</string>
|
||||
<string name="menu_settings">Configuración del emulador…</string>
|
||||
<string name="menu_settings_summary">Configuración general, joystick, teclado</string>
|
||||
<string name="mockingboard_disabled_title">Mockingboard desactivado</string>
|
||||
<string name="mockingboard_disabled_mesg">Mockingboard no pudo ser habilitado</string>
|
||||
<string name="mockingboard_enable">Activar Mockingboard</string>
|
||||
<string name="mockingboard_enable_summary">Revisión C en la ranura 4/5 puede requerir reinicio</string>
|
||||
<string name="mockingboard_volume">Volumen de Mockingboard</string>
|
||||
<string name="mockingboard_volume_summary">Adjustar el volumen del Mockingboard</string>
|
||||
<string name="no">No</string>
|
||||
<string name="ok">Sí</string>
|
||||
<string name="preferences_reset_title">Restablecer preferencias</string>
|
||||
<string name="preferences_reset_summary">Restablecer preferencias y salir</string>
|
||||
<string name="preferences_reset_really">¿Restablecer realmente y salir?</string>
|
||||
<string name="preferences_reset_warning">Usted perderá su configuración</string>
|
||||
<string name="quit">Salir</string>
|
||||
<string name="quit_reboot">Reiniciar o salir el emulador…</string>
|
||||
<string name="quit_reboot_choice">¿Reiniciar o salir?</string>
|
||||
<string name="reboot">Reiniciar</string>
|
||||
<string name="restore">Restauración rápida</string>
|
||||
<string name="save">Guardar rápido</string>
|
||||
<string name="saverestore">Guardar y restaurar…</string>
|
||||
<string name="saverestore_choice">¿Guardar el estado actual o anterior de restauración?</string>
|
||||
<string name="saverestore_summary">Guardar y restaurar rápida</string>
|
||||
<string name="skip">Saltar→</string>
|
||||
<string name="speaker_volume">El volumen del altavoz</string>
|
||||
<string name="speaker_volume_summary">Ajustar el volumen del altavoz</string>
|
||||
<string name="settings">Configuración Apple2ix</string>
|
||||
<string name="settings_advanced">Configuración avanzada</string>
|
||||
<string name="settings_advanced_summary">Advertencia: estos valores puede degradar el rendimiento</string>
|
||||
<string name="settings_advanced_joystick">Configuración de teclado y joystick avanzados</string>
|
||||
<string name="settings_advanced_joystick_summary">Configuración avanzada y optimización del rendimiento</string>
|
||||
<string name="touch_menu_enable">Activar menús táctiles</string>
|
||||
<string name="touch_menu_enable_summary">Los botones del menú en la parte superior de la pantalla</string>
|
||||
<string name="video_configure">Configurar el video…</string>
|
||||
<string name="video_configure_summary">Ajustes de color</string>
|
||||
|
||||
</resources>
|
||||
160
Android/app/src/main/res/values-fr/strings.xml
Normal file
@@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<color name="black">#000000</color>
|
||||
<color name="white">#ffffff</color>
|
||||
|
||||
<!-- developer-only options -->
|
||||
<string name="crasher_summary">Génération du "Test crash"</string>
|
||||
<string name="crasher_title">Plantage de l\'émulateur</string>
|
||||
<string name="crash_null">NULL-deref</string>
|
||||
<string name="crash_java_npe">Java NPE</string>
|
||||
<string name="crash_stackcall_overflow">stack call overflow</string>
|
||||
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
|
||||
|
||||
<!-- main options -->
|
||||
<string name="about_apple2ix">A propos d\'Apple2ix…</string>
|
||||
<string name="about_apple2ix_summary">A propos de ce logiciel</string>
|
||||
<string name="app_name">Apple2ix</string>
|
||||
<string name="audio_configure">Configuration audio…</string>
|
||||
<string name="audio_configure_summary">Volume du haut-parleur, Mockingboard, etc</string>
|
||||
<string name="audio_latency">Délai audio</string>
|
||||
<string name="audio_latency_summary">Délai audio en secs</string>
|
||||
<string name="cancel">Annulation</string>
|
||||
<string name="color_bw">Noir/blanc</string>
|
||||
<string name="color_color">Couleurs</string>
|
||||
<string name="color_interpolated">Interpolation couleurs</string>
|
||||
<string name="crasher">Plantages</string>
|
||||
<string name="crasher_check_title">Vérifier les logs de plantage</string>
|
||||
<string name="crasher_check_summary">Vérifier les logs de plantage avec email au développeur</string>
|
||||
<string name="crasher_send">Envoyer le log de plantage ?</string>
|
||||
<string name="crasher_send_message">Désolé, il y a eu un problème. Voulez-vous envoyer le log du plantage au développeur ?</string>
|
||||
<string name="diskA">Lecteur 1</string>
|
||||
<string name="diskB">Lecteur 2</string>
|
||||
<string name="disk_eject">Ejecter</string>
|
||||
<string name="disk_insert_toast">Insérer la disquette dans le drive en lecture seulement</string>
|
||||
<string name="disk_insert_could_not_read">Désolé, impossible de lire l\'image disque!</string>
|
||||
<string name="disk_read_only">Lecture seulement</string>
|
||||
<string name="disk_read_write">Lecture/Ecriture</string>
|
||||
<string name="disk_show_operation">Afficher les opérations (disque) ][</string>
|
||||
<string name="disk_show_operation_summary">Indique si les disques sont en lecture ou en écriture</string>
|
||||
<string name="emulation_continue">Continuer…</string>
|
||||
<string name="emulation_settings">Configurations…</string>
|
||||
<string name="emulation_disks">Chargement de l\'image disque…</string>
|
||||
<string name="header_disks">Insérer la disquettte :</string>
|
||||
<string name="input_current">Tactile</string>
|
||||
<string name="input_current_summary">Choisir l\'appareil courant</string>
|
||||
<string name="joystick">Joystick</string>
|
||||
<string name="joystick_axis_sensitivity_summary">Calibrer le joystick (décélérer/accélérer)</string>
|
||||
<string name="joystick_button_button1">Bouton 1 (Pomme ouverte)</string>
|
||||
<string name="joystick_button_button2">Bouton 2 (Pomme fermée)</string>
|
||||
<string name="joystick_button_button_both">Les deux</string>
|
||||
<string name="joystick_button_button_none">Rien</string>
|
||||
<string name="joystick_button_tap_button">Sélectionner l\'action</string>
|
||||
<string name="joystick_button_tap_button_summary">Bouton à activer lors d\'une pression vers le bas</string>
|
||||
<string name="joystick_button_tapdelay_summary">Délai de pression du bouton Joystick en secondes</string>
|
||||
<string name="joystick_button_swipe_up_button">Lancement du swipe up</string>
|
||||
<string name="joystick_button_swipe_up_button_summary">Bouton à lancer sur swipe up</string>
|
||||
<string name="joystick_button_swipe_down_button">Lancement du swipe down</string>
|
||||
<string name="joystick_button_swipe_down_button_summary">Bouton à lancer sur swipe down</string>
|
||||
<string name="joystick_button_threshold_summary">Limite en pts pour switcher sur les bouton Joystick/keypad</string>
|
||||
<string name="joystick_calibrate">Calibrer…</string>
|
||||
<string name="joystick_calibrate_summary">Configuration et test des paramètres courants</string>
|
||||
<string name="joystick_configure">Configuration du joystick…</string>
|
||||
<string name="joystick_configure_summary">Ajustements tactiles, boutons, etc</string>
|
||||
<string name="joystick_axisleft">Ajustement du joystick/keypad sur gauche</string>
|
||||
<string name="joystick_axisleft_summary">Ajustement du Joystick/keypad sur gauche (boutons sur droite)</string>
|
||||
<string name="joystick_visible">Visibilité Joystick/keypad</string>
|
||||
<string name="joystick_visible_summary">Montre les controles quand occupé</string>
|
||||
<string name="key_closed_apple">[PommeFermée]</string>
|
||||
<string name="key_ctrl">[Ctrl]</string>
|
||||
<string name="key_down">↓</string>
|
||||
<string name="key_esc">[ESC]</string>
|
||||
<string name="key_left">←</string>
|
||||
<string name="key_none">[Rien]</string>
|
||||
<string name="key_open_apple">[PommeOuverte]</string>
|
||||
<string name="key_ret">[Entrée]</string>
|
||||
<string name="key_right">→</string>
|
||||
<string name="key_space">[Espace]</string>
|
||||
<string name="key_up">↑</string>
|
||||
<string name="keyboard">Clavier</string>
|
||||
<string name="keyboard_choose_alt">Choisir clavier "alt"…</string>
|
||||
<string name="keyboard_choose_alt_summary">Choisir une configuration clavier customisée</string>
|
||||
<string name="keyboard_click_enabled">Permettre le click sur une touche</string>
|
||||
<string name="keyboard_click_enabled_summary">Si disponible, son du click sur une touche</string>
|
||||
<string name="keyboard_configure">Configuration clavier…</string>
|
||||
<string name="keyboard_configure_summary">Transparence, minuscules, touches customisées</string>
|
||||
<string name="keyboard_lowercase_enabled">Permettre les minuscules</string>
|
||||
<string name="keyboard_lowercase_enabled_summary">Permettre les touches en minuscules</string>
|
||||
<string name="keyboard_visibility_active">Visibilité quand actif</string>
|
||||
<string name="keyboard_visibility_active_summary">Clavier et menu tactile visible quand actif</string>
|
||||
<string name="keyboard_visibility_inactive">Visibilité quand inactif</string>
|
||||
<string name="keyboard_visibility_inactive_summary">Clavier et menu tactile visible quand inactif</string>
|
||||
<string name="keypad">Keypad Joystick</string>
|
||||
<string name="keypad_calibrate">@string/joystick_calibrate</string>
|
||||
<string name="keypad_calibrate_summary">@string/joystick_calibrate</string>
|
||||
<string name="keypad_choose">Sélection des touches du keypad…</string>
|
||||
<string name="keypad_choose_summary">Sélection des touches pour les axes et boutons</string>
|
||||
<string name="keypad_choose_title">Axis & boutons</string>
|
||||
<string name="keypad_choose_current">Choisir XXX Key: </string>
|
||||
<string name="keypad_configure">Configuration du "keypad joystick"…</string>
|
||||
<string name="keypad_configure_summary">@string/joystick_configure_summary</string>
|
||||
<string name="keypad_key_axis_c">Centre</string>
|
||||
<string name="keypad_key_axis_dn">Bas</string>
|
||||
<string name="keypad_key_axis_dl">Bas et Gauche</string>
|
||||
<string name="keypad_key_axis_dr">Bas et Droite</string>
|
||||
<string name="keypad_key_axis_l">Gauche</string>
|
||||
<string name="keypad_key_axis_r">Droite</string>
|
||||
<string name="keypad_key_axis_ul">Haut et Gauche</string>
|
||||
<string name="keypad_key_axis_up">Haut</string>
|
||||
<string name="keypad_key_axis_ur">Haut et Droite</string>
|
||||
<string name="keypad_key_button_tap">Presser</string>
|
||||
<string name="keypad_key_button_swipeup">Slider vers le haut</string>
|
||||
<string name="keypad_key_button_swipedown">Slider vers le bas</string>
|
||||
<string name="keypad_preset_crazy_seafox">Touches Seafox ;-)…</string>
|
||||
<string name="keypad_preset_custom">Choisir customisation…</string>
|
||||
<string name="keypad_preset_arrows_space">↑,←,→,↓, pressez barre d\'espace</string>
|
||||
<string name="keypad_preset_az_left_right_space">A,Z,←,→, pressez barre d\'espace</string>
|
||||
<string name="keypad_preset_ijkm_space">I,J,K,M, pressez barre d\'espace</string>
|
||||
<string name="keypad_preset_left_right_space">←,→, pressez barre d\'espace</string>
|
||||
<string name="keypad_preset_wadx_space">W,A,D,X, pressez barre d\'espace</string>
|
||||
<string name="keypad_repeat_summary">Répétition des touches en secs</string>
|
||||
<string name="menu_disks">Chargement de l\'image disque…</string>
|
||||
<string name="menu_disks_summary">Insérer un fichier image (disque) ][</string>
|
||||
<string name="menu_settings">Paramètres de l\'émulateur…</string>
|
||||
<string name="menu_settings_summary">Paramètres généraux, joystick, keyboard</string>
|
||||
<string name="mockingboard_disabled_title">Mockingboard désactivé</string>
|
||||
<string name="mockingboard_disabled_mesg">Le Mockingboard ne peut être activé</string>
|
||||
<string name="mockingboard_enable">Activer le Mockingboard</string>
|
||||
<string name="mockingboard_enable_summary">Révision C dans Slot 4/5 (redémarrage possible)</string>
|
||||
<string name="mockingboard_volume">Volume du Mockingboard</string>
|
||||
<string name="mockingboard_volume_summary">Placer le volume du Mockingboard</string>
|
||||
<string name="no">Non</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preferences_reset_title">Reset des préférences</string>
|
||||
<string name="preferences_reset_summary">Restaurer les préférences par défaut et quitter l\'émulateur</string>
|
||||
<string name="preferences_reset_really">Etes-vous sûr de vouloir faire un reset?</string>
|
||||
<string name="preferences_reset_warning">Vous perdrez toutes vos options de configuration</string>
|
||||
<string name="quit">Quitter</string>
|
||||
<string name="quit_reboot">Rebooter ou quitter l\'émulateur…</string>
|
||||
<string name="quit_reboot_choice">Rebooter ou quitter?</string>
|
||||
<string name="reboot">Rebooter</string>
|
||||
<string name="restore">Restauration rapide</string>
|
||||
<string name="save">Sauvegarde rapide</string>
|
||||
<string name="saverestore">Sauvegarde & restauration…</string>
|
||||
<string name="saverestore_choice">Sauvegarde de l\'état courant ou restaurer un état précédent?</string>
|
||||
<string name="saverestore_summary">Sauvegarde/restauration rapide</string>
|
||||
<string name="skip">Ignorer→</string>
|
||||
<string name="speaker_volume">Volume du haut-parleur</string>
|
||||
<string name="speaker_volume_summary">Placer le volume du haut-parleur</string>
|
||||
<string name="settings">Options de configuration de l\'émulateur Apple2ix</string>
|
||||
<string name="settings_advanced">Configuration avancée</string>
|
||||
<string name="settings_advanced_summary">Attention: ces options peuvent dégrader les performances</string>
|
||||
<string name="settings_advanced_joystick">Configuration avancée du joystick/keypad</string>
|
||||
<string name="settings_advanced_joystick_summary">Configuration avancée et tuning de performance</string>
|
||||
<string name="touch_menu_enable">Activation des menus tactiles</string>
|
||||
<string name="touch_menu_enable_summary">Activation soft des bouton du menu dans les coins en haut de l\'écran</string>
|
||||
<string name="video_configure">Configuration de la vidéo…</string>
|
||||
<string name="video_configure_summary">Configuration des couleurs</string>
|
||||
|
||||
</resources>
|
||||
@@ -4,11 +4,17 @@
|
||||
<color name="black">#000000</color>
|
||||
<color name="white">#ffffff</color>
|
||||
|
||||
<!-- developer-only options -->
|
||||
<string name="crasher_summary">Test crash generation</string>
|
||||
<string name="crasher_title">Crash emulator</string>
|
||||
<string name="crash_null">NULL-deref</string>
|
||||
<string name="crash_java_npe">Java NPE</string>
|
||||
<string name="crash_stackcall_overflow">stack call overflow</string>
|
||||
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
|
||||
|
||||
<!-- main options -->
|
||||
<string name="about_apple2ix">About Apple2ix…</string>
|
||||
<string name="about_apple2ix_summary">About this software</string>
|
||||
<string name="about_apple2">About Apple //e…</string>
|
||||
<string name="about_apple2_summary">More information about the Apple //e computer</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="app_name">Apple2ix</string>
|
||||
<string name="audio_configure">Configure audio…</string>
|
||||
<string name="audio_configure_summary">Speaker volume, Mockingboard, etc</string>
|
||||
@@ -18,43 +24,30 @@
|
||||
<string name="color_bw">Black/white</string>
|
||||
<string name="color_color">Color</string>
|
||||
<string name="color_interpolated">Interpolated color</string>
|
||||
<string name="crasher">Crasher</string>
|
||||
<string name="crasher">Crashes</string>
|
||||
<string name="crasher_check_title">Check for crash reports</string>
|
||||
<string name="crasher_check_summary">Check for crash reports to email developer)</string>
|
||||
<string name="crasher_processing">Processing…</string>
|
||||
<string name="crasher_processing_message">Processing crash reports…</string>
|
||||
<string name="crasher_check_summary">Check for crash reports to email developer</string>
|
||||
<string name="crasher_send">Send crash report?</string>
|
||||
<string name="crasher_send_message">Sorry there has been a problem. Do you want to send a crash report to the developer?</string>
|
||||
<string name="crasher_summary">Test crash generation</string>
|
||||
<string name="crasher_title">Crash emulator</string>
|
||||
<string name="crash_null">NULL-deref</string>
|
||||
<string name="crash_java_npe">Java NPE</string>
|
||||
<string name="crash_stackcall_overflow">stack call overflow</string>
|
||||
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
|
||||
<string name="diskA">Drive 1</string>
|
||||
<string name="diskB">Drive 2</string>
|
||||
<string name="disk_eject">Eject</string>
|
||||
<string name="disk_insert_toast">Inserted disk in drive 1 read-only</string>
|
||||
<string name="disk_insert_could_not_read">OOPS, could not read the disk image!</string>
|
||||
<string name="disk_insert_toast">Inserted disk in drive read-only</string>
|
||||
<string name="disk_insert_could_not_read">Sorry, could not read the disk image!</string>
|
||||
<string name="disk_read_only">Read only</string>
|
||||
<string name="disk_read_write">Read/write</string>
|
||||
<string name="disk_show_operation">Show Disk ][ operations</string>
|
||||
<string name="disk_show_operation_summary">Shows when disk drives are reading or writing</string>
|
||||
<string name="emulation_continue">Continue…</string>
|
||||
<string name="emulation_settings">Settings…</string>
|
||||
<string name="emulation_disks">Load disk image…</string>
|
||||
<string name="header_disks">Insert disk:</string>
|
||||
<string name="input_configure">Configure input devices…</string>
|
||||
<string name="input_configure_summary">Keyboard, joystick, etc</string>
|
||||
<string name="input_current">Current touch device</string>
|
||||
<string name="input_current_summary">Choose current touch device</string>
|
||||
<string name="input_first_joystick">Touch joystick</string>
|
||||
<string name="input_first_keyboard">Touch keyboard</string>
|
||||
<string name="joystick">Joystick</string>
|
||||
<string name="joystickA">Touch Joystick</string>
|
||||
<string name="joystick_axis_sensitivity_summary">Tune joystick axis sensitivity (decelerate or accelerate)</string>
|
||||
<string name="joystick_button_axis_enable">Enable button axis</string>
|
||||
<string name="joystick_button_axis_enable_summary">Enable button axis</string>
|
||||
<string name="joystick_button_button1">Button1 (Open Apple)</string>
|
||||
<string name="joystick_button_button2">Button2 (Closed Apple)</string>
|
||||
<string name="joystick_button_button1">Button 1 (Open Apple)</string>
|
||||
<string name="joystick_button_button2">Button 2 (Closed Apple)</string>
|
||||
<string name="joystick_button_button_both">Both</string>
|
||||
<string name="joystick_button_button_none">None</string>
|
||||
<string name="joystick_button_tap_button">Tap fire</string>
|
||||
@@ -64,15 +57,15 @@
|
||||
<string name="joystick_button_swipe_up_button_summary">Button to fire on swipe up</string>
|
||||
<string name="joystick_button_swipe_down_button">Swipe down fire</string>
|
||||
<string name="joystick_button_swipe_down_button_summary">Button to fire on swipe down</string>
|
||||
<string name="joystick_button_threshold_summary">Joystick/keypad button switch threshold in pts</string>
|
||||
<string name="joystick_button_threshold_summary">Joystick/keypad button switch threshold in pts (max: ⅓ screen height)</string>
|
||||
<string name="joystick_calibrate">Calibrate…</string>
|
||||
<string name="joystick_calibrate_summary">Configure and test current settings</string>
|
||||
<string name="joystick_configure">Configure joystick…</string>
|
||||
<string name="joystick_configure_summary">Axis touch, buttons, etc</string>
|
||||
<string name="joystick_current">Current joystick flavor</string>
|
||||
<string name="joystick_current_summary">Emulated physical joystick or keypad</string>
|
||||
<string name="joystick_axisleft">Joystick/keypad axis on left</string>
|
||||
<string name="joystick_axisleft_summary">Joystick/keypad axis on left (buttons on right)</string>
|
||||
<string name="joystick_azimuth_visible">Show joystick/keypad heading</string>
|
||||
<string name="joystick_azimuth_visible_summary">Shows current axis direction and magnitude</string>
|
||||
<string name="joystick_visible">Joystick/keypad visibility</string>
|
||||
<string name="joystick_visible_summary">Show controls overlay when engaged</string>
|
||||
<string name="key_closed_apple">[ClosedApple]</string>
|
||||
@@ -93,25 +86,21 @@
|
||||
<string name="keyboard_click_enabled_summary">Enables key click sound if available</string>
|
||||
<string name="keyboard_configure">Configure keyboard…</string>
|
||||
<string name="keyboard_configure_summary">Transparency, lowercase, custom keys</string>
|
||||
<string name="keyboard_glyph_scale">Keyboard glyphs scaled 2x</string>
|
||||
<string name="keyboard_glyph_scale_summary">(Makes keyboard appear less pixelated on large screens)</string>
|
||||
<string name="keyboard_lowercase_enabled">Enable lowercase</string>
|
||||
<string name="keyboard_lowercase_enabled_summary">Enable lowercase keys</string>
|
||||
<string name="keyboard_preset_default">Default</string>
|
||||
<string name="keyboard_visibility_active">Visibility when active</string>
|
||||
<string name="keyboard_visibility_active_summary">Keyboard visibility when active</string>
|
||||
<string name="keyboard_visibility_active_summary">Keyboard and touch menu visibility when active</string>
|
||||
<string name="keyboard_visibility_inactive">Visibility when inactive</string>
|
||||
<string name="keyboard_visibility_inactive_summary">Keyboard visibility when inactive</string>
|
||||
<string name="keyboard_visibility_inactive_summary">Keyboard and touch menu visibility when inactive</string>
|
||||
<string name="keypad">Keypad Joystick</string>
|
||||
<string name="keypadA">Touch Keypad Joystick</string>
|
||||
<string name="keypad_button_tap_button">Tap key:</string>
|
||||
<string name="keypad_button_swipe_up_button">Swipe up key:</string>
|
||||
<string name="keypad_button_swipe_down_button">Swipe down key:</string>
|
||||
<string name="keypad_calibrate">Calibrate…</string>
|
||||
<string name="keypad_calibrate_summary">Configure and test current settings</string>
|
||||
<string name="keypad_calibrate">@string/joystick_calibrate</string>
|
||||
<string name="keypad_calibrate_summary">@string/joystick_calibrate</string>
|
||||
<string name="keypad_choose">Choose keypad keys…</string>
|
||||
<string name="keypad_choose_summary">Choose axis and button keys</string>
|
||||
<string name="keypad_choose_title">Axis & buttons</string>
|
||||
<string name="keypad_choose_current">Choose XXX Key: </string>
|
||||
<string name="keypad_chosen_keys">I,J,K,M [Space]</string>
|
||||
<string name="keypad_configure">Configure keypad joystick…</string>
|
||||
<string name="keypad_configure_summary">@string/joystick_configure_summary</string>
|
||||
<string name="keypad_key_axis_c">Center</string>
|
||||
@@ -130,58 +119,45 @@
|
||||
<string name="keypad_preset_custom">Choose custom…</string>
|
||||
<string name="keypad_preset_arrows_space">↑,←,→,↓, tap spacebar</string>
|
||||
<string name="keypad_preset_az_left_right_space">A,Z,←,→, tap spacebar</string>
|
||||
<string name="keypad_preset_ijkl_uo">I,J,L,K, tap U, swipe down O</string>
|
||||
<string name="keypad_preset_ijkm_space">I,J,K,M, tap spacebar</string>
|
||||
<string name="keypad_preset_left_right_space">←,→, tap spacebar</string>
|
||||
<string name="keypad_preset_wadx_space">W,A,D,X, tap spacebar</string>
|
||||
<string name="keypad_repeat_summary">Key repeat threshold in secs</string>
|
||||
<string name="max">Max</string>
|
||||
<string name="menu_disks">Load disk image…</string>
|
||||
<string name="menu_disks_summary">Insert a Disk ][ image file</string>
|
||||
<string name="menu_settings">Emulator settings…</string>
|
||||
<string name="menu_settings_summary">General, CPU, Joystick</string>
|
||||
<string name="menu_settings_summary">General settings, joystick, keyboard</string>
|
||||
<string name="mockingboard_disabled_title">Mockingboard disabled</string>
|
||||
<string name="mockingboard_disabled_mesg">Mockingboard could not be enabled</string>
|
||||
<string name="mockingboard_enable">Enable Mockingboard</string>
|
||||
<string name="mockingboard_enable_summary">Revision C in Slot 4/5 (may require restart)</string>
|
||||
<string name="mockingboard_volume">Mockingboard volume</string>
|
||||
<string name="mockingboard_volume_summary">Set the Mockingboard(s) volume</string>
|
||||
<string name="mockingboard_volume_summary">Set the Mockingboard volume</string>
|
||||
<string name="no">No</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preferences_reset_title">Reset preferences</string>
|
||||
<string name="preferences_reset_summary">Reset preferences to defaults</string>
|
||||
<string name="preferences_reset_really">Really reset?</string>
|
||||
<string name="preferences_reset_summary">Reset preferences to defaults and quit emulator</string>
|
||||
<string name="preferences_reset_really">Really reset and quit?</string>
|
||||
<string name="preferences_reset_warning">You will lose your settings</string>
|
||||
<string name="quit">Quit emulator…</string>
|
||||
<string name="quit_summary"></string>
|
||||
<string name="quit_really">Quit emulator?</string>
|
||||
<string name="quit_warning">You will lose unsaved progress</string>
|
||||
<string name="reboot">Reboot emulator…</string>
|
||||
<string name="reboot_really">Reboot emulator?</string>
|
||||
<string name="reboot_summary"></string>
|
||||
<string name="reboot_warning">You will lose unsaved progress</string>
|
||||
<string name="quit">Quit</string>
|
||||
<string name="quit_reboot">Reboot or quit emulator…</string>
|
||||
<string name="quit_reboot_choice">Reboot or quit?</string>
|
||||
<string name="reboot">Reboot</string>
|
||||
<string name="restore">Quick restore</string>
|
||||
<string name="save">Quick save</string>
|
||||
<string name="saverestore">Save & restore…</string>
|
||||
<string name="saverestore_choice">Save current state or restore previous?</string>
|
||||
<string name="saverestore_summary">Quick save and restore</string>
|
||||
<string name="skip">Skip→</string>
|
||||
<string name="spacer"></string>
|
||||
<string name="speaker_disabled_title">Speaker disabled</string>
|
||||
<string name="speaker_disabled_mesg">Speaker could not be enabled</string>
|
||||
<string name="speaker_enable">Enable speaker</string>
|
||||
<string name="speaker_enable_summary">(Speaker cannot be disabled)</string>
|
||||
<string name="speaker_volume">Speaker volume</string>
|
||||
<string name="speaker_volume_summary">Set the speaker volume</string>
|
||||
<string name="speed_alt">Alternate CPU speed</string>
|
||||
<string name="speed_cpu">CPU Speed</string>
|
||||
<string name="settings">Apple2ix emulator settings</string>
|
||||
<string name="settings_audio">Apple2ix audio settings</string>
|
||||
<string name="settings_advanced">Advanced settings</string>
|
||||
<string name="settings_advanced_summary">Warning: these settings may potentially degrade emulation performance</string>
|
||||
<string name="settings_advanced_summary">Warning: these settings may degrade performance</string>
|
||||
<string name="settings_advanced_joystick">Advanced joystick/keypad settings</string>
|
||||
<string name="settings_advanced_joystick_summary">Advanced settings and performance tuning</string>
|
||||
<string name="tab_general">General</string>
|
||||
<string name="tab_joystick">Joystick</string>
|
||||
<string name="touch_menu_enable">Enable touch menus</string>
|
||||
<string name="touch_menu_enable_summary">Enables soft menu buttons in top screen corners</string>
|
||||
<string name="touch_menu_visibility">Touch menu visibility</string>
|
||||
<string name="touch_menu_visibility_summary">Touch menu visibility when inactive</string>
|
||||
<string name="video_configure">Configure video…</string>
|
||||
<string name="video_configure_summary">Color settings</string>
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
../../disks
|
||||
../../../apple2-images-pub/disks
|
||||
@@ -5,7 +5,6 @@
|
||||
"_comment" : "hex code for special glyphs",
|
||||
"_AA" : "b5",
|
||||
"_CTRL": "b3",
|
||||
"_XX" : "9b",
|
||||
"_ESC" : "bc",
|
||||
"_OA" : "81",
|
||||
"_CA" : "80",
|
||||
@@ -20,7 +19,7 @@
|
||||
["_AA", "", "_CTRL", "", "_ESC", "", "_OA", "", "_CA", ""],
|
||||
[ "", "", "", "", "", "", "", "", "", ""],
|
||||
[ "", "", "", "", "", "_UP", "", "", "", ""],
|
||||
[ "", "", "", "", "_LT", "_XX", "_RT", "", "", ""],
|
||||
[ "", "", "", "", "_LT", "_AA", "_RT", "", "", ""],
|
||||
[ "", "", "", "", "", "_DN", "", "", "", ""],
|
||||
[ "", "", "", "", "", "", "", "", "", ""]
|
||||
]
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"_SP" : "b1"
|
||||
},
|
||||
|
||||
[ "reserved for future use" ],
|
||||
[ "reserved for future use" ],
|
||||
[ "", "", "", "", "", "", "", "", "", "" ],
|
||||
[ "_AA", "", "", "", "", "", "", "", "", "" ],
|
||||
[ "", "", "", "", "", "", "", "", "", "" ],
|
||||
[ "", "", "", "", "", "", "", "", "", "" ],
|
||||
[ "", "", "", "", "", "", "", "", "", "" ],
|
||||
[ "Q", "", "", "", "", "", "", "", "A", "" ],
|
||||
[ "", "", "", "", "", "", "", "_LT", "", "_RT" ],
|
||||
[ "_SP", "", "", "", "", "", "", "", "Z", "" ]
|
||||
|
||||
19
Android/assets/keyboards/moebius.kbd.json
Normal file
@@ -0,0 +1,19 @@
|
||||
[
|
||||
"Alt keyboard optimized for Moebius",
|
||||
|
||||
{
|
||||
"_comment" : "hex code for special glyphs",
|
||||
"_AA" : "b5",
|
||||
"_ESC" : "bc",
|
||||
"_SP" : "b1"
|
||||
},
|
||||
|
||||
[ "Q", "", "", "", "", "", "", "", "", "" ],
|
||||
[ "", "", "", "", "", "", "", "", "", "V"],
|
||||
[ "_AA", "", "", "", "", "", "", "", "", "D"],
|
||||
[ "_ESC", "", "", "", "", "", "", "", "", "G"],
|
||||
[ "Y", "", "", "", "", "", "", "", "", "" ],
|
||||
[ "N", "", "", "", "", "", "", "I", "O", "P"],
|
||||
[ "U", "A", "S", "E", "F", "M", "", "K", "L", ";"],
|
||||
[ "C", "Z", "X", "B", "H", "T", "_SP",",", ".", "/"]
|
||||
]
|
||||
@@ -5,19 +5,19 @@
|
||||
"_comment" : "hex code for special glyphs",
|
||||
"_AA" : "b5",
|
||||
"_ESC" : "bc",
|
||||
"_UP" : "8b",
|
||||
"_UP" : "8d",
|
||||
"_LT" : "88",
|
||||
"_RT" : "95",
|
||||
"_DN" : "8a",
|
||||
"_SP" : "b1"
|
||||
},
|
||||
|
||||
["reserved for future use"],
|
||||
["reserved for future use"],
|
||||
[ "Q", "", "", "", "", "", "", "", "K", "X"],
|
||||
[ "P", "", "", "", "", "", "", "", "D", "B"],
|
||||
["_AA", "", "", "", "", "", "1", "2", "3", "4"],
|
||||
[ "N", "", "", "", "", "", "5", "6", "7", "8"],
|
||||
[ "Y", "", "", "", "", "", "Z", "G", "", "_ESC"],
|
||||
[ "S", "", "", "", "", "", "C", "", "_UP", "" ],
|
||||
[ "", "", "", "", "", "", "", "_LT", "", "_RT"],
|
||||
[ "A", "", "T", "O", "", "", "_SP", "", "_DN", ""]
|
||||
[ "", "", "", "", "", "", "", "_LT", "", "_RT"],
|
||||
[ "A", "", "T", "O", "F", "E", "_SP", "", "_DN", ""]
|
||||
]
|
||||
|
||||
1
Android/assets/shaders/SolidColor.fsh
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../src/video/SolidColor.fsh
|
||||
1
Android/assets/shaders/SolidColor.vsh
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../src/video/SolidColor.vsh
|
||||
0
Android/assets/symbols/x86/.blank
Normal file
@@ -1,4 +1,4 @@
|
||||
APP_ABI := armeabi armeabi-v7a ## TODO : x86
|
||||
APP_ABI := armeabi armeabi-v7a x86
|
||||
|
||||
# Do not change APP_PLATFORM if we care about Gingerbread (2.3.3) devices! We must compile against android-10,
|
||||
# otherwise we may encounter runtime load-library errors from symbols that should have been inlined against older
|
||||
|
||||
@@ -40,6 +40,19 @@ void android_keycode_to_emulator(int keyCode, int metaState, bool pressed) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (keyCode) {
|
||||
case KEYCODE_BUTTON_A:
|
||||
case KEYCODE_BUTTON_X:
|
||||
case KEYCODE_BUTTON_L1:
|
||||
joydriver_setButton0Pressed(pressed);
|
||||
return;
|
||||
case KEYCODE_BUTTON_B:
|
||||
case KEYCODE_BUTTON_Y:
|
||||
case KEYCODE_BUTTON_R1:
|
||||
joydriver_setButton1Pressed(pressed);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (keyCode) {
|
||||
case KEYCODE_0:
|
||||
key = _is_shifted(metaState) ? ')' : keyCode + ASCII_0_OFFSET;
|
||||
|
||||
@@ -98,6 +98,8 @@
|
||||
#define KEYCODE_BUTTON_L2 0x68
|
||||
#define KEYCODE_BUTTON_R1 0x67
|
||||
#define KEYCODE_BUTTON_R2 0x69
|
||||
#define KEYCODE_BUTTON_X 0x63
|
||||
#define KEYCODE_BUTTON_Y 0x64
|
||||
|
||||
#define META_ALT_LEFT_ON 0x00000010
|
||||
#define META_ALT_RIGHT_ON 0x00000020
|
||||
|
||||
@@ -30,14 +30,25 @@ LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
LOCAL_SRC_FILES += $(APPLE2_X86_SRC)
|
||||
LOCAL_CFLAGS += -DNO_UNDERSCORES=1
|
||||
else
|
||||
LOCAL_SRC_FILES += $(APPLE2_ARM_SRC)
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_MODE),release)
|
||||
LOCAL_CFLAGS += -DNDEBUG=1
|
||||
else
|
||||
LOCAL_CFLAGS += -g
|
||||
endif
|
||||
|
||||
ifeq ($(EMBEDDED_STACKWALKER),1)
|
||||
LOCAL_CPPFLAGS += -DEMBEDDED_STACKWALKER=1
|
||||
else
|
||||
$(error OOPS, for now you should build with EMBEDDED_STACKWALKER=1)
|
||||
ifeq ($(RUNNING_GDB),1)
|
||||
# nothing to do
|
||||
else
|
||||
$(error OOPS, for now you should build with EMBEDDED_STACKWALKER=1)
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_SRC_FILES += $(APPLE2_MAIN_SRC) $(APPLE2_META_SRC) $(APPLE2_VIDEO_SRC) $(APPLE2_AUDIO_SRC)
|
||||
@@ -48,5 +59,9 @@ include $(BUILD_SHARED_LIBRARY)
|
||||
# --OR-- Build an executable so native can drive this show
|
||||
#include $(BUILD_EXECUTABLE)
|
||||
|
||||
$(call import-module, breakpad/android/google_breakpad)
|
||||
ifeq ($(RUNNING_GDB),1)
|
||||
# nothing to do
|
||||
else
|
||||
$(call import-module, breakpad/android/google_breakpad)
|
||||
endif
|
||||
$(call import-module, android/cpufeatures)
|
||||
|
||||
@@ -3,10 +3,18 @@
|
||||
package_id="org.deadc0de.apple2ix.basic"
|
||||
apple2_src_path=apple2ix-src
|
||||
glue_srcs="$apple2_src_path/disk.c $apple2_src_path/misc.c $apple2_src_path/display.c $apple2_src_path/vm.c $apple2_src_path/cpu-supp.c $apple2_src_path/audio/speaker.c $apple2_src_path/audio/mockingboard.c"
|
||||
target_arch=armeabi-v7a
|
||||
|
||||
usage() {
|
||||
echo "$0 [--build-release] [--load] [--debug] [--armeabi | --armeabi-v7a]"
|
||||
if test "$(basename $0)" = "clean" ; then
|
||||
echo "$0"
|
||||
echo " # cleans NDK build of $package_id"
|
||||
elif test "$(basename $0)" = "uninstall" ; then
|
||||
echo "$0"
|
||||
echo " # uninstalls $package_id"
|
||||
else
|
||||
echo "$0 [build|release] [load|debug]"
|
||||
echo " # default builds $package_id and then load or debug"
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -14,26 +22,22 @@ export EMBEDDED_STACKWALKER=1
|
||||
|
||||
while test "x$1" != "x"; do
|
||||
case "$1" in
|
||||
"--debug")
|
||||
"build")
|
||||
do_build=1
|
||||
;;
|
||||
|
||||
"release")
|
||||
do_release=1
|
||||
;;
|
||||
|
||||
"debug")
|
||||
do_debug=1
|
||||
;;
|
||||
|
||||
"--load")
|
||||
"load")
|
||||
do_load=1
|
||||
;;
|
||||
|
||||
"--armeabi")
|
||||
target_arch=armeabi
|
||||
;;
|
||||
|
||||
"--v7a")
|
||||
target_arch=armeabi-v7a
|
||||
;;
|
||||
|
||||
"--build-release")
|
||||
do_release=1
|
||||
;;
|
||||
|
||||
"-h")
|
||||
usage
|
||||
;;
|
||||
@@ -43,12 +47,17 @@ while test "x$1" != "x"; do
|
||||
;;
|
||||
|
||||
*)
|
||||
package_id=$1
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test "x$do_build" = "x1" -a "x$do_release" = "x1" ; then
|
||||
echo "Must specify either build or release"
|
||||
usage
|
||||
fi
|
||||
|
||||
set -x
|
||||
|
||||
if test "$(basename $0)" = "clean" ; then
|
||||
@@ -78,22 +87,6 @@ if test "$(basename $0)" = "uninstall" ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#CC=`which clang`
|
||||
CC=`which gcc`
|
||||
CFLAGS="-std=gnu11"
|
||||
|
||||
# ROMz
|
||||
$CC $CFLAGS -o $apple2_src_path/genrom $apple2_src_path/genrom.c && \
|
||||
$apple2_src_path/genrom $apple2_src_path/rom/apple_IIe.rom $apple2_src_path/rom/slot6.rom > $apple2_src_path/rom.c
|
||||
|
||||
# font
|
||||
$CC $CFLAGS -o $apple2_src_path/genfont $apple2_src_path/genfont.c && \
|
||||
$apple2_src_path/genfont < $apple2_src_path/font.txt > $apple2_src_path/font.c
|
||||
|
||||
# glue
|
||||
$apple2_src_path/x86/genglue $glue_srcs > $apple2_src_path/x86/glue.S
|
||||
$apple2_src_path/arm/genglue $glue_srcs > $apple2_src_path/arm/glue.S
|
||||
|
||||
if test "$(basename $0)" = "testcpu" ; then
|
||||
ln -s testcpu.mk Android.mk
|
||||
elif test "$(basename $0)" = "testvm" ; then
|
||||
@@ -108,64 +101,90 @@ fi
|
||||
|
||||
###############################################################################
|
||||
# build native sources
|
||||
if test "x$do_release" = "x1" ; then
|
||||
ndk-build V=1 NDK_MODULE_PATH=. # NDK_TOOLCHAIN_VERSION=clang
|
||||
else
|
||||
ndk-build V=1 NDK_MODULE_PATH=. NDK_DEBUG=1 # NDK_TOOLCHAIN_VERSION=clang
|
||||
|
||||
if test "x$do_build" = "x1" -o "x$do_release" = "x1" ; then
|
||||
|
||||
#CC=`which clang`
|
||||
CC=`which gcc`
|
||||
CFLAGS="-std=gnu11"
|
||||
|
||||
# ROMz
|
||||
$CC $CFLAGS -o $apple2_src_path/genrom $apple2_src_path/genrom.c && \
|
||||
$apple2_src_path/genrom $apple2_src_path/rom/apple_IIe.rom $apple2_src_path/rom/slot6.rom > $apple2_src_path/rom.c
|
||||
|
||||
# font
|
||||
$CC $CFLAGS -o $apple2_src_path/genfont $apple2_src_path/genfont.c && \
|
||||
$apple2_src_path/genfont < $apple2_src_path/font.txt > $apple2_src_path/font.c
|
||||
|
||||
# glue
|
||||
$apple2_src_path/x86/genglue $glue_srcs > $apple2_src_path/x86/glue.S
|
||||
$apple2_src_path/arm/genglue $glue_srcs > $apple2_src_path/arm/glue.S
|
||||
|
||||
if test "x$do_build" = "x1" ; then
|
||||
export BUILD_MODE=debug
|
||||
ndk-build V=1 NDK_MODULE_PATH=. NDK_DEBUG=1 # NDK_TOOLCHAIN_VERSION=clang
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
exit $ret
|
||||
fi
|
||||
else
|
||||
export BUILD_MODE=release
|
||||
ndk-build V=1 NDK_MODULE_PATH=. # NDK_TOOLCHAIN_VERSION=clang
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
exit $ret
|
||||
fi
|
||||
fi
|
||||
|
||||
# Symbolicate and move symbols file into location to be deployed on device
|
||||
|
||||
SYMFILE=libapple2ix.so.sym
|
||||
ARCHES_TO_SYMBOLICATE='armeabi armeabi-v7a x86'
|
||||
|
||||
for arch in $ARCHES_TO_SYMBOLICATE ; do
|
||||
SYMDIR=../assets/symbols/$arch/libapple2ix.so
|
||||
|
||||
# remove old symbols (if any)
|
||||
/bin/rm -rf $SYMDIR
|
||||
|
||||
# Run Breakpad's dump_syms
|
||||
../../externals/bin/dump_syms ../obj/local/$arch/libapple2ix.so > $SYMFILE
|
||||
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
echo "OOPS, dump_syms failed for $arch"
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
# strip to the just the numeric id in the .sym header and verify it makes sense
|
||||
sym_id=$(head -1 $SYMFILE | cut -d ' ' -f 4)
|
||||
sym_id_check=$(echo $sym_id | wc -c)
|
||||
if test "x$sym_id_check" != "x34" ; then
|
||||
echo "OOPS symbol header not expected size, meat-space intervention needed =P"
|
||||
exit 1
|
||||
fi
|
||||
sym_id_check=$(echo $sym_id | tr -d 'A-Fa-f0-9' | wc -c)
|
||||
if test "x$sym_id_check" != "x1" ; then
|
||||
echo "OOPS unexpected characters in symbol header, meat-space intervention needed =P"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $SYMDIR/$sym_id
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
echo "OOPS, could not create symbols directory for arch:$arch and sym_id:$sym_id"
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
/bin/mv $SYMFILE $SYMDIR/$sym_id/
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
echo "OOPS, could not move $SYMFILE to $SYMDIR/$sym_id/"
|
||||
exit $ret
|
||||
fi
|
||||
done
|
||||
|
||||
fi
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# Symbolicate and move symbols file into location to be deployed on device
|
||||
|
||||
SYMFILE=libapple2ix.so.sym
|
||||
ARCHES_TO_SYMBOLICATE='armeabi armeabi-v7a'
|
||||
|
||||
for arch in $ARCHES_TO_SYMBOLICATE ; do
|
||||
SYMDIR=../assets/symbols/$arch/libapple2ix.so
|
||||
|
||||
# remove old symbols (if any)
|
||||
/bin/rm -rf $SYMDIR
|
||||
|
||||
# Run Breakpad's dump_syms
|
||||
../../externals/bin/dump_syms ../obj/local/$arch/libapple2ix.so > $SYMFILE
|
||||
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
echo "OOPS, dump_syms failed for $arch"
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
# strip to the just the numeric id in the .sym header and verify it makes sense
|
||||
sym_id=$(head -1 $SYMFILE | cut -d ' ' -f 4)
|
||||
sym_id_check=$(echo $sym_id | wc -c)
|
||||
if test "x$sym_id_check" != "x34" ; then
|
||||
echo "OOPS symbol header not expected size, meat-space intervention needed =P"
|
||||
exit 1
|
||||
fi
|
||||
sym_id_check=$(echo $sym_id | tr -d 'A-Fa-f0-9' | wc -c)
|
||||
if test "x$sym_id_check" != "x1" ; then
|
||||
echo "OOPS unexpected characters in symbol header, meat-space intervention needed =P"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $SYMDIR/$sym_id
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
echo "OOPS, could not create symbols directory for arch:$arch and sym_id:$sym_id"
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
/bin/mv $SYMFILE $SYMDIR/$sym_id/
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
echo "OOPS, could not move $SYMFILE to $SYMDIR/$sym_id/"
|
||||
exit $ret
|
||||
fi
|
||||
done
|
||||
|
||||
###############################################################################
|
||||
# usually we should build the Java stuff from within Android Studio
|
||||
@@ -179,13 +198,9 @@ fi
|
||||
|
||||
###############################################################################
|
||||
if test "x$do_debug" = "x1" ; then
|
||||
export RUNNING_GDB=1
|
||||
cd ..
|
||||
/bin/rm ./libs/gdbserver
|
||||
/bin/ln -s $target_arch/gdbserver libs/gdbserver
|
||||
##/bin/rm ./libs/gdb.setup
|
||||
##/bin/ln -s $target_arch/gdb.setup libs/gdb.setup
|
||||
##ndk-gdb --verbose --force --launch=org.deadc0de.apple2ix.Apple2Activity
|
||||
ndk-gdb --nowait --verbose --force --launch=org.deadc0de.apple2ix.Apple2Activity
|
||||
ndk-gdb --nowait --force --verbose --launch=org.deadc0de.apple2ix.Apple2Activity
|
||||
elif test "x$do_load" = "x1" ; then
|
||||
adb shell am start -a android.intent.action.MAIN -n org.deadc0de.apple2ix.basic/org.deadc0de.apple2ix.Apple2Activity
|
||||
fi
|
||||
|
||||
@@ -113,6 +113,8 @@ void Java_org_deadc0de_apple2ix_Apple2CrashHandler_nativeProcessCrash(JNIEnv *en
|
||||
|
||||
if (android_armArchV7A) {
|
||||
asprintf(&symbolsPath, "%s/symbols/armeabi-v7a", data_dir);
|
||||
} else if (android_x86) {
|
||||
asprintf(&symbolsPath, "%s/symbols/x86", data_dir);
|
||||
} else /*if (android_armArch)*/ {
|
||||
asprintf(&symbolsPath, "%s/symbols/armeabi", data_dir);
|
||||
} /*else { moar archs ... } */
|
||||
@@ -129,7 +131,7 @@ void Java_org_deadc0de_apple2ix_Apple2CrashHandler_nativeProcessCrash(JNIEnv *en
|
||||
}
|
||||
|
||||
if (symbolsPath) {
|
||||
FREE(symbolsPath);
|
||||
ASPRINTF_FREE(symbolsPath);
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, jCrashPath, crashPath);
|
||||
|
||||
@@ -47,6 +47,7 @@ typedef enum lifecycle_seq_t {
|
||||
static lifecycle_seq_t appState = APP_RUNNING;
|
||||
|
||||
#if TESTING
|
||||
static bool running_tests = false;
|
||||
static void _run_tests(void) {
|
||||
char *local_argv[] = {
|
||||
"-f",
|
||||
@@ -96,34 +97,13 @@ static inline int _androidTouchEvent2InterfaceEvent(jint action) {
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// JNI functions
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir, jint sampleRate, jint monoBufferSize, jint stereoBufferSize) {
|
||||
const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0);
|
||||
|
||||
// Android lifecycle can call onCreate() multiple times...
|
||||
if (data_dir) {
|
||||
LOG("IGNORING multiple calls to nativeOnCreate ...");
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not remove this deadc0de ... it forces a runtime load-library/link error on Gingerbread devices if we have
|
||||
// incorrectly compiled the app against a later version of the NDK!!!
|
||||
int pagesize = getpagesize();
|
||||
LOG("PAGESIZE IS : %d", pagesize);
|
||||
|
||||
data_dir = strdup(dataDir);
|
||||
if (crashHandler && crashHandler->init) {
|
||||
crashHandler->init(data_dir);
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, j_dataDir, dataDir);
|
||||
LOG("data_dir : %s", data_dir);
|
||||
static void discover_cpu_family(void) {
|
||||
LOG("Discovering CPU family...");
|
||||
|
||||
AndroidCpuFamily family = android_getCpuFamily();
|
||||
uint64_t features = android_getCpuFeatures();
|
||||
if (family == ANDROID_CPU_FAMILY_X86) {
|
||||
android_x86 = true;
|
||||
if (features & ANDROID_CPU_X86_FEATURE_SSSE3) {
|
||||
LOG("nANDROID_CPU_X86_FEATURE_SSSE3");
|
||||
android_x86SSSE3Enabled = true;
|
||||
@@ -158,52 +138,86 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobje
|
||||
//android_arm64Arch = true;
|
||||
android_armArchV7A = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// JNI functions
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jclass cls, jstring j_dataDir, jint sampleRate, jint monoBufferSize, jint stereoBufferSize) {
|
||||
const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0);
|
||||
|
||||
// Android lifecycle can call onCreate() multiple times...
|
||||
if (data_dir) {
|
||||
LOG("IGNORING multiple calls to nativeOnCreate ...");
|
||||
return;
|
||||
}
|
||||
|
||||
discover_cpu_family();
|
||||
|
||||
// Do not remove this deadc0de ... it forces a runtime load-library/link error on Gingerbread devices if we have
|
||||
// incorrectly compiled the app against a later version of the NDK!!!
|
||||
int pagesize = getpagesize();
|
||||
LOG("PAGESIZE IS : %d", pagesize);
|
||||
|
||||
data_dir = strdup(dataDir);
|
||||
if (crashHandler && crashHandler->init) {
|
||||
crashHandler->init(data_dir);
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, j_dataDir, dataDir);
|
||||
LOG("data_dir : %s", data_dir);
|
||||
|
||||
android_deviceSampleRateHz = (unsigned long)sampleRate;
|
||||
android_monoBufferSubmitSizeSamples = (unsigned long)monoBufferSize;
|
||||
android_stereoBufferSubmitSizeSamples = (unsigned long)stereoBufferSize;
|
||||
|
||||
#if TESTING
|
||||
assert(cpu_thread_id == 0 && "CPU thread must not be initialized yet...");
|
||||
_run_tests();
|
||||
// CPU thread is started from testsuite (if needed)
|
||||
#else
|
||||
joydriver_setClampBeyondRadius(true);
|
||||
|
||||
#if !TESTING
|
||||
cpu_pause();
|
||||
emulator_start();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeGraphicsChanged(JNIEnv *env, jobject obj, jint width, jint height) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2View_nativeGraphicsChanged(JNIEnv *env, jclass cls, jint width, jint height) {
|
||||
// WARNING : this can happen on non-GL thread
|
||||
LOG("...");
|
||||
video_backend->reshape(width, height);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeGraphicsInitialized(JNIEnv *env, jobject obj, jint width, jint height) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2View_nativeGraphicsInitialized(JNIEnv *env, jclass cls, jint width, jint height) {
|
||||
// WARNING : this needs to happen on the GL thread only
|
||||
LOG("width:%d height:%d", width, height);
|
||||
|
||||
video_shutdown();
|
||||
video_backend->reshape(width, height);
|
||||
video_backend->init((void *)0);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnResume(JNIEnv *env, jobject obj, jboolean isSystemResume) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeEmulationResume(JNIEnv *env, jclass cls) {
|
||||
#if TESTING
|
||||
// test driver thread is managing CPU
|
||||
if (!running_tests) {
|
||||
running_tests = true;
|
||||
assert(cpu_thread_id == 0 && "CPU thread must not be initialized yet...");
|
||||
_run_tests();
|
||||
}
|
||||
#else
|
||||
if (!cpu_isPaused()) {
|
||||
return;
|
||||
}
|
||||
LOG("...");
|
||||
if (!isSystemResume) {
|
||||
#if TESTING
|
||||
// test driver thread is managing CPU
|
||||
#else
|
||||
cpu_resume();
|
||||
cpu_resume();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnPause(JNIEnv *env, jobject obj, jboolean isSystemPause) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeEmulationPause(JNIEnv *env, jclass cls) {
|
||||
if (appState != APP_RUNNING) {
|
||||
return;
|
||||
}
|
||||
|
||||
disk6_flush(0);
|
||||
disk6_flush(1);
|
||||
|
||||
if (cpu_isPaused()) {
|
||||
return;
|
||||
}
|
||||
@@ -216,7 +230,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnPause(JNIEnv *env, jobjec
|
||||
#endif
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeRender(JNIEnv *env, jobject obj) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2View_nativeRender(JNIEnv *env, jclass cls) {
|
||||
SCOPE_TRACE_VIDEO("nativeRender");
|
||||
|
||||
if (UNLIKELY(appState != APP_RUNNING)) {
|
||||
@@ -247,12 +261,12 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeRender(JNIEnv *env, jobject
|
||||
video_backend->render();
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeReboot(JNIEnv *env, jobject obj) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeReboot(JNIEnv *env, jclass cls) {
|
||||
LOG("...");
|
||||
cpu65_reboot();
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnQuit(JNIEnv *env, jobject obj) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnQuit(JNIEnv *env, jclass cls) {
|
||||
#if TESTING
|
||||
// test driver thread is managing CPU
|
||||
#else
|
||||
@@ -267,21 +281,25 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnQuit(JNIEnv *env, jobject
|
||||
#endif
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnKeyDown(JNIEnv *env, jobject obj, jint keyCode, jint metaState) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnKeyDown(JNIEnv *env, jclass cls, jint keyCode, jint metaState) {
|
||||
if (UNLIKELY(appState != APP_RUNNING)) {
|
||||
return;
|
||||
}
|
||||
android_keycode_to_emulator(keyCode, metaState, true);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnKeyUp(JNIEnv *env, jobject obj, jint keyCode, jint metaState) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnKeyUp(JNIEnv *env, jclass cls, jint keyCode, jint metaState) {
|
||||
if (UNLIKELY(appState != APP_RUNNING)) {
|
||||
return;
|
||||
}
|
||||
android_keycode_to_emulator(keyCode, metaState, false);
|
||||
}
|
||||
|
||||
jlong Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnTouch(JNIEnv *env, jobject obj, jint action, jint pointerCount, jint pointerIndex, jfloatArray xCoords, jfloatArray yCoords) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2View_nativeOnJoystickMove(JNIEnv *env, jclass cls, jint x, jint y) {
|
||||
joydriver_setAxisValue((uint8_t)x, (uint8_t)y);
|
||||
}
|
||||
|
||||
jlong Java_org_deadc0de_apple2ix_Apple2View_nativeOnTouch(JNIEnv *env, jclass cls, jint action, jint pointerCount, jint pointerIndex, jfloatArray xCoords, jfloatArray yCoords) {
|
||||
//LOG(": %d/%d/%d :", action, pointerCount, pointerIndex);
|
||||
|
||||
SCOPE_TRACE_TOUCH("nativeOnTouch");
|
||||
@@ -306,11 +324,13 @@ jlong Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnTouch(JNIEnv *env, jobje
|
||||
return flags;
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeChooseDisk(JNIEnv *env, jobject obj, jstring jPath, jboolean driveA, jboolean readOnly) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeChooseDisk(JNIEnv *env, jclass cls, jstring jPath, jboolean driveA, jboolean readOnly) {
|
||||
const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
|
||||
int drive = driveA ? 0 : 1;
|
||||
int ro = readOnly ? 1 : 0;
|
||||
|
||||
assert(cpu_isPaused() && "considered dangerous to insert disk image when CPU thread is running");
|
||||
|
||||
LOG(": (%s, %s, %s)", path, driveA ? "drive A" : "drive B", readOnly ? "read only" : "read/write");
|
||||
if (disk6_insert(drive, path, ro)) {
|
||||
char *gzPath = NULL;
|
||||
@@ -322,18 +342,60 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeChooseDisk(JNIEnv *env, job
|
||||
} else {
|
||||
video_backend->animation_showDiskChosen(drive);
|
||||
}
|
||||
FREE(gzPath);
|
||||
ASPRINTF_FREE(gzPath);
|
||||
} else {
|
||||
video_backend->animation_showDiskChosen(drive);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jPath, path);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeEjectDisk(JNIEnv *env, jobject obj, jboolean driveA) {
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeEjectDisk(JNIEnv *env, jclass cls, jboolean driveA) {
|
||||
LOG("...");
|
||||
disk6_eject(!driveA);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeSaveState(JNIEnv *env, jclass cls, jstring jPath) {
|
||||
const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
|
||||
|
||||
assert(cpu_isPaused() && "considered dangerous to save state when CPU thread is running");
|
||||
|
||||
LOG(": (%s)", path);
|
||||
if (!emulator_saveState(path)) {
|
||||
LOG("OOPS, could not save emulator state");
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, jPath, path);
|
||||
}
|
||||
|
||||
jstring Java_org_deadc0de_apple2ix_Apple2Activity_nativeLoadState(JNIEnv *env, jclass cls, jstring jPath) {
|
||||
const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
|
||||
|
||||
assert(cpu_isPaused() && "considered dangerous to save state when CPU thread is running");
|
||||
|
||||
LOG(": (%s)", path);
|
||||
if (!emulator_loadState(path)) {
|
||||
LOG("OOPS, could not load emulator state");
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, jPath, path);
|
||||
|
||||
// restoring state may cause a change in disk paths, so we need to notify the Java/Android menu system of the change
|
||||
// (normally we drive state from the Java/menu side...)
|
||||
char *disk1 = disk6.disk[0].file_name;
|
||||
bool readOnly1 = disk6.disk[0].is_protected;
|
||||
char *disk2 = disk6.disk[1].file_name;
|
||||
bool readOnly2 = disk6.disk[1].is_protected;
|
||||
char *str = NULL;
|
||||
jstring jstr = NULL;
|
||||
asprintf(&str, "{ disk1 = \"%s\"; readOnly1 = %s; disk2 = \"%s\"; readOnly2 = %s }", (disk1 ?: ""), readOnly1 ? "true" : "false", (disk2 ?: ""), readOnly2 ? "true" : "false");
|
||||
if (str) {
|
||||
jstr = (*env)->NewStringUTF(env, str);
|
||||
ASPRINTF_FREE(str);
|
||||
}
|
||||
|
||||
return jstr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
|
||||
|
||||
@@ -110,6 +110,11 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickVisibili
|
||||
joydriver_setShowControls(visibility);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickAzimuthVisibility(JNIEnv *env, jclass cls, jboolean visibility) {
|
||||
LOG("visibility: %d", visibility);
|
||||
joydriver_setShowAzimuth(visibility);
|
||||
}
|
||||
|
||||
jint Java_org_deadc0de_apple2ix_Apple2Preferences_nativeGetCurrentTouchDevice(JNIEnv *env, jclass cls) {
|
||||
LOG("%s", "");
|
||||
if (joydriver_ownsScreen()) {
|
||||
@@ -130,19 +135,28 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchMenuEnabled(JNIE
|
||||
interface_setTouchMenuEnabled(enabled);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetShowDiskOperationAnimation(JNIEnv *env, jclass cls, jboolean enabled) {
|
||||
LOG("enabled : %d", enabled);
|
||||
if (video_backend && video_backend->animation_setEnableShowTrackSector) {
|
||||
video_backend->animation_setEnableShowTrackSector(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchKeyboardLowercaseEnabled(JNIEnv *env, jclass cls, jboolean enabled) {
|
||||
LOG("enabled : %d", enabled);
|
||||
keydriver_setLowercaseEnabled(enabled);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchMenuVisibility(JNIEnv *env, jclass cls, jfloat alpha) {
|
||||
LOG("visibility : %f", alpha);
|
||||
interface_setTouchMenuVisibility(alpha);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchKeyboardVisibility(JNIEnv *env, jclass cls, jfloat inactiveAlpha, jfloat activeAlpha) {
|
||||
LOG("inactive:%f active:%f", inactiveAlpha, activeAlpha);
|
||||
keydriver_setVisibilityWhenOwnsScreen(inactiveAlpha, activeAlpha);
|
||||
interface_setTouchMenuVisibility(inactiveAlpha, activeAlpha);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchKeyboardGlyphScale(JNIEnv *env, jclass cls, jint glyphScale) {
|
||||
LOG("glyphScale:%d", glyphScale);
|
||||
keydriver_setGlyphScale(glyphScale);
|
||||
interface_setGlyphScale(glyphScale);
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickButtonTypes(JNIEnv *env, jclass cls, jint touchDownButton, jint northButton, jint southButton) {
|
||||
@@ -170,7 +184,7 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickButtonTy
|
||||
rosetteChars[ROSETTE_NORTH] = (uint8_t)MOUSETEXT_UP; rosetteScancodes[ROSETTE_NORTH] = -1;
|
||||
rosetteChars[ROSETTE_NORTHEAST] = ' '; rosetteScancodes[ROSETTE_NORTHEAST] = -1;
|
||||
rosetteChars[ROSETTE_WEST] = (uint8_t)MOUSETEXT_LEFT; rosetteScancodes[ROSETTE_WEST] = -1;
|
||||
rosetteChars[ROSETTE_CENTER] = '+'; rosetteScancodes[ROSETTE_CENTER] = -1;
|
||||
rosetteChars[ROSETTE_CENTER] = ICONTEXT_MENU_TOUCHJOY; rosetteScancodes[ROSETTE_CENTER] = -1;
|
||||
rosetteChars[ROSETTE_EAST] = (uint8_t)MOUSETEXT_RIGHT; rosetteScancodes[ROSETTE_EAST] = -1;
|
||||
rosetteChars[ROSETTE_SOUTHWEST] = ' '; rosetteScancodes[ROSETTE_SOUTHWEST] = -1;
|
||||
rosetteChars[ROSETTE_SOUTH] = (uint8_t)MOUSETEXT_DOWN; rosetteScancodes[ROSETTE_SOUTH] = -1;
|
||||
@@ -227,6 +241,9 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeTouchJoystickSetKeypadTy
|
||||
for (unsigned int i=0; i<(ROSETTE_ROWS * ROSETTE_COLS); i++) {
|
||||
actualChars[i] = (uint8_t)rosetteChars[i];
|
||||
}
|
||||
if (actualChars[4] == ICONTEXT_NONACTIONABLE) {
|
||||
actualChars[4] = ICONTEXT_MENU_TOUCHJOY;
|
||||
}
|
||||
joydriver_setTouchAxisTypes(actualChars, rosetteScans);
|
||||
joydriver_setTouchButtonTypes(
|
||||
(touchjoy_button_type_t)buttonsChars[0], buttonsScans[0],
|
||||
|
||||
@@ -39,8 +39,8 @@ APPLE2_MAIN_SRC = \
|
||||
$(APPLE2_SRC_PATH)/interface.c $(APPLE2_SRC_PATH)/disk.c $(APPLE2_SRC_PATH)/cpu-supp.c \
|
||||
jnihooks.c jniprefs.c androidkeys.c
|
||||
|
||||
APPLE2_OPTIM_CFLAGS := -g -O2
|
||||
APPLE2_BASE_CFLAGS := -DAPPLE2IX=1 -DINTERFACE_TOUCH=1 -DMOBILE_DEVICE=1 -DVIDEO_OPENGL=1 -DDEBUGGER=1 -DAUDIO_ENABLED=1 -std=gnu11 $(APPLE2_OPTIM_CFLAGS) -I$(APPLE2_SRC_PATH)
|
||||
APPLE2_OPTIM_CFLAGS := -O2
|
||||
APPLE2_BASE_CFLAGS := -DAPPLE2IX=1 -DINTERFACE_TOUCH=1 -DMOBILE_DEVICE=1 -DVIDEO_OPENGL=1 -DDEBUGGER=1 -DAUDIO_ENABLED=1 -std=gnu11 -DPREVENT_TEXTREL=1 -fPIC $(APPLE2_OPTIM_CFLAGS) -I$(APPLE2_SRC_PATH)
|
||||
APPLE2_BASE_LDLIBS := -llog -landroid -lGLESv2 -lz -lOpenSLES
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += cpufeatures
|
||||
|
||||
@@ -12,12 +12,13 @@ include $(COMMON_SOURCES_MK)
|
||||
|
||||
LOCAL_MODULE := libapple2ix
|
||||
LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/test/testcommon.c $(APPLE2_SRC_PATH)/test/testcpu.c
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DTEST_CPU -DTESTING=1
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -g -DTEST_CPU -DTESTING=1
|
||||
LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)
|
||||
|
||||
# Add assembly files first ... mostly for the benefit of the ARM assembler ...
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
LOCAL_SRC_FILES += $(APPLE2_X86_SRC)
|
||||
LOCAL_CFLAGS += -DNO_UNDERSCORES=1
|
||||
else
|
||||
LOCAL_SRC_FILES += $(APPLE2_ARM_SRC)
|
||||
endif
|
||||
|
||||
@@ -12,12 +12,13 @@ include $(COMMON_SOURCES_MK)
|
||||
|
||||
LOCAL_MODULE := libapple2ix
|
||||
LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/test/testcommon.c $(APPLE2_SRC_PATH)/test/testdisk.c
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DTEST_DISK -DTESTING=1 -DDISK_TRACING=1
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -g -DTEST_DISK -DTESTING=1 -DDISK_TRACING=1
|
||||
LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)
|
||||
|
||||
# Add assembly files first ... mostly for the benefit of the ARM assembler ...
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
LOCAL_SRC_FILES += $(APPLE2_X86_SRC)
|
||||
LOCAL_CFLAGS += -DNO_UNDERSCORES=1
|
||||
else
|
||||
LOCAL_SRC_FILES += $(APPLE2_ARM_SRC)
|
||||
endif
|
||||
|
||||
@@ -12,12 +12,13 @@ include $(COMMON_SOURCES_MK)
|
||||
|
||||
LOCAL_MODULE := libapple2ix
|
||||
LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/test/testcommon.c $(APPLE2_SRC_PATH)/test/testdisplay.c
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DTEST_DISPLAY -DTESTING=1
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -g -DTEST_DISPLAY -DTESTING=1
|
||||
LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)
|
||||
|
||||
# Add assembly files first ... mostly for the benefit of the ARM assembler ...
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
LOCAL_SRC_FILES += $(APPLE2_X86_SRC)
|
||||
LOCAL_CFLAGS += -DNO_UNDERSCORES=1
|
||||
else
|
||||
LOCAL_SRC_FILES += $(APPLE2_ARM_SRC)
|
||||
endif
|
||||
|
||||
@@ -12,12 +12,13 @@ include $(COMMON_SOURCES_MK)
|
||||
|
||||
LOCAL_MODULE := libapple2ix
|
||||
LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/test/testcommon.c $(APPLE2_SRC_PATH)/test/testvm.c
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DTEST_VM -DTESTING=1
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -g -DTEST_VM -DTESTING=1
|
||||
LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)
|
||||
|
||||
# Add assembly files first ... mostly for the benefit of the ARM assembler ...
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
LOCAL_SRC_FILES += $(APPLE2_X86_SRC)
|
||||
LOCAL_CFLAGS += -DNO_UNDERSCORES=1
|
||||
else
|
||||
LOCAL_SRC_FILES += $(APPLE2_ARM_SRC)
|
||||
endif
|
||||
|
||||
@@ -56,26 +56,31 @@ static int _convert_crlf_to_lf(void) {
|
||||
|
||||
// convert CRLF -> LF
|
||||
|
||||
ssize_t outlen=0;
|
||||
ssize_t outmax=0;
|
||||
for (ssize_t i=0; i<inlen; i++) {
|
||||
char c = inbuf[i];
|
||||
|
||||
if (sawCR && (c != LF)) {
|
||||
outbuf[outlen++] = CR;
|
||||
outbuf[outmax++] = CR;
|
||||
}
|
||||
|
||||
sawCR = false;
|
||||
if (c == CR) {
|
||||
sawCR = true;
|
||||
} else {
|
||||
outbuf[outlen++] = c;
|
||||
outbuf[outmax++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY(write(STDOUT_FILENO, outbuf, outlen)) == -1) {
|
||||
errWrt = "error writing to stdout";
|
||||
break;
|
||||
}
|
||||
ssize_t outlen = 0;
|
||||
do {
|
||||
if (TEMP_FAILURE_RETRY(outlen = write(STDOUT_FILENO, outbuf, outmax)) == -1) {
|
||||
errWrt = "error writing to stdout";
|
||||
break;
|
||||
}
|
||||
outbuf += outlen;
|
||||
outmax -= outlen;
|
||||
} while (outmax > 0);
|
||||
}
|
||||
|
||||
if (sawCR) {
|
||||
|
||||
17
Apple2Mac/Apple2Mac-Prefix.pch
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Prefix header
|
||||
//
|
||||
// The contents of this file are implicitly included at the beginning of every source file.
|
||||
//
|
||||
|
||||
#import <TargetConditionals.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
# ifdef __OBJC__
|
||||
# import <UIKit/UIKit.h>
|
||||
# endif
|
||||
#else
|
||||
# ifdef __OBJC__
|
||||
# import <Cocoa/Cocoa.h>
|
||||
# endif
|
||||
#endif
|
||||
@@ -6,10 +6,14 @@
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleHelpBookFolder</key>
|
||||
<string>Apple2Mac.help</string>
|
||||
<key>CFBundleHelpBookName</key>
|
||||
<string>org.deadc0de.Apple2Mac.help</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.deadc0de.Apple2Mac</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@@ -22,10 +26,6 @@
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleHelpBookFolder</key>
|
||||
<string>Apple2Mac.help</string>
|
||||
<key>CFBundleHelpBookName</key>
|
||||
<string>org.deadc0de.Apple2Mac.help</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.education</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
23
Apple2Mac/Apple2Mac/AppleViewController.h
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// AppleViewController.h
|
||||
// Apple2Mac
|
||||
//
|
||||
// Created by Jerome Vernet on 24/12/2015.
|
||||
// Copyright © 2015 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "iosPrefControllerViewController.h"
|
||||
|
||||
@interface AppleViewController : UIViewController
|
||||
@property (nonatomic, assign) BOOL paused;
|
||||
@property (assign) IBOutlet UIToolbar *mainToolBar;
|
||||
@property (assign) IBOutlet iosPrefControllerViewController *viewPrefs;
|
||||
|
||||
-(IBAction)rebootItemSelected:(id)sender;
|
||||
-(IBAction)prefsItemSelected:(id)sender;
|
||||
-(IBAction)toggleCPUSpeedItemSelected:(id)sender;
|
||||
-(IBAction)togglePauseItemSelected:(id)sender;
|
||||
-(IBAction)diskInsert:(id)sender;
|
||||
|
||||
@end
|
||||
120
Apple2Mac/Apple2Mac/AppleViewController.m
Normal file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// AppleViewController.m
|
||||
// Apple2Mac
|
||||
//
|
||||
// Created by Jerome Vernet on 24/12/2015.
|
||||
// Copyright © 2015 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppleViewController.h"
|
||||
#import "common.h"
|
||||
#import "modelUtil.h"
|
||||
|
||||
@interface AppleViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppleViewController
|
||||
|
||||
@synthesize paused = _paused;
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// [self mainToolBar ];
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Navigation
|
||||
|
||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
// Get the new view controller using [segue destinationViewController].
|
||||
// Pass the selected object to the new view controller.
|
||||
cpu_pause();
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)unwindForSegue:(UIStoryboardSegue*)sender
|
||||
{
|
||||
cpu_resume();
|
||||
}
|
||||
- (IBAction)upSwipe:(id)sender
|
||||
{
|
||||
self.mainToolBar.hidden=NO;
|
||||
}
|
||||
|
||||
- (IBAction)diskInsert:(id)sender
|
||||
{
|
||||
NSLog(@"LISTING ALL FILES FOUND");
|
||||
|
||||
int Count;
|
||||
NSString *path;
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Disks"];
|
||||
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
|
||||
for (Count = 0; Count < (int)[directoryContent count]; Count++)
|
||||
{
|
||||
NSLog(@"File %d: %@", (Count + 1), [directoryContent objectAtIndex:Count]);
|
||||
}
|
||||
}
|
||||
|
||||
-(IBAction)rebootItemSelected:(id)sender{
|
||||
cpu65_reboot();
|
||||
}
|
||||
|
||||
-(IBAction)prefsItemSelected:(id)sender{
|
||||
cpu_pause();
|
||||
//[self.viewPrefs ];
|
||||
//pause
|
||||
//show pref windows
|
||||
cpu_resume();
|
||||
}
|
||||
|
||||
- (IBAction)toggleCPUSpeedItemSelected:(id)sender
|
||||
{
|
||||
cpu_pause();
|
||||
timing_toggleCPUSpeed();
|
||||
if (video_backend && video_backend->animation_showCPUSpeed)
|
||||
{
|
||||
video_backend->animation_showCPUSpeed();
|
||||
}
|
||||
cpu_resume();
|
||||
}
|
||||
|
||||
- (IBAction)togglePauseItemSelected:(id)sender
|
||||
{
|
||||
NSAssert(pthread_main_np(), @"Pause emulation called from non-main thread");
|
||||
self.paused = !_paused;
|
||||
}
|
||||
- (void)setPaused:(BOOL)paused
|
||||
{
|
||||
if (_paused == paused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = paused;
|
||||
if (paused)
|
||||
{
|
||||
cpu_pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_resume();
|
||||
}
|
||||
if (video_backend && video_backend->animation_showPaused)
|
||||
{
|
||||
video_backend->animation_showPaused();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6245" systemVersion="13F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment version="1060" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6245"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
@@ -88,7 +88,7 @@
|
||||
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1178"/>
|
||||
<view key="contentView" id="6V4-fW-Bkm">
|
||||
<rect key="frame" x="7" y="11" width="480" height="270"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
</window>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment version="1060" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
@@ -23,27 +23,6 @@
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Reboot Emulator" id="FjO-UG-hG2" userLabel="Menu Item - Reboot">
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
CA
|
||||
</string>
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="reboot:" target="M8b-ga-iOS" id="AbH-Xq-1VZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Disks" id="IU3-Bt-BuK" userLabel="Menu Item - Disks">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Disks" systemMenu="help" id="Wh3-tN-xkr">
|
||||
<items>
|
||||
<menuItem title="Insert..." keyEquivalent="D" id="Oj8-qO-A80" userLabel="Menu Item - Insert">
|
||||
<connections>
|
||||
<action selector="showDisksWindow:" target="M8b-ga-iOS" id="GVw-D1-gi0"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="236">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
@@ -52,21 +31,6 @@ CA
|
||||
<action selector="showPreferences:" target="M8b-ga-iOS" id="oDD-g4-QEJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Toggle Full Screen" keyEquivalent="F" id="rP9-cs-9dM">
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="M8b-ga-iOS" id="Xan-eQ-CRM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Toggle CPU Speed" keyEquivalent="S" id="b9q-zr-oNh">
|
||||
<connections>
|
||||
<action selector="toggleCPUSpeed:" target="M8b-ga-iOS" id="fA3-dJ-wtg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Pause Emulation" keyEquivalent="X" id="r9g-Ro-UwW">
|
||||
<connections>
|
||||
<action selector="togglePause:" target="M8b-ga-iOS" id="c65-mm-bIj"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="143">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
@@ -103,6 +67,299 @@ CA
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="4dZ-4f-42V">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="ma8-CB-dnr">
|
||||
<items>
|
||||
<menuItem title="Reboot Emulator" id="Xr5-Y9-tRL" userLabel="Menu Item - Reboot">
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
CA
|
||||
</string>
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="reboot:" target="M8b-ga-iOS" id="XtR-At-SSS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Toggle CPU Speed" keyEquivalent="S" id="pJl-yR-ULm">
|
||||
<connections>
|
||||
<action selector="toggleCPUSpeed:" target="M8b-ga-iOS" id="JUd-Uf-yyX"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Pause Emulation" keyEquivalent="X" id="OKW-bt-a58">
|
||||
<connections>
|
||||
<action selector="togglePause:" target="M8b-ga-iOS" id="KLo-hL-5zu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Bp7-3g-GDj"/>
|
||||
<menuItem title="Disks" id="rp2-u6-d0B" userLabel="Menu Item - Disks">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Disks" systemMenu="help" id="8XK-7x-7hh">
|
||||
<items>
|
||||
<menuItem title="Insert..." keyEquivalent="D" id="JhN-ZL-f2O" userLabel="Menu Item - Insert">
|
||||
<connections>
|
||||
<action selector="showDisksWindow:" target="M8b-ga-iOS" id="EEd-WE-b9g"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Mec-fL-Gcp"/>
|
||||
<menuItem title="Page Setup…" enabled="NO" keyEquivalent="P" id="0HU-OV-39A">
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="GVI-mL-WRX"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" enabled="NO" keyEquivalent="p" id="dXC-8t-bQ7">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="MkR-UN-gGO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="ZKa-Nk-KCW">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="WCv-04-9tQ">
|
||||
<items>
|
||||
<menuItem title="Undo" enabled="NO" keyEquivalent="z" id="7ji-O5-1oP">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="nTg-8e-qqX"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" enabled="NO" keyEquivalent="Z" id="jYN-aO-Gse">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="3cC-fV-e1H"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="cRv-NN-CM3"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="B9f-O6-lco">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="cEF-Mr-gEI"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="BRV-TN-Pzv">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="xcu-og-fVt"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="geM-qO-aZ2">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="uDP-lX-2QO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" enabled="NO" keyEquivalent="V" id="gUM-x3-iEs">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="62M-Kk-7W0"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="i2b-GO-OI0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="Ofc-Df-mrY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="l6c-o9-Lcb">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="hfq-sH-Hrd"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPI-YZ-Ej7"/>
|
||||
<menuItem title="Find" id="wpu-4I-0bh">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="Hm4-5s-n7i">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="xx4-kU-rZA">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="QjO-TQ-NTO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="Mzr-n7-gii">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="uJq-AO-zpb"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="EcB-rH-6Fn">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="7oO-Bh-siN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="cYe-Hg-XZ2">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="NLQ-EP-xeT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="VRT-xH-o4f">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="hvL-8z-0XQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="lBL-48-NL8">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="7rr-yF-apD">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="TxR-Iv-fxN">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="Fi5-eF-xtd"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="1NC-db-BRz">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="4Cb-VT-uRv"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="1VO-3p-hKr"/>
|
||||
<menuItem title="Check Spelling While Typing" id="R7T-Py-IUl">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="fRX-Xn-i0s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="A2e-bf-a76">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="PYu-Cs-Nvn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="Z8h-ou-V7a">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="keB-gX-m3T"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="jb7-2B-6xa">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="iMe-LJ-g9B">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="Fa7-uJ-Naj">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="PoI-1s-Hjv"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="lQF-eK-0p9"/>
|
||||
<menuItem title="Smart Copy/Paste" id="KS0-Pe-biv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="Rrf-F9-auF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="uXJ-Bm-7aA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="pZw-O8-1Q6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="8KL-lT-U1f">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="EHC-04-hyV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="hq9-VC-W6c">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="3BN-Bo-i7K"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="qeO-vj-7ge">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="fAF-LU-W4B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="vGB-cx-gYU">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="sQF-gF-l9g"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="898-0g-Oio">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="7Zl-6t-TqO">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="6C2-i8-KVq">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="pjO-OZ-Lwk"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="ZZP-5z-YrA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="4ZN-4K-BgR"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="MIg-Ae-S5l">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="wNF-kk-YaV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="phA-NA-yWC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="voe-xv-aqn">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="zfA-gc-OcH">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="kdt-Em-BHj"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="FHw-p7-luT">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="cAo-hP-Ubn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="TP0-Ag-yPc">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="v0D-uE-mdE">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="dq0-ap-hiO">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="wuW-Cq-NVB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="Kw3-wb-a0i">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="Rab-bb-j9C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Toggle Full Screen" keyEquivalent="F" id="Lem-uE-El9">
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="M8b-ga-iOS" id="0fX-bE-3MN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="yFd-C5-chc"/>
|
||||
<menuItem title="Bring All to Front" id="Kwp-da-LVP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="iee-gu-gae"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="490">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="491">
|
||||
@@ -118,21 +375,50 @@ CA
|
||||
</items>
|
||||
</menu>
|
||||
<window title="Apple2Mac" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371" userLabel="Window - Apple2Mac" customClass="EmulatorWindow">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" unifiedTitleAndToolbar="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="200" y="200" width="568" height="384"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1178"/>
|
||||
<view key="contentView" id="372" customClass="EmulatorGLView">
|
||||
<rect key="frame" x="0.0" y="-1" width="568" height="384"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="568" height="384"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<point key="canvasLocation" x="-315" y="-1328"/>
|
||||
<toolbar key="toolbar" implicitIdentifier="8323D01A-4ECF-4973-8DC6-3BB0A67F10FD" allowsUserCustomization="NO" displayMode="iconAndLabel" sizeMode="small" id="gXM-1s-f0F">
|
||||
<allowedToolbarItems>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarShowColorsItem" id="oed-am-Cfb"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarPrintItem" id="sk6-41-C3g"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="AoN-cv-QQ2"/>
|
||||
<toolbarItem implicitItemIdentifier="CBD2C3ED-B0AA-40F1-818F-B61B04F93E7F" label="Preferences" paletteLabel="Preferences" tag="-1" image="Prefs" id="85b-WO-tks"/>
|
||||
<toolbarItem implicitItemIdentifier="1AF00BE2-1806-4F36-AA9B-EDCD8587D441" label="Reboot" paletteLabel="Reboot" tag="-1" image="Reboot" id="hOg-ec-Okz"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="372-hX-Xt1"/>
|
||||
<toolbarItem implicitItemIdentifier="ED8F052E-C9AE-42F6-BA6D-2A675E8390E5" label="Disks" paletteLabel="Disks" tag="-1" image="Disks" id="jHk-qj-bmw"/>
|
||||
<toolbarItem implicitItemIdentifier="0E674D24-EE72-4444-A2D2-256161A8EEC6" label="CPU" paletteLabel="CPU" tag="-1" image="CPU" id="xjq-6u-Yc9" userLabel="CPU">
|
||||
<connections>
|
||||
<action selector="toggleCPUSpeed:" target="M8b-ga-iOS" id="FVD-QZ-joo"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="B1B89899-E7C4-4A6A-9B19-B29D3C7FB7CC" label="Pause" paletteLabel="Pause" tag="-1" image="Stop" id="hkP-Yj-QZG"/>
|
||||
<toolbarItem implicitItemIdentifier="3358D7A0-4F67-4503-ADD8-6E900BB291CC" label="Toolbar Item" paletteLabel="Toolbar Item" tag="-1" image="NSUser" id="JbN-Qp-xsc"/>
|
||||
<toolbarItem implicitItemIdentifier="E796EDE5-7BB6-4CBB-AC6B-17DA3FC696C9" label="FullScreen" paletteLabel="FullScreen" tag="-1" image="Fullscreen" id="Ahr-ZD-7wt"/>
|
||||
</allowedToolbarItems>
|
||||
<defaultToolbarItems>
|
||||
<toolbarItem reference="hOg-ec-Okz"/>
|
||||
<toolbarItem reference="hkP-Yj-QZG"/>
|
||||
<toolbarItem reference="Ahr-ZD-7wt"/>
|
||||
<toolbarItem reference="AoN-cv-QQ2"/>
|
||||
<toolbarItem reference="AoN-cv-QQ2"/>
|
||||
<toolbarItem reference="jHk-qj-bmw"/>
|
||||
<toolbarItem reference="372-hX-Xt1"/>
|
||||
<toolbarItem reference="sk6-41-C3g"/>
|
||||
<toolbarItem reference="85b-WO-tks"/>
|
||||
</defaultToolbarItems>
|
||||
</toolbar>
|
||||
<point key="canvasLocation" x="-201" y="-1220"/>
|
||||
</window>
|
||||
<customObject id="494" userLabel="EmulatorGLView" customClass="EmulatorGLView"/>
|
||||
<customObject id="M8b-ga-iOS" customClass="EmulatorWindowController" colorLabel="IBBuiltInLabel-Blue">
|
||||
<connections>
|
||||
<outlet property="disksWindow" destination="RAk-at-ZT4" id="64k-qW-zF5"/>
|
||||
<outlet property="pauseMenuItem" destination="r9g-Ro-UwW" id="4YW-pt-lai"/>
|
||||
<outlet property="prefsWindow" destination="Mzv-VG-jce" id="dQt-pf-qdi"/>
|
||||
<outlet property="view" destination="372" id="pRG-Kn-92X"/>
|
||||
<outlet property="window" destination="371" id="z3B-S9-PsV"/>
|
||||
@@ -144,7 +430,7 @@ CA
|
||||
<rect key="contentRect" x="109" y="132" width="522" height="302"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="778"/>
|
||||
<view key="contentView" id="rBl-rx-7uF">
|
||||
<rect key="frame" x="0.0" y="-5" width="522" height="302"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="522" height="302"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="laF-n4-ciZ">
|
||||
@@ -238,7 +524,7 @@ CA
|
||||
<rect key="frame" x="20" y="153" width="212" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="cellSize" width="89" height="18"/>
|
||||
<size key="cellSize" width="88" height="18"/>
|
||||
<size key="intercellSpacing" width="4" height="2"/>
|
||||
<buttonCell key="prototype" type="radio" title="Radio" imagePosition="left" alignment="left" inset="2" id="800-L1-WxW">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
@@ -266,7 +552,7 @@ CA
|
||||
<rect key="frame" x="271" y="153" width="212" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="cellSize" width="89" height="18"/>
|
||||
<size key="cellSize" width="88" height="18"/>
|
||||
<size key="intercellSpacing" width="4" height="2"/>
|
||||
<buttonCell key="prototype" type="radio" title="Radio" imagePosition="left" alignment="left" inset="2" id="uEc-fa-XXZ">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
@@ -365,7 +651,7 @@ DQ
|
||||
<rect key="contentRect" x="109" y="132" width="580" height="360"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="778"/>
|
||||
<view key="contentView" id="bfK-7M-z1X">
|
||||
<rect key="frame" x="0.0" y="1" width="580" height="360"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="580" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<tabView id="xvZ-VK-VbM">
|
||||
@@ -729,5 +1015,15 @@ DQ
|
||||
<outlet property="window" destination="Mzv-VG-jce" id="86q-Ys-9Mt"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<toolbarItem implicitItemIdentifier="ED8F052E-C9AE-42F6-BA6D-2A675E8390E5" label="Disks" paletteLabel="Disks" tag="-1" image="Disks" id="iyV-hM-okT"/>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="CPU" width="32" height="32"/>
|
||||
<image name="Disks" width="32" height="32"/>
|
||||
<image name="Fullscreen" width="32" height="32"/>
|
||||
<image name="NSUser" width="32" height="32"/>
|
||||
<image name="Prefs" width="32" height="32"/>
|
||||
<image name="Reboot" width="32" height="32"/>
|
||||
<image name="Stop" width="32" height="32"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
23
Apple2Mac/Apple2Mac/Images.xcassets/CPU.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "cpu32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "cpu64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "cpu128.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Apple2Mac/Apple2Mac/Images.xcassets/CPU.imageset/cpu128.png
vendored
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/CPU.imageset/cpu32.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/CPU.imageset/cpu64.png
vendored
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
6
Apple2Mac/Apple2Mac/Images.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
23
Apple2Mac/Apple2Mac/Images.xcassets/Disks.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "floppy32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "floppy64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "floppy128.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Disks.imageset/floppy128.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Disks.imageset/floppy32.png
vendored
Normal file
|
After Width: | Height: | Size: 907 B |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Disks.imageset/floppy64.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
23
Apple2Mac/Apple2Mac/Images.xcassets/Fullscreen.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "fullscreen32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "fullscreen64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "fullscreen128.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Fullscreen.imageset/fullscreen128.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Fullscreen.imageset/fullscreen32.png
vendored
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Fullscreen.imageset/fullscreen64.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
23
Apple2Mac/Apple2Mac/Images.xcassets/Prefs.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "pref32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "pref64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "pref128.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Prefs.imageset/pref128.png
vendored
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Prefs.imageset/pref32.png
vendored
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Prefs.imageset/pref64.png
vendored
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
21
Apple2Mac/Apple2Mac/Images.xcassets/Reboot.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "reboot32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Reboot.imageset/reboot32.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
23
Apple2Mac/Apple2Mac/Images.xcassets/Run.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "play32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "play64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "play128.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Run.imageset/play128.png
vendored
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Run.imageset/play32.png
vendored
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Run.imageset/play64.png
vendored
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
23
Apple2Mac/Apple2Mac/Images.xcassets/Stop.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "stop32.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "stop64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "stop128.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Stop.imageset/stop128.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Stop.imageset/stop32.png
vendored
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
Apple2Mac/Apple2Mac/Images.xcassets/Stop.imageset/stop64.png
vendored
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
19
Apple2Mac/Apple2Mac/disksViewController.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// disksViewController.h
|
||||
// Apple2Mac
|
||||
//
|
||||
// Created by Jerome Vernet on 31/12/2015.
|
||||
// Copyright © 2015 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface disksViewController : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate>
|
||||
@property (retain, nonatomic) IBOutlet UIPickerView *disk1Picker;
|
||||
@property (retain, nonatomic) IBOutlet UIPickerView *disk2Picker;
|
||||
@property (retain, nonatomic) IBOutlet UISwitch *diskAProtection;
|
||||
@property (retain, nonatomic) IBOutlet UISwitch *diskBProtection;
|
||||
|
||||
@property (strong,nonatomic) NSArray *_disks;
|
||||
@property (retain,nonatomic) NSString *path;
|
||||
@end
|
||||
93
Apple2Mac/Apple2Mac/disksViewController.m
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// disksViewController.m
|
||||
// Apple2Mac
|
||||
//
|
||||
// Created by Jerome Vernet on 31/12/2015.
|
||||
// Copyright © 2015 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import "disksViewController.h"
|
||||
#import "common.h"
|
||||
|
||||
@implementation disksViewController
|
||||
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
|
||||
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
//self.path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Disks"];
|
||||
self.path = [paths objectAtIndex:0];
|
||||
NSLog(@"Path:%@",self.path);
|
||||
self._disks=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:NULL];
|
||||
|
||||
// Connect data
|
||||
self.disk1Picker.dataSource = self;
|
||||
self.disk1Picker.delegate = self;
|
||||
self.disk2Picker.dataSource = self;
|
||||
self.disk2Picker.delegate = self;
|
||||
}
|
||||
|
||||
// The number of columns of data
|
||||
- (int)numberOfComponentsInPickerView:(UIPickerView *)pickerView
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The number of rows of data
|
||||
- (int)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
|
||||
{
|
||||
return self._disks.count;
|
||||
//_pickerData.cout;
|
||||
}
|
||||
|
||||
// The data to return for the row and component (column) that's being passed in
|
||||
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
|
||||
{
|
||||
return [self._disks objectAtIndex:row];
|
||||
}
|
||||
|
||||
// Catpure the picker view selection
|
||||
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
|
||||
{
|
||||
// This method is triggered whenever the user makes a change to the picker selection.
|
||||
// The parameter named row and component represents what was selected.
|
||||
int drive=0;
|
||||
BOOL ro=YES;
|
||||
|
||||
if(pickerView==self.disk1Picker)
|
||||
{
|
||||
drive=0;
|
||||
ro=self.diskAProtection.on;
|
||||
}
|
||||
if(pickerView==self.disk2Picker)
|
||||
{
|
||||
drive=1;
|
||||
ro=self.diskBProtection.on;
|
||||
}
|
||||
|
||||
NSLog(@"Selected Row %d %@ %c", row,(NSString*)[self._disks objectAtIndex:row],ro);
|
||||
disk6_eject(drive);
|
||||
const char *errMsg = disk6_insert(drive, [[self.path stringByAppendingPathComponent:[self._disks objectAtIndex:row]] UTF8String], ro);
|
||||
}
|
||||
|
||||
- (IBAction)unwindToMainViewController:(UIStoryboardSegue*)sender
|
||||
{ }
|
||||
|
||||
-(IBAction)goodbye:(id)sender
|
||||
{
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
cpu_resume();
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_diskAProtection release];
|
||||
[_diskBProtection release];
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
|
||||
1029
Apple2Mac/Apple2Mac/en.lproj/MainMenu.xib
Normal file
29
Apple2Mac/Apple2Mac/fr.lproj/Credits.rtf
Normal file
@@ -0,0 +1,29 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210
|
||||
{\fonttbl\f0\fnil\fcharset0 Menlo-Bold;\f1\fnil\fcharset0 Menlo-Regular;\f2\fnil\fcharset0 Menlo-Italic;
|
||||
}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\vieww9600\viewh8400\viewkind0
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl216\slmult1\qc
|
||||
|
||||
\f0\b\fs24 \cf0 Authors\
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl216\slmult1\pardirnatural\qc
|
||||
|
||||
\f1\b0 \cf0 Aaron Culliney\
|
||||
and other contributors\
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl120\slmult1\pardirnatural\qc
|
||||
\cf0 \
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl216\slmult1\pardirnatural\qc
|
||||
|
||||
\f0\b \cf0 Web Resources
|
||||
\f1\b0 \
|
||||
|
||||
\f2\i ftp.apple.asimov.net
|
||||
\f1\i0 and elsewhere\
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl120\slmult1\pardirnatural\qc
|
||||
\cf0 \
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\sl216\slmult1\pardirnatural\qc
|
||||
|
||||
\f0\b \cf0 Special thanks to
|
||||
\f1\b0 \
|
||||
Tom Charlesworth\
|
||||
and the AppleWin project}
|
||||
2
Apple2Mac/Apple2Mac/fr.lproj/InfoPlist.strings
Normal file
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
45
Apple2Mac/Apple2Mac/fr.lproj/MainMenu-Test.strings
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
/* Class = "NSMenu"; title = "AMainMenu"; ObjectID = "29"; */
|
||||
"29.title" = "AMainMenu";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Apple2Mac"; ObjectID = "56"; */
|
||||
"56.title" = "Apple2Mac";
|
||||
|
||||
/* Class = "NSMenu"; title = "Apple2Mac"; ObjectID = "57"; */
|
||||
"57.title" = "Apple2Mac";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "About Apple2Mac"; ObjectID = "58"; */
|
||||
"58.title" = "About Apple2Mac";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Preferences…"; ObjectID = "129"; */
|
||||
"129.title" = "Preferences…";
|
||||
|
||||
/* Class = "NSMenu"; title = "Services"; ObjectID = "130"; */
|
||||
"130.title" = "Services";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Services"; ObjectID = "131"; */
|
||||
"131.title" = "Services";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Hide Apple2Mac"; ObjectID = "134"; */
|
||||
"134.title" = "Hide Apple2Mac";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Quit Apple2Mac"; ObjectID = "136"; */
|
||||
"136.title" = "Quit Apple2Mac";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "145"; */
|
||||
"145.title" = "Hide Others";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Show All"; ObjectID = "150"; */
|
||||
"150.title" = "Show All";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Help"; ObjectID = "490"; */
|
||||
"490.title" = "Help";
|
||||
|
||||
/* Class = "NSMenu"; title = "Help"; ObjectID = "491"; */
|
||||
"491.title" = "Help";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Apple2Mac Help"; ObjectID = "492"; */
|
||||
"492.title" = "Apple2Mac Help";
|
||||
|
||||
/* Class = "NSWindow"; title = "Window"; ObjectID = "HyN-la-Rec"; */
|
||||
"HyN-la-Rec.title" = "Window";
|
||||
1062
Apple2Mac/Apple2Mac/fr.lproj/MainMenu.xib
Normal file
45
Apple2Mac/Apple2Mac/iosPrefControllerViewController.h
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// iosPrefControllerViewController.h
|
||||
// Apple2Mac
|
||||
//
|
||||
// Created by Jerome Vernet on 24/12/2015.
|
||||
// Copyright © 2015 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define kApple2SavedPrefs @"kApple2SavedPrefs"
|
||||
#define kApple2CPUSpeed @"kApple2CPUSpeed"
|
||||
#define kApple2CPUSpeedIsMax @"kApple2CPUSpeedIsMax"
|
||||
#define kApple2AltSpeed @"kApple2AltSpeed"
|
||||
#define kApple2AltSpeedIsMax @"kApple2AltSpeedIsMax"
|
||||
#define kApple2SoundcardConfig @"kApple2SoundcardConfig"
|
||||
#define kApple2ColorConfig @"kApple2ColorConfig"
|
||||
#define kApple2JoystickConfig @"kApple2JoystickConfig"
|
||||
#define kApple2JoystickAutoRecenter @"kApple2JoystickAutoRecenter"
|
||||
#define kApple2JoystickClipToRadius @"kApple2JoystickClipToRadius"
|
||||
#define kApple2PrefStartupDiskA @"kApple2PrefStartupDiskA"
|
||||
#define kApple2PrefStartupDiskAProtected @"kApple2PrefStartupDiskAProtected"
|
||||
#define kApple2PrefStartupDiskB @"kApple2PrefStartupDiskB"
|
||||
#define kApple2PrefStartupDiskBProtected @"kApple2PrefStartupDiskBProtected"
|
||||
#define kApple2JoystickStep @"kApple2JoystickStep"
|
||||
|
||||
|
||||
@interface iosPrefControllerViewController : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate>
|
||||
|
||||
@property (retain, nonatomic) IBOutlet UIPickerView *videoModePicker;
|
||||
@property (retain, nonatomic) IBOutlet UISlider *cpuSlider;
|
||||
@property (retain, nonatomic) IBOutlet UISlider *altSlider;
|
||||
@property (retain, nonatomic) IBOutlet UILabel *cpuSliderLabel;
|
||||
@property (retain, nonatomic) IBOutlet UILabel *altSliderLabel;
|
||||
@property (retain, nonatomic) IBOutlet UISwitch *cpuMaxChoice;
|
||||
@property (retain, nonatomic) IBOutlet UISwitch *altMaxChoice;
|
||||
|
||||
@property (strong,nonatomic) NSArray *_videoMode;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
230
Apple2Mac/Apple2Mac/iosPrefControllerViewController.m
Normal file
@@ -0,0 +1,230 @@
|
||||
//
|
||||
// iosPrefControllerViewController.m
|
||||
// Apple2Mac
|
||||
//
|
||||
// Created by Jerome Vernet on 24/12/2015.
|
||||
// Copyright © 2015 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import "iosPrefControllerViewController.h"
|
||||
|
||||
|
||||
#import "common.h"
|
||||
#import "modelUtil.h"
|
||||
|
||||
|
||||
@implementation iosPrefControllerViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
self._videoMode = [[NSArray alloc] initWithObjects:@"Mono",@"Color", nil];
|
||||
|
||||
// Connect data
|
||||
self.videoModePicker.dataSource = self;
|
||||
self.videoModePicker.delegate = self;
|
||||
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
BOOL firstTime = ![defaults boolForKey:kApple2SavedPrefs];
|
||||
if (firstTime)
|
||||
{
|
||||
[defaults setBool:YES forKey:kApple2SavedPrefs];
|
||||
[defaults setDouble:1.0 forKey:kApple2CPUSpeed];
|
||||
[defaults setDouble:CPU_SCALE_SLOWEST forKey:kApple2AltSpeed];
|
||||
[defaults setBool:NO forKey:kApple2CPUSpeedIsMax];
|
||||
[defaults setBool:NO forKey:kApple2AltSpeedIsMax];
|
||||
[defaults setInteger:COLOR_INTERP forKey:kApple2ColorConfig];
|
||||
// [defaults setInteger:JOY_KPAD forKey:kApple2JoystickConfig];
|
||||
[defaults setBool:YES forKey:kApple2JoystickAutoRecenter];
|
||||
[defaults removeObjectForKey:kApple2PrefStartupDiskA];
|
||||
[defaults removeObjectForKey:kApple2PrefStartupDiskB];
|
||||
}
|
||||
|
||||
cpu_scale_factor = [defaults doubleForKey:kApple2CPUSpeed];
|
||||
[self.cpuSlider setValue:cpu_scale_factor animated:NO];
|
||||
self.cpuSliderLabel.text=[NSString stringWithFormat:@"%.0f%%", cpu_scale_factor*100];
|
||||
if ([defaults boolForKey:kApple2CPUSpeedIsMax])
|
||||
{
|
||||
cpu_scale_factor = CPU_SCALE_FASTEST;
|
||||
[self.cpuMaxChoice setOn:YES];
|
||||
[self.cpuSlider setEnabled:NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.cpuMaxChoice setOn:NO];
|
||||
[self.cpuSlider setEnabled:YES];
|
||||
}
|
||||
|
||||
cpu_altscale_factor = [defaults doubleForKey:kApple2AltSpeed];
|
||||
[self.altSlider setValue:cpu_altscale_factor];
|
||||
self.altSliderLabel.text = [NSString stringWithFormat:@"%.0f%%", cpu_altscale_factor*100];
|
||||
if ([defaults boolForKey:kApple2AltSpeedIsMax])
|
||||
{
|
||||
cpu_altscale_factor = CPU_SCALE_FASTEST;
|
||||
[self.altMaxChoice setOn:YES];
|
||||
[self.altSlider setEnabled:NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.altMaxChoice setOn:NO];
|
||||
[self.altSlider setEnabled:YES];
|
||||
}
|
||||
|
||||
NSInteger mode = [defaults integerForKey:kApple2ColorConfig];
|
||||
if (! ((mode >= COLOR_NONE) && (mode < NUM_COLOROPTS)) )
|
||||
{
|
||||
mode = COLOR_NONE;
|
||||
}
|
||||
//[self.videoModePicker d:mode];
|
||||
color_mode = (color_mode_t)mode;
|
||||
|
||||
mode = [defaults integerForKey:kApple2JoystickConfig];
|
||||
if (! ((mode >= JOY_PCJOY) && (mode < NUM_JOYOPTS)) )
|
||||
{
|
||||
mode = JOY_PCJOY;
|
||||
}
|
||||
joy_mode = (joystick_mode_t)mode;
|
||||
// [self.joystickChoice selectItemAtIndex:mode];
|
||||
/*
|
||||
#ifdef KEYPAD_JOYSTICK
|
||||
joy_auto_recenter = [defaults integerForKey:kApple2JoystickAutoRecenter];
|
||||
[self.joystickRecenter setState:joy_auto_recenter ? NSOnState : NSOffState];
|
||||
joy_step = [defaults integerForKey:kApple2JoystickStep];
|
||||
if (!joy_step)
|
||||
{
|
||||
joy_step = 1;
|
||||
}
|
||||
[self.joystickStepLabel setIntegerValue:joy_step];
|
||||
[self.joystickStepper setIntegerValue:joy_step];
|
||||
#endif
|
||||
|
||||
joy_clip_to_radius = [defaults boolForKey:kApple2JoystickClipToRadius];
|
||||
[self.joystickClipToRadius setState:joy_clip_to_radius ? NSOnState : NSOffState];
|
||||
|
||||
[self _setupJoystickUI];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(drawJoystickCalibration:) name:(NSString *)kDrawTimerNotification object:nil];
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
// The number of columns of data
|
||||
- (int)numberOfComponentsInPickerView:(UIPickerView *)pickerView
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The number of rows of data
|
||||
- (int)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
|
||||
{
|
||||
return 2;
|
||||
//_pickerData.count;
|
||||
}
|
||||
|
||||
// The data to return for the row and component (column) that's being passed in
|
||||
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
|
||||
{
|
||||
return [self._videoMode objectAtIndex:row];
|
||||
}
|
||||
|
||||
// Catpure the picker view selection
|
||||
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
|
||||
{
|
||||
// This method is triggered whenever the user makes a change to the picker selection.
|
||||
// The parameter named row and component represents what was selected.
|
||||
NSLog(@"Selected Row %d", row);
|
||||
}
|
||||
|
||||
- (void)_savePrefs
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setBool:YES forKey:kApple2SavedPrefs];
|
||||
[defaults setDouble:cpu_scale_factor forKey:kApple2CPUSpeed];
|
||||
[defaults setDouble:cpu_altscale_factor forKey:kApple2AltSpeed];
|
||||
// [defaults setBool:([self.cpuMaxChoice state] == NSOnState) forKey:kApple2CPUSpeedIsMax];
|
||||
// [defaults setBool:([self.altMaxChoice state] == NSOnState) forKey:kApple2AltSpeedIsMax];
|
||||
[defaults setInteger:color_mode forKey:kApple2ColorConfig];
|
||||
[defaults setInteger:joy_mode forKey:kApple2JoystickConfig];
|
||||
// [defaults setInteger:joy_step forKey:kApple2JoystickStep];
|
||||
// [defaults setBool:joy_auto_recenter forKey:kApple2JoystickAutoRecenter];
|
||||
[defaults setBool:joy_clip_to_radius forKey:kApple2JoystickClipToRadius];
|
||||
}
|
||||
- (IBAction)sliderDidMove:(id)sender
|
||||
{
|
||||
UISlider *slider = (UISlider *)sender;
|
||||
double value = slider.value;
|
||||
if (slider == self.cpuSlider)
|
||||
{
|
||||
cpu_scale_factor = value;
|
||||
self.cpuSliderLabel.text=[NSString stringWithFormat:@"%.0f%%", value*100];
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_altscale_factor = value;
|
||||
self.altSliderLabel.text=[NSString stringWithFormat:@"%.0f%%", value*100];
|
||||
}
|
||||
|
||||
timing_initialize();
|
||||
|
||||
[self _savePrefs];
|
||||
}
|
||||
|
||||
- (IBAction)peggedChoiceChanged:(id)sender
|
||||
{
|
||||
UISwitch *maxButton = (UISwitch *)sender;
|
||||
if (maxButton == self.cpuMaxChoice)
|
||||
{
|
||||
[self.cpuSlider setEnabled:([maxButton state] != YES)];
|
||||
cpu_scale_factor = ([maxButton state] == NO) ? CPU_SCALE_FASTEST : self.cpuSlider.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.altSlider setEnabled:([maxButton state] != YES)];
|
||||
cpu_altscale_factor = ([maxButton state] == YES) ? CPU_SCALE_FASTEST : self.altSlider.value;
|
||||
}
|
||||
|
||||
timing_initialize();
|
||||
|
||||
[self _savePrefs];
|
||||
}
|
||||
/*
|
||||
#pragma mark - Navigation
|
||||
|
||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
// Get the new view controller using [segue destinationViewController].
|
||||
// Pass the selected object to the new view controller.
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
- (void)dealloc {
|
||||
/* [_videoModePicker release];
|
||||
[_cpuSlider release];
|
||||
[_altSlider release];
|
||||
[_cpuSliderLabel release];
|
||||
[_altSlider release];
|
||||
[_cpuMaxChoice release];
|
||||
[_altMaxChoice release];
|
||||
*/
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(IBAction)goodbye:(id)sender
|
||||
{
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
cpu_resume();
|
||||
}
|
||||
- (IBAction)unwindToMainViewController:(UIStoryboardSegue*)sender
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
2
Apple2Mac/Apple2MacTests/fr.lproj/InfoPlist.strings
Normal file
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
17
Apple2Mac/Apple2etvOS/AppDelegate.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// Apple2etvOS
|
||||
//
|
||||
// Created by Jerome Vernet on 01/01/2016.
|
||||
// Copyright © 2016 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
45
Apple2Mac/Apple2etvOS/AppDelegate.m
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// Apple2etvOS
|
||||
//
|
||||
// Created by Jerome Vernet on 01/01/2016.
|
||||
// Copyright © 2016 deadc0de.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "tv",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"layers" : [
|
||||
{
|
||||
"filename" : "Front.imagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Middle.imagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Back.imagestacklayer"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "tv",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "tv",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "tv",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||