diff --git a/Common/File/PathBrowser.cpp b/Common/File/PathBrowser.cpp index 1998c6fa6f27..7bd70e206377 100644 --- a/Common/File/PathBrowser.cpp +++ b/Common/File/PathBrowser.cpp @@ -273,7 +273,7 @@ bool PathBrowser::CanNavigateUp() { } #endif */ - if (path_ == "/") { + if (path_ == "/" || path_ == "") { return false; } return true; diff --git a/Common/System/System.h b/Common/System/System.h index 57cee7bd7284..b304e9621ad9 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -40,6 +40,8 @@ void System_SendMessage(const char *command, const char *parameter); PermissionStatus System_GetPermissionStatus(SystemPermission permission); void System_AskForPermission(SystemPermission permission); +std::vector System_GetExternalStorageDirs(); + // This will get muddy with multi-screen support :/ But this will always be the type of the main device. enum SystemDeviceType { DEVICE_TYPE_MOBILE = 0, // phones and pads @@ -55,6 +57,11 @@ enum SystemProperty { SYSPROP_CLIPBOARD_TEXT, SYSPROP_GPUDRIVER_VERSION, + // Separate SD cards or similar. + // Need hacky solutions to get at this. + SYSPROP_HAS_ADDITIONAL_STORAGE, + SYSPROP_ADDITIONAL_STORAGE_DIRS, + SYSPROP_HAS_FILE_BROWSER, SYSPROP_HAS_FOLDER_BROWSER, SYSPROP_HAS_IMAGE_BROWSER, @@ -95,6 +102,7 @@ enum SystemProperty { }; std::string System_GetProperty(SystemProperty prop); +std::vector System_GetPropertyStringVec(SystemProperty prop); int System_GetPropertyInt(SystemProperty prop); float System_GetPropertyFloat(SystemProperty prop); bool System_GetPropertyBool(SystemProperty prop); diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index ebd0e993e790..2babf3e4baf6 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -803,6 +803,10 @@ void TextView::Draw(UIContext &dc) { dc.DrawTextRect(text_.c_str(), bounds_.Offset(1.0f, 1.0f), shadowColor, textAlign_); } dc.DrawTextRect(text_.c_str(), bounds_, textColor, textAlign_); + if (small_) { + // If we changed font style, reset it. + dc.SetFontStyle(dc.theme->uiFont); + } if (clip) { dc.PopScissor(); } diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 4dfeaebeb565..32ae76e6c614 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -149,6 +149,13 @@ std::string System_GetProperty(SystemProperty prop) { } } +std::vector System_GetPropertyStringVec(SystemProperty prop) { + switch (prop) { + default: + return std::vector(); + } +} + int System_GetPropertyInt(SystemProperty prop) { switch (prop) { #if defined(SDL) diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 8d43dfdb663d..c65f583fc6b9 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -325,6 +325,13 @@ std::string System_GetProperty(SystemProperty prop) { } } +std::vector System_GetPropertyStringVec(SystemProperty prop) { + switch (prop) { + default: + return std::vector(); + } +} + int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index f7ae0cc3f183..643c0540afee 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -540,13 +540,29 @@ UI::EventReturn GameBrowser::LastClick(UI::EventParams &e) { return UI::EVENT_DONE; } -UI::EventReturn GameBrowser::HomeClick(UI::EventParams &e) { -#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) || defined(USING_QT_UI) || defined(USING_WIN_UI) || PPSSPP_PLATFORM(UWP) - if (System_GetPropertyBool(SYSPROP_HAS_FOLDER_BROWSER)) { - System_SendMessage("browse_folder", ""); +UI::EventReturn GameBrowser::BrowseClick(UI::EventParams &e) { + System_SendMessage("browse_folder", ""); + return UI::EVENT_DONE; +} + +UI::EventReturn GameBrowser::StorageClick(UI::EventParams &e) { + std::vector storageDirs = System_GetPropertyStringVec(SYSPROP_ADDITIONAL_STORAGE_DIRS); + if (storageDirs.empty()) { + // Shouldn't happen - this button shouldn't be clickable. + return UI::EVENT_DONE; + } + if (storageDirs.size() == 1) { + SetPath(storageDirs[0]); } else { - SetPath(g_Config.memStickDirectory); + // TODO: We should popup a dialog letting the user choose one. + SetPath(storageDirs[0]); } + return UI::EVENT_DONE; +} + +UI::EventReturn GameBrowser::HomeClick(UI::EventParams &e) { +#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) || defined(USING_WIN_UI) || PPSSPP_PLATFORM(UWP) + SetPath(g_Config.memStickDirectory); #else SetPath(getenv("HOME")); #endif @@ -656,10 +672,12 @@ void GameBrowser::Refresh() { if (browseFlags_ & BrowseFlags::NAVIGATE) { topBar->Add(new Spacer(2.0f)); topBar->Add(new TextView(path_.GetFriendlyPath().c_str(), ALIGN_VCENTER | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); + topBar->Add(new Choice(ImageID("I_HOME"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::HomeClick); + if (System_GetPropertyBool(SYSPROP_HAS_ADDITIONAL_STORAGE)) { + topBar->Add(new Choice(ImageID("I_SDCARD"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::StorageClick); + } if (System_GetPropertyBool(SYSPROP_HAS_FOLDER_BROWSER)) { - topBar->Add(new Choice(mm->T("Browse", "Browse..."), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::HomeClick); - } else { - topBar->Add(new Choice(mm->T("Home"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::HomeClick); + topBar->Add(new Choice(mm->T("Browse", "Browse..."), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::BrowseClick); } } else { topBar->Add(new Spacer(new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); @@ -762,6 +780,7 @@ void GameBrowser::Refresh() { gameList_->Add(new DirButton("..", *gridStyle_, new UI::LinearLayoutParams(UI::FILL_PARENT, UI::FILL_PARENT)))-> OnClick.Handle(this, &GameBrowser::NavigateClick); } + // Add any pinned paths before other directories. auto pinnedPaths = GetPinnedPaths(); for (auto it = pinnedPaths.begin(), end = pinnedPaths.end(); it != end; ++it) { @@ -1079,6 +1098,13 @@ void MainScreen::CreateViews() { logos->Add(new ImageView(ImageID("I_ICON"), IS_DEFAULT, new AnchorLayoutParams(64, 64, 10, 10, NONE, NONE, false))); } logos->Add(new ImageView(ImageID("I_LOGO"), IS_DEFAULT, new LinearLayoutParams(Margins(-12, 0, 0, 0)))); + +#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) + if (!g_Config.bFullScreen) { + logos->Add(new ImageView(ImageID("I_FULLSCREEN"), IS_DEFAULT, new AnchorLayoutParams(64, 64, NONE, 0, 0, NONE, false))); + } +#endif + rightColumnItems->Add(logos); TextView *ver = rightColumnItems->Add(new TextView(versionString, new LinearLayoutParams(Margins(70, -6, 0, 0)))); ver->SetSmall(true); diff --git a/UI/MainScreen.h b/UI/MainScreen.h index f25fa3f12c11..86c22dd52962 100644 --- a/UI/MainScreen.h +++ b/UI/MainScreen.h @@ -68,6 +68,8 @@ class GameBrowser : public UI::LinearLayout { UI::EventReturn NavigateClick(UI::EventParams &e); UI::EventReturn LayoutChange(UI::EventParams &e); UI::EventReturn LastClick(UI::EventParams &e); + UI::EventReturn BrowseClick(UI::EventParams &e); + UI::EventReturn StorageClick(UI::EventParams &e); UI::EventReturn HomeClick(UI::EventParams &e); UI::EventReturn PinToggleClick(UI::EventParams &e); UI::EventReturn GridSettingsClick(UI::EventParams &e); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 4248c5fa2b33..60a73f86952a 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -356,6 +356,13 @@ std::string System_GetProperty(SystemProperty prop) { } } +std::vector System_GetPropertyStringVec(SystemProperty prop) { + switch (prop) { + default: + return std::vector(); + } +} + int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: diff --git a/Windows/main.cpp b/Windows/main.cpp index 1153376021c2..c7e9dc9fd678 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -216,6 +216,13 @@ std::string System_GetProperty(SystemProperty prop) { } } +std::vector System_GetPropertyStringVec(SystemProperty prop) { + switch (prop) { + default: + return std::vector(); + } +} + // Ugly! extern WindowsAudioBackend *winAudioBackend; diff --git a/android/assets/ui_atlas.meta b/android/assets/ui_atlas.meta index e6b9cf53a22c..52c778e3cbc2 100644 Binary files a/android/assets/ui_atlas.meta and b/android/assets/ui_atlas.meta differ diff --git a/android/assets/ui_atlas.zim b/android/assets/ui_atlas.zim index 8a38cfe54d87..3bb407f9e9ac 100644 Binary files a/android/assets/ui_atlas.zim and b/android/assets/ui_atlas.zim differ diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 82a69e8c2712..38087968f005 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -13,6 +13,8 @@ #include #include +#include + #ifndef _MSC_VER #include #include @@ -122,6 +124,8 @@ std::string langRegion; std::string mogaVersion; std::string boardName; +std::vector g_additionalStorageDirs; + static float left_joystick_x_async; static float left_joystick_y_async; static float right_joystick_x_async; @@ -364,6 +368,15 @@ std::string System_GetProperty(SystemProperty prop) { } } +std::vector System_GetPropertyStringVec(SystemProperty prop) { + switch (prop) { + case SYSPROP_ADDITIONAL_STORAGE_DIRS: + return g_additionalStorageDirs; + default: + return std::vector(); + } +} + int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_SYSTEMVERSION: @@ -410,6 +423,8 @@ bool System_GetPropertyBool(SystemProperty prop) { return androidVersion >= 23; // 6.0 Marshmallow introduced run time permissions. case SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE: return sustainedPerfSupported; // 7.0 introduced sustained performance mode as an optional feature. + case SYSPROP_HAS_ADDITIONAL_STORAGE: + return !g_additionalStorageDirs.empty(); case SYSPROP_HAS_BACK_BUTTON: return true; case SYSPROP_HAS_IMAGE_BROWSER: @@ -530,16 +545,19 @@ static void parse_args(std::vector &args, const std::string value) } } +// Need to use raw Android logging before NativeInit. +#define EARLY_LOG(...) __android_log_print(ANDROID_LOG_INFO, "PPSSPP", __VA_ARGS__) + extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init (JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath, - jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jcacheDir, jstring jshortcutParam, + jstring jdataDir, jstring jexternalStorageDir, jstring jadditionalStorageDirs, jstring jlibraryDir, jstring jcacheDir, jstring jshortcutParam, jint jAndroidVersion, jstring jboard) { setCurrentThreadName("androidInit"); // Makes sure we get early permission grants. ProcessFrameCommands(env); - INFO_LOG(SYSTEM, "NativeApp.init() -- begin"); + EARLY_LOG("NativeApp.init() -- begin"); PROFILE_INIT(); renderer_inited = false; @@ -559,9 +577,18 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init systemName = GetJavaString(env, jmodel); langRegion = GetJavaString(env, jlangRegion); - INFO_LOG(SYSTEM, "NativeApp.init(): device name: '%s'", systemName.c_str()); + EARLY_LOG("NativeApp.init(): device name: '%s'", systemName.c_str()); + + std::string externalStorageDir = GetJavaString(env, jexternalStorageDir); + std::string additionalStorageDirsString = GetJavaString(env, jadditionalStorageDirs); + + if (!additionalStorageDirsString.empty()) { + SplitString(additionalStorageDirsString, ':', g_additionalStorageDirs); + for (auto &str : g_additionalStorageDirs) { + EARLY_LOG("Additional storage: %s", str.c_str()); + } + } - std::string externalDir = GetJavaString(env, jexternalDir); std::string user_data_path = GetJavaString(env, jdataDir); if (user_data_path.size() > 0) user_data_path += "/"; @@ -570,8 +597,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init std::string cacheDir = GetJavaString(env, jcacheDir); std::string buildBoard = GetJavaString(env, jboard); boardName = buildBoard; - INFO_LOG(SYSTEM, "NativeApp.init(): External storage path: %s", externalDir.c_str()); - INFO_LOG(SYSTEM, "NativeApp.init(): Launch shortcut parameter: %s", shortcut_param.c_str()); + EARLY_LOG("NativeApp.init(): External storage path: %s", externalStorageDir.c_str()); + EARLY_LOG("NativeApp.init(): Launch shortcut parameter: %s", shortcut_param.c_str()); std::string app_name; std::string app_nice_name; @@ -600,7 +627,9 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init } } - NativeInit((int)args.size(), &args[0], user_data_path.c_str(), externalDir.c_str(), cacheDir.c_str()); + NativeInit((int)args.size(), &args[0], user_data_path.c_str(), externalStorageDir.c_str(), cacheDir.c_str()); + + // No need to use EARLY_LOG anymore. retry: // Now that we've loaded config, set javaGL. diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 54ae0f04aa4b..1262b88e9960 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -46,6 +46,7 @@ import java.io.File; import java.lang.reflect.Field; import java.util.List; +import java.util.ArrayList; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -241,6 +242,91 @@ public void setShortcutParam(String shortcutParam) { this.shortcutParam = ((shortcutParam == null) ? "" : shortcutParam); } + // Unofficial hacks to get a list of SD cards that are not the main "external storage". + private static ArrayList getSdCardPaths(final Context context) { + // Q is the last version that will support normal file access. + ArrayList list = null; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { + Log.i(TAG, "getSdCardPaths: Trying KitKat method"); + list = getSdCardPaths19(context); + } + + if (list == null) { + Log.i(TAG, "getSdCardPaths: Attempting fallback"); + // Try another method. + String removableStoragePath; + list = new ArrayList(); + File fileList[] = new File("/storage/").listFiles(); + for (File file : fileList) { + if (!file.getAbsolutePath().equalsIgnoreCase(Environment.getExternalStorageDirectory().getAbsolutePath()) && file.isDirectory() && file.canRead()) { + list.add(file.getAbsolutePath()); + } + } + } + + // TODO: On older devices, try System.getenv(“EXTERNAL_SDCARD_STORAGE”) + + if (list == null) { + return new ArrayList(); + } else { + return list; + } + } + + /** + * returns a list of all available sd cards paths, or null if not found. + */ + @TargetApi(Build.VERSION_CODES.KITKAT) + private static ArrayList getSdCardPaths19(final Context context) + { + final File[] externalCacheDirs = context.getExternalCacheDirs(); + if (externalCacheDirs == null || externalCacheDirs.length==0) + return null; + if (externalCacheDirs.length == 1) { + if (externalCacheDirs[0] == null) + return null; + final String storageState = Environment.getStorageState(externalCacheDirs[0]); + if (!Environment.MEDIA_MOUNTED.equals(storageState)) + return null; + if (Environment.isExternalStorageEmulated()) + return null; + } + final ArrayList result = new ArrayList<>(); + if (externalCacheDirs.length == 1) + result.add(getRootOfInnerSdCardFolder(externalCacheDirs[0])); + for (int i = 1; i < externalCacheDirs.length; ++i) + { + final File file = externalCacheDirs[i]; + if (file == null) + continue; + final String storageState = Environment.getStorageState(file); + if (Environment.MEDIA_MOUNTED.equals(storageState)) + result.add(getRootOfInnerSdCardFolder(externalCacheDirs[i])); + } + if (result.isEmpty()) + return null; + return result; + } + + /** Given any file/folder inside an sd card, this will return the path of the sd card */ + private static String getRootOfInnerSdCardFolder(File file) + { + if (file == null) + return null; + final long totalSpace = file.getTotalSpace(); + while (true) { + final File parentFile = file.getParentFile(); + if (parentFile == null || !parentFile.canRead()) { + break; + } + if (parentFile.getTotalSpace() != totalSpace) { + break; + } + file = parentFile; + } + return file.getAbsolutePath(); + } + public void Initialize() { // Initialize audio classes. Do this here since detectOptimalAudioSettings() // needs audioManager @@ -292,9 +378,28 @@ public void Initialize() { isXperiaPlay = IsXperiaPlay(); String libraryDir = getApplicationLibraryDir(appInfo); - File sdcard = Environment.getExternalStorageDirectory(); - String externalStorageDir = sdcard.getAbsolutePath(); + String extStorageState = Environment.getExternalStorageState(); + String extStorageDir = Environment.getExternalStorageDirectory().getAbsolutePath(); + + Log.i(TAG, "Ext storage: " + extStorageState + " " + extStorageDir); + + ArrayList sdCards = getSdCardPaths(this); + + // String.join doesn't exist on old devices (???). + StringBuilder s = new StringBuilder(); + for (int i = 0; i < sdCards.size(); i++) { + String sdCard = sdCards.get(i); + Log.i(TAG, "SD card: " + sdCard); + s.append(sdCard); + if (i != sdCards.size() - 1) { + s.append(":"); + } + } + String additionalStorageDirs = s.toString(); + + Log.i(TAG, "End of storage paths"); + File filesDir = this.getFilesDir(); String dataDir = null; if (filesDir != null) { @@ -310,7 +415,7 @@ public void Initialize() { overrideShortcutParam = null; NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(model, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, cacheDir, shortcut, Build.VERSION.SDK_INT, Build.BOARD); + NativeApp.init(model, deviceType, languageRegion, apkFilePath, dataDir, extStorageDir, additionalStorageDirs, libraryDir, cacheDir, shortcut, Build.VERSION.SDK_INT, Build.BOARD); // Allow C++ to tell us to use JavaGL or not. javaGL = "true".equalsIgnoreCase(NativeApp.queryConfig("androidJavaGL")); diff --git a/android/src/org/ppsspp/ppsspp/NativeApp.java b/android/src/org/ppsspp/ppsspp/NativeApp.java index 632c625bed02..4a72d4c6a99a 100644 --- a/android/src/org/ppsspp/ppsspp/NativeApp.java +++ b/android/src/org/ppsspp/ppsspp/NativeApp.java @@ -12,7 +12,7 @@ public class NativeApp { public static final int DEVICE_TYPE_TV = 1; public static final int DEVICE_TYPE_DESKTOP = 2; - public static native void init(String model, int deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String cacheDir, String shortcutParam, int androidVersion, String board); + public static native void init(String model, int deviceType, String languageRegion, String apkPath, String dataDir, String externalStorageDir, String additionalStorageDirs, String libraryDir, String cacheDir, String shortcutParam, int androidVersion, String board); public static native void audioInit(); public static native void audioShutdown(); public static native void audioConfig(int optimalFramesPerBuffer, int optimalSampleRate); diff --git a/assets/ui_atlas.meta b/assets/ui_atlas.meta index e6b9cf53a22c..52c778e3cbc2 100644 Binary files a/assets/ui_atlas.meta and b/assets/ui_atlas.meta differ diff --git a/assets/ui_atlas.zim b/assets/ui_atlas.zim index 8a38cfe54d87..3bb407f9e9ac 100644 Binary files a/assets/ui_atlas.zim and b/assets/ui_atlas.zim differ diff --git a/atlasscript.txt b/atlasscript.txt index ff1fba5aab48..3aa700a8b2fb 100644 --- a/atlasscript.txt +++ b/atlasscript.txt @@ -48,3 +48,7 @@ image I_FLAG_EU source_assets/image/flag_eu.png copy image I_FLAG_HK source_assets/image/flag_hk.png copy image I_FLAG_AS source_assets/image/flag_as.png copy image I_FLAG_KO source_assets/image/flag_ko.png copy +image I_FULLSCREEN source_assets/image/fullscreen.png copy +image I_RESTORE source_assets/image/restore.png copy +image I_SDCARD source_assets/image/sdcard.png copy +image I_HOME source_assets/image/home.png copy \ No newline at end of file diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 331dfa7cbb9f..bbabad7710bf 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -81,15 +81,11 @@ void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } std::string System_GetProperty(SystemProperty prop) { return ""; } -int System_GetPropertyInt(SystemProperty prop) { - return -1; -} -float System_GetPropertyFloat(SystemProperty prop) { - return -1; -} -bool System_GetPropertyBool(SystemProperty prop) { - return false; -} +std::vector System_GetPropertyStringVec(SystemProperty prop) { return std::vector(); } +int System_GetPropertyInt(SystemProperty prop) { return -1; } +float System_GetPropertyFloat(SystemProperty prop) { return -1.0f; } +bool System_GetPropertyBool(SystemProperty prop) { return false; } + void System_SendMessage(const char *command, const char *parameter) {} void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} diff --git a/ios/main.mm b/ios/main.mm index 5daecb3e79d9..80825849334c 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -64,6 +64,13 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, } } +std::vector System_GetPropertyStringVec(SystemProperty prop) { + switch (prop) { + default: + return std::vector(); + } +} + int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 68f8c0ec7dc3..122cab72e22b 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -905,6 +905,8 @@ float System_GetPropertyFloat(SystemProperty prop) } std::string System_GetProperty(SystemProperty prop) { return ""; } +std::vector System_GetPropertyStringVec(SystemProperty prop) { return std::vector(); } + void System_SendMessage(const char *command, const char *parameter) {} void NativeUpdate() {} void NativeRender(GraphicsContext *graphicsContext) {} diff --git a/source_assets/image/buttons.svg b/source_assets/image/buttons.svg index b0b87419ffa8..61aa45225834 100644 --- a/source_assets/image/buttons.svg +++ b/source_assets/image/buttons.svg @@ -1,6 +1,4 @@ - - + + + + + + + + + + + + + + + + + inkscape:window-maximized="1" + inkscape:document-rotation="0"> + + @@ -1669,13 +1768,12 @@ id="rect4729" style="fill:#60d068;fill-opacity:1;stroke:#ffffff;stroke-width:1.68099999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.64893613;stroke-dasharray:none" /> - + style="fill:none;stroke:#ffffff;stroke-width:11.99826908;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + cx="114.28571" + cy="175.21933" + rx="142.85715" + ry="140" /> + style="stroke:#ffffff;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5264)"> - - + + inkscape:export-ydpi="135" + cx="114.28571" + cy="175.21933" + rx="142.85715" + ry="140" /> + inkscape:export-ydpi="135" + transform="translate(339.66379,6.8185296)"> + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5328)" /> + y="34.633499" + style="font-size:40px;line-height:1.25">  + x="270.72089" + y="200.55106" + style="font-size:40px;line-height:1.25">⚙ 1 2 3 4 5 6 + + + SD + + + + + + + + + + + diff --git a/source_assets/image/fullscreen.png b/source_assets/image/fullscreen.png new file mode 100644 index 000000000000..4cf4350efa12 Binary files /dev/null and b/source_assets/image/fullscreen.png differ diff --git a/source_assets/image/home.png b/source_assets/image/home.png new file mode 100644 index 000000000000..dc570a880b66 Binary files /dev/null and b/source_assets/image/home.png differ diff --git a/source_assets/image/restore.png b/source_assets/image/restore.png new file mode 100644 index 000000000000..143ef0779fb2 Binary files /dev/null and b/source_assets/image/restore.png differ diff --git a/source_assets/image/sdcard.png b/source_assets/image/sdcard.png new file mode 100644 index 000000000000..ae7225c65e70 Binary files /dev/null and b/source_assets/image/sdcard.png differ diff --git a/source_assets/image/umd256.png b/source_assets/image/umd256.png deleted file mode 100644 index dc09340d9014..000000000000 Binary files a/source_assets/image/umd256.png and /dev/null differ diff --git a/source_assets/image/umd48.png b/source_assets/image/umd48.png deleted file mode 100644 index edf16fed776f..000000000000 Binary files a/source_assets/image/umd48.png and /dev/null differ diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index b5beb3cefa5a..7e5bd98b9772 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #if defined(ANDROID) @@ -58,7 +59,9 @@ #include "unittest/TestVertexJit.h" #include "unittest/UnitTest.h" + std::string System_GetProperty(SystemProperty prop) { return ""; } +std::vector System_GetPropertyStringVec(SystemProperty prop) { return std::vector(); } int System_GetPropertyInt(SystemProperty prop) { return -1; }