s32 sys_spu_image_open(vm::ptr<sys_spu_image_t> img, vm::cptr<char> path) { sys_spu.warning("sys_spu_image_open(img=*0x%x, path=*0x%x)", img, path); const fs::file f(vfs::get(path.get_ptr())); if (!f) { sys_spu.error("sys_spu_image_open() error: '%s' not found!", path.get_ptr()); return CELL_ENOENT; } SceHeader hdr; hdr.Load(f); if (hdr.CheckMagic()) { throw fmt::exception("sys_spu_image_open() error: '%s' is encrypted! Try to decrypt it manually and try again.", path.get_ptr()); } f.seek(0); u32 entry; u32 offset = LoadSpuImage(f, entry); img->type = SYS_SPU_IMAGE_TYPE_USER; img->entry_point = entry; img->segs.set(offset); // TODO: writing actual segment info img->nsegs = 1; // wrong value return CELL_OK; }
s32 sys_raw_spu_load(s32 id, vm::cptr<char> path, vm::ptr<u32> entry) { sysPrxForUser.warning("sys_raw_spu_load(id=%d, path=*0x%x, entry=*0x%x)", id, path, entry); sysPrxForUser.warning("*** path = '%s'", path.get_ptr()); const fs::file f(vfs::get(path.get_ptr())); if (!f) { sysPrxForUser.error("sys_raw_spu_load() error: '%s' not found!", path.get_ptr()); return CELL_ENOENT; } SceHeader hdr; hdr.Load(f); if (hdr.CheckMagic()) { throw fmt::exception("sys_raw_spu_load() error: '%s' is encrypted! Try to decrypt it manually and try again.", path.get_ptr()); } f.seek(0); u32 _entry; LoadSpuImage(f, _entry, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id); *entry = _entry | 1; return CELL_OK; }
extern bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key) { if (!self) return false; self.seek(0); if (self.size() >= 4 && self.read<u32>() == "SCE\0"_u32) { // Check the ELF file class (32 or 64 bit). bool isElf32 = IsSelfElf32(self); // Start the decrypter on this SELF file. SELFDecrypter self_dec(self); // Load the SELF file headers. if (!self_dec.LoadHeaders(isElf32)) { LOG_ERROR(LOADER, "SELF: Failed to load SELF file headers!"); return false; } // Load and decrypt the SELF file metadata. if (!self_dec.LoadMetadata(klic_key)) { LOG_ERROR(LOADER, "SELF: Failed to load SELF file metadata!"); return false; } } return true; }
static bool IsSelfElf32(const fs::file& f) { if (!f) return false; f.seek(0); SceHeader hdr; SelfHeader sh; hdr.Load(f); sh.Load(f); // Locate the class byte and check it. u8 elf_class[0x8]; f.seek(sh.se_elfoff); f.read(elf_class, 0x8); return (elf_class[4] == 1); }
void save_gui_cfg() { YAML::Emitter out; out.SetSeqFormat(YAML::Flow); out << g_gui_cfg; // Save to file s_gui_cfg.seek(0); s_gui_cfg.trunc(0); s_gui_cfg.write(out.c_str(), out.size()); }
static bool CheckDebugSelf(fs::file& s) { if (s.size() < 0x18) { return false; } // Get the key version. s.seek(0x08); const u16 key_version = s.read<le_t<u16>>(); // Check for DEBUG version. if (key_version == 0x80 || key_version == 0xc0) { LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header..."); // Get the real elf offset. s.seek(0x10); // Start at the real elf offset. s.seek(key_version == 0x80 ? +s.read<be_t<u64>>() : +s.read<le_t<u64>>()); // Write the real ELF file back. fs::file e = fs::make_stream<std::vector<u8>>(); // Copy the data. char buf[2048]; while (u64 size = s.read(buf, 2048)) { e.write(buf, size); } s = std::move(e); return true; } // Leave the file untouched. return false; }
extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key) { if (!elf_or_self) { return fs::file{}; } elf_or_self.seek(0); // Check SELF header first. Check for a debug SELF. if (elf_or_self.size() >= 4 && elf_or_self.read<u32>() == "SCE\0"_u32 && !CheckDebugSelf(elf_or_self)) { // Check the ELF file class (32 or 64 bit). bool isElf32 = IsSelfElf32(elf_or_self); // Start the decrypter on this SELF file. SELFDecrypter self_dec(elf_or_self); // Load the SELF file headers. if (!self_dec.LoadHeaders(isElf32)) { LOG_ERROR(LOADER, "SELF: Failed to load SELF file headers!"); return fs::file{}; } // Load and decrypt the SELF file metadata. if (!self_dec.LoadMetadata(klic_key)) { LOG_ERROR(LOADER, "SELF: Failed to load SELF file metadata!"); return fs::file{}; } // Decrypt the SELF file data. if (!self_dec.DecryptData()) { LOG_ERROR(LOADER, "SELF: Failed to decrypt SELF file data!"); return fs::file{}; } // Make a new ELF file from this SELF. return self_dec.MakeElf(isElf32); } return elf_or_self; }
SettingsDialog::SettingsDialog(wxWindow* parent) : wxDialog(parent, wxID_ANY, "Settings", wxDefaultPosition) { // Load default config loaded = YAML::Load(g_cfg_defaults); // Incrementally load config.yml const fs::file config(fs::get_config_dir() + "/config.yml", fs::read + fs::write + fs::create); loaded += YAML::Load(config.to_string()); std::vector<std::unique_ptr<cfg_adapter>> pads; static const u32 width = 458; static const u32 height = 400; // Settings panels wxNotebook* nb_config = new wxNotebook(this, wxID_ANY, wxPoint(6, 6), wxSize(width, height)); wxPanel* p_system = new wxPanel(nb_config, wxID_ANY); wxPanel* p_core = new wxPanel(nb_config, wxID_ANY); wxPanel* p_graphics = new wxPanel(nb_config, wxID_ANY); wxPanel* p_audio = new wxPanel(nb_config, wxID_ANY); wxPanel* p_io = new wxPanel(nb_config, wxID_ANY); wxPanel* p_misc = new wxPanel(nb_config, wxID_ANY); wxPanel* p_networking = new wxPanel(nb_config, wxID_ANY); nb_config->AddPage(p_core, "Core"); nb_config->AddPage(p_graphics, "Graphics"); nb_config->AddPage(p_audio, "Audio"); nb_config->AddPage(p_io, "Input / Output"); nb_config->AddPage(p_misc, "Misc"); nb_config->AddPage(p_networking, "Networking"); nb_config->AddPage(p_system, "System"); wxBoxSizer* s_subpanel_core = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* s_subpanel_core1 = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_core2 = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_graphics = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* s_subpanel_graphics1 = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_graphics2 = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_audio = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_io = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* s_subpanel_io1 = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_io2 = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_system = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_misc = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_subpanel_networking = new wxBoxSizer(wxVERTICAL); // Core wxStaticBoxSizer* s_round_core_lle = new wxStaticBoxSizer(wxVERTICAL, p_core, "Load libraries"); chbox_list_core_lle = new wxCheckListBox(p_core, wxID_ANY, wxDefaultPosition, wxDefaultSize, {}, wxLB_EXTENDED); chbox_list_core_lle->Bind(wxEVT_CHECKLISTBOX, &SettingsDialog::OnModuleListItemToggled, this); wxTextCtrl* s_module_search_box = new wxTextCtrl(p_core, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, {}); s_module_search_box->Bind(wxEVT_TEXT, &SettingsDialog::OnSearchBoxTextChanged, this); // Graphics wxStaticBoxSizer* s_round_gs_render = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Rendering API"); wxStaticBoxSizer* s_round_gs_d3d_adapter = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "D3D Adapter"); wxStaticBoxSizer* s_round_gs_res = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Resolution"); wxStaticBoxSizer* s_round_gs_aspect = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Aspect ratio"); wxStaticBoxSizer* s_round_gs_frame_limit = new wxStaticBoxSizer(wxVERTICAL, p_graphics, "Frame limit"); // Input / Output wxStaticBoxSizer* s_round_io_pad_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, "Controller handler"); wxStaticBoxSizer* s_round_io_keyboard_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, "Keyboard handler"); wxStaticBoxSizer* s_round_io_mouse_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, "Mouse handler"); wxStaticBoxSizer* s_round_io_camera = new wxStaticBoxSizer(wxVERTICAL, p_io, "Camera"); wxStaticBoxSizer* s_round_io_camera_type = new wxStaticBoxSizer(wxVERTICAL, p_io, "Camera type"); // Audio wxStaticBoxSizer* s_round_audio_out = new wxStaticBoxSizer(wxVERTICAL, p_audio, "Audio out"); // Networking wxStaticBoxSizer* s_round_net_status = new wxStaticBoxSizer(wxVERTICAL, p_networking, "Connection status"); // System wxStaticBoxSizer* s_round_sys_lang = new wxStaticBoxSizer(wxVERTICAL, p_system, "Language"); wxRadioBox* rbox_ppu_decoder; wxRadioBox* rbox_spu_decoder; wxComboBox* cbox_gs_render = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_gs_d3d_adapter = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_gs_resolution = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_gs_aspect = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_gs_frame_limit = new wxComboBox(p_graphics, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_pad_handler = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY);; wxComboBox* cbox_keyboard_handler = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_mouse_handler = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_camera = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_camera_type = new wxComboBox(p_io, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_audio_out = new wxComboBox(p_audio, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0, NULL, wxCB_READONLY); wxComboBox* cbox_net_status = new wxComboBox(p_networking, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY); wxComboBox* cbox_sys_lang = new wxComboBox(p_system, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY); wxCheckBox* chbox_core_hook_stfunc = new wxCheckBox(p_core, wxID_ANY, "Hook static functions"); wxCheckBox* chbox_core_load_liblv2 = new wxCheckBox(p_core, wxID_ANY, "Load liblv2.sprx"); wxCheckBox* chbox_vfs_enable_host_root = new wxCheckBox(p_system, wxID_ANY, "Enable /host_root/"); wxCheckBox* chbox_gs_log_prog = new wxCheckBox(p_graphics, wxID_ANY, "Log shader programs"); wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write depth buffer"); wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write color buffers"); wxCheckBox* chbox_gs_read_color = new wxCheckBox(p_graphics, wxID_ANY, "Read color buffers"); wxCheckBox* chbox_gs_read_depth = new wxCheckBox(p_graphics, wxID_ANY, "Read depth buffer"); wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync"); wxCheckBox* chbox_gs_debug_output = new wxCheckBox(p_graphics, wxID_ANY, "Debug output"); wxCheckBox* chbox_gs_overlay = new wxCheckBox(p_graphics, wxID_ANY, "Debug overlay"); wxCheckBox* chbox_gs_gl_legacy_buffers = new wxCheckBox(p_graphics, wxID_ANY, "Use legacy OpenGL buffers"); wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file"); wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16-bit"); wxCheckBox* chbox_hle_exitonstop = new wxCheckBox(p_misc, wxID_ANY, "Exit RPCS3 when process finishes"); wxCheckBox* chbox_hle_always_start = new wxCheckBox(p_misc, wxID_ANY, "Always start after boot"); wxCheckBox* chbox_dbg_ap_systemcall = new wxCheckBox(p_misc, wxID_ANY, "Automatically pause at system call"); wxCheckBox* chbox_dbg_ap_functioncall = new wxCheckBox(p_misc, wxID_ANY, "Automatically pause at function call"); { // Sort string vector alphabetically static const auto sort_string_vector = [](std::vector<std::string>& vec) { std::sort(vec.begin(), vec.end(), [](const std::string &str1, const std::string &str2) { return str1 < str2; }); }; auto&& data = loaded["Core"]["Load libraries"].as<std::vector<std::string>, std::initializer_list<std::string>>({}); sort_string_vector(data); // List selected modules first for (const auto& unk : data) { lle_module_list.insert(lle_module_list.end(), std::pair<std::string, bool>(unk, true)); chbox_list_core_lle->Check(chbox_list_core_lle->Append(unk)); } const std::string& lle_dir = Emu.GetLibDir(); // TODO std::unordered_set<std::string> set(data.begin(), data.end()); std::vector<std::string> lle_module_list_unselected; for (const auto& prxf : fs::dir(lle_dir)) { // List found unselected modules if (!prxf.is_directory && ppu_prx_object(fs::file(lle_dir + prxf.name)) == elf_error::ok && !set.count(prxf.name)) { lle_module_list_unselected.push_back(prxf.name); } } sort_string_vector(lle_module_list_unselected); for (const auto& prxf : lle_module_list_unselected) { lle_module_list.insert(lle_module_list.end(), std::pair<std::string, bool>(prxf, false)); chbox_list_core_lle->Check(chbox_list_core_lle->Append(prxf), false); } lle_module_list_unselected.clear(); } radiobox_pad_helper ppu_decoder_modes({ "Core", "PPU decoder" }); rbox_ppu_decoder = new wxRadioBox(p_core, wxID_ANY, "PPU decoder", wxDefaultPosition, wxSize(-1, -1), ppu_decoder_modes, 1); pads.emplace_back(std::make_unique<radiobox_pad>(std::move(ppu_decoder_modes), rbox_ppu_decoder)); radiobox_pad_helper spu_decoder_modes({ "Core", "SPU decoder" }); rbox_spu_decoder = new wxRadioBox(p_core, wxID_ANY, "SPU decoder", wxDefaultPosition, wxSize(-1, -1), spu_decoder_modes, 1); pads.emplace_back(std::make_unique<radiobox_pad>(std::move(spu_decoder_modes), rbox_spu_decoder)); rbox_spu_decoder->Enable(3, false); // TODO pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Core", "Hook static functions" }, chbox_core_hook_stfunc)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Core", "Load liblv2.sprx only" }, chbox_core_load_liblv2)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "VFS", "Enable /host_root/" }, chbox_vfs_enable_host_root)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Rendering API" }, cbox_gs_render)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Resolution" }, cbox_gs_resolution)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Aspect ratio" }, cbox_gs_aspect)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "Frame limit" }, cbox_gs_frame_limit)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Log shader programs" }, chbox_gs_log_prog)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Write depth buffer" }, chbox_gs_dump_depth)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Write color buffers" }, chbox_gs_dump_color)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Read color buffers" }, chbox_gs_read_color)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Read depth buffer" }, chbox_gs_read_depth)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "VSync" }, chbox_gs_vsync)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Debug output" }, chbox_gs_debug_output)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Debug overlay" }, chbox_gs_overlay)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Video", "Use legacy OpenGL buffers (Debug)" }, chbox_gs_gl_legacy_buffers)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Audio", "Renderer" }, cbox_audio_out)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Dump to file" }, chbox_audio_dump)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Audio", "Convert to 16-bit" }, chbox_audio_conv)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Controller" }, cbox_pad_handler)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Keyboard" }, cbox_keyboard_handler)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Mouse" }, cbox_mouse_handler)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Camera" }, cbox_camera)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Input/Output", "Camera type" }, cbox_camera_type)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Net", "Connection status" }, cbox_net_status)); pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "System", "Language" }, cbox_sys_lang)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Exit RPCS3 when process finishes" }, chbox_hle_exitonstop)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Always start after boot" }, chbox_hle_always_start)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Automatically pause at system call" }, chbox_dbg_ap_systemcall)); pads.emplace_back(std::make_unique<checkbox_pad>(cfg_location{ "Miscellaneous", "Automatically pause at function call" }, chbox_dbg_ap_functioncall)); #ifdef _MSC_VER Microsoft::WRL::ComPtr<IDXGIFactory4> dxgi_factory; if (SUCCEEDED(CreateDXGIFactory(IID_PPV_ARGS(&dxgi_factory)))) { Microsoft::WRL::ComPtr<IDXGIAdapter> adapter; for (UINT id = 0; dxgi_factory->EnumAdapters(id, adapter.ReleaseAndGetAddressOf()) != DXGI_ERROR_NOT_FOUND; id++) { DXGI_ADAPTER_DESC desc; adapter->GetDesc(&desc); cbox_gs_d3d_adapter->Append(desc.Description); } pads.emplace_back(std::make_unique<combobox_pad>(cfg_location{ "Video", "D3D12", "Adapter" }, cbox_gs_d3d_adapter)); } else #endif { cbox_gs_d3d_adapter->Enable(false); } // Core s_round_core_lle->Add(chbox_list_core_lle, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_core_lle->Add(s_module_search_box, wxSizerFlags().Border(wxALL, 5).Expand()); // Rendering s_round_gs_render->Add(cbox_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_gs_d3d_adapter->Add(cbox_gs_d3d_adapter, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_gs_res->Add(cbox_gs_resolution, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_gs_aspect->Add(cbox_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_gs_frame_limit->Add(cbox_gs_frame_limit, wxSizerFlags().Border(wxALL, 5).Expand()); // Input/Output s_round_io_pad_handler->Add(cbox_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_io_keyboard_handler->Add(cbox_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_io_mouse_handler->Add(cbox_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_io_camera->Add(cbox_camera, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_io_camera_type->Add(cbox_camera_type, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_audio_out->Add(cbox_audio_out, wxSizerFlags().Border(wxALL, 5).Expand()); // Networking s_round_net_status->Add(cbox_net_status, wxSizerFlags().Border(wxALL, 5).Expand()); // System s_round_sys_lang->Add(cbox_sys_lang, wxSizerFlags().Border(wxALL, 5).Expand()); // Core s_subpanel_core1->Add(rbox_ppu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core1->Add(rbox_spu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core1->Add(chbox_core_hook_stfunc, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core1->Add(chbox_core_load_liblv2, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core2->Add(s_round_core_lle, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_core->Add(s_subpanel_core1); s_subpanel_core->Add(s_subpanel_core2); // Graphics s_subpanel_graphics1->Add(s_round_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics1->Add(s_round_gs_res, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics1->Add(s_round_gs_d3d_adapter, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics1->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics1->Add(chbox_gs_read_color, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics1->Add(chbox_gs_dump_depth, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics1->Add(chbox_gs_read_depth, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics1->Add(chbox_gs_gl_legacy_buffers, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics2->Add(s_round_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics2->Add(s_round_gs_frame_limit, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics2->AddSpacer(68); s_subpanel_graphics2->Add(chbox_gs_debug_output, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics2->Add(chbox_gs_overlay, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics2->Add(chbox_gs_log_prog, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics2->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(s_subpanel_graphics1); s_subpanel_graphics->Add(s_subpanel_graphics2); // Input - Output s_subpanel_io1->Add(s_round_io_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_io1->Add(s_round_io_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_io1->Add(s_round_io_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_io2->Add(s_round_io_camera, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_io2->Add(s_round_io_camera_type, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_io->Add(s_subpanel_io1); s_subpanel_io->Add(s_subpanel_io2); // Audio s_subpanel_audio->Add(s_round_audio_out, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_audio->Add(chbox_audio_dump, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_audio->Add(chbox_audio_conv, wxSizerFlags().Border(wxALL, 5).Expand()); // Miscellaneous s_subpanel_misc->Add(chbox_hle_exitonstop, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_misc->Add(chbox_hle_always_start, wxSizerFlags().Border(wxALL, 5).Expand()); // Auto Pause s_subpanel_misc->Add(chbox_dbg_ap_systemcall, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_misc->Add(chbox_dbg_ap_functioncall, wxSizerFlags().Border(wxALL, 5).Expand()); // Networking s_subpanel_networking->Add(s_round_net_status, wxSizerFlags().Border(wxALL, 5).Expand()); // System s_subpanel_system->Add(chbox_vfs_enable_host_root, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_system->Add(s_round_sys_lang, wxSizerFlags().Border(wxALL, 5).Expand()); // Buttons wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); s_b_panel->Add(new wxButton(this, wxID_OK), wxSizerFlags().Border(wxALL, 5).Bottom()); s_b_panel->Add(new wxButton(this, wxID_CANCEL), wxSizerFlags().Border(wxALL, 5).Bottom()); // Resize panels SetSizerAndFit(s_subpanel_core, false); SetSizerAndFit(s_subpanel_graphics, false); SetSizerAndFit(s_subpanel_io, false); SetSizerAndFit(s_subpanel_audio, false); SetSizerAndFit(s_subpanel_misc, false); SetSizerAndFit(s_subpanel_networking, false); SetSizerAndFit(s_subpanel_system, false); SetSizerAndFit(s_b_panel, false); SetSize(width + 26, height + 80); if (ShowModal() == wxID_OK) { std::set<std::string> lle_selected; for (auto& i : lle_module_list) { if (i.second) // selected { lle_selected.emplace(i.first); } } saved.reset(); saved["Core"]["Load libraries"] = std::vector<std::string>(lle_selected.begin(), lle_selected.end()); for (auto& pad : pads) { pad->save(); } loaded += saved; YAML::Emitter out; emit(out, loaded); // Save config config.seek(0); config.trunc(0); config.write(out.c_str(), out.size()); } }
// Decrypts full file fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, const std::string& rap_file_name, u8 *custom_klic, bool verbose) { // Prepare the files. input.seek(0); // Set keys (RIF and DEVKLIC). std::array<u8, 0x10> rifKey{ 0 }; unsigned char devklic[0x10] = { 0 }; // Select the EDAT key mode. switch (mode) { case 0: break; case 1: memcpy(devklic, NP_KLIC_FREE, 0x10); break; case 2: memcpy(devklic, NP_OMAC_KEY_2, 0x10); break; case 3: memcpy(devklic, NP_OMAC_KEY_3, 0x10); break; case 4: memcpy(devklic, NP_KLIC_KEY, 0x10); break; case 5: memcpy(devklic, NP_PSX_KEY, 0x10); break; case 6: memcpy(devklic, NP_PSP_KEY_1, 0x10); break; case 7: memcpy(devklic, NP_PSP_KEY_2, 0x10); break; case 8: { if (custom_klic != NULL) memcpy(devklic, custom_klic, 0x10); else { LOG_ERROR(LOADER, "EDAT: Invalid custom klic!"); return fs::file{}; } break; } default: LOG_ERROR(LOADER, "EDAT: Invalid mode!"); return fs::file{}; } // Read the RAP file, if provided. if (rap_file_name.size()) { fs::file rap(rap_file_name); rifKey = GetEdatRifKeyFromRapFile(rap); } // Delete the bad output file if any errors arise. fs::file output = fs::make_stream<std::vector<u8>>(); if (extract_all_data(&input, &output, input_file_name.c_str(), devklic, rifKey.data(), verbose)) { output.release(); return fs::file{}; } output.seek(0); return output; }
void save_object(const fs::file& stream, const psf::registry& psf) { std::vector<def_table_t> indices; indices.reserve(psf.size()); // Generate indices and calculate key table length std::size_t key_offset = 0, data_offset = 0; for (const auto& entry : psf) { def_table_t index; index.key_off = ::narrow<u32>(key_offset); index.param_fmt = entry.second.type(); index.param_len = entry.second.size(); index.param_max = entry.second.max(); index.data_off = ::narrow<u32>(data_offset); // Update offsets: key_offset += ::narrow<u32>(entry.first.size() + 1); // key size data_offset += index.param_max; indices.push_back(index); } // Align next section (data) offset key_offset = ::align(key_offset, 4); // Generate header header_t header; header.magic = "\0PSF"_u32; header.version = 0x101; header.off_key_table = ::narrow<u32>(sizeof(header_t) + sizeof(def_table_t) * psf.size()); header.off_data_table = ::narrow<u32>(header.off_key_table + key_offset); header.entries_num = ::narrow<u32>(psf.size()); // Save header and indices stream.write(header); stream.write(indices); // Save key table for (const auto& entry : psf) { stream.write(entry.first); stream.write('\0'); } // Skip padding stream.trunc(stream.seek(header.off_data_table)); // Save data for (const auto& entry : psf) { const auto fmt = entry.second.type(); const u32 max = entry.second.max(); if (fmt == format::integer && max == sizeof(u32)) { const le_t<u32> value = entry.second.as_integer(); stream.write(value); } else if (fmt == format::string || fmt == format::array) { const std::string& value = entry.second.as_string(); const std::size_t size = std::min<std::size_t>(max, value.size()); if (value.size() + (fmt == format::string) > max) { // TODO: check real limitations of PSF format LOG_ERROR(LOADER, "Entry value shrinkage (key='%s', value='%s', size=0x%zx, max=0x%x)", entry.first, value, size, max); } stream.write(value); stream.trunc(stream.seek(max - size, fs::seek_cur)); // Skip up to max_size } else { fmt::throw_exception("Invalid entry format (key='%s', fmt=0x%x)" HERE, entry.first, fmt); } } }
registry load_object(const fs::file& stream) { registry result; // Hack for empty input (TODO) if (!stream) { return result; } // Get header header_t header; verify(HERE), stream.read(header); // Check magic and version verify(HERE), header.magic == "\0PSF"_u32, header.version == 0x101, sizeof(header_t) + header.entries_num * sizeof(def_table_t) <= header.off_key_table, header.off_key_table <= header.off_data_table, header.off_data_table <= stream.size(); // Get indices std::vector<def_table_t> indices; verify(HERE), stream.read(indices, header.entries_num); // Get keys std::string keys; verify(HERE), stream.seek(header.off_key_table) == header.off_key_table; verify(HERE), stream.read(keys, header.off_data_table - header.off_key_table); // Load entries for (u32 i = 0; i < header.entries_num; ++i) { verify(HERE), indices[i].key_off < header.off_data_table - header.off_key_table; // Get key name (null-terminated string) std::string key(keys.data() + indices[i].key_off); // Check entry verify(HERE), result.count(key) == 0, indices[i].param_len <= indices[i].param_max, indices[i].data_off < stream.size() - header.off_data_table, indices[i].param_max < stream.size() - indices[i].data_off; // Seek data pointer stream.seek(header.off_data_table + indices[i].data_off); if (indices[i].param_fmt == format::integer && indices[i].param_max == sizeof(u32) && indices[i].param_len == sizeof(u32)) { // Integer data le_t<u32> value; verify(HERE), stream.read(value); result.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::forward_as_tuple(value)); } else if (indices[i].param_fmt == format::string || indices[i].param_fmt == format::array) { // String/array data std::string value; verify(HERE), stream.read(value, indices[i].param_len); if (indices[i].param_fmt == format::string) { // Find null terminator value.resize(std::strlen(value.c_str())); } result.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::forward_as_tuple(indices[i].param_fmt, indices[i].param_max, std::move(value))); } else { // Possibly unsupported format, entry ignored LOG_ERROR(LOADER, "Unknown entry format (key='%s', fmt=0x%x, len=0x%x, max=0x%x)", key, indices[i].param_fmt, indices[i].param_len, indices[i].param_max); } } return result; }