1.0.1 Hotfixes (#190)
* Fixed bug with autosaving where some flags weren't updated in the save buffer * Display message boxes for RT64 initialization errors * Bump version number to 1.0.1
This commit is contained in:
parent
3f9478c7e6
commit
b791a4aa1d
|
@ -8,6 +8,7 @@
|
||||||
namespace recomp {
|
namespace recomp {
|
||||||
constexpr std::u8string_view program_id = u8"Zelda64Recompiled";
|
constexpr std::u8string_view program_id = u8"Zelda64Recompiled";
|
||||||
constexpr std::u8string_view mm_game_id = u8"mm.n64.us.1.0";
|
constexpr std::u8string_view mm_game_id = u8"mm.n64.us.1.0";
|
||||||
|
constexpr std::string_view program_name = "Zelda 64: Recompiled";
|
||||||
|
|
||||||
void load_config();
|
void load_config();
|
||||||
void save_config();
|
void save_config();
|
||||||
|
|
|
@ -9,12 +9,21 @@ namespace RT64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ultramodern {
|
namespace ultramodern {
|
||||||
|
enum class RT64SetupResult {
|
||||||
|
Success,
|
||||||
|
DynamicLibrariesNotFound,
|
||||||
|
InvalidGraphicsAPI,
|
||||||
|
GraphicsAPINotFound,
|
||||||
|
GraphicsDeviceNotFound
|
||||||
|
};
|
||||||
|
|
||||||
struct WindowHandle;
|
struct WindowHandle;
|
||||||
struct RT64Context {
|
struct RT64Context {
|
||||||
public:
|
public:
|
||||||
~RT64Context();
|
~RT64Context();
|
||||||
RT64Context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode);
|
RT64Context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode);
|
||||||
bool valid() { return static_cast<bool>(app); }
|
bool valid() { return static_cast<bool>(app); }
|
||||||
|
RT64SetupResult get_setup_result() { return setup_result; }
|
||||||
|
|
||||||
void update_config(const GraphicsConfig& old_config, const GraphicsConfig& new_config);
|
void update_config(const GraphicsConfig& old_config, const GraphicsConfig& new_config);
|
||||||
void enable_instant_present();
|
void enable_instant_present();
|
||||||
|
@ -25,6 +34,7 @@ namespace ultramodern {
|
||||||
uint32_t get_display_framerate();
|
uint32_t get_display_framerate();
|
||||||
void load_shader_cache(std::span<const char> cache_binary);
|
void load_shader_cache(std::span<const char> cache_binary);
|
||||||
private:
|
private:
|
||||||
|
RT64SetupResult setup_result;
|
||||||
std::unique_ptr<RT64::Application> app;
|
std::unique_ptr<RT64::Application> app;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,18 @@ void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages);
|
||||||
void autosave_reset_timer();
|
void autosave_reset_timer();
|
||||||
void autosave_reset_timer_slow();
|
void autosave_reset_timer_slow();
|
||||||
|
|
||||||
void do_autosave(SramContext* sramCtx) {
|
void do_autosave(PlayState* play) {
|
||||||
|
// Transfer the scene flags into the cycle flags.
|
||||||
|
Play_SaveCycleSceneFlags(&play->state);
|
||||||
|
// Transfer the cycle flags into the save buffer. Logic copied from func_8014546C.
|
||||||
|
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
||||||
|
gSaveContext.save.saveInfo.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
|
||||||
|
gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
|
||||||
|
gSaveContext.save.saveInfo.permanentSceneFlags[i].switch1 = gSaveContext.cycleSceneFlags[i].switch1;
|
||||||
|
gSaveContext.save.saveInfo.permanentSceneFlags[i].clearedRoom = gSaveContext.cycleSceneFlags[i].clearedRoom;
|
||||||
|
gSaveContext.save.saveInfo.permanentSceneFlags[i].collectible = gSaveContext.cycleSceneFlags[i].collectible;
|
||||||
|
}
|
||||||
|
|
||||||
s32 fileNum = gSaveContext.fileNum;
|
s32 fileNum = gSaveContext.fileNum;
|
||||||
|
|
||||||
gSaveContext.save.isOwlSave = SAVE_TYPE_AUTOSAVE;
|
gSaveContext.save.isOwlSave = SAVE_TYPE_AUTOSAVE;
|
||||||
|
@ -78,6 +89,7 @@ void do_autosave(SramContext* sramCtx) {
|
||||||
gSaveContext.save.saveInfo.checksum = 0;
|
gSaveContext.save.saveInfo.checksum = 0;
|
||||||
gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext, offsetof(SaveContext, fileNum));
|
gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext, offsetof(SaveContext, fileNum));
|
||||||
|
|
||||||
|
SramContext* sramCtx = &play->sramCtx;
|
||||||
// Copy the saved parts of the global save context into the sram saving buffer.
|
// Copy the saved parts of the global save context into the sram saving buffer.
|
||||||
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum));
|
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum));
|
||||||
// Synchronously save into the owl save slot and the backup owl save slot.
|
// Synchronously save into the owl save slot and the backup owl save slot.
|
||||||
|
@ -413,7 +425,7 @@ void autosave_post_play_update(PlayState* play) {
|
||||||
frames_since_autosave_ready >= MIN_FRAMES_SINCE_READY &&
|
frames_since_autosave_ready >= MIN_FRAMES_SINCE_READY &&
|
||||||
time_now - last_autosave_time > (OS_USEC_TO_CYCLES(1000 * (recomp_autosave_interval() + extra_autosave_delay_milliseconds)))
|
time_now - last_autosave_time > (OS_USEC_TO_CYCLES(1000 * (recomp_autosave_interval() + extra_autosave_delay_milliseconds)))
|
||||||
) {
|
) {
|
||||||
do_autosave(&play->sramCtx);
|
do_autosave(play);
|
||||||
show_autosave_icon();
|
show_autosave_icon();
|
||||||
autosave_reset_timer();
|
autosave_reset_timer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "nfd.h"
|
#include "nfd.h"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
std::string version_number = "v1.0.0";
|
std::string version_number = "v1.0.1";
|
||||||
|
|
||||||
Rml::DataModelHandle model_handle;
|
Rml::DataModelHandle model_handle;
|
||||||
bool mm_rom_valid = false;
|
bool mm_rom_valid = false;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "recomp_ui.h"
|
#include "recomp_ui.h"
|
||||||
#include "recomp_input.h"
|
#include "recomp_input.h"
|
||||||
#include "recomp_game.h"
|
#include "recomp_game.h"
|
||||||
|
#include "recomp_config.h"
|
||||||
#include "ui_rml_hacks.hpp"
|
#include "ui_rml_hacks.hpp"
|
||||||
|
|
||||||
#include "concurrentqueue.h"
|
#include "concurrentqueue.h"
|
||||||
|
@ -1464,5 +1465,5 @@ recomp::Menu recomp::get_current_menu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void recomp::message_box(const char* msg) {
|
void recomp::message_box(const char* msg) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", msg, nullptr);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, recomp::program_name.data(), msg, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "rt64_layer.h"
|
#include "rt64_layer.h"
|
||||||
#include "recomp.h"
|
#include "recomp.h"
|
||||||
|
#include "recomp_game.h"
|
||||||
#include "recomp_ui.h"
|
#include "recomp_ui.h"
|
||||||
#include "recomp_input.h"
|
#include "recomp_input.h"
|
||||||
#include "rsp.h"
|
#include "rsp.h"
|
||||||
|
@ -301,6 +302,8 @@ void ultramodern::load_shader_cache(std::span<const char> cache_data) {
|
||||||
events_context.action_queue.enqueue(LoadShaderCacheAction{cache_data});
|
events_context.action_queue.enqueue(LoadShaderCacheAction{cache_data});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::atomic<ultramodern::RT64SetupResult> rt64_setup_result = ultramodern::RT64SetupResult::Success;
|
||||||
|
|
||||||
void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_ready, ultramodern::WindowHandle window_handle) {
|
void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_ready, ultramodern::WindowHandle window_handle) {
|
||||||
bool enabled_instant_present = false;
|
bool enabled_instant_present = false;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
@ -313,7 +316,11 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re
|
||||||
ultramodern::RT64Context rt64{rdram, window_handle, cur_config.load().developer_mode};
|
ultramodern::RT64Context rt64{rdram, window_handle, cur_config.load().developer_mode};
|
||||||
|
|
||||||
if (!rt64.valid()) {
|
if (!rt64.valid()) {
|
||||||
throw std::runtime_error("Failed to initialize RT64!");
|
// TODO move recomp code out of ultramodern.
|
||||||
|
rt64_setup_result.store(rt64.get_setup_result());
|
||||||
|
// Notify the caller thread that this thread is ready.
|
||||||
|
thread_ready->signal();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move recomp code out of ultramodern.
|
// TODO move recomp code out of ultramodern.
|
||||||
|
@ -537,6 +544,27 @@ void ultramodern::send_si_message(RDRAM_ARG1) {
|
||||||
osSendMesg(PASS_RDRAM events_context.si.mq, events_context.si.msg, OS_MESG_NOBLOCK);
|
osSendMesg(PASS_RDRAM events_context.si.mq, events_context.si.msg, OS_MESG_NOBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_graphics_api_name(ultramodern::GraphicsApi api) {
|
||||||
|
if (api == ultramodern::GraphicsApi::Auto) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
api = ultramodern::GraphicsApi::D3D12;
|
||||||
|
#elif defined(__gnu_linux__)
|
||||||
|
api = ultramodern::GraphicsApi::Vulkan;
|
||||||
|
#else
|
||||||
|
static_assert(false && "Unimplemented")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (api) {
|
||||||
|
case ultramodern::GraphicsApi::D3D12:
|
||||||
|
return "D3D12";
|
||||||
|
case ultramodern::GraphicsApi::Vulkan:
|
||||||
|
return "Vulkan";
|
||||||
|
default:
|
||||||
|
return "[Unknown graphics API]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ultramodern::init_events(RDRAM_ARG ultramodern::WindowHandle window_handle) {
|
void ultramodern::init_events(RDRAM_ARG ultramodern::WindowHandle window_handle) {
|
||||||
moodycamel::LightweightSemaphore gfx_thread_ready;
|
moodycamel::LightweightSemaphore gfx_thread_ready;
|
||||||
moodycamel::LightweightSemaphore task_thread_ready;
|
moodycamel::LightweightSemaphore task_thread_ready;
|
||||||
|
@ -549,6 +577,30 @@ void ultramodern::init_events(RDRAM_ARG ultramodern::WindowHandle window_handle)
|
||||||
gfx_thread_ready.wait();
|
gfx_thread_ready.wait();
|
||||||
task_thread_ready.wait();
|
task_thread_ready.wait();
|
||||||
|
|
||||||
|
ultramodern::RT64SetupResult setup_result = rt64_setup_result.load();
|
||||||
|
if (rt64_setup_result != ultramodern::RT64SetupResult::Success) {
|
||||||
|
auto show_rt64_error = [](const std::string& msg) {
|
||||||
|
// TODO move recomp code out of ultramodern (message boxes).
|
||||||
|
recomp::message_box(("An error has been encountered on startup: " + msg).c_str());
|
||||||
|
};
|
||||||
|
const std::string driver_os_suffix = "\nPlease make sure your GPU drivers and your OS are up to date.";
|
||||||
|
switch (rt64_setup_result) {
|
||||||
|
case ultramodern::RT64SetupResult::DynamicLibrariesNotFound:
|
||||||
|
show_rt64_error("Failed to load dynamic libraries. Make sure the DLLs are next to the recomp executable.");
|
||||||
|
break;
|
||||||
|
case ultramodern::RT64SetupResult::InvalidGraphicsAPI:
|
||||||
|
show_rt64_error(get_graphics_api_name(cur_config.load().api_option) + " is not supported on this platform. Please select a different graphics API.");
|
||||||
|
break;
|
||||||
|
case ultramodern::RT64SetupResult::GraphicsAPINotFound:
|
||||||
|
show_rt64_error("Unable to initialize " + get_graphics_api_name(cur_config.load().api_option) + "." + driver_os_suffix);
|
||||||
|
break;
|
||||||
|
case ultramodern::RT64SetupResult::GraphicsDeviceNotFound:
|
||||||
|
show_rt64_error("Unable to find compatible graphics device." + driver_os_suffix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Failed to initialize RT64");
|
||||||
|
}
|
||||||
|
|
||||||
events_context.vi.thread = std::thread{ vi_thread_func };
|
events_context.vi.thread = std::thread{ vi_thread_func };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,21 @@ void set_application_user_config(RT64::Application* application, const ultramode
|
||||||
application->userConfig.refreshRateTarget = config.rr_manual_value;
|
application->userConfig.refreshRateTarget = config.rr_manual_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ultramodern::RT64SetupResult map_setup_result(RT64::Application::SetupResult rt64_result) {
|
||||||
|
switch (rt64_result) {
|
||||||
|
case RT64::Application::SetupResult::Success:
|
||||||
|
return ultramodern::RT64SetupResult::Success;
|
||||||
|
case RT64::Application::SetupResult::DynamicLibrariesNotFound:
|
||||||
|
return ultramodern::RT64SetupResult::DynamicLibrariesNotFound;
|
||||||
|
case RT64::Application::SetupResult::InvalidGraphicsAPI:
|
||||||
|
return ultramodern::RT64SetupResult::InvalidGraphicsAPI;
|
||||||
|
case RT64::Application::SetupResult::GraphicsAPINotFound:
|
||||||
|
return ultramodern::RT64SetupResult::GraphicsAPINotFound;
|
||||||
|
case RT64::Application::SetupResult::GraphicsDeviceNotFound:
|
||||||
|
return ultramodern::RT64SetupResult::GraphicsDeviceNotFound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool debug) {
|
ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool debug) {
|
||||||
static unsigned char dummy_rom_header[0x40];
|
static unsigned char dummy_rom_header[0x40];
|
||||||
set_rt64_hooks();
|
set_rt64_hooks();
|
||||||
|
@ -179,7 +194,8 @@ ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
thread_id = window_handle.thread_id;
|
thread_id = window_handle.thread_id;
|
||||||
#endif
|
#endif
|
||||||
if (app->setup(thread_id) != RT64::Application::SetupResult::Success) {
|
setup_result = map_setup_result(app->setup(thread_id));
|
||||||
|
if (setup_result != ultramodern::RT64SetupResult::Success) {
|
||||||
app = nullptr;
|
app = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue