forked from etc/pineapple-src
early-access version 3972
This commit is contained in:
parent
44caed8bb2
commit
16a6230063
8 changed files with 140 additions and 56 deletions
|
@ -1,7 +1,7 @@
|
|||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 3971.
|
||||
This is the source code for early-access 3972.
|
||||
|
||||
## Legal Notice
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "input_common/drivers/virtual_gamepad.h"
|
||||
#include "input_common/main.h"
|
||||
#include "jni/emu_window/emu_window.h"
|
||||
#include "jni/native.h"
|
||||
|
||||
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||
m_window_width = ANativeWindow_getWidth(surface);
|
||||
|
@ -57,6 +58,13 @@ void EmuWindow_Android::OnRemoveNfcTag() {
|
|||
m_input_subsystem->GetVirtualAmiibo()->CloseAmiibo();
|
||||
}
|
||||
|
||||
void EmuWindow_Android::OnFrameDisplayed() {
|
||||
if (!m_first_frame) {
|
||||
EmulationSession::GetInstance().OnEmulationStarted();
|
||||
m_first_frame = true;
|
||||
}
|
||||
}
|
||||
|
||||
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem,
|
||||
ANativeWindow* surface,
|
||||
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
float gyro_z, float accel_x, float accel_y, float accel_z);
|
||||
void OnReadNfcTag(std::span<u8> data);
|
||||
void OnRemoveNfcTag();
|
||||
void OnFrameDisplayed() override {}
|
||||
void OnFrameDisplayed() override;
|
||||
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
|
||||
return {std::make_unique<GraphicsContext_Android>(m_driver_library)};
|
||||
|
@ -61,4 +61,6 @@ private:
|
|||
float m_window_height{};
|
||||
|
||||
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
||||
|
||||
bool m_first_frame = false;
|
||||
};
|
||||
|
|
|
@ -372,8 +372,6 @@ void EmulationSession::RunEmulation() {
|
|||
m_system.InitializeDebugger();
|
||||
}
|
||||
|
||||
OnEmulationStarted();
|
||||
|
||||
while (true) {
|
||||
{
|
||||
[[maybe_unused]] std::unique_lock lock(m_mutex);
|
||||
|
|
|
@ -52,9 +52,10 @@ public:
|
|||
void OnGamepadDisconnectEvent([[maybe_unused]] int index);
|
||||
SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
|
||||
|
||||
static void OnEmulationStarted();
|
||||
|
||||
private:
|
||||
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
||||
static void OnEmulationStarted();
|
||||
static void OnEmulationStopped(Core::SystemResultStatus result);
|
||||
|
||||
private:
|
||||
|
|
|
@ -562,6 +562,120 @@ static std::string PaginateBuffer(std::string_view buffer, std::string_view requ
|
|||
}
|
||||
}
|
||||
|
||||
static VAddr GetModuleEnd(Kernel::KProcessPageTable& page_table, VAddr base) {
|
||||
Kernel::KMemoryInfo mem_info;
|
||||
Kernel::Svc::MemoryInfo svc_mem_info;
|
||||
Kernel::Svc::PageInfo page_info;
|
||||
VAddr cur_addr{base};
|
||||
|
||||
// Expect: r-x Code (.text)
|
||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
||||
svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
|
||||
return cur_addr - 1;
|
||||
}
|
||||
|
||||
// Expect: r-- Code (.rodata)
|
||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
||||
svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
|
||||
return cur_addr - 1;
|
||||
}
|
||||
|
||||
// Expect: rw- CodeData (.data)
|
||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||
return cur_addr - 1;
|
||||
}
|
||||
|
||||
static Loader::AppLoader::Modules FindModules(Core::System& system) {
|
||||
Loader::AppLoader::Modules modules;
|
||||
|
||||
auto& page_table = system.ApplicationProcess()->GetPageTable();
|
||||
auto& memory = system.ApplicationMemory();
|
||||
VAddr cur_addr = 0;
|
||||
|
||||
// Look for executable sections in Code or AliasCode regions.
|
||||
while (true) {
|
||||
Kernel::KMemoryInfo mem_info{};
|
||||
Kernel::Svc::PageInfo page_info{};
|
||||
R_ASSERT(
|
||||
page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||
auto svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
|
||||
if (svc_mem_info.permission == Kernel::Svc::MemoryPermission::ReadExecute &&
|
||||
(svc_mem_info.state == Kernel::Svc::MemoryState::Code ||
|
||||
svc_mem_info.state == Kernel::Svc::MemoryState::AliasCode)) {
|
||||
// Try to read the module name from its path.
|
||||
constexpr s32 PathLengthMax = 0x200;
|
||||
struct {
|
||||
u32 zero;
|
||||
s32 path_length;
|
||||
std::array<char, PathLengthMax> path;
|
||||
} module_path;
|
||||
|
||||
if (memory.ReadBlock(svc_mem_info.base_address + svc_mem_info.size, &module_path,
|
||||
sizeof(module_path))) {
|
||||
if (module_path.zero == 0 && module_path.path_length > 0) {
|
||||
// Truncate module name.
|
||||
module_path.path[PathLengthMax - 1] = '\0';
|
||||
|
||||
// Ignore leading directories.
|
||||
char* path_pointer = module_path.path.data();
|
||||
|
||||
for (s32 i = 0; i < std::min(PathLengthMax, module_path.path_length) &&
|
||||
module_path.path[i] != '\0';
|
||||
i++) {
|
||||
if (module_path.path[i] == '/' || module_path.path[i] == '\\') {
|
||||
path_pointer = module_path.path.data() + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert output.
|
||||
modules.emplace(svc_mem_info.base_address, path_pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we're done.
|
||||
const uintptr_t next_address = svc_mem_info.base_address + svc_mem_info.size;
|
||||
if (next_address <= cur_addr) {
|
||||
break;
|
||||
}
|
||||
|
||||
cur_addr = next_address;
|
||||
}
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
static VAddr FindMainModuleEntrypoint(Core::System& system) {
|
||||
Loader::AppLoader::Modules modules;
|
||||
system.GetAppLoader().ReadNSOModules(modules);
|
||||
|
||||
// Do we have a module named main?
|
||||
const auto main = std::find_if(modules.begin(), modules.end(),
|
||||
[](const auto& key) { return key.second == "main"; });
|
||||
|
||||
if (main != modules.end()) {
|
||||
return main->first;
|
||||
}
|
||||
|
||||
// Do we have any loaded executable sections?
|
||||
modules = FindModules(system);
|
||||
if (!modules.empty()) {
|
||||
return modules.begin()->first;
|
||||
}
|
||||
|
||||
// As a last resort, use the start of the code region.
|
||||
return GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart());
|
||||
}
|
||||
|
||||
void GDBStub::HandleQuery(std::string_view command) {
|
||||
if (command.starts_with("TStatus")) {
|
||||
// no tracepoint support
|
||||
|
@ -573,21 +687,10 @@ void GDBStub::HandleQuery(std::string_view command) {
|
|||
const auto target_xml{arch->GetTargetXML()};
|
||||
SendReply(PaginateBuffer(target_xml, command.substr(30)));
|
||||
} else if (command.starts_with("Offsets")) {
|
||||
Loader::AppLoader::Modules modules;
|
||||
system.GetAppLoader().ReadNSOModules(modules);
|
||||
|
||||
const auto main = std::find_if(modules.begin(), modules.end(),
|
||||
[](const auto& key) { return key.second == "main"; });
|
||||
if (main != modules.end()) {
|
||||
SendReply(fmt::format("TextSeg={:x}", main->first));
|
||||
} else {
|
||||
SendReply(fmt::format(
|
||||
"TextSeg={:x}",
|
||||
GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart())));
|
||||
}
|
||||
const auto main_offset = FindMainModuleEntrypoint(system);
|
||||
SendReply(fmt::format("TextSeg={:x}", main_offset));
|
||||
} else if (command.starts_with("Xfer:libraries:read::")) {
|
||||
Loader::AppLoader::Modules modules;
|
||||
system.GetAppLoader().ReadNSOModules(modules);
|
||||
auto modules = FindModules(system);
|
||||
|
||||
std::string buffer;
|
||||
buffer += R"(<?xml version="1.0"?>)";
|
||||
|
@ -727,37 +830,6 @@ static constexpr const char* GetMemoryPermissionString(const Kernel::Svc::Memory
|
|||
}
|
||||
}
|
||||
|
||||
static VAddr GetModuleEnd(Kernel::KProcessPageTable& page_table, VAddr base) {
|
||||
Kernel::KMemoryInfo mem_info;
|
||||
Kernel::Svc::MemoryInfo svc_mem_info;
|
||||
Kernel::Svc::PageInfo page_info;
|
||||
VAddr cur_addr{base};
|
||||
|
||||
// Expect: r-x Code (.text)
|
||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
||||
svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
|
||||
return cur_addr - 1;
|
||||
}
|
||||
|
||||
// Expect: r-- Code (.rodata)
|
||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||
if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
|
||||
svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
|
||||
return cur_addr - 1;
|
||||
}
|
||||
|
||||
// Expect: rw- CodeData (.data)
|
||||
R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
|
||||
svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
cur_addr = svc_mem_info.base_address + svc_mem_info.size;
|
||||
return cur_addr - 1;
|
||||
}
|
||||
|
||||
void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
||||
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
|
||||
std::string reply;
|
||||
|
@ -784,8 +856,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
|||
reply = "Fastmem is not enabled.\n";
|
||||
}
|
||||
} else if (command_str == "get info") {
|
||||
Loader::AppLoader::Modules modules;
|
||||
system.GetAppLoader().ReadNSOModules(modules);
|
||||
auto modules = FindModules(system);
|
||||
|
||||
reply = fmt::format("Process: {:#x} ({})\n"
|
||||
"Program Id: {:#018x}\n",
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "core/hle/kernel/k_capabilities.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_process_page_table.h"
|
||||
#include "core/hle/kernel/k_trace.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
#include "core/hle/kernel/svc_version.h"
|
||||
|
@ -329,6 +330,8 @@ Result KCapabilities::SetCapabilities(std::span<const u32> caps, KProcessPageTab
|
|||
|
||||
// Map the range.
|
||||
R_TRY(this->MapRange_(cap, size_cap, page_table));
|
||||
} else if (GetCapabilityType(cap) == CapabilityType::MapRegion && !IsKTraceEnabled) {
|
||||
continue;
|
||||
} else {
|
||||
R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table));
|
||||
}
|
||||
|
|
|
@ -1910,7 +1910,8 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
|||
StartGameType type, AmLaunchType launch_type) {
|
||||
LOG_INFO(Frontend, "yuzu starting...");
|
||||
|
||||
if (program_id > static_cast<u64>(Service::AM::Applets::AppletProgramId::MaxProgramId)) {
|
||||
if (program_id == 0 ||
|
||||
program_id > static_cast<u64>(Service::AM::Applets::AppletProgramId::MaxProgramId)) {
|
||||
StoreRecentFile(filename); // Put the filename on top of the list
|
||||
}
|
||||
|
||||
|
@ -4324,7 +4325,7 @@ void GMainWindow::OnAlbum() {
|
|||
|
||||
const auto filename = QString::fromStdString(album_nca->GetFullPath());
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
BootGame(filename);
|
||||
BootGame(filename, AlbumId);
|
||||
}
|
||||
|
||||
void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
|
||||
|
@ -4348,7 +4349,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
|
|||
|
||||
const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
BootGame(filename);
|
||||
BootGame(filename, CabinetId);
|
||||
}
|
||||
|
||||
void GMainWindow::OnMiiEdit() {
|
||||
|
@ -4371,7 +4372,7 @@ void GMainWindow::OnMiiEdit() {
|
|||
|
||||
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
BootGame(filename);
|
||||
BootGame(filename, MiiEditId);
|
||||
}
|
||||
|
||||
void GMainWindow::OnCaptureScreenshot() {
|
||||
|
|
Loading…
Reference in a new issue