Merge branch 'Zelda64Recomp:dev' into joystick_deadzone

This commit is contained in:
GabrielCNoble 2024-05-24 17:41:15 -03:00 committed by GitHub
commit 370117910f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 226 additions and 39 deletions

View file

@ -0,0 +1,9 @@
[Desktop Entry]
Name=Zelda64Recompiled
Type=Application
Terminal=false
Icon=Zelda64Recompiled
Exec=Zelda64Recompiled
GenericName=Zelda64Recompiled
Categories=Game;

17
.github/linux/appimage.sh vendored Executable file
View file

@ -0,0 +1,17 @@
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-static-x86_64.AppImage"
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/raw/master/linuxdeploy-plugin-gtk.sh"
chmod a+x linuxdeploy*
mkdir -p AppDir/usr/bin
cp Zelda64Recompiled AppDir/usr/bin/
cp -r assets/ AppDir/usr/bin/
cp icons/512.png AppDir/Zelda64Recompiled.png
cp .github/linux/Zelda64Recompiled.desktop AppDir/
./linuxdeploy-static-x86_64.AppImage --appimage-extract
mv squashfs-root/ deploy
ARCH=x86_64 ./deploy/AppRun --appdir=AppDir/ -d AppDir/Zelda64Recompiled.desktop -i AppDir/Zelda64Recompiled.png -e AppDir/usr/bin/Zelda64Recompiled --plugin gtk
sed -i 's/exec/#exec/g' AppDir/AppRun
echo 'cd "$this_dir"/usr/bin/' >> AppDir/AppRun
echo './Zelda64Recompiled' >> AppDir/AppRun
ARCH=x86_64 ./deploy/usr/bin/linuxdeploy-plugin-appimage --appdir=AppDir

View file

@ -2,14 +2,23 @@ name: validate
on:
push:
branches:
- main
pull_request:
- dev
pull_request_target:
types: [opened, synchronize]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
authorize:
environment:
${{ github.event_name == 'pull_request_target' &&
github.event.pull_request.head.repo.full_name != github.repository &&
'external' || 'internal' }}
runs-on: ubuntu-latest
steps:
- run: echo ✓
build-unix:
needs: authorize
runs-on: ubuntu-22.04
strategy:
matrix:
@ -18,6 +27,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
submodules: recursive
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
@ -27,7 +37,7 @@ jobs:
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y ninja-build libsdl2-dev libgtk-3-dev lld llvm clang-15
sudo apt-get install -y ninja-build libsdl2-dev libgtk-3-dev lld llvm clang-15 libfuse2
# Install SDL2
echo ::group::install SDL2
@ -45,10 +55,8 @@ jobs:
echo ::endgroup::
- name: Prepare Build
run: |-
git clone https://${{ secrets.PAT }}@github.com/dcvz/zre.git
git clone ${{ secrets.ZRE_REPO_WITH_PAT }}
./zre/process.sh
env:
LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}
- name: Build N64Recomp & RSPRecomp
if: runner.os != 'Windows'
run: |
@ -82,14 +90,21 @@ jobs:
run: |
mv cmake-build/Zelda64Recompiled Zelda64Recompiled
rm -rf assets/scss
tar -czf Zelda64Recompiled-${{ runner.os }}-${{ matrix.type }}.tar.gz Zelda64Recompiled assets/
- name: Archive Zelda64Recomp
uses: actions/upload-artifact@v4
with:
name: Zelda64Recompiled-${{ runner.os }}-${{ matrix.type }}
path: |
Zelda64Recompiled
assets/
path: Zelda64Recompiled-${{ runner.os }}-${{ matrix.type }}.tar.gz
- name: Prepare AppImage
run: ./.github/linux/appimage.sh
- name: Zelda64Recomp AppImage
uses: actions/upload-artifact@v4
with:
name: Zelda64Recompiled-AppImage-${{ matrix.type }}
path: Zelda64Recompiled-x86_64.AppImage
build-windows:
needs: authorize
runs-on: windows-latest
strategy:
matrix:
@ -98,6 +113,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
submodules: recursive
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
@ -111,10 +127,8 @@ jobs:
uses: ilammy/msvc-dev-cmd@v1
- name: Prepare Build
run: |-
git clone https://${{ secrets.PAT }}@github.com/dcvz/zre.git
git clone ${{ secrets.ZRE_REPO_WITH_PAT }}
./zre/process.ps1
env:
LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}
- name: Build N64Recomp & RSPRecomp
run: |
git clone https://github.com/Mr-Wiseguy/N64Recomp.git --recurse-submodules N64RecompSource
@ -145,6 +159,9 @@ jobs:
- name: Prepare Archive
run: |
Move-Item -Path "cmake-build/Zelda64Recompiled.exe" -Destination "Zelda64Recompiled.exe"
Move-Item -Path "cmake-build/dxcompiler.dll" -Destination "dxcompiler.dll"
Move-Item -Path "cmake-build/dxil.dll" -Destination "dxil.dll"
Move-Item -Path "cmake-build/SDL2.dll" -Destination "SDL2.dll"
Remove-Item -Path "assets/scss" -Recurse -Force
- name: Archive Zelda64Recomp
uses: actions/upload-artifact@v4
@ -152,4 +169,7 @@ jobs:
name: Zelda64Recompiled-${{ runner.os }}-${{ matrix.type }}
path: |
Zelda64Recompiled.exe
dxcompiler.dll
dxil.dll
SDL2.dll
assets/

3
.gitmodules vendored
View file

@ -13,3 +13,6 @@
[submodule "lib/lunasvg"]
path = lib/lunasvg
url = https://github.com/sammycage/lunasvg
[submodule "lib/sse2neon"]
path = lib/sse2neon
url = https://github.com/DLTcollab/sse2neon.git

View file

@ -74,7 +74,7 @@ Finally, you can build the project! :rocket:
On Windows, you can open the repository folder with Visual Studio, and you'll be able to `[build / run / debug]` the project from there. If you prefer the commandline or you're on a Unix platform you can build the project using CMake:
```bash
cmake -S . -B cmake-build -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -G Ninja -DCMAKE_BUILD_TYPE=Release # or Debug if you want to debug
cmake -S . -B build-cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -G Ninja -DCMAKE_BUILD_TYPE=Release # or Debug if you want to debug
cmake --build build-cmake --target Zelda64Recompiled -j$(nproc) --config Release # or Debug
```

View file

@ -87,11 +87,15 @@ add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/RecompiledPatches/patches_bin.c
DEPENDS ${CMAKE_SOURCE_DIR}/patches/patches.bin
)
# Generate mm_shader_cache.c from the MM shader cache
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.c ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.h
COMMAND file_to_c ${CMAKE_SOURCE_DIR}/shadercache/mm_shader_cache.bin mm_shader_cache_bytes ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.c ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.h
DEPENDS ${CMAKE_SOURCE_DIR}/shadercache/mm_shader_cache.bin
)
# Generate mm_shader_cache.c from the MM shader cache if it exists
if (EXISTS ${CMAKE_SOURCE_DIR}/shadercache/mm_shader_cache.bin)
set(HAS_MM_SHADER_CACHE TRUE)
add_compile_definitions(HAS_MM_SHADER_CACHE)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.c ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.h
COMMAND file_to_c ${CMAKE_SOURCE_DIR}/shadercache/mm_shader_cache.bin mm_shader_cache_bytes ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.c ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.h
DEPENDS ${CMAKE_SOURCE_DIR}/shadercache/mm_shader_cache.bin
)
endif()
# Recompile patches elf into patches.c
add_custom_command(OUTPUT
@ -159,10 +163,12 @@ set (SOURCES
${CMAKE_SOURCE_DIR}/rsp/njpgdspMain.cpp
${CMAKE_SOURCE_DIR}/lib/RmlUi/Backends/RmlUi_Platform_SDL.cpp
${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.c
)
if (HAS_MM_SHADER_CACHE)
list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/mm_shader_cache.c)
endif()
target_include_directories(Zelda64Recompiled PRIVATE
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/lib/concurrentqueue
@ -175,17 +181,25 @@ target_include_directories(Zelda64Recompiled PRIVATE
${CMAKE_SOURCE_DIR}/lib/rt64/src
${CMAKE_SOURCE_DIR}/lib/rt64/src/rhi
${CMAKE_SOURCE_DIR}/lib/rt64/src/render
${CMAKE_SOURCE_DIR}/lib/sse2neon
${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/nativefiledialog-extended/src/include
${CMAKE_BINARY_DIR}/shaders
${CMAKE_CURRENT_BINARY_DIR}
)
target_compile_options(Zelda64Recompiled PRIVATE
-march=nehalem
-fno-strict-aliasing
-fms-extensions
)
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64")
target_compile_options(Zelda64Recompiled PRIVATE
-march=nehalem
-fno-strict-aliasing
-fms-extensions
)
else()
target_compile_options(Zelda64Recompiled PRIVATE
-fno-strict-aliasing
-fms-extensions
)
endif()
if (WIN32)
include(FetchContent)
@ -289,7 +303,19 @@ if (${WIN32})
set (DXC "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc.exe")
add_compile_definitions(NOMINMAX)
else()
set (DXC "LD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/x64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc")
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64")
if (APPLE)
set (DXC "DYLD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/x64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc")
else()
set (DXC "LD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/x64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc")
endif()
else()
if (APPLE)
set (DXC "DYLD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/arm64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/arm64/dxc-macos")
else()
set (DXC "LD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/arm64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/arm64/dxc-linux")
endif()
endif()
endif()
build_vertex_shader(Zelda64Recompiled "shaders/InterfaceVS.hlsl" "shaders/InterfaceVS.hlsl")

View file

@ -1,7 +1,7 @@
# Zelda 64: Recompiled
Zelda 64: Recompiled is a project that uses [N64: Recompiled](https://github.com/Mr-Wiseguy/N64Recomp) to **statically recompile** Majora's Mask (and soon Ocarina of Time) into a native port with many new features and enhancements. This project uses [RT64](https://github.com/rt64/rt64) as the rendering engine to provide some of these enhancements.
### [Check out the latest release here](https://github.com/Mr-Wiseguy/Zelda64Recomp/releases/tag/v1.0.0).
### [Check out the latest release here](https://github.com/Mr-Wiseguy/Zelda64Recomp/releases/latest).
### **This repository and its releases do not contain game assets. The original game is required to build or run this project.**
@ -102,6 +102,11 @@ You'll probably also want to change the default behavior so that you don't need
- Windows: `%LOCALAPPDATA%\Zelda64Recompiled\saves`
- Linux: `~/.config/Zelda64Recompiled/saves`
#### How do I choose a different ROM?
**You don't.** This project is **only** a port of Majora's Mask (and Ocarina of Time in the future), and it will only accept one specific ROM: the US version of the N64 release of Majora's Mask. ROMs in formats other than .z64 will be automatically converted, as long as it is the correct ROM. **It is not an emulator and it cannot run any arbitrary ROM.**
If you want to play a modded ROM or in another language, note that support for modding and other languages will be added to the project itself in the future and will not rely on you supplying a different ROM.
## Known Issues
* The motion blur effect used by the game was capped to prevent ghosting at incredibly high framerates, which causes it to be less noticeable (this is only really noticeable above 120FPS). This may be fixed in the future by offering the option to render to an HDR framebuffer internally, which would allow it to be uncapped.
* Intel GPUs on Linux may not currently work. If you have experience with Vulkan development on Linux, help here would be greatly appreciated!

View file

@ -8,6 +8,7 @@
namespace recomp {
constexpr std::u8string_view program_id = u8"Zelda64Recompiled";
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 save_config();

View file

@ -20,14 +20,13 @@
// ----------------------------------------------------------------------
#include <cstdint>
#define ARCHITECTURE_AMD64
#if defined(__x86_64__) || defined(_M_X64)
#define ARCHITECTURE_SUPPORTS_SSE4_1 1
#if defined(ARCHITECTURE_AMD64)
#include <nmmintrin.h>
using v128 = __m128i;
#elif defined(ARCHITECTURE_ARM64)
#include <sse2neon.h>
#elif defined(__aarch64__) || defined(_M_ARM64)
#define ARCHITECTURE_SUPPORTS_SSE4_1 1
#include "sse2neon.h"
using v128 = __m128i;
#endif

View file

@ -9,12 +9,21 @@ namespace RT64 {
}
namespace ultramodern {
enum class RT64SetupResult {
Success,
DynamicLibrariesNotFound,
InvalidGraphicsAPI,
GraphicsAPINotFound,
GraphicsDeviceNotFound
};
struct WindowHandle;
struct RT64Context {
public:
~RT64Context();
RT64Context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode);
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 enable_instant_present();
@ -25,6 +34,7 @@ namespace ultramodern {
uint32_t get_display_framerate();
void load_shader_cache(std::span<const char> cache_binary);
private:
RT64SetupResult setup_result;
std::unique_ptr<RT64::Application> app;
};

@ -1 +1 @@
Subproject commit ecdd609c49fb5f10e3040335901d8860ef259f67
Subproject commit 1dd801264dbbf7a2f4e8fc483d28664852f50082

1
lib/sse2neon Submodule

@ -0,0 +1 @@
Subproject commit 42c704755d3ec218ed9126a122f0a667beeb630a

View file

@ -70,7 +70,18 @@ void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages);
void autosave_reset_timer();
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;
gSaveContext.save.isOwlSave = SAVE_TYPE_AUTOSAVE;
@ -78,6 +89,7 @@ void do_autosave(SramContext* sramCtx) {
gSaveContext.save.saveInfo.checksum = 0;
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.
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum));
// 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 &&
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();
autosave_reset_timer();
}

0
shadercache/.gitkeep Normal file
View file

Binary file not shown.

View file

@ -51,6 +51,11 @@ ultramodern::gfx_callbacks_t::gfx_data_t create_gfx() {
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
#if defined(__linux__)
SDL_SetHint(SDL_HINT_VIDEODRIVER, "x11");
#endif
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) > 0) {
exit_error("Failed to initialize SDL2: %s\n", SDL_GetError());
}
@ -133,6 +138,10 @@ ultramodern::WindowHandle create_window(ultramodern::gfx_callbacks_t::gfx_data_t
#elif defined(__ANDROID__)
static_assert(false && "Unimplemented");
#elif defined(__linux__)
if (wmInfo.subsystem != SDL_SYSWM_X11) {
exit_error("Unsupported SDL2 video driver \"%s\". Only X11 is supported on Linux.\n", SDL_GetCurrentVideoDriver());
}
return ultramodern::WindowHandle{ wmInfo.info.x11.display, wmInfo.info.x11.window };
#else
static_assert(false && "Unimplemented");

View file

@ -17,7 +17,9 @@
#include "xxHash/xxh3.h"
#include "../ultramodern/ultramodern.hpp"
#include "../../RecompiledPatches/patches_bin.h"
#ifdef HAS_MM_SHADER_CACHE
#include "mm_shader_cache.h"
#endif
#ifdef _MSC_VER
inline uint32_t byteswap(uint32_t val) {
@ -411,7 +413,11 @@ void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::a
if (!recomp::load_stored_rom(recomp::Game::MM)) {
recomp::message_box("Error opening stored ROM! Please restart this program.");
}
#ifdef HAS_MM_SHADER_CACHE
ultramodern::load_shader_cache({mm_shader_cache_bytes, sizeof(mm_shader_cache_bytes)});
#endif
init(rdram, &context);
try {
recomp_entrypoint(rdram, &context);

View file

@ -6,7 +6,7 @@
#include "nfd.h"
#include <filesystem>
std::string version_number = "v1.0.0";
std::string version_number = "v1.0.1";
Rml::DataModelHandle model_handle;
bool mm_rom_valid = false;

View file

@ -8,6 +8,7 @@
#include "recomp_ui.h"
#include "recomp_input.h"
#include "recomp_game.h"
#include "recomp_config.h"
#include "ui_rml_hacks.hpp"
#include "concurrentqueue.h"
@ -1464,5 +1465,5 @@ recomp::Menu recomp::get_current_menu() {
}
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);
}

View file

@ -16,6 +16,7 @@
#include "config.hpp"
#include "rt64_layer.h"
#include "recomp.h"
#include "recomp_game.h"
#include "recomp_ui.h"
#include "recomp_input.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});
}
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) {
bool enabled_instant_present = false;
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};
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.
@ -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);
}
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) {
moodycamel::LightweightSemaphore gfx_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();
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 };
}

View file

@ -97,6 +97,21 @@ void set_application_user_config(RT64::Application* application, const ultramode
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) {
static unsigned char dummy_rom_header[0x40];
set_rt64_hooks();
@ -179,7 +194,8 @@ ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle
#ifdef _WIN32
thread_id = window_handle.thread_id;
#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;
return;
}