diff options
| -rw-r--r-- | src/core/loader/deconstructed_rom_directory.cpp | 4 | ||||
| -rw-r--r-- | src/core/loader/nro.cpp | 15 | ||||
| -rw-r--r-- | src/core/loader/nso.cpp | 17 | ||||
| -rw-r--r-- | src/core/loader/nso.h | 11 | ||||
| -rw-r--r-- | src/core/settings.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.ui | 23 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 1 | ||||
| -rw-r--r-- | src/yuzu_cmd/yuzu.cpp | 19 |
10 files changed, 84 insertions, 11 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 9a86e5824..951fd8257 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cinttypes> | 5 | #include <cinttypes> |
| 6 | #include <cstring> | ||
| 6 | #include "common/common_funcs.h" | 7 | #include "common/common_funcs.h" |
| 7 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 8 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| @@ -140,7 +141,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) | |||
| 140 | const FileSys::VirtualFile module_file = dir->GetFile(module); | 141 | const FileSys::VirtualFile module_file = dir->GetFile(module); |
| 141 | if (module_file != nullptr) { | 142 | if (module_file != nullptr) { |
| 142 | const VAddr load_addr = next_load_addr; | 143 | const VAddr load_addr = next_load_addr; |
| 143 | next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr, pm); | 144 | next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr, |
| 145 | std::strcmp(module, "rtld") == 0, pm); | ||
| 144 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); | 146 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); |
| 145 | // Register module with GDBStub | 147 | // Register module with GDBStub |
| 146 | GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); | 148 | GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index c10f826a4..25dd3f04e 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -18,7 +18,9 @@ | |||
| 18 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/process.h" |
| 19 | #include "core/hle/kernel/vm_manager.h" | 19 | #include "core/hle/kernel/vm_manager.h" |
| 20 | #include "core/loader/nro.h" | 20 | #include "core/loader/nro.h" |
| 21 | #include "core/loader/nso.h" | ||
| 21 | #include "core/memory.h" | 22 | #include "core/memory.h" |
| 23 | #include "core/settings.h" | ||
| 22 | 24 | ||
| 23 | namespace Loader { | 25 | namespace Loader { |
| 24 | 26 | ||
| @@ -150,6 +152,19 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) { | |||
| 150 | codeset->segments[i].size = PageAlignSize(nro_header.segments[i].size); | 152 | codeset->segments[i].size = PageAlignSize(nro_header.segments[i].size); |
| 151 | } | 153 | } |
| 152 | 154 | ||
| 155 | if (!Settings::values.program_args.empty()) { | ||
| 156 | const auto arg_data = Settings::values.program_args; | ||
| 157 | codeset->DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; | ||
| 158 | NSOArgumentHeader args_header{ | ||
| 159 | NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}}; | ||
| 160 | const auto end_offset = program_image.size(); | ||
| 161 | program_image.resize(static_cast<u32>(program_image.size()) + | ||
| 162 | NSO_ARGUMENT_DATA_ALLOCATION_SIZE); | ||
| 163 | std::memcpy(program_image.data() + end_offset, &args_header, sizeof(NSOArgumentHeader)); | ||
| 164 | std::memcpy(program_image.data() + end_offset + sizeof(NSOArgumentHeader), arg_data.data(), | ||
| 165 | arg_data.size()); | ||
| 166 | } | ||
| 167 | |||
| 153 | // Read MOD header | 168 | // Read MOD header |
| 154 | ModHeader mod_header{}; | 169 | ModHeader mod_header{}; |
| 155 | // Default .bss to NRO header bss size if MOD0 section doesn't exist | 170 | // Default .bss to NRO header bss size if MOD0 section doesn't exist |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 2186b02af..28c6dd9b7 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "core/hle/kernel/vm_manager.h" | 17 | #include "core/hle/kernel/vm_manager.h" |
| 18 | #include "core/loader/nso.h" | 18 | #include "core/loader/nso.h" |
| 19 | #include "core/memory.h" | 19 | #include "core/memory.h" |
| 20 | #include "core/settings.h" | ||
| 20 | 21 | ||
| 21 | namespace Loader { | 22 | namespace Loader { |
| 22 | 23 | ||
| @@ -94,6 +95,7 @@ static constexpr u32 PageAlignSize(u32 size) { | |||
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, | 97 | VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, |
| 98 | bool should_pass_arguments, | ||
| 97 | boost::optional<FileSys::PatchManager> pm) { | 99 | boost::optional<FileSys::PatchManager> pm) { |
| 98 | if (file == nullptr) | 100 | if (file == nullptr) |
| 99 | return {}; | 101 | return {}; |
| @@ -125,6 +127,19 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, | |||
| 125 | codeset->segments[i].size = PageAlignSize(static_cast<u32>(data.size())); | 127 | codeset->segments[i].size = PageAlignSize(static_cast<u32>(data.size())); |
| 126 | } | 128 | } |
| 127 | 129 | ||
| 130 | if (should_pass_arguments && !Settings::values.program_args.empty()) { | ||
| 131 | const auto arg_data = Settings::values.program_args; | ||
| 132 | codeset->DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; | ||
| 133 | NSOArgumentHeader args_header{ | ||
| 134 | NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}}; | ||
| 135 | const auto end_offset = program_image.size(); | ||
| 136 | program_image.resize(static_cast<u32>(program_image.size()) + | ||
| 137 | NSO_ARGUMENT_DATA_ALLOCATION_SIZE); | ||
| 138 | std::memcpy(program_image.data() + end_offset, &args_header, sizeof(NSOArgumentHeader)); | ||
| 139 | std::memcpy(program_image.data() + end_offset + sizeof(NSOArgumentHeader), arg_data.data(), | ||
| 140 | arg_data.size()); | ||
| 141 | } | ||
| 142 | |||
| 128 | // MOD header pointer is at .text offset + 4 | 143 | // MOD header pointer is at .text offset + 4 |
| 129 | u32 module_offset; | 144 | u32 module_offset; |
| 130 | std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32)); | 145 | std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32)); |
| @@ -172,7 +187,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) { | |||
| 172 | 187 | ||
| 173 | // Load module | 188 | // Load module |
| 174 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); | 189 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); |
| 175 | LoadModule(file, base_address); | 190 | LoadModule(file, base_address, true); |
| 176 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); | 191 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); |
| 177 | 192 | ||
| 178 | process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); | 193 | process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); |
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 05353d4d9..70ab3b718 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h | |||
| @@ -11,6 +11,15 @@ | |||
| 11 | 11 | ||
| 12 | namespace Loader { | 12 | namespace Loader { |
| 13 | 13 | ||
| 14 | constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000; | ||
| 15 | |||
| 16 | struct NSOArgumentHeader { | ||
| 17 | u32_le allocated_size; | ||
| 18 | u32_le actual_size; | ||
| 19 | INSERT_PADDING_BYTES(0x18); | ||
| 20 | }; | ||
| 21 | static_assert(sizeof(NSOArgumentHeader) == 0x20, "NSOArgumentHeader has incorrect size."); | ||
| 22 | |||
| 14 | /// Loads an NSO file | 23 | /// Loads an NSO file |
| 15 | class AppLoader_NSO final : public AppLoader, Linker { | 24 | class AppLoader_NSO final : public AppLoader, Linker { |
| 16 | public: | 25 | public: |
| @@ -27,7 +36,7 @@ public: | |||
| 27 | return IdentifyType(file); | 36 | return IdentifyType(file); |
| 28 | } | 37 | } |
| 29 | 38 | ||
| 30 | static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base, | 39 | static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base, bool should_pass_arguments, |
| 31 | boost::optional<FileSys::PatchManager> pm = boost::none); | 40 | boost::optional<FileSys::PatchManager> pm = boost::none); |
| 32 | 41 | ||
| 33 | ResultStatus Load(Kernel::Process& process) override; | 42 | ResultStatus Load(Kernel::Process& process) override; |
diff --git a/src/core/settings.h b/src/core/settings.h index 1808f5937..83b9a04c8 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -155,6 +155,7 @@ struct Values { | |||
| 155 | // Debugging | 155 | // Debugging |
| 156 | bool use_gdbstub; | 156 | bool use_gdbstub; |
| 157 | u16 gdbstub_port; | 157 | u16 gdbstub_port; |
| 158 | std::string program_args; | ||
| 158 | 159 | ||
| 159 | // WebService | 160 | // WebService |
| 160 | bool enable_telemetry; | 161 | bool enable_telemetry; |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 650dd03c0..7fec15991 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -134,6 +134,7 @@ void Config::ReadValues() { | |||
| 134 | qt_config->beginGroup("Debugging"); | 134 | qt_config->beginGroup("Debugging"); |
| 135 | Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool(); | 135 | Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool(); |
| 136 | Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt(); | 136 | Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt(); |
| 137 | Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString(); | ||
| 137 | qt_config->endGroup(); | 138 | qt_config->endGroup(); |
| 138 | 139 | ||
| 139 | qt_config->beginGroup("WebService"); | 140 | qt_config->beginGroup("WebService"); |
| @@ -269,6 +270,7 @@ void Config::SaveValues() { | |||
| 269 | qt_config->beginGroup("Debugging"); | 270 | qt_config->beginGroup("Debugging"); |
| 270 | qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub); | 271 | qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub); |
| 271 | qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port); | 272 | qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port); |
| 273 | qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args)); | ||
| 272 | qt_config->endGroup(); | 274 | qt_config->endGroup(); |
| 273 | 275 | ||
| 274 | qt_config->beginGroup("WebService"); | 276 | qt_config->beginGroup("WebService"); |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 45d84f19a..9e765fc93 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -33,6 +33,7 @@ void ConfigureDebug::setConfiguration() { | |||
| 33 | ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | 33 | ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |
| 34 | ui->toggle_console->setChecked(UISettings::values.show_console); | 34 | ui->toggle_console->setChecked(UISettings::values.show_console); |
| 35 | ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); | 35 | ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); |
| 36 | ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); | ||
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | void ConfigureDebug::applyConfiguration() { | 39 | void ConfigureDebug::applyConfiguration() { |
| @@ -40,6 +41,7 @@ void ConfigureDebug::applyConfiguration() { | |||
| 40 | Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); | 41 | Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); |
| 41 | UISettings::values.show_console = ui->toggle_console->isChecked(); | 42 | UISettings::values.show_console = ui->toggle_console->isChecked(); |
| 42 | Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); | 43 | Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); |
| 44 | Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); | ||
| 43 | Debugger::ToggleConsole(); | 45 | Debugger::ToggleConsole(); |
| 44 | Log::Filter filter; | 46 | Log::Filter filter; |
| 45 | filter.ParseFilterString(Settings::values.log_filter); | 47 | filter.ParseFilterString(Settings::values.log_filter); |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 5ae7276bd..ff4987604 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -107,6 +107,29 @@ | |||
| 107 | </widget> | 107 | </widget> |
| 108 | </item> | 108 | </item> |
| 109 | <item> | 109 | <item> |
| 110 | <widget class="QGroupBox" name="groupBox_3"> | ||
| 111 | <property name="title"> | ||
| 112 | <string>Homebrew</string> | ||
| 113 | </property> | ||
| 114 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 115 | <item> | ||
| 116 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 117 | <item> | ||
| 118 | <widget class="QLabel" name="label"> | ||
| 119 | <property name="text"> | ||
| 120 | <string>Arguments String</string> | ||
| 121 | </property> | ||
| 122 | </widget> | ||
| 123 | </item> | ||
| 124 | <item> | ||
| 125 | <widget class="QLineEdit" name="homebrew_args_edit"/> | ||
| 126 | </item> | ||
| 127 | </layout> | ||
| 128 | </item> | ||
| 129 | </layout> | ||
| 130 | </widget> | ||
| 131 | </item> | ||
| 132 | <item> | ||
| 110 | <spacer name="verticalSpacer"> | 133 | <spacer name="verticalSpacer"> |
| 111 | <property name="orientation"> | 134 | <property name="orientation"> |
| 112 | <enum>Qt::Vertical</enum> | 135 | <enum>Qt::Vertical</enum> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 9d934e220..2470f4640 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -138,6 +138,7 @@ void Config::ReadValues() { | |||
| 138 | Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false); | 138 | Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false); |
| 139 | Settings::values.gdbstub_port = | 139 | Settings::values.gdbstub_port = |
| 140 | static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); | 140 | static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); |
| 141 | Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", ""); | ||
| 141 | 142 | ||
| 142 | // Web Service | 143 | // Web Service |
| 143 | Settings::values.enable_telemetry = | 144 | Settings::values.enable_telemetry = |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 1d951ca3f..27aba95f6 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -56,9 +56,10 @@ static void PrintHelp(const char* argv0) { | |||
| 56 | std::cout << "Usage: " << argv0 | 56 | std::cout << "Usage: " << argv0 |
| 57 | << " [options] <filename>\n" | 57 | << " [options] <filename>\n" |
| 58 | "-g, --gdbport=NUMBER Enable gdb stub on port NUMBER\n" | 58 | "-g, --gdbport=NUMBER Enable gdb stub on port NUMBER\n" |
| 59 | "-f, --fullscreen Start in fullscreen mode\n" | 59 | "-f, --fullscreen Start in fullscreen mode\n" |
| 60 | "-h, --help Display this help and exit\n" | 60 | "-h, --help Display this help and exit\n" |
| 61 | "-v, --version Output version information and exit\n"; | 61 | "-v, --version Output version information and exit\n" |
| 62 | "-p, --program Pass following string as arguments to executable\n"; | ||
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | static void PrintVersion() { | 65 | static void PrintVersion() { |
| @@ -103,15 +104,13 @@ int main(int argc, char** argv) { | |||
| 103 | bool fullscreen = false; | 104 | bool fullscreen = false; |
| 104 | 105 | ||
| 105 | static struct option long_options[] = { | 106 | static struct option long_options[] = { |
| 106 | {"gdbport", required_argument, 0, 'g'}, | 107 | {"gdbport", required_argument, 0, 'g'}, {"fullscreen", no_argument, 0, 'f'}, |
| 107 | {"fullscreen", no_argument, 0, 'f'}, | 108 | {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, |
| 108 | {"help", no_argument, 0, 'h'}, | 109 | {"program", optional_argument, 0, 'p'}, {0, 0, 0, 0}, |
| 109 | {"version", no_argument, 0, 'v'}, | ||
| 110 | {0, 0, 0, 0}, | ||
| 111 | }; | 110 | }; |
| 112 | 111 | ||
| 113 | while (optind < argc) { | 112 | while (optind < argc) { |
| 114 | char arg = getopt_long(argc, argv, "g:fhv", long_options, &option_index); | 113 | char arg = getopt_long(argc, argv, "g:fhvp::", long_options, &option_index); |
| 115 | if (arg != -1) { | 114 | if (arg != -1) { |
| 116 | switch (arg) { | 115 | switch (arg) { |
| 117 | case 'g': | 116 | case 'g': |
| @@ -135,6 +134,10 @@ int main(int argc, char** argv) { | |||
| 135 | case 'v': | 134 | case 'v': |
| 136 | PrintVersion(); | 135 | PrintVersion(); |
| 137 | return 0; | 136 | return 0; |
| 137 | case 'p': | ||
| 138 | Settings::values.program_args = argv[optind]; | ||
| 139 | ++optind; | ||
| 140 | break; | ||
| 138 | } | 141 | } |
| 139 | } else { | 142 | } else { |
| 140 | #ifdef _WIN32 | 143 | #ifdef _WIN32 |