This commit is contained in:
wheremyfoodat 2024-02-17 11:33:58 +02:00
parent 5ec6d8a5d5
commit c8db0098f5
12 changed files with 51 additions and 55 deletions

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
class AndroidUtils { namespace AndroidUtils {
public: int openDocument(const char* directory, const char* mode);
static int openDocument(const char* directory, const char* mode); }
};

View file

@ -41,7 +41,8 @@ bool IOFile::open(const char* filename, const char* permissions) {
#ifdef __ANDROID__ #ifdef __ANDROID__
std::string path(filename); std::string path(filename);
if(path.find("://") != std::string::npos){ //IF SAF URI // Check if this is a URI directory, which will need special handling due to SAF
if (path.find("://") != std::string::npos ) {
handle = fdopen(AndroidUtils::openDocument(filename, permissions), permissions); handle = fdopen(AndroidUtils::openDocument(filename, permissions), permissions);
} else { } else {
handle = std::fopen(filename, permissions); handle = std::fopen(filename, permissions);
@ -49,6 +50,7 @@ bool IOFile::open(const char* filename, const char* permissions) {
#else #else
handle = std::fopen(filename, permissions); handle = std::fopen(filename, permissions);
#endif #endif
return isOpen(); return isOpen();
} }

View file

@ -32,17 +32,15 @@ public class AlberDriver {
public static native void setShaderJitEnabled(boolean enable); public static native void setShaderJitEnabled(boolean enable);
public static int openDocument(String path, String mode) {
public static int openDocument(String path, String mode){
try { try {
mode = FileUtils.parseNativeMode(mode); mode = FileUtils.parseNativeMode(mode);
Context context = PandroidApplication.getAppContext(); Context context = PandroidApplication.getAppContext();
Uri uri = FileUtils.obtainUri(path); Uri uri = FileUtils.obtainUri(path);
ParcelFileDescriptor parcel; ParcelFileDescriptor parcel;
if (Objects.equals(uri.getScheme(), "game")) { if (Objects.equals(uri.getScheme(), "game")) {
if (mode.contains("w")){ if (mode.contains("w")) {
throw new IllegalArgumentException("Cannot write to rom-fs"); throw new IllegalArgumentException("Cannot open ROM file as writable");
} }
uri = FileUtils.obtainUri(GameUtils.getCurrentGame().getRealPath()); uri = FileUtils.obtainUri(GameUtils.getCurrentGame().getRealPath());
} }
@ -51,7 +49,7 @@ public class AlberDriver {
parcel.close(); parcel.close();
return fd; return fd;
} catch (Exception e){ } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }

View file

@ -2,7 +2,6 @@ package com.panda3ds.pandroid.app;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -13,7 +12,6 @@ import com.panda3ds.pandroid.app.main.GamesFragment;
import com.panda3ds.pandroid.app.main.SearchFragment; import com.panda3ds.pandroid.app.main.SearchFragment;
import com.panda3ds.pandroid.app.main.SettingsFragment; import com.panda3ds.pandroid.app.main.SettingsFragment;
public class MainActivity extends BaseActivity implements NavigationBarView.OnItemSelectedListener { public class MainActivity extends BaseActivity implements NavigationBarView.OnItemSelectedListener {
private final GamesFragment gamesFragment = new GamesFragment(); private final GamesFragment gamesFragment = new GamesFragment();
private final SearchFragment searchFragment = new SearchFragment(); private final SearchFragment searchFragment = new SearchFragment();

View file

@ -105,7 +105,7 @@ public class DrawerFragment extends Fragment implements DrawerLayout.DrawerListe
close(); close();
} else if (id == R.id.exit) { } else if (id == R.id.exit) {
requireActivity().finish(); requireActivity().finish();
} else if (id == R.id.lua_script){ } else if (id == R.id.lua_script) {
new LuaDialogFragment().show(getParentFragmentManager(), null); new LuaDialogFragment().show(getParentFragmentManager(), null);
} else if (id == R.id.change_orientation) { } else if (id == R.id.change_orientation) {
boolean isLandscape = getResources().getDisplayMetrics().widthPixels > getResources().getDisplayMetrics().heightPixels; boolean isLandscape = getResources().getDisplayMetrics().widthPixels > getResources().getDisplayMetrics().heightPixels;

View file

@ -21,10 +21,8 @@ import com.panda3ds.pandroid.utils.Constants;
import com.panda3ds.pandroid.utils.FileUtils; import com.panda3ds.pandroid.utils.FileUtils;
import com.panda3ds.pandroid.utils.GameUtils; import com.panda3ds.pandroid.utils.GameUtils;
import com.panda3ds.pandroid.view.gamesgrid.GamesGridView; import com.panda3ds.pandroid.view.gamesgrid.GamesGridView;
import java.util.UUID; import java.util.UUID;
public class GamesFragment extends Fragment implements ActivityResultCallback<Uri> { public class GamesFragment extends Fragment implements ActivityResultCallback<Uri> {
private final ActivityResultContracts.OpenDocument openRomContract = new ActivityResultContracts.OpenDocument(); private final ActivityResultContracts.OpenDocument openRomContract = new ActivityResultContracts.OpenDocument();
private ActivityResultLauncher<String[]> pickFileRequest; private ActivityResultLauncher<String[]> pickFileRequest;
@ -62,32 +60,32 @@ public class GamesFragment extends Fragment implements ActivityResultCallback<Ur
String extension = FileUtils.extension(uri); String extension = FileUtils.extension(uri);
if (extension.equals("elf") || extension.endsWith("axf")){ // For ELF and AXF files the emulator core uses the C++ iostreams API to be compatible with elfio unlike other file types
// As such, instead of writing more SAF code for operating with iostreams we just copy the ELF/AXF file to our own private directory
// And use it without caring about SAF
if (extension.equals("elf") || extension.endsWith("axf")) {
importELF(uri); importELF(uri);
} else { } else {
FileUtils.makeUriPermanent(uri, FileUtils.MODE_READ); FileUtils.makeUriPermanent(uri, FileUtils.MODE_READ);
importGame(uri);
GameMetadata game = new GameMetadata(uri, FileUtils.getName(uri).split("\\.")[0], getString(R.string.unknown));
GameUtils.addGame(game);
GameUtils.launch(requireActivity(), game);
} }
} }
} }
} }
private void importGame(String uri){
GameMetadata game = new GameMetadata(uri, FileUtils.getName(uri).split("\\.")[0], getString(R.string.unknown));
GameUtils.addGame(game);
GameUtils.launch(requireActivity(), game);
}
private void importELF(String uri) { private void importELF(String uri) {
AlertDialog dialog = new LoadingAlertDialog(requireActivity(), R.string.loading).create(); AlertDialog dialog = new LoadingAlertDialog(requireActivity(), R.string.loading).create();
dialog.show(); dialog.show();
new Task(()->{ new Task(() -> {
String uuid = UUID.randomUUID().toString() + "." + FileUtils.extension(uri); String uuid = UUID.randomUUID().toString() + "." + FileUtils.extension(uri);
String name = FileUtils.getName(uri); String name = FileUtils.getName(uri);
FileUtils.copyFile(uri, FileUtils.getResourcePath(Constants.RESOURCE_FOLDER_ELF), uuid); FileUtils.copyFile(uri, FileUtils.getResourcePath(Constants.RESOURCE_FOLDER_ELF), uuid);
gameListView.post(()->{ gameListView.post(() -> {
dialog.hide(); dialog.hide();
GameMetadata game = new GameMetadata("elf://"+uuid, name.substring(0, name.length()-4).trim(), ""); GameMetadata game = new GameMetadata("elf://" + uuid, name.substring(0, name.length() - 4).trim(), "");
GameUtils.addGame(game); GameUtils.addGame(game);
GameUtils.launch(requireActivity(), game); GameUtils.launch(requireActivity(), game);
}); });

View file

@ -43,7 +43,7 @@ public class GameMetadata {
return romPath; return romPath;
} }
public String getRealPath(){ public String getRealPath() {
return GameUtils.resolvePath(romPath); return GameUtils.resolvePath(romPath);
} }

View file

@ -39,7 +39,7 @@ public class FileUtils {
return parseFile(path).getName(); return parseFile(path).getName();
} }
public static String getResourcesPath(){ public static String getResourcesPath() {
File file = new File(getPrivatePath(), "config/resources"); File file = new File(getPrivatePath(), "config/resources");
if (!file.exists()) { if (!file.exists()) {
file.mkdirs(); file.mkdirs();
@ -48,7 +48,7 @@ public class FileUtils {
return file.getAbsolutePath(); return file.getAbsolutePath();
} }
public static String getResourcePath(String name){ public static String getResourcePath(String name) {
File file = new File(getResourcesPath(), name); File file = new File(getResourcesPath(), name);
file.mkdirs(); file.mkdirs();
@ -73,9 +73,9 @@ public class FileUtils {
return file.getAbsolutePath(); return file.getAbsolutePath();
} }
public static String parseNativeMode(String mode){ public static String parseNativeMode(String mode) {
mode = mode.toLowerCase(); mode = mode.toLowerCase();
switch (mode){ switch (mode) {
case "r": case "r":
case "rb": case "rb":
return "r"; return "r";
@ -98,7 +98,7 @@ public class FileUtils {
return parseFile(path).exists(); return parseFile(path).exists();
} }
public static void rename(String path, String newName){ public static void rename(String path, String newName) {
parseFile(path).renameTo(newName); parseFile(path).renameTo(newName);
} }
@ -234,7 +234,7 @@ public class FileUtils {
} }
} }
public static void updateFile(String path){ public static void updateFile(String path) {
DocumentFile file = parseFile(path); DocumentFile file = parseFile(path);
Uri uri = file.getUri(); Uri uri = file.getUri();
@ -260,12 +260,12 @@ public class FileUtils {
return parseFile(path).lastModified(); return parseFile(path).lastModified();
} }
public static String[] listFiles(String path){ public static String[] listFiles(String path) {
DocumentFile folder = parseFile(path); DocumentFile folder = parseFile(path);
DocumentFile[] files = folder.listFiles(); DocumentFile[] files = folder.listFiles();
String[] result = new String[files.length]; String[] result = new String[files.length];
for (int i = 0; i < result.length; i++){ for (int i = 0; i < result.length; i++) {
result[i] = files[i].getName(); result[i] = files[i].getName();
} }
@ -278,7 +278,7 @@ public class FileUtils {
public static String extension(String uri) { public static String extension(String uri) {
String name = getName(uri); String name = getName(uri);
if (!name.contains(".")){ if (!name.contains(".")) {
return name.toLowerCase(); return name.toLowerCase();
} }
String[] parts = name.split("\\."); String[] parts = name.split("\\.");
@ -302,7 +302,7 @@ public class FileUtils {
out.flush(); out.flush();
out.close(); out.close();
in.close(); in.close();
} catch (Exception e){ } catch (Exception e) {
Log.e(Constants.LOG_TAG, "ERROR ON COPY FILE", e); Log.e(Constants.LOG_TAG, "ERROR ON COPY FILE", e);
return false; return false;
} }

View file

@ -63,13 +63,13 @@ public class GameUtils {
writeChanges(); writeChanges();
} }
public static String resolvePath(String path){ public static String resolvePath(String path) {
String lower = path.toLowerCase(); String lower = path.toLowerCase();
if (!lower.contains("://")){ if (!lower.contains("://")) {
return path; return path;
} }
Uri uri = Uri.parse(path); Uri uri = Uri.parse(path);
switch (uri.getScheme().toLowerCase()){ switch (uri.getScheme().toLowerCase()) {
case "elf":{ case "elf":{
return FileUtils.getResourcePath(Constants.RESOURCE_FOLDER_ELF)+"/"+uri.getAuthority(); return FileUtils.getResourcePath(Constants.RESOURCE_FOLDER_ELF)+"/"+uri.getAuthority();
} }

View file

@ -93,7 +93,7 @@ public class BasicTextEditor extends AppCompatEditText {
super.scrollTo(scrollX, scrollY); super.scrollTo(scrollX, scrollY);
} }
public void adjustScroll(){ public void adjustScroll() {
setScroll(getScrollX(), getScrollY()); setScroll(getScrollX(), getScrollY());
} }

View file

@ -3,16 +3,17 @@ package com.panda3ds.pandroid.view.code.syntax;
import java.util.regex.Pattern; import java.util.regex.Pattern;
class PatternUtils { class PatternUtils {
public static Pattern buildGenericKeywords(String... keywords){ public static Pattern buildGenericKeywords(String... keywords) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("\\b("); builder.append("\\b(");
for (int i = 0; i < keywords.length; i++){ for (int i = 0; i < keywords.length; i++) {
builder.append(keywords[i]); builder.append(keywords[i]);
if (i+1 != keywords.length){ if (i + 1 != keywords.length) {
builder.append("|"); builder.append("|");
} }
} }
builder.append(")\\b");
return Pattern.compile(builder.toString()); builder.append(")\\b");
} return Pattern.compile(builder.toString());
}
} }

View file

@ -34,7 +34,7 @@ public class PerformanceView extends AppCompatTextView {
setShadowLayer(padding,0,0,Color.BLACK); setShadowLayer(padding,0,0,Color.BLACK);
} }
public void refresh(){ public void refresh() {
running = isShown(); running = isShown();
if (!running) { if (!running) {
return; return;