mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2025-10-30 08:02:29 +00:00
Game Registration API (#1)
This commit is contained in:
parent
2430c82cbd
commit
32632ab2ff
9 changed files with 9430 additions and 84 deletions
|
|
@ -7,3 +7,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
add_subdirectory(ultramodern)
|
add_subdirectory(ultramodern)
|
||||||
add_subdirectory(librecomp)
|
add_subdirectory(librecomp)
|
||||||
|
|
||||||
|
set(RT64_STATIC TRUE)
|
||||||
|
add_subdirectory(rt64)
|
||||||
|
|
|
||||||
|
|
@ -30,5 +30,6 @@ add_library(librecomp STATIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/vi.cpp")
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/vi.cpp")
|
||||||
|
|
||||||
target_include_directories(librecomp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
target_include_directories(librecomp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
|
target_include_directories(librecomp PRIVATE "${CMAKE_SOURCE_DIR}/rt64/src/contrib")
|
||||||
|
target_compile_options(librecomp PRIVATE -Wno-deprecated-declarations)
|
||||||
target_link_libraries(librecomp PRIVATE ultramodern)
|
target_link_libraries(librecomp PRIVATE ultramodern)
|
||||||
|
|
|
||||||
|
|
@ -6,23 +6,19 @@
|
||||||
|
|
||||||
#include "recomp.h"
|
#include "recomp.h"
|
||||||
#include <ultramodern/ultramodern.hpp>
|
#include <ultramodern/ultramodern.hpp>
|
||||||
#include "rt64_layer.h"
|
|
||||||
|
|
||||||
namespace recomp {
|
namespace recomp {
|
||||||
// TODO refactor this to allow a particular project to specify games.
|
struct GameEntry {
|
||||||
// A register game function should be added which takes:
|
uint64_t rom_hash;
|
||||||
// * Expected ROM hash
|
std::string internal_name;
|
||||||
// * Internal ROM name (for error messages)
|
std::u8string game_id;
|
||||||
// * Entrypoint function to run for the game
|
std::span<const char> cache_data;
|
||||||
// * Shader cache (optional)
|
bool is_enabled;
|
||||||
// The register game function should return a handle struct (probably containing an ID) so the project can check
|
|
||||||
// which game is running (if any) by querying it.
|
void (*entrypoint)();
|
||||||
enum class Game {
|
|
||||||
OoT,
|
std::u8string stored_filename() const;
|
||||||
MM,
|
};
|
||||||
None,
|
|
||||||
Quit
|
|
||||||
};
|
|
||||||
enum class RomValidationError {
|
enum class RomValidationError {
|
||||||
Good,
|
Good,
|
||||||
FailedToOpen,
|
FailedToOpen,
|
||||||
|
|
@ -32,17 +28,21 @@ namespace recomp {
|
||||||
IncorrectVersion,
|
IncorrectVersion,
|
||||||
OtherError
|
OtherError
|
||||||
};
|
};
|
||||||
|
bool register_game(const recomp::GameEntry& entry);
|
||||||
|
void register_patch(const char* patch, std::size_t size);
|
||||||
void check_all_stored_roms();
|
void check_all_stored_roms();
|
||||||
bool load_stored_rom(Game game);
|
bool load_stored_rom(std::u8string& game_id);
|
||||||
RomValidationError select_rom(const std::filesystem::path& rom_path, Game game);
|
RomValidationError select_rom(const std::filesystem::path& rom_path, std::u8string& game_id);
|
||||||
bool is_rom_valid(Game game);
|
bool is_rom_valid(std::u8string& game_id);
|
||||||
bool is_rom_loaded();
|
bool is_rom_loaded();
|
||||||
void set_rom_contents(std::vector<uint8_t>&& new_rom);
|
void set_rom_contents(std::vector<uint8_t>&& new_rom);
|
||||||
void do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes);
|
void do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes);
|
||||||
void do_rom_pio(uint8_t* rdram, gpr ram_address, uint32_t physical_addr);
|
void do_rom_pio(uint8_t* rdram, gpr ram_address, uint32_t physical_addr);
|
||||||
void start(ultramodern::WindowHandle window_handle, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input_callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks);
|
void start(ultramodern::WindowHandle window_handle, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input_callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks);
|
||||||
void start_game(Game game);
|
void start_game(std::u8string game_id);
|
||||||
void message_box(const char* message);
|
void message_box(const char* message);
|
||||||
|
std::filesystem::path get_app_folder_path();
|
||||||
|
std::u8string current_game_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,12 @@
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#define ARCHITECTURE_AMD64
|
#if defined(__x86_64__) || defined(_M_X64)
|
||||||
#define ARCHITECTURE_SUPPORTS_SSE4_1 1
|
#define ARCHITECTURE_SUPPORTS_SSE4_1 1
|
||||||
|
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
#include <nmmintrin.h>
|
#include <nmmintrin.h>
|
||||||
using v128 = __m128i;
|
using v128 = __m128i;
|
||||||
#elif defined(ARCHITECTURE_ARM64)
|
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
#define ARCHITECTURE_SUPPORTS_SSE4_1 1
|
||||||
#include <sse2neon.h>
|
#include <sse2neon.h>
|
||||||
using v128 = __m128i;
|
using v128 = __m128i;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "recomp.h"
|
#include "recomp.h"
|
||||||
#include "recomp_game.h"
|
#include "recomp_game.h"
|
||||||
#include "recomp_config.h"
|
|
||||||
#include <ultramodern/ultra64.h>
|
#include <ultramodern/ultra64.h>
|
||||||
#include <ultramodern/ultramodern.hpp>
|
#include <ultramodern/ultramodern.hpp>
|
||||||
|
|
||||||
|
|
@ -95,7 +94,7 @@ struct {
|
||||||
} save_context;
|
} save_context;
|
||||||
|
|
||||||
const std::u8string save_folder = u8"saves";
|
const std::u8string save_folder = u8"saves";
|
||||||
const std::u8string save_filename = std::u8string{recomp::mm_game_id} + u8".bin";
|
const std::u8string save_filename = std::u8string{recomp::current_game_id()} + u8".bin";
|
||||||
|
|
||||||
std::filesystem::path get_save_file_path() {
|
std::filesystem::path get_save_file_path() {
|
||||||
return recomp::get_app_folder_path() / save_folder / save_filename;
|
return recomp::get_app_folder_path() / save_folder / save_filename;
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,9 @@
|
||||||
#include "recomp.h"
|
#include "recomp.h"
|
||||||
#include "recomp_overlays.h"
|
#include "recomp_overlays.h"
|
||||||
#include "recomp_game.h"
|
#include "recomp_game.h"
|
||||||
#include "recomp_config.h"
|
|
||||||
#include "xxHash/xxh3.h"
|
#include "xxHash/xxh3.h"
|
||||||
#include <ultramodern/ultramodern.hpp>
|
#include <ultramodern/ultramodern.hpp>
|
||||||
#include "../../RecompiledPatches/patches_bin.h"
|
//#include "../../RecompiledPatches/patches_bin.h"
|
||||||
#include "mm_shader_cache.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
inline uint32_t byteswap(uint32_t val) {
|
inline uint32_t byteswap(uint32_t val) {
|
||||||
|
|
@ -29,19 +27,38 @@ constexpr uint32_t byteswap(uint32_t val) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct RomEntry {
|
enum GameStatus {
|
||||||
uint64_t xxhash3_value;
|
None,
|
||||||
std::u8string stored_filename;
|
Running,
|
||||||
std::string internal_rom_name;
|
Quit
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::unordered_map<recomp::Game, RomEntry> game_roms {
|
// Mutexes
|
||||||
{ recomp::Game::MM, { 0xEF18B4A9E2386169ULL, std::u8string{recomp::mm_game_id} + u8".z64", "ZELDA MAJORA'S MASK" }},
|
std::mutex game_roms_mutex;
|
||||||
};
|
std::mutex patch_data_mutex;
|
||||||
|
std::mutex current_game_mutex;
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
std::vector<char> patch_data;
|
||||||
|
std::unordered_map<std::u8string, recomp::GameEntry> game_roms {};
|
||||||
|
|
||||||
|
std::u8string recomp::GameEntry::stored_filename() const {
|
||||||
|
return game_id + u8".z64";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool recomp::register_game(const recomp::GameEntry& entry) {
|
||||||
|
std::lock_guard<std::mutex> lock(game_roms_mutex);
|
||||||
|
game_roms.insert({ entry.game_id, entry });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recomp::register_patch(const char* patch, std::size_t size) {
|
||||||
|
std::lock_guard<std::mutex> lock(patch_data_mutex);
|
||||||
|
std::memcpy(patch_data.data(), patch, size);
|
||||||
|
}
|
||||||
|
|
||||||
bool check_hash(const std::vector<uint8_t>& rom_data, uint64_t expected_hash) {
|
bool check_hash(const std::vector<uint8_t>& rom_data, uint64_t expected_hash) {
|
||||||
uint64_t calculated_hash = XXH3_64bits(rom_data.data(), rom_data.size());
|
uint64_t calculated_hash = XXH3_64bits(rom_data.data(), rom_data.size());
|
||||||
|
|
||||||
return calculated_hash == expected_hash;
|
return calculated_hash == expected_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,23 +90,49 @@ bool write_file(const std::filesystem::path& path, const std::vector<uint8_t>& d
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_stored_rom(const RomEntry& game_entry) {
|
std::filesystem::path recomp::get_app_folder_path() {
|
||||||
|
std::filesystem::path recomp_dir{};
|
||||||
|
|
||||||
std::vector stored_rom_data = read_file(recomp::get_app_folder_path() / game_entry.stored_filename);
|
#if defined(_WIN32)
|
||||||
|
// Deduce local app data path.
|
||||||
|
PWSTR known_path = NULL;
|
||||||
|
HRESULT result = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &known_path);
|
||||||
|
if (result == S_OK) {
|
||||||
|
recomp_dir = std::filesystem::path{known_path} / recomp::program_id;
|
||||||
|
}
|
||||||
|
|
||||||
if (!check_hash(stored_rom_data, game_entry.xxhash3_value)) {
|
CoTaskMemFree(known_path);
|
||||||
|
#elif defined(__linux__)
|
||||||
|
const char *homedir;
|
||||||
|
|
||||||
|
if ((homedir = getenv("HOME")) == nullptr) {
|
||||||
|
homedir = getpwuid(getuid())->pw_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (homedir != nullptr) {
|
||||||
|
recomp_dir = std::filesystem::path{homedir} / (std::u8string{u8".config/"} + std::u8string{recomp::program_id});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return recomp_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_stored_rom(const recomp::GameEntry& game_entry) {
|
||||||
|
std::vector stored_rom_data = read_file(recomp::get_app_folder_path() / game_entry.stored_filename());
|
||||||
|
|
||||||
|
if (!check_hash(stored_rom_data, game_entry.rom_hash)) {
|
||||||
// Incorrect hash, remove the stored ROM file if it exists.
|
// Incorrect hash, remove the stored ROM file if it exists.
|
||||||
std::filesystem::remove(recomp::get_app_folder_path() / game_entry.stored_filename);
|
std::filesystem::remove(recomp::get_app_folder_path() / game_entry.stored_filename());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unordered_set<recomp::Game> valid_game_roms;
|
static std::unordered_set<std::u8string> valid_game_roms;
|
||||||
|
|
||||||
bool recomp::is_rom_valid(recomp::Game game) {
|
bool recomp::is_rom_valid(std::u8string& game_id) {
|
||||||
return valid_game_roms.contains(game);
|
return valid_game_roms.contains(game_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void recomp::check_all_stored_roms() {
|
void recomp::check_all_stored_roms() {
|
||||||
|
|
@ -100,18 +143,18 @@ void recomp::check_all_stored_roms() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool recomp::load_stored_rom(recomp::Game game) {
|
bool recomp::load_stored_rom(std::u8string& game_id) {
|
||||||
auto find_it = game_roms.find(game);
|
auto find_it = game_roms.find(game_id);
|
||||||
|
|
||||||
if (find_it == game_roms.end()) {
|
if (find_it == game_roms.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> stored_rom_data = read_file(recomp::get_app_folder_path() / find_it->second.stored_filename);
|
std::vector<uint8_t> stored_rom_data = read_file(recomp::get_app_folder_path() / find_it->second.stored_filename());
|
||||||
|
|
||||||
if (!check_hash(stored_rom_data, find_it->second.xxhash3_value)) {
|
if (!check_hash(stored_rom_data, find_it->second.rom_hash)) {
|
||||||
// The ROM no longer has the right hash, delete it.
|
// The ROM no longer has the right hash, delete it.
|
||||||
std::filesystem::remove(recomp::get_app_folder_path() / find_it->second.stored_filename);
|
std::filesystem::remove(recomp::get_app_folder_path() / find_it->second.stored_filename());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,8 +176,6 @@ ByteswapType check_rom_start(const std::vector<uint8_t>& rom_data) {
|
||||||
return ByteswapType::Invalid;
|
return ByteswapType::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matched_all = true;
|
|
||||||
|
|
||||||
auto check_match = [&](uint8_t index0, uint8_t index1, uint8_t index2, uint8_t index3) {
|
auto check_match = [&](uint8_t index0, uint8_t index1, uint8_t index2, uint8_t index3) {
|
||||||
return
|
return
|
||||||
rom_data[0] == first_rom_bytes[index0] &&
|
rom_data[0] == first_rom_bytes[index0] &&
|
||||||
|
|
@ -176,14 +217,14 @@ void byteswap_data(std::vector<uint8_t>& rom_data, size_t index_xor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recomp::RomValidationError recomp::select_rom(const std::filesystem::path& rom_path, Game game) {
|
recomp::RomValidationError recomp::select_rom(const std::filesystem::path& rom_path, std::u8string& game_id) {
|
||||||
auto find_it = game_roms.find(game);
|
auto find_it = game_roms.find(game_id);
|
||||||
|
|
||||||
if (find_it == game_roms.end()) {
|
if (find_it == game_roms.end()) {
|
||||||
return recomp::RomValidationError::OtherError;
|
return recomp::RomValidationError::OtherError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RomEntry& game_entry = find_it->second;
|
const recomp::GameEntry& game_entry = find_it->second;
|
||||||
|
|
||||||
std::vector<uint8_t> rom_data = read_file(rom_path);
|
std::vector<uint8_t> rom_data = read_file(rom_path);
|
||||||
|
|
||||||
|
|
@ -209,13 +250,13 @@ recomp::RomValidationError recomp::select_rom(const std::filesystem::path& rom_p
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_hash(rom_data, game_entry.xxhash3_value)) {
|
if (!check_hash(rom_data, game_entry.rom_hash)) {
|
||||||
const std::string_view name{ reinterpret_cast<const char*>(rom_data.data()) + 0x20, game_entry.internal_rom_name.size()};
|
const std::string_view name{ reinterpret_cast<const char*>(rom_data.data()) + 0x20, game_entry.internal_name.size()};
|
||||||
if (name == game_entry.internal_rom_name) {
|
if (name == game_entry.internal_name) {
|
||||||
return recomp::RomValidationError::IncorrectVersion;
|
return recomp::RomValidationError::IncorrectVersion;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (game == recomp::Game::MM && std::string_view{ reinterpret_cast<const char*>(rom_data.data()) + 0x20, 19 } == "THE LEGEND OF ZELDA") {
|
if (game_entry.is_enabled && std::string_view{ reinterpret_cast<const char*>(rom_data.data()) + 0x20, 19 } == game_entry.internal_name) {
|
||||||
return recomp::RomValidationError::NotYet;
|
return recomp::RomValidationError::NotYet;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -224,7 +265,7 @@ recomp::RomValidationError recomp::select_rom(const std::filesystem::path& rom_p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write_file(recomp::get_app_folder_path() / game_entry.stored_filename, rom_data);
|
write_file(recomp::get_app_folder_path() / game_entry.stored_filename(), rom_data);
|
||||||
|
|
||||||
return recomp::RomValidationError::Good;
|
return recomp::RomValidationError::Good;
|
||||||
}
|
}
|
||||||
|
|
@ -304,8 +345,8 @@ gpr get_entrypoint_address();
|
||||||
const char* get_rom_name();
|
const char* get_rom_name();
|
||||||
|
|
||||||
void read_patch_data(uint8_t* rdram, gpr patch_data_address) {
|
void read_patch_data(uint8_t* rdram, gpr patch_data_address) {
|
||||||
for (size_t i = 0; i < sizeof(mm_patches_bin); i++) {
|
for (size_t i = 0; i < patch_data.size(); i++) {
|
||||||
MEM_B(i, patch_data_address) = mm_patches_bin[i];
|
MEM_B(i, patch_data_address) = patch_data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,15 +388,22 @@ void init(uint8_t* rdram, recomp_context* ctx) {
|
||||||
MEM_W(osMemSize, 0) = 8 * 1024 * 1024; // 8MB
|
MEM_W(osMemSize, 0) = 8 * 1024 * 1024; // 8MB
|
||||||
}
|
}
|
||||||
|
|
||||||
std::atomic<recomp::Game> game_started = recomp::Game::None;
|
std::optional<std::u8string> current_game = std::nullopt;
|
||||||
|
std::atomic<GameStatus> game_status = GameStatus::None;
|
||||||
|
|
||||||
void recomp::start_game(recomp::Game game) {
|
std::u8string recomp::current_game_id() {
|
||||||
game_started.store(game);
|
std::lock_guard<std::mutex> lock(current_game_mutex);
|
||||||
game_started.notify_all();
|
return current_game.value();
|
||||||
|
};
|
||||||
|
|
||||||
|
void recomp::start_game(std::u8string game_id) {
|
||||||
|
std::lock_guard<std::mutex> lock(current_game_mutex);
|
||||||
|
current_game = game_id;
|
||||||
|
game_status.store(GameStatus::Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ultramodern::is_game_started() {
|
bool ultramodern::is_game_started() {
|
||||||
return game_started.load() != recomp::Game::None;
|
return game_status.load() != GameStatus::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_audio_callbacks(const ultramodern::audio_callbacks_t& callbacks);
|
void set_audio_callbacks(const ultramodern::audio_callbacks_t& callbacks);
|
||||||
|
|
@ -365,9 +413,11 @@ std::atomic_bool exited = false;
|
||||||
|
|
||||||
void ultramodern::quit() {
|
void ultramodern::quit() {
|
||||||
exited.store(true);
|
exited.store(true);
|
||||||
recomp::Game desired = recomp::Game::None;
|
GameStatus desired = GameStatus::None;
|
||||||
game_started.compare_exchange_strong(desired, recomp::Game::Quit);
|
game_status.compare_exchange_strong(desired, GameStatus::Quit);
|
||||||
game_started.notify_all();
|
game_status.notify_all();
|
||||||
|
std::lock_guard<std::mutex> lock(current_game_mutex);
|
||||||
|
current_game.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input_callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks_) {
|
void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input_callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks_) {
|
||||||
|
|
@ -403,16 +453,20 @@ void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::a
|
||||||
|
|
||||||
ultramodern::preinit(rdram, window_handle);
|
ultramodern::preinit(rdram, window_handle);
|
||||||
|
|
||||||
game_started.wait(recomp::Game::None);
|
game_status.wait(GameStatus::None);
|
||||||
recomp_context context{};
|
recomp_context context{};
|
||||||
|
|
||||||
switch (game_started.load()) {
|
switch (game_status.load()) {
|
||||||
// TODO refactor this to allow a project to specify what entrypoint function to run for a give game.
|
// TODO refactor this to allow a project to specify what entrypoint function to run for a give game.
|
||||||
case recomp::Game::MM:
|
case GameStatus::Running:
|
||||||
if (!recomp::load_stored_rom(recomp::Game::MM)) {
|
if (!recomp::load_stored_rom(current_game.value())) {
|
||||||
recomp::message_box("Error opening stored ROM! Please restart this program.");
|
recomp::message_box("Error opening stored ROM! Please restart this program.");
|
||||||
}
|
}
|
||||||
ultramodern::load_shader_cache({mm_shader_cache_bytes, sizeof(mm_shader_cache_bytes)});
|
|
||||||
|
auto find_it = game_roms.find(current_game.value());
|
||||||
|
const recomp::GameEntry& game_entry = find_it->second;
|
||||||
|
|
||||||
|
ultramodern::load_shader_cache(game_entry.cache_data);
|
||||||
init(rdram, &context);
|
init(rdram, &context);
|
||||||
try {
|
try {
|
||||||
recomp_entrypoint(rdram, &context);
|
recomp_entrypoint(rdram, &context);
|
||||||
|
|
@ -420,7 +474,7 @@ void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::a
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case recomp::Game::Quit:
|
case GameStatus::Quit:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
9289
thirdparty/sse2neon/sse2neon.h
vendored
Normal file
9289
thirdparty/sse2neon/sse2neon.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -9,10 +9,6 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
# TODO: uncoment this when we fix the warnings
|
# TODO: uncoment this when we fix the warnings
|
||||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
set(LINUX TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(ultramodern STATIC
|
add_library(ultramodern STATIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/audio.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/audio.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/events.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/events.cpp"
|
||||||
|
|
@ -28,8 +24,12 @@ add_library(ultramodern STATIC
|
||||||
|
|
||||||
target_include_directories(ultramodern PUBLIC
|
target_include_directories(ultramodern PUBLIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/"
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/ultramodern" # FIXME: remove redundant path
|
|
||||||
"${CMAKE_SOURCE_DIR}/thirdparty/concurrentqueue"
|
"${CMAKE_SOURCE_DIR}/thirdparty/concurrentqueue"
|
||||||
|
"${CMAKE_SOURCE_DIR}/thirdparty/sse2neon"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(ultramodern PRIVATE
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/ultramodern"
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: remove when rt64 is no longer a hard dependency
|
# TODO: remove when rt64 is no longer a hard dependency
|
||||||
|
|
@ -63,9 +63,10 @@ if (WIN32)
|
||||||
target_link_directories(ultramodern PRIVATE
|
target_link_directories(ultramodern PRIVATE
|
||||||
${sdl2_SOURCE_DIR}/lib/x64
|
${sdl2_SOURCE_DIR}/lib/x64
|
||||||
)
|
)
|
||||||
endif()
|
elseif (APPLE)
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
if (LINUX)
|
target_include_directories(ultramodern PRIVATE ${SDL2_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(X11 REQUIRED)
|
find_package(X11 REQUIRED)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@
|
||||||
#include "ultramodern.hpp"
|
#include "ultramodern.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "rt64_layer.h"
|
#include "rt64_layer.h"
|
||||||
|
#include "recomp_ui.h"
|
||||||
#include "recomp.h"
|
#include "recomp.h"
|
||||||
#include "recomp_game.h"
|
#include "recomp_game.h"
|
||||||
#include "ultramodern/recomp_ui.h"
|
|
||||||
#include "recomp_input.h"
|
#include "recomp_input.h"
|
||||||
#include "rsp.h"
|
#include "rsp.h"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue