├── settings.gradle
├── app
├── src
│ ├── main
│ │ ├── assets
│ │ │ └── roms
│ │ │ │ ├── os
│ │ │ │ ├── os01
│ │ │ │ └── b
│ │ │ │ ├── BASIC.ROM
│ │ │ │ └── DFS-0.9.rom
│ │ ├── jni
│ │ │ ├── bbctext.h
│ │ │ ├── Application.mk
│ │ │ ├── Android.mk
│ │ │ ├── adc.c
│ │ │ ├── main.h
│ │ │ ├── disc.c
│ │ │ ├── ssd.c
│ │ │ └── uservia.c
│ │ ├── libs
│ │ │ ├── x86
│ │ │ │ └── libbbcmicro.so
│ │ │ ├── armeabi
│ │ │ │ └── libbbcmicro.so
│ │ │ └── armeabi-v7a
│ │ │ │ └── libbbcmicro.so
│ │ ├── res
│ │ │ ├── drawable-hdpi
│ │ │ │ ├── key.png
│ │ │ │ ├── dpad0.png
│ │ │ │ ├── icon.png
│ │ │ │ ├── save.png
│ │ │ │ ├── key_fn.png
│ │ │ │ ├── keyboard.png
│ │ │ │ ├── led_off.png
│ │ │ │ ├── led_on.png
│ │ │ │ ├── controller.png
│ │ │ │ ├── dpad_arrow_up.png
│ │ │ │ ├── pad_pressed.png
│ │ │ │ ├── tab_normal.9.png
│ │ │ │ ├── dpad_arrow_down.png
│ │ │ │ ├── dpad_arrow_left.png
│ │ │ │ ├── keyboard_cancel.png
│ │ │ │ ├── dpad_arrow_right.png
│ │ │ │ ├── nnf_ic_file_folder.png
│ │ │ │ └── nnf_ic_collections_add_collection.png
│ │ │ ├── drawable-mdpi
│ │ │ │ ├── tab1.9.png
│ │ │ │ ├── nnf_ic_file_folder.png
│ │ │ │ └── nnf_ic_collections_add_collection.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ ├── nnf_ic_file_folder.png
│ │ │ │ └── nnf_ic_collections_add_collection.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ ├── nnf_ic_file_folder.png
│ │ │ │ └── nnf_ic_collections_add_collection.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ │ └── nnf_ic_file_folder.png
│ │ │ ├── values-xlarge
│ │ │ │ └── dimen.xml
│ │ │ ├── drawable
│ │ │ │ ├── button_bg.xml
│ │ │ │ ├── tab.xml
│ │ │ │ ├── tab_bg_unselected.xml
│ │ │ │ ├── tab_bg_selected.xml
│ │ │ │ ├── form_standalone.xml
│ │ │ │ ├── tab_text_selector.xml
│ │ │ │ ├── form_standalone_normal.xml
│ │ │ │ ├── form_standalone_focused.xml
│ │ │ │ ├── form_standalone_pressed.xml
│ │ │ │ └── tab_bg_selector.xml
│ │ │ ├── layout
│ │ │ │ ├── listitem_add_new_saved_game.xml
│ │ │ │ ├── activity_controllers.xml
│ │ │ │ ├── activity_savedgames.xml
│ │ │ │ ├── tabs_bg.xml
│ │ │ │ ├── listitem_diskinfo_header.xml
│ │ │ │ ├── listview.xml
│ │ │ │ ├── listview_online.xml
│ │ │ │ ├── listitem_diskinfo.xml
│ │ │ │ ├── nnf_activity_filepicker.xml
│ │ │ │ ├── listitem_controllerinfo.xml
│ │ │ │ ├── nnf_fragment_filepicker.xml
│ │ │ │ ├── activity_loaddisk.xml
│ │ │ │ ├── nnf_dialog_folder_name.xml
│ │ │ │ ├── activity_beebdroid.xml
│ │ │ │ ├── listitem_savedgame.xml
│ │ │ │ ├── nnf_filepicker_listitem_dir.xml
│ │ │ │ ├── nnf_filepicker_listitem_checkable.xml
│ │ │ │ └── activity_about.xml
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── attr.xml
│ │ │ │ ├── picker_strings.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ ├── menu
│ │ │ │ └── picker_actions.xml
│ │ │ └── layout-land
│ │ │ │ └── activity_beebdroid.xml
│ │ ├── java
│ │ │ ├── com
│ │ │ │ ├── littlefluffytoys
│ │ │ │ │ └── beebdroid
│ │ │ │ │ │ ├── App.java
│ │ │ │ │ │ ├── InstalledDisks.java
│ │ │ │ │ │ ├── AboutActivity.java
│ │ │ │ │ │ ├── ControllerInfo.java
│ │ │ │ │ │ ├── DiskInfo.java
│ │ │ │ │ │ ├── Model.java
│ │ │ │ │ │ ├── ControllerView.java
│ │ │ │ │ │ ├── UserPrefs.java
│ │ │ │ │ │ ├── BeebKeys.java
│ │ │ │ │ │ ├── DPad.java
│ │ │ │ │ │ ├── SavedGameInfo.java
│ │ │ │ │ │ ├── Keyboard.java
│ │ │ │ │ │ ├── TouchpadsView.java
│ │ │ │ │ │ └── Controllers.java
│ │ │ │ └── nononsenseapps
│ │ │ │ │ └── filepicker
│ │ │ │ │ ├── FileItemAdapter.java
│ │ │ │ │ ├── LogicHandler.java
│ │ │ │ │ └── NewItemFragment.java
│ │ │ └── common
│ │ │ │ ├── Packageable.java
│ │ │ │ ├── Network.java
│ │ │ │ └── Utils.java
│ │ └── AndroidManifest.xml
│ └── ouya
│ │ └── AndroidManifest.xml
└── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── Beebdroid.iml
├── gradlew.bat
└── gradlew
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/src/main/assets/roms/os:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/assets/roms/os
--------------------------------------------------------------------------------
/app/src/main/jni/bbctext.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/jni/bbctext.h
--------------------------------------------------------------------------------
/app/src/main/assets/roms/os01:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/assets/roms/os01
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/assets/roms/b/BASIC.ROM:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/assets/roms/b/BASIC.ROM
--------------------------------------------------------------------------------
/app/src/main/assets/roms/b/DFS-0.9.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/assets/roms/b/DFS-0.9.rom
--------------------------------------------------------------------------------
/app/src/main/libs/x86/libbbcmicro.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/libs/x86/libbbcmicro.so
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/key.png
--------------------------------------------------------------------------------
/app/src/main/libs/armeabi/libbbcmicro.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/libs/armeabi/libbbcmicro.so
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/dpad0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/dpad0.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/save.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/key_fn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/key_fn.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/keyboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/keyboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/led_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/led_off.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/led_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/led_on.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/tab1.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-mdpi/tab1.9.png
--------------------------------------------------------------------------------
/app/src/main/libs/armeabi-v7a/libbbcmicro.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/libs/armeabi-v7a/libbbcmicro.so
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/controller.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/dpad_arrow_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/dpad_arrow_up.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/pad_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/pad_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/tab_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/tab_normal.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/dpad_arrow_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/dpad_arrow_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/dpad_arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/dpad_arrow_left.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/keyboard_cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/keyboard_cancel.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/dpad_arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/dpad_arrow_right.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/nnf_ic_file_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/nnf_ic_file_folder.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/nnf_ic_file_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-mdpi/nnf_ic_file_folder.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/nnf_ic_file_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-xhdpi/nnf_ic_file_folder.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/nnf_ic_file_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-xxhdpi/nnf_ic_file_folder.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/nnf_ic_file_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-xxxhdpi/nnf_ic_file_folder.png
--------------------------------------------------------------------------------
/app/src/main/res/values-xlarge/dimen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 400dp
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/nnf_ic_collections_add_collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-hdpi/nnf_ic_collections_add_collection.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/nnf_ic_collections_add_collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-mdpi/nnf_ic_collections_add_collection.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/nnf_ic_collections_add_collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-xhdpi/nnf_ic_collections_add_collection.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/nnf_ic_collections_add_collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/littlefluffytoys/Beebdroid/HEAD/app/src/main/res/drawable-xxhdpi/nnf_ic_collections_add_collection.png
--------------------------------------------------------------------------------
/app/src/ouya/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/jni/Application.mk:
--------------------------------------------------------------------------------
1 | # The ARMv7 is significanly faster due to the use of the hardware FPU
2 | APP_ABI := armeabi armeabi-v7a x86
3 | APP_PLATFORM := android-8
4 |
5 | ifneq ($(APP_OPTIM),debug)
6 | APP_CFLAGS += -O3
7 | endif
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tab_bg_unselected.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tab_bg_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/App.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import android.app.Application;
4 |
5 | /**
6 | * Created by reuben on 08/09/15.
7 | */
8 | public class App extends Application {
9 |
10 | public static App app;
11 |
12 | public App() {
13 | app = this;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/form_standalone.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tab_text_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 7
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listitem_add_new_saved_game.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_controllers.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_savedgames.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/form_standalone_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 | obj/
15 |
16 | # Local configuration file (sdk path, etc)
17 | local.properties
18 |
19 | # Windows thumbnail db
20 | Thumbs.db
21 |
22 | # OSX files
23 | .DS_Store
24 |
25 | # Eclipse project files
26 | .classpath
27 | .project
28 |
29 | # Android Studio
30 | *.iml
31 | .idea
32 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
33 | .gradle
34 | build/
35 |
36 | /*/out
37 | /*/*/build
38 | /*/*/production
39 | *.iws
40 | *.ipr
41 | *~
42 | *.swp
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/tabs_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listitem_diskinfo_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/form_standalone_focused.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
21 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/form_standalone_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
21 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | #FFff8c00
6 | #FFffA500
7 | #7FFFA814
8 | #FFFFAB26
9 | #FFFFFFFF
10 | #FFA0A0A0
11 | #FFFF4040
12 | #FFC0C0C0
13 | #FF408040
14 | #FFFFFFFF
15 |
16 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 |
5 | LOCAL_CFLAGS := -DANDROID_NDK \
6 | -DDISABLE_IMPORTGL
7 |
8 | LOCAL_MODULE := bbcmicro
9 |
10 | ifeq ($(TARGET_ARCH),arm)
11 | LOCAL_CFLAGS += -march=armv6t2 -O9 -D_ARM_
12 | LOCAL_SRC_FILES := 6502asm_arm.S
13 | endif
14 | ifeq ($(TARGET_ARCH),x86)
15 | LOCAL_CFLAGS += -m32
16 | LOCAL_SRC_FILES := 6502asm_x86.S
17 | endif
18 |
19 | LOCAL_SRC_FILES += \
20 | 6502.c \
21 | 8271.c \
22 | adc.c \
23 | disc.c \
24 | main.c \
25 | sound.c \
26 | ssd.c \
27 | sysvia.c \
28 | uservia.c \
29 | video.c
30 |
31 |
32 | LOCAL_LDLIBS += -lm -llog -ljnigraphics -lz -lGLESv2
33 |
34 | include $(BUILD_SHARED_LIBRARY)
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tab_bg_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
9 |
10 |
11 |
12 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listview.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
14 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listview_online.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
15 |
16 |
27 |
--------------------------------------------------------------------------------
/Beebdroid.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attr.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/picker_strings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 | New folder
20 | Failed to create folder
21 | Name
22 | Please select something first
23 | Permisson to access filesystem denied
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listitem_diskinfo.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
20 |
21 |
29 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/picker_actions.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nnf_activity_filepicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
23 |
24 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listitem_controllerinfo.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
20 |
21 |
29 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
15 |
16 |
17 |
25 |
26 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nnf_fragment_filepicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
17 |
18 |
25 |
26 |
27 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_loaddisk.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
13 |
17 |
18 |
19 |
26 |
27 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/InstalledDisks.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.ArrayList;
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | import common.Packageable;
11 |
12 | import android.content.Context;
13 |
14 | public class InstalledDisks {
15 | public static final int CURRENT_VERSION=1;
16 |
17 | public static List disks = new ArrayList();
18 | private static Map map = new HashMap();
19 |
20 | public static void load(Context context) {
21 | packageable.load(context, new File(context.getCacheDir(), "disks.dat"), CURRENT_VERSION);
22 | for (DiskInfo disk : disks) {
23 | map.put(disk.key, disk);
24 | }
25 | }
26 | public static int getCount() {
27 | return disks.size();
28 | }
29 | public static DiskInfo getByIndex(int index) {
30 | return disks.get(index);
31 | }
32 | public static DiskInfo getByKey(String key) {
33 | return map.get(key);
34 | }
35 | public static DiskInfo add(DiskInfo diskInfo) {
36 | disks.add(0, diskInfo);
37 | map.put(diskInfo.key, diskInfo);
38 | packageable.save();
39 | return diskInfo;
40 | }
41 |
42 | static Packageable packageable = new Packageable() {
43 | @Override
44 | public void readFromPackage(PackageInputStream in) throws IOException {
45 | disks = in.readPackageableList(DiskInfo.class);
46 | }
47 |
48 | @Override
49 | public void writeToPackage(PackageOutputStream out) throws IOException {
50 | out.writePackageableList(disks);
51 | }
52 | };
53 |
54 |
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nnf_dialog_folder_name.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
23 |
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/AboutActivity.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.view.Window;
9 | import android.view.View.OnClickListener;
10 | import android.widget.Button;
11 | import android.widget.CheckBox;
12 |
13 | public class AboutActivity extends Activity {
14 | private static final String TAG="AboutActivity";
15 | CheckBox box;
16 |
17 | @Override
18 | public void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | Log.d(TAG, "onCreate");
21 |
22 | requestWindowFeature(Window.FEATURE_NO_TITLE);
23 | setContentView(R.layout.activity_about);
24 | }
25 | @Override
26 | public void onStart() {
27 | super.onStart();
28 | final int aboutBoxStatus = UserPrefs.getAboutScreenCheckbox(this);
29 |
30 | if (aboutBoxStatus == UserPrefs.ABOUTSCREEN_FIRST_EVER) {
31 | // don't show the "show next time" checkbox on the splashscreen the very first time ever that we show it;
32 | // instead, remember that next time we will show the checkbox
33 | UserPrefs.setAboutScreenCheckbox(getApplicationContext(), UserPrefs.ABOUTSCREEN_SHOW);
34 | }
35 | else {
36 | // show the "show next time" checkbox on the splashscreen
37 | box = (CheckBox)findViewById(R.id.showNextTime);
38 | box.setVisibility(View.VISIBLE);
39 | box.setChecked(aboutBoxStatus == UserPrefs.ABOUTSCREEN_SHOW);
40 | }
41 |
42 | Button btnOK = (Button)findViewById(R.id.button_ok);
43 | btnOK.setOnClickListener(new OnClickListener() {
44 | @Override
45 | public void onClick(View v) {
46 | if (box != null) {
47 | UserPrefs.setAboutScreenCheckbox(v.getContext(), box.isChecked() ? UserPrefs.ABOUTSCREEN_SHOW : UserPrefs.ABOUTSCREEN_HIDE);
48 | }
49 | AboutActivity.this.finish();
50 | }
51 | });
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | import org.apache.tools.ant.taskdefs.condition.Os
2 |
3 | apply plugin: 'com.android.application'
4 |
5 | android {
6 | compileSdkVersion 23
7 | buildToolsVersion '23.0'
8 | defaultConfig {
9 | applicationId "com.littlefluffytoys.beebdroid"
10 | targetSdkVersion 23
11 | minSdkVersion 13
12 | }
13 | useLibrary 'org.apache.http.legacy'
14 | sourceSets.main {
15 | jniLibs.srcDir 'src/main/libs' //set .so files location to libs instead of jniLibs
16 | jni.srcDirs = [] //disable automatic ndk-build call
17 | }
18 | // add a task that calls regular ndk-build(.cmd) script from app directory
19 | task ndkBuild(type: Exec) {
20 | if (Os.isFamily(Os.FAMILY_WINDOWS)) {
21 | commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
22 | } else {
23 | commandLine '/Users/reuben/android/sdk/ndk-bundle/ndk-build', '-C', file('src/main').absolutePath
24 | }
25 | }
26 | // add this task as a dependency of Java compilation
27 | tasks.withType(JavaCompile) {
28 | compileTask -> compileTask.dependsOn ndkBuild
29 | }
30 | buildTypes {
31 | release {
32 | minifyEnabled false
33 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
34 | }
35 | }
36 | productFlavors {
37 | ouya {
38 | minSdkVersion 14
39 | dependencies {
40 | compile 'ouya:ouya-sdk:+' // You can replace "+" with a specific version number
41 | }
42 | }
43 | }
44 | }
45 |
46 | dependencies {
47 | compile 'com.android.support:appcompat-v7:23.0.1'
48 | compile 'com.android.support:recyclerview-v7:23.0.1'
49 | compile 'com.android.support:support-annotations:23.0.1'
50 | compile 'com.android.support:support-v13:23.0.1'
51 | compile 'com.android.support:support-v4:23.0.1'
52 | }
53 |
54 | repositories {
55 | maven {
56 | url "http://maven.ouya.tv/"
57 | }
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_beebdroid.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
19 |
30 |
31 |
32 |
33 |
39 |
40 |
47 |
48 |
53 |
54 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-land/activity_beebdroid.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
19 |
20 |
21 |
26 |
31 |
32 |
37 |
38 |
43 |
44 |
45 |
46 |
47 |
48 |
57 |
58 |
59 |
65 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listitem_savedgame.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
18 |
27 |
37 |
38 |
48 |
60 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/jni/adc.c:
--------------------------------------------------------------------------------
1 | /*B-em v2.1 by Tom Walker
2 | ADC emulation*/
3 |
4 | #include "main.h"
5 |
6 | int joy1x,joy1y,joy2x,joy2y;
7 |
8 | uint8_t adcstatus,adchigh,adclow,adclatch;
9 | int adcconvert;
10 |
11 | uint8_t readadc(uint16_t addr)
12 | {
13 | switch (addr&3)
14 | {
15 | case 0:
16 | return adcstatus;
17 | break;
18 | case 1:
19 | return adchigh;
20 | break;
21 | case 2:
22 | return adclow;
23 | break;
24 | }
25 | return 0x40;
26 | }
27 |
28 | void writeadc(uint16_t addr, uint8_t val)
29 | {
30 | if (!(addr&3))
31 | {
32 | adclatch=val;
33 | adcconvert=60;
34 | adcstatus=(val&0xF)|0x80; /*Busy, converting*/
35 | // printf("ADC conversion - %02X\n",val);
36 | }
37 | }
38 |
39 | void polladc()
40 | {
41 | /*
42 | uint32_t val;
43 | joy1x=joy1y=0;
44 | switch (adcstatus&3)
45 | {
46 | case 0: val=(128-joy[0].stick[0].axis[0].pos)*256; break;
47 | case 1: val=(128-joy[0].stick[0].axis[1].pos)*256; break;
48 | case 2: val=(128-joy[1].stick[0].axis[0].pos)*256; break;
49 | case 3: val=(128-joy[1].stick[0].axis[1].pos)*256; break;
50 | }
51 | if (val>0xFFFF) val=0xFFFF;
52 | if (val<0) val=0;
53 | adcstatus=(adcstatus&0xF)|0x40; //Not busy, conversion complete
54 | adcstatus|=(val&0xC000)>>10;
55 | adchigh=val>>8;
56 | adclow=val&0xFF;
57 | syscb1();
58 | */
59 | }
60 |
61 | void initadc()
62 | {
63 | adcstatus=0x40; /*Not busy, conversion complete*/
64 | adchigh=adclow=adclatch=0;
65 | adcconvert=0;
66 | //rjh install_joystick(JOY_TYPE_AUTODETECT);
67 | }
68 |
69 | void saveadcstate(FILE *f)
70 | {
71 | putc(adcstatus,f);
72 | putc(adclow,f);
73 | putc(adchigh,f);
74 | putc(adclatch,f);
75 | putc(adcconvert,f);
76 | }
77 |
78 | void loadadcstate(FILE *f)
79 | {
80 | adcstatus=getc(f);
81 | adclow=getc(f);
82 | adchigh=getc(f);
83 | adclatch=getc(f);
84 | adcconvert=getc(f);
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nnf_filepicker_listitem_dir.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
30 |
31 |
32 |
42 |
43 |
55 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nnf_filepicker_listitem_checkable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
30 |
31 |
32 |
33 |
43 |
44 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/ControllerInfo.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 |
9 | public class ControllerInfo {
10 |
11 | public String name;
12 | public ArrayList keyinfos = new ArrayList();
13 | public Map keyinfosMappedByAndroidKeycode = new HashMap();
14 | public boolean useDPad;
15 | public int androidKeycode;
16 |
17 | public class KeyInfo {
18 | String label;
19 | int labelIconId;
20 | String keylabel;
21 | int scancode;
22 | float xc,yc, width, height;
23 | }
24 |
25 | public static class TriggerAction {
26 | short pc_trigger;
27 | public TriggerAction(short pc_trigger) {
28 | this.pc_trigger = pc_trigger;
29 | }
30 | }
31 | public static class TriggerActionSetController extends TriggerAction {
32 | public TriggerActionSetController(short pc_trigger, ControllerInfo controllerInfo) {
33 | super(pc_trigger);
34 | this.controllerInfo = controllerInfo;
35 | }
36 | ControllerInfo controllerInfo;
37 | }
38 | public List triggers = new ArrayList();
39 |
40 | public void addTrigger(short pc, ControllerInfo switchToController) {
41 | TriggerActionSetController trigger = new TriggerActionSetController(pc, switchToController);
42 | triggers.add(trigger);
43 | }
44 |
45 |
46 | public void addKey(String label, String keylabel, float xc, float yc, float width, float height, int scancode) {
47 | addKey(label, keylabel, xc, yc, width, height, scancode, 0);
48 | }
49 | public void addKey(String label, String keylabel, float xc, float yc, float width, float height, int scancode, int androidKeycode) {
50 | addKey(label, keylabel, xc, yc, width, height, scancode, androidKeycode, 0);
51 | }
52 | public void addKey(String label, String keylabel, float xc, float yc, float width, float height, int scancode, int androidKeycode, int androidKeycode2) {
53 | KeyInfo key = new KeyInfo();
54 | key.label = label;
55 | key.keylabel = keylabel;
56 | key.xc = xc;
57 | key.yc = yc;
58 | key.width = width;
59 | key.height = height;
60 | key.scancode = scancode;
61 | keyinfos.add(key);
62 | if (androidKeycode != 0) {
63 | keyinfosMappedByAndroidKeycode.put(androidKeycode, key);
64 | }
65 | if (androidKeycode2 != 0) {
66 | keyinfosMappedByAndroidKeycode.put(androidKeycode2, key);
67 | }
68 | }
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 | 168dp
9 |
10 | Beebdroid
11 | the BBC Micro emulator
12 | by Little Fluffy Toys Ltd
13 | www.littlefluffytoys.mobi
14 | At LFT we grew up with the BBC Micro and we loved it, so we\'re bringing it back to the world! Written by LFT\'s CTO Reuben Scratton so he could play the games that LFT\'s CEO Kenton Price wrote when they were kids. Based on B-Em for Linux by Tom Walker.
15 | This FREE and OPEN SOURCE application is licensed under GNU General Public License v2.0 as detailed at http://www.gnu.org/licenses/gpl-2.0.html - we encourage others to assist us in developing Beebdroid further once the source code is publised on Github. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
16 | Beebdroid does not ship with any third party programs - these are accessed via third party websites which have hosted such programs for years. Should any licence holders object to third party websites providing such programs, please contact the third party websites in question. We are furthermore also happy to block the visibility of specific programs within Beebdroid upon written request from product licence holders. We are able to offer an in-app payment solution for your programs in such circumstances - please contact us for details.
17 | See our other apps
18 | Show this info on startup
19 | OK
20 | HINT: press MENU to load disks
21 | HINT: press MENU to switch keyboards
22 | HINT: if a game says \'Press SPACE to start\', just touch the screen!
23 | Switch keyboard
24 | Load Disk
25 | About
26 |
27 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
53 |
54 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nononsenseapps/filepicker/FileItemAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Jonas Kalderstam
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.nononsenseapps.filepicker;
19 |
20 | import android.support.v7.util.SortedList;
21 | import android.support.v7.widget.RecyclerView;
22 | import android.view.ViewGroup;
23 |
24 | /**
25 | * A simple adapter which also inserts a header item ".." to handle going up to the parent folder.
26 | * @param the type which is used, for example a normal java File object.
27 | */
28 | public class FileItemAdapter extends RecyclerView.Adapter {
29 |
30 | private final LogicHandler mLogic;
31 | private SortedList mList = null;
32 |
33 | public FileItemAdapter(LogicHandler logic) {
34 | this.mLogic = logic;
35 | }
36 |
37 | public void setList(SortedList list) {
38 | mList = list;
39 | notifyDataSetChanged();
40 | }
41 |
42 | @Override
43 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
44 | return mLogic.onCreateViewHolder(parent, viewType);
45 | }
46 |
47 | @Override
48 | @SuppressWarnings("unchecked")
49 | public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int headerPosition) {
50 | if (headerPosition == 0) {
51 | mLogic.onBindHeaderViewHolder((FilePickerFragment.HeaderViewHolder) viewHolder);
52 | } else {
53 | int pos = headerPosition - 1;
54 | mLogic.onBindViewHolder((FilePickerFragment.DirViewHolder) viewHolder, pos, mList.get(pos));
55 | }
56 | }
57 |
58 | @Override
59 | public int getItemViewType(int headerPosition) {
60 | if (0 == headerPosition) {
61 | return LogicHandler.VIEWTYPE_HEADER;
62 | } else {
63 | int pos = headerPosition - 1;
64 | return mLogic.getItemViewType(pos, mList.get(pos));
65 | }
66 | }
67 |
68 | @Override
69 | public int getItemCount() {
70 | if (mList == null) {
71 | return 0;
72 | }
73 |
74 | // header + count
75 | return 1 + mList.size();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/DiskInfo.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.net.URI;
6 |
7 | import org.json.JSONException;
8 | import org.json.JSONObject;
9 |
10 | import common.Packageable;
11 | import common.Utils;
12 |
13 |
14 |
15 | public class DiskInfo extends Packageable {
16 |
17 | String key;
18 | String title;
19 | String publisher;
20 | String coverUrl;
21 | String diskUrl;
22 | String bootCmd;
23 | //ControllerInfo defaultController;
24 | //TriggerAction[] triggers;
25 | //public boolean renderAt25fps;
26 |
27 | public DiskInfo() {
28 | }
29 | public DiskInfo(JSONObject obj) throws JSONException {
30 | key = obj.getString("k");
31 | title = obj.getString("t");
32 | publisher = obj.getString("pub");
33 | diskUrl = Utils.safeGetJsonString(obj, "disk");
34 | coverUrl = Utils.safeGetJsonString(obj, "cover");
35 | bootCmd = Utils.safeGetJsonString(obj, "boot");
36 | }
37 |
38 | public File getFile() {
39 | if (key.startsWith("file:/")) {
40 | return new File(URI.create(key));
41 | }
42 | return new File(App.app.getFilesDir(), key);
43 | }
44 |
45 | @Override
46 | public void readFromPackage(PackageInputStream in) throws IOException {
47 | key = in.readString();
48 | title = in.readString();
49 | publisher = in.readString();
50 | coverUrl = in.readString();
51 | diskUrl = in.readString();
52 | bootCmd = in.readString();
53 | }
54 |
55 | @Override
56 | public void writeToPackage(PackageOutputStream out) throws IOException {
57 | out.writeString(key);
58 | out.writeString(title);
59 | out.writeString(publisher);
60 | out.writeString(coverUrl);
61 | out.writeString(diskUrl);
62 | out.writeString(bootCmd);
63 | }
64 |
65 | /*public DiskInfo(String key, String title, String publisher, String bootCmd, ControllerInfo defaultController, TriggerAction[] triggers) {
66 | this.key = key;
67 | this.cover = key + ".jpg";
68 | this.title = title;
69 | this.publisher = publisher;
70 | this.diskImage = key;
71 | this.bootCmd = bootCmd;
72 | this.defaultController = defaultController;
73 | this.triggers = triggers;
74 | renderAt25fps = true;
75 | if (key.equals("starquake") || key.equals("hyper_viper")) {
76 | renderAt25fps = false;
77 | }
78 | diskMap.put(key, this);
79 | }*/
80 |
81 | /*public static class TriggerAction {
82 | short pc_trigger;
83 | public TriggerAction(short pc_trigger) {
84 | this.pc_trigger = pc_trigger;
85 | }
86 | }
87 | public static class TriggerActionSetController extends TriggerAction {
88 | public TriggerActionSetController(short pc_trigger, ControllerInfo controllerInfo) {
89 | super(pc_trigger);
90 | this.controllerInfo = controllerInfo;
91 | }
92 | ControllerInfo controllerInfo;
93 | }*/
94 |
95 |
96 |
97 |
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/Model.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.nio.ByteBuffer;
6 |
7 | import android.content.Context;
8 | import android.util.Log;
9 |
10 | public class Model {
11 |
12 | public static final int FLAG_I8271 = 1;
13 | public static final int FLAG_WD1770 = 2;
14 | public static final int FLAG_x65c02 = 4;
15 | public static final int FLAG_BPLUS = 8;
16 | public static final int FLAG_MASTER = 16;
17 | public static final int FLAG_SWRAM = 32;
18 | public static final int FLAG_MODELA = 64;
19 | public static final int FLAG_OS01 = 128;
20 | public static final int FLAG_COMPACT = 256;
21 |
22 | public static class ModelInfo {
23 | String name;
24 | int flags;
25 | String os;
26 | String roms;
27 | public ModelInfo(String name, String os, String roms, int flags) {
28 | this.name = name;
29 | this.os = os;
30 | this.roms = roms;
31 | this.flags = flags;
32 | }
33 |
34 | }
35 |
36 | ModelInfo info;
37 | //ByteBuffer os;
38 | //ByteBuffer rom;
39 | //ByteBuffer ram;
40 | ByteBuffer mem;
41 | ByteBuffer roms;
42 |
43 | public Model() {
44 | mem = ByteBuffer.allocateDirect(65536);
45 | roms = ByteBuffer.allocateDirect(16*16384);
46 | }
47 |
48 |
49 | public void loadAsset(Context context, ByteBuffer buff, int offset, String assetPath) {
50 | InputStream strm;
51 | try {
52 | strm = context.getAssets().open(assetPath);
53 | int size = strm.available();
54 | //Log.d("Beebdroid", "loadAsset " + assetPath + " is " + size + " bytes");
55 | byte[] localbuff = new byte[size];
56 | strm.read(localbuff, 0, size);
57 | strm.close();
58 | buff.position(offset);
59 | buff.put(localbuff);
60 | buff.position(0);
61 | } catch (IOException e) {
62 | e.printStackTrace();
63 | }
64 | }
65 | public void loadRoms(Context context, ModelInfo info) {
66 | this.info = info;
67 |
68 | // TODO: loadcmos(models[curmodel]);
69 |
70 | // OS ROM first.
71 | if (info.os != null) {
72 | loadAsset(context, mem, 0xc000, "roms/"+info.os);
73 | }
74 |
75 | // Load BASIC and other ROMs.
76 | String[] romPaths = info.roms.split(";");
77 | for (int i=0,c=15 ; i.
16 | */
17 |
18 | package com.nononsenseapps.filepicker;
19 |
20 | import android.net.Uri;
21 | import android.support.v4.content.Loader;
22 | import android.support.v7.util.SortedList;
23 | import android.support.v7.widget.RecyclerView;
24 | import android.view.ViewGroup;
25 |
26 | /**
27 | * An interface for the methods required to handle backend-specific stuff.
28 | */
29 | public interface LogicHandler {
30 |
31 | int VIEWTYPE_HEADER = 0;
32 | int VIEWTYPE_DIR = 1;
33 | int VIEWTYPE_CHECKABLE = 2;
34 |
35 | /**
36 | * Return true if the path is a directory and not a file.
37 | *
38 | * @param path
39 | */
40 | boolean isDir(final T path);
41 |
42 | /**
43 | * @param path
44 | * @return filename of path
45 | */
46 | String getName(final T path);
47 |
48 | /**
49 | * Convert the path to a URI for the return intent
50 | *
51 | * @param path
52 | * @return a Uri
53 | */
54 | Uri toUri(final T path);
55 |
56 | /**
57 | * Return the path to the parent directory. Should return the root if
58 | * from is root.
59 | *
60 | * @param from
61 | */
62 | T getParent(final T from);
63 |
64 | /**
65 | * @param path
66 | * @return the full path to the file
67 | */
68 | String getFullPath(final T path);
69 |
70 | /**
71 | * Convert the path to the type used.
72 | *
73 | * @param path
74 | */
75 | T getPath(final String path);
76 |
77 | /**
78 | * Get the root path (lowest allowed).
79 | */
80 | T getRoot();
81 |
82 | /**
83 | * Get a loader that lists the files in the current path,
84 | * and monitors changes.
85 | */
86 | Loader> getLoader();
87 |
88 | /**
89 | * Bind the header ".." which goes to parent folder.
90 | *
91 | * @param viewHolder
92 | */
93 | void onBindHeaderViewHolder(FilePickerFragment.HeaderViewHolder viewHolder);
94 |
95 | /**
96 | * Header is subtracted from the position
97 | *
98 | * @param parent
99 | * @param viewType
100 | * @return a view holder for a file or directory
101 | */
102 | RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType);
103 |
104 | /**
105 | * @param viewHolder to bind data from either a file or directory
106 | * @param position 0 - n, where the header has been subtracted
107 | * @param data
108 | */
109 | void onBindViewHolder(FilePickerFragment.DirViewHolder viewHolder, int position, T data);
110 |
111 | /**
112 | * @param position 0 - n, where the header has been subtracted
113 | * @param data
114 | * @return an integer greater than 0
115 | */
116 | int getItemViewType(int position, T data);
117 | }
118 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/ControllerView.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 |
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.RectF;
7 | import android.util.AttributeSet;
8 | import android.view.MotionEvent;
9 |
10 | public class ControllerView extends TouchpadsView implements DPad.Listener {
11 |
12 | public ControllerView(Context context, AttributeSet attrs) {
13 | super(context, attrs);
14 | }
15 |
16 | ControllerInfo controllerInfo;
17 | DPad dpad;
18 | int dpadSize;
19 | int scancodeLeft;
20 | int scancodeRight;
21 | int scancodeUp;
22 | int scancodeDown;
23 |
24 | public void setController(ControllerInfo info) {
25 | controllerInfo = info;
26 |
27 | // Don't create visible keys on a Play
28 | if (beebdroid.isXperiaPlay) {
29 | return;
30 | }
31 |
32 | dpadSize = (int)Beebdroid.dp(160);
33 | dpad = null;
34 | if (info.useDPad) {
35 | dpad = new DPad(getContext());
36 | dpad.listener = this;
37 | requestLayout();
38 | }
39 | recreateKeys();
40 | }
41 |
42 | private void recreateKeys() {
43 | allkeys.clear();
44 | if (controllerInfo == null) {
45 | return;
46 | }
47 |
48 | int div = 4;
49 | if (Beebdroid.DP_SCREEN_WIDTH >= 500) { // big bastard screen
50 | div = 6;
51 | }
52 | float padwidth = Beebdroid.DP_SCREEN_WIDTH / div;
53 | float padheight = padwidth;
54 |
55 | int width = getWidth();
56 | int height = getHeight();
57 | for (ControllerInfo.KeyInfo keyinfo : controllerInfo.keyinfos) {
58 | Key key = new Key();
59 | key.scancode = keyinfo.scancode;
60 | key.label = keyinfo.label;
61 |
62 | float l = (keyinfo.xc<0) ? (width + keyinfo.xc*padwidth) : (keyinfo.xc*padwidth);
63 | float t = (keyinfo.yc<0) ? (height + keyinfo.yc*padheight) : (keyinfo.yc*padheight);
64 | key.bounds = new RectF(l, t, (l+padwidth*keyinfo.width), (t+padwidth*keyinfo.height));
65 |
66 | if (dpad != null) {
67 | if (keyinfo.label.equals("Left")) {scancodeLeft = keyinfo.scancode; continue;}
68 | if (keyinfo.label.equals("Right")) {scancodeRight = keyinfo.scancode; continue;}
69 | if (keyinfo.label.equals("Up")) {scancodeUp = keyinfo.scancode; continue;}
70 | if (keyinfo.label.equals("Down")) {scancodeDown = keyinfo.scancode; continue;}
71 | }
72 |
73 | allkeys.add(key);
74 |
75 | }
76 | invalidate();
77 | }
78 |
79 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
80 | super.onLayout(changed, l, t, r, b);
81 | if (dpad != null) {
82 | dpad.onLayout(l, b-dpadSize, l+dpadSize, b);
83 | //dpad.onLayout(r-dpadSize, b-dpadSize, r, b);
84 | }
85 | recreateKeys();
86 | }
87 |
88 |
89 | @Override
90 | public void draw(Canvas canvas) {
91 | if (beebdroid.isXperiaPlay) {
92 | return;
93 | }
94 | super.draw(canvas);
95 | if(dpad != null) {
96 | dpad.draw(canvas);
97 | }
98 | }
99 |
100 | @Override
101 | public boolean onTouchEvent(MotionEvent event) {
102 |
103 | // Dpad
104 | if (dpad != null) {
105 | if (dpad.onTouchEvent(event)) {
106 | //invalidate();
107 | return true;
108 | }
109 | }
110 |
111 | return super.onTouchEvent(event);
112 | }
113 |
114 |
115 |
116 | //
117 | // DPadView.Listener
118 | //
119 | @Override
120 | public void onLeft(boolean pressed) {
121 | beebdroid.bbcKeyEvent(scancodeLeft, 0, pressed?1:0);
122 | invalidate();
123 | }
124 | @Override
125 | public void onUp(boolean pressed) {
126 | beebdroid.bbcKeyEvent(scancodeUp, 0, pressed?1:0);
127 | invalidate();
128 | }
129 | @Override
130 | public void onRight(boolean pressed) {
131 | beebdroid.bbcKeyEvent(scancodeRight, 0, pressed?1:0);
132 | invalidate();
133 | }
134 | @Override
135 | public void onDown(boolean pressed) {
136 | beebdroid.bbcKeyEvent(scancodeDown, 0, pressed?1:0);
137 | invalidate();
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/UserPrefs.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, Little Fluffy Toys Ltd
3 | * All rights reserved.
4 | */
5 | package com.littlefluffytoys.beebdroid;
6 |
7 | import java.util.Locale;
8 |
9 | import android.content.Context;
10 | import android.content.SharedPreferences;
11 | import android.preference.PreferenceActivity;
12 | import android.preference.PreferenceManager;
13 |
14 | public class UserPrefs extends PreferenceActivity {
15 |
16 | private static final String TAG="UserPrefs";
17 |
18 | public static final String PREFKEY_ABOUT_CHECKBOX = "AboutCheckbox";
19 | public static final String PREFKEY_GRANDFATHERED_IN = "GrandfatheredIn";
20 |
21 | public static final int ABOUTSCREEN_FIRST_EVER = 0;
22 | public static final int ABOUTSCREEN_SHOW = 1;
23 | public static final int ABOUTSCREEN_HIDE = 2;
24 |
25 | public static int aboutScreenCheckbox = ABOUTSCREEN_FIRST_EVER;
26 |
27 | public static int getAboutScreenCheckbox(Context context) {
28 | return PreferenceManager.getDefaultSharedPreferences(context).getInt(PREFKEY_ABOUT_CHECKBOX, ABOUTSCREEN_FIRST_EVER);
29 | }
30 | public static void setAboutScreenCheckbox(Context context, int value) {
31 | aboutScreenCheckbox = value;
32 | putInt(context, UserPrefs.PREFKEY_ABOUT_CHECKBOX, aboutScreenCheckbox);
33 | }
34 |
35 | public static void hideSplashScreen(Context context) {
36 | setAboutScreenCheckbox(context, ABOUTSCREEN_HIDE);
37 | }
38 |
39 | public static boolean shouldShowSplashScreen(Context context) {
40 | return (getAboutScreenCheckbox(context) != ABOUTSCREEN_HIDE);
41 | }
42 |
43 | public static void setGrandfatheredIn(Context context, boolean value) {
44 | putBoolean(context, UserPrefs.PREFKEY_GRANDFATHERED_IN, value);
45 | }
46 | static int safeGetPrefsInt(SharedPreferences prefs, String key, int defaultVal) {
47 | // This function is stupidly named. The preference must be stored as a string, not an integer.
48 | // Be absolutely 100% certain sure that your preference is stored as a string not an integer,
49 | // else you have an epic runtime fail
50 | return Integer.parseInt(prefs.getString(key, String.valueOf(defaultVal)));
51 | }
52 | static float safeGetPrefsFloat(SharedPreferences prefs, String key, float defaultVal) {
53 | int i = safeGetPrefsInt(prefs, key, (int)(100 * defaultVal));
54 | return ((float)i)/100f;
55 | }
56 |
57 | static void refresh(Context context) {
58 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
59 | aboutScreenCheckbox = prefs.getInt(PREFKEY_ABOUT_CHECKBOX, ABOUTSCREEN_FIRST_EVER);
60 |
61 | }
62 |
63 | static int getInt(Context context, String key, int defaultVal) {
64 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
65 | int intValue = prefs.getInt(key, defaultVal);
66 | prefs = null;
67 | return intValue;
68 | }
69 | static void putInt(Context context, String key, int val) {
70 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
71 | SharedPreferences.Editor editor = prefs.edit();
72 | editor.putInt(key, val);
73 | editor.commit();
74 | editor = null;
75 | prefs = null;
76 | }
77 | static void putLong(Context context, String key, long val) {
78 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
79 | SharedPreferences.Editor editor = prefs.edit();
80 | editor.putLong(key, val);
81 | editor.commit();
82 | editor = null;
83 | prefs = null;
84 | }
85 | static void putBoolean(Context context, String key, boolean val) {
86 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
87 | SharedPreferences.Editor editor = prefs.edit();
88 | editor.putBoolean(key, val);
89 | editor.commit();
90 | editor = null;
91 | prefs = null;
92 | }
93 | static void putString(Context context, String key, String val) {
94 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
95 | SharedPreferences.Editor editor = prefs.edit();
96 | editor.putString(key, val);
97 | editor.commit();
98 | editor = null;
99 | prefs = null;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
21 |
22 |
27 |
28 |
37 |
38 |
47 |
48 |
55 |
56 |
64 |
65 |
66 |
67 |
68 |
69 |
74 |
75 |
80 |
81 |
89 |
90 |
98 |
99 |
107 |
108 |
109 |
110 |
111 |
112 |
121 |
122 |
126 |
127 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nononsenseapps/filepicker/NewItemFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Jonas Kalderstam
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.nononsenseapps.filepicker;
19 |
20 |
21 | import android.app.Activity;
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import android.support.annotation.NonNull;
26 | import android.support.v4.app.DialogFragment;
27 | import android.support.v7.app.AlertDialog;
28 | import android.text.Editable;
29 | import android.text.TextWatcher;
30 | import android.view.View;
31 | import android.widget.Button;
32 | import android.widget.EditText;
33 | import com.littlefluffytoys.beebdroid.R;
34 |
35 | public abstract class NewItemFragment extends DialogFragment {
36 |
37 | private OnNewFolderListener listener = null;
38 |
39 | public NewItemFragment() {
40 | super();
41 | }
42 |
43 | public void setListener(final OnNewFolderListener listener) {
44 | this.listener = listener;
45 | }
46 |
47 | @Override
48 | public void onAttach(Activity activity) {
49 | super.onAttach(activity);
50 | }
51 |
52 | @NonNull
53 | @Override
54 | public Dialog onCreateDialog(Bundle savedInstanceState) {
55 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
56 | builder.setView(R.layout.nnf_dialog_folder_name)
57 | .setTitle(R.string.nnf_new_folder)
58 | .setNegativeButton(android.R.string.cancel,
59 | null)
60 | .setPositiveButton(android.R.string.ok,
61 | null);
62 |
63 | final AlertDialog dialog = builder.create();
64 |
65 | dialog.setOnShowListener(new DialogInterface.OnShowListener() {
66 | @Override
67 | public void onShow(DialogInterface dialog1) {
68 | final AlertDialog dialog = (AlertDialog) dialog1;
69 | final EditText editText = (EditText) dialog.findViewById(R.id.edit_text);
70 |
71 | Button cancel = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
72 | cancel.setOnClickListener(new View.OnClickListener() {
73 |
74 | @Override
75 | public void onClick(View view) {
76 | dialog.cancel();
77 | }
78 | });
79 |
80 | final Button ok = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
81 | // Start disabled
82 | ok.setEnabled(false);
83 | ok.setOnClickListener(new View.OnClickListener() {
84 |
85 | @Override
86 | public void onClick(View view) {
87 | String itemName = editText.getText().toString();
88 | if (validateName(itemName)) {
89 | if (listener != null) {
90 | listener.onNewFolder(itemName);
91 | }
92 | dialog.dismiss();
93 | }
94 | }
95 | });
96 |
97 | editText.addTextChangedListener(new TextWatcher() {
98 | @Override
99 | public void beforeTextChanged(final CharSequence s, final int start,
100 | final int count, final int after) {
101 | }
102 |
103 | @Override
104 | public void onTextChanged(final CharSequence s, final int start,
105 | final int before, final int count) {
106 | }
107 |
108 | @Override
109 | public void afterTextChanged(final Editable s) {
110 | ok.setEnabled(validateName(s.toString()));
111 | }
112 | });
113 | }
114 | });
115 |
116 |
117 | return dialog;
118 | }
119 |
120 | protected abstract boolean validateName(final String itemName);
121 |
122 | public interface OnNewFolderListener {
123 | /**
124 | * Name is validated to be non-null, non-empty and not containing any
125 | * slashes.
126 | *
127 | * @param name The name of the folder the user wishes to create.
128 | */
129 | void onNewFolder(final String name);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/BeebKeys.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | public class BeebKeys {
4 | /*
5 | * BBC Model B Keyboard : taken from http://www.flickr.com/photos/39013214@N03/5660684665/sizes/o/in/photostream/
6 |
7 | 0 1 2 3 4 5 6 7 8 9
8 | ----------------------------------------------
9 | 0x70 ESC F1 F2 F3 F5 F6 F8 F9 \| right
10 | 0x10 Q 3 4 5 F4 8 F7 -= ^~ left
11 | 0x20 F0 W E T 7 I 9 0 _ down
12 | 0x30 1 2 D R 6 U O P [( up
13 | 0x40 CAP A X F Y J K @ :* RET
14 | 0x50 SLC S C G H N L ;+ ]) DEL
15 | 0x60 TAB Z SPC V B M ,< .> /? CPY
16 | */
17 |
18 | public static final int BBCKEY_BREAK = 0xaa;
19 | // 0x00
20 | public static final int BBCKEY_SHIFT = 0x100;
21 | public static final int BBCKEY_CTRL = 0x01;
22 | // 0x10 Q 3 4 5 F4 8 F7 -= ^~
23 | public static final int BBCKEY_Q = 0x10;
24 | public static final int BBCKEY_3 = 0x11;
25 | public static final int BBCKEY_4 = 0x12;
26 | public static final int BBCKEY_5 = 0x13;
27 | public static final int BBCKEY_F4 = 0x14;
28 | public static final int BBCKEY_8 = 0x15;
29 | public static final int BBCKEY_F7 = 0x16;
30 | public static final int BBCKEY_MINUS = 0x17;
31 | public static final int BBCKEY_EQUALS = 0x117;
32 | public static final int BBCKEY_TILDE = 0x118;
33 | public static final int BBCKEY_CARET = 0x18;
34 | public static final int BBCKEY_ARROW_LEFT = 0x19;
35 | // 0x20 F0 W E T 7 I 9 0 _
36 | public static final int BBCKEY_F0 = 0x20;
37 | public static final int BBCKEY_W = 0x21;
38 | public static final int BBCKEY_E = 0x22;
39 | public static final int BBCKEY_T = 0x23;
40 | public static final int BBCKEY_7 = 0x24;
41 | public static final int BBCKEY_I = 0x25;
42 | public static final int BBCKEY_9 = 0x26;
43 | public static final int BBCKEY_0 = 0x27;
44 | public static final int BBCKEY_UNDERSCORE = 0x28;
45 | public static final int BBCKEY_POUND = 0x128;
46 | public static final int BBCKEY_ARROW_DOWN = 0x29;
47 | // 0x30 1 2 O R 6 U O P [(
48 | public static final int BBCKEY_1 = 0x30;
49 | public static final int BBCKEY_2 = 0x31;
50 | public static final int BBCKEY_D = 0x32;
51 | public static final int BBCKEY_R = 0x33;
52 | public static final int BBCKEY_6 = 0x34;
53 | public static final int BBCKEY_U = 0x35;
54 | public static final int BBCKEY_O = 0x36;
55 | public static final int BBCKEY_P = 0x37;
56 | public static final int BBCKEY_BRACKET_LEFT = 0x138;
57 | public static final int BBCKEY_BRACKET_LEFT_SQ = 0x38;
58 | public static final int BBCKEY_ARROW_UP = 0x39;
59 | // 0x40 CAP A X F Y J K @ :*
60 | public static final int BBCKEY_CAPS = 0x40;
61 | public static final int BBCKEY_A = 0x41;
62 | public static final int BBCKEY_X = 0x42;
63 | public static final int BBCKEY_F = 0x43;
64 | public static final int BBCKEY_Y = 0x44;
65 | public static final int BBCKEY_J = 0x45;
66 | public static final int BBCKEY_K = 0x46;
67 | public static final int BBCKEY_AT = 0x47;
68 | public static final int BBCKEY_COLON = 0x48;
69 | public static final int BBCKEY_STAR = 0x148;
70 | public static final int BBCKEY_ENTER = 0x49;
71 | // 0x50 SLC S C G H N L ;+ ])
72 | public static final int BBCKEY_SHIFTLOCK = 0x50;
73 | public static final int BBCKEY_S = 0x51;
74 | public static final int BBCKEY_C = 0x52;
75 | public static final int BBCKEY_G = 0x53;
76 | public static final int BBCKEY_H = 0x54;
77 | public static final int BBCKEY_N = 0x55;
78 | public static final int BBCKEY_L = 0x56;
79 | public static final int BBCKEY_SEMICOLON = 0x57;
80 | public static final int BBCKEY_PLUS = 0x157;
81 | public static final int BBCKEY_BRACKET_RIGHT = 0x158;
82 | public static final int BBCKEY_BRACKET_RIGHT_SQ = 0x58;
83 | public static final int BBCKEY_DELETE = 0x59;
84 | // 0x60 TAB Z SPC V B M ,< .> /?
85 | public static final int BBCKEY_TAB = 0x60;
86 | public static final int BBCKEY_Z = 0x61;
87 | public static final int BBCKEY_SPACE = 0x62;
88 | public static final int BBCKEY_V = 0x63;
89 | public static final int BBCKEY_B = 0x64;
90 | public static final int BBCKEY_M = 0x65;
91 | public static final int BBCKEY_COMMA = 0x66;
92 | public static final int BBCKEY_LESS_THAN = 0x166;
93 | public static final int BBCKEY_PERIOD = 0x67;
94 | public static final int BBCKEY_MORE_THAN = 0x167;
95 | public static final int BBCKEY_SLASH = 0x68;
96 | public static final int BBCKEY_QUESTIONMARK = 0x168;
97 | public static final int BBCKEY_COPY = 0x69;
98 | // 0x70 ESC F1 F2 F3 F5 F6 F8 F9 \|
99 | public static final int BBCKEY_ESCAPE = 0x70;
100 | public static final int BBCKEY_F1 = 0x71;
101 | public static final int BBCKEY_F2 = 0x72;
102 | public static final int BBCKEY_F3 = 0x73;
103 | public static final int BBCKEY_F5 = 0x74;
104 | public static final int BBCKEY_F6 = 0x75;
105 | public static final int BBCKEY_F8 = 0x76;
106 | public static final int BBCKEY_F9 = 0x77;
107 | public static final int BBCKEY_BACKSLASH = 0x78;
108 | public static final int BBCKEY_ARROW_RIGHT = 0x79;
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/app/src/main/jni/main.h:
--------------------------------------------------------------------------------
1 | /*
2 | * main.h
3 | *
4 | *
5 | * Written by Reuben Scratton, based on original code by Tom Walker
6 | *
7 | */
8 | #ifndef MAIN_H_INCLUDED
9 | #define MAIN_H_INCLUDED
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | typedef signed int fixed;
21 |
22 | typedef struct BITMAP {
23 | int width;
24 | int height;
25 | int bpp;
26 | int stride;
27 | unsigned char* pixels;
28 | } BITMAP;
29 |
30 | BITMAP *create_bitmap(int width, int height);
31 |
32 | #define RED(x) (x&0xff)
33 | #define GREEN(x) ((x&0xff00)>>8)
34 | #define BLUE(x) ((x&0xff0000)>>16)
35 |
36 |
37 |
38 | #define LOG_TAG "beebdroid"
39 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
40 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
41 |
42 |
43 | void blit_to_screen(int source_x, int source_y, int width, int height);
44 |
45 |
46 | #define FLAG_C 1
47 | #define FLAG_Z 2
48 | #define FLAG_I 4
49 | #define FLAG_D 8
50 | #define FLAG_V 0x40
51 | #define FLAG_N 0x80
52 |
53 | typedef struct {
54 | uint8_t* mem; // +0
55 | uint16_t pc; // +4
56 | uint8_t a; // +6
57 | uint8_t x; // +7
58 | uint8_t y; // +8
59 | uint8_t s; // +9
60 | uint8_t p; // +10
61 | uint8_t unused; //
62 | int interrupt; // +12
63 | int nmi; // +16
64 | int takeint; // +20
65 | int cycles; // +24
66 | uint16_t pc_trigger_hit; //+28
67 | uint16_t pc_triggers[4]; //+30
68 | int cycles2; // +38
69 | } M6502;
70 |
71 | extern M6502* the_cpu;
72 |
73 | extern uint8_t *roms;
74 | extern int swram[16];
75 | extern int motorspin;
76 | extern int fdctime;
77 | extern int motoron;
78 | extern int disctime;
79 | extern int frames;
80 |
81 | typedef struct VIA
82 | {
83 | uint8_t ora,orb,ira,irb;
84 | uint8_t ddra,ddrb;
85 | uint8_t sr;
86 | uint32_t t1l,t2l;
87 | int t1c,t2c;
88 | uint8_t acr,pcr,ifr,ier;
89 | int t1hit,t2hit;
90 | uint8_t porta,portb;
91 | int ca1,ca2;
92 | } VIA;
93 | extern VIA sysvia,uservia;
94 |
95 | extern int scrsize;
96 |
97 | void (*fdccallback)();
98 | void (*fdcdata)(uint8_t dat);
99 | void (*fdcspindown)();
100 | void (*fdcfinishread)();
101 | void (*fdcnotfound)();
102 | void (*fdcdatacrcerror)();
103 | void (*fdcheadercrcerror)();
104 | void (*fdcwriteprotect)();
105 | int (*fdcgetdata)(int last);
106 |
107 | extern int writeprot[2],fwriteprot[2];
108 |
109 | void initvideo();
110 | void closevideo();
111 | void makemode7chars();
112 | void pollvideo(int clocks);
113 | uint8_t readcrtc(uint16_t addr);
114 | void writecrtc(uint16_t addr, uint8_t val);
115 | extern uint8_t crtc[32];
116 | extern int crtci;
117 | extern int hc,vc,sc;
118 | extern uint16_t ma;
119 |
120 |
121 | void reset6502();
122 | void exec6502();
123 |
124 | void writesysvia(uint16_t addr, uint8_t val);
125 | uint8_t readsysvia(uint16_t addr);
126 | void resetsysvia();
127 | void checkkeys();
128 | void clearkeys();
129 |
130 | void writeuservia(uint16_t addr, uint8_t val);
131 | uint8_t readuservia(uint16_t addr);
132 | void resetuservia();
133 |
134 | void ssd_reset();
135 | void ssd_load(int drive, unsigned char *img, int cb);
136 | void ssd_close(int drive);
137 | void dsd_load(int drive, unsigned char *img, int cb);
138 | void ssd_seek(int drive, int track);
139 | void ssd_readsector(int drive, int sector, int track, int side, int density);
140 | void ssd_writesector(int drive, int sector, int track, int side, int density);
141 | void ssd_readaddress(int drive, int sector, int side, int density);
142 | void ssd_format(int drive, int sector, int side, int density);
143 | void ssd_poll();
144 |
145 | void disc_reset();
146 | void disc_poll();
147 | void disc_seek(int drive, int track);
148 | void disc_readsector(int drive, int sector, int track, int side, int density);
149 | void disc_writesector(int drive, int sector, int track, int side, int density);
150 | void disc_readaddress(int drive, int track, int side, int density);
151 | void disc_format(int drive, int track, int side, int density);
152 |
153 | void reset8271();
154 | uint8_t read8271(uint16_t addr);
155 | void write8271(uint16_t addr, uint8_t val);
156 |
157 | void writecrtc(uint16_t addr, uint8_t val);
158 | void writeula(uint16_t addr, uint8_t val);
159 | extern uint8_t bakpal[16];
160 | extern uint8_t ulactrl;
161 |
162 |
163 | struct
164 | {
165 | void (*seek)(int drive, int track);
166 | void (*readsector)(int drive, int sector, int track, int side, int density);
167 | void (*writesector)(int drive, int sector, int track, int side, int density);
168 | void (*readaddress)(int drive, int track, int side, int density);
169 | void (*format)(int drive, int track, int side, int density);
170 | void (*poll)();
171 | } drives[2];
172 |
173 | int curdrive;
174 |
175 |
176 | extern int adcconvert;
177 | extern int joybutton[2];
178 |
179 | void initsound();
180 |
181 | void initadc();
182 | uint8_t readadc(uint16_t addr);
183 | void writeadc(uint16_t addr, uint8_t val);
184 |
185 | extern int defaultwriteprot;
186 |
187 | extern int idecallback;
188 | extern int vidchange;
189 | extern int autoboot;
190 | extern int ideenable;
191 |
192 | #endif
193 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/DPad.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 |
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.util.Log;
9 | import android.view.MotionEvent;
10 | import android.view.VelocityTracker;
11 |
12 |
13 | public class DPad {
14 |
15 | public interface Listener {
16 | public void onLeft(boolean pressed);
17 | public void onUp(boolean pressed);
18 | public void onRight(boolean pressed);
19 | public void onDown(boolean pressed);
20 | }
21 | Listener listener;
22 | Drawable bkgnd;
23 | Drawable arrowUp, arrowDown, arrowLeft, arrowRight;
24 | Drawable joystick;
25 | boolean joystickMode;
26 |
27 | int current;
28 | Rect bounds = new Rect();
29 | int midx, midy;
30 | public static final int FLAG_LEFT = 1;
31 | public static final int FLAG_RIGHT = 2;
32 | public static final int FLAG_UP = 4;
33 | public static final int FLAG_DOWN = 8;
34 |
35 | public DPad(Context context) {
36 | bkgnd = context.getResources().getDrawable(R.drawable.dpad0);
37 | arrowUp = context.getResources().getDrawable(R.drawable.dpad_arrow_up);
38 | arrowDown = context.getResources().getDrawable(R.drawable.dpad_arrow_down);
39 | arrowLeft = context.getResources().getDrawable(R.drawable.dpad_arrow_left);
40 | arrowRight = context.getResources().getDrawable(R.drawable.dpad_arrow_right);
41 | joystickMode = false;
42 | velocityTracker = VelocityTracker.obtain();
43 | //joystick = context.getResources().getDrawable(R.drawable.joystick);
44 | }
45 |
46 | /*@Override
47 | protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
48 | super.onLayout(changed, left, top, right, bottom);
49 | }*/
50 | public void onLayout(int left, int top, int right, int bottom) {
51 | bounds.set(left, top, right, bottom);
52 | bkgnd.setBounds(left, top, right, bottom);
53 | int arrowWidth = (int)Beebdroid.dp(20);
54 | int arrowHeight = (int)Beebdroid.dp(28);
55 | int margin = (int)Beebdroid.dp(10);
56 | midx = left + (right-left)/2;
57 | midy = top + (bottom-top)/2;
58 | arrowUp.setBounds(midx - arrowWidth, margin, midx+arrowWidth, margin+arrowHeight);
59 | arrowLeft.setBounds(left+margin, midy-arrowWidth, left+margin+arrowHeight, midy+arrowWidth);
60 | arrowRight.setBounds(right - (margin+arrowHeight), midy-arrowWidth, right-margin, midy+arrowWidth);
61 | arrowDown.setBounds(midx - arrowWidth, bottom-(margin+arrowHeight), midx+arrowWidth, bottom-margin);
62 | }
63 |
64 |
65 | public void draw(Canvas canvas) {
66 | bkgnd.draw(canvas);
67 | if ((current & FLAG_UP) != 0) arrowUp.draw(canvas);
68 | if ((current & FLAG_DOWN) != 0) arrowDown.draw(canvas);
69 | if ((current & FLAG_LEFT) != 0) arrowLeft.draw(canvas);
70 | if ((current & FLAG_RIGHT) != 0) arrowRight.draw(canvas);
71 | }
72 |
73 | VelocityTracker velocityTracker;
74 |
75 | public boolean onTouchEventJoystick(MotionEvent event) {
76 | int actionCode = event.getActionMasked(); // action & MotionEvent.ACTION_MASK;
77 | int newFlags = 0;
78 | switch (actionCode) {
79 | case MotionEvent.ACTION_DOWN:
80 | velocityTracker.clear();
81 | velocityTracker.addMovement(event);
82 | return true;
83 | case MotionEvent.ACTION_MOVE:
84 | velocityTracker.addMovement(event);
85 | velocityTracker.computeCurrentVelocity(50);
86 | int vx = (int)velocityTracker.getXVelocity()/20;
87 | int vy = (int)velocityTracker.getYVelocity()/20;
88 | //Log.d("Joystick", "Velocity: x=" + vx + " y=" + vy);
89 | if (vx==0 && vy==0) { // no change of direction, do nothing
90 | return true;
91 | }
92 | if (vx<0) newFlags |= FLAG_LEFT;
93 | if (vx>0) newFlags |= FLAG_RIGHT;
94 | if (vy<0) newFlags |= FLAG_UP;
95 | if (vy>0) newFlags |= FLAG_DOWN;
96 | break;
97 | case MotionEvent.ACTION_UP:
98 | velocityTracker.clear();
99 | break;
100 | }
101 | processNewMovement(newFlags);
102 | return true;
103 | }
104 |
105 | public boolean onTouchEvent(MotionEvent event) {
106 | float x = event.getX();
107 | float y = event.getY();
108 | if (!bounds.contains((int)x, (int)y)) {
109 | return false;
110 | }
111 | if (joystickMode) {
112 | return onTouchEventJoystick(event);
113 | }
114 | int actionCode = event.getActionMasked(); // action & MotionEvent.ACTION_MASK;
115 | int newFlags = 0;
116 | switch (actionCode) {
117 | case MotionEvent.ACTION_DOWN:
118 | case MotionEvent.ACTION_MOVE:
119 | double da = 180+Math.toDegrees(Math.atan2(y-midy, x-midx));
120 | da = (da-22.5)/45;
121 | if (da<0) da+=360/45;
122 | int a = (int)da;
123 | if (a==0 || a==1 || a==2) newFlags |=FLAG_UP;
124 | if (a==2 || a==3 || a==4) newFlags |=FLAG_RIGHT;
125 | if (a==4 || a==5 || a==6) newFlags |=FLAG_DOWN;
126 | if (a==6 || a==7 || a==0) newFlags |=FLAG_LEFT;
127 | //Log.d("DPad", "angle " + (int)a);
128 | break;
129 | case MotionEvent.ACTION_UP:
130 | break;
131 | default:
132 | return false;
133 | }
134 | processNewMovement(newFlags);
135 | return true;
136 | }
137 |
138 | protected void processNewMovement(int newFlags) {
139 | int changes = newFlags ^ current;
140 | if (changes != 0) {
141 | if (listener != null) {
142 | if ((changes & FLAG_LEFT)!=0) listener.onLeft((newFlags &FLAG_LEFT) !=0);
143 | if ((changes & FLAG_RIGHT)!=0) listener.onRight((newFlags &FLAG_RIGHT) !=0);
144 | if ((changes & FLAG_UP)!=0) listener.onUp((newFlags &FLAG_UP) !=0);
145 | if ((changes & FLAG_DOWN)!=0) listener.onDown((newFlags &FLAG_DOWN) !=0);
146 | }
147 | current = newFlags;
148 | }
149 |
150 | }
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/SavedGameInfo.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.DataInputStream;
5 | import java.io.DataOutputStream;
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.util.ArrayList;
11 | import java.util.Collections;
12 | import java.util.Comparator;
13 |
14 | import android.content.Context;
15 | import android.graphics.Bitmap;
16 | import android.graphics.Bitmap.Config;
17 | import android.graphics.BitmapFactory;
18 | import android.graphics.Canvas;
19 | import android.graphics.Paint;
20 | import android.graphics.PorterDuff.Mode;
21 | import android.graphics.PorterDuffXfermode;
22 | import android.graphics.Rect;
23 | import android.graphics.Bitmap.CompressFormat;
24 | import android.graphics.RectF;
25 | import android.text.TextUtils;
26 | import android.util.Log;
27 | import android.widget.Toast;
28 |
29 |
30 | public class SavedGameInfo {
31 |
32 | public static SavedGameInfo current;
33 |
34 | public String filename;
35 | public DiskInfo diskInfo;
36 | public Bitmap thumbnail;
37 | public long offsetToMachineData;
38 | public long timestamp;
39 |
40 |
41 | public static ArrayList savedGames;
42 |
43 |
44 |
45 | public static void init(Context c) {
46 | savedGames = new ArrayList();
47 |
48 |
49 | File[] files = c.getFilesDir().listFiles();
50 | if (files == null) {
51 | return;
52 | }
53 | for (int i=0 ; i() {
97 | @Override
98 | public int compare(SavedGameInfo object1, SavedGameInfo object2) {
99 | return (int)(object2.timestamp - object1.timestamp);
100 | }
101 |
102 | });
103 | }
104 | }
105 |
106 | public static void delete(Context c, int index) {
107 | SavedGameInfo info = savedGames.get(index);
108 | c.deleteFile(info.filename);
109 | savedGames.remove(index);
110 | }
111 |
112 |
113 | public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
114 | Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
115 | bitmap.getHeight(), Config.ARGB_8888);
116 | Canvas canvas = new Canvas(output);
117 |
118 | final int color = 0xff424242;
119 | final Paint paint = new Paint();
120 | final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
121 | final RectF rectF = new RectF(rect);
122 | final float roundPx = Beebdroid.dp(16);
123 |
124 | paint.setAntiAlias(true);
125 | canvas.drawARGB(0, 0, 0, 0);
126 | paint.setColor(color);
127 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
128 |
129 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
130 | canvas.drawBitmap(bitmap, rect, rect, paint);
131 |
132 | return output;
133 | }
134 | //
135 | // save
136 | //
137 | public void save(Beebdroid beebdroid) {
138 | diskInfo = beebdroid.diskInfo;
139 |
140 | // Create thumbnail
141 | int thumbWidth = (int)Beebdroid.dp(160);
142 | int thumbHeight = (int)Beebdroid.dp(128);
143 | Bitmap bmp = Bitmap.createBitmap(800, 600, Bitmap.Config.RGB_565);
144 | int dims = beebdroid.bbcGetThumbnail(bmp);
145 | thumbnail = Bitmap.createBitmap(thumbWidth, thumbHeight, Config.ARGB_8888);
146 | Canvas canvas = new Canvas(thumbnail);
147 | Paint paint = new Paint();
148 | paint.setAntiAlias(true);
149 | paint.setFilterBitmap(true);
150 | Rect rc = new Rect(0,0,thumbWidth,thumbHeight);
151 | canvas.drawBitmap(bmp, new Rect(0,0,672,272), rc, paint);
152 | // Round the corners
153 | bmp.recycle();
154 | thumbnail = getRoundedCornerBitmap(thumbnail);
155 | // Cleanup
156 | bmp = null;
157 | System.gc();
158 |
159 | if (filename == null) {
160 | filename = "saved_" + Long.toString(System.currentTimeMillis());
161 | }
162 | try {
163 | //FileOutputStream fileOut = new FileOutputStream(new File(dir, filename)); //, Context.MODE_PRIVATE);
164 | FileOutputStream fileOut = beebdroid.openFileOutput(filename, Context.MODE_PRIVATE);
165 | DataOutputStream dout = new DataOutputStream(fileOut);
166 |
167 | // Start with version number
168 | dout.writeInt(1);
169 |
170 | // Disk name
171 | String diskName = (diskInfo==null) ? "" : diskInfo.key;
172 | dout.writeUTF(diskName);
173 |
174 | // Machine data, preceded by its length
175 | offsetToMachineData = fileOut.getChannel().position();
176 | byte[] buffer = new byte[65*1024];
177 | int cb = beebdroid.bbcSerialize(buffer);
178 | dout.writeInt(cb);
179 | dout.write(buffer, 0, cb);
180 |
181 | // Thumbnail image
182 | ByteArrayOutputStream bo = new ByteArrayOutputStream(16*1024);
183 | thumbnail.compress(CompressFormat.PNG, 0, bo);
184 | cb = bo.size();
185 | dout.write(bo.toByteArray(), 0, cb);
186 |
187 | dout.close();
188 | timestamp = System.currentTimeMillis();
189 | current = this;
190 | Toast.makeText(beebdroid, "Saved", Toast.LENGTH_SHORT).show();
191 | }
192 | catch (IOException ex) {
193 | String text = "Error saving state: " + ex;
194 | Toast.makeText(beebdroid, text, Toast.LENGTH_LONG).show();
195 | }
196 | }
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/app/src/main/java/common/Packageable.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedOutputStream;
5 | import java.io.DataInputStream;
6 | import java.io.DataOutputStream;
7 | import java.io.File;
8 | import java.io.FileInputStream;
9 | import java.io.FileNotFoundException;
10 | import java.io.FileOutputStream;
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.io.OutputStream;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import android.content.Context;
17 | import android.os.AsyncTask;
18 |
19 | /*
20 | * Packageable - a storage mechanism that's wayyyy faster than SQLite and Serializable
21 | */
22 |
23 | public abstract class Packageable {
24 | public abstract void readFromPackage(PackageInputStream in) throws IOException ;
25 | public abstract void writeToPackage(PackageOutputStream out) throws IOException ;
26 |
27 | private File file;
28 | private int currentVersion;
29 |
30 | public void load(Context context, File file, int currentVersion) {
31 | this.file = file;
32 | this.currentVersion = currentVersion;
33 | PackageInputStream in = null;
34 | try {
35 | in = new PackageInputStream(new FileInputStream(file));
36 | int version = in.readInt();
37 | if (version == currentVersion) {
38 | readFromPackage(in);
39 | }
40 | }
41 | catch (FileNotFoundException ex) { // no problem
42 | }
43 | catch (IOException e) {
44 | e.printStackTrace();
45 | }
46 | if (in != null) {
47 | in.close();
48 | }
49 | }
50 |
51 | public void save() {
52 | new AsyncTask() {
53 |
54 | @Override
55 | protected Integer doInBackground(Integer... params) {
56 | PackageOutputStream out = null;
57 | try {
58 | out = new PackageOutputStream(new FileOutputStream(file));
59 | out.writeInt(currentVersion);
60 | writeToPackage(out);
61 | }
62 | catch (FileNotFoundException ex) { // cant happen
63 | }
64 | catch (IOException e) {
65 | e.printStackTrace();
66 | }
67 | if (out != null) {
68 | out.close();
69 | }
70 | return 1;
71 | }
72 |
73 | }.execute();
74 | }
75 |
76 |
77 | public static final class PackageInputStream {
78 |
79 | private DataInputStream input;
80 |
81 | public PackageInputStream(InputStream in) {
82 | input = new DataInputStream(new BufferedInputStream(in));
83 | }
84 |
85 | public void close() {
86 | if (input != null) {
87 | try {
88 | input.close();
89 | }
90 | catch (IOException ex) {
91 | }
92 | input = null;
93 | }
94 | }
95 |
96 | // Primitives
97 | public final boolean readBoolean() throws IOException {
98 | return input.readBoolean();
99 | }
100 | public final int readInt() throws IOException {
101 | return input.readInt();
102 | }
103 | public final long readLong() throws IOException {
104 | return input.readLong();
105 | }
106 | public final long[] readLongArray() throws IOException {
107 | int c = input.readInt();
108 | if (c == -1) {
109 | return null;
110 | }
111 | long[] a = new long[c];
112 | for (int i=0 ; i T readPackageable(Class clazz) throws IOException {
127 | int i = input.readByte();
128 | if (i > 0) {
129 | try {
130 | T item = (T) clazz.newInstance();
131 | item.readFromPackage(this);
132 | return item;
133 | } catch (InstantiationException e) {
134 | e.printStackTrace();
135 | } catch (IllegalAccessException e) {
136 | e.printStackTrace();
137 | }
138 | }
139 | return null;
140 | }
141 | public final List readPackageableList(Class clazz) throws IOException {
142 | int N = readInt();
143 | if (N == -1) {
144 | return null;
145 | }
146 | ArrayList list = new ArrayList();
147 | while (N>0) {
148 | T item = readPackageable(clazz);
149 | list.add(item);
150 | N--;
151 | }
152 | return list;
153 | }
154 |
155 | }
156 |
157 |
158 |
159 |
160 | public static final class PackageOutputStream {
161 |
162 | private DataOutputStream output;
163 |
164 | public PackageOutputStream(OutputStream out) {
165 | output = new DataOutputStream(new BufferedOutputStream(out));
166 | }
167 |
168 | public void close() {
169 | if (output != null) {
170 | try {
171 | output.close();
172 | }
173 | catch (IOException ex) {
174 | }
175 | output = null;
176 | }
177 | }
178 |
179 | // Primitives
180 | public final void writeBoolean(boolean val) throws IOException {
181 | output.writeBoolean(val);
182 | }
183 | public final void writeInt(int val) throws IOException {
184 | output.writeInt(val);
185 | }
186 | public final void writeLong(long val) throws IOException {
187 | output.writeLong(val);
188 | }
189 | public final void writeLongArray(long[] val) throws IOException {
190 | if (val == null) {
191 | writeInt(-1);
192 | return;
193 | }
194 | writeInt(val.length);
195 | for (int i=0 ; i void writePackageableList(List val) throws IOException {
223 | if (val == null) {
224 | writeInt(-1);
225 | return;
226 | }
227 | int N = val.size();
228 | int i=0;
229 | writeInt(N);
230 | while (i < N) {
231 | Packageable item = val.get(i);
232 | writePackageable(item);
233 | i++;
234 | }
235 | }
236 |
237 | }
238 | }
--------------------------------------------------------------------------------
/app/src/main/jni/disc.c:
--------------------------------------------------------------------------------
1 | /*B-em v2.1 by Tom Walker
2 | Disc support (also some tape)*/
3 |
4 | #include "main.h"
5 |
6 | int motoron,fdctime,disctime,motorspin;
7 |
8 | struct
9 | {
10 | char *ext;
11 | void (*load)(int drive, unsigned char *img, int cb);
12 | void (*close)(int drive);
13 | int size;
14 | }
15 | loaders[]=
16 | {
17 | {"SSD",ssd_load,ssd_close, 80*10*256},
18 | {"DSD",dsd_load,ssd_close,2*80*10*256},
19 | //{"ADF",adf_load,adf_close, 80*16*256},
20 | //{"ADL",adl_load,adf_close,2*80*16*256},
21 | //{"FDI",fdi_load,fdi_close,-1},
22 | {0,0,0}
23 | };
24 |
25 | int driveloaders[2];
26 |
27 | void loaddisc(int drive, int loader, unsigned char* discimg, int cb)
28 | {
29 | driveloaders[drive]=loader;
30 | loaders[loader].load(drive, discimg, cb);
31 |
32 | /*f=fopen(fn,"rb");
33 | if (!f) return;
34 | fseek(f,-1,SEEK_END);
35 | c=ftell(f)+1;
36 | fclose(f);
37 | rpclog("Size %i\n",c);
38 | if (c==(800*1024)) // 800k ADFS/DOS - 80*2*5*1024
39 | {
40 | driveloaders[drive]=2;
41 | loaders[2].load(drive,fn);
42 | return;
43 | }
44 | if (c==(640*1024)) // 640k ADFS/DOS - 80*2*16*256
45 | {
46 | driveloaders[drive]=3;
47 | loaders[3].load(drive,fn);
48 | return;
49 | }
50 | if (c==(720*1024)) // 720k DOS - 80*2*9*512
51 | {
52 | driveloaders[drive]=3;
53 | adl_loadex(drive,fn,9,512,0);
54 | return;
55 | }
56 | if (c==(360*1024)) // 360k DOS - 40*2*9*512
57 | {
58 | driveloaders[drive]=3;
59 | adl_loadex(drive,fn,9,512,1);
60 | return;
61 | }
62 | if (c<=(200*1024)) // 200k DFS - 80*1*10*256
63 | {
64 | driveloaders[drive]=0;
65 | loaders[0].load(drive,fn);
66 | return;
67 | }
68 | if (c<=(400*1024)) // 400k DFS - 80*2*10*256
69 | {
70 | driveloaders[drive]=1;
71 | loaders[1].load(drive,fn);
72 | return;
73 | }*/
74 | }
75 |
76 | /*
77 | void newdisc(int drive, char *fn)
78 | {
79 | int c=0,d;
80 | FILE *f;
81 | char *p=(char*)get_extension(fn);
82 | while (loaders[c].ext)
83 | {
84 | if (!strcasecmp(p,loaders[c].ext) && loaders[c].size!=-1)
85 | {
86 | f=fopen(fn,"wb");
87 | for (d=0;d {
32 | protected static final String TAG="DownloadTask";
33 | protected String errorMessage;
34 | protected int httpCode;
35 |
36 | // Functions to be implemented by derived classes
37 | abstract protected HttpUriRequest getHttpRequest();
38 | abstract protected void onError(String errorText);
39 |
40 | protected boolean processStatusLine(HttpResponse response) {
41 | httpCode = response.getStatusLine().getStatusCode();
42 | Log.d(TAG, "got HTTP " + httpCode);
43 | if (httpCode != 200 && httpCode !=206) {
44 | if (httpCode == 403) {
45 | errorMessage = "Access Denied"; // urgh! can we be less forbidding?
46 | }
47 | else {
48 | errorMessage = "HTTP Error " + httpCode;
49 | }
50 | return false;
51 | }
52 | return true;
53 | }
54 |
55 | }
56 |
57 | //
58 | // DownloadTextTask - a background task for downloading relatively small
59 | // amounts of text.
60 | //
61 | abstract public static class DownloadTextTask extends DownloadTaskBase {
62 |
63 | protected String responseETag = "";
64 |
65 | // Functions to be implemented by derived classes
66 | abstract protected void onDownloadComplete(String str);
67 |
68 | @Override
69 | protected String doInBackground(String... params) {
70 | HttpClient client = new DefaultHttpClient();
71 | HttpUriRequest request = getHttpRequest();
72 | Log.d(TAG, request.getRequestLine().toString());
73 | try {
74 | HttpResponse response = client.execute(request);
75 | if (!processStatusLine(response)) {
76 | return null;
77 | }
78 | responseETag = "";
79 | if (response.containsHeader("ETag")) {
80 | responseETag = response.getFirstHeader("ETag").getValue();
81 | }
82 | String rv = Utils.getHttpResponseText(response);
83 | Log.d("DownloadTextTask", "Response text is:\n" + rv);
84 | return rv;
85 | }
86 | catch (UnknownHostException e) {
87 | errorMessage = "No network";
88 | }
89 | catch (IOException e) {
90 | errorMessage = "Error during download: " + e.getMessage();
91 | }
92 | return null;
93 | }
94 |
95 | @Override protected void onPostExecute(String str) {
96 | if (str == null) {
97 | if (TextUtils.isEmpty(errorMessage)) {
98 | errorMessage = "Unspecified error";
99 | }
100 | Log.e(TAG, errorMessage);
101 | onError(errorMessage);
102 | return;
103 | }
104 | onDownloadComplete(str);
105 | }
106 | }
107 |
108 |
109 |
110 | //
111 | // DownloadJsonTask - helper for downloading JSON
112 | //
113 | abstract public static class DownloadJsonTask extends DownloadTextTask {
114 |
115 | // Functions to be implemented by derived classes
116 | abstract protected void onDownloadJsonComplete(Object object) throws JSONException;
117 |
118 | // Parse the text response into JSON
119 | @Override
120 | protected final void onDownloadComplete(String str) {
121 | JSONTokener tokener = new JSONTokener(str);
122 | try {
123 | Object object = tokener.nextValue();
124 | if (object instanceof JSONObject) {
125 | onDownloadJsonComplete(object);
126 | }
127 | else if (object instanceof JSONArray) {
128 | onDownloadJsonComplete(object);
129 | }
130 | else {
131 | onError("JSON response is an unexpected data type");
132 | }
133 | } catch (JSONException e) {
134 | onError("JSONException while parsing response: " + e.getLocalizedMessage());
135 | }
136 | }
137 | }
138 |
139 |
140 |
141 | //
142 | // DownloadBinaryTask - a background task for downloading any size any kind of data
143 | //
144 | abstract public static class DownloadBinaryTask extends DownloadTaskBase {
145 | protected String localPath;
146 | protected long cbTotalSize = -1;
147 | protected long cbDownloaded = 0;
148 | protected boolean append;
149 | public String contentType;
150 |
151 | // Functions to be implemented by derived classes
152 | abstract protected void onDownloadComplete();
153 |
154 | // Constructor.
155 | public DownloadBinaryTask(String localPath, boolean append) {
156 | this.localPath = localPath;
157 | this.append = append;
158 | }
159 |
160 | @Override
161 | protected String doInBackground(String... params) {
162 | HttpClient client = new DefaultHttpClient();
163 | File outputFile=new File(localPath);
164 | HttpUriRequest request = getHttpRequest();
165 | long cbDownloaded = 0;
166 | if (outputFile.exists()) {
167 | if (!append) {
168 | outputFile.delete();
169 | }
170 | else {
171 | cbDownloaded = outputFile.length();
172 | Log.d(TAG, "Adding header: Range: " + cbDownloaded + "-");
173 | request.addHeader("Range", "bytes=" + Long.toString(cbDownloaded) + "-");
174 | }
175 | }
176 | try {
177 | HttpResponse response = client.execute(request);
178 | if (!processStatusLine(response)) {
179 | return null;
180 | }
181 | HttpEntity entity = response.getEntity();
182 | contentType = "";
183 | Header hdrContentType = response.getFirstHeader("Content-Type");
184 | if (hdrContentType != null) {
185 | contentType = hdrContentType.getValue();
186 | }
187 | if (entity != null) {
188 | byte[] sBuffer = new byte[16384];
189 | InputStream inputStream = entity.getContent();
190 | long cbThisDownloadSize = entity.getContentLength();
191 | cbTotalSize = cbDownloaded + cbThisDownloadSize;
192 | Log.d(TAG, "cbTotalSize is " + cbTotalSize);
193 | RandomAccessFile output = new RandomAccessFile(localPath, "rw");
194 | if (cbDownloaded > 0) {
195 | output.seek(cbDownloaded);
196 | }
197 | int readBytes = 0;
198 | while ((readBytes = inputStream.read(sBuffer)) != -1) {
199 | output.write(sBuffer, 0, readBytes);
200 | cbDownloaded += readBytes;
201 | publishProgress(cbDownloaded, cbTotalSize);
202 | if (isCancelled()) {
203 | break;
204 | }
205 | }
206 | output.close();
207 | entity.consumeContent();
208 | return "OK"; // success
209 | }
210 | }
211 | catch (IOException e2) {
212 | errorMessage = "Exception in download: " + e2.getLocalizedMessage();
213 | }
214 | return null;
215 | }
216 |
217 | @Override protected void onPostExecute(String str) {
218 | if (isCancelled()) {
219 | return;
220 | }
221 | if (str == null) {
222 | if (TextUtils.isEmpty(errorMessage)) {
223 | errorMessage = "Unspecified error";
224 | }
225 | Log.e(TAG, errorMessage);
226 | onError(errorMessage);
227 | return;
228 | }
229 | onDownloadComplete();
230 | }
231 | }
232 |
233 | }
234 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/Keyboard.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.util.ArrayList;
4 |
5 | import com.littlefluffytoys.beebdroid.TouchpadsView.Key;
6 |
7 | import android.content.Context;
8 | import android.graphics.Canvas;
9 | import android.graphics.RectF;
10 | import android.graphics.drawable.Drawable;
11 | import android.util.AttributeSet;
12 |
13 | public class Keyboard extends TouchpadsView {
14 |
15 | // The height of a row of keys
16 | private static final int ROWHEIGHT_SMALL = 36;
17 |
18 | // Shift modes
19 | public static final int SHIFTMODE_NORMAL = 0;
20 | public static final int SHIFTMODE_ONCE = 1;
21 | public static final int SHIFTMODE_LOCKED = 2;
22 | public int shiftMode;
23 | public boolean shiftActuallyHeld;
24 |
25 | // Shift LED drawables
26 | Drawable ledOn, ledOff;
27 |
28 | // The keyboard keys, arranged in rows
29 | public ArrayList rows = new ArrayList();
30 |
31 | public Keyboard(Context context, AttributeSet attrs) {
32 | super(context, attrs);
33 |
34 | ledOff = context.getResources().getDrawable(R.drawable.led_off);
35 | ledOn = context.getResources().getDrawable(R.drawable.led_on);
36 |
37 | addRow();
38 | add("TAB", null, 1f, BeebKeys.BBCKEY_TAB);
39 | add("f0", null, 1f, BeebKeys.BBCKEY_F0, 1);
40 | add("f1", null, 1f, BeebKeys.BBCKEY_F1, 1);
41 | add("f2", null, 1f, BeebKeys.BBCKEY_F2, 1);
42 | add("f3", null, 1f, BeebKeys.BBCKEY_F3, 1);
43 | add("f4", null, 1f, BeebKeys.BBCKEY_F4, 1);
44 | add("f5", null, 1f, BeebKeys.BBCKEY_F5, 1);
45 | add("f6", null, 1f, BeebKeys.BBCKEY_F6, 1);
46 | add("f7", null, 1f, BeebKeys.BBCKEY_F7, 1);
47 | add("f8", null, 1f, BeebKeys.BBCKEY_F8, 1);
48 | add("f9", null, 1f, BeebKeys.BBCKEY_F9, 1);
49 | add("BREAK", null, 1f, BeebKeys.BBCKEY_BREAK);
50 | addRow();
51 | add("ESC", null, 1f, BeebKeys.BBCKEY_ESCAPE);
52 | add("1", "!", 1f, BeebKeys.BBCKEY_1);
53 | add("2", "\"", 1f, BeebKeys.BBCKEY_2);
54 | add("3", "#", 1f, BeebKeys.BBCKEY_3);
55 | add("4", "$", 1f, BeebKeys.BBCKEY_4);
56 | add("5", "%", 1f, BeebKeys.BBCKEY_5);
57 | add("6", "&", 1f, BeebKeys.BBCKEY_6);
58 | add("7", "'", 1f, BeebKeys.BBCKEY_7);
59 | add("8", "(", 1f, BeebKeys.BBCKEY_8);
60 | add("9", ")", 1f, BeebKeys.BBCKEY_9);
61 | add("0", null, 1f, BeebKeys.BBCKEY_0);
62 | add("-", "=", 1f, BeebKeys.BBCKEY_MINUS);
63 | add("^", "~", 1f, BeebKeys.BBCKEY_CARET);
64 | add("\\", "|", 1f, BeebKeys.BBCKEY_BACKSLASH);
65 | addRow();
66 | add("Q", null, 1f, BeebKeys.BBCKEY_Q);
67 | add("W", null, 1f, BeebKeys.BBCKEY_W);
68 | add("E", null, 1f, BeebKeys.BBCKEY_E);
69 | add("R", null, 1f, BeebKeys.BBCKEY_R);
70 | add("T", null, 1f, BeebKeys.BBCKEY_T);
71 | add("Y", null, 1f, BeebKeys.BBCKEY_Y);
72 | add("U", null, 1f, BeebKeys.BBCKEY_U);
73 | add("I", null, 1f, BeebKeys.BBCKEY_I);
74 | add("O", null, 1f, BeebKeys.BBCKEY_O);
75 | add("P", null, 1f, BeebKeys.BBCKEY_P);
76 | add("@", null, 1f, BeebKeys.BBCKEY_AT);
77 | add("[", "{", 1f, BeebKeys.BBCKEY_BRACKET_LEFT_SQ);
78 | add("_", "\u00a3", 1f, BeebKeys.BBCKEY_UNDERSCORE);
79 | addRow();
80 | add("A", null, 1f, BeebKeys.BBCKEY_A);
81 | add("S", null, 1f, BeebKeys.BBCKEY_S);
82 | add("D", null, 1f, BeebKeys.BBCKEY_D);
83 | add("F", null, 1f, BeebKeys.BBCKEY_F);
84 | add("G", null, 1f, BeebKeys.BBCKEY_G);
85 | add("H", null, 1f, BeebKeys.BBCKEY_H);
86 | add("J", null, 1f, BeebKeys.BBCKEY_J);
87 | add("K", null, 1f, BeebKeys.BBCKEY_K);
88 | add("L", null, 1f, BeebKeys.BBCKEY_L);
89 | add(";", "+", 1f, BeebKeys.BBCKEY_SEMICOLON);
90 | add(":", "*", 1f, BeebKeys.BBCKEY_COLON);
91 | add("]", "}", 1f, BeebKeys.BBCKEY_BRACKET_RIGHT_SQ);
92 | add("\u2190", null, 1f, BeebKeys.BBCKEY_ARROW_LEFT);
93 | add("\u2192", null, 1f, BeebKeys.BBCKEY_ARROW_RIGHT);
94 | addRow();
95 | add("Z", null, 1f, BeebKeys.BBCKEY_Z);
96 | add("X", null, 1f, BeebKeys.BBCKEY_X);
97 | add("C", null, 1f, BeebKeys.BBCKEY_C);
98 | add("V", null, 1f, BeebKeys.BBCKEY_V);
99 | add("B", null, 1f, BeebKeys.BBCKEY_B);
100 | add("N", null, 1f, BeebKeys.BBCKEY_N);
101 | add("M", null, 1f, BeebKeys.BBCKEY_M);
102 | add(",", "<", 1f, BeebKeys.BBCKEY_COMMA);
103 | add(".", ">", 1f, BeebKeys.BBCKEY_PERIOD);
104 | add("/", "?", 1f, BeebKeys.BBCKEY_SLASH);
105 | add("\u2191", null, 1f, BeebKeys.BBCKEY_ARROW_UP);
106 | add("\u2193", null, 1f, BeebKeys.BBCKEY_ARROW_DOWN);
107 | addRow();
108 | Key shiftkey = add("SHIFT", null, 2f, BeebKeys.BBCKEY_SHIFT);
109 | shiftkey.listener = new KeyListener() {
110 | @Override
111 | public void onKeyPressed(boolean pressed) {
112 | shiftActuallyHeld = pressed;
113 | if (pressed) {
114 | shiftMode = SHIFTMODE_ONCE;
115 | shiftPressed = true;
116 | }
117 | else {
118 | if (shiftMode == SHIFTMODE_NORMAL) {
119 | shiftPressed = false;
120 | }
121 | }
122 | invalidate();
123 | }
124 | };
125 | add("CTRL", null, 1f, BeebKeys.BBCKEY_CTRL);
126 | add(" ", null, 4f, BeebKeys.BBCKEY_SPACE);
127 | add("DEL", null, 1f, BeebKeys.BBCKEY_DELETE);
128 | add("COPY", null, 1f, BeebKeys.BBCKEY_COPY);
129 | add("RETURN", null, 2f, BeebKeys.BBCKEY_ENTER);
130 | }
131 |
132 | public Key add(String label, String labelTop, float weight, int scancode, int flags) {
133 | KeyRow row = rows.get(rows.size()-1);
134 | Key pad = new Key();
135 | pad.label = label;
136 | pad.labelTop = labelTop;
137 | pad.scancode = scancode;
138 | pad.layout_width = 0;
139 | pad.layout_weight = weight;
140 | pad.flags = flags;
141 | row.keys.add(pad);
142 | allkeys.add(pad);
143 | return pad;
144 | }
145 | public Key add(String label, String labelTop, float weight, int scancode) {
146 | return add(label, labelTop, weight, scancode, 0);
147 | }
148 |
149 | @Override
150 | public void defaultOnKeyPressed(Key key, boolean pressed) {
151 | if (shiftPressed && !shiftActuallyHeld && shiftMode == SHIFTMODE_ONCE) {
152 | shiftPressed = false;
153 | invalidate();
154 | }
155 | if (shiftActuallyHeld) {
156 | shiftMode = SHIFTMODE_NORMAL;
157 | }
158 | }
159 |
160 | public void addRow() {
161 | rows.add(new KeyRow());
162 | }
163 |
164 | @Override
165 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
166 | super.onLayout(changed, l, t, r, b);
167 |
168 | float rowheight = (b-t)/6f;//ROWHEIGHT_SMALL * (getContext().getResources().getDisplayMetrics().heightPixels / 480f);
169 |
170 | float y = 0;
171 | for (KeyRow row : rows) {
172 | row.layout(r-l, y, y+rowheight+Beebdroid.dp(2));
173 | y += rowheight ;//- Beebdroid.dp(2);
174 | }
175 |
176 | b -=t;
177 | t = 0;
178 | int o = (int)Beebdroid.dp(8);
179 | int d = (int)Beebdroid.dp(10);
180 | ledOn.setBounds(o, b-(d+o), d+o, b-o);
181 | ledOff.setBounds(o, b-(d+o), d+o, b-o);
182 | }
183 |
184 | @Override
185 | public void draw(Canvas canvas) {
186 | super.draw(canvas);
187 | Drawable led = shiftPressed ? ledOn : ledOff;
188 | led.draw(canvas);
189 | }
190 |
191 |
192 |
193 | //
194 | // KeyRow
195 | //
196 | public static class KeyRow {
197 | public ArrayList keys = new ArrayList();
198 | public void layout(int width, float ftop, float fbottom) {
199 | float sumweights = 0;
200 | float sumwidths = 0;
201 | for (Key key : keys) {
202 | sumweights += key.layout_weight;
203 | sumwidths += key.layout_width;
204 | }
205 | float x = 0;
206 | float excess_space = width - Beebdroid.dp(sumwidths);
207 | float excess_unit = (sumweights==0) ? 0 : (excess_space / sumweights);
208 | for (Key key : keys) {
209 | float keywidth = Beebdroid.dp(key.layout_width) + excess_unit * key.layout_weight;
210 | key.bounds = new RectF(x, ftop, x+keywidth, fbottom);
211 | x += keywidth;
212 | }
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/TouchpadsView.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.util.ArrayList;
4 |
5 | import android.content.Context;
6 | import android.content.res.Configuration;
7 | import android.graphics.Canvas;
8 | import android.graphics.Color;
9 | import android.graphics.Paint;
10 | import android.graphics.Paint.Align;
11 | import android.graphics.RectF;
12 | import android.graphics.Typeface;
13 | import android.graphics.drawable.Drawable;
14 | import android.graphics.drawable.GradientDrawable.Orientation;
15 | import android.util.AttributeSet;
16 | import android.util.Log;
17 | import android.view.GestureDetector;
18 | import android.view.MotionEvent;
19 | import android.view.View;
20 |
21 |
22 | public class TouchpadsView extends View {
23 |
24 |
25 |
26 | public void defaultOnKeyPressed(Key key, boolean pressed) {
27 | }
28 |
29 | public static interface KeyListener {
30 | public void onKeyPressed(boolean pressed);
31 | }
32 |
33 | public class Key {
34 | String label, labelTop;
35 | int flags;
36 | float layout_width;
37 | float layout_weight;
38 | int scancode;
39 | boolean pressed;
40 | RectF bounds;
41 | KeyListener listener;
42 | public void press(boolean pressed) {
43 | if (listener == null) {
44 | defaultOnKeyPressed(this, pressed);
45 | }
46 | else {
47 | listener.onKeyPressed(pressed);
48 | }
49 | this.pressed = pressed;
50 | }
51 | }
52 |
53 |
54 | public ArrayList allkeys = new ArrayList();
55 | public boolean shiftPressed;
56 |
57 |
58 | public Beebdroid beebdroid;
59 | private Drawable padDrawable, padDrawableFn, padDrawableHilite;
60 | private Paint paint, paintBig, paintTiny;
61 |
62 | public TouchpadsView(Context context, AttributeSet attrs) {
63 | super(context, attrs);
64 | padDrawable = getResources().getDrawable(R.drawable.key);
65 | padDrawableFn = getResources().getDrawable(R.drawable.key_fn);
66 | padDrawableHilite = getResources().getDrawable(R.drawable.pad_pressed);
67 | int alpha = (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) ? 127:255;
68 | padDrawable.setAlpha(alpha);
69 | padDrawableFn.setAlpha(alpha);
70 | padDrawableHilite.setAlpha(alpha);
71 | paintTiny = new Paint();
72 | paintTiny.setColor(Color.WHITE);
73 | paintTiny.setTextSize(12);
74 | paintTiny.setTextAlign(Align.CENTER);
75 | paintTiny.setAntiAlias(true);
76 | paint = new Paint();
77 | paint.setColor(Color.WHITE);
78 | paint.setTextSize(22);
79 | paint.setTextAlign(Align.CENTER);
80 | paint.setAntiAlias(true);
81 | paintBig = new Paint();
82 | paintBig.setColor(Color.WHITE);
83 | paintBig.setTypeface(Typeface.DEFAULT_BOLD);
84 | paintBig.setTextSize(30);
85 | paintBig.setTextAlign(Align.CENTER);
86 | }
87 |
88 |
89 | private Key[] pressedPads = {null,null,null,null};
90 |
91 |
92 | private void dumpEvent(MotionEvent event) {
93 | String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
94 | "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
95 | StringBuilder sb = new StringBuilder();
96 | int action = event.getAction();
97 | int actionCode = action & MotionEvent.ACTION_MASK;
98 | sb.append("event ACTION_" ).append(names[actionCode]);
99 | if (actionCode == MotionEvent.ACTION_POINTER_DOWN
100 | || actionCode == MotionEvent.ACTION_POINTER_UP) {
101 | sb.append("(pid " ).append(
102 | action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
103 | sb.append(")" );
104 | }
105 | sb.append("[" );
106 | for (int i = 0; i < event.getPointerCount(); i++) {
107 | sb.append("#" ).append(i);
108 | sb.append("(pid " ).append(event.getPointerId(i));
109 | sb.append(")=" ).append((int) event.getX(i));
110 | sb.append("," ).append((int) event.getY(i));
111 | if (i + 1 < event.getPointerCount())
112 | sb.append(";" );
113 | }
114 | sb.append("]" );
115 | Log.d("Touch", sb.toString());
116 | }
117 |
118 | private Key hitTest(int x, int y) {
119 | for (Key key : allkeys) {
120 | if (key.bounds.contains(x, y)) {
121 | return key;
122 | }
123 | }
124 | return null;
125 | }
126 |
127 | @Override public boolean onTouchEvent(MotionEvent event) {
128 | //dumpEvent(event);
129 |
130 | int action = event.getAction();
131 | int actionCode = event.getActionMasked(); // action & MotionEvent.ACTION_MASK;
132 | int pid = -1;
133 | Key touchedPad, prevPad;
134 |
135 |
136 | switch (actionCode) {
137 | case MotionEvent.ACTION_DOWN:
138 | pid = 0; //event.getPointerId(0);
139 | // Log.d("Touch", "ACTION_DOWN " + pid);
140 | touchedPad = hitTest((int)event.getX(pid), (int)event.getY(pid));
141 | pressedPads[pid] = touchedPad;
142 | if (touchedPad != null) {
143 | beebdroid.bbcKeyEvent(touchedPad.scancode, shiftPressed?1:0, 1);
144 | touchedPad.press(true);
145 | invalidate();
146 | //Log.d("Touch", touchedPad.label + " in pid=" + pid);
147 | return true;
148 | }
149 | break;
150 | case MotionEvent.ACTION_POINTER_DOWN:
151 | pid = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
152 | // Log.d("Touch", "ACTION_POINTER_DOWN " + pid);
153 | touchedPad = hitTest((int)event.getX(pid), (int)event.getY(pid));
154 | pressedPads[pid] = touchedPad;
155 | if (touchedPad != null) {
156 | beebdroid.bbcKeyEvent(touchedPad.scancode, shiftPressed?1:0, 1);
157 | touchedPad.press(true);
158 | invalidate();
159 | // Log.d("Touch", touchedPad.label + " in pid=" + pid);
160 | return true;
161 | }
162 | break;
163 |
164 | case MotionEvent.ACTION_UP:
165 | pid = event.getPointerId(0);
166 | // Log.d("Touch", "ACTION_UP " + pid);
167 | prevPad = pressedPads[pid];
168 | if (prevPad != null) {
169 | prevPad.press(false);
170 | beebdroid.bbcKeyEvent(prevPad.scancode, shiftPressed?1:0, 0);
171 | invalidate();
172 | // Log.d("Touch", prevPad.label + " out pid=" + pid);
173 | }
174 | pressedPads[pid] = null;
175 | break;
176 | case MotionEvent.ACTION_POINTER_UP:
177 | pid = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
178 | //Log.d("Touch", "ACTION_POINTER_UP " + pid);
179 | prevPad = pressedPads[pid];
180 | if (prevPad != null) {
181 | prevPad.press(false);
182 | beebdroid.bbcKeyEvent(prevPad.scancode, shiftPressed?1:0, 0);
183 | invalidate();
184 | //Log.d("Touch", prevPad.label + " out pid=" + pid);
185 | }
186 | pressedPads[pid] = null;
187 | break;
188 |
189 | case MotionEvent.ACTION_MOVE:
190 |
191 | for (int i = 0; i < event.getPointerCount(); i++) {
192 | pid = event.getPointerId(i);
193 | if (pid >=4) continue;
194 | prevPad = pressedPads[pid];
195 | touchedPad = hitTest((int)event.getX(i), (int)event.getY(i));
196 |
197 | // If nothing changed, nothing to do
198 | if (prevPad==null && touchedPad==null) {
199 | continue;
200 | }
201 | if (prevPad!=null) { // only care if tracking a gesture that started on a pad
202 | if (prevPad.equals(touchedPad)) {
203 | continue;
204 | }
205 | }
206 |
207 | // Moved into a new pad OR out of one we were in before
208 | if (prevPad!=null) {
209 | beebdroid.bbcKeyEvent(prevPad.scancode, 0, 0);
210 | prevPad.press(false);
211 | //Log.d("Touch", prevPad.label + " dragout pid=" + pid);
212 | invalidate();
213 | }
214 | if (touchedPad != null) {
215 | beebdroid.bbcKeyEvent(touchedPad.scancode, 0, 1);
216 | touchedPad.press(true);
217 | invalidate();
218 | //Log.d("Touch", touchedPad.label + " dragin pid=" + pid);
219 | }
220 | pressedPads[pid] = touchedPad;
221 | }
222 | break;
223 |
224 | }
225 | return true;
226 | }
227 |
228 |
229 | @Override
230 | protected void onDraw(Canvas canvas) {
231 | for (Key key : allkeys) {
232 | Drawable d = key.pressed?padDrawableHilite:padDrawable;
233 | if (0 != (key.flags & 1)) {
234 | d = padDrawableFn;
235 | }
236 | d.setBounds((int)key.bounds.left, (int)key.bounds.top, (int)key.bounds.right, (int)key.bounds.bottom);
237 | d.draw(canvas);
238 | float y = key.bounds.centerY();
239 | if (key.labelTop != null) {
240 | if (shiftPressed) {
241 | y-=Beebdroid.dp(4);
242 | canvas.drawText(key.labelTop, key.bounds.centerX(), y, paint);
243 | y+=Beebdroid.dp(12);
244 | canvas.drawText(key.label, key.bounds.centerX(), y, paintTiny);
245 | }
246 | else {
247 | y-=Beebdroid.dp(8);
248 | canvas.drawText(key.labelTop, key.bounds.centerX(), y, paintTiny);
249 | y+=Beebdroid.dp(13);
250 | canvas.drawText(key.label, key.bounds.centerX(), y, paint);
251 | }
252 | }
253 | else {
254 | canvas.drawText(key.label, key.bounds.centerX(), y, key.label.length() > 1 ? paintTiny : paint);
255 | }
256 | }
257 | }
258 | }
259 |
260 |
261 |
--------------------------------------------------------------------------------
/app/src/main/java/common/Utils.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import java.io.BufferedOutputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileNotFoundException;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.io.OutputStream;
12 | import java.nio.ByteBuffer;
13 | import java.text.SimpleDateFormat;
14 | import java.util.ArrayList;
15 | import java.util.Collection;
16 | import java.util.HashMap;
17 | import java.util.List;
18 | import java.util.zip.ZipEntry;
19 | import java.util.zip.ZipInputStream;
20 |
21 | import junit.framework.Assert;
22 |
23 | import org.apache.http.HttpEntity;
24 | import org.apache.http.HttpResponse;
25 | import org.json.JSONException;
26 | import org.json.JSONObject;
27 |
28 | import android.app.Activity;
29 | import android.app.Dialog;
30 | import android.graphics.Typeface;
31 | import android.util.Log;
32 | import android.view.View;
33 | import android.view.ViewGroup;
34 | import android.widget.ImageView;
35 | import android.widget.TextView;
36 |
37 | public class Utils {
38 |
39 | public static void setVisibility(Object object, int id, int visibility) {
40 | View view = getView(object, id);
41 | if (view != null) {
42 | view.setVisibility(visibility);
43 | }
44 | }
45 | public static void setVisible(Object object, int id, boolean visible) {
46 | setVisibility(object, id, visible?View.VISIBLE:View.GONE);
47 | }
48 |
49 | public static String getText(Object object, int id) {
50 | TextView textView = (TextView)getView(object, id);
51 | if (textView != null) {
52 | return textView.getText().toString();
53 | }
54 | return "";
55 | }
56 |
57 | public static void setText(Object object, int id, String text) {
58 | TextView textView = (TextView)getView(object, id);
59 | if (textView != null) {
60 | textView.setText(text);
61 | }
62 | }
63 |
64 | public static void setImage(Object object, int id, int resourceId) {
65 | ImageView imageView = (ImageView)getView(object, id);
66 | if (imageView != null) {
67 | imageView.setImageResource(resourceId);
68 | }
69 | }
70 |
71 | public static void setTextBold(Object object, int id, boolean bold) {
72 | TextView textView = (TextView)getView(object, id);
73 | if (textView != null) {
74 | textView.setTypeface(bold ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
75 | }
76 | }
77 |
78 | public static View getView(Object object, int id) {
79 | View view = null;
80 | if (object instanceof Dialog) {
81 | view = ((Dialog)object).findViewById(id);
82 | }
83 | else if (object instanceof Activity) {
84 | view = ((Activity)object).findViewById(id);
85 | }
86 | else if (object instanceof ViewGroup) {
87 | view = ((ViewGroup)object).findViewById(id);
88 | }
89 | return view;
90 | }
91 |
92 |
93 | public static String getHttpResponseText(HttpResponse response) throws IOException {
94 | HttpEntity entity = response.getEntity();
95 | if (entity == null) {
96 | return "";
97 | }
98 | byte[] sBuffer = new byte[4096];
99 | InputStream inputStream = entity.getContent();
100 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4096);
101 | int readBytes = 0;
102 | int totalBytesRead = 0;
103 | while ((readBytes = inputStream.read(sBuffer)) != -1) {
104 | outputStream.write(sBuffer, 0, readBytes);
105 | totalBytesRead += readBytes;
106 | }
107 | entity.consumeContent();
108 | return new String(outputStream.toByteArray());
109 | }
110 |
111 | public static String readTextStreamAvailable(InputStream inputStream) throws IOException {
112 | byte[] buffer = new byte[4096];
113 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4096);
114 |
115 | // Do the first byte via a blocking read
116 | outputStream.write(inputStream.read());
117 |
118 | // Slurp the rest
119 | int available = inputStream.available();
120 | while (available > 0) {
121 | int cbToRead = Math.min(buffer.length, available);
122 | int cbRead = inputStream.read(buffer, 0, cbToRead);
123 | if (cbRead <= 0) {
124 | throw new IOException("Unexpected end of stream");
125 | }
126 | outputStream.write(buffer, 0, cbRead);
127 | available -= cbRead;
128 | }
129 | return new String(outputStream.toByteArray());
130 | }
131 |
132 | //
133 | // readTextStream
134 | //
135 | public static String readTextStream(InputStream inputStream) throws IOException {
136 | byte[] buffer = new byte[4096];
137 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4096);
138 | int readBytes = 0;
139 | int totalBytesRead = 0;
140 | while ((readBytes = inputStream.read(buffer)) != -1) {
141 | outputStream.write(buffer, 0, readBytes);
142 | totalBytesRead += readBytes;
143 | }
144 | return new String(outputStream.toByteArray());
145 | }
146 |
147 |
148 | //
149 | // getCommaDelimitedIntArray
150 | //
151 | public static int[] getCommaDelimitedIntArray(String s) {
152 | if (s.indexOf(',')==-1) {
153 | return new int[] {};
154 | }
155 | String[] as = s.split(",");
156 | int[] ai = new int[as.length];
157 | for (int i=0 ; i0) {
172 | retval = hours + "h ";
173 | minutes -= hours * 60;
174 | seconds -= hours * 60*60;
175 | }
176 | if (minutes>0) {
177 | retval += minutes + "m ";
178 | seconds -= minutes * 60;
179 | }
180 | retval += seconds + "s";
181 | return retval;
182 | }
183 |
184 | public static class HashMapArrayList extends HashMap {
185 | private static final long serialVersionUID = 1L;
186 | private ArrayList array = new ArrayList();
187 |
188 | public ArrayList getList() {
189 | return array;
190 | }
191 |
192 | public V[] toArray(V[] a) {
193 | return array.toArray(a);
194 | }
195 | @Override
196 | public V put(K k, V v) {
197 | array.add(v);
198 | v = super.put(k, v);
199 | Assert.assertTrue(size()==array.size()); // Broken? Change this function to not allow duplicate entries in this.array
200 | return v;
201 | }
202 |
203 | public V getByIndex(int index) {
204 | if (index>=array.size()) {
205 | return null;
206 | }
207 | return array.get(index);
208 | }
209 |
210 | @Override
211 | public V remove(Object k) {
212 | V v = get(k);
213 | if (v != null) {
214 | array.remove(v);
215 | }
216 | super.remove(k);
217 | return v;
218 | }
219 |
220 | @Override
221 | public void clear() {
222 | super.clear();
223 | array.clear();
224 | }
225 | }
226 |
227 |
228 | public static void closeQuietly(InputStream input) {
229 | try {
230 | if (input != null) {
231 | input.close();
232 | }
233 | } catch (IOException ioe) {
234 | // ignore
235 | }
236 | }
237 | public static void closeQuietly(OutputStream output) {
238 | try {
239 | if (output != null) {
240 | output.close();
241 | }
242 | } catch (IOException ioe) {
243 | // ignore
244 | }
245 | }
246 |
247 |
248 | public static String safeGetJsonString(JSONObject obj, String fieldName) throws JSONException {
249 | if (obj.has(fieldName)) {
250 | return obj.getString(fieldName);
251 | }
252 | return "";
253 | }
254 |
255 | public static String age(long timestamp) {
256 | long age = System.currentTimeMillis() - timestamp;
257 |
258 | if (age<5000){
259 | return "just now";
260 | }
261 |
262 | long seconds = age / 1000;
263 | if (seconds<60){
264 | return Long.toString(seconds) + " seconds ago";
265 | }
266 |
267 | long minutes = seconds / 60;
268 | if (minutes<60){
269 | return Long.toString(minutes) + ((minutes==1) ? " minute ago" : " minutes ago");
270 | }
271 |
272 | long hours = minutes / 60;
273 | if (hours<24){
274 | return Long.toString(hours) + ((hours==1) ? " hour ago" : " hours ago");
275 | }
276 |
277 | long days = hours / 24;
278 | if (days<7) {
279 | return (days==1) ? "Yesterday" : (Long.toString(days) + " days ago");
280 | }
281 |
282 |
283 | long weeks = days / 7;
284 | if (weeks<4){
285 | return Long.toString(weeks) + ((weeks==1) ? " week ago" : " weeks ago");
286 | }
287 |
288 | SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
289 | return formatter.format(timestamp);
290 | }
291 |
292 |
293 | public static void unzip(File zipfile, File targetfile, boolean deleteZipAfterwards) throws IOException {
294 | ZipInputStream input = new ZipInputStream(new FileInputStream(zipfile));
295 | ZipEntry entry = input.getNextEntry();
296 | OutputStream output = new BufferedOutputStream(new FileOutputStream(targetfile));
297 | int count;
298 | byte buffer[] = new byte[4096];
299 | while ((count = input.read(buffer, 0, 4096)) != -1) {
300 | output.write(buffer, 0, count);
301 | }
302 | output.flush();
303 | output.close();
304 | input.close();
305 | if (deleteZipAfterwards) {
306 | zipfile.delete();
307 | }
308 |
309 | }
310 | }
311 |
--------------------------------------------------------------------------------
/app/src/main/jni/ssd.c:
--------------------------------------------------------------------------------
1 | /*B-em v2.1 by Tom Walker
2 | SSD/DSD disc handling*/
3 | #include "main.h"
4 |
5 |
6 | struct {
7 | unsigned char* img;
8 | int cb;
9 | int pos;
10 | } ssdf[2];
11 | uint8_t trackinfo[2][2][10*256];
12 | int dsd[2],ssdtrackc[2];
13 | int writeprot[2],fwriteprot[2];
14 |
15 | int ssdsector,ssdtrack,ssdside,ssddrive;
16 | int ssdread,ssdwrite,ssdreadpos,ssdreadaddr;
17 | int ssdtime;
18 | int ssdnotfound;
19 | int ssdrsector=0;
20 | int ssdformat=0;
21 |
22 | void ssd_reset()
23 | {
24 | ssdf[0].img=NULL;
25 | ssdf[0].cb=0;
26 | ssdf[0].pos=0;
27 | ssdf[1].img=NULL;
28 | ssdf[1].cb=0;
29 | ssdf[1].pos=0;
30 | dsd[0]=dsd[1]=0;
31 | ssdnotfound=0;
32 | ssdsector=ssdtrack=ssdside=ssddrive=0;
33 | ssdread=ssdwrite=ssdreadpos=ssdreadaddr=0;
34 | ssdtime=0;
35 | ssdnotfound=0;
36 | ssdrsector=0;
37 | ssdformat=0;
38 | }
39 |
40 | void ssd_load(int drive, unsigned char *img, int cb)
41 | {
42 | LOGI("ssd_load");
43 | writeprot[drive]=0;
44 | ssdf[drive].img = img;
45 | ssdf[drive].cb = cb;
46 | ssdf[drive].pos = 0;
47 | dsd[drive]=0;
48 | drives[drive].seek=ssd_seek;
49 | drives[drive].readsector=ssd_readsector;
50 | drives[drive].writesector=ssd_writesector;
51 | drives[drive].readaddress=ssd_readaddress;
52 | drives[drive].poll=ssd_poll;
53 | drives[drive].format=ssd_format;
54 | }
55 |
56 | void dsd_load(int drive, unsigned char *img, int cb)
57 | {
58 | LOGI("dsd_load");
59 | writeprot[drive]=0;
60 | ssdf[drive].img = img;
61 | ssdf[drive].cb = cb;
62 | ssdf[drive].pos = 0;
63 | dsd[drive]=1;
64 | drives[drive].seek=ssd_seek;
65 | drives[drive].readsector=ssd_readsector;
66 | drives[drive].writesector=ssd_writesector;
67 | drives[drive].readaddress=ssd_readaddress;
68 | drives[drive].poll=ssd_poll;
69 | drives[drive].format=ssd_format;
70 | }
71 |
72 | void ssd_close(int drive)
73 | {
74 | LOGI("ssd_close");
75 | ssdf[drive].img=NULL;
76 | ssdf[drive].cb=0;
77 | ssdf[drive].pos = 0;
78 | }
79 |
80 | #define min(x,y) (((x)<(y)) ? (x) : (y))
81 |
82 | void ssd_seek(int drive, int track)
83 | {
84 | if (!ssdf[drive].img) return;
85 | LOGI("ssd_seek :%i to %i\n",drive,track);
86 | ssdtrackc[drive]=track;
87 | if (dsd[drive])
88 | {
89 | ssdf[drive].pos = track*20*256; //fseek(ssdf[drive],track*20*256,SEEK_SET);
90 | memcpy(trackinfo[drive][0], ssdf[drive].img+ssdf[drive].pos, 10*256); //fread(trackinfo[drive][0],10*256,1,ssdf[drive]);
91 | ssdf[drive].pos += 10*256;
92 | memcpy(trackinfo[drive][1], ssdf[drive].img+ssdf[drive].pos, 10*256); //fread(trackinfo[drive][1],10*256,1,ssdf[drive]);
93 | ssdf[drive].pos += 10*256;
94 | }
95 | else
96 | {
97 | ssdf[drive].pos = track*10*256; //fseek(ssdf[drive],track*10*256,SEEK_SET);
98 | int cb = 10*256;
99 | cb = min(cb, ssdf[drive].cb-ssdf[drive].pos);
100 | LOGI("cb=%d pos=%d drive.cb=%d", cb, ssdf[drive].pos, ssdf[drive].cb);
101 | memcpy(trackinfo[drive][0], ssdf[drive].img+ssdf[drive].pos, cb); //fread(trackinfo[drive][0],10*256,1,ssdf[drive]);
102 | ssdf[drive].pos += cb;
103 | }
104 | }
105 |
106 |
107 |
108 | void ssd_writeback(int drive, int track)
109 | {
110 | LOGI("ssd_writeback NYI");
111 | /*
112 | * TODO
113 |
114 | if (!ssdf[drive]) return;
115 | if (dsd[drive])
116 | {
117 | fseek(ssdf[drive],track*20*256,SEEK_SET);
118 | fwrite(trackinfo[drive][0],10*256,1,ssdf[drive]);
119 | fwrite(trackinfo[drive][1],10*256,1,ssdf[drive]);
120 | }
121 | else
122 | {
123 | fseek(ssdf[drive],track*10*256,SEEK_SET);
124 | fwrite(trackinfo[drive][0],10*256,1,ssdf[drive]);
125 | }
126 | */
127 | }
128 |
129 | void ssd_readsector(int drive, int sector, int track, int side, int density)
130 | {
131 | ssdsector=sector;
132 | ssdtrack=track;
133 | ssdside=side;
134 | ssddrive=drive;
135 | LOGI("ssd_readsector %i %i %i %i\n",drive,side,track,sector);
136 |
137 | if (!ssdf[drive].img || (side && !dsd[drive]) || density || track!=ssdtrackc[drive])
138 | {
139 | ssdnotfound=500;
140 | LOGI("ssd_readsector - not found!\n");
141 | return;
142 | }
143 | ssdread=1;
144 | ssdreadpos=0;
145 | // printf("GO\n");
146 | }
147 |
148 | void ssd_writesector(int drive, int sector, int track, int side, int density)
149 | {
150 | ssdsector=sector;
151 | ssdtrack=track;
152 | ssdside=side;
153 | ssddrive=drive;
154 | LOGI("ssd_writesector %i %i %i %i\n",drive,side,track,sector);
155 |
156 | if (!ssdf[drive].img || (side && !dsd[drive]) || density || track!=ssdtrackc[drive])
157 | {
158 | ssdnotfound=500;
159 | return;
160 | }
161 | ssdwrite=1;
162 | ssdreadpos=0;
163 | ssdtime=-1000;
164 | }
165 |
166 | void ssd_readaddress(int drive, int track, int side, int density)
167 | {
168 | ssdtrack=track;
169 | ssdside=side;
170 | ssddrive=drive;
171 | // printf("Read address %i %i %i %i\n",drive,track,side,density);
172 |
173 | if (!ssdf[drive].img || (side && !dsd[drive]) || density || track!=ssdtrackc[drive])
174 | {
175 | ssdnotfound=500;
176 | return;
177 | }
178 | ssdrsector=0;
179 | ssdreadpos=0;
180 | ssdreadaddr=1;
181 | }
182 |
183 | void ssd_format(int drive, int track, int side, int density)
184 | {
185 | ssdtrack=track;
186 | ssdside=side;
187 | ssddrive=drive;
188 |
189 | if (!ssdf[drive].img || (side && !dsd[drive]) || density || track!=ssdtrackc[drive])
190 | {
191 | ssdnotfound=500;
192 | return;
193 | }
194 | ssdsector=0;
195 | ssdreadpos=0;
196 | ssdformat=1;
197 | }
198 |
199 | void ssd_poll()
200 | {
201 | int c;
202 | ssdtime++;
203 | if (ssdtime<16) return;
204 | ssdtime=0;
205 |
206 | if (ssdnotfound)
207 | {
208 | ssdnotfound--;
209 | if (!ssdnotfound)
210 | {
211 | fdcnotfound();
212 | }
213 | }
214 | //LOGI("ssdpoll ssdread=%i ssdf[ssddrive].img=%X",ssdread, ssdf[ssddrive].img);
215 | if (ssdread && ssdf[ssddrive].img)
216 | {
217 | //LOGI("ssdpoll ssdread ssdreadpos=%d", ssdreadpos);
218 |
219 | fdcdata(trackinfo[ssddrive][ssdside][(ssdsector<<8)+ssdreadpos]);
220 | ssdreadpos++;
221 | if (ssdreadpos==256)
222 | {
223 | ssdread=0;
224 | fdcfinishread();
225 | }
226 | }
227 | if (ssdwrite && ssdf[ssddrive].img)
228 | {
229 | if (writeprot[ssddrive])
230 | {
231 | fdcwriteprotect();
232 | ssdwrite=0;
233 | return;
234 | }
235 | // printf("Write data %i\n",ssdreadpos);
236 | c=fdcgetdata(ssdreadpos==255);
237 | if (c==-1)
238 | {
239 | // printf("Data overflow!\n");
240 | // exit(-1);
241 | }
242 | trackinfo[ssddrive][ssdside][(ssdsector<<8)+ssdreadpos]=c;
243 | ssdreadpos++;
244 | if (ssdreadpos==256)
245 | {
246 | ssdwrite=0;
247 | fdcfinishread();
248 | ssd_writeback(ssddrive,ssdtrack);
249 | }
250 | }
251 | if (ssdreadaddr && ssdf[ssddrive].img)
252 | {
253 | //LOGI("ssdpoll ssdreadaddr");
254 | switch (ssdreadpos)
255 | {
256 | case 0: fdcdata(ssdtrack); break;
257 | case 1: fdcdata(ssdside); break;
258 | case 2: fdcdata(ssdrsector); break;
259 | case 3: fdcdata(1); break;
260 | case 4: fdcdata(0); break;
261 | case 5: fdcdata(0); break;
262 | case 6:
263 | ssdreadaddr=0;
264 | fdcfinishread();
265 | ssdrsector++;
266 | if (ssdrsector==10) ssdrsector=0;
267 | break;
268 | }
269 | ssdreadpos++;
270 | }
271 | if (ssdformat && ssdf[ssddrive].img)
272 | {
273 | if (writeprot[ssddrive])
274 | {
275 | fdcwriteprotect();
276 | ssdformat=0;
277 | return;
278 | }
279 | trackinfo[ssddrive][ssdside][(ssdsector<<8)+ssdreadpos]=0;
280 | ssdreadpos++;
281 | if (ssdreadpos==256)
282 | {
283 | ssdreadpos=0;
284 | ssdsector++;
285 | if (ssdsector==10)
286 | {
287 | ssdformat=0;
288 | fdcfinishread();
289 | ssd_writeback(ssddrive,ssdtrack);
290 | }
291 | }
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/app/src/main/jni/uservia.c:
--------------------------------------------------------------------------------
1 | /*B-em v2.1 by Tom Walker
2 | User VIA + Master 512 mouse emulation*/
3 |
4 | #include "main.h"
5 |
6 | //#define printf rpclog
7 | #undef printf
8 | VIA uservia;
9 |
10 | int mx=0,my=0;
11 |
12 | #define TIMER1INT 0x40
13 | #define TIMER2INT 0x20
14 | #define PORTBINT 0x18
15 | #define PORTAINT 0x03
16 |
17 | #define ORB 0x00
18 | #define ORA 0x01
19 | #define DDRB 0x02
20 | #define DDRA 0x03
21 | #define T1CL 0x04
22 | #define T1CH 0x05
23 | #define T1LL 0x06
24 | #define T1LH 0x07
25 | #define T2CL 0x08
26 | #define T2CH 0x09
27 | #define SR 0x0a
28 | #define ACR 0x0b
29 | #define PCR 0x0c
30 | #define IFR 0x0d
31 | #define IER 0x0e
32 | #define ORAnh 0x0f
33 |
34 | void updateuserIFR()
35 | {
36 | if ((uservia.ifr&0x7F)&(uservia.ier&0x7F))
37 | {
38 | uservia.ifr|=0x80;
39 | the_cpu->interrupt|=2;
40 | }
41 | else
42 | {
43 | uservia.ifr&=~0x80;
44 | the_cpu->interrupt&=~2;
45 | }
46 | }
47 |
48 | int timerout=1;
49 |
50 | int vc,sc;
51 |
52 | void updateusertimers()
53 | {
54 | if (uservia.t1c<-3)
55 | {
56 | while (uservia.t1c<-3)
57 | uservia.t1c+=uservia.t1l+4;
58 | if (!uservia.t1hit)
59 | {
60 | // rpclog("User T1 interrupt! %04X %i %i\n",uservia.t1l,vc,sc);
61 | uservia.ifr|=TIMER1INT;
62 | updateuserIFR();
63 | }
64 | if ((uservia.acr&0x80) && !uservia.t1hit)
65 | {
66 | uservia.orb^=0x80;
67 | uservia.irb^=0x80;
68 | uservia.portb^=0x80;
69 | timerout^=1;
70 | }
71 | if (!(uservia.acr&0x40))
72 | uservia.t1hit=1;
73 | }
74 | if (!(uservia.acr&0x20))
75 | {
76 | if (uservia.t2c<-3 && !uservia.t2hit)
77 | {
78 | if (!uservia.t2hit)
79 | {
80 | // rpclog("User T2 interrupt!\n");
81 | uservia.ifr|=TIMER2INT;
82 | updateuserIFR();
83 | }
84 | uservia.t2hit=1;
85 | }
86 | }
87 | }
88 |
89 | void writeuservia(uint16_t addr, uint8_t val)
90 | {
91 | // rpclog("Write User VIA %04X %02X %04X\n",addr,val,pc);
92 | switch (addr&0xF)
93 | {
94 | case ORA:
95 | uservia.ifr&=0xfc;//~PORTAINT;
96 | updateuserIFR();
97 | case ORAnh:
98 | // rpclog("Write User ORA %02X\n",val);
99 | uservia.ora=val;
100 | uservia.porta=(uservia.porta & ~uservia.ddra)|(uservia.ora & uservia.ddra);
101 | break;
102 |
103 | case ORB:
104 | uservia.orb=val;
105 | uservia.portb=(uservia.portb & ~uservia.ddrb)|(uservia.orb & uservia.ddrb);
106 | uservia.ifr&=0xee;//~PORTBINT;
107 | updateuserIFR();
108 | break;
109 |
110 | case DDRA:
111 | // rpclog("User DDRA = %02X\n",val);
112 | uservia.ddra=val;
113 | break;
114 | case DDRB:
115 | uservia.ddrb=val;
116 | break;
117 | case ACR:
118 | uservia.acr=val;
119 | // rpclog("SR ACR = %02X\n",val);
120 | break;
121 | case PCR:
122 | uservia.pcr=val;
123 | break;
124 | case SR:
125 | uservia.sr=val;
126 | break;
127 | case T1LL:
128 | case T1CL:
129 | uservia.t1l&=0x1FE00;
130 | uservia.t1l|=(val<<1);
131 | // rpclog("T1L now %05X\n",uservia.t1l);
132 | break;
133 | case T1LH:
134 | uservia.t1l&=0x1FE;
135 | uservia.t1l|=(val<<9);
136 | if (uservia.acr&0x40)
137 | {
138 | uservia.ifr&=~TIMER1INT;
139 | updateuserIFR();
140 | }
141 | // rpclog("T1L now %05X\n",uservia.t1l);
142 | break;
143 | case T1CH:
144 | if ((uservia.acr&0xC0)==0x80) timerout=0;
145 | uservia.t1l&=0x1FE;
146 | uservia.t1l|=(val<<9);
147 | uservia.t1c=uservia.t1l+1;
148 | uservia.ifr&=~TIMER1INT;
149 | updateuserIFR();
150 | uservia.t1hit=0;
151 | // rpclog("T1L now %05X\n",uservia.t1l);
152 | break;
153 | case T2CL:
154 | uservia.t2l&=0x1FE00;
155 | uservia.t2l|=(val<<1);
156 | // printf("T2L now %05X\n",uservia.t2l);
157 | break;
158 | case T2CH:
159 | if ((uservia.t2c==-3 && (uservia.ier&TIMER2INT)) ||
160 | (uservia.ifr&uservia.ier&TIMER2INT))
161 | {
162 | the_cpu->interrupt|=128;
163 | }
164 | uservia.t2l&=0x1FE;
165 | uservia.t2l|=(val<<9);
166 | uservia.t2c=uservia.t2l+1;
167 | uservia.ifr&=~TIMER2INT;
168 | updateuserIFR();
169 | uservia.t2hit=0;
170 | // printf("T2L now %05X\n",uservia.t2l);
171 | break;
172 | case IER:
173 | if (val&0x80)
174 | uservia.ier|=(val&0x7F);
175 | else
176 | uservia.ier&=~(val&0x7F);
177 | updateuserIFR();
178 | // printf("USER IER now %02X\n",sysvia.ier);
179 | // printf("User IER now %02X\n",val);
180 | break;
181 | case IFR:
182 | uservia.ifr&=~(val&0x7F);
183 | updateuserIFR();
184 | break;
185 | }
186 | }
187 |
188 | uint8_t readuservia(uint16_t addr)
189 | {
190 | uint8_t temp;
191 | // if (addr==0xFE6A) rpclog("Read User VIA %04X %04X\n",addr,pc);
192 | addr&=0xF;
193 | switch (addr&0xF)
194 | {
195 | case ORA:
196 | uservia.ifr&=~PORTAINT;
197 | updateuserIFR();
198 | case ORAnh:
199 | // rpclog("Read User ORA %02X %02X %02X\n",uservia.ora,uservia.porta,uservia.ddra);
200 | temp=uservia.ora & uservia.ddra;
201 | temp|=(uservia.porta & ~uservia.ddra);
202 | temp&=0x7F;
203 | return temp;
204 |
205 | case ORB:
206 | uservia.ifr&=~PORTBINT;
207 | updateuserIFR();
208 | temp=uservia.orb & uservia.ddrb;
209 | // rpclog("ORB %02X %02X %02X %i\n",temp,uservia.orb,uservia.ddrb,uservia.acr&2);
210 | if (uservia.acr&2)
211 | temp|=(uservia.irb & ~uservia.ddrb);
212 | else
213 | temp|=(uservia.portb & ~uservia.ddrb);
214 | // temp|=0xFF;
215 | if (timerout) temp|=0x80;
216 | else temp&=~0x80;
217 | // rpclog("Read ORB %02X %04X\n",temp,pc);
218 | return temp;
219 |
220 | case DDRA:
221 | return uservia.ddra;
222 | case DDRB:
223 | return uservia.ddrb;
224 | case T1LL:
225 | return (uservia.t1l&0x1FE)>>1;
226 | case T1LH:
227 | return uservia.t1l>>9;
228 | case T1CL:
229 | uservia.ifr&=~TIMER1INT;
230 | updateuserIFR();
231 | if (uservia.t1c<-1) return 0xFF;
232 | return ((uservia.t1c+1)>>1)&0xFF;
233 | case T1CH:
234 | if (uservia.t1c<-1) return 0xFF;
235 | return (uservia.t1c+1)>>9;
236 | case T2CL:
237 | uservia.ifr&=~TIMER2INT;
238 | updateuserIFR();
239 | return ((uservia.t2c+1)>>1)&0xFF;
240 | case T2CH:
241 | return (uservia.t2c+1)>>9;
242 | case SR:
243 | return uservia.sr;
244 | case ACR:
245 | return uservia.acr;
246 | case PCR:
247 | return uservia.pcr;
248 | case IER:
249 | return uservia.ier|0x80;
250 | case IFR:
251 | // printf("Reading user IFR %02X\n",uservia.ifr);
252 | return uservia.ifr;
253 | }
254 | return 0xFE;
255 | }
256 |
257 | void resetuservia()
258 | {
259 | uservia.ora=0x80; uservia.orb=0xFF;
260 | uservia.ddra=uservia.ddrb=0xFF;
261 | uservia.ifr=uservia.ier=0;
262 | uservia.t1c=uservia.t1l=0x1FFFE;
263 | uservia.t2c=uservia.t2l=0x1FFFE;
264 | uservia.t1hit=uservia.t2hit=1;
265 | timerout=1;
266 | uservia.acr=0;
267 | }
268 |
269 | void dumpuservia()
270 | {
271 | // rpclog("T1 = %04X %04X T2 = %04X %04X\n",uservia.t1c,uservia.t1l,uservia.t2c,uservia.t2l);
272 | // rpclog("%02X %02X %02X %02X\n",uservia.ifr,uservia.ier,uservia.pcr,uservia.acr);
273 | }
274 |
275 | /*
276 | int mxs=0,mys=0;
277 | int mfirst=1;
278 | int mon=0;
279 | int beebmousex=0,beebmousey=0;
280 | void domouse()
281 | {
282 | int x,y;
283 | if (mouse_x>0 && mouse_x<640 && mouse_y>0 && mouse_y<512)
284 | {
285 | beebmousex=mouse_x;
286 | beebmousey=256-(mouse_y/2);
287 | }
288 | if (uservia.ifr&0x18) return;
289 | if (mouse_x!=mx)
290 | {
291 | uservia.ifr|=0x10;
292 | if (mxs==((mouse_x>mx)?1:-1)) uservia.portb^=8;
293 | mxs=(mouse_x>mx)?1:-1;
294 | mx+=mxs;
295 | }
296 | if (mouse_y!=my)
297 | {
298 | if (mfirst)
299 | {
300 | mfirst=0;
301 | uservia.portb|=0x10;
302 | }
303 | uservia.ifr|=0x08;
304 | if (mys==((mouse_y>my)?1:-1)) uservia.portb^=0x10;
305 | mys=(mouse_y>my)?1:-1;
306 | my+=mys;
307 | }
308 | updateuserIFR();
309 | if (mouse_b&1) uservia.portb&=~1;
310 | else uservia.portb|=1;
311 | if (mouse_b&2) uservia.portb&=~4;
312 | else uservia.portb|=4;
313 | uservia.portb|=2;
314 | mem[0x2821]=beebmousey>>8;
315 | mem[0x2822]=beebmousey&0xFF;
316 | mem[0x2823]=beebmousex>>8;
317 | mem[0x2824]=beebmousex&0xFF;
318 | }
319 |
320 | void getmousepos(uint16_t *AX, uint16_t *CX, uint16_t *DX)
321 | {
322 | int c=mouse_b&1;
323 | if (mouse_b&2) c|=4;
324 | if (mouse_b&4) c|=2;
325 | *AX=c;
326 | *CX=beebmousex;
327 | *DX=beebmousey;
328 | }
329 |
330 |
331 | void saveuserviastate(FILE *f)
332 | {
333 | putc(uservia.ora,f);
334 | putc(uservia.orb,f);
335 | putc(uservia.ira,f);
336 | putc(uservia.irb,f);
337 | putc(uservia.porta,f);
338 | putc(uservia.portb,f);
339 | putc(uservia.ddra,f);
340 | putc(uservia.ddrb,f);
341 | putc(uservia.sr,f);
342 | putc(uservia.acr,f);
343 | putc(uservia.pcr,f);
344 | putc(uservia.ifr,f);
345 | putc(uservia.ier,f);
346 | putc(uservia.t1l,f); putc(uservia.t1l>>8,f); putc(uservia.t1l>>16,f); putc(uservia.t1l>>24,f);
347 | putc(uservia.t2l,f); putc(uservia.t2l>>8,f); putc(uservia.t2l>>16,f); putc(uservia.t2l>>24,f);
348 | putc(uservia.t1c,f); putc(uservia.t1c>>8,f); putc(uservia.t1c>>16,f); putc(uservia.t1c>>24,f);
349 | putc(uservia.t2c,f); putc(uservia.t2c>>8,f); putc(uservia.t2c>>16,f); putc(uservia.t2c>>24,f);
350 | putc(uservia.t1hit,f);
351 | putc(uservia.t2hit,f);
352 | putc(uservia.ca1,f);
353 | putc(uservia.ca2,f);
354 | }
355 |
356 | void loaduserviastate(FILE *f)
357 | {
358 | uservia.ora=getc(f);
359 | uservia.orb=getc(f);
360 | uservia.ira=getc(f);
361 | uservia.irb=getc(f);
362 | uservia.porta=getc(f);
363 | uservia.portb=getc(f);
364 | uservia.ddra=getc(f);
365 | uservia.ddrb=getc(f);
366 | uservia.sr=getc(f);
367 | uservia.acr=getc(f);
368 | uservia.pcr=getc(f);
369 | uservia.ifr=getc(f);
370 | uservia.ier=getc(f);
371 | uservia.t1l=getc(f); uservia.t1l|=getc(f)<<8; uservia.t1l|=getc(f)<<16; uservia.t1l|=getc(f)<<24;
372 | uservia.t2l=getc(f); uservia.t2l|=getc(f)<<8; uservia.t2l|=getc(f)<<16; uservia.t2l|=getc(f)<<24;
373 | uservia.t1c=getc(f); uservia.t1c|=getc(f)<<8; uservia.t1c|=getc(f)<<16; uservia.t1c|=getc(f)<<24;
374 | uservia.t2c=getc(f); uservia.t2c|=getc(f)<<8; uservia.t2c|=getc(f)<<16; uservia.t2c|=getc(f)<<24;
375 | uservia.t1hit=getc(f);
376 | uservia.t2hit=getc(f);
377 | uservia.ca1=getc(f);
378 | uservia.ca2=getc(f);
379 | }
380 | */
381 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlefluffytoys/beebdroid/Controllers.java:
--------------------------------------------------------------------------------
1 | package com.littlefluffytoys.beebdroid;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 |
7 | import android.view.KeyEvent;
8 |
9 | public class Controllers {
10 |
11 |
12 | static ControllerInfo controller_ZX_4way = new ControllerInfo();
13 | static ControllerInfo controller_ZX_5way = new ControllerInfo();
14 | static ControllerInfo controller_RocketRaid_Game = new ControllerInfo();
15 | static ControllerInfo controller_Qman_Game = new ControllerInfo();
16 | static ControllerInfo controller_Arcadians_Game = new ControllerInfo();
17 | static ControllerInfo controller_Arcadians_Menu = new ControllerInfo();
18 | static ControllerInfo controller_CastleQuest_Game = new ControllerInfo();
19 | static ControllerInfo controller_ChuckieEgg_Game = new ControllerInfo();
20 | static ControllerInfo controller_ChuckieEgg_Game_Alt = new ControllerInfo();
21 | static ControllerInfo controller_DareDevilDennis_Game = new ControllerInfo();
22 | static ControllerInfo controller_Thrust_Game = new ControllerInfo();
23 | static ControllerInfo controller_Planetoid_Game = new ControllerInfo();
24 | static ControllerInfo controller_Imogen_Game = new ControllerInfo();
25 | static ControllerInfo controller_Elite_Game = new ControllerInfo();
26 | static ControllerInfo controller_Zalaga_Game = new ControllerInfo();
27 |
28 | static ControllerInfo DEFAULT_CONTROLLER = controller_ZX_5way;
29 |
30 | static {
31 | controller_ZX_4way.addKey("Left", "Z", 0, -1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
32 | controller_ZX_4way.addKey("Right", "X", 1, -1, 1f, 1f, BeebKeys.BBCKEY_X, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
33 | controller_ZX_4way.addKey("Up", ":", -1, 0, 1f, 1f, BeebKeys.BBCKEY_COLON, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_BUTTON_Y);
34 | controller_ZX_4way.addKey("Down", "/", -1, 1, 1f, 1f, BeebKeys.BBCKEY_SLASH, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
35 | controller_ZX_4way.useDPad = true;
36 | controller_ZX_5way.addKey("Left", "Z", 0, -1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
37 | controller_ZX_5way.addKey("Right", "X", 1, -1, 1f, 1f, BeebKeys.BBCKEY_X, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
38 | controller_ZX_5way.addKey("Up", ":", -2, 0, 1f, 1f, BeebKeys.BBCKEY_COLON, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_BUTTON_Y);
39 | controller_ZX_5way.addKey("Down", "/", -2, 1, 1f, 1f, BeebKeys.BBCKEY_SLASH, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
40 | controller_ZX_5way.addKey("Fire", "Return", -1, 0, 1f, 2f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1);
41 | controller_ZX_5way.useDPad = true;
42 | controller_RocketRaid_Game.addKey("Left", "SPACE", 0, -1, 1f, 1f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_DPAD_LEFT);
43 | controller_RocketRaid_Game.addKey("Right", "SHIFT", 1, -1, 1f, 1f, BeebKeys.BBCKEY_SHIFT, KeyEvent.KEYCODE_DPAD_RIGHT);
44 | controller_RocketRaid_Game.addKey("Up", "A", -2, 0, 1f, 1f, BeebKeys.BBCKEY_A, KeyEvent.KEYCODE_DPAD_UP);
45 | controller_RocketRaid_Game.addKey("Down", "Z", -2, 1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_DOWN);
46 | controller_RocketRaid_Game.addKey("Fire", "Return", -1, 0, 1f, 1f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_DPAD_CENTER);
47 | controller_RocketRaid_Game.addKey("Bomb", "Tab", -1, 1, 1f, 1f, BeebKeys.BBCKEY_TAB, KeyEvent.KEYCODE_BACK);
48 | controller_RocketRaid_Game.useDPad = true;
49 | controller_Qman_Game.addKey("Up-Left", "A", 0, 0, 1f, 1f, BeebKeys.BBCKEY_A, KeyEvent.KEYCODE_BUTTON_X);
50 | controller_Qman_Game.addKey("Down-Left", "Z", 0, -1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_DOWN);
51 | controller_Qman_Game.addKey("Up-Right", ":", -1, 0, 1f, 1f, BeebKeys.BBCKEY_COLON, KeyEvent.KEYCODE_DPAD_RIGHT);
52 | controller_Qman_Game.addKey("Down-Right", "/", -1, 1, 1f, 1f, BeebKeys.BBCKEY_SLASH, KeyEvent.KEYCODE_DPAD_CENTER);
53 |
54 | // Arcadians has 2 controllers and uses PC triggers to switch between them
55 | // controller_Arcadians_Menu.addKey("1","1", 0f, 0, 1.5f, 1.5f, BeebKeys.BBCKEY_1);
56 | // controller_Arcadians_Menu.addKey("2","2", 1.5f, 0, 1.5f, 1.5f, BeebKeys.BBCKEY_2);
57 | // controller_Arcadians_Menu.addTrigger((short) 0x3203, controller_Arcadians_Game);
58 | controller_Arcadians_Menu.addKey("Left","Caps", 0f, 0, 1.25f, 1.25f, BeebKeys.BBCKEY_CAPS, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
59 | controller_Arcadians_Menu.addKey("Right","Ctrl", 1.25f, 0, 1.25f, 1.25f, BeebKeys.BBCKEY_CTRL, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
60 | controller_Arcadians_Menu.addKey("Fire","Return", -1f, 0, 1f, 1.25f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1);
61 | // controller_Arcadians_Game.addTrigger((short) 0x4d95, controller_Arcadians_Menu);
62 |
63 | controller_CastleQuest_Game.addKey("Left", "Z", 0, -1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_LEFT);
64 | controller_CastleQuest_Game.addKey("Right", "X", 1, -1, 1f, 1f, BeebKeys.BBCKEY_X, KeyEvent.KEYCODE_DPAD_RIGHT);
65 | controller_CastleQuest_Game.addKey("Up", ":", -1, 0, 1f, 1f, BeebKeys.BBCKEY_COLON, KeyEvent.KEYCODE_DPAD_UP);
66 | controller_CastleQuest_Game.addKey("Down", "/", -1, 1, 1f, 1f, BeebKeys.BBCKEY_SLASH, KeyEvent.KEYCODE_DPAD_DOWN);
67 | controller_CastleQuest_Game.addKey("Jump", "Return", -2, 1, 2f, 1f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1);
68 | controller_CastleQuest_Game.addKey("Pick Up", "P", -1, 0, 1f, 1f, BeebKeys.BBCKEY_P, KeyEvent.KEYCODE_BUTTON_Y);
69 | controller_CastleQuest_Game.addKey("Drop", "D", -2, 0, 1f, 1f, BeebKeys.BBCKEY_D, KeyEvent.KEYCODE_DPAD_CENTER);
70 | controller_CastleQuest_Game.useDPad = true;
71 | controller_ChuckieEgg_Game.addKey("Left", ",", 0, -1, 1f, 1f, BeebKeys.BBCKEY_COMMA, KeyEvent.KEYCODE_DPAD_LEFT);
72 | controller_ChuckieEgg_Game.addKey("Right", ".", 1, -1, 1f, 1f, BeebKeys.BBCKEY_PERIOD, KeyEvent.KEYCODE_DPAD_RIGHT);
73 | controller_ChuckieEgg_Game.addKey("Up", "A", -2, 0, 1f, 1f, BeebKeys.BBCKEY_A, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_BUTTON_Y);
74 | controller_ChuckieEgg_Game.addKey("Down", "Z", -2, 1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_CENTER);
75 | controller_ChuckieEgg_Game.addKey("Jump", " ", -1, 0, 1f, 2f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_BACK);
76 | controller_ChuckieEgg_Game.addKey("S", "S", -1.75f, 1f, .5f, .5f, BeebKeys.BBCKEY_S);
77 | controller_ChuckieEgg_Game.addKey("1", "1", -1.75f, 1.5f, .5f, .5f, BeebKeys.BBCKEY_1);
78 | controller_ChuckieEgg_Game.useDPad = true;
79 | controller_ChuckieEgg_Game_Alt.addKey("Left", ",", 0, -1, 1f, 1f, BeebKeys.BBCKEY_COMMA, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
80 | controller_ChuckieEgg_Game_Alt.addKey("Right", ".", 1, -1, 1f, 1f, BeebKeys.BBCKEY_PERIOD, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
81 | controller_ChuckieEgg_Game_Alt.addKey("Up", "A", -2, 0, 1f, 1f, BeebKeys.BBCKEY_A, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_BUTTON_Y);
82 | controller_ChuckieEgg_Game_Alt.addKey("Down", "Z", -2, 1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
83 | controller_ChuckieEgg_Game_Alt.addKey("Jump", " ", -1, 0, 1f, 2f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1);
84 | controller_ChuckieEgg_Game_Alt.addKey("S", "S", -1.75f, 1f, .5f, .5f, BeebKeys.BBCKEY_S);
85 | controller_ChuckieEgg_Game_Alt.addKey("1", "1", -1.75f, 1.5f, .5f, .5f, BeebKeys.BBCKEY_1);
86 | controller_ChuckieEgg_Game_Alt.useDPad = true;
87 | controller_DareDevilDennis_Game.addKey("Accel", "Shift", 0, 0, 1f, 2f, BeebKeys.BBCKEY_SHIFT, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
88 | controller_DareDevilDennis_Game.addKey("Stop", "Return", 1, 0, 1f, 2f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
89 | controller_DareDevilDennis_Game.addKey("Jump", "", -2, 0, 2f, 2f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1);
90 | controller_Imogen_Game.addKey("Left", "Z", 0, -1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
91 | controller_Imogen_Game.addKey("Right", "X", 1, -1, 1f, 1f, BeebKeys.BBCKEY_X, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
92 | controller_Imogen_Game.addKey("Up", ":", -2, 0, 1f, 1f, BeebKeys.BBCKEY_COLON, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_BUTTON_Y);
93 | controller_Imogen_Game.addKey("Down", "/", -2, 1, 1f, 1f, BeebKeys.BBCKEY_SLASH, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
94 | controller_Imogen_Game.addKey("Fire", "Return", -1, 0, 1f, 2f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1);
95 | controller_Imogen_Game.addKey("<-", "<-", -2, 0, .5f, .5f, BeebKeys.BBCKEY_ARROW_LEFT, KeyEvent.KEYCODE_BUTTON_Y);
96 | controller_Imogen_Game.addKey("->", "->", -2, 0.5f, .5f, .5f, BeebKeys.BBCKEY_ARROW_RIGHT, KeyEvent.KEYCODE_BACK);
97 | controller_Imogen_Game.addKey("[]", "[]", -2, 1, .5f, .5f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_DPAD_CENTER);
98 | controller_Imogen_Game.useDPad = true;
99 | controller_Thrust_Game.addKey("Left","Caps", 0f, -1, 1f, 1f, BeebKeys.BBCKEY_CAPS, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
100 | controller_Thrust_Game.addKey("Right","Ctrl", 1f, -1, 1f, 1f, BeebKeys.BBCKEY_CTRL, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
101 | controller_Thrust_Game.addKey("Thrust","Shift", -1f, 0, 1f, 2f, BeebKeys.BBCKEY_SHIFT, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
102 | controller_Thrust_Game.addKey("Fire","Return", -2f, 0, 1f, 1f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_BUTTON_R1);
103 | controller_Thrust_Game.addKey("Shield","", -2f, 1, 1f, 1f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_BUTTON_L1);
104 | controller_Planetoid_Game.addKey("Up", "A", 1, 0, 1f, 1f, BeebKeys.BBCKEY_A, KeyEvent.KEYCODE_DPAD_UP);
105 | controller_Planetoid_Game.addKey("Down", "Z", 1, 1, 1f, 1f, BeebKeys.BBCKEY_Z, KeyEvent.KEYCODE_DPAD_DOWN);
106 | controller_Planetoid_Game.addKey("Forwards", "SHIFT", 2, 0.5f, 1f, 1f, BeebKeys.BBCKEY_SHIFT, KeyEvent.KEYCODE_DPAD_RIGHT);
107 | controller_Planetoid_Game.addKey("Reverse", "SPACE", 0, 0.5f, 1f, 1f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_DPAD_LEFT);
108 | controller_Planetoid_Game.addKey("Fire", "Return", -2, 0, 2f, 1f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_DPAD_CENTER);
109 | controller_Planetoid_Game.addKey("Bomb", "Tab", -1.5f, 1.2f, 1f, 1f, BeebKeys.BBCKEY_TAB, KeyEvent.KEYCODE_BACK);
110 | controller_Elite_Game.addKey("Left", "<", 0, 0.8f, .75f, .75f, BeebKeys.BBCKEY_LESS_THAN, KeyEvent.KEYCODE_DPAD_LEFT);
111 | controller_Elite_Game.addKey("Right", ">", 1.5f, 0.8f, .75f, .75f, BeebKeys.BBCKEY_MORE_THAN, KeyEvent.KEYCODE_DPAD_RIGHT);
112 | controller_Elite_Game.addKey("Up", "S", .75f, .5f, .75f, .75f, BeebKeys.BBCKEY_S, KeyEvent.KEYCODE_DPAD_UP);
113 | controller_Elite_Game.addKey("Down", "X", .75f, 1.25f, .75f, .75f, BeebKeys.BBCKEY_X, KeyEvent.KEYCODE_DPAD_DOWN);
114 | controller_Elite_Game.addKey("Fire", "A", -.75f, 0, .75f, 2f, BeebKeys.BBCKEY_A, KeyEvent.KEYCODE_DPAD_CENTER);
115 | controller_Elite_Game.addKey("Acc.", "SPC",-1.35f, 0, .5f, 1f, BeebKeys.BBCKEY_SPACE, KeyEvent.KEYCODE_DPAD_CENTER);
116 | controller_Elite_Game.addKey("Dec.", "?", -1.35f, 1, .5f, 1f, BeebKeys.BBCKEY_QUESTIONMARK, KeyEvent.KEYCODE_DPAD_CENTER);
117 | controller_Elite_Game.addKey("F0", "Launch", 0f, 0, .5f, .5f, BeebKeys.BBCKEY_F0);
118 | controller_Elite_Game.addKey("F1", "Rear", .5f, 0, .5f, .5f, BeebKeys.BBCKEY_F1);
119 | controller_Elite_Game.addKey("F2", "Left", 1f, 0, .5f, .5f, BeebKeys.BBCKEY_F2);
120 | controller_Elite_Game.addKey("F3", "Right", 1.5f, 0, .5f, .5f, BeebKeys.BBCKEY_F3);
121 | controller_Zalaga_Game.addKey("Left","Caps", 0f, 0, 1.25f, 1.25f, BeebKeys.BBCKEY_CAPS, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_BUTTON_X);
122 | controller_Zalaga_Game.addKey("Right","Ctrl", 1.25f, 0, 1.25f, 1.25f, BeebKeys.BBCKEY_CTRL, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_BACK);
123 | controller_Zalaga_Game.addKey("Fire","Return", -1f, 0, 1f, 1.25f, BeebKeys.BBCKEY_ENTER, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1);
124 | }
125 |
126 | //
127 | // This section maps disk keys to built-in ControllerInfos
128 | //
129 | static Map controllersForKnownDisks = new HashMap();
130 | static {
131 | controllersForKnownDisks.put("arcadians", controller_Arcadians_Menu);
132 | controllersForKnownDisks.put("castle_quest", controller_CastleQuest_Game);
133 | //controllersForKnownDisks.put("chuckie_egg", controller_ChuckieEgg_Game);
134 | controllersForKnownDisks.put("chuckie_egg", controller_ChuckieEgg_Game_Alt);
135 | controllersForKnownDisks.put("dare_devil_dennis", controller_DareDevilDennis_Game);
136 | controllersForKnownDisks.put("firetrack", controller_ZX_4way);
137 | controllersForKnownDisks.put("gimpo", controller_ZX_4way);
138 | controllersForKnownDisks.put("hyper_viper", controller_ZX_4way);
139 | controllersForKnownDisks.put("elite", controller_Elite_Game);
140 | controllersForKnownDisks.put("imogen", controller_Imogen_Game);
141 | controllersForKnownDisks.put("qman", controller_Qman_Game);
142 | controllersForKnownDisks.put("planetoid", controller_Planetoid_Game);
143 | controllersForKnownDisks.put("repton1", controller_ZX_4way);
144 | controllersForKnownDisks.put("repton2", controller_ZX_4way);
145 | controllersForKnownDisks.put("repton3", controller_ZX_4way);
146 | controllersForKnownDisks.put("repton_infinity", controller_ZX_4way);
147 | controllersForKnownDisks.put("repton_thru_time", controller_ZX_4way);
148 | controllersForKnownDisks.put("ripton", controller_ZX_4way);
149 | controllersForKnownDisks.put("rocket_raid", controller_RocketRaid_Game);
150 | controllersForKnownDisks.put("snapper", controller_ZX_4way);
151 | controllersForKnownDisks.put("thrust", controller_Thrust_Game);
152 | controllersForKnownDisks.put("zalaga", controller_Zalaga_Game);
153 | }
154 | }
155 |
--------------------------------------------------------------------------------