199 Commits

Author SHA1 Message Date
Aaron Culliney
e7eb467f4f Get Linux desktop build unstuck 2016-01-09 14:01:00 -08:00
Aaron Culliney
0c77e4a659 Fix testdisk assertions in debug builds 2016-01-09 14:00:33 -08:00
Aaron Culliney
e1adc07db0 Update README.md 2016-01-09 13:43:08 -08:00
Aaron Culliney
144086c667 Don't LOG() in Breakpad callback 2016-01-09 12:44:11 -08:00
Aaron Culliney
b2824e9145 Improve tap responsiveness in GL touch joystick 2016-01-08 00:28:57 -08:00
Aaron Culliney
a64941694f Expose timespec_add 2016-01-07 22:42:04 -08:00
Aaron Culliney
9bbfca3193 Take into account device screen small axis when calculating button switch threshold 2016-01-07 22:41:50 -08:00
Aaron Culliney
18c02d3673 Fix broken assert 2016-01-07 20:57:22 -08:00
Aaron Culliney
659a338d26 Avoid crashing if azimuth model is unavailable (shader failed to compile) 2016-01-05 23:19:12 -08:00
Aaron Culliney
4436b9b7ca Fix semi-opaque glyph shading with scales > 2
- Also add defensive coding in debug builds
2016-01-05 23:04:27 -08:00
Aaron Culliney
3089b98a30 For now, enable logging in release builds on Android 2016-01-05 21:39:04 -08:00
Aaron Culliney
94882c48bc Send app version in crash report 2016-01-05 20:58:57 -08:00
Aaron Culliney
f7cb3da434 Mark certain core emulation modules as problematic on iOS/Mac, and something we should fix 2016-01-05 00:11:58 -08:00
Aaron Culliney
281fccb73b Update misc project settings =) 2016-01-05 00:11:38 -08:00
Aaron Culliney
086f7d0da2 Do not free the model positions prematurely ... since we occasionally change them 2016-01-05 00:11:16 -08:00
Aaron Culliney
c5256dde85 Add new shader to iOS and Mac bundle 2016-01-05 00:10:11 -08:00
jvernet
1b2c6fff83 Project update 2016-01-04 21:25:28 -08:00
jvernet
5f21ef14a4 Macs Flat icons, Toolbar 2016-01-04 21:25:28 -08:00
jvernet
4de4fa6685 ?? 2016-01-04 21:25:28 -08:00
jvernet
680fbea853 Add missing IOS icon 2016-01-04 21:25:28 -08:00
jvernet
29e6dcde2f dsk document definition
so that you can download .dsk directly in Apple2IOS Document/inbox
directly from Safari. But need a way to show Inbox folder in Disk View…
2016-01-04 21:25:28 -08:00
jvernet
0fee86bc3c Added ReadOnly Switchs for disks 2016-01-04 21:25:27 -08:00
jvernet
b6a9f667ef Latest commit from mauiaaron need common.h in imagutil for FREE and MALLOC macros 2016-01-04 21:25:27 -08:00
jvernet
7008d21fcf IOS icon 2016-01-04 21:25:27 -08:00
jvernet
f05ce4d247 IOS icons 2016-01-04 21:25:27 -08:00
jvernet
6445546ff9 Toolbar Icons 2016-01-04 21:25:27 -08:00
jvernet
672d824946 Yes, it work !
https://youtu.be/C5no96qnCNQ
2016-01-04 21:25:27 -08:00
jvernet
4d89d173f4 Here we are: now everything work for iPad. 2016-01-04 21:25:27 -08:00
jvernet
86064cf1c6 Hard to understand those Segues ***ing 2016-01-04 21:25:27 -08:00
jvernet
b60a697b86 Finally ! First time loading disk !!! 2016-01-04 21:25:27 -08:00
jvernet
3cea55cc40 Est ce que je vais terminer un jour ? 2016-01-04 21:25:26 -08:00
jvernet
f722725992 IOS Pref more 2016-01-04 21:25:26 -08:00
jvernet
28875b5e76 IOS Prefs 2016-01-04 21:25:26 -08:00
jvernet
a3040dfb05 IOS stuff 2016-01-04 21:25:26 -08:00
jvernet
d23b0593fb IOS Stuff 2016-01-04 21:25:26 -08:00
jvernet
97700bbff6 More IOS work
but it doesn’t work better.
2016-01-04 21:25:26 -08:00
jvernet
b9a6f0060d test on real iPad 2016-01-04 21:25:26 -08:00
jvernet
4522fa98ac ToolBar properly at bottom 2016-01-04 21:25:26 -08:00
jvernet
bf341731f0 Separate View/controller 2016-01-04 21:25:26 -08:00
jvernet
b04e7760c2 IOS ToolBar Trying
Need to know how it work…
2016-01-04 21:25:26 -08:00
jvernet
f984bfc5b0 IOS 2016-01-04 21:25:25 -08:00
jvernet
b251e122e2 Localization Preferences 2016-01-04 21:25:25 -08:00
jvernet
4d1224ce29 Localization French 2016-01-04 21:25:25 -08:00
jvernet
746dcb2e3d Suite 2016-01-04 21:25:25 -08:00
jvernet
5d86735a69 Fixed Crash on reboot
It crash ? Killing // ;)
2016-01-04 21:25:25 -08:00
jvernet
f4258ade45 Initials changes
Added NSToolbar and French Localization
2016-01-04 21:25:25 -08:00
Aaron Culliney
40129d9a14 Bump Android version to 1.1.5 2016-01-04 20:41:46 -08:00
Aaron Culliney
e7e6af1335 WIP : first cut at MainMenu popup 2016-01-04 20:34:27 -08:00
Aaron Culliney
97f52ef2ff Get Android build unstuck 2016-01-04 20:34:27 -08:00
Aaron Culliney
5737e89150 Initial iOS target compiles, links, and appears to run in simulator and on device =) 2016-01-04 20:34:27 -08:00
Aaron Culliney
6af1309e2d Various project changes to prepare for iOS target 2016-01-04 20:33:35 -08:00
Aaron Culliney
042edd8bab Segregate Mac-specific classes into OSX group 2016-01-04 20:33:35 -08:00
Aaron Culliney
0b7f3a75b5 deal with short writes 2016-01-04 20:33:35 -08:00
Aaron Culliney
0bb0df0960 Support building Android version in release mode (without -g and with -DNDEBUG=1) 2016-01-03 13:59:52 -08:00
Aaron Culliney
64338d30c3 German translation from Guido Lehwalder 2016-01-03 13:50:55 -08:00
Aaron Culliney
bda8efeb45 Slight tweak to custom keyboard 2016-01-03 13:09:57 -08:00
Aaron Culliney
5a2529651c Fix recent Android build break 2016-01-03 13:09:23 -08:00
Aaron Culliney
08a6d99334 Fix assert/crash on desktop Linux introduced by overzealous malloc fencing 2016-01-03 13:01:48 -08:00
Aaron Culliney
c89ee87bd4 Tweak heuristic calculation of when to use 2x glyphs 2016-01-03 12:58:12 -08:00
Aaron Culliney
d8fc04ec2e Expose ability to set azimuth visibility on Android 2016-01-03 12:49:23 -08:00
Aaron Culliney
42feeb1bd3 Remove new English strings
- Native speakers are encouraged to send me a pull req for these ;-)
2016-01-03 12:48:01 -08:00
Aaron Culliney
c2014e2cde Add simple display of touch joystick azimuth 2016-01-03 12:36:13 -08:00
Aaron Culliney
29282dcac6 Expose identity matrix and only calculate it once 2016-01-03 12:02:06 -08:00
Aaron Culliney
9219fa7053 Creation of GLCustom model is slightly more RAII 2016-01-03 11:57:48 -08:00
Aaron Culliney
2ec88ad433 Iterate on GLTouchJoystick
- Use smaller models/textures
    - Slightly change the joystick/kpad glyphs
2016-01-02 15:08:06 -08:00
Aaron Culliney
691dbd5ac2 Coalesce duplicate fade-out codepaths 2016-01-02 14:23:09 -08:00
Aaron Culliney
8b3f288018 Reduce duplicate OpenGL plumbing codepaths
- Apple //e "framebuffer" OpenGL model/texture is now a complete GLModel object
    - Readability FTW! ... use args struct in quadCreation function to allow for named args
2016-01-02 13:39:07 -08:00
Aaron Culliney
7ca679350d Move shader/program creation into video_util module 2016-01-02 11:33:47 -08:00
Aaron Culliney
b59672815f Allow setting keyboard and HUD menu glyph scale 2016-01-02 00:14:21 -08:00
Aaron Culliney
904d89aff8 Get touch menu min/max alpha matching touch keyboard 2016-01-01 21:38:35 -08:00
Aaron Culliney
39c654ae9d Simplify and coalesce touch menu settings into keyboard settings for now 2016-01-01 21:35:49 -08:00
Aaron Culliney
b1cbe44a05 Placeholder menu strings 2016-01-01 19:58:46 -08:00
Aaron Culliney
f5bbda4c6e Refactor HUD model to allow scaling font glyphs
- Should be less pixelation of touch keyboard on large tablet screens
2016-01-01 15:02:29 -08:00
Aaron Culliney
a54a69efcc Call "super init" during HUD model creation 2015-12-31 22:54:34 -08:00
Aaron Culliney
abae59767c Enable simple heap memory fencing/scribbling in debug builds 2015-12-31 22:50:43 -08:00
Aaron Culliney
fce1f010b0 Bump Android version to 1.1.4 2015-12-28 19:01:34 -08:00
Aaron Culliney
20278ca91e Migration to 1.1.3+ should remove disks that were excised 2015-12-24 22:17:29 -08:00
Aaron Culliney
b996083a42 tweaks for Spanish localizations 2015-12-24 21:12:24 -08:00
Aaron Culliney
3e777477e2 Wish profuse apologies to native speakers, first cut at Spanish translation 2015-12-22 21:54:18 -08:00
Aaron Culliney
4d9eda4862 Work around another UI race exposed by NVIDIA Shield Portable 2015-12-22 21:53:14 -08:00
Aaron Culliney
4deedb2215 Move main menu dialog code into Apple2MainMenu 2015-12-20 16:45:59 -08:00
Aaron Culliney
bf3ef3ae18 GZIP the supplied disk images to help cut down on app space 2015-12-20 15:18:09 -08:00
Aaron Culliney
9fd288c0b9 Remove aggressive assert that fired on Cyanogen device (even with a valid CPU pause/resume lifecycle) ... 2015-12-20 15:04:20 -08:00
Aaron Culliney
abe1346051 Remove unused method 2015-12-20 15:04:06 -08:00
Aaron Culliney
145b6a6cef Refactor JNI plumbing for consistency 2015-12-20 12:54:27 -08:00
Aaron Culliney
22b1bc9ad8 Move key handling back to the Activity, otherwise we don't seem to receive onKeyUp() for the Android back button 2015-12-20 12:11:12 -08:00
Aaron Culliney
2f7f7bd359 Preliminary support for mapping an Android physical gamepad/joystick to emulated Apple //e joystick
- No support for custom joystick/gamepad configurations (yet)
2015-12-19 23:59:02 -08:00
Aaron Culliney
7dd0f0b3cf Avoid another UI race exposed by NVIDIA Shield Portable
- Use AtomicBoolean to avoid spurious extra taps/clicks/presses
2015-12-19 23:24:45 -08:00
Aaron Culliney
3ff877d80c Refactor : move event handling into custom view 2015-12-19 23:13:52 -08:00
Aaron Culliney
13de08f8cb map L1 and R1 keys to joy buttons 2015-12-19 23:13:44 -08:00
Aaron Culliney
1d248c5e22 Whitespace and style changes 2015-12-19 23:13:33 -08:00
Aaron Culliney
e5e2f98835 Avoid nasty UI race manifesting on NVIDIA Shield Portable
- For some reason this device has really slow Java UI, so it exposed a case where spammy touch resulted in two
      save/restore popups and a subsequent assert on the native side if you saved while the emulation was resumed.
2015-12-19 23:12:05 -08:00
Aaron Culliney
1e573c34ad Meager support for Android joystick/gamepad keys 2015-12-19 13:14:46 -08:00
Aaron Culliney
e165da72fc Explicitly not supporting older joystick devices 2015-12-19 13:14:10 -08:00
Aaron Culliney
1c50d12963 Source InputManager from AOSP 2015-12-19 13:08:48 -08:00
Aaron Culliney
d69b416c58 Lightly refactor emulator joystick API in preparation for more comprehensive refactor 2015-12-19 13:01:28 -08:00
Aaron Culliney
a1fbc63f98 Semi-inscrutible changes insisted upon by Android Studio 2015-12-19 12:59:40 -08:00
Aaron Culliney
c7c209907b Allow for keyboard to completely own/cover screen
- Includes updated alternate/custom keyboards
2015-12-19 12:56:24 -08:00
Aaron Culliney
5bd7ff2fe1 Simplify switching to "useralt" touch keyboard 2015-12-16 22:15:19 -08:00
Aaron Culliney
72fb577166 Update misc Android assets 2015-12-16 22:14:29 -08:00
Aaron Culliney
69b096ec14 Avoid showing redundant 0 nibble 2015-12-16 21:33:25 -08:00
Aaron Culliney
f872e0c05c fix i386 variant of op_SBC_dec (now re-passes tests on x86 Android) 2015-12-16 21:12:45 -08:00
Aaron Culliney
5211722d63 Switch to using DSK to speed up tests on Android 2015-12-16 21:11:52 -08:00
Aaron Culliney
785577e252 Fix some compiler warnings in testdisk.c 2015-12-16 21:11:35 -08:00
Aaron Culliney
3a20c96296 Check more paths in attempt to satisfy test suite disk insertion
- This is mainly to accommodate disk locations on Android
2015-12-16 21:01:50 -08:00
Aaron Culliney
2c8284d41f Start running tests on Android after first resume
- This allows for a more consistent test environment (test disks copied out of APK and available, etc) and also
      mimics main app behavior
2015-12-16 20:59:20 -08:00
Aaron Culliney
9e5274ee18 Flip-flop test to correctly account for e5f08849 2015-12-16 20:56:20 -08:00
Aaron Culliney
26e452c3a3 Avoid bufover in testsuite -- sprintf() already writes terminating null byte! 2015-12-16 20:53:16 -08:00
Aaron Culliney
870a24ced6 Fix test compilation on Android 2015-12-15 22:24:43 -08:00
Aaron Culliney
2dbd77e344 Excise uthash.h from testcpu suite
- Works around issue where Android NDK GCC 4.8/4.9 would take an inordinate amount of time when compiling testcpu with -O2
2015-12-14 23:56:48 -08:00
Aaron Culliney
699746a743 Alleviate compiler warnings in testvm/testdisplay 2015-12-14 23:55:08 -08:00
Aaron Culliney
74e97ccc97 Alleviate compiler warnings in testcpu 2015-12-14 22:11:29 -08:00
Aaron Culliney
1f0021667b Fix display test failures
- New framebuffer SHAs result of recent improvements to DHIRES colors
2015-12-14 18:59:44 -08:00
Aaron Culliney
836044c80b Bump Android version to 1.1.3 2015-12-13 22:48:29 -08:00
Aaron Culliney
341885e233 Undo selected character highlight when keyboard fades out 2015-12-13 13:38:03 -08:00
Aaron Culliney
87761df512 Avoid using magic row/column numbers when redrawing adjacent characters 2015-12-13 13:24:25 -08:00
Aaron Culliney
f34cf4c384 Band-aid for joystick state corruption after foregrounding 2015-12-13 12:44:03 -08:00
Aaron Culliney
2a51a62127 Avoid NPE when external storage is unavailable 2015-12-13 12:09:49 -08:00
Aaron Culliney
b32a97b6fc Slightly better translation via @stef-pellegrino 2015-12-12 14:50:41 -08:00
Aaron Culliney
6cef33b501 Request and handle external storage permissions on Marshmallow
- Also disentangles exposing APK assets internally and on external storage
2015-12-12 13:38:22 -08:00
Aaron Culliney
ac78e00afa Alter UI only on UI thread 2015-12-12 13:29:50 -08:00
Aaron Culliney
b1b55006be Resetting preferences will also quit to re-trigger any migration code 2015-12-12 13:20:47 -08:00
Aaron Culliney
a761c11382 First cut at support for Android versioning and data migrations 2015-12-12 12:09:14 -08:00
Aaron Culliney
d819220a07 Pass Apple2Activity to out getExternalStorageDirectory() function 2015-12-12 12:03:41 -08:00
Aaron Culliney
22914de79c Enable setting to show/hide disk read/write HUD messages 2015-12-12 12:01:41 -08:00
Aaron Culliney
cdb0f7b06b Shunt disk-state-change information back to the Java/Android menu system 2015-12-12 11:42:33 -08:00
Aaron Culliney
edf42b81f9 Improve disk quick save/restore
- Flush disk I/O on save
    - Ignore ephemeral track_valid/track_dirty bits
    - Insure disks are ejected if there was a problem loading state
2015-12-12 00:21:27 -08:00
Aaron Culliney
0aed046b5e Simplify modulo offset calculations in trackimage 2015-12-12 00:17:58 -08:00
Aaron Culliney
ef1963a175 Avoid potential read off end of trackimage 2015-12-12 00:16:14 -08:00
Aaron Culliney
651ac246e3 Flush disk IO on backgrounding 2015-12-11 23:42:57 -08:00
Aaron Culliney
05cb322feb Bump Android version to 1.1.2 2015-12-09 22:46:22 -08:00
Aaron Culliney
0f98a34e06 Refactor naming of user-chosen alternate keyboard 2015-12-09 22:11:44 -08:00
Aaron Culliney
1147ce7cd7 Avoid crash potential by doing less during resource acquisition
- (This also would have fixed ctrlPressed background bug -- previous 02147f3d commit)
2015-12-09 21:56:28 -08:00
Aaron Culliney
02147f3d9a Refactor and avoid NULL deref edge-case
- Bug was triggered if ctrlPressed was true when going to background.  Foregrounding would reset/NULLify the
      GLModel, but attempt to render the ctrl key highlighted before the new GLModel was fully created.
2015-12-09 21:25:09 -08:00
stef-pellegrino
791bb91843 French version 2015-12-09 19:55:37 -08:00
Aaron Culliney
b48cfa2084 First cut at French translation for Android (blame Google for this one ;-) 2015-12-08 22:36:10 -08:00
Aaron Culliney
d96db51bd2 Clarify and clean up a number of settings 2015-12-08 22:35:59 -08:00
Aaron Culliney
2e100c9b67 Remove a bunch of unused string resources 2015-12-08 20:46:22 -08:00
Aaron Culliney
ad7902b41f First cut at Moebius keyboard
- Takes a bit getting used to, but I successfully completed Earth level employing finger-muscle-memory strategies
      from the '80s ;-)
2015-12-07 23:05:03 -08:00
Aaron Culliney
943b8842f7 Show disk track sector change animations 2015-12-07 23:03:44 -08:00
Aaron Culliney
74c951f64f Bump Android version to 1.1.1 2015-12-04 23:10:47 -08:00
Aaron Culliney
05698c6a5e Avoid another audio buffer overflow manifesting on Kindle 2015-11-29 22:14:55 -08:00
Aaron Culliney
c7250d860f Send SDK version in crash reports 2015-11-29 21:31:23 -08:00
Aaron Culliney
0d74d21608 Bump Android version to 1.1.10 2015-11-29 14:41:54 -08:00
Aaron Culliney
e1629095b6 Get crash symbolication working for x86 build 2015-11-29 14:35:01 -08:00
Aaron Culliney
5a9770829e Fix commentary and ignore expected_bytes if set to zero 2015-11-29 13:31:17 -08:00
Aaron Culliney
ff204a4300 Slight refactor to move common ".gz" extension handling code to interface module 2015-11-29 13:23:13 -08:00
Aaron Culliney
12b2103a56 Condense reboot/quit main menu item into one popup
- This works better on lo-res devices (ahem, Galaxy Y) and I'd rather not iterate too much on the Java menus for now
      since they appear to be basically working =P
2015-11-25 23:13:43 -08:00
Aaron Culliney
b9d6d38b17 First cut at save/restore emulator state feature
- This adds to overall UX ... (you can finally finish some very difficult arcade games by strategically leveraging
      this feature)
    - Currently enabled for Android, but not Android-specific
2015-11-22 18:22:01 -10:00
Aaron Culliney
46c286719f Fix Android build after Mac iteration 2015-11-14 11:09:33 -08:00
Aaron Culliney
c35122beb6 Changes insisted upon by Xcode 7.x 2015-11-14 10:42:17 -08:00
Aaron Culliney
ee83ecb52c Enable CPU speed animation 2015-11-14 10:41:53 -08:00
Aaron Culliney
29fd1f5025 Bugfix : avoid massively overflowing heap memory 2015-11-14 09:56:11 -08:00
Aaron Culliney
33160be9ac Disambiguate texture name from texture() function in basic fragment shader 2015-11-14 08:09:10 -08:00
Aaron Culliney
0aacdfa9e5 Various fixes from Apple Clang static analyzer 2015-11-14 08:03:44 -08:00
Aaron Culliney
a61fd339a6 Various fixes to get Mac build compiling 2015-11-14 08:01:20 -08:00
Aaron Culliney
dc1845afe9 Add correct files to Mac project 2015-11-13 23:09:24 -08:00
Aaron Culliney
a41dc46eee Fix broken menus on x86 Android
- Make it explicit that we are dealing with uint8_t values and not ambiguous signed int values
2015-11-10 22:22:31 -08:00
Aaron Culliney
ad5a6e8061 Get NDK debugging working from script: './apple2ix debug' 2015-11-10 22:08:32 -08:00
Aaron Culliney
e4c669f016 x86 builds and basically works on Android x86 devices 2015-11-09 22:45:52 -08:00
Aaron Culliney
3bdbe50f0f Bump Android version to 1.0.4 2015-11-08 22:03:22 -08:00
Aaron Culliney
0cefd912b5 Build against API 23 now that text relocs appear to be solved 2015-11-08 21:13:13 -08:00
Aaron Culliney
456f9a14e4 Build PIC without relocations in TEXT section 2015-11-08 21:11:03 -08:00
Aaron Culliney
f06257b2c5 Add ARM assembly PIC without TEXTREL
- Adds codepaths that allow for Position Independent Code (PIC) that also avoids having TEXT relocations (TEXTREL)
      that the dynamic linker needs to patch up
2015-11-08 14:42:03 -08:00
Aaron Culliney
7a8c4dda63 Update generated file 2015-11-07 10:44:08 -08:00
Aaron Culliney
63b6e0a29a Fix my blended rendering on Tegra 2 (and arguably globally) 2015-11-07 10:36:20 -08:00
Aaron Culliney
f423c2dbe6 Work around broken Tegra 2 GPU 2015-11-06 22:18:16 -08:00
Aaron Culliney
dd7727f757 Simplify fragment shader and remove dead macro 2015-11-06 21:20:33 -08:00
Aaron Culliney
e9bae19e9e Bump Android version to 1.0.3 2015-11-04 21:15:12 -08:00
Aaron Culliney
bc96417091 DO NOT use API 23 yet ... we need to fix text relocations first!
- This prevents crashing on Marshmallow (for the time being)
2015-11-04 20:03:28 -08:00
Aaron Culliney
fb4d6f466b Splash screen is not dismissable during first time initialization or crash reporting 2015-11-03 22:47:35 -08:00
Aaron Culliney
a6ac111707 lightly refactor two-phase first-time launch 2015-11-03 22:42:24 -08:00
Aaron Culliney
d0319bd2ff Splash screen may be dismissable (or not) 2015-11-03 22:41:50 -08:00
Aaron Culliney
9b56050c1e All the Broken Adrenos! 2015-11-02 20:46:16 -08:00
Aaron Culliney
871762975a Bump Android version to 1.0.2 2015-11-01 22:03:39 -08:00
Aaron Culliney
ce974177b2 Correct link 2015-11-01 21:00:05 -08:00
Aaron Culliney
b524b5a068 Point to curated public domain images repo 2015-11-01 20:48:46 -08:00
Aaron Culliney
646d64cd92 Don't forget to clean up crash spam ;-) 2015-11-01 19:33:39 -08:00
Aaron Culliney
6de1cae478 Move nativeOnCreate back to proper position as first native call
- This runs discovery of CPU family
    - This sets up native crash handling
2015-11-01 19:26:34 -08:00
Aaron Culliney
4999471ade Work around black screen if someone went to joystick calibration from splash screen 2015-11-01 14:19:40 -08:00
Aaron Culliney
933e99c927 Bugfix Gingerbread GLSurfaceView lifecycle 2015-11-01 14:17:10 -08:00
Aaron Culliney
9a2044f75e Apparently not possible to query this early on Gingerbread devices 2015-11-01 13:43:09 -08:00
Aaron Culliney
3d634004cf Avoid reinitializing preferences every resume of GLView 2015-11-01 13:42:05 -08:00
Aaron Culliney
bf54615198 Refactor menu ownership and dismissal
- Fix incorrect iteration in dismissAll() that could lead to restarting CPU too early
    - Semi-lazy-loaded Apple2MainMenu (which depends on GLSurfaceView/Apple2View as main content) no longer owns
      Apple2SettingsMenu and Apple2DisksMenu
2015-11-01 12:44:31 -08:00
Aaron Culliney
521d1daccf Refactor app startup
- Make sure crash checking is performed as early as possible
    - Minimize calling complex native functions until after splash screen is dimissed
    - Do not attempt to setup/resume OpenGL until after splash screen is dimissed
2015-11-01 10:14:40 -08:00
Aaron Culliney
cbe8a734d0 Move CPU feature discovery into CTOR 2015-10-31 23:00:45 -07:00
Aaron Culliney
6c959a030c Remove unused public methods 2015-10-31 14:03:53 -07:00
Aaron Culliney
acdc8da64f Refactor pause/resume functions to be strictly CPU thread pause/resume 2015-10-31 14:01:47 -07:00
Aaron Culliney
e52f753bf3 Remove commented code 2015-10-31 10:35:24 -07:00
Aaron Culliney
d4adabda93 SNEAKY BUGFIX race condition between UI thread and CPU thread on disk insertion
- Previously we would start the CPU thread and then insert, which has been a long standing race condition, but
      possibly better exposed since the recent disk.c rephactor to use mmap I/O
    - This directly manifested on a Kindle Fire 1st Gen as a crash, and, anecdotally on other devices as a "stalled"
      disk read requiring a reboot of the virtual machine.  Yay for crappy devices helping to expose crappy code! (git
      blame me). =P
2015-10-30 23:19:33 -07:00
Aaron Culliney
20f79dc5eb Avoid buffer overflow
- Appears to fix a crash on Kindle Fire 1st Gen
2015-10-30 23:14:20 -07:00
Aaron Culliney
84fe0dd479 Fix crash on Nexus 10 device due to regfree()ing something not regcomp()ed 2015-10-30 23:12:12 -07:00
Aaron Culliney
5c4ab06612 Hopefully improve crash reporting on older devices by sending a crash summary (possibly in addition to the attachment) 2015-10-30 00:13:14 -07:00
Aaron Culliney
dcd77a4650 Allow and gracefully handle case when external files directory is null 2015-10-28 23:52:54 -07:00
Aaron Culliney
916a54fb4b Update README.md 2015-10-28 00:04:03 -07:00
Aaron Culliney
616428a03f Slightly improved DHIRES colors 2015-10-26 23:11:29 -07:00
Aaron Culliney
38dce3e212 Check if parent view exists as proxy for isShowing 2015-10-25 22:03:44 -07:00
Aaron Culliney
844d8b815b Losing trust with implementation(s) of Apple2MenuView.isShowing()
- This changes the behavior to rely on non-null status as proxy for showing
    - TODO : investigate why isShowing() appears to be a race/bogus
2015-10-25 21:00:16 -07:00
Aaron Culliney
997461318f Bump Android version code 2015-10-25 20:56:51 -07:00
264 changed files with 17907 additions and 3524 deletions

View File

@@ -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
View File

@@ -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>

View File

@@ -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"
}

View File

@@ -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;
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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() {

View File

@@ -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();
}
}

View File

@@ -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) {

View File

@@ -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"));

View File

@@ -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();
}
});

View File

@@ -114,7 +114,7 @@ public class Apple2JoystickCalibration implements Apple2MenuView {
}
public boolean isShowing() {
return mSettingsView.isShown();
return mSettingsView.getParent() != null;
}
public View getView() {

View File

@@ -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");
}
});

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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() {

View File

@@ -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;
}
}

View 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">&#8595;</string>
<string name="key_esc">[ESC]</string>
<string name="key_left">&#8592;</string>
<string name="key_none">[Keine]</string>
<string name="key_open_apple">[OffenerApfel]</string>
<string name="key_ret">[Return]</string>
<string name="key_right">&#8594;</string>
<string name="key_space">[Space]</string>
<string name="key_up">&#8593;</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 &amp; 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">&#8593;,&#8592;,&#8594;,&#8595;, tippe auf die Leerstaste</string>
<string name="keypad_preset_az_left_right_space">A,Z,&#8592;,&#8594;, 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">&#8592;,&#8594;, 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 &amp; 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&#8594;</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>

View 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">&#8595;</string>
<string name="key_esc">[ESC]</string>
<string name="key_left">&#8592;</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">&#8594;</string>
<string name="key_space">[Espaciadora]</string>
<string name="key_up">&#8593;</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">&#8593;,&#8592;,&#8594;,&#8595;, pulse espaciadora</string>
<string name="keypad_preset_az_left_right_space">A,Z,&#8592;,&#8594;, pulse espaciadora</string>
<string name="keypad_preset_ijkm_space">I,J,K,M, pulse espaciadora</string>
<string name="keypad_preset_left_right_space">&#8592;,&#8594;, 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"></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&#8594;</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>

View 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">&#8595;</string>
<string name="key_esc">[ESC]</string>
<string name="key_left">&#8592;</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">&#8594;</string>
<string name="key_space">[Espace]</string>
<string name="key_up">&#8593;</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 &amp; 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">&#8593;,&#8592;,&#8594;,&#8595;, pressez barre d\'espace</string>
<string name="keypad_preset_az_left_right_space">A,Z,&#8592;,&#8594;, 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">&#8592;,&#8594;, 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 &amp; 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&#8594;</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>

View File

@@ -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: &#8531; 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 &amp; 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">&#8593;,&#8592;,&#8594;,&#8595;, tap spacebar</string>
<string name="keypad_preset_az_left_right_space">A,Z,&#8592;,&#8594;, 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">&#8592;,&#8594;, 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 &amp; 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&#8594;</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>

View File

@@ -1 +1 @@
../../disks
../../../apple2-images-pub/disks

View File

@@ -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", "", "", "", ""],
[ "", "", "", "", "", "", "", "", "", ""]
]

View File

@@ -9,11 +9,11 @@
"_SP" : "b1"
},
[ "reserved for future use" ],
[ "reserved for future use" ],
[ "", "", "", "", "", "", "", "", "", "" ],
[ "_AA", "", "", "", "", "", "", "", "", "" ],
[ "", "", "", "", "", "", "", "", "", "" ],
[ "", "", "", "", "", "", "", "", "", "" ],
[ "", "", "", "", "", "", "", "", "", "" ],
[ "Q", "", "", "", "", "", "", "", "A", "" ],
[ "", "", "", "", "", "", "", "_LT", "", "_RT" ],
[ "_SP", "", "", "", "", "", "", "", "Z", "" ]

View 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",",", ".", "/"]
]

View File

@@ -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", ""]
]

View File

@@ -0,0 +1 @@
../../../src/video/SolidColor.fsh

View File

@@ -0,0 +1 @@
../../../src/video/SolidColor.vsh

View File

View 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

View File

@@ -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;

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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],

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -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>

View 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

View 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

View File

@@ -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>

View File

@@ -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>

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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}

View File

@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View 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";

File diff suppressed because it is too large Load Diff

View 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

View 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

View File

@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View 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

View 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

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,17 @@
{
"layers" : [
{
"filename" : "Front.imagestacklayer"
},
{
"filename" : "Middle.imagestacklayer"
},
{
"filename" : "Back.imagestacklayer"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Some files were not shown because too many files have changed in this diff Show More