27 Commits

Author SHA1 Message Date
Aaron Culliney
341885e233 Undo selected character highlight when keyboard fades out 2015-12-13 13:38:03 -08:00
Aaron Culliney
87761df512 Avoid using magic row/column numbers when redrawing adjacent characters 2015-12-13 13:24:25 -08:00
Aaron Culliney
f34cf4c384 Band-aid for joystick state corruption after foregrounding 2015-12-13 12:44:03 -08:00
Aaron Culliney
2a51a62127 Avoid NPE when external storage is unavailable 2015-12-13 12:09:49 -08:00
Aaron Culliney
b32a97b6fc Slightly better translation via @stef-pellegrino 2015-12-12 14:50:41 -08:00
Aaron Culliney
6cef33b501 Request and handle external storage permissions on Marshmallow
- Also disentangles exposing APK assets internally and on external storage
2015-12-12 13:38:22 -08:00
Aaron Culliney
ac78e00afa Alter UI only on UI thread 2015-12-12 13:29:50 -08:00
Aaron Culliney
b1b55006be Resetting preferences will also quit to re-trigger any migration code 2015-12-12 13:20:47 -08:00
Aaron Culliney
a761c11382 First cut at support for Android versioning and data migrations 2015-12-12 12:09:14 -08:00
Aaron Culliney
d819220a07 Pass Apple2Activity to out getExternalStorageDirectory() function 2015-12-12 12:03:41 -08:00
Aaron Culliney
22914de79c Enable setting to show/hide disk read/write HUD messages 2015-12-12 12:01:41 -08:00
Aaron Culliney
cdb0f7b06b Shunt disk-state-change information back to the Java/Android menu system 2015-12-12 11:42:33 -08:00
Aaron Culliney
edf42b81f9 Improve disk quick save/restore
- Flush disk I/O on save
    - Ignore ephemeral track_valid/track_dirty bits
    - Insure disks are ejected if there was a problem loading state
2015-12-12 00:21:27 -08:00
Aaron Culliney
0aed046b5e Simplify modulo offset calculations in trackimage 2015-12-12 00:17:58 -08:00
Aaron Culliney
ef1963a175 Avoid potential read off end of trackimage 2015-12-12 00:16:14 -08:00
Aaron Culliney
651ac246e3 Flush disk IO on backgrounding 2015-12-11 23:42:57 -08:00
Aaron Culliney
05cb322feb Bump Android version to 1.1.2 2015-12-09 22:46:22 -08:00
Aaron Culliney
0f98a34e06 Refactor naming of user-chosen alternate keyboard 2015-12-09 22:11:44 -08:00
Aaron Culliney
1147ce7cd7 Avoid crash potential by doing less during resource acquisition
- (This also would have fixed ctrlPressed background bug -- previous 02147f3d commit)
2015-12-09 21:56:28 -08:00
Aaron Culliney
02147f3d9a Refactor and avoid NULL deref edge-case
- Bug was triggered if ctrlPressed was true when going to background.  Foregrounding would reset/NULLify the
      GLModel, but attempt to render the ctrl key highlighted before the new GLModel was fully created.
2015-12-09 21:25:09 -08:00
stef-pellegrino
791bb91843 French version 2015-12-09 19:55:37 -08:00
Aaron Culliney
b48cfa2084 First cut at French translation for Android (blame Google for this one ;-) 2015-12-08 22:36:10 -08:00
Aaron Culliney
d96db51bd2 Clarify and clean up a number of settings 2015-12-08 22:35:59 -08:00
Aaron Culliney
2e100c9b67 Remove a bunch of unused string resources 2015-12-08 20:46:22 -08:00
Aaron Culliney
ad7902b41f First cut at Moebius keyboard
- Takes a bit getting used to, but I successfully completed Earth level employing finger-muscle-memory strategies
      from the '80s ;-)
2015-12-07 23:05:03 -08:00
Aaron Culliney
943b8842f7 Show disk track sector change animations 2015-12-07 23:03:44 -08:00
Aaron Culliney
74c951f64f Bump Android version to 1.1.1 2015-12-04 23:10:47 -08:00
16 changed files with 612 additions and 221 deletions

View File

@@ -27,8 +27,8 @@ android {
applicationId "org.deadc0de.apple2ix.basic"
minSdkVersion 10
targetSdkVersion 23
versionCode 10
versionName "1.1.0"
versionCode 12
versionName "1.1.2"
ndk {
moduleName "apple2ix"
}

View File

@@ -11,12 +11,15 @@
package org.deadc0de.apple2ix;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
@@ -35,6 +38,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.deadc0de.apple2ix.basic.BuildConfig;
import org.deadc0de.apple2ix.basic.R;
import org.json.JSONException;
import org.json.JSONObject;
public class Apple2Activity extends Activity {
@@ -89,6 +94,8 @@ public class Apple2Activity extends Activity {
public final static long NATIVE_TOUCH_ASCII_MASK = 0xFF00L;
public final static long NATIVE_TOUCH_SCANCODE_MASK = 0x00FFL;
public final static int REQUEST_PERMISSION_RWSTORE = 42;
private native void nativeOnCreate(String dataDir, int sampleRate, int monoBufferSize, int stereoBufferSize);
private native void nativeOnKeyDown(int keyCode, int metaState);
@@ -97,7 +104,7 @@ public class Apple2Activity extends Activity {
private native void nativeSaveState(String path);
private native void nativeLoadState(String path);
private native String nativeLoadState(String path);
public native void nativeEmulationResume();
@@ -153,12 +160,37 @@ public class Apple2Activity extends Activity {
String dataDir = Apple2DisksMenu.getDataDir(this);
nativeOnCreate(dataDir, sampleRate, monoBufferSize, stereoBufferSize);
final boolean firstTime = !Apple2Preferences.FIRST_TIME_CONFIGURED.booleanValue(this);
Apple2Preferences.FIRST_TIME_CONFIGURED.saveBoolean(this, true);
final boolean firstTime = (Apple2Preferences.EMULATOR_VERSION.intValue(this) != BuildConfig.VERSION_CODE);
if (firstTime) {
// allow for primitive migrations as needed
Apple2Preferences.EMULATOR_VERSION.saveInt(this, BuildConfig.VERSION_CODE);
Log.v(TAG, "Triggering migration to Apple2ix version : "+BuildConfig.VERSION_NAME);
}
showSplashScreen(!firstTime);
Apple2CrashHandler.getInstance().checkForCrashes(this);
boolean extperm = true;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// On Marshmallow+ specifically ask for permission to read/write storage
String readPermission = Manifest.permission.READ_EXTERNAL_STORAGE;
String writePermission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
int hasReadPermission = checkSelfPermission(readPermission);
int hasWritePermission = checkSelfPermission(writePermission);
ArrayList<String> permissions = new ArrayList<String>();
if (hasReadPermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(readPermission);
}
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(writePermission);
}
if (!permissions.isEmpty()) {
extperm = false;
String[] params = permissions.toArray(new String[permissions.size()]);
requestPermissions(params, REQUEST_PERMISSION_RWSTORE);
}
}
mGraphicsInitializedRunnable = new Runnable() {
@Override
public void run() {
@@ -170,11 +202,15 @@ public class Apple2Activity extends Activity {
};
// first-time initializations
final boolean externalStoragePermission = extperm;
if (firstTime) {
new Thread(new Runnable() {
@Override
public void run() {
Apple2DisksMenu.firstTime(Apple2Activity.this);
Apple2DisksMenu.exposeAPKAssets(Apple2Activity.this);
if (externalStoragePermission) {
Apple2DisksMenu.exposeAPKAssetsToExternal(Apple2Activity.this);
}
mSplashScreen.setDismissable(true);
Log.d(TAG, "Finished first time copying...");
}
@@ -197,6 +233,26 @@ public class Apple2Activity extends Activity {
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// We should already be gracefully handling the case where user denies access.
if (requestCode == REQUEST_PERMISSION_RWSTORE) {
boolean grantedPermissions = true;
for (int grant : grantResults) {
if (grant == PackageManager.PERMISSION_DENIED) {
grantedPermissions = false;
break;
}
}
if (grantedPermissions) {
// this will force copying APK files (now that we have permission
Apple2DisksMenu.exposeAPKAssetsToExternal(Apple2Activity.this);
} // else ... we keep nagging on app startup ...
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@Override
protected void onResume() {
super.onResume();
@@ -415,7 +471,7 @@ public class Apple2Activity extends Activity {
/* ... */
}
File storageDir = Apple2DisksMenu.getExternalStorageDirectory();
File storageDir = Apple2DisksMenu.getExternalStorageDirectory(Apple2Activity.this);
if (storageDir != null) {
String storagePath = storageDir.getAbsolutePath();
if (diskPath.contains(storagePath)) {
@@ -588,25 +644,29 @@ public class Apple2Activity extends Activity {
}).setNeutralButton(R.string.quit, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
nativeOnQuit();
Apple2Activity.this.finish();
new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
// ...
}
System.exit(0);
}
}.run();
quitEmulator();
}
}).setNegativeButton(R.string.cancel, null).create();
registerAndShowDialog(rebootQuitDialog);
}
public void quitEmulator() {
nativeOnQuit();
finish();
new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
// ...
}
System.exit(0);
}
}.run();
}
public void maybeSaveRestore() {
nativeEmulationPause();
@@ -621,7 +681,22 @@ public class Apple2Activity extends Activity {
}).setNeutralButton(R.string.restore, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Apple2Activity.this.nativeLoadState(quickSavePath);
// loading state can change the disk inserted ... reflect that in
String jsonData = Apple2Activity.this.nativeLoadState(quickSavePath);
try {
JSONObject map = new JSONObject(jsonData);
String diskPath1 = map.getString("disk1");
boolean readOnly1 = map.getBoolean("readOnly1");
Apple2Preferences.CURRENT_DISK_A.setPath(Apple2Activity.this, diskPath1);
Apple2Preferences.CURRENT_DISK_A_RO.saveBoolean(Apple2Activity.this, readOnly1);
String diskPath2 = map.getString("disk2");
boolean readOnly2 = map.getBoolean("readOnly2");
Apple2Preferences.CURRENT_DISK_B.setPath(Apple2Activity.this, diskPath2);
Apple2Preferences.CURRENT_DISK_B_RO.saveBoolean(Apple2Activity.this, readOnly2);
} catch (JSONException je) {
Log.v(TAG, "OOPS : "+je);
}
Apple2Activity.this.mMainMenu.dismiss();
}
}).setNegativeButton(R.string.cancel, null).create();

View File

@@ -50,25 +50,6 @@ public class Apple2AudioSettingsMenu extends Apple2AbstractMenu {
}
enum SETTINGS implements Apple2AbstractMenu.IMenuEnum {
SPEAKER_ENABLED {
@Override
public final String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.speaker_enable);
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.speaker_enable_summary);
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
convertView = _basicView(activity, this, convertView);
CheckBox cb = _addCheckbox(activity, this, convertView, true);
cb.setEnabled(false);
return convertView;
}
},
SPEAKER_VOLUME {
@Override
public final String getTitle(Apple2Activity activity) {

View File

@@ -75,10 +75,10 @@ public class Apple2DisksMenu implements Apple2MenuView {
}
});
getExternalStorageDirectory();
getExternalStorageDirectory(activity);
}
public static File getExternalStorageDirectory() {
public static File getExternalStorageDirectory(Apple2Activity activity) {
do {
if (sExternalFilesDir != null) {
@@ -135,29 +135,27 @@ public class Apple2DisksMenu implements Apple2MenuView {
return sDataDir;
}
public static void firstTime(Apple2Activity activity) {
public static void exposeAPKAssetsToExternal(Apple2Activity activity) {
getExternalStorageDirectory(activity);
if (sExternalFilesDir == null) {
return;
}
final ProgressBar bar = (ProgressBar) activity.findViewById(R.id.crash_progressBar);
try {
bar.setVisibility(View.VISIBLE);
bar.setIndeterminate(true);
} catch (NullPointerException npe) {
Log.v(TAG, "Whoa, avoided NPE in first time #1");
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
bar.setVisibility(View.VISIBLE);
bar.setIndeterminate(true);
} catch (NullPointerException npe) {
Log.v(TAG, "Avoid NPE in exposeAPKAssetsToExternal #1");
}
}
});
getDataDir(activity);
Log.d(TAG, "First time copying stuff-n-things out of APK for ease-of-NDK access...");
getExternalStorageDirectory();
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"disks", /*to location:*/new File(sDataDir, "disks").getAbsolutePath());
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/new File(sDataDir, "keyboards").getAbsolutePath());
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"shaders", /*to location:*/new File(sDataDir, "shaders").getAbsolutePath());
// expose keyboards to modding
if (sExternalFilesDir != null) {
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/sExternalFilesDir.getAbsolutePath());
}
Log.v(TAG, "Overwriting system files in /sdcard/apple2ix/ (external storage) ...");
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/sExternalFilesDir.getAbsolutePath());
activity.runOnUiThread(new Runnable() {
@Override
@@ -166,7 +164,43 @@ public class Apple2DisksMenu implements Apple2MenuView {
bar.setVisibility(View.INVISIBLE);
bar.setIndeterminate(false);
} catch (NullPointerException npe) {
Log.v(TAG, "Whoa, avoided NPE in first time #2");
Log.v(TAG, "Avoid NPE in exposeAPKAssetsToExternal #2");
}
}
});
}
public static void exposeAPKAssets(Apple2Activity activity) {
final ProgressBar bar = (ProgressBar) activity.findViewById(R.id.crash_progressBar);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
bar.setVisibility(View.VISIBLE);
bar.setIndeterminate(true);
} catch (NullPointerException npe) {
Log.v(TAG, "Avoid NPE in exposeAPKAssets #1");
}
}
});
getDataDir(activity);
Log.d(TAG, "First time copying stuff-n-things out of APK for ease-of-NDK access...");
getExternalStorageDirectory(activity);
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"disks", /*to location:*/new File(sDataDir, "disks").getAbsolutePath());
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"keyboards", /*to location:*/new File(sDataDir, "keyboards").getAbsolutePath());
recursivelyCopyAPKAssets(activity, /*from APK directory:*/"shaders", /*to location:*/new File(sDataDir, "shaders").getAbsolutePath());
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
bar.setVisibility(View.INVISIBLE);
bar.setIndeterminate(false);
} catch (NullPointerException npe) {
Log.v(TAG, "Avoid NPE in exposeAPKAssets #1");
}
}
});
@@ -463,7 +497,7 @@ public class Apple2DisksMenu implements Apple2MenuView {
Arrays.sort(files);
getExternalStorageDirectory();
getExternalStorageDirectory(mActivity);
final boolean includeExternalStoragePath = (sExternalFilesDir != null && isRootPath);
final boolean includeDownloadsPath = (sDownloadFilesDir != null && isRootPath);
final int offset = includeExternalStoragePath ? (includeDownloadsPath ? 2 : 1) : (includeDownloadsPath ? 1 : 0);

View File

@@ -226,7 +226,7 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
File extKeyboardDir = Apple2DisksMenu.getExternalStorageDirectory();
File extKeyboardDir = Apple2DisksMenu.getExternalStorageDirectory(activity);
FilenameFilter kbdJsonFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {

View File

@@ -18,18 +18,19 @@ import android.util.Log;
import java.io.File;
import org.deadc0de.apple2ix.basic.BuildConfig;
import org.deadc0de.apple2ix.basic.R;
public enum Apple2Preferences {
FIRST_TIME_CONFIGURED {
EMULATOR_VERSION {
@Override
public void load(Apple2Activity activity) {
/* ... */
}
@Override
public void saveBoolean(Apple2Activity activity, boolean ignored) {
activity.getPreferences(Context.MODE_PRIVATE).edit().putBoolean(toString(), true).apply();
public void saveInt(Apple2Activity activity, int version) {
activity.getPreferences(Context.MODE_PRIVATE).edit().putInt(toString(), version).apply();
}
},
CURRENT_DISK_PATH {
@@ -99,6 +100,11 @@ public enum Apple2Preferences {
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
load(activity);
}
@Override
public void setPath(Apple2Activity activity, String str) {
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
}
},
CURRENT_DISK_A_RO {
@Override
@@ -133,6 +139,11 @@ public enum Apple2Preferences {
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
load(activity);
}
@Override
public void setPath(Apple2Activity activity, String str) {
activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), str).apply();
}
},
CURRENT_DISK_B_RO {
@Override
@@ -173,22 +184,6 @@ public enum Apple2Preferences {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), HiresColor.INTERPOLATED.ordinal());
}
},
SPEAKER_ENABLED {
@Override
public void load(Apple2Activity activity) {
boolean enabled = booleanValue(activity);
boolean result = nativeSetSpeakerEnabled(enabled);
if (enabled && !result) {
warnError(activity, R.string.speaker_disabled_title, R.string.speaker_disabled_mesg);
activity.getPreferences(Context.MODE_PRIVATE).edit().putBoolean(toString(), false).apply();
}
}
@Override
public boolean booleanValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
}
},
SPEAKER_VOLUME {
@Override
public void load(Apple2Activity activity) {
@@ -295,6 +290,18 @@ public enum Apple2Preferences {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 5);
}
},
SHOW_DISK_OPERATIONS {
@Override
public void load(Apple2Activity activity) {
boolean enabled = booleanValue(activity);
nativeSetShowDiskOperationAnimation(enabled);
}
@Override
public boolean booleanValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true);
}
},
JOYSTICK_AXIS_SENSITIVIY {
@Override
public void load(Apple2Activity activity) {
@@ -911,6 +918,10 @@ public enum Apple2Preferences {
load(activity);
}
public void setPath(Apple2Activity activity, String path) {
/* ... */
}
// accessors
public boolean booleanValue(Apple2Activity activity) {
@@ -941,13 +952,13 @@ public enum Apple2Preferences {
for (Apple2Preferences pref : Apple2Preferences.values()) {
pref.load(activity);
}
// HACK FIXME TODO 2015/12/13 : native GLTouchDevice is conflating various things ... forcefully reset the current touch device here for now
Apple2Preferences.CURRENT_TOUCH_DEVICE.load(activity);
}
public static void resetPreferences(Apple2Activity activity) {
activity.getPreferences(Context.MODE_PRIVATE).edit().clear().commit();
FIRST_TIME_CONFIGURED.saveBoolean(activity, true);
KeypadPreset.IJKM_SPACE.apply(activity);
loadPreferences(activity);
activity.quitEmulator();
}
public String asciiString() {
@@ -1059,6 +1070,8 @@ public enum Apple2Preferences {
private static native void nativeSetTouchMenuVisibility(float alpha);
public static native void nativeSetShowDiskOperationAnimation(boolean enabled);
private static native void nativeSetTouchKeyboardVisibility(float inactiveAlpha, float activeAlpha);
private static native void nativeSetTouchKeyboardLowercaseEnabled(boolean enabled);

View File

@@ -249,6 +249,30 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
});
}
},
SHOW_DISK_OPERATIONS {
@Override
public final String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.disk_show_operation);
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.disk_show_operation_summary);
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
convertView = _basicView(activity, this, convertView);
CheckBox cb = _addCheckbox(activity, this, convertView, Apple2Preferences.SHOW_DISK_OPERATIONS.booleanValue(activity));
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Apple2Preferences.SHOW_DISK_OPERATIONS.saveBoolean(activity, isChecked);
}
});
return convertView;
}
},
ABOUT {
@Override
public final String getTitle(Apple2Activity activity) {

View File

@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#000000</color>
<color name="white">#ffffff</color>
<!-- developer-only options -->
<string name="crasher_summary">Génération du "Test crash"</string>
<string name="crasher_title">Plantage de l\'émulateur</string>
<string name="crash_null">NULL-deref</string>
<string name="crash_java_npe">Java NPE</string>
<string name="crash_stackcall_overflow">stack call overflow</string>
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
<!-- main options -->
<string name="about_apple2ix">A propos d\'Apple2ix…</string>
<string name="about_apple2ix_summary">A propos de ce logiciel</string>
<string name="app_name">Apple2ix</string>
<string name="audio_configure">Configuration audio…</string>
<string name="audio_configure_summary">Volume du haut-parleur, Mockingboard, etc</string>
<string name="audio_latency">Délai audio</string>
<string name="audio_latency_summary">Délai audio en secs</string>
<string name="cancel">Annulation</string>
<string name="color_bw">Noir/blanc</string>
<string name="color_color">Couleurs</string>
<string name="color_interpolated">Interpolation couleurs</string>
<string name="crasher">Plantages</string>
<string name="crasher_check_title">Vérifier les logs de plantage</string>
<string name="crasher_check_summary">Vérifier les logs de plantage avec email au développeur</string>
<string name="crasher_send">Envoyer le log de plantage ?</string>
<string name="crasher_send_message">Désolé, il y a eu un problème. Voulez-vous envoyer le log du plantage au développeur ?</string>
<string name="diskA">Lecteur 1</string>
<string name="diskB">Lecteur 2</string>
<string name="disk_eject">Ejecter</string>
<string name="disk_insert_toast">Insérer la disquette dans le drive en lecture seulement</string>
<string name="disk_insert_could_not_read">Désolé, impossible de lire l\'image disque!</string>
<string name="disk_read_only">Lecture seulement</string>
<string name="disk_read_write">Lecture/Ecriture</string>
<string name="disk_show_operation">Afficher les opérations (disque) ][</string>
<string name="disk_show_operation_summary">Indique si les disques sont en lecture ou en écriture</string>
<string name="emulation_continue">Continuer…</string>
<string name="emulation_settings">Configurations…</string>
<string name="emulation_disks">Chargement de l\'image disque…</string>
<string name="header_disks">Insérer la disquettte :</string>
<string name="input_current">Tactile</string>
<string name="input_current_summary">Choisir l\'appareil courant</string>
<string name="joystick">Joystick</string>
<string name="joystick_axis_sensitivity_summary">Calibrer le joystick (décélérer/accélérer)</string>
<string name="joystick_button_button1">Bouton 1 (Pomme ouverte)</string>
<string name="joystick_button_button2">Bouton 2 (Pomme fermée)</string>
<string name="joystick_button_button_both">Les deux</string>
<string name="joystick_button_button_none">Rien</string>
<string name="joystick_button_tap_button">Sélectionner l\'action</string>
<string name="joystick_button_tap_button_summary">Bouton à activer lors d\'une pression vers le bas</string>
<string name="joystick_button_tapdelay_summary">Délai de pression du bouton Joystick en secondes</string>
<string name="joystick_button_swipe_up_button">Lancement du swipe up</string>
<string name="joystick_button_swipe_up_button_summary">Bouton à lancer sur swipe up</string>
<string name="joystick_button_swipe_down_button">Lancement du swipe down</string>
<string name="joystick_button_swipe_down_button_summary">Bouton à lancer sur swipe down</string>
<string name="joystick_button_threshold_summary">Limite en pts pour switcher sur les bouton Joystick/keypad</string>
<string name="joystick_calibrate">Calibrer…</string>
<string name="joystick_calibrate_summary">Configuration et test des paramètres courants</string>
<string name="joystick_configure">Configuration du joystick…</string>
<string name="joystick_configure_summary">Ajustements tactiles, boutons, etc</string>
<string name="joystick_axisleft">Ajustement du joystick/keypad sur gauche</string>
<string name="joystick_axisleft_summary">Ajustement du Joystick/keypad sur gauche (boutons sur droite)</string>
<string name="joystick_visible">Visibilité Joystick/keypad</string>
<string name="joystick_visible_summary">Montre les controles quand occupé</string>
<string name="key_closed_apple">[PommeFermée]</string>
<string name="key_ctrl">[Ctrl]</string>
<string name="key_down">&#8595;</string>
<string name="key_esc">[ESC]</string>
<string name="key_left">&#8592;</string>
<string name="key_none">[Rien]</string>
<string name="key_open_apple">[PommeOuverte]</string>
<string name="key_ret">[Entrée]</string>
<string name="key_right">&#8594;</string>
<string name="key_space">[Espace]</string>
<string name="key_up">&#8593;</string>
<string name="keyboard">Clavier</string>
<string name="keyboard_choose_alt">Choisir clavier "alt"…</string>
<string name="keyboard_choose_alt_summary">Choisir une configuration clavier customisée</string>
<string name="keyboard_click_enabled">Permettre le click sur une touche</string>
<string name="keyboard_click_enabled_summary">Si disponible, son du click sur une touche</string>
<string name="keyboard_configure">Configuration clavier…</string>
<string name="keyboard_configure_summary">Transparence, minuscules, touches customisées</string>
<string name="keyboard_lowercase_enabled">Permettre les minuscules</string>
<string name="keyboard_lowercase_enabled_summary">Permettre les touches en minuscules</string>
<string name="keyboard_visibility_active">Visibilité quand actif</string>
<string name="keyboard_visibility_active_summary">Voir le clavier quand actif</string>
<string name="keyboard_visibility_inactive">Visibilité quand inactif</string>
<string name="keyboard_visibility_inactive_summary">Clavier visible quand inactif</string>
<string name="keypad">Keypad Joystick</string>
<string name="keypad_calibrate">@string/joystick_calibrate</string>
<string name="keypad_calibrate_summary">@string/joystick_calibrate</string>
<string name="keypad_choose">Sélection des touches du keypad…</string>
<string name="keypad_choose_summary">Sélection des touches pour les axes et boutons</string>
<string name="keypad_choose_title">Axis &amp; boutons</string>
<string name="keypad_choose_current">Choisir XXX Key: </string>
<string name="keypad_configure">Configuration du "keypad joystick"…</string>
<string name="keypad_configure_summary">@string/joystick_configure_summary</string>
<string name="keypad_key_axis_c">Centre</string>
<string name="keypad_key_axis_dn">Bas</string>
<string name="keypad_key_axis_dl">Bas et Gauche</string>
<string name="keypad_key_axis_dr">Bas et Droite</string>
<string name="keypad_key_axis_l">Gauche</string>
<string name="keypad_key_axis_r">Droite</string>
<string name="keypad_key_axis_ul">Haut et Gauche</string>
<string name="keypad_key_axis_up">Haut</string>
<string name="keypad_key_axis_ur">Haut et Droite</string>
<string name="keypad_key_button_tap">Presser</string>
<string name="keypad_key_button_swipeup">Slider vers le haut</string>
<string name="keypad_key_button_swipedown">Slider vers le bas</string>
<string name="keypad_preset_crazy_seafox">Touches Seafox ;-)…</string>
<string name="keypad_preset_custom">Choisir customisation…</string>
<string name="keypad_preset_arrows_space">&#8593;,&#8592;,&#8594;,&#8595;, pressez barre d\'espace</string>
<string name="keypad_preset_az_left_right_space">A,Z,&#8592;,&#8594;, pressez barre d\'espace</string>
<string name="keypad_preset_ijkm_space">I,J,K,M, pressez barre d\'espace</string>
<string name="keypad_preset_left_right_space">&#8592;,&#8594;, pressez barre d\'espace</string>
<string name="keypad_preset_wadx_space">W,A,D,X, pressez barre d\'espace</string>
<string name="keypad_repeat_summary">Répétition des touches en secs</string>
<string name="menu_disks">Chargement de l\'image disque…</string>
<string name="menu_disks_summary">Insérer un fichier image (disque) ][</string>
<string name="menu_settings">Paramètres de l\'émulateur…</string>
<string name="menu_settings_summary">Paramètres généraux, joystick, keyboard</string>
<string name="mockingboard_disabled_title">Mockingboard désactivé</string>
<string name="mockingboard_disabled_mesg">Le Mockingboard ne peut être activé</string>
<string name="mockingboard_enable">Activer le Mockingboard</string>
<string name="mockingboard_enable_summary">Révision C dans Slot 4/5 (redémarrage possible)</string>
<string name="mockingboard_volume">Volume du Mockingboard</string>
<string name="mockingboard_volume_summary">Placer le volume du Mockingboard</string>
<string name="no">Non</string>
<string name="ok">OK</string>
<string name="preferences_reset_title">Reset des préférences</string>
<string name="preferences_reset_summary">Restaurer les préférences par défaut et quitter l\'émulateur</string>
<string name="preferences_reset_really">Etes-vous sûr de vouloir faire un reset?</string>
<string name="preferences_reset_warning">Vous perdrez toutes vos options de configuration</string>
<string name="quit">Quitter</string>
<string name="quit_reboot">Rebooter ou quitter l\'émulateur…</string>
<string name="quit_reboot_choice">Rebooter ou quitter?</string>
<string name="reboot">Rebooter</string>
<string name="restore">Restauration rapide</string>
<string name="save">Sauvegarde rapide</string>
<string name="saverestore">Sauvegarde &amp; restauration…</string>
<string name="saverestore_choice">Sauvegarde de l\'état courant ou restaurer un état précédent?</string>
<string name="saverestore_summary">Sauvegarde/restauration rapide</string>
<string name="skip">Ignorer&#8594;</string>
<string name="speaker_volume">Volume du haut-parleur</string>
<string name="speaker_volume_summary">Placer le volume du haut-parleur</string>
<string name="settings">Options de configuration de l\'émulateur Apple2ix</string>
<string name="settings_advanced">Configuration avancée</string>
<string name="settings_advanced_summary">Attention: ces options peuvent dégrader les performances</string>
<string name="settings_advanced_joystick">Configuration avancée du joystick/keypad</string>
<string name="settings_advanced_joystick_summary">Configuration avancée et tuning de performance</string>
<string name="touch_menu_enable">Activation des menus tactiles</string>
<string name="touch_menu_enable_summary">Activation soft des bouton du menu dans les coins en haut de l\'écran</string>
<string name="touch_menu_visibility">Visibilité du menu tactile</string>
<string name="touch_menu_visibility_summary">Menu tactile visible quand inactif</string>
<string name="video_configure">Configuration de la vidéo…</string>
<string name="video_configure_summary">Configuration des couleurs</string>
</resources>

View File

@@ -4,11 +4,17 @@
<color name="black">#000000</color>
<color name="white">#ffffff</color>
<!-- developer-only options -->
<string name="crasher_summary">Test crash generation</string>
<string name="crasher_title">Crash emulator</string>
<string name="crash_null">NULL-deref</string>
<string name="crash_java_npe">Java NPE</string>
<string name="crash_stackcall_overflow">stack call overflow</string>
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
<!-- main options -->
<string name="about_apple2ix">About Apple2ix…</string>
<string name="about_apple2ix_summary">About this software</string>
<string name="about_apple2">About Apple //e…</string>
<string name="about_apple2_summary">More information about the Apple //e computer</string>
<string name="action_settings">Settings</string>
<string name="app_name">Apple2ix</string>
<string name="audio_configure">Configure audio…</string>
<string name="audio_configure_summary">Speaker volume, Mockingboard, etc</string>
@@ -18,43 +24,30 @@
<string name="color_bw">Black/white</string>
<string name="color_color">Color</string>
<string name="color_interpolated">Interpolated color</string>
<string name="crasher">Crasher</string>
<string name="crasher">Crashes</string>
<string name="crasher_check_title">Check for crash reports</string>
<string name="crasher_check_summary">Check for crash reports to email developer)</string>
<string name="crasher_processing">Processing…</string>
<string name="crasher_processing_message">Processing crash reports…</string>
<string name="crasher_check_summary">Check for crash reports to email developer</string>
<string name="crasher_send">Send crash report?</string>
<string name="crasher_send_message">Sorry there has been a problem. Do you want to send a crash report to the developer?</string>
<string name="crasher_summary">Test crash generation</string>
<string name="crasher_title">Crash emulator</string>
<string name="crash_null">NULL-deref</string>
<string name="crash_java_npe">Java NPE</string>
<string name="crash_stackcall_overflow">stack call overflow</string>
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
<string name="diskA">Drive 1</string>
<string name="diskB">Drive 2</string>
<string name="disk_eject">Eject</string>
<string name="disk_insert_toast">Inserted disk in drive 1 read-only</string>
<string name="disk_insert_could_not_read">OOPS, could not read the disk image!</string>
<string name="disk_insert_toast">Inserted disk in drive read-only</string>
<string name="disk_insert_could_not_read">Sorry, could not read the disk image!</string>
<string name="disk_read_only">Read only</string>
<string name="disk_read_write">Read/write</string>
<string name="disk_show_operation">Show Disk ][ operations</string>
<string name="disk_show_operation_summary">Shows when disk drives are reading or writing</string>
<string name="emulation_continue">Continue…</string>
<string name="emulation_settings">Settings…</string>
<string name="emulation_disks">Load disk image…</string>
<string name="header_disks">Insert disk:</string>
<string name="input_configure">Configure input devices…</string>
<string name="input_configure_summary">Keyboard, joystick, etc</string>
<string name="input_current">Current touch device</string>
<string name="input_current_summary">Choose current touch device</string>
<string name="input_first_joystick">Touch joystick</string>
<string name="input_first_keyboard">Touch keyboard</string>
<string name="joystick">Joystick</string>
<string name="joystickA">Touch Joystick</string>
<string name="joystick_axis_sensitivity_summary">Tune joystick axis sensitivity (decelerate or accelerate)</string>
<string name="joystick_button_axis_enable">Enable button axis</string>
<string name="joystick_button_axis_enable_summary">Enable button axis</string>
<string name="joystick_button_button1">Button1 (Open Apple)</string>
<string name="joystick_button_button2">Button2 (Closed Apple)</string>
<string name="joystick_button_button1">Button 1 (Open Apple)</string>
<string name="joystick_button_button2">Button 2 (Closed Apple)</string>
<string name="joystick_button_button_both">Both</string>
<string name="joystick_button_button_none">None</string>
<string name="joystick_button_tap_button">Tap fire</string>
@@ -69,8 +62,6 @@
<string name="joystick_calibrate_summary">Configure and test current settings</string>
<string name="joystick_configure">Configure joystick…</string>
<string name="joystick_configure_summary">Axis touch, buttons, etc</string>
<string name="joystick_current">Current joystick flavor</string>
<string name="joystick_current_summary">Emulated physical joystick or keypad</string>
<string name="joystick_axisleft">Joystick/keypad axis on left</string>
<string name="joystick_axisleft_summary">Joystick/keypad axis on left (buttons on right)</string>
<string name="joystick_visible">Joystick/keypad visibility</string>
@@ -95,23 +86,17 @@
<string name="keyboard_configure_summary">Transparency, lowercase, custom keys</string>
<string name="keyboard_lowercase_enabled">Enable lowercase</string>
<string name="keyboard_lowercase_enabled_summary">Enable lowercase keys</string>
<string name="keyboard_preset_default">Default</string>
<string name="keyboard_visibility_active">Visibility when active</string>
<string name="keyboard_visibility_active_summary">Keyboard visibility when active</string>
<string name="keyboard_visibility_inactive">Visibility when inactive</string>
<string name="keyboard_visibility_inactive_summary">Keyboard visibility when inactive</string>
<string name="keypad">Keypad Joystick</string>
<string name="keypadA">Touch Keypad Joystick</string>
<string name="keypad_button_tap_button">Tap key:</string>
<string name="keypad_button_swipe_up_button">Swipe up key:</string>
<string name="keypad_button_swipe_down_button">Swipe down key:</string>
<string name="keypad_calibrate">Calibrate…</string>
<string name="keypad_calibrate_summary">Configure and test current settings</string>
<string name="keypad_calibrate">@string/joystick_calibrate</string>
<string name="keypad_calibrate_summary">@string/joystick_calibrate</string>
<string name="keypad_choose">Choose keypad keys…</string>
<string name="keypad_choose_summary">Choose axis and button keys</string>
<string name="keypad_choose_title">Axis &amp; buttons</string>
<string name="keypad_choose_current">Choose XXX Key: </string>
<string name="keypad_chosen_keys">I,J,K,M [Space]</string>
<string name="keypad_configure">Configure keypad joystick…</string>
<string name="keypad_configure_summary">@string/joystick_configure_summary</string>
<string name="keypad_key_axis_c">Center</string>
@@ -130,27 +115,25 @@
<string name="keypad_preset_custom">Choose custom…</string>
<string name="keypad_preset_arrows_space">&#8593;,&#8592;,&#8594;,&#8595;, tap spacebar</string>
<string name="keypad_preset_az_left_right_space">A,Z,&#8592;,&#8594;, tap spacebar</string>
<string name="keypad_preset_ijkl_uo">I,J,L,K, tap U, swipe down O</string>
<string name="keypad_preset_ijkm_space">I,J,K,M, tap spacebar</string>
<string name="keypad_preset_left_right_space">&#8592;,&#8594;, tap spacebar</string>
<string name="keypad_preset_wadx_space">W,A,D,X, tap spacebar</string>
<string name="keypad_repeat_summary">Key repeat threshold in secs</string>
<string name="max">Max</string>
<string name="menu_disks">Load disk image…</string>
<string name="menu_disks_summary">Insert a Disk ][ image file</string>
<string name="menu_settings">Emulator settings…</string>
<string name="menu_settings_summary">General, CPU, Joystick</string>
<string name="menu_settings_summary">General settings, joystick, keyboard</string>
<string name="mockingboard_disabled_title">Mockingboard disabled</string>
<string name="mockingboard_disabled_mesg">Mockingboard could not be enabled</string>
<string name="mockingboard_enable">Enable Mockingboard</string>
<string name="mockingboard_enable_summary">Revision C in Slot 4/5 (may require restart)</string>
<string name="mockingboard_volume">Mockingboard volume</string>
<string name="mockingboard_volume_summary">Set the Mockingboard(s) volume</string>
<string name="mockingboard_volume_summary">Set the Mockingboard volume</string>
<string name="no">No</string>
<string name="ok">OK</string>
<string name="preferences_reset_title">Reset preferences</string>
<string name="preferences_reset_summary">Reset preferences to defaults</string>
<string name="preferences_reset_really">Really reset?</string>
<string name="preferences_reset_summary">Reset preferences to defaults and quit emulator</string>
<string name="preferences_reset_really">Really reset and quit?</string>
<string name="preferences_reset_warning">You will lose your settings</string>
<string name="quit">Quit</string>
<string name="quit_reboot">Reboot or quit emulator…</string>
@@ -162,23 +145,13 @@
<string name="saverestore_choice">Save current state or restore previous?</string>
<string name="saverestore_summary">Quick save and restore</string>
<string name="skip">Skip&#8594;</string>
<string name="spacer"></string>
<string name="speaker_disabled_title">Speaker disabled</string>
<string name="speaker_disabled_mesg">Speaker could not be enabled</string>
<string name="speaker_enable">Enable speaker</string>
<string name="speaker_enable_summary">(Speaker cannot be disabled)</string>
<string name="speaker_volume">Speaker volume</string>
<string name="speaker_volume_summary">Set the speaker volume</string>
<string name="speed_alt">Alternate CPU speed</string>
<string name="speed_cpu">CPU Speed</string>
<string name="settings">Apple2ix emulator settings</string>
<string name="settings_audio">Apple2ix audio settings</string>
<string name="settings_advanced">Advanced settings</string>
<string name="settings_advanced_summary">Warning: these settings may potentially degrade emulation performance</string>
<string name="settings_advanced_summary">Warning: these settings may degrade performance</string>
<string name="settings_advanced_joystick">Advanced joystick/keypad settings</string>
<string name="settings_advanced_joystick_summary">Advanced settings and performance tuning</string>
<string name="tab_general">General</string>
<string name="tab_joystick">Joystick</string>
<string name="touch_menu_enable">Enable touch menus</string>
<string name="touch_menu_enable_summary">Enables soft menu buttons in top screen corners</string>
<string name="touch_menu_visibility">Touch menu visibility</string>

View File

@@ -0,0 +1,19 @@
[
"Alt keyboard optimized for Moebius",
{
"_comment" : "hex code for special glyphs",
"_AA" : "b5",
"_ESC" : "bc",
"_SP" : "b1"
},
["reserved for future use"],
["reserved for future use"],
["_AA", "", "", "", "", "", "", "", "", "D"],
[ "_ESC", "", "", "", "", "", "", "", "", "G"],
[ "Y", "", "", "", "", "", "", "", "", "" ],
[ "N", "", "", "", "", "", "", "I", "O", "P"],
[ "U", "A", "S", "E", "F", "M", "", "K", "L", ";"],
[ "C", "Z", "X", "B", "H", "T", "_SP",",", ".", "/"]
]

View File

@@ -210,6 +210,10 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeEmulationPause(JNIEnv *env,
if (appState != APP_RUNNING) {
return;
}
disk6_flush(0);
disk6_flush(1);
if (cpu_isPaused()) {
return;
}
@@ -355,7 +359,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeSaveState(JNIEnv *env, jobj
(*env)->ReleaseStringUTFChars(env, jPath, path);
}
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeLoadState(JNIEnv *env, jobject obj, jstring jPath) {
jstring Java_org_deadc0de_apple2ix_Apple2Activity_nativeLoadState(JNIEnv *env, jobject obj, jstring jPath) {
const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
assert(cpu_isPaused() && "considered dangerous to save state CPU thread is running");
@@ -366,6 +370,22 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeLoadState(JNIEnv *env, jobj
}
(*env)->ReleaseStringUTFChars(env, jPath, path);
// restoring state may cause a change in disk paths, so we need to notify the Java/Android menu system of the change
// (normally we drive state from the Java/menu side...)
char *disk1 = disk6.disk[0].file_name;
bool readOnly1 = disk6.disk[0].is_protected;
char *disk2 = disk6.disk[1].file_name;
bool readOnly2 = disk6.disk[1].is_protected;
char *str = NULL;
jstring jstr = NULL;
asprintf(&str, "{ disk1 = \"%s\"; readOnly1 = %s; disk2 = \"%s\"; readOnly2 = %s }", (disk1 ?: ""), readOnly1 ? "true" : "false", (disk2 ?: ""), readOnly2 ? "true" : "false");
if (str) {
jstr = (*env)->NewStringUTF(env, str);
FREE(str);
}
return jstr;
}
// ----------------------------------------------------------------------------

View File

@@ -130,6 +130,13 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchMenuEnabled(JNIE
interface_setTouchMenuEnabled(enabled);
}
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetShowDiskOperationAnimation(JNIEnv *env, jclass cls, jboolean enabled) {
LOG("enabled : %d", enabled);
if (video_backend && video_backend->animation_setEnableShowTrackSector) {
video_backend->animation_setEnableShowTrackSector(enabled);
}
}
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchKeyboardLowercaseEnabled(JNIEnv *env, jclass cls, jboolean enabled) {
LOG("enabled : %d", enabled);
keydriver_setLowercaseEnabled(enabled);

View File

@@ -356,6 +356,8 @@ static void denibblize_track(const uint8_t * const src, int drive, uint8_t * con
unsigned int offset = 0;
int sector = -1;
const unsigned int trackwidth = disk6.disk[drive].track_width;
// iterate over 2x sectors (accounting for header and data sections)
for (unsigned int sct2=0; sct2<(NUM_SECTORS<<1)+1; sct2++) {
uint8_t prologue[3] = {0,0,0}; // D5AA..
@@ -367,10 +369,7 @@ static void denibblize_track(const uint8_t * const src, int drive, uint8_t * con
prologue[idx] = byte;
++idx;
}
++offset;
if (offset >= disk6.disk[drive].track_width) {
offset = 0;
}
offset = (offset+1) % trackwidth;
if (idx >= 3) {
break;
}
@@ -383,13 +382,11 @@ static void denibblize_track(const uint8_t * const src, int drive, uint8_t * con
#define SCTOFF 0x4
if (prologue[2] == 0x96) {
// found header prologue : extract sector
offset += SCTOFF;
if (offset >= disk6.disk[drive].track_width) {
RELEASE_LOG("WRAPPING PROLOGUE ...");
offset -= disk6.disk[drive].track_width;
}
sector = ((trackimage[offset++] & 0x55) << 1);
sector |= (trackimage[offset++] & 0x55);
offset = (offset+SCTOFF) % trackwidth;
sector = ((trackimage[offset] & 0x55) << 1);
offset = (offset+1) % trackwidth;
sector |= (trackimage[offset] & 0x55);
offset = (offset+1) % trackwidth;
continue;
}
if (UNLIKELY(prologue[2] != 0xAD)) {
@@ -402,11 +399,7 @@ static void denibblize_track(const uint8_t * const src, int drive, uint8_t * con
uint8_t work_buf[NUM_SIXBIT_NIBS+1];
for (unsigned int idx=0; idx<(NUM_SIXBIT_NIBS+1); idx++) {
work_buf[idx] = trackimage[offset];
++offset;
if (offset >= disk6.disk[drive].track_width) {
offset = 0;
LOG("WARNING : wrapping trackimage ... trk:%d sct:%d [0]:0x%02X", (disk6.disk[drive].phase >> 1), sector, trackimage[offset]);
}
offset = (offset+1) % trackwidth;
}
assert(sector >= 0 && sector < 16 && "invalid previous nibblization");
int sec_off = 256 * disk6.disk[drive].skew_table[ sector ];
@@ -463,6 +456,23 @@ static void save_track_data(int drive) {
disk6.disk[drive].track_dirty = false;
}
static inline void animate_disk_track_sector(void) {
if (video_backend && video_backend->animation_showTrackSector) {
static int previous_sect = 0;
int sect_width = disk6.disk[disk6.drive].track_width>>4; // div-by-16
do {
if (UNLIKELY(sect_width <= 0)) {
break;
}
int sect = disk6.disk[disk6.drive].run_byte/sect_width;
if (sect != previous_sect) {
previous_sect = sect;
video_backend->animation_showTrackSector(disk6.drive, disk6.disk[disk6.drive].phase>>1, sect);
}
} while (0);
}
}
// ----------------------------------------------------------------------------
// Emulator hooks
@@ -536,6 +546,9 @@ GLUE_C_READ(disk_read_write_byte)
if (disk6.disk[disk6.drive].run_byte >= disk6.disk[disk6.drive].track_width) {
disk6.disk[disk6.drive].run_byte = 0;
}
animate_disk_track_sector();
#if DISK_TRACING
if ((disk6.disk[disk6.drive].run_byte % NIB_SEC_SIZE) == 0) {
if (disk6.ddrw) {
@@ -615,6 +628,8 @@ GLUE_C_READ(disk_read_phase)
fprintf(test_write_fp, "NEW TRK:%d\n", (disk6.disk[disk6.drive].phase>>1));
}
#endif
animate_disk_track_sector();
}
return ea == 0xE0 ? 0xFF : floating_bus_hibit(1);
@@ -930,6 +945,8 @@ bool disk6_saveState(StateHelper_s *helper) {
break;
}
disk6_flush(i);
state = (uint8_t)disk6.disk[i].is_protected;
if (!helper->save(fd, &state, 1)) {
break;
@@ -961,17 +978,17 @@ bool disk6_saveState(StateHelper_s *helper) {
LOG("SAVE disk[%lu] (0) <NULL>", i);
}
state = (uint8_t)disk6.disk[i].track_valid;
// Save unused placeholder -- backwards compatibility
state = 0x0;
if (!helper->save(fd, &state, 1)) {
break;
}
LOG("SAVE track_valid[%lu] = %02x", i, state);
state = (uint8_t)disk6.disk[i].track_dirty;
// Save unused placeholder -- backwards compatibility
state = 0x0;
if (!helper->save(fd, &state, 1)) {
break;
}
LOG("SAVE track_dirty[%lu] = %02x", i, state);
state = (uint8_t)disk6.disk[i].phase;
if (!helper->save(fd, &state, 1)) {
@@ -1065,25 +1082,28 @@ bool disk6_loadState(StateHelper_s *helper) {
break;
}
snprintf(namebuf+namelen, gzlen, "%s", EXT_GZ);
namebuf[namelen+gzlen] = '\0';
LOG("LOAD disk[%lu] : (%u) %s", i, namelen, namebuf);
disk6_insert(i, namebuf, disk6.disk[i].is_protected);
namebuf[namelen] = '\0';
if (disk6_insert(i, namebuf, disk6.disk[i].is_protected)) {
snprintf(namebuf+namelen, gzlen, "%s", EXT_GZ);
namebuf[namelen+gzlen] = '\0';
LOG("LOAD disk[%lu] : (%u) %s", i, namelen, namebuf);
if (disk6_insert(i, namebuf, disk6.disk[i].is_protected)) {
break;
}
}
FREE(namebuf);
}
// load placeholder
if (!helper->load(fd, &state, 1)) {
break;
}
disk6.disk[i].track_valid = state;
LOG("LOAD track_valid[%lu] = %02x", i, disk6.disk[i].track_valid);
// load placeholder
if (!helper->load(fd, &state, 1)) {
break;
}
disk6.disk[i].track_dirty = state;
LOG("LOAD track_dirty[%lu] = %02x", i, disk6.disk[i].track_dirty);
if (!helper->load(fd, &state, 1)) {
break;
@@ -1100,6 +1120,8 @@ bool disk6_loadState(StateHelper_s *helper) {
}
if (!loaded_drives) {
disk6_eject(0);
disk6_eject(1);
break;
}

View File

@@ -233,7 +233,6 @@ static void _animation_showMessage(char *messageTemplate, unsigned int cols, uns
nextMessage = message;
nextMessageCols = framedCols;
nextMessageRows = framedRows;
LOG("New message with %d cols %d rows", nextMessageCols, nextMessageRows);
pthread_mutex_unlock(&messageMutex);
}
@@ -314,6 +313,49 @@ static void _animation_showDiskChosen(int drive) {
_animation_showMessage(template, shownCols, DISK_ANIMATION_ROWS);
}
static void _animation_showTrackSector(int drive, int track, int sect) {
#define DISK_TRACK_SECTOR_ROWS 3
#define DISK_TRACK_SECTOR_COLS 9
static char diskTrackSectorTemplate[DISK_TRACK_SECTOR_ROWS][DISK_TRACK_SECTOR_COLS+1] = {
" ",
"D / TT/SS",
" ",
};
char *template = diskTrackSectorTemplate[0];
char c = diskTrackSectorTemplate[1][2];
switch (c) {
case '/':
c = '-';
break;
case '-':
c = '\\';
break;
case '\\':
c = '|';
break;
case '|':
c = '/';
break;
default:
assert(false && "should not happen");
break;
}
snprintf(&diskTrackSectorTemplate[1][0], DISK_TRACK_SECTOR_COLS+1, "%d %c %02X/%02X", drive+1, c, track, sect);
_animation_showMessage(template, DISK_TRACK_SECTOR_COLS, DISK_TRACK_SECTOR_ROWS);
}
static void _animation_setEnableShowTrackSector(bool enabled) {
if (enabled) {
video_backend->animation_showTrackSector = &_animation_showTrackSector;
} else {
video_backend->animation_showTrackSector = NULL;
}
}
__attribute__((constructor(CTOR_PRIORITY_LATE)))
static void _init_glalert(void) {
LOG("Initializing message animation subsystem");
@@ -322,6 +364,8 @@ static void _init_glalert(void) {
video_backend->animation_showPaused = &_animation_showPaused;
video_backend->animation_showCPUSpeed = &_animation_showCPUSpeed;
video_backend->animation_showDiskChosen = &_animation_showDiskChosen;
video_backend->animation_showTrackSector = &_animation_showTrackSector;
video_backend->animation_setEnableShowTrackSector = &_animation_setEnableShowTrackSector;
glnode_registerNode(RENDER_MIDDLE, (GLNode){
.setup = &alert_init,

View File

@@ -33,7 +33,6 @@
#define DEFAULT_CTRL_COL 2
#define ROW_WITH_ADJACENTS (KBD_TEMPLATE_ROWS-1)
#define _ROWOFF 2 // main keyboard row offset
#define KBD_FB_WIDTH (KBD_TEMPLATE_COLS * FONT80_WIDTH_PIXELS)
@@ -82,7 +81,7 @@ static uint8_t kbdTemplateAlt[KBD_TEMPLATE_ROWS][KBD_TEMPLATE_COLS+1] = {
"$|\\XXX.^XX",
};
static uint8_t kbdTemplateArrow[KBD_TEMPLATE_ROWS][KBD_TEMPLATE_COLS+1] = {
static uint8_t kbdTemplateUserAlt[KBD_TEMPLATE_ROWS][KBD_TEMPLATE_COLS+1] = {
"@ @ @ @ @ ",
" ",
" @ ",
@@ -111,7 +110,6 @@ static struct {
static struct {
GLModel *model;
bool modelDirty; // TODO : movement animation
int selectedCol;
int selectedRow;
@@ -164,19 +162,32 @@ static void _rerender_character(int col, int row) {
static inline void _rerender_selected(int col, int row) {
if ((col >= 0) && (row >= 0)) {
_rerender_character(col, row);
if (row == ROW_WITH_ADJACENTS) {
if ((col == 3) || (col == 4) || (col == 8)) {
// rerender certain adjacent keys ...
GLModelHUDKeyboard *hudKeyboard = (GLModelHUDKeyboard *)(kbd.model->custom);
const unsigned int indexRow = (hudKeyboard->tplWidth+1) * row;
uint8_t key = (hudKeyboard->tpl+indexRow)[col];
switch (key) {
case ICONTEXT_LEFTSPACE:
_rerender_character(col+1, row);
}
if ((col == 4) || (col == 5) || (col == 9)) {
_rerender_character(col-1, row);
}
if (col == 3) {
_rerender_character(col+2, row);
}
if (col == 5) {
break;
case ICONTEXT_MIDSPACE:
_rerender_character(col-1, row);
_rerender_character(col+1, row);
break;
case ICONTEXT_RIGHTSPACE:
_rerender_character(col-2, row);
}
_rerender_character(col-1, row);
break;
case ICONTEXT_RETURN_L:
_rerender_character(col+1, row);
break;
case ICONTEXT_RETURN_R:
_rerender_character(col-1, row);
break;
default:
break;
}
}
}
@@ -203,13 +214,13 @@ static inline void _switch_keyboard(GLModel *parent, uint8_t *template) {
}
}
static inline void _toggle_arrows(void) {
static inline void _show_useralt_kbd(void) {
GLModelHUDKeyboard *hudKeyboard = (GLModelHUDKeyboard *)kbd.model->custom;
uint8_t c = hudKeyboard->tpl[_ROWOFF*(KBD_TEMPLATE_COLS+1)];
if (c == ICONTEXT_NONACTIONABLE) {
_switch_keyboard(kbd.model, kbdTemplateUCase[0]);
} else {
_switch_keyboard(kbd.model, kbdTemplateArrow[0]);
_switch_keyboard(kbd.model, kbdTemplateUserAlt[0]);
}
}
@@ -227,6 +238,9 @@ static inline float _get_keyboard_visibility(void) {
alpha -= ((float)deltat.tv_nsec-(NANOSECONDS_PER_SECOND/2)) / (float)(NANOSECONDS_PER_SECOND/2);
if (alpha < minAlpha) {
alpha = minAlpha;
_rerender_selected(kbd.selectedCol, kbd.selectedRow);
kbd.selectedCol = -1;
kbd.selectedRow = -1;
}
}
}
@@ -361,7 +375,7 @@ static inline int64_t _tap_key_at_point(float x, float y) {
case ICONTEXT_MENU_SPROUT:
key = 0;
_toggle_arrows();
_show_useralt_kbd();
break;
case ICONTEXT_GOTO:
@@ -437,7 +451,11 @@ static void _setup_touchkbd_hud(GLModel *parent) {
hudKeyboard->tpl = calloc(size, 1);
hudKeyboard->pixels = calloc(KBD_FB_WIDTH * KBD_FB_HEIGHT, 1);
_switch_keyboard(parent, kbdTemplateUCase[0]);
memcpy(hudKeyboard->tpl, kbdTemplateUCase[0], sizeof(kbdTemplateUCase/* assuming all the same size */));
// setup normal color pixels
hudKeyboard->colorScheme = RED_ON_BLACK;
glhud_setupDefault(parent);
}
static void *_create_touchkbd_hud(void) {
@@ -460,10 +478,24 @@ static void _destroy_touchkbd_hud(GLModel *parent) {
// ----------------------------------------------------------------------------
// GLNode functions
static void gltouchkbd_setup(void) {
LOG("gltouchkbd_setup ...");
static void gltouchkbd_shutdown(void) {
LOG("gltouchkbd_shutdown ...");
if (!isAvailable) {
return;
}
isAvailable = false;
mdlDestroyModel(&kbd.model);
kbd.selectedCol = -1;
kbd.selectedRow = -1;
kbd.ctrlPressed = false;
}
static void gltouchkbd_setup(void) {
LOG("gltouchkbd_setup ... %u", sizeof(kbd));
gltouchkbd_shutdown();
kbd.model = mdlCreateQuad(-1.0, -1.0, KBD_OBJ_W, KBD_OBJ_H, MODEL_DEPTH, KBD_FB_WIDTH, KBD_FB_HEIGHT, (GLCustom){
.create = &_create_touchkbd_hud,
@@ -484,17 +516,6 @@ static void gltouchkbd_setup(void) {
isAvailable = true;
}
static void gltouchkbd_shutdown(void) {
LOG("gltouchkbd_shutdown ...");
if (!isAvailable) {
return;
}
isAvailable = false;
mdlDestroyModel(&kbd.model);
}
static void gltouchkbd_render(void) {
if (!isAvailable) {
return;
@@ -521,11 +542,6 @@ static void gltouchkbd_render(void) {
_HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_TOUCHKBD, kbd.model->textureName);
glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, kbd.model->texWidth, kbd.model->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, kbd.model->texPixels);
}
if (kbd.modelDirty) {
kbd.modelDirty = false;
glBindBuffer(GL_ARRAY_BUFFER, kbd.model->posBufferName);
glBufferData(GL_ARRAY_BUFFER, kbd.model->positionArraySize, kbd.model->positions, GL_DYNAMIC_DRAW);
}
glUniform1i(texSamplerLoc, TEXTURE_ID_TOUCHKBD);
glhud_renderDefault(kbd.model);
}
@@ -567,6 +583,8 @@ static int64_t gltouchkbd_onTouchEvent(interface_touch_event_t action, int point
int64_t flags = TOUCH_FLAGS_KBD | TOUCH_FLAGS_HANDLED;
clock_gettime(CLOCK_MONOTONIC, &kbd.timingBegin);
switch (action) {
case TOUCH_DOWN:
case TOUCH_POINTER_DOWN:
@@ -593,8 +611,6 @@ static int64_t gltouchkbd_onTouchEvent(interface_touch_event_t action, int point
return 0x0LL;
}
clock_gettime(CLOCK_MONOTONIC, &kbd.timingBegin);
return flags;
}
@@ -760,10 +776,10 @@ static void gltouchkbd_loadAltKbd(const char *kbdPath) {
const int size = end - start;
if (size == 1) {
kbdTemplateArrow[row][col] = parsedData.jsonString[start];
kbdTemplateUserAlt[row][col] = parsedData.jsonString[start];
continue;
} else if (size == 0) {
kbdTemplateArrow[row][col] = ICONTEXT_NONACTIONABLE;
kbdTemplateUserAlt[row][col] = ICONTEXT_NONACTIONABLE;
continue;
} else if (size < 0) {
assert(false && "negative size coming from jsmn!");
@@ -789,7 +805,7 @@ static void gltouchkbd_loadAltKbd(const char *kbdPath) {
if (foundMatch) {
start = parsedData.jsonTokens[i+1].start;
uint8_t ch = (uint8_t)strtol(&parsedData.jsonString[start], NULL, /*base:*/16);
kbdTemplateArrow[row][col] = ch;
kbdTemplateUserAlt[row][col] = ch;
break;
}
}
@@ -840,8 +856,8 @@ static void _initialize_keyboard_templates(void) {
}
for (unsigned int i=0; i<KBD_TEMPLATE_ROWS; i++) {
for (unsigned int j=0; j<KBD_TEMPLATE_COLS; j++) {
if (kbdTemplateArrow[i][j] == ' ') {
kbdTemplateArrow[i][j] = ICONTEXT_NONACTIONABLE;
if (kbdTemplateUserAlt[i][j] == ' ') {
kbdTemplateUserAlt[i][j] = ICONTEXT_NONACTIONABLE;
}
}
}
@@ -849,37 +865,37 @@ static void _initialize_keyboard_templates(void) {
kbdTemplateLCase[0][0] = ICONTEXT_UPPERCASE;
kbdTemplateUCase[0][0] = ICONTEXT_SHOWALT1;
kbdTemplateAlt [0][0] = ICONTEXT_UPPERCASE;
kbdTemplateArrow[0][0] = ICONTEXT_UPPERCASE;
kbdTemplateUserAlt[0][0] = ICONTEXT_UPPERCASE;
kbdTemplateUCase[0][2] = ICONTEXT_CTRL;
kbdTemplateLCase[0][2] = ICONTEXT_CTRL;
kbdTemplateAlt [0][2] = ICONTEXT_CTRL;
kbdTemplateArrow[0][2] = ICONTEXT_CTRL;
kbdTemplateUserAlt[0][2] = ICONTEXT_CTRL;
kbdTemplateUCase[0][4] = ICONTEXT_ESC;
kbdTemplateLCase[0][4] = ICONTEXT_ESC;
kbdTemplateAlt [0][4] = ICONTEXT_ESC;
kbdTemplateArrow[0][4] = ICONTEXT_ESC;
kbdTemplateUserAlt[0][4] = ICONTEXT_ESC;
kbdTemplateUCase[0][6] = MOUSETEXT_OPENAPPLE;
kbdTemplateLCase[0][6] = MOUSETEXT_OPENAPPLE;
kbdTemplateAlt [0][6] = MOUSETEXT_OPENAPPLE;
kbdTemplateArrow[0][6] = MOUSETEXT_OPENAPPLE;
kbdTemplateUserAlt[0][6] = MOUSETEXT_OPENAPPLE;
kbdTemplateUCase[0][8] = MOUSETEXT_CLOSEDAPPLE;
kbdTemplateLCase[0][8] = MOUSETEXT_CLOSEDAPPLE;
kbdTemplateAlt [0][8] = MOUSETEXT_CLOSEDAPPLE;
kbdTemplateArrow[0][8] = MOUSETEXT_CLOSEDAPPLE;
kbdTemplateUserAlt[0][8] = MOUSETEXT_CLOSEDAPPLE;
kbdTemplateArrow[2][5] = MOUSETEXT_UP;
kbdTemplateArrow[3][4] = MOUSETEXT_LEFT;
kbdTemplateArrow[3][6] = MOUSETEXT_RIGHT;
kbdTemplateArrow[4][5] = MOUSETEXT_DOWN;
kbdTemplateUserAlt[2][5] = MOUSETEXT_UP;
kbdTemplateUserAlt[3][4] = MOUSETEXT_LEFT;
kbdTemplateUserAlt[3][6] = MOUSETEXT_RIGHT;
kbdTemplateUserAlt[4][5] = MOUSETEXT_DOWN;
kbdTemplateUCase[3][5] = ICONTEXT_MENU_SPROUT;
kbdTemplateLCase[3][5] = ICONTEXT_MENU_SPROUT;
kbdTemplateAlt [3][5] = ICONTEXT_MENU_SPROUT;
kbdTemplateArrow[3][5] = ICONTEXT_MENU_SPROUT;
kbdTemplateUserAlt[3][5] = ICONTEXT_MENU_SPROUT;
kbdTemplateUCase[_ROWOFF+2][0] = ICONTEXT_NONACTIONABLE;
kbdTemplateLCase[_ROWOFF+2][0] = ICONTEXT_NONACTIONABLE;

View File

@@ -39,6 +39,7 @@ typedef struct video_backend_s {
void (*animation_showCPUSpeed)(void);
void (*animation_showDiskChosen)(int drive);
void (*animation_showTrackSector)(int drive, int track, int sect);
void (*animation_setEnableShowTrackSector)(bool enabled);
} video_backend_s;