mirror of
https://github.com/izzy2lost/PSX2.git
synced 2026-07-05 15:18:36 -07:00
Bios now boots without opening games to fix crashes on some devices
This commit is contained in:
@@ -1457,9 +1457,17 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
|
||||
|
||||
VkPhysicalDevice physicalDevice = physicalDevices[physicalDeviceIndex];
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &rendererData->physicalDeviceProperties);
|
||||
// Accept Vulkan 1.0 and above (was checking for < 1 which would never be true)
|
||||
// Some devices report 1.0.x which is valid
|
||||
if (VK_VERSION_MAJOR(rendererData->physicalDeviceProperties.apiVersion) < 1) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Skipping device with API version < 1.0");
|
||||
continue;
|
||||
}
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Found device: %s (API version %d.%d.%d)",
|
||||
rendererData->physicalDeviceProperties.deviceName,
|
||||
VK_VERSION_MAJOR(rendererData->physicalDeviceProperties.apiVersion),
|
||||
VK_VERSION_MINOR(rendererData->physicalDeviceProperties.apiVersion),
|
||||
VK_VERSION_PATCH(rendererData->physicalDeviceProperties.apiVersion));
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &rendererData->physicalDeviceMemoryProperties);
|
||||
vkGetPhysicalDeviceFeatures(physicalDevice, &rendererData->physicalDeviceFeatures);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamiliesCount, NULL);
|
||||
@@ -1507,9 +1515,13 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
|
||||
}
|
||||
|
||||
if (rendererData->graphicsQueueFamilyIndex == queueFamiliesCount) { // no good queues found
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Device %s: No graphics queue found",
|
||||
rendererData->physicalDeviceProperties.deviceName);
|
||||
continue;
|
||||
}
|
||||
if (rendererData->presentQueueFamilyIndex == queueFamiliesCount) { // no good queues found
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Device %s: No present queue found",
|
||||
rendererData->physicalDeviceProperties.deviceName);
|
||||
continue;
|
||||
}
|
||||
result = vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &deviceExtensionCount, NULL);
|
||||
@@ -1548,8 +1560,12 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
|
||||
}
|
||||
}
|
||||
if (!hasSwapchainExtension) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Device %s: Missing VK_KHR_swapchain extension",
|
||||
rendererData->physicalDeviceProperties.deviceName);
|
||||
continue;
|
||||
}
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Device %s: Selected as suitable Vulkan device",
|
||||
rendererData->physicalDeviceProperties.deviceName);
|
||||
rendererData->physicalDevice = physicalDevice;
|
||||
break;
|
||||
}
|
||||
@@ -1557,9 +1573,12 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
|
||||
SDL_free(queueFamiliesProperties);
|
||||
SDL_free(deviceExtensions);
|
||||
if (!rendererData->physicalDevice) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "No viable Vulkan physical devices found. Checked %d device(s).", physicalDeviceCount);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Devices must support: Vulkan 1.0+, VK_KHR_swapchain, graphics queue, and present queue");
|
||||
SET_ERROR_MESSAGE("No viable physical devices found");
|
||||
return VK_ERROR_UNKNOWN;
|
||||
}
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Selected Vulkan device: %s", rendererData->physicalDeviceProperties.deviceName);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1172,6 +1172,16 @@ Java_com_izzy2lost_psx2_NativeApp_runVMThread(JNIEnv *env, jclass clazz,
|
||||
// fast_boot : (false:bios->game, true:game)
|
||||
VMBootParameters boot_params;
|
||||
boot_params.filename = _szPath;
|
||||
|
||||
// Enable fast boot when booting BIOS-only (no game loaded)
|
||||
// This skips the BIOS animation and goes straight to the PS2 menu
|
||||
Console.WriteLn("runVMThread: path='%s', length=%zu", _szPath.c_str(), _szPath.length());
|
||||
if (_szPath.empty()) {
|
||||
boot_params.fast_boot = true;
|
||||
Console.WriteLn("BIOS-only boot: Fast boot ENABLED to skip animation");
|
||||
} else {
|
||||
Console.WriteLn("Game boot: path=%s, fast_boot will use default behavior", _szPath.c_str());
|
||||
}
|
||||
|
||||
// Apply per-game settings (if any) before applying core settings
|
||||
ApplyPerGameSettingsForPath(_szPath);
|
||||
|
||||
@@ -1406,10 +1406,20 @@ bool VMManager::Initialize(VMBootParameters boot_params)
|
||||
|
||||
// Read fast boot setting late so it can be overridden per-game.
|
||||
// ELFs must be fast booted, and GS dumps are never fast booted.
|
||||
// Allow fast boot for BIOS-only boots if explicitly requested via boot_params
|
||||
const bool has_disc = (CDVDsys_GetSourceType() != CDVD_SourceType::NoDisc);
|
||||
const bool has_elf = !s_elf_override.empty();
|
||||
const bool fast_boot_requested = boot_params.fast_boot.value_or(static_cast<bool>(EmuConfig.EnableFastBoot));
|
||||
|
||||
Console.WriteLn("VMManager::Initialize - Fast boot check: has_disc=%d, has_elf=%d, fast_boot_requested=%d",
|
||||
has_disc, has_elf, fast_boot_requested);
|
||||
|
||||
s_fast_boot_requested =
|
||||
(boot_params.fast_boot.value_or(static_cast<bool>(EmuConfig.EnableFastBoot)) || !s_elf_override.empty()) &&
|
||||
(CDVDsys_GetSourceType() != CDVD_SourceType::NoDisc || !s_elf_override.empty()) &&
|
||||
(fast_boot_requested || has_elf) &&
|
||||
(has_disc || has_elf || fast_boot_requested) && // Allow fast boot for BIOS-only if explicitly requested
|
||||
!GSDumpReplayer::IsReplayingDump();
|
||||
|
||||
Console.WriteLn("VMManager::Initialize - s_fast_boot_requested=%d", s_fast_boot_requested);
|
||||
|
||||
if (!s_elf_override.empty())
|
||||
{
|
||||
|
||||
@@ -328,6 +328,18 @@ bool LoadBIOS()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if BIOS is already loaded and matches the current path
|
||||
// This avoids reloading the same BIOS file on every game launch
|
||||
if (!BiosRom.empty() && !BiosPath.empty() && BiosPath == path)
|
||||
{
|
||||
Console.WriteLn("BIOS already loaded from cache: %s", path.c_str());
|
||||
// Just copy the cached BIOS to memory instead of reloading from disk
|
||||
CopyBIOSToMemory();
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLn("Loading BIOS from disk: %s", path.c_str());
|
||||
|
||||
auto fp = FileSystem::OpenManagedCFile(path.c_str(), "rb");
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
@@ -496,20 +496,13 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
f.setCancelable(false);
|
||||
f.show(getSupportFragmentManager(), "setup_wizard");
|
||||
} else {
|
||||
// Only auto-open games dialog if this is NOT the first boot after setup
|
||||
// (Setup wizard handles opening the games dialog on first completion)
|
||||
// Don't auto-open games dialog on app start
|
||||
// User can open it manually via home button or controller
|
||||
// This prevents crashes on devices where BIOS boot + dialog opening is too much at once
|
||||
boolean hasOpenedGamesAfterSetup = prefs.getBoolean("has_opened_games_after_setup", false);
|
||||
if (hasOpenedGamesAfterSetup) {
|
||||
try {
|
||||
final View decor = (getWindow() != null) ? getWindow().getDecorView() : null;
|
||||
if (decor != null) {
|
||||
decor.postDelayed(() -> {
|
||||
if (!isFinishing() && !mSetupWizardActive) {
|
||||
openGamesDialog();
|
||||
}
|
||||
}, 1600); // small delay to let BIOS boot briefly
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
if (!hasOpenedGamesAfterSetup) {
|
||||
// Mark as opened so we don't show this message again
|
||||
prefs.edit().putBoolean("has_opened_games_after_setup", true).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,6 +567,17 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
if (btn_settings != null) {
|
||||
btn_settings.setOnClickListener(v -> {
|
||||
try {
|
||||
// Pause the emulation (BIOS or game) before opening drawer
|
||||
// This prevents crashes on some devices when drawer opens during emulation
|
||||
if (isThread() && !NativeApp.isPaused()) {
|
||||
try {
|
||||
NativeApp.pause();
|
||||
android.util.Log.d("MainActivity", "Paused emulation before opening drawer");
|
||||
} catch (Throwable e) {
|
||||
android.util.Log.e("MainActivity", "Error pausing before drawer open: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Open the drawer via post() to avoid reentrancy/layout timing issues
|
||||
// (programmatic open can sometimes race with layout/insets handling)
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
@@ -2501,20 +2505,21 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
mDrawerOpen = false;
|
||||
android.util.Log.d("DrawerTracking", "Drawer closed. Dialog count: " + mOpenDialogCount);
|
||||
if (mOpenDialogCount == 0 && !mDrawerOpen) {
|
||||
// All dialogs closed and no drawers open, resume the game with a small delay
|
||||
// All dialogs closed and no drawers open, resume the emulation (game or BIOS) with a small delay
|
||||
View root = findViewById(android.R.id.content);
|
||||
if (root != null) {
|
||||
root.postDelayed(() -> {
|
||||
try {
|
||||
if (hasSelectedGame() && isThread() && NativeApp.isPaused()) {
|
||||
android.util.Log.d("DrawerTracking", "Resuming game on drawer close");
|
||||
// Resume if emulation thread is running and paused (works for both game and BIOS)
|
||||
if (isThread() && NativeApp.isPaused()) {
|
||||
android.util.Log.d("DrawerTracking", "Resuming emulation on drawer close");
|
||||
NativeApp.resume();
|
||||
updatePausePlayButton();
|
||||
} else {
|
||||
android.util.Log.d("DrawerTracking", "Not resuming - hasGame: " + hasSelectedGame() + ", isThread: " + isThread() + ", isPaused: " + (isThread() ? NativeApp.isPaused() : "N/A"));
|
||||
android.util.Log.d("DrawerTracking", "Not resuming - isThread: " + isThread() + ", isPaused: " + (isThread() ? NativeApp.isPaused() : "N/A"));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
android.util.Log.e("DrawerTracking", "Error resuming game: " + e.getMessage());
|
||||
android.util.Log.e("DrawerTracking", "Error resuming emulation: " + e.getMessage());
|
||||
}
|
||||
}, 100); // Small delay to let drawer fully close
|
||||
}
|
||||
|
||||
@@ -197,20 +197,10 @@ public class SetupWizardDialogFragment extends DialogFragment {
|
||||
dismissAllowingStateLoss();
|
||||
if (a != null) {
|
||||
// Use adaptive delay based on device capabilities
|
||||
long manualDelay = getTimeoutForDevice(2000, 4000); // 2s normal, 4s lower-end
|
||||
android.util.Log.d("SetupWizard", "Using manual delay: " + manualDelay + "ms");
|
||||
|
||||
final MainActivity act = a;
|
||||
View decor = act.getWindow() != null ? act.getWindow().getDecorView() : null;
|
||||
if (decor != null) {
|
||||
decor.postDelayed(() -> {
|
||||
act.openGamesDialog();
|
||||
}, manualDelay);
|
||||
} else {
|
||||
act.runOnUiThread(() -> {
|
||||
act.openGamesDialog();
|
||||
});
|
||||
}
|
||||
// Don't auto-open games dialog after setup wizard
|
||||
// This prevents crashes when BIOS is still booting
|
||||
// User can open it manually via home button when ready
|
||||
android.util.Log.d("SetupWizard", "Setup complete - user can open games dialog via home button");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -389,13 +379,9 @@ public class SetupWizardDialogFragment extends DialogFragment {
|
||||
MainActivity a = (MainActivity) requireActivity();
|
||||
a.setSetupWizardActive(false);
|
||||
dismissAllowingStateLoss();
|
||||
// Add adaptive delay before opening games dialog
|
||||
View mainDecor = a.getWindow() != null ? a.getWindow().getDecorView() : null;
|
||||
if (mainDecor != null) {
|
||||
mainDecor.postDelayed(() -> {
|
||||
a.openGamesDialog();
|
||||
}, gamesDialogDelay);
|
||||
}
|
||||
// Don't auto-open games dialog after setup wizard
|
||||
// This prevents crashes when BIOS is still booting
|
||||
// User can open it manually via home button when ready
|
||||
} catch (Throwable ignored) {}
|
||||
}, autoAdvanceDelay);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user