mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-09-10 08:54:33 +00:00
Merge branch 'develop' ... latest Linux, Android, and Mac variant
This commit is contained in:
commit
b445c2dcf1
26
.gitignore
vendored
26
.gitignore
vendored
@ -43,16 +43,19 @@ ylwrap
|
||||
apple2ix*.tar.gz
|
||||
test-driver
|
||||
|
||||
# GDB
|
||||
.gdb_history
|
||||
|
||||
# generated sources
|
||||
src/rom.c
|
||||
src/x86/glue.S
|
||||
src/meta/debug.c
|
||||
src/arm/glue.S
|
||||
|
||||
# sub{tree,module}
|
||||
src/rom
|
||||
|
||||
# generated binaries
|
||||
apple2ix
|
||||
/apple2ix
|
||||
genfont
|
||||
genrom
|
||||
|
||||
@ -64,3 +67,22 @@ man6
|
||||
xcuserdata
|
||||
.DS_Store
|
||||
xcshareddata
|
||||
|
||||
# Android CLI builds
|
||||
Android/bin
|
||||
Android/gen
|
||||
Android/libs
|
||||
# Android.mk is tEh dynamicz!
|
||||
Android/jni/Android.mk
|
||||
*.apk
|
||||
|
||||
# Android Studio
|
||||
.gradle
|
||||
Android/local.properties
|
||||
Android/.idea/workspace.xml
|
||||
Android/.idea/libraries
|
||||
Android/.idea/dictionaries
|
||||
Android/build
|
||||
Android/jni/obj
|
||||
Android/obj
|
||||
|
||||
|
9
Android/.classpath
Normal file
9
Android/.classpath
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
1
Android/.idea/.name
Normal file
1
Android/.idea/.name
Normal file
@ -0,0 +1 @@
|
||||
Android
|
22
Android/.idea/compiler.xml
Normal file
22
Android/.idea/compiler.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
<entry name="!?*.aj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
9
Android/.idea/copyright/deadc0de_org.xml
Normal file
9
Android/.idea/copyright/deadc0de_org.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright (c) deadc0de.org" />
|
||||
<option name="keyword" value="Copyright" />
|
||||
<option name="allowReplaceKeyword" value="" />
|
||||
<option name="myName" value="deadc0de.org" />
|
||||
<option name="myLocal" value="true" />
|
||||
</copyright>
|
||||
</component>
|
3
Android/.idea/copyright/profiles_settings.xml
Normal file
3
Android/.idea/copyright/profiles_settings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
19
Android/.idea/gradle.xml
Normal file
19
Android/.idea/gradle.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="LOCAL" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.4" />
|
||||
<option name="gradleJvm" value="1.7" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
46
Android/.idea/misc.xml
Normal file
46
Android/.idea/misc.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<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">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
9
Android/.idea/modules.xml
Normal file
9
Android/.idea/modules.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Android.iml" filepath="$PROJECT_DIR$/Android.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
12
Android/.idea/runConfigurations.xml
Normal file
12
Android/.idea/runConfigurations.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
6
Android/.idea/vcs.xml
Normal file
6
Android/.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="" />
|
||||
</component>
|
||||
</project>
|
19
Android/Android.iml
Normal file
19
Android/Android.iml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id="Android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="java-gradle" name="Java-Gradle">
|
||||
<configuration>
|
||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||
<option name="BUILDABLE" value="false" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
1
Android/AndroidManifest.xml
Symbolic link
1
Android/AndroidManifest.xml
Symbolic link
@ -0,0 +1 @@
|
||||
app/build/intermediates/manifests/full/debug/AndroidManifest.xml
|
1
Android/app/.gitignore
vendored
Normal file
1
Android/app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
97
Android/app/app.iml
Normal file
97
Android/app/app.iml
Normal file
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="Android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugAndroidTestSources</task>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.1.0/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.1.0/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-23.1.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="appcompat-v7-23.1.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-23.1.0" level="project" />
|
||||
</component>
|
||||
</module>
|
41
Android/app/build.gradle
Normal file
41
Android/app/build.gradle
Normal file
@ -0,0 +1,41 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "21.1.2"
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file("release2.keystore")
|
||||
storePassword System.getenv("GOOGSTOREPWD")
|
||||
keyPassword System.getenv("GOOGKEYPWD")
|
||||
keyAlias "release"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
debug {
|
||||
debuggable true
|
||||
jniDebuggable true
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.deadc0de.apple2ix.basic"
|
||||
minSdkVersion 10
|
||||
targetSdkVersion 23
|
||||
versionCode 7
|
||||
versionName "1.0.4"
|
||||
ndk {
|
||||
moduleName "apple2ix"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:23.1.0'
|
||||
}
|
17
Android/app/proguard-rules.pro
vendored
Normal file
17
Android/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /home/asc/Android/Sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -0,0 +1,13 @@
|
||||
package org.deadc0de.apple2ix;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
7
Android/app/src/debug/AndroidManifest.xml
Normal file
7
Android/app/src/debug/AndroidManifest.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.deadc0de.apple2ix.basic" >
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
</manifest>
|
54
Android/app/src/main/AndroidManifest.xml
Normal file
54
Android/app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.deadc0de.apple2ix.basic" >
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<supports-screens
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:resizeable="true"
|
||||
android:smallScreens="false" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name" >
|
||||
|
||||
<activity
|
||||
android:name="org.deadc0de.apple2ix.Apple2Activity"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:windowSoftInputMode="adjustResize" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/x-gzip" android:pathPattern="/.*\\.nib\\.gz" />
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/x-gzip" android:pathPattern="/.*\\.dsk\\.gz" />
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/x-gzip" android:pathPattern="/.*\\.do\\.gz" />
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/x-gzip" android:pathPattern="/.*\\.po\\.gz" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="file" /> <!-- catch-all since I can't get the following to work because ... Android -->
|
||||
<!--
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/octet-stream" android:pathPattern="/.*\\.nib" />
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/octet-stream" android:pathPattern="/.*\\.dsk" />
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/octet-stream" android:pathPattern="/.*\\.do" />
|
||||
<data android:scheme="file" android:host="*" android:mimeType="application/octet-stream" android:pathPattern="/.*\\.po" />
|
||||
-->
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
1
Android/app/src/main/assets
Symbolic link
1
Android/app/src/main/assets
Symbolic link
@ -0,0 +1 @@
|
||||
../../../assets
|
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Apple // emulator for *nix
|
||||
*
|
||||
* This software package is subject to the GNU General Public License
|
||||
* version 3 or later (your choice) as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Copyright 2015 Aaron Culliney
|
||||
*
|
||||
*/
|
||||
|
||||
package org.deadc0de.apple2ix;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.deadc0de.apple2ix.basic.R;
|
||||
|
||||
public abstract class Apple2AbstractMenu implements Apple2MenuView {
|
||||
|
||||
private final static String TAG = "Apple2AbstractMenu";
|
||||
|
||||
protected Apple2Activity mActivity = null;
|
||||
private View mSettingsView = null;
|
||||
|
||||
public Apple2AbstractMenu(Apple2Activity activity) {
|
||||
mActivity = activity;
|
||||
setup();
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (isShowing()) {
|
||||
return;
|
||||
}
|
||||
mActivity.pushApple2View(this);
|
||||
}
|
||||
|
||||
public void dismiss() {
|
||||
mActivity.popApple2View(this);
|
||||
}
|
||||
|
||||
public void dismissAll() {
|
||||
this.dismiss();
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mSettingsView.getParent() != null;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
return mSettingsView;
|
||||
}
|
||||
|
||||
public boolean isCalibrating() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onKeyTapCalibrationEvent(char ascii, int scancode) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// required overrides ...
|
||||
|
||||
public interface IMenuEnum {
|
||||
public String getTitle(final Apple2Activity activity);
|
||||
|
||||
public String getSummary(final Apple2Activity activity);
|
||||
|
||||
public View getView(final Apple2Activity activity, View convertView);
|
||||
|
||||
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked);
|
||||
}
|
||||
|
||||
public abstract IMenuEnum[] allValues();
|
||||
|
||||
public abstract String[] allTitles();
|
||||
|
||||
public abstract boolean areAllItemsEnabled();
|
||||
|
||||
public abstract boolean isEnabled(int position);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// boilerplate menu view code
|
||||
|
||||
protected static View _basicView(Apple2Activity activity, IMenuEnum setting, View convertView) {
|
||||
TextView tv = (TextView) convertView.findViewById(R.id.a2preference_title);
|
||||
if (tv == null) {
|
||||
// attemping to recycle different layout ...
|
||||
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = inflater.inflate(R.layout.a2preference, null, false);
|
||||
tv = (TextView) convertView.findViewById(R.id.a2preference_title);
|
||||
}
|
||||
tv.setText(setting.getTitle(activity));
|
||||
|
||||
tv = (TextView) convertView.findViewById(R.id.a2preference_summary);
|
||||
tv.setText(setting.getSummary(activity));
|
||||
|
||||
LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.a2preference_widget_frame);
|
||||
if (layout.getChildCount() > 0) {
|
||||
// layout cells appear to be reused when scrolling into view ... make sure we start with clear hierarchy
|
||||
layout.removeAllViews();
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
public interface IPreferenceLoadSave {
|
||||
public int intValue();
|
||||
|
||||
public void saveInt(int value);
|
||||
}
|
||||
|
||||
public interface IPreferenceSlider extends IPreferenceLoadSave {
|
||||
public void showValue(int value, final TextView seekBarValue);
|
||||
}
|
||||
|
||||
protected static View _sliderView(final Apple2Activity activity, final IMenuEnum setting, final int numChoices, final IPreferenceSlider iLoadSave) {
|
||||
|
||||
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View view = inflater.inflate(R.layout.a2preference_slider, null, false);
|
||||
|
||||
TextView tv = (TextView) view.findViewById(R.id.a2preference_slider_summary);
|
||||
tv.setText(setting.getSummary(activity));
|
||||
|
||||
final TextView seekBarValue = (TextView) view.findViewById(R.id.a2preference_slider_seekBarValue);
|
||||
|
||||
SeekBar sb = (SeekBar) view.findViewById(R.id.a2preference_slider_seekBar);
|
||||
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (!fromUser) {
|
||||
return;
|
||||
}
|
||||
iLoadSave.showValue(progress, seekBarValue);
|
||||
iLoadSave.saveInt(progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
});
|
||||
|
||||
sb.setMax(0); // http://stackoverflow.com/questions/10278467/seekbar-not-setting-actual-progress-setprogress-not-working-on-early-android
|
||||
sb.setMax(numChoices);
|
||||
int progress = iLoadSave.intValue();
|
||||
sb.setProgress(progress);
|
||||
iLoadSave.showValue(progress, seekBarValue);
|
||||
return view;
|
||||
}
|
||||
|
||||
protected static void _alertDialogHandleSelection(final Apple2Activity activity, final int titleId, final String[] choices, final IPreferenceLoadSave iLoadSave) {
|
||||
_alertDialogHandleSelection(activity, activity.getResources().getString(titleId), choices, iLoadSave);
|
||||
}
|
||||
|
||||
protected static void _alertDialogHandleSelection(final Apple2Activity activity, final String titleId, final String[] choices, final IPreferenceLoadSave iLoadSave) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(titleId);
|
||||
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
final int checkedPosition = iLoadSave.intValue();
|
||||
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, android.R.layout.select_dialog_singlechoice, choices) {
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view = super.getView(position, convertView, parent);
|
||||
CheckedTextView ctv = (CheckedTextView) view.findViewById(android.R.id.text1);
|
||||
ctv.setChecked(position == checkedPosition);
|
||||
return view;
|
||||
}
|
||||
};
|
||||
|
||||
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int value) {
|
||||
iLoadSave.saveInt(value);
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = builder.create();
|
||||
activity.registerAndShowDialog(dialog);
|
||||
}
|
||||
|
||||
protected static ImageView _addPopupIcon(Apple2Activity activity, IMenuEnum setting, View convertView) {
|
||||
ImageView imageView = new ImageView(activity);
|
||||
Drawable drawable = activity.getResources().getDrawable(android.R.drawable.ic_menu_edit);
|
||||
imageView.setImageDrawable(drawable);
|
||||
LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.a2preference_widget_frame);
|
||||
layout.addView(imageView);
|
||||
return imageView;
|
||||
}
|
||||
|
||||
protected static CheckBox _addCheckbox(Apple2Activity activity, IMenuEnum setting, View convertView, boolean isChecked) {
|
||||
CheckBox checkBox = new CheckBox(activity);
|
||||
checkBox.setChecked(isChecked);
|
||||
LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.a2preference_widget_frame);
|
||||
layout.addView(checkBox);
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
|
||||
LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mSettingsView = inflater.inflate(R.layout.activity_settings, null, false);
|
||||
|
||||
final Button cancelButton = (Button) mSettingsView.findViewById(R.id.cancelButton);
|
||||
cancelButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mActivity.dismissAllMenus();
|
||||
}
|
||||
});
|
||||
|
||||
ListView settingsList = (ListView) mSettingsView.findViewById(R.id.listView_settings);
|
||||
settingsList.setEnabled(true);
|
||||
|
||||
ArrayAdapter<?> adapter = new ArrayAdapter<String>(mActivity, R.layout.a2preference, R.id.a2preference_title, allTitles()) {
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return Apple2AbstractMenu.this.areAllItemsEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return Apple2AbstractMenu.this.isEnabled(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
//View view = super.getView(position, convertView, parent);
|
||||
// ^^^ WHOA ... this is catching an NPE deep in AOSP code on the second time loading ... WTF?
|
||||
// Methinks it is related to the hack of loading a completely different R.layout.something for certain views...
|
||||
View view = convertView != null ? convertView : super.getView(position, null, parent);
|
||||
IMenuEnum setting = allValues()[position];
|
||||
return setting.getView(mActivity, view);
|
||||
}
|
||||
};
|
||||
|
||||
settingsList.setAdapter(adapter);
|
||||
settingsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
IMenuEnum setting = allValues()[position];
|
||||
LinearLayout layout = (LinearLayout) view.findViewById(R.id.a2preference_widget_frame);
|
||||
if (layout == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
View childView = layout.getChildAt(0);
|
||||
boolean selected = false;
|
||||
if (childView != null && childView instanceof CheckBox) {
|
||||
CheckBox checkBox = (CheckBox) childView;
|
||||
checkBox.setChecked(!checkBox.isChecked());
|
||||
selected = checkBox.isChecked();
|
||||
}
|
||||
setting.handleSelection(mActivity, Apple2AbstractMenu.this, selected);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,608 @@
|
||||
/*
|
||||
* Apple // emulator for *nix
|
||||
*
|
||||
* This software package is subject to the GNU General Public License
|
||||
* version 3 or later (your choice) as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Copyright 2015 Aaron Culliney
|
||||
*
|
||||
*/
|
||||
|
||||
package org.deadc0de.apple2ix;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
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.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;
|
||||
|
||||
import org.deadc0de.apple2ix.basic.BuildConfig;
|
||||
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 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;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("apple2ix");
|
||||
} catch (Throwable barf) {
|
||||
sNativeBarfed = true;
|
||||
sNativeBarfedThrowable = barf;
|
||||
}
|
||||
}
|
||||
|
||||
public final static long NATIVE_TOUCH_HANDLED = (1 << 0);
|
||||
public final static long NATIVE_TOUCH_REQUEST_SHOW_MENU = (1 << 1);
|
||||
|
||||
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 native void nativeOnCreate(String dataDir, int sampleRate, int monoBufferSize, int stereoBufferSize);
|
||||
|
||||
private native void nativeOnKeyDown(int keyCode, int metaState);
|
||||
|
||||
private native void nativeOnKeyUp(int keyCode, int metaState);
|
||||
|
||||
public native void nativeEmulationResume();
|
||||
|
||||
public native void nativeEmulationPause();
|
||||
|
||||
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 nativeChooseDisk(String path, boolean driveA, boolean readOnly);
|
||||
|
||||
public native void nativeEjectDisk(boolean driveA);
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if (Apple2Activity.DEBUG_STRICT && BuildConfig.DEBUG) {
|
||||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectDiskReads()
|
||||
.detectDiskWrites()
|
||||
.detectAll()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
|
||||
.detectLeakedSqlLiteObjects()
|
||||
/*.detectLeakedClosableObjects()*/
|
||||
.penaltyLog()
|
||||
.penaltyDeath()
|
||||
.build());
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
int sampleRate = DevicePropertyCalculator.getRecommendedSampleRate(this);
|
||||
int monoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(this, /*isStereo:*/false);
|
||||
int stereoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(this, /*isStereo:*/true);
|
||||
Log.d(TAG, "Device sampleRate:" + sampleRate + " mono bufferSize:" + monoBufferSize + " stereo bufferSize:" + stereoBufferSize);
|
||||
|
||||
String dataDir = Apple2DisksMenu.getDataDir(this);
|
||||
nativeOnCreate(dataDir, sampleRate, monoBufferSize, stereoBufferSize);
|
||||
|
||||
final boolean firstTime = !Apple2Preferences.FIRST_TIME_CONFIGURED.booleanValue(this);
|
||||
Apple2Preferences.FIRST_TIME_CONFIGURED.saveBoolean(this, true);
|
||||
|
||||
showSplashScreen(!firstTime);
|
||||
Apple2CrashHandler.getInstance().checkForCrashes(this);
|
||||
|
||||
mGraphicsInitializedRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (firstTime) {
|
||||
Apple2Preferences.KeypadPreset.IJKM_SPACE.apply(Apple2Activity.this);
|
||||
}
|
||||
Apple2Preferences.loadPreferences(Apple2Activity.this);
|
||||
}
|
||||
};
|
||||
|
||||
// first-time initializations
|
||||
if (firstTime) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Apple2DisksMenu.firstTime(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
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (sNativeBarfed) {
|
||||
Apple2CrashHandler.getInstance().abandonAllHope(this, sNativeBarfedThrowable);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "onResume()");
|
||||
showSplashScreen(/*dismissable:*/true);
|
||||
Apple2CrashHandler.getInstance().checkForCrashes(this); // NOTE : needs to be called again to clean-up
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (sNativeBarfed) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean wasPausing = mPausing.getAndSet(true);
|
||||
if (wasPausing) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "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();
|
||||
nativeEmulationPause();
|
||||
}
|
||||
|
||||
mPausing.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (sNativeBarfed) {
|
||||
return true;
|
||||
}
|
||||
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) || (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) || (keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
|
||||
return false;
|
||||
}
|
||||
nativeOnKeyDown(keyCode, event.getMetaState());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (sNativeBarfed) {
|
||||
return true;
|
||||
}
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
Apple2MenuView apple2MenuView = peekApple2View();
|
||||
if (apple2MenuView == null) {
|
||||
showMainMenu();
|
||||
} else {
|
||||
apple2MenuView.dismiss();
|
||||
}
|
||||
return true;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
public void showMainMenu() {
|
||||
if (mMainMenu != null) {
|
||||
if (!(mSettingsMenu.isShowing() || mDisksMenu.isShowing())) {
|
||||
mMainMenu.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Apple2MainMenu getMainMenu() {
|
||||
return mMainMenu;
|
||||
}
|
||||
|
||||
public synchronized Apple2DisksMenu getDisksMenu() {
|
||||
return mDisksMenu;
|
||||
}
|
||||
|
||||
public synchronized Apple2SettingsMenu getSettingsMenu() {
|
||||
return mSettingsMenu;
|
||||
}
|
||||
|
||||
private void handleInsertDiskIntent(final String path) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (Apple2Activity.this) {
|
||||
if (mMainMenu == null) {
|
||||
return;
|
||||
}
|
||||
String diskPath = path;
|
||||
File diskFile = new File(diskPath);
|
||||
if (!diskFile.canRead()) {
|
||||
Toast.makeText(Apple2Activity.this, Apple2Activity.this.getString(R.string.disk_insert_could_not_read), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Apple2Preferences.CURRENT_DISK_A_RO.saveBoolean(Apple2Activity.this, true);
|
||||
final int len = diskPath.length();
|
||||
final String suffix = diskPath.substring(len - 3, len);
|
||||
if (suffix.equalsIgnoreCase(".gz")) { // HACK FIXME TODO : small amount of code duplication of Apple2DisksMenu
|
||||
diskPath = diskPath.substring(0, len - 3);
|
||||
}
|
||||
Apple2Preferences.CURRENT_DISK_A.saveString(Apple2Activity.this, diskPath);
|
||||
|
||||
while (mDisksMenu.popPathStack() != null) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
File storageDir = Apple2DisksMenu.getExternalStorageDirectory();
|
||||
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()) {
|
||||
String token = tokenizer.nextToken();
|
||||
if (token.equals("")) {
|
||||
continue;
|
||||
}
|
||||
if (Apple2DisksMenu.hasDiskExtension(token)) {
|
||||
continue;
|
||||
}
|
||||
mDisksMenu.pushPathStack(token);
|
||||
}
|
||||
|
||||
Toast.makeText(Apple2Activity.this, Apple2Activity.this.getString(R.string.disk_insert_toast), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
dialog.show();
|
||||
mAlertDialogs.add(dialog);
|
||||
}
|
||||
|
||||
public synchronized void pushApple2View(Apple2MenuView apple2MenuView) {
|
||||
mMenuStack.add(apple2MenuView);
|
||||
View menuView = apple2MenuView.getView();
|
||||
nativeEmulationPause();
|
||||
addContentView(menuView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
}
|
||||
|
||||
public synchronized Apple2MenuView popApple2View() {
|
||||
int lastIndex = mMenuStack.size() - 1;
|
||||
if (lastIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Apple2MenuView apple2MenuView = mMenuStack.remove(lastIndex);
|
||||
_disposeApple2View(apple2MenuView);
|
||||
return apple2MenuView;
|
||||
}
|
||||
|
||||
public synchronized Apple2MenuView peekApple2View() {
|
||||
int lastIndex = mMenuStack.size() - 1;
|
||||
if (lastIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mMenuStack.get(lastIndex);
|
||||
}
|
||||
|
||||
public synchronized Apple2MenuView peekApple2View(int index) {
|
||||
int lastIndex = mMenuStack.size() - 1;
|
||||
if (lastIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return mMenuStack.get(index);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void dismissAllMenus() {
|
||||
if (mMainMenu != null) {
|
||||
mMainMenu.dismiss();
|
||||
}
|
||||
|
||||
for (AlertDialog dialog : mAlertDialogs) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
mAlertDialogs.clear();
|
||||
|
||||
// Get rid of the menu hierarchy
|
||||
ArrayList<Apple2MenuView> menuHierarchy = new ArrayList<Apple2MenuView>(mMenuStack);
|
||||
Collections.reverse(menuHierarchy);
|
||||
for (Apple2MenuView view : menuHierarchy) {
|
||||
view.dismissAll();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Apple2MenuView popApple2View(Apple2MenuView apple2MenuView) {
|
||||
boolean wasRemoved = mMenuStack.remove(apple2MenuView);
|
||||
_disposeApple2View(apple2MenuView);
|
||||
return wasRemoved ? apple2MenuView : null;
|
||||
}
|
||||
|
||||
private void _disposeApple2View(Apple2MenuView apple2MenuView) {
|
||||
|
||||
boolean dismissedSplashScreen = false;
|
||||
|
||||
// Actually remove View from view hierarchy
|
||||
{
|
||||
View menuView = apple2MenuView.getView();
|
||||
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(); // 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void maybeResumeCPU() {
|
||||
if (mMenuStack.size() == 0 && !mPausing.get()) {
|
||||
nativeEmulationResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void maybeQuitApp() {
|
||||
nativeEmulationPause();
|
||||
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();
|
||||