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
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3971.
|
This is the source code for early-access 3972.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "input_common/drivers/virtual_gamepad.h"
|
#include "input_common/drivers/virtual_gamepad.h"
|
||||||
#include "input_common/main.h"
|
#include "input_common/main.h"
|
||||||
#include "jni/emu_window/emu_window.h"
|
#include "jni/emu_window/emu_window.h"
|
||||||
|
#include "jni/native.h"
|
||||||
|
|
||||||
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
m_window_width = ANativeWindow_getWidth(surface);
|
m_window_width = ANativeWindow_getWidth(surface);
|
||||||
|
@ -57,6 +58,13 @@ void EmuWindow_Android::OnRemoveNfcTag() {
|
||||||
m_input_subsystem->GetVirtualAmiibo()->CloseAmiibo();
|
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,
|
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem,
|
||||||
ANativeWindow* surface,
|
ANativeWindow* surface,
|
||||||
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
float gyro_z, float accel_x, float accel_y, float accel_z);
|
float gyro_z, float accel_x, float accel_y, float accel_z);
|
||||||
void OnReadNfcTag(std::span<u8> data);
|
void OnReadNfcTag(std::span<u8> data);
|
||||||
void OnRemoveNfcTag();
|
void OnRemoveNfcTag();
|
||||||
void OnFrameDisplayed() override {}
|
void OnFrameDisplayed() override;
|
||||||
|
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
|
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
|
||||||
return {std::make_unique<GraphicsContext_Android>(m_driver_library)};
|
return {std::make_unique<GraphicsContext_Android>(m_driver_library)};
|
||||||
|
@ -61,4 +61,6 @@ private:
|
||||||
float m_window_height{};
|
float m_window_height{};
|
||||||
|
|
||||||
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
||||||
|
|
||||||
|
bool m_first_frame = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -372,8 +372,6 @@ void EmulationSession::RunEmulation() {
|
||||||
m_system.InitializeDebugger();
|
m_system.InitializeDebugger();
|
||||||
}
|
}
|
||||||
|
|
||||||
OnEmulationStarted();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
{
|
{
|
||||||
[[maybe_unused]] std::unique_lock lock(m_mutex);
|
[[maybe_unused]] std::unique_lock lock(m_mutex);
|
||||||
|
|
|
@ -52,9 +52,10 @@ public:
|
||||||
void OnGamepadDisconnectEvent([[maybe_unused]] int index);
|
void OnGamepadDisconnectEvent([[maybe_unused]] int index);
|
||||||
SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
|
SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
|
||||||
|
|
||||||
|
static void OnEmulationStarted();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
||||||
static void OnEmulationStarted();
|
|
||||||
static void OnEmulationStopped(Core::SystemResultStatus result);
|
static void OnEmulationStopped(Core::SystemResultStatus result);
|
||||||
|
|
||||||
private:
|
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) {
|
void GDBStub::HandleQuery(std::string_view command) {
|
||||||
if (command.starts_with("TStatus")) {
|
if (command.starts_with("TStatus")) {
|
||||||
// no tracepoint support
|
// no tracepoint support
|
||||||
|
@ -573,21 +687,10 @@ void GDBStub::HandleQuery(std::string_view command) {
|
||||||
const auto target_xml{arch->GetTargetXML()};
|
const auto target_xml{arch->GetTargetXML()};
|
||||||
SendReply(PaginateBuffer(target_xml, command.substr(30)));
|
SendReply(PaginateBuffer(target_xml, command.substr(30)));
|
||||||
} else if (command.starts_with("Offsets")) {
|
} else if (command.starts_with("Offsets")) {
|
||||||
Loader::AppLoader::Modules modules;
|
const auto main_offset = FindMainModuleEntrypoint(system);
|
||||||
system.GetAppLoader().ReadNSOModules(modules);
|
SendReply(fmt::format("TextSeg={:x}", main_offset));
|
||||||
|
|
||||||
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())));
|
|
||||||
}
|
|
||||||
} else if (command.starts_with("Xfer:libraries:read::")) {
|
} else if (command.starts_with("Xfer:libraries:read::")) {
|
||||||
Loader::AppLoader::Modules modules;
|
auto modules = FindModules(system);
|
||||||
system.GetAppLoader().ReadNSOModules(modules);
|
|
||||||
|
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
buffer += R"(<?xml version="1.0"?>)";
|
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) {
|
void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
||||||
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
|
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
|
||||||
std::string reply;
|
std::string reply;
|
||||||
|
@ -784,8 +856,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
||||||
reply = "Fastmem is not enabled.\n";
|
reply = "Fastmem is not enabled.\n";
|
||||||
}
|
}
|
||||||
} else if (command_str == "get info") {
|
} else if (command_str == "get info") {
|
||||||
Loader::AppLoader::Modules modules;
|
auto modules = FindModules(system);
|
||||||
system.GetAppLoader().ReadNSOModules(modules);
|
|
||||||
|
|
||||||
reply = fmt::format("Process: {:#x} ({})\n"
|
reply = fmt::format("Process: {:#x} ({})\n"
|
||||||
"Program Id: {:#018x}\n",
|
"Program Id: {:#018x}\n",
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "core/hle/kernel/k_capabilities.h"
|
#include "core/hle/kernel/k_capabilities.h"
|
||||||
#include "core/hle/kernel/k_memory_layout.h"
|
#include "core/hle/kernel/k_memory_layout.h"
|
||||||
#include "core/hle/kernel/k_process_page_table.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/kernel.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/kernel/svc_version.h"
|
#include "core/hle/kernel/svc_version.h"
|
||||||
|
@ -329,6 +330,8 @@ Result KCapabilities::SetCapabilities(std::span<const u32> caps, KProcessPageTab
|
||||||
|
|
||||||
// Map the range.
|
// Map the range.
|
||||||
R_TRY(this->MapRange_(cap, size_cap, page_table));
|
R_TRY(this->MapRange_(cap, size_cap, page_table));
|
||||||
|
} else if (GetCapabilityType(cap) == CapabilityType::MapRegion && !IsKTraceEnabled) {
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table));
|
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) {
|
StartGameType type, AmLaunchType launch_type) {
|
||||||
LOG_INFO(Frontend, "yuzu starting...");
|
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
|
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());
|
const auto filename = QString::fromStdString(album_nca->GetFullPath());
|
||||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||||
BootGame(filename);
|
BootGame(filename, AlbumId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
|
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());
|
const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
|
||||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||||
BootGame(filename);
|
BootGame(filename, CabinetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnMiiEdit() {
|
void GMainWindow::OnMiiEdit() {
|
||||||
|
@ -4371,7 +4372,7 @@ void GMainWindow::OnMiiEdit() {
|
||||||
|
|
||||||
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
|
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
|
||||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||||
BootGame(filename);
|
BootGame(filename, MiiEditId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnCaptureScreenshot() {
|
void GMainWindow::OnCaptureScreenshot() {
|
||||||
|
|
Loading…
Reference in a new issue