From 0542855d924a5a3163d667f0d3895e74a1d7a0b6 Mon Sep 17 00:00:00 2001 From: weihuoya Date: Wed, 16 Oct 2019 11:09:03 +0800 Subject: [PATCH] update --- CMakeLists.txt | 6 +- .../java/org/citra/emu/NativeLibrary.java | 10 +- .../java/org/citra/emu/model/GameFile.java | 24 + .../org/citra/emu/ui/EmulationActivity.java | 5 +- .../citra/emu/ui/GameFilePickerActivity.java | 4 +- .../java/org/citra/emu/ui/MainActivity.java | 13 +- .../org/citra/emu/ui/MiiSelectorDialog.java | 136 ++++++ .../citra/emu/ui/RunningSettingDialog.java | 1 - .../citra/emu/utils/PermissionsHandler.java | 25 + .../main/res/layout/dialog_mii_selector.xml | 31 ++ .../app/src/main/res/values-zh/strings.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + .../app/src/main/res/values/styles.xml | 30 -- src/android/jni/main_android.cpp | 10 + src/citra/citra.cpp | 4 +- src/citra/default_ini.h | 13 - src/citra/emu_window/emu_window_sdl2.cpp | 11 + src/citra/emu_window/emu_window_sdl2.h | 3 + src/citra_qt/CMakeLists.txt | 6 + src/citra_qt/configuration/config.cpp | 23 +- .../configuration/configure_general.cpp | 2 + .../configuration/configure_general.ui | 7 + .../configuration/configure_graphics.cpp | 24 +- .../configuration/configure_graphics.h | 2 + src/citra_qt/configuration/configure_ui.ui | 14 +- src/citra_qt/debugger/ipc/record_dialog.cpp | 65 +++ src/citra_qt/debugger/ipc/record_dialog.h | 36 ++ src/citra_qt/debugger/ipc/record_dialog.ui | 245 ++++++++++ src/citra_qt/debugger/ipc/recorder.cpp | 183 ++++++++ src/citra_qt/debugger/ipc/recorder.h | 52 +++ src/citra_qt/debugger/ipc/recorder.ui | 93 ++++ src/citra_qt/game_list.cpp | 97 ++-- src/citra_qt/game_list.h | 10 +- src/citra_qt/game_list_p.h | 45 +- src/citra_qt/game_list_worker.cpp | 8 +- src/citra_qt/game_list_worker.h | 5 +- src/citra_qt/main.cpp | 56 ++- src/citra_qt/main.h | 8 +- src/citra_qt/uisettings.h | 16 +- src/common/CMakeLists.txt | 2 +- src/common/hash.cpp | 51 ++ src/common/hash.h | 56 +-- src/core/CMakeLists.txt | 2 + src/core/core.cpp | 16 +- src/core/core_timing.cpp | 4 +- src/core/hle/kernel/hle_ipc.cpp | 33 ++ src/core/hle/kernel/hle_ipc.h | 3 + src/core/hle/kernel/ipc.cpp | 22 +- src/core/hle/kernel/ipc.h | 5 +- src/core/hle/kernel/ipc_debugger/recorder.cpp | 169 +++++++ src/core/hle/kernel/ipc_debugger/recorder.h | 129 ++++++ src/core/hle/kernel/kernel.cpp | 10 + src/core/hle/kernel/kernel.h | 9 + src/core/hle/kernel/memory.cpp | 4 +- src/core/hle/kernel/svc.cpp | 33 +- src/core/hle/service/dsp/dsp_dsp.cpp | 3 +- src/core/hle/service/fs/fs_user.cpp | 21 +- src/core/hle/service/fs/fs_user.h | 2 + src/core/hle/service/gsp/gsp_gpu.cpp | 13 +- src/core/hle/service/service.cpp | 9 + src/core/hle/service/service.h | 3 + src/core/hle/service/sm/sm.cpp | 9 + src/core/hle/service/sm/sm.h | 6 + src/core/hw/gpu.cpp | 7 +- src/core/hw/hw.cpp | 48 +- src/core/hw/lcd.cpp | 3 +- src/core/memory.cpp | 56 +-- src/core/perf_stats.h | 1 + src/video_core/CMakeLists.txt | 2 + src/video_core/command_processor.cpp | 24 +- .../renderer_opengl/gl_rasterizer.cpp | 147 +++--- .../renderer_opengl/gl_rasterizer.h | 8 +- .../renderer_opengl/gl_rasterizer_cache.cpp | 320 ++++--------- .../renderer_opengl/gl_rasterizer_cache.h | 4 + .../renderer_opengl/gl_resource_manager.cpp | 14 +- .../renderer_opengl/gl_shader_gen.cpp | 237 ++++++---- .../renderer_opengl/gl_shader_gen.h | 43 +- .../renderer_opengl/gl_shader_manager.cpp | 245 +++++----- .../renderer_opengl/gl_shader_manager.h | 7 +- .../renderer_opengl/gl_shader_util.cpp | 12 + src/video_core/renderer_opengl/gl_state.cpp | 268 +++++++---- src/video_core/renderer_opengl/gl_state.h | 24 +- src/video_core/renderer_opengl/gl_vars.cpp | 233 ++++++++++ src/video_core/renderer_opengl/gl_vars.h | 19 +- .../renderer_opengl/on_screen_display.cpp | 436 ++++++++++++++++++ .../renderer_opengl/on_screen_display.h | 44 ++ .../renderer_opengl/renderer_opengl.cpp | 221 +++++---- .../renderer_opengl/renderer_opengl.h | 10 +- 88 files changed, 3256 insertions(+), 1116 deletions(-) create mode 100644 src/android/app/src/main/java/org/citra/emu/ui/MiiSelectorDialog.java create mode 100644 src/android/app/src/main/res/layout/dialog_mii_selector.xml create mode 100644 src/citra_qt/debugger/ipc/record_dialog.cpp create mode 100644 src/citra_qt/debugger/ipc/record_dialog.h create mode 100644 src/citra_qt/debugger/ipc/record_dialog.ui create mode 100644 src/citra_qt/debugger/ipc/recorder.cpp create mode 100644 src/citra_qt/debugger/ipc/recorder.h create mode 100644 src/citra_qt/debugger/ipc/recorder.ui create mode 100644 src/common/hash.cpp create mode 100644 src/core/hle/kernel/ipc_debugger/recorder.cpp create mode 100644 src/core/hle/kernel/ipc_debugger/recorder.h create mode 100644 src/video_core/renderer_opengl/on_screen_display.cpp create mode 100644 src/video_core/renderer_opengl/on_screen_display.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b1afb4b821a..9368d3fb57a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -327,10 +327,12 @@ git_describe(GIT_DESC --always --long --dirty) git_branch_name(GIT_BRANCH) get_timestamp(BUILD_DATE) -enable_testing() +if(NOT ANDROID) + enable_testing() + add_subdirectory(dist/installer) +endif() add_subdirectory(externals) add_subdirectory(src) -add_subdirectory(dist/installer) # Set citra-qt project or citra project as default StartUp Project in Visual Studio depending on whether QT is enabled or not diff --git a/src/android/app/src/main/java/org/citra/emu/NativeLibrary.java b/src/android/app/src/main/java/org/citra/emu/NativeLibrary.java index c305d1ed7d6..00e3f20fc6a 100644 --- a/src/android/app/src/main/java/org/citra/emu/NativeLibrary.java +++ b/src/android/app/src/main/java/org/citra/emu/NativeLibrary.java @@ -58,7 +58,7 @@ public static void showInputBoxDialog(int maxLength, String hint, String button0 public static void showMiiSelectorDialog(boolean cancel, String title, String[] miis) { EmulationActivity activity = EmulationActivity.get(); if (activity != null) { - activity.showMiiSelectorDialog(cancel, title, miis); + activity.runOnUiThread(() -> activity.showMiiSelectorDialog(cancel, title, miis)); } } @@ -84,6 +84,12 @@ public static void updateProgress(String name, int written, int total) { } } + public static boolean isValidFile(String filename) { + String name = filename.toLowerCase(); + return (name.endsWith(".cia") || name.endsWith(".cci") || name.endsWith(".3ds") || + name.endsWith(".cxi")); + } + public static native String GetAppId(String path); public static native String GetAppTitle(String path); @@ -92,6 +98,8 @@ public static void updateProgress(String name, int written, int total) { public static native int GetAppRegion(String path); + public static native boolean IsAppExecutable(String path); + public static native void SaveScreenShot(); public static native void InstallCIA(String[] path); diff --git a/src/android/app/src/main/java/org/citra/emu/model/GameFile.java b/src/android/app/src/main/java/org/citra/emu/model/GameFile.java index b5f086b7f4a..8dbd4b0016c 100644 --- a/src/android/app/src/main/java/org/citra/emu/model/GameFile.java +++ b/src/android/app/src/main/java/org/citra/emu/model/GameFile.java @@ -3,6 +3,15 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; + import java.nio.IntBuffer; import org.citra.emu.NativeLibrary; import org.citra.emu.R; @@ -53,6 +62,21 @@ public Bitmap getIcon(Context context) { mIcon = Bitmap.createBitmap(48, 48, Bitmap.Config.RGB_565); mIcon.copyPixelsFromBuffer(IntBuffer.wrap(pixels)); } + + // rounded corners + float radius = 5.0f; + Rect rect = new Rect(0, 0, mIcon.getWidth(), mIcon.getHeight()); + Bitmap output = Bitmap.createBitmap(mIcon.getWidth(), mIcon.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(output); + BitmapShader shader = new BitmapShader(mIcon, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setShader(shader); + // rect contains the bounds of the shape + // radius is the radius in pixels of the rounded corners + // paint contains the shader that will texture the shape + canvas.drawRoundRect(new RectF(rect), radius, radius, paint); + mIcon = output; } return mIcon; } diff --git a/src/android/app/src/main/java/org/citra/emu/ui/EmulationActivity.java b/src/android/app/src/main/java/org/citra/emu/ui/EmulationActivity.java index 384a350a6b1..4b1b0e7439c 100644 --- a/src/android/app/src/main/java/org/citra/emu/ui/EmulationActivity.java +++ b/src/android/app/src/main/java/org/citra/emu/ui/EmulationActivity.java @@ -56,7 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { // Go back to immersive fullscreen mode in 3s Handler handler = new Handler(getMainLooper()); - handler.postDelayed(this ::enableFullscreenImmersive, 3000 /* 3s */); + handler.postDelayed(this::enableFullscreenImmersive, 3000 /* 3s */); } }); mStopEmulation = false; @@ -213,7 +213,8 @@ public void showInputBoxDialog(int maxLength, String hint, String button0, Strin } public void showMiiSelectorDialog(boolean cancel, String title, String[] miis) { - // todo + MiiSelectorDialog.newInstance(cancel, title, miis) + .show(getSupportFragmentManager(), "MiiSelectorDialog"); } public void refreshControls() { diff --git a/src/android/app/src/main/java/org/citra/emu/ui/GameFilePickerActivity.java b/src/android/app/src/main/java/org/citra/emu/ui/GameFilePickerActivity.java index 1a5430226c0..920277c7c5f 100644 --- a/src/android/app/src/main/java/org/citra/emu/ui/GameFilePickerActivity.java +++ b/src/android/app/src/main/java/org/citra/emu/ui/GameFilePickerActivity.java @@ -9,6 +9,7 @@ import com.nononsenseapps.filepicker.FilePickerActivity; import com.nononsenseapps.filepicker.FilePickerFragment; import java.io.File; +import org.citra.emu.NativeLibrary; public final class GameFilePickerActivity extends FilePickerActivity { @Override @@ -41,8 +42,7 @@ protected boolean isItemVisible(final File file) { return false; if (file.isDirectory()) return true; - String filename = file.getName().toLowerCase(); - return filename.endsWith(".cci") || filename.endsWith(".cia"); + return NativeLibrary.isValidFile(file.getName()); } } } diff --git a/src/android/app/src/main/java/org/citra/emu/ui/MainActivity.java b/src/android/app/src/main/java/org/citra/emu/ui/MainActivity.java index b8b4ca398db..775553d555b 100644 --- a/src/android/app/src/main/java/org/citra/emu/ui/MainActivity.java +++ b/src/android/app/src/main/java/org/citra/emu/ui/MainActivity.java @@ -11,8 +11,6 @@ import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; @@ -223,7 +221,7 @@ public void refreshLibrary() { public void addGamesInDirectory(String directory) { File[] files = new File(directory).listFiles((File dir, String name) -> { - if (name.toLowerCase().endsWith(".cci")) { + if (NativeLibrary.isValidFile(name)) { String path = dir.getPath() + File.separator + name; for (GameFile game : mGames) { if (path.equals(game.getPath())) { @@ -240,7 +238,9 @@ public void addGamesInDirectory(String directory) { } for (File f : files) { - mGames.add(new GameFile(f.getPath())); + String path = f.getPath(); + if (NativeLibrary.IsAppExecutable(path)) + mGames.add(new GameFile(path)); } } @@ -252,7 +252,7 @@ public void saveGameList() { } File cache = getGameListCache(); - FileWriter writer = null; + FileWriter writer; try { writer = new FileWriter(cache); writer.write(sb.toString()); @@ -277,7 +277,8 @@ public void loadGameList() { mGames.clear(); for (String path : content.split(";")) { - if (!path.isEmpty() && path.endsWith(".cci") && new File(path).exists()) { + if (NativeLibrary.isValidFile(path) && new File(path).exists() && + NativeLibrary.IsAppExecutable(path)) { mGames.add(new GameFile(path)); } } diff --git a/src/android/app/src/main/java/org/citra/emu/ui/MiiSelectorDialog.java b/src/android/app/src/main/java/org/citra/emu/ui/MiiSelectorDialog.java new file mode 100644 index 00000000000..2134f574c6a --- /dev/null +++ b/src/android/app/src/main/java/org/citra/emu/ui/MiiSelectorDialog.java @@ -0,0 +1,136 @@ +package org.citra.emu.ui; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; +import com.nononsenseapps.filepicker.DividerItemDecoration; +import java.util.ArrayList; +import org.citra.emu.R; + +public class MiiSelectorDialog extends DialogFragment { + private static final String ARG_CANCEL = "cancel"; + private static final String ARG_TITLE = "title"; + private static final String ARG_MIIS = "miis"; + + public static MiiSelectorDialog newInstance(boolean cancel, String title, String[] miis) { + MiiSelectorDialog fragment = new MiiSelectorDialog(); + Bundle arguments = new Bundle(); + arguments.putBoolean(ARG_CANCEL, cancel); + arguments.putString(ARG_TITLE, title); + arguments.putStringArray(ARG_MIIS, miis); + fragment.setArguments(arguments); + return fragment; + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + ViewGroup contents = (ViewGroup)getActivity().getLayoutInflater().inflate( + R.layout.dialog_mii_selector, null); + + Drawable lineDivider = getContext().getDrawable(R.drawable.line_divider); + RecyclerView recyclerView = contents.findViewById(R.id.list_settings); + RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext()); + recyclerView.setLayoutManager(layoutManager); + MiisAdapter adapter = new MiisAdapter(); + recyclerView.setAdapter(adapter); + recyclerView.addItemDecoration(new DividerItemDecoration(lineDivider)); + builder.setView(contents); + return builder.create(); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + } + + public class SettingsItem {} + + public abstract class SettingViewHolder + extends RecyclerView.ViewHolder implements View.OnClickListener { + public SettingViewHolder(View itemView) { + super(itemView); + itemView.setOnClickListener(this); + findViews(itemView); + } + + protected abstract void findViews(View root); + + public abstract void bind(SettingsItem item); + + public abstract void onClick(View clicked); + } + + public final class CheckBoxSettingViewHolder + extends SettingViewHolder implements CompoundButton.OnCheckedChangeListener { + SettingsItem mItem; + private TextView mTextSettingName; + private CheckBox mCheckbox; + + public CheckBoxSettingViewHolder(View itemView) { + super(itemView); + } + + @Override + protected void findViews(View root) { + mTextSettingName = root.findViewById(R.id.text_setting_name); + mCheckbox = root.findViewById(R.id.checkbox); + mCheckbox.setOnCheckedChangeListener(this); + } + + @Override + public void bind(SettingsItem item) { + mItem = item; + // mTextSettingName.setText(item.getName()); + // mCheckbox.setChecked(mItem.getValue() > 0); + } + + @Override + public void onClick(View clicked) { + mCheckbox.toggle(); + // mItem.setValue(mCheckbox.isChecked() ? 1 : 0); + } + + @Override + public void onCheckedChanged(CompoundButton view, boolean isChecked) { + // mItem.setValue(isChecked ? 1 : 0); + } + } + + public class MiisAdapter extends RecyclerView.Adapter { + private ArrayList mSettings; + + public MiisAdapter() {} + + @NonNull + @Override + public SettingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + View itemView = inflater.inflate(R.layout.list_item_running_checkbox, parent, false); + return new CheckBoxSettingViewHolder(itemView); + } + + @Override + public int getItemCount() { + return mSettings.size(); + } + + @Override + public void onBindViewHolder(@NonNull SettingViewHolder holder, int position) { + holder.bind(mSettings.get(position)); + } + } +} diff --git a/src/android/app/src/main/java/org/citra/emu/ui/RunningSettingDialog.java b/src/android/app/src/main/java/org/citra/emu/ui/RunningSettingDialog.java index 56cfb62d5c2..2b4580cb984 100644 --- a/src/android/app/src/main/java/org/citra/emu/ui/RunningSettingDialog.java +++ b/src/android/app/src/main/java/org/citra/emu/ui/RunningSettingDialog.java @@ -38,7 +38,6 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { ViewGroup contents = (ViewGroup)getActivity().getLayoutInflater().inflate( R.layout.dialog_running_settings, null); - int columns = 1; Drawable lineDivider = getContext().getDrawable(R.drawable.line_divider); RecyclerView recyclerView = contents.findViewById(R.id.list_settings); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext()); diff --git a/src/android/app/src/main/java/org/citra/emu/utils/PermissionsHandler.java b/src/android/app/src/main/java/org/citra/emu/utils/PermissionsHandler.java index 3fd76ebbddf..4784a608845 100644 --- a/src/android/app/src/main/java/org/citra/emu/utils/PermissionsHandler.java +++ b/src/android/app/src/main/java/org/citra/emu/utils/PermissionsHandler.java @@ -1,5 +1,6 @@ package org.citra.emu.utils; +import static android.Manifest.permission.CAMERA; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import android.annotation.TargetApi; @@ -15,6 +16,7 @@ public final class PermissionsHandler { public static final int REQUEST_CODE_WRITE_PERMISSION = 500; + public static final int REQUEST_CODE_CAMERA_PERMISSION = 501; @TargetApi(Build.VERSION_CODES.M) public static boolean checkWritePermission(final Activity activity) { @@ -43,6 +45,29 @@ public static boolean checkWritePermission(final Activity activity) { return true; } + @TargetApi(Build.VERSION_CODES.M) + public static boolean checkCameraPermission(final Activity activity) { + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + return true; + } + + int permission = ContextCompat.checkSelfPermission(activity, CAMERA); + if (permission != PackageManager.PERMISSION_GRANTED) { + if (activity.shouldShowRequestPermissionRationale(CAMERA)) { + showMessageOKCancel(activity, activity.getString(R.string.camera_permission_needed), + (dialog, which) + -> activity.requestPermissions( + new String[] {CAMERA}, REQUEST_CODE_CAMERA_PERMISSION)); + return false; + } + + activity.requestPermissions(new String[] {CAMERA}, REQUEST_CODE_CAMERA_PERMISSION); + return false; + } + + return true; + } + public static boolean hasWriteAccess(Context context) { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int hasWritePermission = diff --git a/src/android/app/src/main/res/layout/dialog_mii_selector.xml b/src/android/app/src/main/res/layout/dialog_mii_selector.xml new file mode 100644 index 00000000000..2c414552d3e --- /dev/null +++ b/src/android/app/src/main/res/layout/dialog_mii_selector.xml @@ -0,0 +1,31 @@ + + + + + +