diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidProgressCallback.java b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidProgressCallback.java
index a68bc821d..a76f48f1d 100644
--- a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidProgressCallback.java
+++ b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidProgressCallback.java
@@ -12,7 +12,7 @@ public class AndroidProgressCallback {
public AndroidProgressCallback(Activity context) {
mContext = context;
mDialog = new ProgressDialog(context);
- mDialog.setMessage("Please wait...");
+ mDialog.setMessage(context.getString(R.string.android_progress_callback_please_wait));
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setIndeterminate(false);
mDialog.setMax(100);
@@ -54,7 +54,7 @@ public class AndroidProgressCallback {
new AlertDialog.Builder(mContext)
.setTitle("Error")
.setMessage(message)
- .setPositiveButton("OK", (dialog, button) -> {
+ .setPositiveButton(mContext.getString(R.string.android_progress_callback_ok), (dialog, button) -> {
dialog.dismiss();
})
.setOnDismissListener((dialogInterface) -> {
@@ -78,9 +78,9 @@ public class AndroidProgressCallback {
Object lock = new Object();
mContext.runOnUiThread(() -> {
new AlertDialog.Builder(mContext)
- .setTitle("Information")
+ .setTitle(mContext.getString(R.string.android_progress_callback_information))
.setMessage(message)
- .setPositiveButton("OK", (dialog, button) -> {
+ .setPositiveButton(mContext.getString(R.string.android_progress_callback_ok), (dialog, button) -> {
dialog.dismiss();
})
.setOnDismissListener((dialogInterface) -> {
@@ -108,13 +108,13 @@ public class AndroidProgressCallback {
ConfirmationResult result = new ConfirmationResult();
mContext.runOnUiThread(() -> {
new AlertDialog.Builder(mContext)
- .setTitle("Confirmation")
+ .setTitle(mContext.getString(R.string.android_progress_callback_confirmation))
.setMessage(message)
- .setPositiveButton("Yes", (dialog, button) -> {
+ .setPositiveButton(mContext.getString(R.string.android_progress_callback_yes), (dialog, button) -> {
result.result = true;
dialog.dismiss();
})
- .setNegativeButton("No", (dialog, button) -> {
+ .setNegativeButton(mContext.getString(R.string.android_progress_callback_no), (dialog, button) -> {
result.result = false;
dialog.dismiss();
})
diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/EmulationActivity.java b/android/app/src/main/java/com/github/stenzek/duckstation/EmulationActivity.java
index 628d5096e..8ed4a49d1 100644
--- a/android/app/src/main/java/com/github/stenzek/duckstation/EmulationActivity.java
+++ b/android/app/src/main/java/com/github/stenzek/duckstation/EmulationActivity.java
@@ -60,9 +60,9 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
private void reportErrorOnUIThread(String message) {
// Toast.makeText(this, message, Toast.LENGTH_LONG);
new AlertDialog.Builder(this)
- .setTitle("Error")
+ .setTitle(R.string.emulation_activity_error)
.setMessage(message)
- .setPositiveButton("OK", (dialog, button) -> {
+ .setPositiveButton(R.string.emulation_activity_ok, (dialog, button) -> {
dialog.dismiss();
enableFullscreenImmersive();
})
@@ -77,9 +77,9 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
runOnUiThread(() -> {
// Toast.makeText(this, message, Toast.LENGTH_LONG);
new AlertDialog.Builder(this)
- .setTitle("Error")
+ .setTitle(R.string.emulation_activity_error)
.setMessage(message)
- .setPositiveButton("OK", (dialog, button) -> {
+ .setPositiveButton(R.string.emulation_activity_ok, (dialog, button) -> {
dialog.dismiss();
enableFullscreenImmersive();
synchronized (lock) {
@@ -448,11 +448,11 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
AlertDialog.Builder builder = new AlertDialog.Builder(this);
CharSequence[] items = new CharSequence[(codes != null) ? (codes.length + 1) : 1];
- items[0] = "Import Patch Codes...";
+ items[0] = getString(R.string.emulation_activity_import_patch_codes);
if (codes != null) {
for (int i = 0; i < codes.length; i++) {
final PatchCode cc = codes[i];
- items[i + 1] = String.format("%s %s", cc.isEnabled() ? "(ON)" : "(OFF)", cc.getDescription());
+ items[i + 1] = String.format("%s %s", cc.isEnabled() ? getString(R.string.emulation_activity_patch_on) : getString(R.string.emulation_activity_patch_off), cc.getDescription());
}
}
@@ -465,7 +465,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
- startActivityForResult(Intent.createChooser(intent, "Choose Patch Code File"), REQUEST_IMPORT_PATCH_CODES);
+ startActivityForResult(Intent.createChooser(intent, getString(R.string.emulation_activity_choose_patch_code_file)), REQUEST_IMPORT_PATCH_CODES);
}
});
builder.setOnCancelListener(dialogInterface -> onMenuClosed());
@@ -475,7 +475,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
private void importPatchesFromFile(Uri uri) {
String str = FileUtil.readFileFromUri(this, uri, 512 * 1024);
if (str == null || !AndroidHostInterface.getInstance().importPatchCodesFromString(str)) {
- reportErrorOnUIThread("Failed to import patch codes. Make sure you selected a PCSXR or Libretro format file.");
+ reportErrorOnUIThread(getString(R.string.emulation_activity_failed_to_import_patch_codes));
}
}
diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java b/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java
index ec5c1aa22..536546dbc 100644
--- a/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java
+++ b/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java
@@ -135,7 +135,7 @@ public class MainActivity extends AppCompatActivity {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- startActivityForResult(Intent.createChooser(i, "Choose directory"),
+ startActivityForResult(Intent.createChooser(i, getString(R.string.main_activity_choose_directory)),
REQUEST_ADD_DIRECTORY_TO_GAME_LIST);
}
@@ -190,11 +190,9 @@ public class MainActivity extends AppCompatActivity {
String path = FileUtil.getFullPathFromUri(uri, this);
if (path.length() < 5) {
new AlertDialog.Builder(this)
- .setTitle("Error")
- .setMessage("Failed to get path for the selected file. Please make sure the file is in internal/external storage.\n\n" +
- "Tap the overflow button in the directory selector.\nSelect \"Show Internal Storage\".\n" +
- "Tap the menu button and select your device name or SD card.")
- .setPositiveButton("OK", (dialog, button) -> {
+ .setTitle(R.string.main_activity_error)
+ .setMessage(R.string.main_activity_get_path_from_file_error)
+ .setPositiveButton(R.string.main_activity_ok, (dialog, button) -> {
})
.create()
.show();
@@ -208,11 +206,9 @@ public class MainActivity extends AppCompatActivity {
String path = FileUtil.getFullPathFromTreeUri(treeUri, this);
if (path.length() < 5) {
new AlertDialog.Builder(this)
- .setTitle("Error")
- .setMessage("Failed to get path for the selected directory. Please make sure the directory is in internal/external storage.\n\n" +
- "Tap the overflow button in the directory selector.\nSelect \"Show Internal Storage\".\n" +
- "Tap the menu button and select your device name or SD card.")
- .setPositiveButton("OK", (dialog, button) -> {
+ .setTitle(R.string.main_activity_error)
+ .setMessage(R.string.main_activity_get_path_from_directory_error)
+ .setPositiveButton(R.string.main_activity_ok, (dialog, button) -> {
})
.create()
.show();
@@ -298,7 +294,7 @@ public class MainActivity extends AppCompatActivity {
}
} else {
Toast.makeText(this,
- "External storage permissions are required to use DuckStation.",
+ R.string.main_activity_external_storage_permissions_error,
Toast.LENGTH_LONG);
finish();
}
@@ -320,7 +316,7 @@ public class MainActivity extends AppCompatActivity {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
- startActivityForResult(Intent.createChooser(intent, "Choose Disc Image"), REQUEST_START_FILE);
+ startActivityForResult(Intent.createChooser(intent, getString(R.string.main_activity_choose_disc_image)), REQUEST_START_FILE);
}
private boolean doBIOSCheck() {
@@ -328,10 +324,10 @@ public class MainActivity extends AppCompatActivity {
return true;
new AlertDialog.Builder(this)
- .setTitle("Missing BIOS Image")
- .setMessage("No BIOS image was found in DuckStation's bios directory. Do you with to locate and import a BIOS image now?")
- .setPositiveButton("Yes", (dialog, button) -> importBIOSImage())
- .setNegativeButton("No", (dialog, button) -> {
+ .setTitle(R.string.main_activity_missing_bios_image)
+ .setMessage(R.string.main_activity_missing_bios_image_prompt)
+ .setPositiveButton(R.string.main_activity_yes, (dialog, button) -> importBIOSImage())
+ .setNegativeButton(R.string.main_activity_no, (dialog, button) -> {
})
.create()
.show();
@@ -343,7 +339,7 @@ public class MainActivity extends AppCompatActivity {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
- startActivityForResult(Intent.createChooser(intent, "Choose BIOS Image"), REQUEST_IMPORT_BIOS_IMAGE);
+ startActivityForResult(Intent.createChooser(intent, getString(R.string.main_activity_choose_bios_image)), REQUEST_IMPORT_BIOS_IMAGE);
}
private void onImportBIOSImageResult(Uri uri) {
@@ -354,7 +350,7 @@ public class MainActivity extends AppCompatActivity {
try {
stream = getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
- Toast.makeText(this, "Failed to open BIOS image.", Toast.LENGTH_LONG);
+ Toast.makeText(this, R.string.main_activity_failed_to_open_bios_image, Toast.LENGTH_LONG);
return;
}
@@ -365,13 +361,13 @@ public class MainActivity extends AppCompatActivity {
while ((len = stream.read(buffer)) > 0) {
os.write(buffer, 0, len);
if (os.size() > MAX_BIOS_SIZE) {
- throw new IOException("BIOS image is too large.");
+ throw new IOException(getString(R.string.main_activity_bios_image_too_large));
}
}
} catch (IOException e) {
new AlertDialog.Builder(this)
- .setMessage("Failed to read BIOS image: " + e.getMessage())
- .setPositiveButton("OK", (dialog, button) -> {
+ .setMessage(getString(R.string.main_activity_failed_to_read_bios_image_prefix) + e.getMessage())
+ .setPositiveButton(R.string.main_activity_ok, (dialog, button) -> {
})
.create()
.show();
@@ -379,11 +375,11 @@ public class MainActivity extends AppCompatActivity {
}
String importResult = AndroidHostInterface.getInstance().importBIOSImage(os.toByteArray());
- String message = (importResult == null) ? "This BIOS image is invalid, or has already been imported." : ("BIOS '" + importResult + "' imported.");
+ String message = (importResult == null) ? getString(R.string.main_activity_invalid_error) : ("BIOS '" + importResult + "' imported.");
new AlertDialog.Builder(this)
.setMessage(message)
- .setPositiveButton("OK", (dialog, button) -> {
+ .setPositiveButton(R.string.main_activity_ok, (dialog, button) -> {
})
.create()
.show();
@@ -392,14 +388,14 @@ public class MainActivity extends AppCompatActivity {
private void showVersion() {
final String message = AndroidHostInterface.getFullScmVersion();
new AlertDialog.Builder(this)
- .setTitle("Version")
+ .setTitle(R.string.main_activity_show_version_title)
.setMessage(message)
- .setPositiveButton("OK", (dialog, button) -> {
+ .setPositiveButton(R.string.main_activity_ok, (dialog, button) -> {
})
- .setNeutralButton("Copy", (dialog, button) -> {
+ .setNeutralButton(R.string.main_activity_copy, (dialog, button) -> {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
if (clipboard != null)
- clipboard.setPrimaryClip(ClipData.newPlainText("Version", message));
+ clipboard.setPrimaryClip(ClipData.newPlainText(getString(R.string.main_activity_show_version_title), message));
})
.create()
.show();
diff --git a/android/app/src/main/res/menu/menu_game_list_entry.xml b/android/app/src/main/res/menu/menu_game_list_entry.xml
index 37ab82ceb..a71da250a 100644
--- a/android/app/src/main/res/menu/menu_game_list_entry.xml
+++ b/android/app/src/main/res/menu/menu_game_list_entry.xml
@@ -3,8 +3,8 @@
xmlns:android="http://schemas.android.com/apk/res/android">
+ android:title="@string/menu_game_list_entry_start_game" />
+ android:title="@string/menu_game_list_entry_resume_game" />
\ No newline at end of file
diff --git a/android/app/src/main/res/menu/menu_main.xml b/android/app/src/main/res/menu/menu_main.xml
index 1ff712b1d..c4533a130 100644
--- a/android/app/src/main/res/menu/menu_main.xml
+++ b/android/app/src/main/res/menu/menu_main.xml
@@ -5,36 +5,36 @@
+ android:title="@string/menu_main_resume_last_session" />
+ android:title="@string/menu_main_start_file" />
+ android:title="@string/menu_main_start_bios" />
+ android:title="@string/menu_main_add_game_directory" />
+ android:title="@string/menu_main_scan_for_new_games" />
+ android:title="@string/menu_main_rescan_all_games" />
+ android:title="@string/menu_main_import_bios" />
+ android:title="@string/menu_main_show_version" />
+ android:title="@string/menu_main_github_repository" />
+ android:title="@string/menu_main_discord_server" />
- DuckStation
Settings
Settings
-
-
- Console
- Behavior
- On-Screen Display
- CPU
- GPU
-
-
Console Region
- Auto
- BIOS Path
Enable TTY Output
Fast Boot
-
-
- Enable Speed Limiter
- Pause On Start
- Sync To Audio
- Sync To Video
-
-
Show Messages
Show Emulation Speed
Show FPS
Show VPS
-
-
CPU Execution Mode
- Interpreter
-
-
GPU Renderer
- Display Linear Filtering
Resolution Scale
- True 24-Bit Color (Disables Dithering)
-
EmulationActivity
- Dummy Button
- DUMMY\nCONTENT
-
-
- Hello blank fragment
- TestControllerActivity
+ Emulation Speed
+ Fast Forward Speed
+ Save State On Exit
+ Pause When Menu Opened
+ Emulation Screen Orientation
+ Load Patch Codes
+ Automatically saves the emulator state when powering down or exiting. You can then resume directly from where you left off next time.
+ Pauses emulation when ingame and the menu is opened.
+ .cht in PCSXR format. Codes can be toggled while ingame.]]>
+ Apply Compatibility Settings
+ Automatically disable enhancements when they are not supported by games.
+ Enable this option to match DuckStation\'s refresh rate with your current monitor or screen. VSync is automatically disabled when it is not possible (e.g. running at non-100% speed).
+ Video Sync
+ CPU Overclocking
+ CD-ROM Region Check
+ Prevents discs from incorrect regions being read by the emulator. Usually safe to disable.
+ CD-ROM Preload Image to RAM
+ Loads the game image into RAM. Useful for network paths that may become unreliable during gameplay. In some cases also eliminates stutter when games initiate audio track playback.
+ PGXP Vertex Cache
+ Uses screen coordinates as a fallback when tracking vertices through memory fails. May improve PGXP compatibility.
+ PGXP CPU Mode
+ Tries to track vertex manipulation through the CPU. Some games require this option for PGXP to be effective. Very slow, and incompatible with the recompiler.
+ CPU Recompiler ICache
+ Determines whether the CPU\'s instruction cache is simulated in the recompiler. Improves accuracy at a small cost to performance. If games are running too fast, try enabling this option.
+ CPU Recompiler Fast Memory Access
+ Makes guest memory access more efficient by using page faults and backpatching. Disable if it is unstable on your device.
+ Presented Frame Limit
+ Logging Level
+ Log To File
+ Writes log messages to duckstation.log in your user directory. Only use for debugging as it slows down emulation.
+ Log To Logcat
+ Writes log messages to the Android message logger. Only useful when attached to a computer with adb.
+ Volume
+ Controls the volume of the emulator\'s sound output.
+ Mute All Sound
+ Prevents the emulator from emitting any sound.
+ Mute CD Audio
+ Forcibly mutes both CD-DA and XA audio from the CD-ROM. Can be used to disable background music in some games.
+ Audio Backend
+ Audio Buffer Size
+ Determines the latency between audio being generated and output to speakers. Smaller values reduce latency, but variations in emulation speed will cause hitches.
+ Audio Sync
+ Throttles the emulation speed based on the audio backend pulling audio frames. This helps to remove noises or crackling if emulation is too fast. Sync will automatically be disabled if not running at 100% speed.
+ Controller Type
+ Enable Analog Mode On Reset
+ Touchscreen Controller View
+ Auto-Hide Touchscreen Controller
+ Hides the touchscreen controller when an external controller is detected.
+ Vibrate On Press
+ Enables a short vibration when a touchscreen button is pressed. Requires \"Vibrate on Touch\" to be enabled on your device.
+ Enable Vibration
+ Forwards rumble from the game to the phone\'s vibration motor.
+ Memory Card 1 Type
+ Memory Card 2 Type
+ Crop Mode
+ Aspect Ratio
+ Linear Upscaling
+ Integer Upscaling
+ Smooths out the image when upscaling the console to the screen.
+ Adds padding to the display area to ensure that the ratio between pixels on the host to pixels in the console is an integer number. May result in a sharper image in some 2D games.
+ Shows on-screen-display messages when events occur such as save states being created/loaded, screenshots being taken, etc.
+ Sets the target emulation speed. It is not guaranteed that this speed will be reached, and if not, the emulator will run as fast as it can manage.
+ Shows the internal frame rate of the game in the top-right corner of the display.
+ Shows the number of frames (or v-syncs) displayed per second by the system in the top-right corner of the display.
+ CD-ROM Read Speedup
+ Speeds up CD-ROM reads by the specified factor. Only applies to double-speed reads, and is ignored when audio is playing. May improve loading speeds in some games, at the cost of breaking others.
+ Skips the BIOS shell/intro, booting directly into the game. Usually safe to enable, but some games break.
+ Multisample Antialiasing
+ True Color Rendering (24-bit, disables dithering)
+ This produces nicer looking gradients at the cost of making some colours look slightly different. Disabling the option also enables dithering. Most games are compatible with this option.
+ Scaled Dithering (scale dither pattern to resolution)
+ Scales the dither pattern to the resolution scale of the emulated GPU. This makes the dither pattern much less obvious at higher resolutions. Usually safe to enable, and only supported by the hardware renderers.
+ Disable Interlacing (force progressive render/scan)
+ Forces the rendering and display of frames to progressive mode. This removes the \"combing\" effect seen in 480i games by rendering them in 480p. Usually safe to enable.
+ Texture Filtering
+ Force NTSC Timings (60hz-on-PAL)
+ Uses NTSC frame timings when the console is in PAL mode, forcing PAL games to run at 60hz.
+ Widescreen Hack
+ Scales vertex positions in screen-space to a widescreen aspect ratio, essentially increasing the field of view from 4:3 to 16:9 in 3D games. Not be compatible with all games.
+ Force 4:3 For 24-Bit Display
+ Switches back to 4:3 display aspect ratio when displaying 24-bit content, usually FMVs.
+ Chroma Smoothing For 24-Bit Display
+ Smooths out blockyness between colour transitions in 24-bit content, usually FMVs. Only applies to the hardware renderers.
+ PGXP Geometry Correction
+ Only works with the hardware renderers. May not be compatible with all games.]]>
+ PGXP Culling Correction
+ Increases the precision of polygon culling, reducing the number of holes in geometry. Requires geometry correction enabled.
+ PGXP Texture Correction
+ Uses perspective-correct interpolation for texture coordinates and colors, straightening out warped textures. Requires geometry correction enabled.
+ PGXP Preserve Projection Precision
+ Enables additional precision for PGXP. May improve visuals in some games but break others.
+ Resume Last Session
+ Start File
+ Start BIOS
+ Add Game Directory
+ Scan For New Games
+ Rescan All Games
+ Import BIOS
+ Show Version
+ GitHub Repository
+ Discord Server
+ Start Game
+ Resume Game
+ Please wait...
+ OK
+ Information
+ Confirmation
+ Yes
+ No
+ Error
+ OK
+ Import Patch Codes...
+ (ON)
+ (OFF)
+ Choose Patch Code File
+ Failed to import patch codes. Make sure you selected a PCSXR or Libretro format file.
+ Choose directory
+ Error
+ Failed to get path for the selected file. Please make sure the file is in internal/external storage.\n\nTap the overflow button in the directory selector.\nSelect "Show Internal Storage".\nTap the menu button and select your device name or SD card.
+ OK
+ Failed to get path for the selected directory. Please make sure the directory is in internal/external storage.\n\nTap the overflow button in the directory selector.\nSelect \"Show Internal Storage\".\nTap the menu button and select your device name or SD card.
+ External storage permissions are required to use DuckStation.
+ Choose Disc Image
+ No BIOS image was found in DuckStation\'s bios directory. Do you with to locate and import a BIOS image now?
+ Missing BIOS Image
+ Yes
+ No
+ Choose BIOS Image
+ Failed to open BIOS image.
+ \"Failed to read BIOS image: \"
+ BIOS image is too large.
+ This BIOS image is invalid, or has already been imported.
+ Version
+ Copy
diff --git a/android/app/src/main/res/xml/advanced_preferences.xml b/android/app/src/main/res/xml/advanced_preferences.xml
index 9f00e9ce8..e689f64c6 100644
--- a/android/app/src/main/res/xml/advanced_preferences.xml
+++ b/android/app/src/main/res/xml/advanced_preferences.xml
@@ -17,7 +17,7 @@
diff --git a/android/app/src/main/res/xml/audio_preferences.xml b/android/app/src/main/res/xml/audio_preferences.xml
index 1ea8ddba5..b8fbede83 100644
--- a/android/app/src/main/res/xml/audio_preferences.xml
+++ b/android/app/src/main/res/xml/audio_preferences.xml
@@ -19,8 +19,8 @@
diff --git a/android/app/src/main/res/xml/controllers_preferences.xml b/android/app/src/main/res/xml/controllers_preferences.xml
index 565ce5ce2..0afa4b74e 100644
--- a/android/app/src/main/res/xml/controllers_preferences.xml
+++ b/android/app/src/main/res/xml/controllers_preferences.xml
@@ -18,7 +18,7 @@
diff --git a/android/app/src/main/res/xml/enhancements_preferences.xml b/android/app/src/main/res/xml/enhancements_preferences.xml
index 6e1c527e3..d7da35dc5 100644
--- a/android/app/src/main/res/xml/enhancements_preferences.xml
+++ b/android/app/src/main/res/xml/enhancements_preferences.xml
@@ -17,18 +17,18 @@
diff --git a/android/app/src/main/res/xml/general_preferences.xml b/android/app/src/main/res/xml/general_preferences.xml
index 8dc24f92e..91180c3d7 100644
--- a/android/app/src/main/res/xml/general_preferences.xml
+++ b/android/app/src/main/res/xml/general_preferences.xml
@@ -18,7 +18,7 @@