From b334c677b9e7aeb4f2487c306bdcbd07414cc0d2 Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Sun, 14 Apr 2024 15:59:42 -0400 Subject: [PATCH] Update RT64 and refactor RT64 handling --- .gitmodules | 3 - CMakeLists.txt | 15 +- include/rt64_layer.h | 30 ++-- lib/nativefiledialog-extended | 1 - lib/rt64 | 2 +- src/recomp/rt64_layer.cpp | 303 ---------------------------------- src/ui/ui_config.cpp | 8 +- src/ui/ui_renderer.cpp | 2 +- ultramodern/events.cpp | 22 +-- ultramodern/rt64_layer.cpp | 237 ++++++++++++++++++++++++++ 10 files changed, 277 insertions(+), 346 deletions(-) delete mode 160000 lib/nativefiledialog-extended delete mode 100644 src/recomp/rt64_layer.cpp create mode 100644 ultramodern/rt64_layer.cpp diff --git a/.gitmodules b/.gitmodules index 645c6da..25e5d53 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "lib/RmlUi"] path = lib/RmlUi url = https://github.com/mikke89/RmlUi/ -[submodule "lib/nativefiledialog-extended"] - path = lib/nativefiledialog-extended - url = https://github.com/btzy/nativefiledialog-extended [submodule "lib/rt64"] path = lib/rt64 url = https://github.com/rt64/rt64 diff --git a/CMakeLists.txt b/CMakeLists.txt index c298cf4..8127449 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/") +set(RT64_STATIC TRUE) add_subdirectory(${CMAKE_SOURCE_DIR}/lib/rt64 ${CMAKE_BINARY_DIR}/rt64) # set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}") @@ -31,11 +32,8 @@ add_subdirectory(${CMAKE_SOURCE_DIR}/lib/lunasvg) # set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}") SET(ENABLE_SVG_PLUGIN OFF CACHE BOOL "" FORCE) add_subdirectory(${CMAKE_SOURCE_DIR}/lib/RmlUi) -add_subdirectory(${CMAKE_SOURCE_DIR}/lib/nativefiledialog-extended) target_include_directories(rt64 PRIVATE ${CMAKE_BINARY_DIR}/rt64/src) -get_target_property(RT64_BASENAME rt64 OUTPUT_NAME) -set(RT64_DLL ${RT64_BASENAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) # RecompiledFuncs - Library containing the primary recompiler output add_library(RecompiledFuncs STATIC) @@ -111,6 +109,7 @@ set (SOURCES ${CMAKE_SOURCE_DIR}/ultramodern/threads.cpp ${CMAKE_SOURCE_DIR}/ultramodern/timer.cpp ${CMAKE_SOURCE_DIR}/ultramodern/ultrainit.cpp + ${CMAKE_SOURCE_DIR}/ultramodern/rt64_layer.cpp ${CMAKE_SOURCE_DIR}/src/recomp/ai.cpp ${CMAKE_SOURCE_DIR}/src/recomp/cont.cpp @@ -127,7 +126,6 @@ set (SOURCES ${CMAKE_SOURCE_DIR}/src/recomp/ultra_translation.cpp ${CMAKE_SOURCE_DIR}/src/recomp/print.cpp ${CMAKE_SOURCE_DIR}/src/recomp/recomp.cpp - ${CMAKE_SOURCE_DIR}/src/recomp/rt64_layer.cpp ${CMAKE_SOURCE_DIR}/src/recomp/sp.cpp ${CMAKE_SOURCE_DIR}/src/recomp/vi.cpp @@ -175,7 +173,7 @@ target_include_directories(Zelda64Recompiled PRIVATE ${CMAKE_SOURCE_DIR}/lib/rt64/src/rhi ${CMAKE_SOURCE_DIR}/lib/rt64/src/render ${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include - ${CMAKE_SOURCE_DIR}/lib/lib/nativefiledialog-extended/src/include + ${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/nativefiledialog-extended/src/include ${CMAKE_BINARY_DIR}/shaders ) @@ -214,7 +212,7 @@ if (WIN32) PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE" LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup" - LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup" + # LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup" LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup" ) @@ -257,8 +255,3 @@ target_sources(Zelda64Recompiled PRIVATE ${SOURCES}) set_property(TARGET Zelda64Recompiled PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") -add_custom_command(TARGET Zelda64Recompiled POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_BINARY_DIR}/${RT64_DLL} - ${CMAKE_SOURCE_DIR} - MAIN_DEPENDENCY ${CMAKE_BINARY_DIR}/${RT64_DLL}) diff --git a/include/rt64_layer.h b/include/rt64_layer.h index 1b207c7..a0bf2e3 100644 --- a/include/rt64_layer.h +++ b/include/rt64_layer.h @@ -10,18 +10,26 @@ namespace RT64 { namespace ultramodern { struct WindowHandle; -} + struct RT64Context { + public: + ~RT64Context(); + RT64Context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode); + bool valid() { return static_cast(app); } -RT64::Application* RT64Init(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool developer_mode); -void RT64UpdateConfig(RT64::Application* application, const ultramodern::GraphicsConfig& old_config, const ultramodern::GraphicsConfig& new_config); -void RT64EnableInstantPresent(RT64::Application* application); -void RT64SendDL(uint8_t* rdram, const OSTask* task); -void RT64UpdateScreen(uint32_t vi_origin); -void RT64ChangeWindow(); -void RT64Shutdown(); -RT64::UserConfiguration::Antialiasing RT64MaxMSAA(); -bool RT64SamplePositionsSupported(); -uint32_t RT64GetDisplayFramerate(RT64::Application* application); + void update_config(const GraphicsConfig& old_config, const GraphicsConfig& new_config); + void enable_instant_present(); + void send_dl(const OSTask* task); + void update_screen(uint32_t vi_origin); + void shutdown(); + void set_dummy_vi(); + uint32_t get_display_framerate(); + private: + std::unique_ptr app; + }; + + RT64::UserConfiguration::Antialiasing RT64MaxMSAA(); + bool RT64SamplePositionsSupported(); +} void set_rt64_hooks(); diff --git a/lib/nativefiledialog-extended b/lib/nativefiledialog-extended deleted file mode 160000 index 75cbdf8..0000000 --- a/lib/nativefiledialog-extended +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 75cbdf819785d9f94855987724e30a6ba0a87e29 diff --git a/lib/rt64 b/lib/rt64 index 3e20a48..cbab135 160000 --- a/lib/rt64 +++ b/lib/rt64 @@ -1 +1 @@ -Subproject commit 3e20a48565c8b33dce93c283267262854bdd36df +Subproject commit cbab135a3133313085cf515d2067f7b037a88a52 diff --git a/src/recomp/rt64_layer.cpp b/src/recomp/rt64_layer.cpp deleted file mode 100644 index 09baf6e..0000000 --- a/src/recomp/rt64_layer.cpp +++ /dev/null @@ -1,303 +0,0 @@ -#include -#include -// #include - -#define HLSL_CPU -#include "hle/rt64_application.h" -#include "rt64_layer.h" -#include "rt64_render_hooks.h" - -typedef struct { - // void* hWnd; - // void* hStatusBar; - - // int Reserved; - - unsigned char* HEADER; /* This is the rom header (first 40h bytes of the rom) */ - unsigned char* RDRAM; - unsigned char* DMEM; - unsigned char* IMEM; - - unsigned int* MI_INTR_REG; - - unsigned int* DPC_START_REG; - unsigned int* DPC_END_REG; - unsigned int* DPC_CURRENT_REG; - unsigned int* DPC_STATUS_REG; - unsigned int* DPC_CLOCK_REG; - unsigned int* DPC_BUFBUSY_REG; - unsigned int* DPC_PIPEBUSY_REG; - unsigned int* DPC_TMEM_REG; - - unsigned int* VI_STATUS_REG; - unsigned int* VI_ORIGIN_REG; - unsigned int* VI_WIDTH_REG; - unsigned int* VI_INTR_REG; - unsigned int* VI_V_CURRENT_LINE_REG; - unsigned int* VI_TIMING_REG; - unsigned int* VI_V_SYNC_REG; - unsigned int* VI_H_SYNC_REG; - unsigned int* VI_LEAP_REG; - unsigned int* VI_H_START_REG; - unsigned int* VI_V_START_REG; - unsigned int* VI_V_BURST_REG; - unsigned int* VI_X_SCALE_REG; - unsigned int* VI_Y_SCALE_REG; - - void (*CheckInterrupts)(void); - - unsigned int version; - unsigned int* SP_STATUS_REG; - const unsigned int* RDRAM_SIZE; -} GFX_INFO; - -#ifdef _WIN32 -#define DLLEXPORT extern "C" __declspec(dllexport) -#define DLLIMPORT extern "C" __declspec(dllimport) -#define CALL __cdecl -#else -#define DLLEXPORT extern "C" __attribute__((visibility("default"))) -#define DLLIMPORT extern "C" -#endif - -#if defined(_WIN32) -extern "C" RT64::Application* InitiateGFXWindows(GFX_INFO Gfx_Info, HWND hwnd, DWORD threadId, uint8_t debug); -#elif defined(__ANDROID__) -static_assert(false && "Unimplemented"); -#elif defined(__linux__) -extern "C" RT64::Application* InitiateGFXLinux(GFX_INFO Gfx_Info, Window window, Display *display, uint8_t debug); -#else -static_assert(false && "Unimplemented"); -#endif - -DLLIMPORT void ProcessRDPList(void); -DLLIMPORT void ProcessDList(void); -DLLIMPORT void UpdateScreen(void); -DLLIMPORT void ChangeWindow(void); -DLLIMPORT void PluginShutdown(void); - -static uint8_t DMEM[0x1000]; -static uint8_t IMEM[0x1000]; - -unsigned int MI_INTR_REG = 0; - -unsigned int DPC_START_REG = 0; -unsigned int DPC_END_REG = 0; -unsigned int DPC_CURRENT_REG = 0; -unsigned int DPC_STATUS_REG = 0; -unsigned int DPC_CLOCK_REG = 0; -unsigned int DPC_BUFBUSY_REG = 0; -unsigned int DPC_PIPEBUSY_REG = 0; -unsigned int DPC_TMEM_REG = 0; - -unsigned int VI_STATUS_REG = 0; -unsigned int VI_ORIGIN_REG = 0; -unsigned int VI_WIDTH_REG = 0; -unsigned int VI_INTR_REG = 0; -unsigned int VI_V_CURRENT_LINE_REG = 0; -unsigned int VI_TIMING_REG = 0; -unsigned int VI_V_SYNC_REG = 0; -unsigned int VI_H_SYNC_REG = 0; -unsigned int VI_LEAP_REG = 0; -unsigned int VI_H_START_REG = 0; -unsigned int VI_V_START_REG = 0; -unsigned int VI_V_BURST_REG = 0; -unsigned int VI_X_SCALE_REG = 0; -unsigned int VI_Y_SCALE_REG = 0; - -unsigned int SP_STATUS_REG = 0; -unsigned int RDRAM_SIZE = 0x800000; - -static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None; -static bool sample_positions_supported = false; - -#define GET_FUNC(lib, name) \ - name = (decltype(name))GetProcAddress(lib, #name) - -void dummy_check_interrupts() { - -} - -RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampleCounts bits) { - if (bits & RT64::RenderSampleCount::Bits::COUNT_2) { - if (bits & RT64::RenderSampleCount::Bits::COUNT_4) { - if (bits & RT64::RenderSampleCount::Bits::COUNT_8) { - return RT64::UserConfiguration::Antialiasing::MSAA8X; - } - return RT64::UserConfiguration::Antialiasing::MSAA4X; - } - return RT64::UserConfiguration::Antialiasing::MSAA2X; - }; - return RT64::UserConfiguration::Antialiasing::None; -} - -RT64::Application* RT64Init(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool debug) { - static unsigned char dummy_rom_header[0x40]; - set_rt64_hooks(); - - GFX_INFO gfx_info{}; - - gfx_info.HEADER = dummy_rom_header; - gfx_info.RDRAM = rdram; - gfx_info.DMEM = DMEM; - gfx_info.IMEM = IMEM; - - gfx_info.MI_INTR_REG = &MI_INTR_REG; - - gfx_info.DPC_START_REG = &DPC_START_REG; - gfx_info.DPC_END_REG = &DPC_END_REG; - gfx_info.DPC_CURRENT_REG = &DPC_CURRENT_REG; - gfx_info.DPC_STATUS_REG = &DPC_STATUS_REG; - gfx_info.DPC_CLOCK_REG = &DPC_CLOCK_REG; - gfx_info.DPC_BUFBUSY_REG = &DPC_BUFBUSY_REG; - gfx_info.DPC_PIPEBUSY_REG = &DPC_PIPEBUSY_REG; - gfx_info.DPC_TMEM_REG = &DPC_TMEM_REG; - - gfx_info.VI_STATUS_REG = &VI_STATUS_REG; - gfx_info.VI_ORIGIN_REG = &VI_ORIGIN_REG; - gfx_info.VI_WIDTH_REG = &VI_WIDTH_REG; - gfx_info.VI_INTR_REG = &VI_INTR_REG; - gfx_info.VI_V_CURRENT_LINE_REG = &VI_V_CURRENT_LINE_REG; - gfx_info.VI_TIMING_REG = &VI_TIMING_REG; - gfx_info.VI_V_SYNC_REG = &VI_V_SYNC_REG; - gfx_info.VI_H_SYNC_REG = &VI_H_SYNC_REG; - gfx_info.VI_LEAP_REG = &VI_LEAP_REG; - gfx_info.VI_H_START_REG = &VI_H_START_REG; - gfx_info.VI_V_START_REG = &VI_V_START_REG; - gfx_info.VI_V_BURST_REG = &VI_V_BURST_REG; - gfx_info.VI_X_SCALE_REG = &VI_X_SCALE_REG; - gfx_info.VI_Y_SCALE_REG = &VI_Y_SCALE_REG; - - gfx_info.CheckInterrupts = dummy_check_interrupts; - - gfx_info.version = 2; - gfx_info.SP_STATUS_REG = &SP_STATUS_REG; - gfx_info.RDRAM_SIZE = &RDRAM_SIZE; - -#if defined(_WIN32) - RT64::Application* ret = InitiateGFXWindows(gfx_info, window_handle.window, window_handle.thread_id, debug); -#elif defined(__ANDROID__) - static_assert(false && "Unimplemented"); -#elif defined(__linux__) - RT64::Application* ret = InitiateGFXLinux(gfx_info, window_handle.window, window_handle.display, debug); -#else - static_assert(false && "Unimplemented"); -#endif - - // Before configuring multisampling, make sure the device actually supports it for the formats we'll use. If it doesn't, turn off antialiasing in the configuration. - // RT64 requires programmable sample positions for MSAA to function without issues, so check that first. - if (ret->device->getCapabilities().sampleLocations) { - RT64::RenderSampleCounts color_sample_counts = ret->device->getSampleCountsSupported(RT64::RenderFormat::R8G8B8A8_UNORM); - RT64::RenderSampleCounts depth_sample_counts = ret->device->getSampleCountsSupported(RT64::RenderFormat::D32_FLOAT); - RT64::RenderSampleCounts common_sample_counts = color_sample_counts & depth_sample_counts; - device_max_msaa = compute_max_supported_aa(common_sample_counts); - sample_positions_supported = true; - } - else { - device_max_msaa = RT64::UserConfiguration::Antialiasing::None; - sample_positions_supported = false; - } - - // Update the config to account for MSAA support. - ultramodern::GraphicsConfig cur_config = ultramodern::get_graphics_config(); - cur_config.msaa_option = std::min(cur_config.msaa_option, device_max_msaa); - ultramodern::set_graphics_config(cur_config); - - // Force gbi depth branches to prevent LODs from kicking in. - ret->enhancementConfig.f3dex.forceBranch = true; - // Scale LODs based on the output resolution. - ret->enhancementConfig.textureLOD.scale = true; - - ret->updateEnhancementConfig(); - - return ret; -} - -void RT64SendDL(uint8_t* rdram, const OSTask* task) { - OSTask task_copy = *task; - task_copy.t.data_ptr &= 0x3FFFFFF; - task_copy.t.ucode &= 0x3FFFFFF; - task_copy.t.ucode_data &= 0x3FFFFFF; - - memcpy(DMEM + 0xFC0, &task_copy, 0x40); - - ProcessDList(); -} - -void RT64UpdateScreen(uint32_t vi_origin) { - VI_ORIGIN_REG = vi_origin; - - UpdateScreen(); -} - -void RT64Shutdown() { - PluginShutdown(); -} - -void RT64UpdateConfig(RT64::Application* application, const ultramodern::GraphicsConfig& old_config, const ultramodern::GraphicsConfig& new_config) { - if (new_config.wm_option != old_config.wm_option) { - application->setFullScreen(new_config.wm_option == ultramodern::WindowMode::Fullscreen); - } - - switch (new_config.res_option) { - default: - case ultramodern::Resolution::Auto: - application->userConfig.resolution = RT64::UserConfiguration::Resolution::WindowIntegerScale; - application->userConfig.downsampleMultiplier = 1; - break; - case ultramodern::Resolution::Original: - application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual; - application->userConfig.resolutionMultiplier = new_config.ds_option; - application->userConfig.downsampleMultiplier = new_config.ds_option; - break; - case ultramodern::Resolution::Original2x: - application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual; - application->userConfig.resolutionMultiplier = 2.0 * new_config.ds_option; - application->userConfig.downsampleMultiplier = new_config.ds_option; - break; - } - - switch (new_config.hr_option) { - default: - case ultramodern::HUDRatioMode::Original: - application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Original; - break; - case ultramodern::HUDRatioMode::Clamp16x9: - application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Manual; - application->userConfig.extAspectTarget = 16.0/9.0; - break; - case ultramodern::HUDRatioMode::Full: - application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Expand; - break; - } - - application->userConfig.aspectRatio = new_config.ar_option; - application->userConfig.antialiasing = new_config.msaa_option; - application->userConfig.refreshRate = new_config.rr_option; - application->userConfig.refreshRateTarget = new_config.rr_manual_value; - - application->updateUserConfig(true); - - if (new_config.msaa_option != old_config.msaa_option) { - application->updateMultisampling(); - } -} - -void RT64EnableInstantPresent(RT64::Application* application) { - // Enable the present early presentation mode for minimal latency. - application->enhancementConfig.presentation.mode = RT64::EnhancementConfiguration::Presentation::Mode::PresentEarly; - - application->updateEnhancementConfig(); -} - -RT64::UserConfiguration::Antialiasing RT64MaxMSAA() { - return device_max_msaa; -} - -bool RT64SamplePositionsSupported() { - return sample_positions_supported; -} - -uint32_t RT64GetDisplayFramerate(RT64::Application* application) { - return application->presentQueue->ext.sharedResources->swapChainRate; -} diff --git a/src/ui/ui_config.cpp b/src/ui/ui_config.cpp index 2cc183d..33eac19 100644 --- a/src/ui/ui_config.cpp +++ b/src/ui/ui_config.cpp @@ -658,10 +658,10 @@ void recomp::set_debug_mode_enabled(bool enabled) { } void recomp::update_supported_options() { - msaa2x_supported = RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA2X; - msaa4x_supported = RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA4X; - msaa8x_supported = RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA8X; - sample_positions_supported = RT64SamplePositionsSupported(); + msaa2x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA2X; + msaa4x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA4X; + msaa8x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA8X; + sample_positions_supported = ultramodern::RT64SamplePositionsSupported(); new_options = ultramodern::get_graphics_config(); diff --git a/src/ui/ui_renderer.cpp b/src/ui/ui_renderer.cpp index 28f8bee..581fe2c 100644 --- a/src/ui/ui_renderer.cpp +++ b/src/ui/ui_renderer.cpp @@ -243,7 +243,7 @@ public: // Create vertex buffer for the screen drawer (full-screen triangle). screen_vertex_buffer_size_ = sizeof(Rml::Vertex) * 3; - screen_vertex_buffer_ = render_context->device->createBuffer(RT64::RenderBufferDesc::UploadBuffer(screen_vertex_buffer_size_)); + screen_vertex_buffer_ = render_context->device->createBuffer(RT64::RenderBufferDesc::VertexBuffer(screen_vertex_buffer_size_, RT64::RenderHeapType::UPLOAD)); Rml::Vertex *vertices = (Rml::Vertex *)(screen_vertex_buffer_->map()); const Rml::Colourb white(255, 255, 255, 255); vertices[0] = Rml::Vertex{ Rml::Vector2f(-1.0f, 1.0f), white, Rml::Vector2f(0.0f, 0.0f) }; diff --git a/ultramodern/events.cpp b/ultramodern/events.cpp index 8b17981..aefe6e9 100644 --- a/ultramodern/events.cpp +++ b/ultramodern/events.cpp @@ -297,14 +297,14 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern ultramodern::GraphicsConfig old_config; - RT64::Application* application = RT64Init(rdram, window_handle, cur_config.load().developer_mode); + ultramodern::RT64Context rt64{rdram, window_handle, cur_config.load().developer_mode}; + + if (!rt64.valid()) { + throw std::runtime_error("Failed to initialize RT64!"); + } // TODO move recomp code out of ultramodern. recomp::update_supported_options(); - - if (application == nullptr) { - throw std::runtime_error("Failed to initialize RT64!"); - } rsp_constants_init(); @@ -320,7 +320,7 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern if (const auto* task_action = std::get_if(&action)) { // Turn on instant present if the game has been started and it hasn't been turned on yet. if (ultramodern::is_game_started() && !enabled_instant_present) { - RT64EnableInstantPresent(application); + rt64.enable_instant_present(); enabled_instant_present = true; } // Tell the game that the RSP completed instantly. This will allow it to queue other task types, but it won't @@ -331,20 +331,20 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern ultramodern::measure_input_latency(); auto rt64_start = std::chrono::high_resolution_clock::now(); - RT64SendDL(rdram, &task_action->task); + rt64.send_dl(&task_action->task); auto rt64_end = std::chrono::high_resolution_clock::now(); dp_complete(); // printf("RT64 ProcessDList time: %d us\n", static_cast(std::chrono::duration_cast(rt64_end - rt64_start).count())); } else if (const auto* swap_action = std::get_if(&action)) { events_context.vi.current_buffer = events_context.vi.next_buffer; - RT64UpdateScreen(swap_action->origin); - display_refresh_rate = RT64GetDisplayFramerate(application); + rt64.update_screen(swap_action->origin); + display_refresh_rate = rt64.get_display_framerate(); } else if (const auto* config_action = std::get_if(&action)) { ultramodern::GraphicsConfig new_config = cur_config; if (old_config != new_config) { - RT64UpdateConfig(application, old_config, new_config); + rt64.update_config(old_config, new_config); old_config = new_config; } } @@ -352,7 +352,7 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern } // TODO move recomp code out of ultramodern. recomp::destroy_ui(); - RT64Shutdown(); + rt64.shutdown(); } extern unsigned int VI_STATUS_REG; diff --git a/ultramodern/rt64_layer.cpp b/ultramodern/rt64_layer.cpp new file mode 100644 index 0000000..ab14d37 --- /dev/null +++ b/ultramodern/rt64_layer.cpp @@ -0,0 +1,237 @@ +#include +#include +// #include + +#define HLSL_CPU +#include "hle/rt64_application.h" +#include "rt64_layer.h" +#include "rt64_render_hooks.h" + +ultramodern::RT64Context::~RT64Context() = default; + +static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None; +static bool sample_positions_supported = false; + +static uint8_t DMEM[0x1000]; +static uint8_t IMEM[0x1000]; + +unsigned int MI_INTR_REG = 0; + +unsigned int DPC_START_REG = 0; +unsigned int DPC_END_REG = 0; +unsigned int DPC_CURRENT_REG = 0; +unsigned int DPC_STATUS_REG = 0; +unsigned int DPC_CLOCK_REG = 0; +unsigned int DPC_BUFBUSY_REG = 0; +unsigned int DPC_PIPEBUSY_REG = 0; +unsigned int DPC_TMEM_REG = 0; + +unsigned int VI_STATUS_REG = 0; +unsigned int VI_ORIGIN_REG = 0; +unsigned int VI_WIDTH_REG = 0; +unsigned int VI_INTR_REG = 0; +unsigned int VI_V_CURRENT_LINE_REG = 0; +unsigned int VI_TIMING_REG = 0; +unsigned int VI_V_SYNC_REG = 0; +unsigned int VI_H_SYNC_REG = 0; +unsigned int VI_LEAP_REG = 0; +unsigned int VI_H_START_REG = 0; +unsigned int VI_V_START_REG = 0; +unsigned int VI_V_BURST_REG = 0; +unsigned int VI_X_SCALE_REG = 0; +unsigned int VI_Y_SCALE_REG = 0; + +void dummy_check_interrupts() { + +} + +RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampleCounts bits) { + if (bits & RT64::RenderSampleCount::Bits::COUNT_2) { + if (bits & RT64::RenderSampleCount::Bits::COUNT_4) { + if (bits & RT64::RenderSampleCount::Bits::COUNT_8) { + return RT64::UserConfiguration::Antialiasing::MSAA8X; + } + return RT64::UserConfiguration::Antialiasing::MSAA4X; + } + return RT64::UserConfiguration::Antialiasing::MSAA2X; + }; + return RT64::UserConfiguration::Antialiasing::None; +} + +void set_application_user_config(RT64::Application* application, const ultramodern::GraphicsConfig& config) { + switch (config.res_option) { + default: + case ultramodern::Resolution::Auto: + application->userConfig.resolution = RT64::UserConfiguration::Resolution::WindowIntegerScale; + application->userConfig.downsampleMultiplier = 1; + break; + case ultramodern::Resolution::Original: + application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual; + application->userConfig.resolutionMultiplier = config.ds_option; + application->userConfig.downsampleMultiplier = config.ds_option; + break; + case ultramodern::Resolution::Original2x: + application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual; + application->userConfig.resolutionMultiplier = 2.0 * config.ds_option; + application->userConfig.downsampleMultiplier = config.ds_option; + break; + } + + switch (config.hr_option) { + default: + case ultramodern::HUDRatioMode::Original: + application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Original; + break; + case ultramodern::HUDRatioMode::Clamp16x9: + application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Manual; + application->userConfig.extAspectTarget = 16.0/9.0; + break; + case ultramodern::HUDRatioMode::Full: + application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Expand; + break; + } + + application->userConfig.aspectRatio = config.ar_option; + application->userConfig.antialiasing = config.msaa_option; + application->userConfig.refreshRate = config.rr_option; + application->userConfig.refreshRateTarget = config.rr_manual_value; +} + +ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool debug) { + static unsigned char dummy_rom_header[0x40]; + set_rt64_hooks(); + + // Set up the RT64 application core fields. + RT64::Application::Core appCore{}; +#if defined(_WIN32) + appCore.window = window_handle.window; +#elif defined(__ANDROID__) + assert(false && "Unimplemented"); +#elif defined(__linux__) + appCore.window.display = window_handle.display; + appCore.window.window = window_handle.window; +#endif + + appCore.checkInterrupts = dummy_check_interrupts; + + appCore.HEADER = dummy_rom_header; + appCore.RDRAM = rdram; + appCore.DMEM = DMEM; + appCore.IMEM = IMEM; + + appCore.MI_INTR_REG = &MI_INTR_REG; + + appCore.DPC_START_REG = &DPC_START_REG; + appCore.DPC_END_REG = &DPC_END_REG; + appCore.DPC_CURRENT_REG = &DPC_CURRENT_REG; + appCore.DPC_STATUS_REG = &DPC_STATUS_REG; + appCore.DPC_CLOCK_REG = &DPC_CLOCK_REG; + appCore.DPC_BUFBUSY_REG = &DPC_BUFBUSY_REG; + appCore.DPC_PIPEBUSY_REG = &DPC_PIPEBUSY_REG; + appCore.DPC_TMEM_REG = &DPC_TMEM_REG; + + appCore.VI_STATUS_REG = &VI_STATUS_REG; + appCore.VI_ORIGIN_REG = &VI_ORIGIN_REG; + appCore.VI_WIDTH_REG = &VI_WIDTH_REG; + appCore.VI_INTR_REG = &VI_INTR_REG; + appCore.VI_V_CURRENT_LINE_REG = &VI_V_CURRENT_LINE_REG; + appCore.VI_TIMING_REG = &VI_TIMING_REG; + appCore.VI_V_SYNC_REG = &VI_V_SYNC_REG; + appCore.VI_H_SYNC_REG = &VI_H_SYNC_REG; + appCore.VI_LEAP_REG = &VI_LEAP_REG; + appCore.VI_H_START_REG = &VI_H_START_REG; + appCore.VI_V_START_REG = &VI_V_START_REG; + appCore.VI_V_BURST_REG = &VI_V_BURST_REG; + appCore.VI_X_SCALE_REG = &VI_X_SCALE_REG; + appCore.VI_Y_SCALE_REG = &VI_Y_SCALE_REG; + + // Set up the RT64 application configuration fields. + RT64::ApplicationConfiguration appConfig; + appConfig.useConfigurationFile = false; + + // Create the RT64 application. + app = std::make_unique(appCore, appConfig); + + // Set initial user config settings based on the current settings. + ultramodern::GraphicsConfig cur_config = ultramodern::get_graphics_config(); + set_application_user_config(app.get(), cur_config); + app->userConfig.developerMode = debug; + // Force gbi depth branches to prevent LODs from kicking in. + app->enhancementConfig.f3dex.forceBranch = true; + // Scale LODs based on the output resolution. + app->enhancementConfig.textureLOD.scale = true; + + // Set up the RT64 application. + if (!app->setup(window_handle.thread_id)) { + app = nullptr; + return; + } + + // Set the application's fullscreen state. + app->setFullScreen(cur_config.wm_option == ultramodern::WindowMode::Fullscreen); + + // Check if the selected device actually supports MSAA sample positions and MSAA for for the formats that will be used + // and downgrade the configuration accordingly. + if (app->device->getCapabilities().sampleLocations) { + RT64::RenderSampleCounts color_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::R8G8B8A8_UNORM); + RT64::RenderSampleCounts depth_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::D32_FLOAT); + RT64::RenderSampleCounts common_sample_counts = color_sample_counts & depth_sample_counts; + device_max_msaa = compute_max_supported_aa(common_sample_counts); + sample_positions_supported = true; + } + else { + device_max_msaa = RT64::UserConfiguration::Antialiasing::None; + sample_positions_supported = false; + } +} + +void ultramodern::RT64Context::send_dl(const OSTask* task) { + app->state->rsp->reset(); + app->interpreter->loadUCodeGBI(task->t.ucode & 0x3FFFFFF, task->t.ucode_data & 0x3FFFFFF, true); + app->processDisplayLists(app->core.RDRAM, task->t.data_ptr & 0x3FFFFFF, 0, true); +} + +void ultramodern::RT64Context::update_screen(uint32_t vi_origin) { + VI_ORIGIN_REG = vi_origin; + + app->updateScreen(); +} + +void ultramodern::RT64Context::shutdown() { + if (app != nullptr) { + app->end(); + } +} + +void ultramodern::RT64Context::update_config(const ultramodern::GraphicsConfig& old_config, const ultramodern::GraphicsConfig& new_config) { + if (new_config.wm_option != old_config.wm_option) { + app->setFullScreen(new_config.wm_option == ultramodern::WindowMode::Fullscreen); + } + + set_application_user_config(app.get(), new_config); + + app->updateUserConfig(true); + + if (new_config.msaa_option != old_config.msaa_option) { + app->updateMultisampling(); + } +} + +void ultramodern::RT64Context::enable_instant_present() { + // Enable the present early presentation mode for minimal latency. + app->enhancementConfig.presentation.mode = RT64::EnhancementConfiguration::Presentation::Mode::PresentEarly; + + app->updateEnhancementConfig(); +} + +uint32_t ultramodern::RT64Context::get_display_framerate() { + return app->presentQueue->ext.sharedResources->swapChainRate; +} + +RT64::UserConfiguration::Antialiasing ultramodern::RT64MaxMSAA() { + return device_max_msaa; +} + +bool ultramodern::RT64SamplePositionsSupported() { + return sample_positions_supported; +}