Merge pull request #27 from N64Recomp/upstreaming_zelda_changes

Upstream latest changes made to the ModernRuntime in the Zelda repo
This commit is contained in:
Anghelo Carvajal 2024-06-01 12:24:10 -04:00 committed by GitHub
commit d6f0f66e71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 103 additions and 18 deletions

View file

@ -1,4 +0,0 @@
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
#endif

View file

@ -101,15 +101,37 @@ std::filesystem::path get_save_file_path() {
return config_path / save_folder / (std::u8string{recomp::current_game_id()} + u8".bin");
}
void update_save_file() {
std::ofstream save_file{ get_save_file_path(), std::ios_base::binary };
std::filesystem::path get_save_file_path_temp() {
return config_path / save_folder / (recomp::current_game_id() + u8".bin.temp");
}
if (save_file.good()) {
std::lock_guard lock{ save_context.save_buffer_mutex };
save_file.write(save_context.save_buffer.data(), save_context.save_buffer.size());
} else {
fprintf(stderr, "Failed to save!\n");
std::exit(EXIT_FAILURE);
std::filesystem::path get_save_file_path_backup() {
return config_path / save_folder / (recomp::current_game_id() + u8".bin.bak");
}
void update_save_file() {
{
std::ofstream save_file{ get_save_file_path_temp(), std::ios_base::binary };
if (save_file.good()) {
std::lock_guard lock{ save_context.save_buffer_mutex };
save_file.write(save_context.save_buffer.data(), save_context.save_buffer.size());
}
else {
ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions. If you have moved your appdata folder to Dropbox or similar, this can cause issues.");
}
}
std::error_code ec;
if (std::filesystem::exists(get_save_file_path(), ec)) {
std::filesystem::copy_file(get_save_file_path(), get_save_file_path_backup(), std::filesystem::copy_options::overwrite_existing, ec);
if (ec) {
printf("[ERROR] Failed to copy save file backup\n");
}
}
std::filesystem::copy_file(get_save_file_path_temp(), get_save_file_path(), std::filesystem::copy_options::overwrite_existing, ec);
if (ec) {
ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions. If you have moved your appdata folder to Dropbox or similar, this can cause issues.");
}
}
@ -176,6 +198,7 @@ void save_clear(uint32_t start, uint32_t size, char value) {
void ultramodern::init_saving(RDRAM_ARG1) {
std::filesystem::path save_file_path = get_save_file_path();
std::filesystem::path save_file_path_backup = get_save_file_path_backup();
// Ensure the save file directory exists.
std::filesystem::create_directories(save_file_path.parent_path());
@ -185,8 +208,14 @@ void ultramodern::init_saving(RDRAM_ARG1) {
if (save_file.good()) {
save_file.read(save_context.save_buffer.data(), save_context.save_buffer.size());
} else {
// Otherwise clear the save file to all zeroes.
save_context.save_buffer.fill(0);
// Reading the save file faield, so try to read the backup save file.
std::ifstream save_file_backup{ save_file_path_backup, std::ios_base::binary };
if (save_file_backup.good()) {
save_file_backup.read(save_context.save_buffer.data(), save_context.save_buffer.size());
} else {
// Otherwise clear the save file to all zeroes.
save_context.save_buffer.fill(0);
}
}
save_context.saving_thread = std::thread{saving_thread_func, PASS_RDRAM};

2
rt64

@ -1 +1 @@
Subproject commit ca26fb8096b9af117c668e8dfaa49fdde815c3b7
Subproject commit 1adcbea31a04f2403da729eb5dfed3950dd7ec52

View file

@ -61,6 +61,7 @@ if (WIN32)
target_link_directories(ultramodern PRIVATE
${sdl2_SOURCE_DIR}/lib/x64
)
add_compile_definitions(NOMINMAX)
elseif (APPLE)
find_package(SDL2 REQUIRED)
target_include_directories(ultramodern PRIVATE ${SDL2_INCLUDE_DIRS})

View file

@ -28,6 +28,12 @@ namespace ultramodern {
Vulkan,
OptionCount
};
enum class HighPrecisionFramebuffer {
Auto,
On,
Off,
OptionCount
};
struct GraphicsConfig {
Resolution res_option;
@ -38,6 +44,7 @@ namespace ultramodern {
RT64::UserConfiguration::AspectRatio ar_option;
RT64::UserConfiguration::Antialiasing msaa_option;
RT64::UserConfiguration::RefreshRate rr_option;
HighPrecisionFramebuffer hpfb_option;
int rr_manual_value;
int ds_option;
bool developer_mode;
@ -70,6 +77,12 @@ namespace ultramodern {
{ultramodern::GraphicsApi::D3D12, "D3D12"},
{ultramodern::GraphicsApi::Vulkan, "Vulkan"},
});
NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::HighPrecisionFramebuffer, {
{ultramodern::HighPrecisionFramebuffer::Auto, "Auto"},
{ultramodern::HighPrecisionFramebuffer::On, "On"},
{ultramodern::HighPrecisionFramebuffer::Off, "Off"},
});
};
#endif

View file

@ -32,14 +32,16 @@ namespace ultramodern {
void shutdown();
void set_dummy_vi();
uint32_t get_display_framerate();
float get_resolution_scale();
void load_shader_cache(std::span<const char> cache_binary);
private:
RT64SetupResult setup_result;
std::unique_ptr<RT64::Application> app;
};
RT64::UserConfiguration::Antialiasing RT64MaxMSAA();
bool RT64SamplePositionsSupported();
bool RT64HighPrecisionFBEnabled();
}
void set_rt64_hooks();

View file

@ -122,9 +122,9 @@ void sleep_milliseconds(uint32_t millis);
void sleep_until(const std::chrono::high_resolution_clock::time_point& time_point);
// Graphics
void get_window_size(uint32_t& width, uint32_t& height);
uint32_t get_target_framerate(uint32_t original);
uint32_t get_display_refresh_rate();
float get_resolution_scale();
void load_shader_cache(std::span<const char> cache_data);
// Audio

View file

@ -241,6 +241,7 @@ ultramodern::GraphicsConfig ultramodern::get_graphics_config() {
}
std::atomic_uint32_t display_refresh_rate = 60;
std::atomic<float> resolution_scale = 1.0f;
uint32_t ultramodern::get_target_framerate(uint32_t original) {
ultramodern::GraphicsConfig graphics_config = ultramodern::get_graphics_config();
@ -260,6 +261,10 @@ uint32_t ultramodern::get_display_refresh_rate() {
return display_refresh_rate.load();
}
float ultramodern::get_resolution_scale() {
return resolution_scale.load();
}
void ultramodern::load_shader_cache(std::span<const char> cache_data) {
events_context.action_queue.enqueue(LoadShaderCacheAction{cache_data});
}
@ -322,6 +327,7 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re
events_context.vi.current_buffer = events_context.vi.next_buffer;
rt64.update_screen(swap_action->origin);
display_refresh_rate = rt64.get_display_framerate();
resolution_scale = rt64.get_resolution_scale();
}
else if (const auto* config_action = std::get_if<UpdateConfigAction>(&action)) {
ultramodern::GraphicsConfig new_config = cur_config;

View file

@ -1,6 +1,5 @@
#include <memory>
#include <cstring>
// #include <Windows.h>
#define HLSL_CPU
#include "hle/rt64_application.h"
@ -11,6 +10,7 @@ ultramodern::RT64Context::~RT64Context() = default;
static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
static bool sample_positions_supported = false;
static bool high_precision_fb_enabled = false;
static uint8_t DMEM[0x1000];
static uint8_t IMEM[0x1000];
@ -58,6 +58,19 @@ RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampl
return RT64::UserConfiguration::Antialiasing::None;
}
RT64::UserConfiguration::InternalColorFormat to_rt64(ultramodern::HighPrecisionFramebuffer option) {
switch (option) {
case ultramodern::HighPrecisionFramebuffer::Off:
return RT64::UserConfiguration::InternalColorFormat::Standard;
case ultramodern::HighPrecisionFramebuffer::On:
return RT64::UserConfiguration::InternalColorFormat::High;
case ultramodern::HighPrecisionFramebuffer::Auto:
return RT64::UserConfiguration::InternalColorFormat::Automatic;
default:
return RT64::UserConfiguration::InternalColorFormat::OptionCount;
}
}
void set_application_user_config(RT64::Application* application, const ultramodern::GraphicsConfig& config) {
switch (config.res_option) {
default:
@ -95,6 +108,7 @@ void set_application_user_config(RT64::Application* application, const ultramode
application->userConfig.antialiasing = config.msaa_option;
application->userConfig.refreshRate = config.rr_option;
application->userConfig.refreshRateTarget = config.rr_manual_value;
application->userConfig.internalColorFormat = to_rt64(config.hpfb_option);
}
ultramodern::RT64SetupResult map_setup_result(RT64::Application::SetupResult rt64_result) {
@ -223,6 +237,8 @@ ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle
device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
sample_positions_supported = false;
}
high_precision_fb_enabled = app->shaderLibrary->usesHDR;
}
void ultramodern::RT64Context::send_dl(const OSTask* task) {
@ -268,6 +284,24 @@ uint32_t ultramodern::RT64Context::get_display_framerate() {
return app->presentQueue->ext.sharedResources->swapChainRate;
}
float ultramodern::RT64Context::get_resolution_scale() {
constexpr int ReferenceHeight = 240;
switch (app->userConfig.resolution) {
case RT64::UserConfiguration::Resolution::WindowIntegerScale:
if (app->sharedQueueResources->swapChainHeight > 0) {
return std::max(float((app->sharedQueueResources->swapChainHeight + ReferenceHeight - 1) / ReferenceHeight), 1.0f);
}
else {
return 1.0f;
}
case RT64::UserConfiguration::Resolution::Manual:
return float(app->userConfig.resolutionMultiplier);
case RT64::UserConfiguration::Resolution::Original:
default:
return 1.0f;
}
}
void ultramodern::RT64Context::load_shader_cache(std::span<const char> cache_binary) {
// TODO figure out how to avoid a copy here.
std::istringstream cache_stream{std::string{cache_binary.data(), cache_binary.size()}};
@ -285,3 +319,7 @@ RT64::UserConfiguration::Antialiasing ultramodern::RT64MaxMSAA() {
bool ultramodern::RT64SamplePositionsSupported() {
return sample_positions_supported;
}
bool ultramodern::RT64HighPrecisionFBEnabled() {
return high_precision_fb_enabled;
}