Android: Create a per-game configuration view

Android: Pass game configuration options to emu

TODO: Fix inability to reload fragment w/ new settings

Android: Limit preference scope, Avoid static crutch

Android: Obligatory button to commit PGC settings

Android pressures the use of async preferences, but does not properly block threads. This causes the settings from one view to bleed into the next when swapping back and forth. This can be overcome by explicitely writing to the specific pref object.

Android: Add PGC documentation to window
This commit is contained in:
Ender's Games 2018-08-20 16:50:21 -04:00
parent 4e050bb753
commit ef6242d2f7
15 changed files with 467 additions and 264 deletions

View File

@ -208,7 +208,9 @@ int dc_init(int argc,wchar* argv[])
sh4_cpu.Reset(false);
#ifndef _ANDROID
LoadCustom();
#endif
return rv;
}

View File

@ -1,5 +1,6 @@
package com.reicast.emulator;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
@ -101,6 +102,25 @@ public class Emulator extends Application {
JNIdc.dreamtime(DreamTime.getDreamtime());
}
public void getGameConfiguration(String gameId) {
SharedPreferences mPrefs = getSharedPreferences(gameId, Activity.MODE_PRIVATE);
Emulator.unstableopt = mPrefs.getBoolean(pref_unstable, unstableopt);
Emulator.dynsafemode = mPrefs.getBoolean(pref_dynsafemode, dynsafemode);
Emulator.frameskip = mPrefs.getInt(pref_frameskip, frameskip);
Emulator.pvrrender = mPrefs.getBoolean(pref_pvrrender, pvrrender);
Emulator.syncedrender = mPrefs.getBoolean(pref_syncedrender, syncedrender);
Emulator.modvols = mPrefs.getBoolean(pref_modvols, modvols);
}
public void loadGameConfiguration() {
JNIdc.unstable(Emulator.unstableopt ? 1 : 0);
JNIdc.safemode(Emulator.dynsafemode ? 1 : 0);
JNIdc.frameskip(Emulator.frameskip);
JNIdc.pvrrender(Emulator.pvrrender ? 1 : 0);
JNIdc.syncedrender(Emulator.syncedrender ? 1 : 0);
JNIdc.modvols(Emulator.modvols ? 1 : 0);
}
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

View File

@ -18,8 +18,6 @@ import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
@ -35,6 +33,7 @@ import android.view.WindowManager;
import android.widget.TextView;
import com.reicast.emulator.config.Config;
import com.reicast.emulator.config.PGConfigFragment;
import com.reicast.emulator.config.InputFragment;
import com.reicast.emulator.config.OptionsFragment;
import com.reicast.emulator.debug.GenerateLogs;
@ -364,15 +363,6 @@ public class MainActivity extends AppCompatActivity implements
onMainBrowseSelected(true, null, false, null);
}
public void onSettingsReload(Fragment options) {
getSupportFragmentManager().beginTransaction().remove(options).commit();
OptionsFragment optionsFrag = new OptionsFragment();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, optionsFrag, "OPTIONS_FRAG")
.addToBackStack(null).commit();
}
@Override
protected void onPause() {
super.onPause();
@ -449,6 +439,24 @@ public class MainActivity extends AppCompatActivity implements
drawer.closeDrawer(GravityCompat.START);
return true;
case R.id.pgconfig_menu:
PGConfigFragment pgconfigFrag = (PGConfigFragment) getSupportFragmentManager()
.findFragmentByTag("PGCONFIG_FRAG");
if (pgconfigFrag != null) {
if (pgconfigFrag.isVisible()) {
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
pgconfigFrag = new PGConfigFragment();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, pgconfigFrag, "PGCONFIG_FRAG")
.addToBackStack(null).commit();
setTitle(R.string.pgconfig);
drawer.closeDrawer(GravityCompat.START);
return true;
case R.id.input_menu:
InputFragment inputFrag = (InputFragment) getSupportFragmentManager()
.findFragmentByTag("INPUT_FRAG");

View File

@ -1,178 +0,0 @@
package com.reicast.emulator.config;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import com.reicast.emulator.Emulator;
import com.reicast.emulator.R;
public class GameConfigFragment extends Fragment {
private SharedPreferences mPrefs;
// Container Activity must implement this interface
public interface OnClickListener {
void onMainBrowseSelected(boolean browse, String path_entry, boolean games, String query);
void onSettingsReload(Fragment options);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.game_config_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
Emulator app = (Emulator) getActivity().getApplicationContext();
app.getConfigurationPrefs(mPrefs);
// Generate the menu options and fill in existing settings
OnCheckedChangeListener dynarec_options = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_dynarecopt, isChecked).apply();
Emulator.dynarecopt = isChecked;
}
};
CompoundButton dynarec_opt = (CompoundButton) getView().findViewById(
R.id.dynarec_option);
dynarec_opt.setChecked(Emulator.dynarecopt);
dynarec_opt.setOnCheckedChangeListener(dynarec_options);
OnCheckedChangeListener unstable_option = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_unstable, isChecked).apply();
Emulator.unstableopt = isChecked;
}
};
CompoundButton unstable_opt = (CompoundButton) getView().findViewById(
R.id.unstable_option);
if (Emulator.unstableopt) {
unstable_opt.setChecked(true);
} else {
unstable_opt.setChecked(false);
}
unstable_opt.setOnCheckedChangeListener(unstable_option);
OnCheckedChangeListener safemode_option = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_dynsafemode, isChecked).apply();
Emulator.dynsafemode = isChecked;
}
};
CompoundButton safemode_opt = (CompoundButton) getView().findViewById(
R.id.dynarec_safemode);
if (Emulator.dynsafemode) {
safemode_opt.setChecked(true);
} else {
safemode_opt.setChecked(false);
}
safemode_opt.setOnCheckedChangeListener(safemode_option);
final EditText mainFrames = (EditText) getView().findViewById(R.id.current_frames);
mainFrames.setText(String.valueOf(Emulator.frameskip));
final SeekBar frameSeek = (SeekBar) getView().findViewById(R.id.frame_seekbar);
frameSeek.setProgress(Emulator.frameskip);
frameSeek.setIndeterminate(false);
frameSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mainFrames.setText(String.valueOf(progress));
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onStopTrackingTouch(SeekBar seekBar) {
int progress = seekBar.getProgress();
mPrefs.edit().putInt(Emulator.pref_frameskip, progress).apply();
Emulator.frameskip = progress;
}
});
mainFrames.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
Editable frameText = mainFrames.getText();
if (frameText != null) {
int frames = Integer.parseInt(frameText.toString());
frameSeek.setProgress(frames);
mPrefs.edit().putInt(Emulator.pref_frameskip, frames).apply();
Emulator.frameskip = frames;
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
OnCheckedChangeListener pvr_rendering = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_pvrrender, isChecked).apply();
Emulator.pvrrender = isChecked;
}
};
CompoundButton pvr_render = (CompoundButton) getView().findViewById(R.id.render_option);
pvr_render.setChecked(Emulator.pvrrender);
pvr_render.setOnCheckedChangeListener(pvr_rendering);
OnCheckedChangeListener synchronous = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_syncedrender, isChecked).apply();
Emulator.syncedrender = isChecked;
}
};
CompoundButton synced_render = (CompoundButton) getView().findViewById(R.id.syncrender_option);
synced_render.setChecked(Emulator.syncedrender);
synced_render.setOnCheckedChangeListener(synchronous);
OnCheckedChangeListener mod_volumes = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_modvols, isChecked).apply();
Emulator.modvols = isChecked;
}
};
CompoundButton modifier_volumes = (CompoundButton) getView().findViewById(R.id.modvols_option);
modifier_volumes.setChecked(Emulator.modvols);
modifier_volumes.setOnCheckedChangeListener(mod_volumes);
}
}

View File

@ -71,7 +71,6 @@ public class OptionsFragment extends Fragment {
// Container Activity must implement this interface
public interface OnClickListener {
void onMainBrowseSelected(boolean browse, String path_entry, boolean games, String query);
void onSettingsReload(Fragment options);
}
@Override
@ -175,8 +174,7 @@ public class OptionsFragment extends Fragment {
mPrefs.edit().putBoolean(Emulator.pref_usereios, isChecked).apply();
}
};
CompoundButton reios_opt = (CompoundButton) getView().findViewById(
R.id.reios_option);
CompoundButton reios_opt = (CompoundButton) getView().findViewById(R.id.reios_option);
reios_opt.setChecked(mPrefs.getBoolean(Emulator.pref_usereios, false));
reios_opt.setOnCheckedChangeListener(reios_options);
@ -195,15 +193,13 @@ public class OptionsFragment extends Fragment {
}
}
};
CompoundButton details_opt = (CompoundButton) getView().findViewById(
R.id.details_option);
CompoundButton details_opt = (CompoundButton) getView().findViewById(R.id.details_option);
details_opt.setChecked(mPrefs.getBoolean(Config.pref_gamedetails, false));
details_opt.setOnCheckedChangeListener(details_options);
Button gameBrowse = (Button) getView().findViewById(R.id.browse_game_path);
final EditText editGames = (EditText) getView().findViewById(
R.id.game_path);
final EditText editGames = (EditText) getView().findViewById(R.id.game_path);
game_directory = mPrefs.getString(Config.pref_games, game_directory);
editGames.setText(game_directory);
@ -235,19 +231,16 @@ public class OptionsFragment extends Fragment {
String[] bios = getResources().getStringArray(R.array.bios);
codes = getResources().getStringArray(R.array.bioscode);
Spinner bios_spnr = (Spinner) getView().findViewById(
R.id.bios_spinner);
Spinner bios_spnr = (Spinner) getView().findViewById(R.id.bios_spinner);
ArrayAdapter<String> biosAdapter = new ArrayAdapter<String>(
getActivity(), android.R.layout.simple_spinner_item, bios);
biosAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
biosAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
bios_spnr.setAdapter(biosAdapter);
String region = mPrefs.getString("localized", codes[4]);
bios_spnr.setSelection(biosAdapter.getPosition(region), true);
bios_spnr.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
flashBios(codes[pos]);
}
@ -262,12 +255,10 @@ public class OptionsFragment extends Fragment {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_nativeact, isChecked).apply();
Emulator.nativeact = isChecked;
}
};
CompoundButton native_opt = (CompoundButton) getView().findViewById(
R.id.native_option);
native_opt.setChecked(Emulator.nativeact);
CompoundButton native_opt = (CompoundButton) getView().findViewById(R.id.native_option);
native_opt.setChecked(mPrefs.getBoolean(Emulator.pref_nativeact, Emulator.nativeact));
native_opt.setOnCheckedChangeListener(native_options);
OnCheckedChangeListener dynarec_options = new OnCheckedChangeListener() {
@ -275,11 +266,9 @@ public class OptionsFragment extends Fragment {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_dynarecopt, isChecked).apply();
Emulator.dynarecopt = isChecked;
}
};
CompoundButton dynarec_opt = (CompoundButton) getView().findViewById(
R.id.dynarec_option);
CompoundButton dynarec_opt = (CompoundButton) getView().findViewById(R.id.dynarec_option);
dynarec_opt.setChecked(Emulator.dynarecopt);
dynarec_opt.setOnCheckedChangeListener(dynarec_options);
@ -288,16 +277,10 @@ public class OptionsFragment extends Fragment {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_unstable, isChecked).apply();
Emulator.unstableopt = isChecked;
}
};
CompoundButton unstable_opt = (CompoundButton) getView().findViewById(
R.id.unstable_option);
if (Emulator.unstableopt) {
unstable_opt.setChecked(true);
} else {
unstable_opt.setChecked(false);
}
CompoundButton unstable_opt = (CompoundButton) getView().findViewById(R.id.unstable_option);
unstable_opt.setChecked(mPrefs.getBoolean(Emulator.pref_unstable, Emulator.unstableopt));
unstable_opt.setOnCheckedChangeListener(unstable_option);
OnCheckedChangeListener safemode_option = new OnCheckedChangeListener() {
@ -305,36 +288,27 @@ public class OptionsFragment extends Fragment {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_dynsafemode, isChecked).apply();
Emulator.dynsafemode = isChecked;
}
};
CompoundButton safemode_opt = (CompoundButton) getView().findViewById(
R.id.dynarec_safemode);
if (Emulator.dynsafemode) {
safemode_opt.setChecked(true);
} else {
safemode_opt.setChecked(false);
}
CompoundButton safemode_opt = (CompoundButton) getView().findViewById(R.id.dynarec_safemode);
safemode_opt.setChecked(mPrefs.getBoolean(Emulator.pref_dynsafemode, Emulator.dynsafemode));
safemode_opt.setOnCheckedChangeListener(safemode_option);
String[] cables = getResources().getStringArray(
R.array.cable);
Spinner cable_spnr = (Spinner) getView().findViewById(
R.id.cable_spinner);
String[] cables = getResources().getStringArray(R.array.cable);
Spinner cable_spnr = (Spinner) getView().findViewById(R.id.cable_spinner);
ArrayAdapter<String> cableAdapter = new ArrayAdapter<String>(
getActivity(), R.layout.spinner_selected, cables);
cableAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cableAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cable_spnr.setAdapter(cableAdapter);
cable_spnr.setSelection(Emulator.cable - 1, true);
cable_spnr.setSelection(mPrefs.getInt(
Emulator.pref_cable, Emulator.cable) - 1, true);
cable_spnr.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
mPrefs.edit().putInt(Emulator.pref_cable, pos + 1).apply();
Emulator.cable = pos + 1;
}
public void onNothingSelected(AdapterView<?> arg0) {
@ -351,11 +325,10 @@ public class OptionsFragment extends Fragment {
getActivity(), R.layout.spinner_selected, regions);
regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
region_spnr.setAdapter(regionAdapter);
region_spnr.setSelection(Emulator.dcregion, true);
region_spnr.setSelection(mPrefs.getInt(Emulator.pref_dcregion, Emulator.dcregion), true);
region_spnr.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
mPrefs.edit().putInt(Emulator.pref_dcregion, pos).apply();
Emulator.dcregion = pos;
}
@ -372,7 +345,7 @@ public class OptionsFragment extends Fragment {
broadcast_spnr.setAdapter(broadcastAdapter);
int select = 0;
String cast = String.valueOf(Emulator.broadcast);
String cast = String.valueOf(mPrefs.getInt(Emulator.pref_broadcast, Emulator.broadcast));
for (int i = 0; i < broadcasts.length; i++) {
if (broadcasts[i].startsWith(cast + " - "))
select = i;
@ -385,7 +358,6 @@ public class OptionsFragment extends Fragment {
String item = parent.getItemAtPosition(pos).toString();
String selection = item.substring(0, item.indexOf(" - "));
mPrefs.edit().putInt(Emulator.pref_broadcast, Integer.parseInt(selection)).apply();
Emulator.broadcast = Integer.parseInt(selection);
}
@ -398,40 +370,39 @@ public class OptionsFragment extends Fragment {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_limitfps, isChecked).apply();
Emulator.limitfps = isChecked;
}
};
CompoundButton limit_fps = (CompoundButton) getView().findViewById(R.id.limitfps_option);
limit_fps.setChecked(Emulator.limitfps);
limit_fps.setChecked(mPrefs.getBoolean(Emulator.pref_limitfps, Emulator.limitfps));
limit_fps.setOnCheckedChangeListener(limitfps_option);
OnCheckedChangeListener mipmaps_option = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_mipmaps, isChecked).apply();
Emulator.mipmaps = isChecked;
}
};
CompoundButton mipmap_opt = (CompoundButton) getView().findViewById(R.id.mipmaps_option);
mipmap_opt.setChecked(Emulator.mipmaps);
mipmap_opt.setChecked(mPrefs.getBoolean(Emulator.pref_mipmaps, Emulator.mipmaps));
mipmap_opt.setOnCheckedChangeListener(mipmaps_option);
OnCheckedChangeListener full_screen = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_widescreen, isChecked).apply();
Emulator.widescreen = isChecked;
}
};
CompoundButton stretch_view = (CompoundButton) getView().findViewById(R.id.stretch_option);
stretch_view.setChecked(Emulator.widescreen);
stretch_view.setChecked(mPrefs.getBoolean(Emulator.pref_widescreen, Emulator.widescreen));
stretch_view.setOnCheckedChangeListener(full_screen);
int frameskip = mPrefs.getInt(Emulator.pref_frameskip, Emulator.frameskip);
final EditText mainFrames = (EditText) getView().findViewById(R.id.current_frames);
mainFrames.setText(String.valueOf(Emulator.frameskip));
mainFrames.setText(String.valueOf(frameskip));
final SeekBar frameSeek = (SeekBar) getView().findViewById(R.id.frame_seekbar);
frameSeek.setProgress(Emulator.frameskip);
frameSeek.setProgress(frameskip);
frameSeek.setIndeterminate(false);
frameSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
@ -445,7 +416,6 @@ public class OptionsFragment extends Fragment {
public void onStopTrackingTouch(SeekBar seekBar) {
int progress = seekBar.getProgress();
mPrefs.edit().putInt(Emulator.pref_frameskip, progress).apply();
Emulator.frameskip = progress;
}
});
mainFrames.addTextChangedListener(new TextWatcher() {
@ -455,7 +425,6 @@ public class OptionsFragment extends Fragment {
int frames = Integer.parseInt(frameText.toString());
frameSeek.setProgress(frames);
mPrefs.edit().putInt(Emulator.pref_frameskip, frames).apply();
Emulator.frameskip = frames;
}
}
@ -470,32 +439,29 @@ public class OptionsFragment extends Fragment {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_pvrrender, isChecked).apply();
Emulator.pvrrender = isChecked;
}
};
CompoundButton pvr_render = (CompoundButton) getView().findViewById(R.id.render_option);
pvr_render.setChecked(Emulator.pvrrender);
pvr_render.setChecked(mPrefs.getBoolean(Emulator.pref_pvrrender, Emulator.pvrrender));
pvr_render.setOnCheckedChangeListener(pvr_rendering);
OnCheckedChangeListener synchronous = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_syncedrender, isChecked).apply();
Emulator.syncedrender = isChecked;
}
};
CompoundButton synced_render = (CompoundButton) getView().findViewById(R.id.syncrender_option);
synced_render.setChecked(Emulator.syncedrender);
synced_render.setChecked(mPrefs.getBoolean(Emulator.pref_syncedrender, Emulator.syncedrender));
synced_render.setOnCheckedChangeListener(synchronous);
OnCheckedChangeListener mod_volumes = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_modvols, isChecked).apply();
Emulator.modvols = isChecked;
}
};
CompoundButton modifier_volumes = (CompoundButton) getView().findViewById(R.id.modvols_option);
modifier_volumes.setChecked(Emulator.modvols);
modifier_volumes.setChecked(mPrefs.getBoolean(Emulator.pref_modvols, Emulator.modvols));
modifier_volumes.setOnCheckedChangeListener(mod_volumes);
// final EditText bootdiskEdit = (EditText) getView().findViewById(R.id.boot_disk);
@ -559,7 +525,6 @@ public class OptionsFragment extends Fragment {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putBoolean(Emulator.pref_nosound, isChecked).apply();
Emulator.nosound = isChecked;
}
};
boolean sound = mPrefs.getBoolean(Emulator.pref_nosound, false);
@ -589,7 +554,7 @@ public class OptionsFragment extends Fragment {
}
});
Button resetEmu = (Button) getView().findViewById(R.id.reset_emu_settings);
Button resetEmu = (Button) getView().findViewById(R.id.reset_emu_btn);
resetEmu.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
@ -623,12 +588,10 @@ public class OptionsFragment extends Fragment {
for (final String type : mediaTypes) {
filter[i] = new FilenameFilter() {
public boolean accept(File dir, String name) {
if (dir.getName().startsWith(".")
|| name.startsWith(".")) {
if (dir.getName().startsWith(".") || name.startsWith(".")) {
return false;
} else {
return StringUtils.endsWithIgnoreCase(name, "."
+ type);
return StringUtils.endsWithIgnoreCase(name, "." + type);
}
}
};
@ -753,7 +716,7 @@ public class OptionsFragment extends Fragment {
mPrefs.edit().remove(Config.pref_renderdepth).apply();
mPrefs.edit().remove(Config.pref_theme).apply();
mCallback.onSettingsReload(this);
getActivity().finish();
}
private void showToastMessage(String message, int duration) {

View File

@ -0,0 +1,235 @@
package com.reicast.emulator.config;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import com.android.util.FileUtils;
import com.reicast.emulator.Emulator;
import com.reicast.emulator.R;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PGConfigFragment extends Fragment {
private Emulator app;
private Spinner mSpnrConfigs;
private CompoundButton unstable_opt;
private CompoundButton safemode_opt;
private EditText mainFrames;
private SeekBar frameSeek;
private CompoundButton pvr_render;
private CompoundButton synced_render;
private CompoundButton modifier_volumes;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.pgconfig_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
app = (Emulator) getActivity().getApplicationContext();
app.getConfigurationPrefs(PreferenceManager.getDefaultSharedPreferences(getActivity()));
mSpnrConfigs = (Spinner) getView().findViewById(R.id.config_spinner);
new LocateConfigs(PGConfigFragment.this).execute(
getActivity().getFilesDir().getAbsolutePath());
unstable_opt = (CompoundButton) getView().findViewById(R.id.unstable_option);
safemode_opt = (CompoundButton) getView().findViewById(R.id.dynarec_safemode);
mainFrames = (EditText) getView().findViewById(R.id.current_frames);
frameSeek = (SeekBar) getView().findViewById(R.id.frame_seekbar);
pvr_render = (CompoundButton) getView().findViewById(R.id.render_option);
synced_render = (CompoundButton) getView().findViewById(R.id.syncrender_option);
modifier_volumes = (CompoundButton) getView().findViewById(R.id.modvols_option);
}
private void saveSettings(SharedPreferences mPrefs) {
mPrefs.edit().putBoolean(Emulator.pref_unstable, unstable_opt.isChecked())
.putBoolean(Emulator.pref_dynsafemode, safemode_opt.isChecked())
.putInt(Emulator.pref_frameskip, frameSeek.getProgress())
.putBoolean(Emulator.pref_pvrrender, pvr_render.isChecked())
.putBoolean(Emulator.pref_syncedrender, synced_render.isChecked())
.putBoolean(Emulator.pref_modvols, modifier_volumes.isChecked()).apply();
}
private void configureViewByGame(String gameId) {
final SharedPreferences mPrefs = getActivity()
.getSharedPreferences(gameId, Activity.MODE_PRIVATE);
unstable_opt.setChecked(mPrefs.getBoolean(Emulator.pref_unstable, Emulator.unstableopt));
safemode_opt.setChecked(mPrefs.getBoolean(Emulator.pref_dynsafemode, Emulator.dynsafemode));
int frameskip = mPrefs.getInt(Emulator.pref_frameskip, Emulator.frameskip);
mainFrames.setText(String.valueOf(frameskip));
frameSeek.setProgress(frameskip);
frameSeek.setIndeterminate(false);
frameSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mainFrames.setText(String.valueOf(progress));
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mainFrames.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
Editable frameText = mainFrames.getText();
if (frameText != null) {
int frames = Integer.parseInt(frameText.toString());
frameSeek.setProgress(frames);
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
pvr_render.setChecked(mPrefs.getBoolean(Emulator.pref_pvrrender, Emulator.pvrrender));
synced_render.setChecked(mPrefs.getBoolean(Emulator.pref_syncedrender, Emulator.syncedrender));
modifier_volumes.setChecked(mPrefs.getBoolean(Emulator.pref_modvols, Emulator.modvols));
Button savePGC = (Button) getView().findViewById(R.id.save_pg_btn);
savePGC.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
saveSettings(mPrefs);
}
});
}
private static class LocateConfigs extends AsyncTask<String, Integer, List<File>> {
private WeakReference<PGConfigFragment> options;
LocateConfigs(PGConfigFragment context) {
options = new WeakReference<>(context);
}
@Override
protected List<File> doInBackground(String... paths) {
File storage = new File(paths[0]);
String[] mediaTypes = options.get().getResources().getStringArray(R.array.configs);
FilenameFilter[] filter = new FilenameFilter[mediaTypes.length];
int i = 0;
for (final String type : mediaTypes) {
filter[i] = new FilenameFilter() {
public boolean accept(File dir, String name) {
if (dir.getName().startsWith(".") || name.startsWith(".")) {
return false;
} else {
return StringUtils.endsWithIgnoreCase(name, "." + type);
}
}
};
i++;
}
FileUtils fileUtils = new FileUtils();
Collection<File> files = fileUtils.listFiles(storage, filter, 0);
return (List<File>) files;
}
@Override
protected void onPostExecute(List<File> items) {
if (items != null && !items.isEmpty()) {
final Map<String, String> gameMap = new HashMap<>();
String[] titles = new String[items.size()];
for (int i = 0; i < items.size(); i ++) {
String filename = items.get(i).getName();
try {
InputStream iS = options.get().getActivity().openFileInput(filename);
if (iS != null) {
InputStreamReader iSR = new InputStreamReader(iS);
BufferedReader bR = new BufferedReader(iSR);
String readString = "";
StringBuilder stringBuilder = new StringBuilder();
while ( (readString = bR.readLine()) != null ) {
stringBuilder.append(readString);
}
iS.close();
titles[i] = stringBuilder.toString();
gameMap.put(titles[i], filename.substring(0, filename.length() - 4));
}
} catch (IOException e) {
// TODO: Appropriate error message
}
}
ArrayAdapter<String> configAdapter = new ArrayAdapter<String>(
options.get().getActivity(), android.R.layout.simple_spinner_item, titles);
configAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
options.get().mSpnrConfigs.setAdapter(configAdapter);
options.get().mSpnrConfigs.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View select, int pos, long id) {
options.get().configureViewByGame(gameMap.get(
String.valueOf(parent.getItemAtPosition(pos))
));
}
@Override
public void onNothingSelected(AdapterView<?> parentView) {
}
});
} else {
options.get().mSpnrConfigs.setEnabled(false);
}
}
}
}

View File

@ -675,15 +675,19 @@ public class GL2JNIView extends GLSurfaceView
}
void reiosInfo(String reiosId, String reiosSoftware) {
String gameId = reiosId.replaceAll("[^a-zA-Z0-9]+", "").toLowerCase();
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
context.openFileOutput(reiosId+".cfg", Context.MODE_PRIVATE));
context.openFileOutput(gameId + ".pgc", Context.MODE_PRIVATE));
outputStreamWriter.write(reiosSoftware);
outputStreamWriter.close();
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
Emulator app = (Emulator) context.getApplicationContext();
app.getGameConfiguration(gameId);
app.loadGameConfiguration();
}
}

View File

@ -825,7 +825,7 @@
android:orientation="vertical" >
<Button
android:id="@+id/reset_emu_settings"
android:id="@+id/reset_emu_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/reset_emu" />

View File

@ -9,6 +9,46 @@
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/pgc_docs"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="@string/pgc_doc" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginTop="20dp"
android:orientation="vertical" >
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1"
android:text="@string/pgc_select_game" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Spinner
android:id="@+id/config_spinner"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10" >
<requestFocus />
</Spinner>
</LinearLayout>
</LinearLayout>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -213,7 +253,33 @@
android:focusable="true" />
</LinearLayout>
</TableRow>
<TableRow
android:layout_marginTop="10dp"
android:gravity="center_vertical" >
<TextView
android:id="@+id/apply_pg_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:ems="10"
android:gravity="center_vertical|left"
android:text="@string/save_pgc_title" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right"
android:orientation="vertical" >
<Button
android:id="@+id/save_pg_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/write_pgc" />
</LinearLayout>
</TableRow>
</TableLayout>
</LinearLayout>

View File

@ -825,7 +825,7 @@
android:orientation="vertical" >
<Button
android:id="@+id/reset_emu_settings"
android:id="@+id/reset_emu_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/reset_emu" />

View File

@ -9,6 +9,46 @@
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/pgc_docs"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="@string/pgc_doc" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginTop="20dp"
android:orientation="vertical" >
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1"
android:text="@string/pgc_select_game" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Spinner
android:id="@+id/config_spinner"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10" >
<requestFocus />
</Spinner>
</LinearLayout>
</LinearLayout>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -213,7 +253,33 @@
android:focusable="true" />
</LinearLayout>
</TableRow>
<TableRow
android:layout_marginTop="10dp"
android:gravity="center_vertical" >
<TextView
android:id="@+id/apply_pg_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:ems="10"
android:gravity="center_vertical|left"
android:text="@string/save_pgc_title" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right"
android:orientation="vertical" >
<Button
android:id="@+id/save_pg_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/write_pgc" />
</LinearLayout>
</TableRow>
</TableLayout>
</LinearLayout>

View File

@ -12,6 +12,10 @@
android:id="@+id/settings_menu"
android:icon="@drawable/ic_settings"
android:title="@string/settings" />
<item
android:id="@+id/pgconfig_menu"
android:icon="@drawable/ic_settings"
android:title="@string/pgconfig" />
<item
android:id="@+id/input_menu"
android:icon="@drawable/ic_input"

View File

@ -7,6 +7,9 @@
<item android:title="@string/settings"
android:id="@+id/settings_menu"
android:icon="@mipmap/menu_config" />
<item android:title="@string/pgconfig"
android:id="@+id/pgconfig_menu"
android:icon="@mipmap/menu_config" />
<item android:title="@string/input"
android:id="@+id/input_menu"
android:icon="@mipmap/menu_input" />

View File

@ -63,4 +63,8 @@
<item>K</item>
</string-array>
<string-array name="configs">
<item>pgc</item>
</string-array>
</resources>

View File

@ -58,7 +58,12 @@
<string name="reset_emu">Reset Emu</string>
<string name="reset_emu_title">Reset Emulator Settings</string>
<string name="reset_emu_details">Warning: Emulator settings will be cleared. Folder and input settings are not included. This cannot be undone.\nAre you sure you want to continue?</string>
<string name="pgc_doc">Per-Game Configuration\nThese options will override the default settings.\nTo add a game, launch it from the main game list\nGames will appear when returning to this window\nAfter changing settings, make sure to \"Save PCG\"</string>
<string name="pgc_select_game">Select Game</string>
<string name="save_pgc_title">Save Per-Game Config</string>
<string name="write_pgc">Save PGC</string>
<string name="games_listing">Game List</string>
<string name="search_hint">Game (ie. Crazy Taxi)</string>
@ -113,6 +118,7 @@
<string name="drawer_shut">Menu Closed</string>
<string name="browser">Browser</string>
<string name="settings">Settings</string>
<string name="pgconfig">PG Config</string>
<string name="paths">Paths</string>
<string name="input">Input</string>
<string name="about">About</string>