external: Update few submodule and remove unicorn.

- Remove all Unicorn references from language files and project as it’s deprecated and unused.
- Update SPIRV-Cross to vulkan-sdk-1.4.321.
- Update YAML to latest master.
- Fix CMake minimum version requirement errors by ensuring minimum version 3.5.
This commit is contained in:
Zangetsu38
2025-07-28 06:25:59 +02:00
committed by scribam
parent 5f3c81f1bb
commit 3df27923b4
31 changed files with 18 additions and 663 deletions
-3
View File
@@ -51,9 +51,6 @@
[submodule "external/stb"]
path = external/stb
url = https://github.com/nothings/stb
[submodule "external/unicorn"]
path = external/unicorn
url = https://github.com/Vita3K/unicorn.git
[submodule "external/vita-toolchain"]
path = external/vita-toolchain
url = https://github.com/vitasdk/vita-toolchain.git
-3
View File
@@ -136,9 +136,6 @@ if(MSVC)
endif()
endif()
set(UNICORN_ARCH "arm")
add_subdirectory(unicorn EXCLUDE_FROM_ALL)
add_library(vita-toolchain INTERFACE)
target_include_directories(vita-toolchain INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/vita-toolchain/src")
-1
Submodule external/unicorn deleted from 9c816e02de
-3
View File
@@ -608,9 +608,6 @@ Please download and install the last PS Vita firmware.</no_modules>
<manual_description>Select Manual mode to load selected modules from the list below.</manual_description>
</core>
<cpu>
<unicorn>Unicorn (deprecated)</unicorn>
<cpu_backend>CPU Backend</cpu_backend>
<select_cpu_backend>Select your preferred CPU backend.</select_cpu_backend>
<cpu_opt>Enable optimizations</cpu_opt>
<cpu_opt_description>Check the box to enable additional CPU JIT optimizations.</cpu_opt_description>
</cpu>
-3
View File
@@ -608,9 +608,6 @@ Please download and install the last PS Vita firmware.</no_modules>
<manual_description>Select Manual mode to load selected modules from the list below.</manual_description>
</core>
<cpu>
<unicorn>Unicorn (deprecated)</unicorn>
<cpu_backend>CPU Backend</cpu_backend>
<select_cpu_backend>Select your preferred CPU backend.</select_cpu_backend>
<cpu_opt>Enable optimizations</cpu_opt>
<cpu_opt_description>Check the box to enable additional CPU JIT optimizations.</cpu_opt_description>
</cpu>
-3
View File
@@ -589,9 +589,6 @@ Proszę pobrać i zainstalować najnowsze oprogramowanie systemu PS Vita.</no_mo
<refresh_list>Odśwież listę</refresh_list>
</core>
<cpu name="Procesor">
<unicorn>Unicorn (porzucone)</unicorn>
<cpu_backend>Backend procesora</cpu_backend>
<select_cpu_backend>Wybierz preferowany backend procesora.</select_cpu_backend>
<cpu_opt>Włącz optymalizacje</cpu_opt>
<cpu_opt_description>Zaznacz, aby włączyć dodatkowe optymalizacje CPU JIT.</cpu_opt_description>
</cpu>
-3
View File
@@ -590,9 +590,6 @@
<manual_description>Выберите Ручной режим для загрузки только выбранных модулей из списка ниже.</manual_description>
</core>
<cpu>
<unicorn>Unicorn (устарел)</unicorn>
<cpu_backend>CPU бэкенд</cpu_backend>
<select_cpu_backend>Выберите бэкенд процессора.</select_cpu_backend>
<cpu_opt>Включить оптимизацию</cpu_opt>
<cpu_opt_description>Установите флажок, чтобы включить дополнительные JIT-оптимизации процессора.</cpu_opt_description>
</cpu>
-3
View File
@@ -606,9 +606,6 @@
<refresh_list>刷新列表</refresh_list>
</core>
<cpu>
<unicorn>Unicorn(已弃用)</unicorn>
<cpu_backend>CPU后端</cpu_backend>
<select_cpu_backend>选择您喜欢的CPU后端。</select_cpu_backend>
<cpu_opt>启用优化</cpu_opt>
<cpu_opt_description>勾选此项启用额外的CPU JIT优化。</cpu_opt_description>
</cpu>
-3
View File
@@ -606,9 +606,6 @@
<refresh_list>更新列表</refresh_list>
</core>
<cpu>
<unicorn>Unicorn(已棄用)</unicorn>
<cpu_backend>CPU後端</cpu_backend>
<select_cpu_backend>選擇您喜歡的CPU後端。</select_cpu_backend>
<cpu_opt>啟用最佳化</cpu_opt>
<cpu_opt_description>勾選此項啟用額外的CPU JIT最佳化。</cpu_opt_description>
</cpu>
-3
View File
@@ -549,9 +549,6 @@ Silakan download dan install firmware PS Vita terakhir.</no_modules>
<refresh_list>Perbarui Daftar</refresh_list>
</core>
<cpu>
<unicorn>Unicorn (tidak digunakan lagi)</unicorn>
<cpu_backend>Bagian Belakang CPU</cpu_backend>
<select_cpu_backend>Pilih perender backend pilihan kamu.</select_cpu_backend>
<cpu_opt>Aktifkan Pengoptimalan</cpu_opt>
<cpu_opt_description>Centang kotak untuk mengaktifkan optimasi CPU JIT tambahan.</cpu_opt_description>
</cpu>
-3
View File
@@ -553,9 +553,6 @@ Sila muat turun dan pasang PS Vita yang terakhir firmware.</no_modules>
<refresh_list>Muat Semula Senarai</refresh_list>
</core>
<cpu>
<unicorn>Unicorn (tidak digunakan lagi)</unicorn>
<cpu_backend>CPU Bahagian Belakang</cpu_backend>
<select_cpu_backend>Pilih bahagian belakang CPU pilihan awak.</select_cpu_backend>
<cpu_opt>Dayakan pengoptimuman</cpu_opt>
<cpu_opt_description>Tandai kotak untuk mendayakan pengoptimuman CPU JIT tambahan.</cpu_opt_description>
</cpu>
-3
View File
@@ -556,9 +556,6 @@
<refresh_list>Оновити список</refresh_list>
</core>
<cpu>
<unicorn>Unicorn (застарілий)</unicorn>
<cpu_backend>Бекенд центрального процесора</cpu_backend>
<select_cpu_backend>Оберіть бажаний бекенд центрального процесора.</select_cpu_backend>
<cpu_opt>Дозволити оптимізації</cpu_opt>
<cpu_opt_description>Оберіть цей пункт, аби дозволити додаткові JIT-оптимізації процесора.</cpu_opt_description>
</cpu>
-3
View File
@@ -392,9 +392,6 @@ bool late_init(EmuEnvState &state) {
return false;
}
if (state.mem.use_page_table && state.kernel.cpu_backend == CPUBackend::Unicorn)
LOG_CRITICAL("Unicorn backend is not supported with a page table");
const ResumeAudioThread resume_thread = [&state](SceUID thread_id) {
const auto thread = state.kernel.get_thread(thread_id);
const std::lock_guard<std::mutex> lock(thread->mutex);
-1
View File
@@ -100,7 +100,6 @@ enum ScreenshotFormat {
code(int, "delay-start", 10, delay_start) \
code(float, "background-alpha", .300f, background_alpha) \
code(int, "log-level", 0 /*SPDLOG_LEVEL_TRACE*/, log_level) \
code(std::string, "cpu-backend", "Dynarmic", cpu_backend) \
code(bool, "cpu-opt", true, cpu_opt) \
code(std::string, "pref-path", std::string{}, pref_path) \
code(bool, "discord-rich-presence", true, discord_rich_presence) \
-1
View File
@@ -58,7 +58,6 @@ struct Config {
* All the settings that appear in this struct can be adjusted using app-specific custom config files.
*/
struct CurrentConfig {
std::string cpu_backend;
bool cpu_opt = true;
int modules_mode = ModulesMode::AUTOMATIC;
std::vector<std::string> lle_modules = {};
+1 -3
View File
@@ -4,14 +4,12 @@ include/cpu/common.h
include/cpu/functions.h
include/cpu/impl/dynarmic_cpu.h
include/cpu/impl/interface.h
include/cpu/impl/unicorn_cpu.h
include/cpu/disasm/functions.h
include/cpu/disasm/state.h
src/disasm.cpp
src/cpu.cpp
src/dynarmic_cpu.cpp
src/unicorn_cpu.cpp
)
add_library(
@@ -24,4 +22,4 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})
target_include_directories(cpu PUBLIC include)
target_link_libraries(cpu PUBLIC mem util)
target_link_libraries(cpu PRIVATE dynarmic unicorn capstone merry::mcl)
target_link_libraries(cpu PRIVATE dynarmic capstone merry::mcl)
-5
View File
@@ -106,11 +106,6 @@ struct CPUContext {
}
};
enum class CPUBackend {
Dynarmic,
Unicorn,
};
union DoubleReg {
double d;
float f[2];
+1 -1
View File
@@ -26,7 +26,7 @@
struct MemState;
CPUStatePtr init_cpu(CPUBackend backend, bool cpu_opt, SceUID thread_id, std::size_t processor_id, MemState &mem, CPUProtocolBase *protocol);
CPUStatePtr init_cpu(bool cpu_opt, SceUID thread_id, std::size_t processor_id, MemState &mem, CPUProtocolBase *protocol);
int run(CPUState &state);
int step(CPUState &state);
void stop(CPUState &state);
-105
View File
@@ -1,105 +0,0 @@
// Vita3K emulator project
// Copyright (C) 2025 Vita3K team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#pragma once
#include <cpu/impl/interface.h>
#include <cpu/state.h>
#include <unicorn/unicorn.h>
#include <functional>
#include <memory>
#include <stack>
typedef std::unique_ptr<uc_struct, std::function<void(uc_struct *)>> UnicornPtr;
struct CPUState;
class UnicornCPU : public CPUInterface {
UnicornPtr uc;
CPUState *parent;
Address ep;
uc_hook memory_read_hook_handle = 0;
uc_hook memory_write_hook_handle = 0;
uc_hook code_hook_handle = 0;
bool is_inside_intr_hook = false;
std::stack<Address> lr_stack;
bool returning = false;
bool did_break = false;
bool did_inject = false;
void log_error_details(uc_err code);
static void intr_hook(uc_engine *uc, uint32_t intno, void *user_data);
static void code_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data);
static void read_hook(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data);
static void write_hook(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data);
void log_memory_access(uc_engine *uc, const char *type, Address address, int size, int64_t value, MemState &mem, CPUState &cpu, Address offset);
public:
UnicornCPU(CPUState *state);
int execute_instructions_no_check(int num);
int run() override;
int step() override;
void stop() override;
uint32_t get_reg(uint8_t idx) override;
void set_reg(uint8_t idx, uint32_t val) override;
uint32_t get_sp() override;
void set_sp(uint32_t val) override;
uint32_t get_pc() override;
void set_pc(uint32_t val) override;
uint32_t get_lr() override;
void set_lr(uint32_t val) override;
uint32_t get_cpsr() override;
void set_cpsr(uint32_t val) override;
uint32_t get_tpidruro() override;
void set_tpidruro(uint32_t val) override;
uint32_t get_fpscr() override;
void set_fpscr(uint32_t val) override;
float get_float_reg(uint8_t idx) override;
void set_float_reg(uint8_t idx, float val) override;
bool is_thumb_mode() override;
CPUContext save_context() override;
void load_context(const CPUContext &ctx) override;
void invalidate_jit_cache(Address start, size_t length) override;
bool hit_breakpoint() override;
void trigger_breakpoint() override;
void set_log_code(bool log) override;
void set_log_mem(bool log) override;
bool get_log_code() override;
bool get_log_mem() override;
};
+3 -15
View File
@@ -19,7 +19,6 @@
#include <cpu/functions.h>
#include <cpu/impl/dynarmic_cpu.h>
#include <cpu/impl/interface.h>
#include <cpu/impl/unicorn_cpu.h>
#include <cpu/state.h>
#include <mem/ptr.h>
#include <util/types.h>
@@ -39,7 +38,7 @@ SceUID get_thread_id(CPUState &state) {
return state.thread_id;
}
CPUStatePtr init_cpu(CPUBackend backend, bool cpu_opt, SceUID thread_id, std::size_t processor_id, MemState &mem, CPUProtocolBase *protocol) {
CPUStatePtr init_cpu(bool cpu_opt, SceUID thread_id, std::size_t processor_id, MemState &mem, CPUProtocolBase *protocol) {
CPUStatePtr state(new CPUState(), delete_cpu_state);
state->mem = &mem;
state->protocol = protocol;
@@ -57,19 +56,8 @@ CPUStatePtr init_cpu(CPUBackend backend, bool cpu_opt, SceUID thread_id, std::si
return CPUStatePtr();
}
switch (backend) {
case CPUBackend::Dynarmic: {
Dynarmic::ExclusiveMonitor *monitor = static_cast<Dynarmic::ExclusiveMonitor *>(protocol->get_exclusive_monitor());
state->cpu = std::make_unique<DynarmicCPU>(state.get(), processor_id, monitor, cpu_opt);
break;
}
case CPUBackend::Unicorn: {
state->cpu = std::make_unique<UnicornCPU>(state.get());
break;
}
default:
return nullptr;
}
Dynarmic::ExclusiveMonitor *monitor = static_cast<Dynarmic::ExclusiveMonitor *>(protocol->get_exclusive_monitor());
state->cpu = std::make_unique<DynarmicCPU>(state.get(), processor_id, monitor, cpu_opt);
return state;
}
-446
View File
@@ -1,446 +0,0 @@
// Vita3K emulator project
// Copyright (C) 2025 Vita3K team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#include <cpu/functions.h>
#include <cpu/impl/unicorn_cpu.h>
#include <mem/functions.h>
#include <mem/ptr.h>
#include <mem/util.h>
#include <util/log.h>
#include <cassert>
#include <cpu/disasm/functions.h>
#include <util/string_utils.h>
constexpr bool TRACE_RETURN_VALUES = true;
constexpr bool LOG_REGISTERS = false;
static inline void func_trace(CPUState &state) {
if (TRACE_RETURN_VALUES)
if (is_returning(state.disasm))
LOG_TRACE("Returning, r0: {}", log_hex(read_reg(state, 0)));
}
void UnicornCPU::code_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
UnicornCPU &state = *static_cast<UnicornCPU *>(user_data);
std::string disassembly = disassemble(*state.parent, address);
if (LOG_REGISTERS) {
for (int i = 0; i < 12; i++) {
auto reg_name = fmt::format("r{}", i);
auto reg_name_with_value = fmt::format("{}({})", reg_name, log_hex(state.get_reg(i)));
string_utils::replace(disassembly, reg_name, reg_name_with_value);
}
string_utils::replace(disassembly, "lr", fmt::format("lr({})", log_hex(state.get_lr())));
string_utils::replace(disassembly, "sp", fmt::format("sp({})", log_hex(state.get_sp())));
}
LOG_TRACE("{} ({}): {} {}", log_hex((uint64_t)uc), state.parent->thread_id, log_hex(address), disassembly);
func_trace(*state.parent);
}
void UnicornCPU::read_hook(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) {
assert(value == 0);
UnicornCPU &state = *static_cast<UnicornCPU *>(user_data);
MemState &mem = *state.parent->mem;
auto start = state.parent->protocol->get_watch_memory_addr(address);
if (start) {
memcpy(&value, Ptr<const void>(static_cast<Address>(address)).get(mem), size);
state.log_memory_access(uc, "Read", start, size, value, mem, *state.parent, address - start);
}
}
void UnicornCPU::write_hook(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) {
UnicornCPU &state = *static_cast<UnicornCPU *>(user_data);
auto start = state.parent->protocol->get_watch_memory_addr(address);
if (start) {
MemState &mem = *state.parent->mem;
state.log_memory_access(uc, "Write", start, size, value, mem, *state.parent, address - start);
}
}
void UnicornCPU::log_memory_access(uc_engine *uc, const char *type, Address address, int size, int64_t value, MemState &mem, CPUState &cpu, Address offset) {
const char *const name = mem_name(address, mem);
auto pc = get_pc();
LOG_TRACE("{} ({}): {} {} bytes, address {} + {} ({}, {}), value {} at {}", log_hex((uint64_t)uc), cpu.thread_id, type, size, log_hex(address), log_hex(offset), log_hex(address + offset), name, log_hex(value), log_hex(pc));
}
constexpr uint32_t INT_SVC = 2;
constexpr uint32_t INT_BKPT = 7;
void UnicornCPU::intr_hook(uc_engine *uc, uint32_t intno, void *user_data) {
assert(intno == INT_SVC || intno == INT_BKPT);
UnicornCPU &state = *static_cast<UnicornCPU *>(user_data);
uint32_t pc = state.get_pc();
state.is_inside_intr_hook = true;
if (intno == INT_SVC) {
assert(!state.is_thumb_mode());
const Address svc_address = pc - 4;
uint32_t svc_instruction = 0;
const auto err = uc_mem_read(uc, svc_address, &svc_instruction, sizeof(svc_instruction));
assert(err == UC_ERR_OK);
const uint32_t svc = state.is_thumb_mode() ? (svc_instruction & 0xff0000) >> 16 : svc_instruction & 0xffffff;
state.parent->svc_called = true;
state.parent->svc = svc;
state.stop();
} else if (intno == INT_BKPT) {
state.stop();
state.did_break = true;
}
state.is_inside_intr_hook = false;
}
static void enable_vfp_fpu(uc_engine *uc) {
uint64_t c1_c0_2 = 0;
uc_err err = uc_reg_read(uc, UC_ARM_REG_C1_C0_2, &c1_c0_2);
assert(err == UC_ERR_OK);
c1_c0_2 |= (0xf << 20);
err = uc_reg_write(uc, UC_ARM_REG_C1_C0_2, &c1_c0_2);
assert(err == UC_ERR_OK);
const uint64_t fpexc = 0xf0000000;
err = uc_reg_write(uc, UC_ARM_REG_FPEXC, &fpexc);
assert(err == UC_ERR_OK);
}
void UnicornCPU::log_error_details(uc_err code) {
// I don't especially want the time logged for every line, but I also want it to print to the log file...
LOG_ERROR("Unicorn error {}. {}\n{}", log_hex(code), uc_strerror(code), this->save_context().description());
auto pc = this->get_pc();
if (pc < parent->mem->page_size)
LOG_CRITICAL("PC is 0x{:x}", pc);
else
LOG_WARN("Executing: {}", disassemble(*parent, pc, nullptr));
}
UnicornCPU::UnicornCPU(CPUState *state)
: parent(state) {
uc_engine *temp_uc = nullptr;
uc_err err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &temp_uc);
assert(err == UC_ERR_OK);
uc = UnicornPtr(temp_uc, uc_close);
temp_uc = nullptr;
uc_hook hh = 0;
err = uc_hook_add(uc.get(), &hh, UC_HOOK_INTR, reinterpret_cast<void *>(&intr_hook), this, 1, 0);
assert(err == UC_ERR_OK);
// Don't map the null page into unicorn so that unicorn returns access error instead of
// crashing the whole emulator on invalid access
err = uc_mem_map_ptr(uc.get(), state->mem->page_size, GiB(4) - state->mem->page_size, UC_PROT_ALL, &state->mem->memory[state->mem->page_size]);
assert(err == UC_ERR_OK);
enable_vfp_fpu(uc.get());
}
int UnicornCPU::execute_instructions_no_check(int num) {
std::uint32_t pc = get_pc();
bool thumb_mode = is_thumb_mode();
if (thumb_mode) {
pc |= 1;
}
uc_err err = uc_emu_start(uc.get(), pc, 1ULL << 63, 0, num);
if (err != UC_ERR_OK) {
log_error_details(err);
return -1;
}
return 0;
}
int UnicornCPU::run() {
uint32_t pc = get_pc();
bool thumb_mode = is_thumb_mode();
did_break = false;
parent->svc_called = false;
pc = get_pc();
if (thumb_mode) {
pc |= 1;
}
uc_err err = uc_emu_start(uc.get(), pc, 0, 0, 0);
if (err != UC_ERR_OK) {
log_error_details(err);
return -1;
}
pc = get_pc();
thumb_mode = is_thumb_mode();
if (thumb_mode) {
pc |= 1;
}
return parent->halt_instruction_pc <= pc && pc <= parent->halt_instruction_pc + 4;
}
int UnicornCPU::step() {
uint32_t pc = get_pc();
bool thumb_mode = is_thumb_mode();
did_break = false;
parent->svc_called = false;
pc = get_pc();
if (thumb_mode) {
pc |= 1;
}
uc_err err = uc_emu_start(uc.get(), pc, 0, 0, 1);
if (err != UC_ERR_OK) {
log_error_details(err);
return -1;
}
pc = get_pc();
thumb_mode = is_thumb_mode();
if (thumb_mode) {
pc |= 1;
}
return parent->halt_instruction_pc <= pc && pc <= parent->halt_instruction_pc + 4;
}
void UnicornCPU::stop() {
const uc_err err = uc_emu_stop(uc.get());
assert(err == UC_ERR_OK);
}
uint32_t UnicornCPU::get_reg(uint8_t idx) {
uint32_t value = 0;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_R0 + static_cast<int>(idx), &value);
assert(err == UC_ERR_OK);
return value;
}
void UnicornCPU::set_reg(uint8_t idx, uint32_t val) {
const uc_err err = uc_reg_write(uc.get(), UC_ARM_REG_R0 + static_cast<int>(idx), &val);
assert(err == UC_ERR_OK);
}
uint32_t UnicornCPU::get_sp() {
uint32_t value = 0;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_SP, &value);
assert(err == UC_ERR_OK);
return value;
}
void UnicornCPU::set_sp(uint32_t val) {
const uc_err err = uc_reg_write(uc.get(), UC_ARM_REG_SP, &val);
assert(err == UC_ERR_OK);
}
uint32_t UnicornCPU::get_pc() {
uint32_t value = 0;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_PC, &value);
assert(err == UC_ERR_OK);
return value;
}
void UnicornCPU::set_pc(uint32_t val) {
const uc_err err = uc_reg_write(uc.get(), UC_ARM_REG_PC, &val);
assert(err == UC_ERR_OK);
}
uint32_t UnicornCPU::get_lr() {
uint32_t value = 0;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_LR, &value);
assert(err == UC_ERR_OK);
return value;
}
void UnicornCPU::set_lr(uint32_t val) {
const uc_err err = uc_reg_write(uc.get(), UC_ARM_REG_LR, &val);
assert(err == UC_ERR_OK);
}
uint32_t UnicornCPU::get_cpsr() {
uint32_t value = 0;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_CPSR, &value);
assert(err == UC_ERR_OK);
return value;
}
void UnicornCPU::set_cpsr(uint32_t val) {
const uc_err err = uc_reg_write(uc.get(), UC_ARM_REG_CPSR, &val);
assert(err == UC_ERR_OK);
}
uint32_t UnicornCPU::get_tpidruro() {
uint32_t value = 0;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_C13_C0_3, &value);
assert(err == UC_ERR_OK);
return value;
}
void UnicornCPU::set_tpidruro(uint32_t val) {
const uc_err err = uc_reg_write(uc.get(), UC_ARM_REG_C13_C0_3, &val);
assert(err == UC_ERR_OK);
}
uint32_t UnicornCPU::get_fpscr() {
uint32_t value = 0;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_FPSCR, &value);
assert(err == UC_ERR_OK);
return value;
}
void UnicornCPU::set_fpscr(uint32_t val) {
const uc_err err = uc_reg_write(uc.get(), UC_ARM_REG_FPSCR, &val);
assert(err == UC_ERR_OK);
}
float UnicornCPU::get_float_reg(uint8_t idx) {
DoubleReg value;
const int single_index = idx / 2;
const uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_D0 + single_index, &value);
assert(err == UC_ERR_OK);
return value.f[idx % 2];
}
void UnicornCPU::set_float_reg(uint8_t idx, float val) {
DoubleReg value;
const int single_index = idx / 2;
uc_err err = uc_reg_read(uc.get(), UC_ARM_REG_D0 + single_index, &value);
assert(err == UC_ERR_OK);
value.f[idx % 2] = val;
err = uc_reg_write(uc.get(), UC_ARM_REG_D0 + single_index, &value);
assert(err == UC_ERR_OK);
}
bool UnicornCPU::is_thumb_mode() {
size_t mode = 0;
const uc_err err = uc_query(uc.get(), UC_QUERY_MODE, &mode);
assert(err == UC_ERR_OK);
return mode & UC_MODE_THUMB;
}
CPUContext UnicornCPU::save_context() {
CPUContext ctx;
for (size_t i = 0; i < 13; i++) {
ctx.cpu_registers[i] = get_reg(i);
}
ctx.cpu_registers[13] = get_sp();
ctx.cpu_registers[14] = get_lr();
ctx.set_pc(is_thumb_mode() ? get_pc() | 1 : get_pc());
for (size_t i = 0; i < ctx.fpu_registers.size(); i++) {
ctx.fpu_registers[i] = get_float_reg(i);
}
// Unicorn doesn't like tweaking cpsr
// ctx.cpsr = get_cpsr();
// ctx.fpscr = get_fpscr();
return ctx;
}
void UnicornCPU::load_context(const CPUContext &ctx) {
for (size_t i = 0; i < ctx.fpu_registers.size(); i++) {
set_float_reg(i, ctx.fpu_registers[i]);
}
// Unicorn doesn't like tweaking cpsr
// set_cpsr(ctx.cpsr);
// set_fpscr(ctx.fpscr);
for (size_t i = 0; i < 16; i++) {
set_reg(i, ctx.cpu_registers[i]);
}
set_sp(ctx.get_sp());
set_lr(ctx.get_lr());
set_pc(ctx.thumb() ? ctx.get_pc() | 1 : ctx.get_pc());
}
void UnicornCPU::invalidate_jit_cache(Address start, size_t length) {
uc_ctl_remove_cache(uc.get(), start, start + length);
}
bool UnicornCPU::hit_breakpoint() {
return did_break;
}
void UnicornCPU::trigger_breakpoint() {
stop();
did_break = true;
}
void UnicornCPU::set_log_code(bool log) {
if (get_log_code() == log) {
return;
}
if (log) {
const uc_err err = uc_hook_add(uc.get(), &code_hook_handle, UC_HOOK_CODE, reinterpret_cast<void *>(&code_hook), this, 1, 0);
assert(err == UC_ERR_OK);
} else {
auto err = uc_hook_del(uc.get(), code_hook_handle);
assert(err == UC_ERR_OK);
code_hook_handle = 0;
}
}
void UnicornCPU::set_log_mem(bool log) {
if (get_log_mem() == log) {
return;
}
if (log) {
uc_err err = uc_hook_add(uc.get(), &memory_read_hook_handle, UC_HOOK_MEM_READ, reinterpret_cast<void *>(&read_hook), this, 1, 0);
assert(err == UC_ERR_OK);
err = uc_hook_add(uc.get(), &memory_write_hook_handle, UC_HOOK_MEM_WRITE, reinterpret_cast<void *>(&write_hook), this, 1, 0);
assert(err == UC_ERR_OK);
} else {
auto err = uc_hook_del(uc.get(), memory_read_hook_handle);
assert(err == UC_ERR_OK);
memory_read_hook_handle = 0;
err = uc_hook_del(uc.get(), memory_write_hook_handle);
assert(err == UC_ERR_OK);
memory_write_hook_handle = 0;
}
}
bool UnicornCPU::get_log_code() {
return code_hook_handle != 0;
}
bool UnicornCPU::get_log_mem() {
return memory_read_hook_handle != 0 && memory_write_hook_handle != 0;
}
-1
View File
@@ -54,7 +54,6 @@ std::vector<std::string>::iterator get_live_area_current_open_apps_list_index(Gu
std::map<DateTime, std::string> get_date_time(GuiState &gui, EmuEnvState &emuenv, const tm &date_time);
std::string get_unit_size(const size_t size);
void get_app_param(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
std::string get_cpu_backend(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
void get_firmware_file(EmuEnvState &emuenv);
void get_modules_list(GuiState &gui, EmuEnvState &emuenv);
void get_notice_list(EmuEnvState &emuenv);
+4 -4
View File
@@ -343,8 +343,8 @@ void draw_app_context_menu(GuiState &gui, EmuEnvState &emuenv, const std::string
if (has_state_report) {
const auto copy_vita3k_summary = [&]() {
const auto vita3k_summary = fmt::format(
"# Vita3K summary\n- Version: {}\n- Build number: {}\n- Commit hash: https://github.com/vita3k/vita3k/commit/{}\n- CPU backend: {}\n- GPU backend: {}",
app_version, app_number, app_hash, get_cpu_backend(gui, emuenv, app_path), emuenv.cfg.backend_renderer);
"# Vita3K summary\n- Version: {}\n- Build number: {}\n- Commit hash: https://github.com/vita3k/vita3k/commit/{}\n- GPU backend: {}",
app_version, app_number, app_hash, emuenv.cfg.backend_renderer);
ImGui::LogToClipboard();
ImGui::LogText("%s", vita3k_summary.c_str());
ImGui::LogFinish();
@@ -385,8 +385,8 @@ void draw_app_context_menu(GuiState &gui, EmuEnvState &emuenv, const std::string
// Create Vita3K summary
const auto vita3k_summary = fmt::format(
"%23 Vita3K summary%0A- Version: {}%0A- Build number: {}%0A- Commit hash: https://github.com/vita3k/vita3k/commit/{}%0A- CPU backend: {}%0A- GPU backend: {}",
app_version, app_number, app_hash, get_cpu_backend(gui, emuenv, app_path), emuenv.cfg.backend_renderer);
"%23 Vita3K summary%0A- Version: {}%0A- Build number: {}%0A- Commit hash: https://github.com/vita3k/vita3k/commit/{}%0A- GPU backend: {}",
app_version, app_number, app_hash, emuenv.cfg.backend_renderer);
#ifdef _WIN32
const auto user = std::getenv("USERNAME");
+2 -31
View File
@@ -123,8 +123,6 @@ static void change_emulator_path(GuiState &gui, EmuEnvState &emuenv) {
}
}
static CPUBackend config_cpu_backend;
/**
* @brief Set up `config` with the values contained in the custom config file of a certain PlayStation Vita application
*
@@ -160,7 +158,6 @@ static bool get_custom_config(GuiState &gui, EmuEnvState &emuenv, const std::str
// Load CPU Config
if (!config_child.child("cpu").empty()) {
const auto cpu_child = config_child.child("cpu");
config.cpu_backend = cpu_child.attribute("cpu-backend").as_string();
config.cpu_opt = cpu_child.attribute("cpu-opt").as_bool();
}
@@ -216,10 +213,6 @@ static bool get_custom_config(GuiState &gui, EmuEnvState &emuenv, const std::str
return false;
}
static CPUBackend set_cpu_backend(std::string &cpu_backend) {
return cpu_backend == "Dynarmic" ? CPUBackend::Dynarmic : CPUBackend::Unicorn;
}
static int current_aniso_filter_log, max_aniso_filter_log, audio_backend_idx, current_user_lang;
static std::vector<std::string> list_user_lang;
@@ -234,7 +227,6 @@ void init_config(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path
// If no app-specific config file is being used for the initialized application,
// set up `config` with the values set in the global emulator configuration
if (!get_custom_config(gui, emuenv, app_path)) {
config.cpu_backend = emuenv.cfg.cpu_backend;
config.cpu_opt = emuenv.cfg.cpu_opt;
config.modules_mode = emuenv.cfg.modules_mode;
config.lle_modules = emuenv.cfg.lle_modules;
@@ -276,7 +268,6 @@ void init_config(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path
get_modules_list(gui, emuenv);
config.stretch_the_display_area = emuenv.cfg.stretch_the_display_area;
config.fullscreen_hd_res_pixel_perfect = emuenv.cfg.fullscreen_hd_res_pixel_perfect;
config_cpu_backend = set_cpu_backend(config.cpu_backend);
current_aniso_filter_log = static_cast<int>(log2f(static_cast<float>(config.anisotropic_filtering)));
max_aniso_filter_log = static_cast<int>(log2f(static_cast<float>(emuenv.renderer->get_max_anisotropic_filtering())));
audio_backend_idx = (emuenv.cfg.audio_backend == "SDL") ? 0 : 1;
@@ -318,7 +309,6 @@ static void save_config(GuiState &gui, EmuEnvState &emuenv) {
// CPU
auto cpu_child = config_child.append_child("cpu");
cpu_child.append_attribute("cpu-backend") = config.cpu_backend.c_str();
cpu_child.append_attribute("cpu-opt") = config.cpu_opt;
// GPU
@@ -357,7 +347,6 @@ static void save_config(GuiState &gui, EmuEnvState &emuenv) {
if (!save_xml)
LOG_ERROR("Failed to save custom config xml for app path: {}, in path: {}", emuenv.app_path, CONFIG_PATH);
} else {
emuenv.cfg.cpu_backend = config.cpu_backend;
emuenv.cfg.cpu_opt = config.cpu_opt;
emuenv.cfg.modules_mode = config.modules_mode;
emuenv.cfg.lle_modules = config.lle_modules;
@@ -398,13 +387,6 @@ static void save_config(GuiState &gui, EmuEnvState &emuenv) {
config::serialize_config(emuenv.cfg, emuenv.cfg.config_path);
}
std::string get_cpu_backend(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) {
if (!get_custom_config(gui, emuenv, app_path))
return emuenv.cfg.cpu_backend;
return config.cpu_backend;
}
static void set_vsync_state(const bool &state) {
if (state) {
// Try adaptive vsync first, falling back to regular vsync.
@@ -433,7 +415,6 @@ void set_config(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path)
emuenv.cfg.current_config = config;
else {
// Else inherit the values from the global emulator config
emuenv.cfg.current_config.cpu_backend = emuenv.cfg.cpu_backend;
emuenv.cfg.current_config.cpu_opt = emuenv.cfg.cpu_opt;
emuenv.cfg.current_config.modules_mode = emuenv.cfg.modules_mode;
emuenv.cfg.current_config.lle_modules = emuenv.cfg.lle_modules;
@@ -482,7 +463,6 @@ void set_config(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path)
// No change it if app already running
if (emuenv.io.title_id.empty()) {
emuenv.kernel.cpu_backend = set_cpu_backend(emuenv.cfg.current_config.cpu_backend);
emuenv.kernel.cpu_opt = emuenv.cfg.current_config.cpu_opt;
emuenv.audio.set_backend(emuenv.cfg.audio_backend);
}
@@ -576,17 +556,8 @@ void draw_settings_dialog(GuiState &gui, EmuEnvState &emuenv) {
if (ImGui::BeginTabItem("CPU")) {
ImGui::PopStyleColor();
ImGui::Spacing();
static const char *LIST_CPU_BACKEND[] = { "Dynarmic", "Unicorn" };
const char *LIST_CPU_BACKEND_DISPLAY[] = { "Dynarmic", lang.cpu["unicorn"].c_str() };
ImGui::TextColored(GUI_COLOR_TEXT_TITLE, "%s", lang.cpu["cpu_backend"].c_str());
if (ImGui::Combo("##cpu_backend", reinterpret_cast<int *>(&config_cpu_backend), LIST_CPU_BACKEND_DISPLAY, IM_ARRAYSIZE(LIST_CPU_BACKEND_DISPLAY)))
config.cpu_backend = LIST_CPU_BACKEND[static_cast<int>(config_cpu_backend)];
SetTooltipEx(lang.cpu["select_cpu_backend"].c_str());
if (config_cpu_backend == CPUBackend::Dynarmic) {
ImGui::Spacing();
ImGui::Checkbox(lang.cpu["cpu_opt"].c_str(), &config.cpu_opt);
SetTooltipEx(lang.cpu["cpu_opt_description"].c_str());
}
ImGui::Checkbox(lang.cpu["cpu_opt"].c_str(), &config.cpu_opt);
SetTooltipEx(lang.cpu["cpu_opt_description"].c_str());
ImGui::EndTabItem();
} else
ImGui::PopStyleColor();
+2 -3
View File
@@ -391,7 +391,7 @@ static ExitCode load_app_impl(SceUID &main_module_id, EmuEnvState &emuenv) {
const auto call_import = [&emuenv](CPUState &cpu, uint32_t nid, SceUID thread_id) {
::call_import(emuenv, cpu, nid, thread_id);
};
if (!emuenv.kernel.init(emuenv.mem, call_import, emuenv.kernel.cpu_backend, emuenv.kernel.cpu_opt)) {
if (!emuenv.kernel.init(emuenv.mem, call_import, emuenv.kernel.cpu_opt)) {
LOG_WARN("Failed to init kernel!");
return KernelInitFailed;
}
@@ -405,8 +405,7 @@ static ExitCode load_app_impl(SceUID &main_module_id, EmuEnvState &emuenv) {
logging::set_level(static_cast<spdlog::level::level_enum>(emuenv.cfg.log_level));
}
LOG_INFO("cpu-backend: {}", emuenv.cfg.current_config.cpu_backend);
LOG_INFO_IF(emuenv.kernel.cpu_backend == CPUBackend::Dynarmic, "CPU Optimisation state: {}", emuenv.cfg.current_config.cpu_opt);
LOG_INFO("CPU Optimisation state: {}", emuenv.cfg.current_config.cpu_opt);
LOG_INFO("ngs state: {}", emuenv.cfg.current_config.ngs_enable);
LOG_INFO("Resolution multiplier: {}", emuenv.cfg.resolution_multiplier);
if (emuenv.ctrl.controllers_num) {
+1 -2
View File
@@ -131,7 +131,6 @@ struct KernelState {
ModuleUidByNid module_uid_by_nid;
bool cpu_opt;
CPUBackend cpu_backend;
CorenumAllocator corenum_allocator;
CPUProtocolPtr cpu_protocol;
ExclusiveMonitorPtr exclusive_monitor;
@@ -148,7 +147,7 @@ struct KernelState {
return next_uid++;
}
bool init(MemState &mem, const CallImportFunc &call_import, CPUBackend cpu_backend, bool cpu_opt);
bool init(MemState &mem, const CallImportFunc &call_import, bool cpu_opt);
void load_process_param(MemState &mem, Ptr<uint32_t> ptr);
ThreadStatePtr create_thread(MemState &mem, const char *name, Ptr<const void> entry_point = Ptr<const void>(0));
ThreadStatePtr create_thread(MemState &mem, const char *name, Ptr<const void> entry_point, int init_priority, SceInt32 affinity_mask, int stack_size, const SceKernelThreadOptParam *option);
+1 -2
View File
@@ -82,7 +82,7 @@ KernelState::KernelState()
: debugger(*this) {
}
bool KernelState::init(MemState &mem, const CallImportFunc &call_import, CPUBackend cpu_backend, bool cpu_opt) {
bool KernelState::init(MemState &mem, const CallImportFunc &call_import, bool cpu_opt) {
constexpr std::size_t MAX_CORE_COUNT = 150;
corenum_allocator.set_max_core_count(MAX_CORE_COUNT);
@@ -90,7 +90,6 @@ bool KernelState::init(MemState &mem, const CallImportFunc &call_import, CPUBack
start_tick = rtc_get_ticks(rtc_base_ticks());
base_tick = { rtc_base_ticks() };
cpu_protocol = std::make_unique<CPUProtocol>(*this, mem, call_import);
this->cpu_backend = cpu_backend;
this->cpu_opt = cpu_opt;
return true;
+1 -1
View File
@@ -71,7 +71,7 @@ int ThreadState::init(const char *name, Ptr<const void> entry_point, int init_pr
start_tick = rtc_get_ticks(kernel.base_tick.tick);
last_vblank_waited = 0;
cpu = init_cpu(kernel.cpu_backend, kernel.cpu_opt, id, static_cast<std::size_t>(core_num), mem, kernel.cpu_protocol.get());
cpu = init_cpu(kernel.cpu_opt, id, static_cast<std::size_t>(core_num), mem, kernel.cpu_protocol.get());
if (!cpu) {
return SCE_KERNEL_ERROR_ERROR;
}
-3
View File
@@ -531,9 +531,6 @@ struct LangState {
{ "manual_description", "Select Manual mode to load selected modules from the list below." }
};
std::map<std::string, std::string> cpu = {
{ "unicorn", "Unicorn (deprecated)" },
{ "cpu_backend", "CPU Backend" },
{ "select_cpu_backend", "Select your preferred CPU backend." },
{ "cpu_opt", "Enable optimizations" },
{ "cpu_opt_description", "Check the box to enable additional CPU JIT optimizations." }
};