2015-02-15 17:52:27 +00:00
/ *
2015-02-23 19:19:41 +00:00
* Apple // emulator for *nix
2015-02-15 17:52:27 +00:00
*
* This software package is subject to the GNU General Public License
2015-10-22 05:13:26 +00:00
* version 3 or later ( your choice ) as published by the Free Software
2015-02-15 17:52:27 +00:00
* Foundation .
*
2015-10-22 05:13:26 +00:00
* Copyright 2015 Aaron Culliney
2015-02-15 17:52:27 +00:00
*
* /
2015-03-10 20:38:14 +00:00
package org.deadc0de.apple2ix ;
2015-02-15 17:52:27 +00:00
import android.app.Activity ;
2015-03-11 21:42:57 +00:00
import android.app.AlertDialog ;
import android.content.DialogInterface ;
2015-10-04 20:32:26 +00:00
import android.content.Intent ;
2015-07-31 04:36:22 +00:00
import android.media.AudioManager ;
2015-10-04 20:32:26 +00:00
import android.net.Uri ;
2015-02-15 17:52:27 +00:00
import android.os.Bundle ;
2015-06-10 04:06:32 +00:00
import android.os.StrictMode ;
2015-02-23 19:19:41 +00:00
import android.util.Log ;
2015-03-01 05:48:08 +00:00
import android.view.KeyEvent ;
2015-03-11 06:32:08 +00:00
import android.view.MotionEvent ;
2015-07-25 07:06:20 +00:00
import android.view.View ;
import android.view.ViewGroup ;
import android.widget.FrameLayout ;
2015-10-04 20:32:26 +00:00
import android.widget.Toast ;
2015-02-15 17:52:27 +00:00
2015-10-04 20:32:26 +00:00
import java.io.File ;
2015-07-25 07:06:20 +00:00
import java.util.ArrayList ;
2015-11-01 20:44:31 +00:00
import java.util.Collections ;
2015-10-04 20:32:26 +00:00
import java.util.StringTokenizer ;
2015-09-26 21:52:15 +00:00
import java.util.concurrent.atomic.AtomicBoolean ;
2015-02-23 19:19:41 +00:00
2015-09-05 21:40:44 +00:00
import org.deadc0de.apple2ix.basic.BuildConfig ;
import org.deadc0de.apple2ix.basic.R ;
2015-02-15 17:52:27 +00:00
public class Apple2Activity extends Activity {
2015-02-23 19:19:41 +00:00
private final static String TAG = " Apple2Activity " ;
2015-04-02 02:59:38 +00:00
private final static int MAX_FINGERS = 32 ; // HACK ...
2015-09-13 17:32:17 +00:00
private static volatile boolean DEBUG_STRICT = false ;
2015-02-23 19:19:41 +00:00
2015-02-25 00:03:21 +00:00
private Apple2View mView = null ;
2015-11-04 06:38:29 +00:00
private Runnable mGraphicsInitializedRunnable = null ;
2015-08-06 05:36:07 +00:00
private Apple2SplashScreen mSplashScreen = null ;
private Apple2MainMenu mMainMenu = null ;
2015-11-01 20:44:31 +00:00
private Apple2SettingsMenu mSettingsMenu = null ;
private Apple2DisksMenu mDisksMenu = null ;
2015-07-25 07:06:20 +00:00
private ArrayList < Apple2MenuView > mMenuStack = new ArrayList < Apple2MenuView > ( ) ;
2015-09-13 17:43:53 +00:00
private ArrayList < AlertDialog > mAlertDialogs = new ArrayList < AlertDialog > ( ) ;
2015-03-14 22:42:02 +00:00
2015-09-26 21:52:15 +00:00
private AtomicBoolean mPausing = new AtomicBoolean ( false ) ;
2015-04-02 02:59:38 +00:00
private float [ ] mXCoords = new float [ MAX_FINGERS ] ;
private float [ ] mYCoords = new float [ MAX_FINGERS ] ;
2015-09-27 20:34:58 +00:00
// 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 ;
2015-02-15 17:52:27 +00:00
static {
2015-09-27 20:34:58 +00:00
try {
System . loadLibrary ( " apple2ix " ) ;
} catch ( Throwable barf ) {
sNativeBarfed = true ;
sNativeBarfedThrowable = barf ;
}
2015-02-23 19:19:41 +00:00
}
2015-02-15 17:52:27 +00:00
2015-08-19 05:17:12 +00:00
public final static long NATIVE_TOUCH_HANDLED = ( 1 < < 0 ) ;
public final static long NATIVE_TOUCH_REQUEST_SHOW_MENU = ( 1 < < 1 ) ;
2015-07-31 06:00:00 +00:00
2015-08-19 05:17:12 +00:00
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 ) ;
2015-08-29 17:42:24 +00:00
public final static long NATIVE_TOUCH_JOY_KPAD = ( 1 < < 8 ) ;
2015-07-31 04:36:22 +00:00
2015-08-19 05:17:12 +00:00
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 ;
2015-07-31 06:00:00 +00:00
2015-11-02 03:26:34 +00:00
private native void nativeOnCreate ( String dataDir , int sampleRate , int monoBufferSize , int stereoBufferSize ) ;
2015-03-14 22:42:02 +00:00
private native void nativeOnKeyDown ( int keyCode , int metaState ) ;
2015-07-26 22:07:43 +00:00
2015-03-14 22:42:02 +00:00
private native void nativeOnKeyUp ( int keyCode , int metaState ) ;
2015-07-26 22:07:43 +00:00
2015-11-01 18:14:40 +00:00
public native void nativeEmulationResume ( ) ;
2015-07-26 22:07:43 +00:00
2015-10-31 21:01:47 +00:00
public native void nativeEmulationPause ( ) ;
2015-07-26 22:07:43 +00:00
2015-03-11 21:42:57 +00:00
public native void nativeOnQuit ( ) ;
2015-04-08 02:54:02 +00:00
2015-07-31 04:36:22 +00:00
public native long nativeOnTouch ( int action , int pointerCount , int pointerIndex , float [ ] xCoords , float [ ] yCoords ) ;
2015-04-02 02:59:38 +00:00
2015-03-11 21:42:57 +00:00
public native void nativeReboot ( ) ;
2015-07-26 22:07:43 +00:00
2015-04-08 05:40:22 +00:00
public native void nativeChooseDisk ( String path , boolean driveA , boolean readOnly ) ;
2015-04-08 02:54:02 +00:00
2015-08-22 21:16:56 +00:00
public native void nativeEjectDisk ( boolean driveA ) ;
2015-04-08 02:54:02 +00:00
2015-07-28 05:36:39 +00:00
@Override
public void onCreate ( Bundle savedInstanceState ) {
2015-09-13 17:32:17 +00:00
if ( Apple2Activity . DEBUG_STRICT & & BuildConfig . DEBUG ) {
2015-07-28 05:36:39 +00:00
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 ) ;
2015-06-06 19:23:14 +00:00
2015-02-23 19:19:41 +00:00
Log . e ( TAG , " onCreate() " ) ;
2015-11-01 18:14:40 +00:00
// placeholder view on initial launch
if ( mView = = null ) {
setContentView ( new View ( this ) ) ;
}
2015-09-27 21:28:10 +00:00
Apple2CrashHandler . getInstance ( ) . initializeAndSetCustomExceptionHandler ( this ) ;
2015-09-27 20:34:58 +00:00
if ( sNativeBarfed ) {
Log . e ( TAG , " NATIVE BARFED... " , sNativeBarfedThrowable ) ;
return ;
}
2015-08-22 18:36:12 +00:00
2015-11-02 03:26:34 +00:00
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 ) ;
2015-11-04 06:38:29 +00:00
final boolean firstTime = ! Apple2Preferences . FIRST_TIME_CONFIGURED . booleanValue ( this ) ;
Apple2Preferences . FIRST_TIME_CONFIGURED . saveBoolean ( this , true ) ;
2015-11-01 18:14:40 +00:00
2015-11-04 06:47:35 +00:00
showSplashScreen ( ! firstTime ) ;
Apple2CrashHandler . getInstance ( ) . checkForCrashes ( this ) ;
2015-11-04 06:38:29 +00:00
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 ) {
2015-11-04 06:47:35 +00:00
new Thread ( new Runnable ( ) {
@Override
public void run ( ) {
Apple2DisksMenu . firstTime ( Apple2Activity . this ) ;
mSplashScreen . setDismissable ( true ) ;
Log . d ( TAG , " Finished first time copying... " ) ;
}
} ) . start ( ) ;
2015-08-22 18:36:12 +00:00
}
2015-06-28 19:49:26 +00:00
2015-11-01 20:44:31 +00:00
mSettingsMenu = new Apple2SettingsMenu ( this ) ;
mDisksMenu = new Apple2DisksMenu ( this ) ;
2015-11-01 18:14:40 +00:00
Intent intent = getIntent ( ) ;
String path = null ;
if ( intent ! = null ) {
Uri data = intent . getData ( ) ;
if ( data ! = null ) {
path = data . getPath ( ) ;
2015-03-11 19:54:50 +00:00
}
2015-11-01 18:14:40 +00:00
}
if ( path ! = null & & Apple2DisksMenu . hasDiskExtension ( path ) ) {
handleInsertDiskIntent ( path ) ;
}
2015-02-15 17:52:27 +00:00
}
@Override
protected void onResume ( ) {
super . onResume ( ) ;
2015-09-27 20:34:58 +00:00
if ( sNativeBarfed ) {
Apple2CrashHandler . getInstance ( ) . abandonAllHope ( this , sNativeBarfedThrowable ) ;
return ;
}
2015-04-15 04:51:43 +00:00
Log . d ( TAG , " onResume() " ) ;
2015-11-04 06:47:35 +00:00
showSplashScreen ( /*dismissable:*/ true ) ;
Apple2CrashHandler . getInstance ( ) . checkForCrashes ( this ) ; // NOTE : needs to be called again to clean-up
2015-02-15 17:52:27 +00:00
}
@Override
2015-09-27 20:31:55 +00:00
protected void onPause ( ) {
2015-02-15 17:52:27 +00:00
super . onPause ( ) ;
2015-09-27 20:34:58 +00:00
if ( sNativeBarfed ) {
return ;
}
2015-09-26 21:52:15 +00:00
2015-09-27 20:31:55 +00:00
boolean wasPausing = mPausing . getAndSet ( true ) ;
if ( wasPausing ) {
return ;
}
2015-09-26 21:52:15 +00:00
2015-04-15 04:51:43 +00:00
Log . d ( TAG , " onPause() " ) ;
2015-11-01 18:14:40 +00:00
if ( mView ! = null ) {
mView . onPause ( ) ;
}
2015-03-12 22:12:18 +00:00
2015-04-15 04:51:43 +00:00
// Apparently not good to leave popup/dialog windows showing when backgrounding.
// Dismiss these popups to avoid android.view.WindowLeaked issues
2015-09-16 05:41:33 +00:00
synchronized ( this ) {
dismissAllMenus ( ) ;
2015-10-31 21:01:47 +00:00
nativeEmulationPause ( ) ;
2015-09-16 05:41:33 +00:00
}
2015-09-26 21:52:15 +00:00
mPausing . set ( false ) ;
2015-02-15 17:52:27 +00:00
}
2015-03-01 05:48:08 +00:00
@Override
public boolean onKeyDown ( int keyCode , KeyEvent event ) {
2015-09-27 20:34:58 +00:00
if ( sNativeBarfed ) {
return true ;
}
2015-06-27 19:59:59 +00:00
if ( ( keyCode = = KeyEvent . KEYCODE_VOLUME_DOWN ) | | ( keyCode = = KeyEvent . KEYCODE_VOLUME_MUTE ) | | ( keyCode = = KeyEvent . KEYCODE_VOLUME_UP ) ) {
return false ;
}
2015-03-01 05:48:08 +00:00
nativeOnKeyDown ( keyCode , event . getMetaState ( ) ) ;
return true ;
}
@Override
public boolean onKeyUp ( int keyCode , KeyEvent event ) {
2015-09-27 20:34:58 +00:00
if ( sNativeBarfed ) {
return true ;
}
2015-03-11 21:42:57 +00:00
if ( keyCode = = KeyEvent . KEYCODE_BACK ) {
2015-08-06 05:36:07 +00:00
Apple2MenuView apple2MenuView = peekApple2View ( ) ;
2015-07-25 07:06:20 +00:00
if ( apple2MenuView = = null ) {
2015-08-06 05:36:07 +00:00
showMainMenu ( ) ;
2015-07-25 07:06:20 +00:00
} else {
apple2MenuView . dismiss ( ) ;
2015-03-12 22:12:18 +00:00
}
return true ;
2015-03-12 21:59:09 +00:00
} else if ( keyCode = = KeyEvent . KEYCODE_MENU ) {
2015-08-06 05:36:07 +00:00
showMainMenu ( ) ;
2015-03-12 22:12:18 +00:00
return true ;
2015-03-12 21:59:09 +00:00
} else if ( ( keyCode = = KeyEvent . KEYCODE_VOLUME_DOWN ) | | ( keyCode = = KeyEvent . KEYCODE_VOLUME_MUTE ) | | ( keyCode = = KeyEvent . KEYCODE_VOLUME_UP ) ) {
2015-06-27 19:59:59 +00:00
return false ;
2015-03-12 22:12:18 +00:00
} else {
nativeOnKeyUp ( keyCode , event . getMetaState ( ) ) ;
return true ;
2015-03-11 21:42:57 +00:00
}
2015-03-01 05:48:08 +00:00
}
2015-03-11 06:32:08 +00:00
@Override
public boolean onTouchEvent ( MotionEvent event ) {
2015-03-14 22:42:02 +00:00
do {
2015-07-28 05:36:39 +00:00
2015-09-27 20:34:58 +00:00
if ( sNativeBarfed ) {
break ;
}
2015-08-06 05:36:07 +00:00
if ( mMainMenu = = null ) {
2015-03-14 22:42:02 +00:00
break ;
}
2015-07-28 05:36:39 +00:00
Apple2MenuView apple2MenuView = peekApple2View ( ) ;
2015-08-02 18:28:48 +00:00
if ( ( apple2MenuView ! = null ) & & ( ! apple2MenuView . isCalibrating ( ) ) ) {
2015-04-08 05:40:22 +00:00
break ;
}
2015-03-14 22:42:02 +00:00
2015-04-05 05:36:04 +00:00
//printSamples(event);
2015-03-14 22:42:02 +00:00
int action = event . getActionMasked ( ) ;
2015-04-02 02:59:38 +00:00
int pointerIndex = event . getActionIndex ( ) ;
int pointerCount = event . getPointerCount ( ) ;
2015-07-26 22:07:43 +00:00
for ( int i = 0 ; i < pointerCount /* && i < MAX_FINGERS */ ; i + + ) {
2015-04-02 02:59:38 +00:00
mXCoords [ i ] = event . getX ( i ) ;
mYCoords [ i ] = event . getY ( i ) ;
}
2015-03-14 22:42:02 +00:00
2015-07-31 04:36:22 +00:00
long nativeFlags = nativeOnTouch ( action , pointerCount , pointerIndex , mXCoords , mYCoords ) ;
if ( ( nativeFlags & NATIVE_TOUCH_HANDLED ) = = 0 ) {
2015-03-14 22:42:02 +00:00
break ;
}
2015-07-31 04:36:22 +00:00
if ( ( nativeFlags & NATIVE_TOUCH_REQUEST_SHOW_MENU ) ! = 0 ) {
2015-08-06 05:36:07 +00:00
mMainMenu . show ( ) ;
2015-07-31 04:36:22 +00:00
}
if ( ( nativeFlags & NATIVE_TOUCH_KEY_TAP ) ! = 0 ) {
2015-09-04 05:25:38 +00:00
if ( Apple2Preferences . KEYBOARD_CLICK_ENABLED . booleanValue ( this ) ) {
AudioManager am = ( AudioManager ) getSystemService ( AUDIO_SERVICE ) ;
if ( am ! = null ) {
am . playSoundEffect ( AudioManager . FX_KEY_CLICK ) ;
}
2015-07-31 04:36:22 +00:00
}
2015-08-19 05:17:12 +00:00
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 ) ;
}
2015-07-31 04:36:22 +00:00
}
2015-07-31 06:00:00 +00:00
if ( ( nativeFlags & NATIVE_TOUCH_MENU ) = = 0 ) {
break ;
}
// handle menu-specific actions
if ( ( nativeFlags & NATIVE_TOUCH_INPUT_DEVICE_CHANGED ) ! = 0 ) {
2015-08-29 17:42:24 +00:00
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 ) ;
}
2015-08-22 06:33:08 +00:00
Apple2Preferences . CURRENT_TOUCH_DEVICE . saveTouchDevice ( this , nextVariant ) ;
2015-08-29 17:42:24 +00:00
} else if ( ( nativeFlags & NATIVE_TOUCH_CPU_SPEED_DEC ) ! = 0 ) {
2015-07-31 06:00:00 +00:00
int percentSpeed = Apple2Preferences . nativeGetCPUSpeed ( ) ;
2015-10-04 20:03:21 +00:00
if ( percentSpeed > 400 ) { // HACK: max value from native side
percentSpeed = 375 ;
} else if ( percentSpeed > 100 ) {
2015-07-31 06:00:00 +00:00
percentSpeed - = 25 ;
} else {
percentSpeed - = 5 ;
}
Apple2Preferences . CPU_SPEED_PERCENT . saveInt ( this , percentSpeed ) ;
2015-08-29 17:42:24 +00:00
} else if ( ( nativeFlags & NATIVE_TOUCH_CPU_SPEED_INC ) ! = 0 ) {
2015-07-31 06:00:00 +00:00
int percentSpeed = Apple2Preferences . nativeGetCPUSpeed ( ) ;
if ( percentSpeed > = 100 ) {
percentSpeed + = 25 ;
} else {
percentSpeed + = 5 ;
}
Apple2Preferences . CPU_SPEED_PERCENT . saveInt ( this , percentSpeed ) ;
}
2015-03-14 22:42:02 +00:00
} while ( false ) ;
return super . onTouchEvent ( event ) ;
}
2015-08-06 05:36:07 +00:00
public void showMainMenu ( ) {
if ( mMainMenu ! = null ) {
2015-11-01 20:44:31 +00:00
if ( ! ( mSettingsMenu . isShowing ( ) | | mDisksMenu . isShowing ( ) ) ) {
2015-08-06 05:36:07 +00:00
mMainMenu . show ( ) ;
}
}
}
public Apple2MainMenu getMainMenu ( ) {
return mMainMenu ;
}
2015-11-01 20:44:31 +00:00
public synchronized Apple2DisksMenu getDisksMenu ( ) {
return mDisksMenu ;
}
public synchronized Apple2SettingsMenu getSettingsMenu ( ) {
return mSettingsMenu ;
}
2015-10-04 20:32:26 +00:00
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 ) ;
2015-11-01 20:44:31 +00:00
while ( mDisksMenu . popPathStack ( ) ! = null ) {
2015-10-04 20:32:26 +00:00
/* ... */
}
2015-10-29 06:49:40 +00:00
File storageDir = Apple2DisksMenu . getExternalStorageDirectory ( ) ;
if ( storageDir ! = null ) {
String storagePath = storageDir . getAbsolutePath ( ) ;
if ( diskPath . contains ( storagePath ) ) {
diskPath = diskPath . replace ( storagePath + File . separator , " " ) ;
2015-11-01 20:44:31 +00:00
mDisksMenu . pushPathStack ( storagePath ) ;
2015-10-29 06:49:40 +00:00
}
2015-10-04 20:32:26 +00:00
}
StringTokenizer tokenizer = new StringTokenizer ( diskPath , File . separator ) ;
while ( tokenizer . hasMoreTokens ( ) ) {
String token = tokenizer . nextToken ( ) ;
if ( token . equals ( " " ) ) {
continue ;
}
if ( Apple2DisksMenu . hasDiskExtension ( token ) ) {
continue ;
}
2015-11-01 20:44:31 +00:00
mDisksMenu . pushPathStack ( token ) ;
2015-10-04 20:32:26 +00:00
}
Toast . makeText ( Apple2Activity . this , Apple2Activity . this . getString ( R . string . disk_insert_toast ) , Toast . LENGTH_SHORT ) . show ( ) ;
}
}
} ) ;
}
2015-11-04 06:47:35 +00:00
public Apple2SplashScreen getSplashScreen ( ) {
return mSplashScreen ;
}
private void showSplashScreen ( boolean dismissable ) {
2015-10-26 03:57:48 +00:00
if ( mSplashScreen ! = null ) {
return ;
}
2015-11-04 06:47:35 +00:00
mSplashScreen = new Apple2SplashScreen ( this , dismissable ) ;
2015-11-01 18:14:40 +00:00
mSplashScreen . show ( ) ;
}
private void setupGLView ( ) {
boolean glViewFirstTime = false ;
if ( mView = = null ) {
glViewFirstTime = true ;
2015-11-04 06:38:29 +00:00
mView = new Apple2View ( this , mGraphicsInitializedRunnable ) ;
mGraphicsInitializedRunnable = null ;
2015-11-01 18:14:40 +00:00
mMainMenu = new Apple2MainMenu ( this , mView ) ;
}
2015-11-01 22:17:10 +00:00
if ( glViewFirstTime ) {
// HACK NOTE : do not blanket setContentView() ... it appears to wedge Gingerbread
setContentView ( mView ) ;
} else {
2015-11-01 18:14:40 +00:00
mView . onResume ( ) ;
}
2015-03-11 06:32:08 +00:00
}
2015-09-13 17:43:53 +00:00
public void registerAndShowDialog ( AlertDialog dialog ) {
dialog . show ( ) ;
mAlertDialogs . add ( dialog ) ;
}
2015-07-25 07:06:20 +00:00
public synchronized void pushApple2View ( Apple2MenuView apple2MenuView ) {
mMenuStack . add ( apple2MenuView ) ;
View menuView = apple2MenuView . getView ( ) ;
2015-10-31 21:01:47 +00:00
nativeEmulationPause ( ) ;
2015-11-01 18:14:40 +00:00
addContentView ( menuView , new FrameLayout . LayoutParams ( FrameLayout . LayoutParams . MATCH_PARENT , FrameLayout . LayoutParams . MATCH_PARENT ) ) ;
2015-07-25 07:06:20 +00:00
}
public synchronized Apple2MenuView popApple2View ( ) {
2015-07-26 22:07:43 +00:00
int lastIndex = mMenuStack . size ( ) - 1 ;
2015-07-25 07:06:20 +00:00
if ( lastIndex < 0 ) {
return null ;
}
Apple2MenuView apple2MenuView = mMenuStack . remove ( lastIndex ) ;
_disposeApple2View ( apple2MenuView ) ;
return apple2MenuView ;
}
2015-07-28 05:36:39 +00:00
public synchronized Apple2MenuView peekApple2View ( ) {
int lastIndex = mMenuStack . size ( ) - 1 ;
if ( lastIndex < 0 ) {
return null ;
}
return mMenuStack . get ( lastIndex ) ;
}
2015-08-08 06:00:08 +00:00
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 ;
}
}
2015-08-06 05:36:07 +00:00
public void dismissAllMenus ( ) {
if ( mMainMenu ! = null ) {
mMainMenu . dismiss ( ) ;
2015-08-02 18:28:48 +00:00
}
2015-09-13 17:43:53 +00:00
for ( AlertDialog dialog : mAlertDialogs ) {
dialog . dismiss ( ) ;
2015-08-06 05:36:07 +00:00
}
2015-09-13 17:43:53 +00:00
mAlertDialogs . clear ( ) ;
2015-08-06 05:36:07 +00:00
// Get rid of the menu hierarchy
2015-11-01 20:44:31 +00:00
ArrayList < Apple2MenuView > menuHierarchy = new ArrayList < Apple2MenuView > ( mMenuStack ) ;
Collections . reverse ( menuHierarchy ) ;
for ( Apple2MenuView view : menuHierarchy ) {
view . dismissAll ( ) ;
}
2015-08-02 18:28:48 +00:00
}
2015-07-25 07:06:20 +00:00
public synchronized Apple2MenuView popApple2View ( Apple2MenuView apple2MenuView ) {
boolean wasRemoved = mMenuStack . remove ( apple2MenuView ) ;
_disposeApple2View ( apple2MenuView ) ;
return wasRemoved ? apple2MenuView : null ;
}
private void _disposeApple2View ( Apple2MenuView apple2MenuView ) {
2015-11-01 18:14:40 +00:00
boolean dismissedSplashScreen = false ;
2015-07-25 07:06:20 +00:00
// Actually remove View from view hierarchy
{
View menuView = apple2MenuView . getView ( ) ;
2015-10-26 04:48:41 +00:00
ViewGroup viewGroup = ( ViewGroup ) menuView . getParent ( ) ;
if ( viewGroup ! = null ) {
viewGroup . removeView ( menuView ) ;
2015-07-25 07:06:20 +00:00
}
2015-11-01 22:19:40 +00:00
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)
2015-10-26 03:57:48 +00:00
mSplashScreen = null ;
2015-11-01 18:14:40 +00:00
dismissedSplashScreen = true ;
2015-10-26 03:57:48 +00:00
}
2015-07-25 07:06:20 +00:00
}
// if no more views on menu stack, resume emulation
if ( mMenuStack . size ( ) = = 0 ) {
2015-11-01 21:43:09 +00:00
dismissAllMenus ( ) ; // NOTE : at this point, this should not be re-entrant into mMenuStack, it should just dismiss lingering popups
2015-11-01 18:14:40 +00:00
if ( ! mPausing . get ( ) ) {
2015-11-01 20:44:31 +00:00
if ( dismissedSplashScreen ) {
setupGLView ( ) ;
} else {
nativeEmulationResume ( ) ;
}
2015-11-01 18:14:40 +00:00
}
2015-09-26 21:52:15 +00:00
}
}
2015-11-01 20:44:31 +00:00
public void maybeResumeCPU ( ) {
2015-09-26 21:52:15 +00:00
if ( mMenuStack . size ( ) = = 0 & & ! mPausing . get ( ) ) {
2015-10-31 21:01:47 +00:00
nativeEmulationResume ( ) ;
2015-07-25 07:06:20 +00:00
}
}
2015-03-11 21:42:57 +00:00
public void maybeQuitApp ( ) {
2015-10-31 21:01:47 +00:00
nativeEmulationPause ( ) ;
2015-09-13 17:43:53 +00:00
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 ) {
// ...
2015-09-12 22:33:22 +00:00
}
2015-09-13 17:43:53 +00:00
System . exit ( 0 ) ;
}
} . run ( ) ;
}
} ) . setNegativeButton ( R . string . no , null ) . create ( ) ;
registerAndShowDialog ( quitDialog ) ;
2015-03-11 21:42:57 +00:00
}
2015-03-14 22:42:02 +00:00
2015-04-08 02:54:02 +00:00
public void maybeReboot ( ) {
2015-10-31 21:01:47 +00:00
nativeEmulationPause ( ) ;
2015-09-13 17:43:53 +00:00
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 ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
nativeReboot ( ) ;
Apple2Activity . this . mMainMenu . dismiss ( ) ;
}
} ) . setNegativeButton ( R . string . no , null ) . create ( ) ;
registerAndShowDialog ( rebootDialog ) ;
2015-04-08 02:54:02 +00:00
}
2015-02-15 17:52:27 +00:00
}