Android: Expose custom rtc options

This commit is contained in:
Charles Lombardo 2023-01-17 13:18:33 -05:00
parent d63462a14e
commit bbb83054af
8 changed files with 173 additions and 0 deletions

View File

@ -44,6 +44,8 @@ public enum BooleanSetting implements AbstractBooleanSetting
MAIN_OVERCLOCK_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "OverclockEnable", false),
MAIN_RAM_OVERRIDE_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "RAMOverrideEnable",
false),
MAIN_CUSTOM_RTC_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableCustomRTC",
false),
MAIN_AUTO_DISC_CHANGE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AutoDiscChange", false),
MAIN_ALLOW_SD_WRITES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "WiiSDCardAllowWrites",
true),
@ -267,6 +269,7 @@ public enum BooleanSetting implements AbstractBooleanSetting
MAIN_PAUSE_ON_PANIC,
MAIN_ACCURATE_CPU_CACHE,
MAIN_RAM_OVERRIDE_ENABLE,
MAIN_CUSTOM_RTC_ENABLE,
MAIN_DSP_JIT,
};

View File

@ -21,6 +21,9 @@ public enum StringSetting implements AbstractStringSetting
MAIN_BBA_BUILTIN_DNS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_BUILTIN_DNS",
"149.56.167.128"),
MAIN_CUSTOM_RTC_VALUE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CustomRTCValue",
"0x386d4380"),
MAIN_GFX_BACKEND(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "GFXBackend",
NativeLibrary.GetDefaultGraphicsBackendName()),
@ -39,6 +42,7 @@ public enum StringSetting implements AbstractStringSetting
"PostProcessingShader", "");
private static final StringSetting[] NOT_RUNTIME_EDITABLE_ARRAY = new StringSetting[]{
MAIN_CUSTOM_RTC_VALUE,
MAIN_GFX_BACKEND,
};

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.settings.model.view
import android.content.Context
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
import org.dolphinemu.dolphinemu.features.settings.model.Settings
class DateTimeChoiceSetting(
context: Context,
private val setting: AbstractStringSetting,
nameId: Int,
descriptionId: Int
) : SettingsItem(context, nameId, descriptionId) {
override fun getType(): Int {
return TYPE_DATETIME_CHOICE
}
override fun getSetting(): AbstractSetting {
return setting
}
fun setSelectedValue(settings: Settings?, selection: String) {
setting.setString(settings, selection)
}
fun getSelectedValue(settings: Settings): String {
return setting.getString(settings)
}
}

View File

@ -29,6 +29,7 @@ public abstract class SettingsItem
public static final int TYPE_RUN_RUNNABLE = 10;
public static final int TYPE_STRING = 11;
public static final int TYPE_HYPERLINK_HEADER = 12;
public static final int TYPE_DATETIME_CHOICE = 13;
private final CharSequence mName;
private final CharSequence mDescription;

View File

@ -9,6 +9,7 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.provider.DocumentsContract;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
@ -20,10 +21,14 @@ import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.color.MaterialColors;
import com.google.android.material.datepicker.CalendarConstraints;
import com.google.android.material.datepicker.MaterialDatePicker;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.elevation.ElevationOverlayProvider;
import com.google.android.material.slider.Slider;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.timepicker.MaterialTimePicker;
import com.google.android.material.timepicker.TimeFormat;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.databinding.DialogInputStringBinding;
@ -34,6 +39,7 @@ import org.dolphinemu.dolphinemu.databinding.ListItemSettingSwitchBinding;
import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding;
import org.dolphinemu.dolphinemu.dialogs.MotionAlertDialog;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.model.view.DateTimeChoiceSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
import org.dolphinemu.dolphinemu.features.settings.model.view.FloatSliderSetting;
@ -47,6 +53,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.DateTimeSettingViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.FilePickerViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.HeaderHyperLinkViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.HeaderViewHolder;
@ -68,6 +75,8 @@ import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.TimeZone;
public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolder>
implements DialogInterface.OnClickListener, Slider.OnChangeListener
@ -135,6 +144,9 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
case SettingsItem.TYPE_HYPERLINK_HEADER:
return new HeaderHyperLinkViewHolder(ListItemHeaderBinding.inflate(inflater), this);
case SettingsItem.TYPE_DATETIME_CHOICE:
return new DateTimeSettingViewHolder(ListItemSettingBinding.inflate(inflater), this);
default:
throw new IllegalArgumentException("Invalid view type: " + viewType);
}
@ -366,6 +378,63 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
mView.getActivity().startActivityForResult(intent, filePicker.getRequestType());
}
public void onDateTimeClick(DateTimeChoiceSetting item, int position)
{
mClickedItem = item;
mClickedPosition = position;
long storedTime = Long.decode(item.getSelectedValue(mView.getSettings())) * 1000;
// Helper to extract hour and minute from epoch time
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(storedTime);
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
// Start and end epoch times available for the Wii's date picker
CalendarConstraints calendarConstraints = new CalendarConstraints.Builder()
.setStart(946684800000L)
.setEnd(2082672000000L)
.build();
int timeFormat = TimeFormat.CLOCK_12H;
if (DateFormat.is24HourFormat(mView.getActivity()))
{
timeFormat = TimeFormat.CLOCK_24H;
}
MaterialDatePicker<Long> datePicker = MaterialDatePicker.Builder.datePicker()
.setSelection(storedTime)
.setTitleText(R.string.select_rtc_date)
.setCalendarConstraints(calendarConstraints)
.build();
MaterialTimePicker timePicker = new MaterialTimePicker.Builder()
.setTimeFormat(timeFormat)
.setHour(calendar.get(Calendar.HOUR_OF_DAY))
.setMinute(calendar.get(Calendar.MINUTE))
.setTitleText(R.string.select_rtc_time)
.build();
datePicker.addOnPositiveButtonClickListener(
selection -> timePicker.show(mView.getActivity().getSupportFragmentManager(),
"TimePicker"));
timePicker.addOnPositiveButtonClickListener(selection ->
{
long epochTime = datePicker.getSelection() / 1000;
epochTime += (long) timePicker.getHour() * 60 * 60;
epochTime += (long) timePicker.getMinute() * 60;
String rtcString = "0x" + Long.toHexString(epochTime);
if (!item.getSelectedValue(mView.getSettings()).equals(rtcString))
{
notifyItemChanged(mClickedPosition);
mView.onSettingChanged();
}
item.setSelectedValue(mView.getSettings(), rtcString);
mClickedItem = null;
});
datePicker.show(mView.getActivity().getSupportFragmentManager(), "DatePicker");
}
public void onFilePickerConfirmation(String selectedFile)
{
FilePicker filePicker = (FilePicker) mClickedItem;

View File

@ -25,6 +25,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.PostProcessing;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.WiimoteProfileStringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.DateTimeChoiceSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
import org.dolphinemu.dolphinemu.features.settings.model.view.HeaderSetting;
@ -811,6 +812,12 @@ public final class SettingsFragmentPresenter
sl.add(new SingleChoiceSetting(mContext, synchronizeGpuThread, R.string.synchronize_gpu_thread,
R.string.synchronize_gpu_thread_description, R.array.synchronizeGpuThreadEntries,
R.array.synchronizeGpuThreadValues));
sl.add(new HeaderSetting(mContext, R.string.custom_rtc_options, 0));
sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_CUSTOM_RTC_ENABLE,
R.string.custom_rtc_enable, R.string.custom_rtc_description));
sl.add(new DateTimeChoiceSetting(mContext, StringSetting.MAIN_CUSTOM_RTC_VALUE,
R.string.set_custom_rtc, 0));
}
private void addSerialPortSubSettings(ArrayList<SettingsItem> sl, int serialPort1Type)

View File

@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
import android.text.TextUtils
import android.view.View
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
import org.dolphinemu.dolphinemu.features.settings.model.view.DateTimeChoiceSetting
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
class DateTimeSettingViewHolder(
private val binding: ListItemSettingBinding,
adapter: SettingsAdapter
) : SettingViewHolder(binding.root, adapter) {
private var mItem: DateTimeChoiceSetting? = null
override fun bind(item: SettingsItem) {
mItem = item as DateTimeChoiceSetting
val inputTime = mItem!!.getSelectedValue(adapter.settings)
binding.textSettingName.text = item.getName()
if (!TextUtils.isEmpty(inputTime)) {
val epochTime = inputTime.substring(2).toLong(16)
val instant = Instant.ofEpochMilli(epochTime * 1000)
val zonedTime = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"))
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
binding.textSettingDescription.text = dateFormatter.format(zonedTime)
} else {
binding.textSettingDescription.text = item.getDescription()
}
setStyle(binding.textSettingName, mItem)
}
override fun onClick(clicked: View) {
if (!mItem!!.isEditable) {
showNotRuntimeEditableError()
return
}
adapter.onDateTimeClick(mItem, bindingAdapterPosition)
setStyle(binding.textSettingName, mItem)
}
override fun getItem(): SettingsItem? {
return mItem
}
}

View File

@ -404,6 +404,12 @@
<string name="gpu_options">GPU Options</string>
<string name="synchronize_gpu_thread">Synchronize GPU Thread</string>
<string name="synchronize_gpu_thread_description">Synchronizing the GPU thread reduces the risk of games crashing or becoming unstable with dual core enabled, but can also reduce the performance gain of dual core. If unsure, select \"On Idle Skipping\". Selecting \"Never\" is risky and not recommended!</string>
<string name="custom_rtc_options">Custom RTC Options</string>
<string name="custom_rtc_enable">Enable Custom RTC</string>
<string name="custom_rtc_description">This settings allows you to set a custom real time clock (RTC) separate from your current system time.</string>
<string name="set_custom_rtc">Set Custom RTC</string>
<string name="select_rtc_date">Select RTC Date</string>
<string name="select_rtc_time">Select RTC Time</string>
<!-- Log Configuration -->
<string name="log_submenu">Log</string>