Compare commits

..

No commits in common. "master" and "v0.9" have entirely different histories.
master ... v0.9

89 changed files with 573 additions and 3848 deletions

22
.github/gles.patch vendored
View file

@ -1,3 +1,25 @@
diff --git a/src/host_shaders/opengl_display.frag b/src/host_shaders/opengl_display.frag
index 612671c8..1937f711 100644
--- a/src/host_shaders/opengl_display.frag
+++ b/src/host_shaders/opengl_display.frag
@@ -1,4 +1,5 @@
-#version 410 core
+#version 300 es
+precision mediump float;
in vec2 UV;
out vec4 FragColor;
diff --git a/src/host_shaders/opengl_display.vert b/src/host_shaders/opengl_display.vert
index 990e2f80..2e7842ac 100644
--- a/src/host_shaders/opengl_display.vert
+++ b/src/host_shaders/opengl_display.vert
@@ -1,4 +1,5 @@
-#version 410 core
+#version 300 es
+precision mediump float;
out vec2 UV;
void main() {
diff --git a/src/host_shaders/opengl_fragment_shader.frag b/src/host_shaders/opengl_fragment_shader.frag
index 9f07df0b..96a35afa 100644
--- a/src/host_shaders/opengl_fragment_shader.frag

View file

@ -23,9 +23,6 @@ jobs:
- name: Fetch submodules
run: git submodule update --init --recursive
- name: Setup CCache
uses: hendrikmuhs/ccache-action@v1.2
- name: Set up gradle caches
uses: actions/cache@v4
with:
@ -37,9 +34,9 @@ jobs:
${{ runner.os }}-pandroid-x86_64-
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -50,7 +47,7 @@ jobs:
java-version: '17'
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DBUILD_HYDRA_CORE=1 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake -DANDROID_ABI=x86_64 -DENABLE_VULKAN=0 -DENABLE_USER_BUILD=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
run: cmake -B ${{github.workspace}}/build -DBUILD_HYDRA_CORE=1 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake -DANDROID_ABI=x86_64 -DENABLE_VULKAN=0 -DENABLE_USER_BUILD=ON
- name: Build
run: |
@ -91,9 +88,6 @@ jobs:
- name: Fetch submodules
run: git submodule update --init --recursive
- name: Setup CCache
uses: hendrikmuhs/ccache-action@v1.2
- name: Set up gradle caches
uses: actions/cache@v4
with:
@ -105,9 +99,9 @@ jobs:
${{ runner.os }}-pandroid-arm64-
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -118,7 +112,7 @@ jobs:
java-version: '17'
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DBUILD_HYDRA_CORE=1 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DENABLE_VULKAN=0 -DENABLE_USER_BUILD=ON -DCMAKE_CXX_FLAGS="-march=armv8-a+crypto" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
run: cmake -B ${{github.workspace}}/build -DBUILD_HYDRA_CORE=1 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DENABLE_VULKAN=0 -DENABLE_USER_BUILD=ON -DCMAKE_CXX_FLAGS="-march=armv8-a+crypto"
- name: Build
run: |

View file

@ -30,9 +30,9 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang

View file

@ -20,9 +20,9 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -63,9 +63,9 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -116,9 +116,9 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -163,9 +163,9 @@ jobs:
sudo apt-get update && sudo apt install libx11-dev libgl1 libglx-mesa0 mesa-common-dev libfuse2 libwayland-dev
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -180,36 +180,3 @@ jobs:
with:
name: Android Hydra core
path: '${{github.workspace}}/build/libAlber.so'
ARM-Libretro:
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- name: Fetch submodules
run: git submodule update --init --recursive
- name: Install misc packages
run: |
sudo apt-get update && sudo apt install libx11-dev libxext-dev libgl1 libglx-mesa0 mesa-common-dev libfuse2 libwayland-dev
- name: Install newer Clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Configure CMake
run: |
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DENABLE_USER_BUILD=ON -DBUILD_LIBRETRO_CORE=ON -DENABLE_VULKAN=OFF -DCRYPTOPP_OPT_DISABLE_ASM=ON
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Upload Libretro core
uses: actions/upload-artifact@v4
with:
name: Linux arm64 Libretro core
path: |
${{github.workspace}}/build/panda3ds_libretro.so
${{github.workspace}}/docs/libretro/panda3ds_libretro.info

View file

@ -33,9 +33,9 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang

View file

@ -33,9 +33,9 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang

View file

@ -25,9 +25,9 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang

View file

@ -26,9 +26,9 @@ jobs:
version: 6.2.0
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -64,9 +64,9 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
@ -162,9 +162,9 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang

View file

@ -24,9 +24,9 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: 1.3.296.0
vulkan-query-version: latest
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang

View file

@ -1,39 +0,0 @@
name: iOS Simulator Build
on:
push:
branches:
- master
pull_request:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Fetch submodules
run: git submodule update --init --recursive
- name: Update Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: 1.3.296.0
vulkan-use-cache: true
vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
- name: Build core and frontend
run: cd src/pandios && ./build.sh

7
.gitmodules vendored
View file

@ -1,6 +1,9 @@
[submodule "third_party/elfio"]
path = third_party/elfio
url = https://github.com/serge1/ELFIO
[submodule "third_party/SDL2"]
path = third_party/SDL2
url = https://github.com/libsdl-org/SDL
[submodule "third_party/cryptopp/cryptopp"]
path = third_party/cryptopp/cryptopp
url = https://github.com/weidai11/cryptopp
@ -82,7 +85,3 @@
[submodule "third_party/oaknut"]
path = third_party/oaknut
url = https://github.com/panda3ds-emu/oaknut
[submodule "third_party/SDL2"]
path = third_party/SDL2
url = https://github.com/libsdl-org/SDL
branch = SDL2

View file

@ -50,7 +50,6 @@ option(GPU_DEBUG_INFO "Enable additional GPU debugging info" OFF)
option(ENABLE_OPENGL "Enable OpenGL rendering backend" ON)
option(ENABLE_VULKAN "Enable Vulkan rendering backend" ON)
option(ENABLE_METAL "Enable Metal rendering backend (if available)" ON)
option(ENABLE_WAYLAND "Enable Wayland support on Linux platforms" ON)
option(ENABLE_LTO "Enable link-time optimization" OFF)
option(ENABLE_TESTS "Compile unit-tests" OFF)
option(ENABLE_USER_BUILD "Make a user-facing build. These builds have various assertions disabled, LTO, and more" OFF)
@ -64,14 +63,6 @@ option(BUILD_HYDRA_CORE "Build a Hydra core" OFF)
option(BUILD_LIBRETRO_CORE "Build a Libretro core" OFF)
option(ENABLE_RENDERDOC_API "Build with support for Renderdoc's capture API for graphics debugging" ON)
option(DISABLE_SSE4 "Build with SSE4 instructions disabled, may reduce performance" OFF)
option(USE_LIBRETRO_AUDIO "Enable to use the LR audio device with the LR core. Otherwise our own device is used" OFF)
option(IOS_SIMULATOR_BUILD "Compiling for IOS simulator (Set to off if compiling for a real iPhone)" ON)
# Discord RPC & LuaJIT are currently not supported on iOS
if(IOS)
set(ENABLE_DISCORD_RPC OFF)
set(ENABLE_LUAJIT OFF)
endif()
set(OPENGL_PROFILE ${DEFAULT_OPENGL_PROFILE} CACHE STRING "OpenGL profile to use if OpenGL is enabled. Valid values are 'OpenGL' and 'OpenGLES'.")
set_property(CACHE OPENGL_PROFILE PROPERTY STRINGS OpenGL OpenGLES)
@ -88,10 +79,6 @@ endif()
if(BUILD_LIBRETRO_CORE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_definitions(__LIBRETRO__)
if(USE_LIBRETRO_AUDIO)
add_compile_definitions(USE_LIBRETRO_AUDIO_DEVICE)
endif()
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND ENABLE_USER_BUILD)
@ -110,29 +97,22 @@ endif()
if(GIT_FOUND AND ENABLE_GIT_VERSIONING)
execute_process(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
OUTPUT_VARIABLE git_version_tag OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE PANDA3DS_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
OUTPUT_VARIABLE git_version_rev OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags
OUTPUT_VARIABLE git_version_tag OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT git_version_tag STREQUAL "")
set(PANDA3DS_VERSION "${git_version_tag}")
execute_process(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags
OUTPUT_VARIABLE git_version_desc OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(git_version_tag STREQUAL git_version_desc)
set(git_version_rev "")
endif()
unset(git_version_desc)
endif()
if(NOT git_version_rev STREQUAL "")
set(PANDA3DS_VERSION "${PANDA3DS_VERSION}.${git_version_rev}")
if(NOT PANDA3DS_VERSION STREQUAL git_version_tag)
execute_process(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --always --abbrev=7
OUTPUT_VARIABLE git_version_rev OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(PANDA3DS_VERSION "${PANDA3DS_VERSION}.${git_version_rev}")
unset(git_version_rev)
endif()
string(REGEX REPLACE "^v" "" PANDA3DS_VERSION "${PANDA3DS_VERSION}")
unset(git_version_tag)
unset(git_version_rev)
endif()
configure_file(${CMAKE_BINARY_DIR}/include/version.hpp.in ${CMAKE_BINARY_DIR}/include/version.hpp)
include_directories(${CMAKE_BINARY_DIR}/include/)
@ -160,15 +140,12 @@ add_compile_definitions(NOMINMAX) # Make windows.h not define min/ma
add_compile_definitions(WIN32_LEAN_AND_MEAN) # Make windows.h not include literally everything
add_compile_definitions(SDL_MAIN_HANDLED)
if(ENABLE_WAYLAND)
add_compile_definitions(WAYLAND_ENABLED)
endif()
if(ENABLE_DISCORD_RPC AND NOT ANDROID)
add_subdirectory(third_party/discord-rpc)
include_directories(third_party/discord-rpc/include)
endif()
if (NOT ANDROID)
if (USE_SYSTEM_SDL2)
find_package(SDL2 CONFIG REQUIRED)
@ -327,8 +304,8 @@ set(SOURCE_FILES src/emulator.cpp src/io_file.cpp src/config.cpp
src/core/CPU/cpu_dynarmic.cpp src/core/CPU/dynarmic_cycles.cpp
src/core/memory.cpp src/renderer.cpp src/core/renderer_null/renderer_null.cpp
src/http_server.cpp src/stb_image_write.c src/core/cheats.cpp src/core/action_replay.cpp
src/discord_rpc.cpp src/lua.cpp src/memory_mapped_file.cpp src/renderdoc.cpp
src/frontend_settings.cpp src/miniaudio/miniaudio.cpp
src/discord_rpc.cpp src/lua.cpp src/memory_mapped_file.cpp src/miniaudio.cpp src/renderdoc.cpp
src/frontend_settings.cpp
)
set(CRYPTO_SOURCE_FILES src/core/crypto/aes_engine.cpp)
set(KERNEL_SOURCE_FILES src/core/kernel/kernel.cpp src/core/kernel/resource_limits.cpp
@ -413,19 +390,9 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp
include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp
include/services/dsp_firmware_db.hpp include/frontend_settings.hpp include/fs/archive_twl_photo.hpp
include/fs/archive_twl_sound.hpp include/fs/archive_card_spi.hpp include/services/ns.hpp include/audio/audio_device.hpp
include/audio/audio_device_interface.hpp include/audio/libretro_audio_device.hpp
include/fs/archive_twl_sound.hpp include/fs/archive_card_spi.hpp include/services/ns.hpp
)
if(IOS)
set(SOURCE_FILES ${SOURCE_FILES} src/miniaudio/miniaudio.m)
target_compile_definitions(AlberCore PUBLIC "PANDA3DS_IOS=1")
if (IOS_SIMULATOR_BUILD)
target_compile_definitions(AlberCore PUBLIC "PANDA3DS_IOS_SIMULATOR=1")
endif()
endif()
cmrc_add_resource_library(
resources_console_fonts
NAMESPACE ConsoleFonts
@ -455,22 +422,16 @@ if(ENABLE_LUAJIT AND NOT ANDROID)
target_link_libraries(AlberCore PRIVATE uv_a)
endif()
set(GL_CONTEXT_SOURCE_FILES "")
if(ENABLE_QT_GUI)
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/window_info.cpp third_party/duckstation/gl/context.cpp)
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/window_info.cpp third_party/duckstation/gl/context.cpp)
if(APPLE)
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_agl.mm)
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_agl.mm)
elseif(WIN32)
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_wgl.cpp)
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_wgl.cpp)
else()
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_egl.cpp third_party/duckstation/gl/context_egl_x11.cpp
third_party/duckstation/gl/context_glx.cpp third_party/duckstation/gl/x11_window.cpp)
if(ENABLE_WAYLAND)
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_egl_wayland.cpp)
endif()
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_egl.cpp third_party/duckstation/gl/context_egl_wayland.cpp
third_party/duckstation/gl/context_egl_x11.cpp third_party/duckstation/gl/context_glx.cpp third_party/duckstation/gl/x11_window.cpp)
endif()
endif()
@ -484,7 +445,7 @@ source_group("Source Files\\Core\\Applets" FILES ${APPLET_SOURCE_FILES})
source_group("Source Files\\Core\\PICA" FILES ${PICA_SOURCE_FILES})
source_group("Source Files\\Core\\Audio" FILES ${AUDIO_SOURCE_FILES})
source_group("Source Files\\Core\\Software Renderer" FILES ${RENDERER_SW_SOURCE_FILES})
source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES} ${GL_CONTEXT_SOURCE_FILES})
source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES})
set(RENDERER_GL_SOURCE_FILES "") # Empty by default unless we are compiling with the GL renderer
set(RENDERER_VK_SOURCE_FILES "") # Empty by default unless we are compiling with the VK renderer
@ -499,9 +460,8 @@ if(ENABLE_OPENGL)
set(RENDERER_GL_SOURCE_FILES src/core/renderer_gl/renderer_gl.cpp
src/core/renderer_gl/textures.cpp src/core/renderer_gl/etc1.cpp
src/core/renderer_gl/gl_state.cpp src/host_shaders/opengl_display.vert
src/host_shaders/opengl_display.frag src/host_shaders/opengl_es_display.vert
src/host_shaders/opengl_es_display.frag src/host_shaders/opengl_vertex_shader.vert
src/core/renderer_gl/gl_state.cpp src/host_shaders/opengl_display.frag
src/host_shaders/opengl_display.vert src/host_shaders/opengl_vertex_shader.vert
src/host_shaders/opengl_fragment_shader.frag
)
@ -514,10 +474,8 @@ if(ENABLE_OPENGL)
resources_renderer_gl
NAMESPACE RendererGL
WHENCE "src/host_shaders/"
"src/host_shaders/opengl_display.vert"
"src/host_shaders/opengl_display.frag"
"src/host_shaders/opengl_es_display.vert"
"src/host_shaders/opengl_es_display.frag"
"src/host_shaders/opengl_display.vert"
"src/host_shaders/opengl_vertex_shader.vert"
"src/host_shaders/opengl_fragment_shader.frag"
)
@ -604,16 +562,14 @@ if(ENABLE_METAL AND APPLE)
include/renderer_mtl/mtl_common.hpp
include/renderer_mtl/pica_to_mtl.hpp
include/renderer_mtl/objc_helper.hpp
include/renderer_mtl/texture_decoder.hpp
)
set(RENDERER_MTL_SOURCE_FILES src/core/renderer_mtl/metal_cpp_impl.cpp
src/core/renderer_mtl/renderer_mtl.cpp
src/core/renderer_mtl/mtl_texture.cpp
src/core/renderer_mtl/mtl_etc1.cpp
src/core/renderer_mtl/mtl_lut_texture.cpp
src/core/renderer_mtl/pica_to_mtl.cpp
src/core/renderer_mtl/objc_helper.mm
src/core/renderer_mtl/texture_decoder.cpp
src/host_shaders/metal_shaders.metal
src/host_shaders/metal_blit.metal
#src/host_shaders/metal_copy_to_lut_texture.metal
@ -627,26 +583,15 @@ if(ENABLE_METAL AND APPLE)
set(SHADER_SOURCE "${CMAKE_SOURCE_DIR}/src/host_shaders/${SHADER}.metal")
set(SHADER_IR "${CMAKE_SOURCE_DIR}/src/host_shaders/${SHADER}.ir")
set(SHADER_METALLIB "${CMAKE_SOURCE_DIR}/src/host_shaders/${SHADER}.metallib")
# MacOS, iOS and the iOS simulator all use different compilation options for shaders
set(MetalSDK "macosx")
if(IOS)
if (IOS_SIMULATOR_BUILD)
set(MetalSDK "iphonesimulator")
else()
set(MetalSDK "iphoneos")
endif()
endif()
# TODO: only include sources in debug builds
add_custom_command(
OUTPUT ${SHADER_IR}
COMMAND xcrun -sdk ${MetalSDK} metal -gline-tables-only -frecord-sources -o ${SHADER_IR} -c ${SHADER_SOURCE}
COMMAND xcrun -sdk macosx metal -gline-tables-only -frecord-sources -o ${SHADER_IR} -c ${SHADER_SOURCE}
DEPENDS ${SHADER_SOURCE}
VERBATIM)
add_custom_command(
OUTPUT ${SHADER_METALLIB}
COMMAND xcrun -sdk ${MetalSDK} metallib -o ${SHADER_METALLIB} ${SHADER_IR}
COMMAND xcrun -sdk macosx metallib -o ${SHADER_METALLIB} ${SHADER_IR}
DEPENDS ${SHADER_IR}
VERBATIM)
set(RENDERER_MTL_HOST_SHADERS_SOURCES ${RENDERER_MTL_HOST_SHADERS_SOURCES} ${SHADER_METALLIB})
@ -675,7 +620,7 @@ if(ENABLE_METAL AND APPLE)
target_compile_definitions(AlberCore PUBLIC "PANDA3DS_ENABLE_METAL=1")
target_include_directories(AlberCore PRIVATE third_party/metal-cpp)
# TODO: check if all of them are needed
target_link_libraries(AlberCore PUBLIC "-framework Metal" "-framework Foundation" "-framework QuartzCore" resources_renderer_mtl)
target_link_libraries(AlberCore PRIVATE "-framework Metal" "-framework Foundation" "-framework QuartzCore" resources_renderer_mtl)
endif()
source_group("Header Files\\Core" FILES ${HEADER_FILES})
@ -781,14 +726,11 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE)
docs/img/rsob_icon.png docs/img/rstarstruck_icon.png docs/img/rpog_icon.png docs/img/rsyn_icon.png
docs/img/settings_icon.png docs/img/display_icon.png docs/img/speaker_icon.png
docs/img/sparkling_icon.png docs/img/battery_icon.png docs/img/sdcard_icon.png
docs/img/rnap_icon.png docs/img/rcow_icon.png docs/img/skyemu_icon.png docs/img/runpog_icon.png
docs/img/rnap_icon.png docs/img/rcow_icon.png docs/img/skyemu_icon.png
)
# Translation files in Qt's .ts format. Will be converted into binary files and embedded into the executable
set(TRANSLATIONS_TS docs/translations/en.ts docs/translations/el.ts docs/translations/es.ts docs/translations/pt_br.ts docs/translations/nl.ts
docs/translations/sv.ts
)
set(TRANSLATIONS_TS docs/translations/en.ts docs/translations/el.ts docs/translations/es.ts docs/translations/pt_br.ts docs/translations/nl.ts)
set_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS})
@ -809,17 +751,11 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE)
endif()
target_link_libraries(Alber PRIVATE AlberCore)
target_sources(Alber PRIVATE ${FRONTEND_SOURCE_FILES} ${FRONTEND_HEADER_FILES} ${GL_CONTEXT_SOURCE_FILES} ${APP_RESOURCES})
target_sources(Alber PRIVATE ${FRONTEND_SOURCE_FILES} ${FRONTEND_HEADER_FILES} ${APP_RESOURCES})
elseif(BUILD_HYDRA_CORE)
target_compile_definitions(AlberCore PRIVATE PANDA3DS_HYDRA_CORE=1)
include_directories(third_party/hydra_core/include)
set(SHARED_SOURCE_FILES src/hydra_core.cpp)
if(IOS)
set(SHARED_SOURCE_FILES ${SHARED_SOURCE_FILES} src/ios_driver.mm)
endif()
add_library(Alber SHARED ${SHARED_SOURCE_FILES})
add_library(Alber SHARED src/hydra_core.cpp)
target_link_libraries(Alber PUBLIC AlberCore)
elseif(BUILD_LIBRETRO_CORE)
include_directories(third_party/libretro/include)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -1,774 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="sv_SE">
<extra-po-header-language>sv</extra-po-header-language>
<extra-po-header-language_team></extra-po-header-language_team>
<extra-po-header-last_translator>Daniel Nylander &lt;github@danielnylander.se&gt;</extra-po-header-last_translator>
<extra-po-header-po_revision_date></extra-po-header-po_revision_date>
<extra-po-header-pot_creation_date></extra-po-header-pot_creation_date>
<extra-po-header-project_id_version></extra-po-header-project_id_version>
<extra-po-header-x_generator>Poedit 3.5</extra-po-header-x_generator>
<extra-po-headers>Project-Id-Version,POT-Creation-Date,PO-Revision-Date,Last-Translator,Language-Team,Language,MIME-Version,Content-Type,Content-Transfer-Encoding,X-Qt-Contexts,X-Generator</extra-po-headers>
<context>
<name>AboutWindow</name>
<message>
<location filename="../../src/panda_qt/about_window.cpp" line="16"/>
<source>About Panda3DS</source>
<translation>Om Panda3DS</translation>
</message>
<message>
<location filename="../../src/panda_qt/about_window.cpp" line="35"/>
<source>Panda3DS is a free and open source Nintendo 3DS emulator, for Windows, MacOS and Linux</source>
<translation>Panda3DS är en Nintendo 3DS-emulator med fri och öppen källkod för Windows, MacOS och Linux</translation>
</message>
<message>
<location filename="../../src/panda_qt/about_window.cpp" line="36"/>
<source>Visit panda3ds.com for help with Panda3DS and links to our official support sites.</source>
<translation>Besök panda3ds.com för att hjälp med Panda3DS och länkar till våra officiella supportwebbplatser.</translation>
</message>
<message>
<location filename="../../src/panda_qt/about_window.cpp" line="38"/>
<source>Panda3DS is developed by volunteers in their spare time. Below is a list of some of these volunteers who&apos;ve agreed to be listed here, in no particular order.&lt;br&gt;If you think you should be listed here too, please inform us&lt;br&gt;&lt;br&gt;- Peach (wheremyfoodat)&lt;br&gt;- noumidev&lt;br&gt;- liuk707&lt;br&gt;- Wunk&lt;br&gt;- marysaka&lt;br&gt;- Sky&lt;br&gt;- merryhime&lt;br&gt;- TGP17&lt;br&gt;- Shadow&lt;br&gt;</source>
<translation>Panda3DS utvecklas av volontärer deras fritid. Nedan finns en lista över några av dessa volontärer som har gått med att listas här, utan någon särskild ordning.&lt;br&gt;Om du tycker att du också borde listas här, informera oss&lt;br&gt;&lt;br&gt;- Peach (wheremyfoodat)&lt;br&gt;- noumidev&lt;br&gt;- liuk707&lt;br&gt;- Wunk&lt;br&gt;- marysaka&lt;br&gt;- Sky&lt;br&gt;- merryhime&lt;br&gt;- TGP17&lt;br&gt;- Shadow&lt;br&gt;</translation>
</message>
</context>
<context>
<name>CheatEditDialog</name>
<message>
<location filename="../../src/panda_qt/cheats_window.cpp" line="72"/>
<source>Edit Cheat</source>
<translation>Redigera fusk</translation>
</message>
<message>
<location filename="../../src/panda_qt/cheats_window.cpp" line="82"/>
<source>Cheat name</source>
<translation>Fusknamn</translation>
</message>
</context>
<context>
<name>CheatEntryWidget</name>
<message>
<location filename="../../src/panda_qt/cheats_window.cpp" line="34"/>
<source>Edit</source>
<translation>Redigera</translation>
</message>
</context>
<context>
<name>CheatsWindow</name>
<message>
<location filename="../../src/panda_qt/cheats_window.cpp" line="164"/>
<source>Cheats</source>
<translation>Fusk</translation>
</message>
<message>
<location filename="../../src/panda_qt/cheats_window.cpp" line="177"/>
<source>Add</source>
<translation>Lägg till</translation>
</message>
<message>
<location filename="../../src/panda_qt/cheats_window.cpp" line="178"/>
<source>Remove</source>
<translation>Ta bort</translation>
</message>
</context>
<context>
<name>ConfigWindow</name>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="7"/>
<source>Configuration</source>
<translation>Konfiguration</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="63"/>
<source>Interface Settings</source>
<translation>Inställningar för gränssnitt</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="69"/>
<source>System</source>
<translation>System</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="70"/>
<source>Light</source>
<translation>Ljus</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="71"/>
<source>Dark</source>
<translation>Mörk</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="72"/>
<source>Greetings Cat</source>
<translation>Hälsningskatt</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="73"/>
<source>Cream</source>
<translation>Grädde</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="81"/>
<source>Color theme</source>
<translation>Färgtema</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="84"/>
<source>Happy panda</source>
<translation>Glad panda</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="85"/>
<source>Happy panda (colourful)</source>
<translation>Glad panda (färgglad)</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="86"/>
<source>Sleepy panda</source>
<translation>Sömnig panda</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="87"/>
<source>Cow panda</source>
<translation>Ko-panda</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="88"/>
<source>The penguin from SkyEmu</source>
<translation>Pingvinen från SkyEmu</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="97"/>
<source>Window icon</source>
<translation>Fönsterikon</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="100"/>
<source>Language</source>
<translation>Språk</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="102"/>
<source>Show version on window title</source>
<translation>Visa version fönstertitel</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="15"/>
<location filename="../../src/panda_qt/config_window.cpp" line="109"/>
<source>Alber v%1</source>
<translation>Alber v%1</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="109"/>
<source>Alber</source>
<translation>Alber</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="114"/>
<source>Remember window position</source>
<translation>Kom ihåg fönstrets position</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="119"/>
<source>General Settings</source>
<translation>Allmänna inställningar</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="130"/>
<source>Browse...</source>
<translation>Bläddra...</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="134"/>
<source>Select Directory</source>
<translation>Välj katalog</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="146"/>
<source>Default ROMs path</source>
<translation>Standardsökväg för ROMar</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="148"/>
<source>Enable Discord RPC</source>
<translation>Aktivera Discord RPC</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="152"/>
<source>Use portable build</source>
<translation>Använd portabelt bygge</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="156"/>
<source>Print version in console output</source>
<translation>Skriv ut versionen i konsolutmatningen</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="161"/>
<source>Graphics Settings</source>
<translation>Grafikinställningar</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="167"/>
<location filename="../../src/panda_qt/config_window.cpp" line="221"/>
<source>Null</source>
<translation>Null</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="168"/>
<source>OpenGL</source>
<translation>OpenGL</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="169"/>
<source>Vulkan</source>
<translation>Vulkan</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="175"/>
<source>GPU renderer</source>
<translation>GPU-rendering</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="177"/>
<source>Enable Renderdoc</source>
<translation>Aktivera Renderdoc</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="181"/>
<source>Enable shader JIT</source>
<translation>Aktivera shader JIT</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="185"/>
<source>Enable VSync</source>
<translation>Aktivera VSync</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="189"/>
<source>Use ubershaders (No stutter, maybe slower)</source>
<translation>Använda ubershaders (inga hackningar, kanske långsammare)</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="193"/>
<source>Accurate shader multiplication</source>
<translation>Korrekt multiplicering av shaders</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="197"/>
<source>Accelerate shaders</source>
<translation>Snabbare shaders</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="201"/>
<source>Force shadergen when rendering lights</source>
<translation>Tvinga fram shadergen vid rendering av ljus</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="212"/>
<source>Light threshold for forcing shadergen</source>
<translation>Ljuströskel för att tvinga shadergen</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="215"/>
<source>Audio Settings</source>
<translation>Ljudinställningar</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="222"/>
<source>LLE</source>
<translation>LLE</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="223"/>
<source>HLE</source>
<translation>HLE</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="229"/>
<source>DSP emulation</source>
<translation>DSP-emulering</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="231"/>
<source>Enable audio</source>
<translation>Aktivera ljud</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="235"/>
<source>Enable AAC audio</source>
<translation>Aktivera AAC-ljud</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="239"/>
<source>Print DSP firmware</source>
<translation>Skriv ut firmware för DSP</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="243"/>
<source>Mute audio device</source>
<translation>Stäng av ljudet audioenheten</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="248"/>
<source>Cubic</source>
<translation>Kubisk</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="249"/>
<source>Linear</source>
<translation>Linjär</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="255"/>
<source>Volume curve</source>
<translation>Volymkurva</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="273"/>
<source>Audio device volume</source>
<translation>Ljudenhetens volym</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="276"/>
<source>Battery Settings</source>
<translation>Batteriinställningar</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="288"/>
<source>Battery percentage</source>
<translation>Batteriprocent</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="290"/>
<source>Charger plugged</source>
<translation>Laddaren är ansluten</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="295"/>
<source>SD Card Settings</source>
<translation>Inställningar för SD-kort</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="300"/>
<source>Enable virtual SD card</source>
<translation>Aktivera virtuellt SD-kort</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="304"/>
<source>Write protect virtual SD card</source>
<translation>Skrivskydd för virtuellt SD-kort</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="309"/>
<source>Interface</source>
<translation>Gränssnitt</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="309"/>
<source>User Interface settings</source>
<translation>Inställningar för användargränssnitt</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="310"/>
<source>General</source>
<translation>Allmänt</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="310"/>
<source>General emulator settings</source>
<translation>Allmänna inställningar för emulatorn</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="311"/>
<source>Graphics</source>
<translation>Grafik</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="311"/>
<source>Graphics emulation and output settings</source>
<translation>Inställningar för grafikemulering och utdata</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="312"/>
<source>Audio</source>
<translation>Ljud</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="312"/>
<source>Audio emulation and output settings</source>
<translation>Inställningar för ljudemulering och utdata</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="313"/>
<source>Battery</source>
<translation>Batteri</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="313"/>
<source>Battery emulation settings</source>
<translation>Inställningar för batteriemulering</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="314"/>
<source>SD Card</source>
<translation>SD-kort</translation>
</message>
<message>
<location filename="../../src/panda_qt/config_window.cpp" line="314"/>
<source>SD Card emulation settings</source>
<translation>Inställningar för emulering av SD-kort</translation>
</message>
<message>
<location filename="../../src/panda_qt/translations.cpp" line="75"/>
<source>Language change successful</source>
<translation>Språkändringen lyckades</translation>
</message>
<message>
<location filename="../../src/panda_qt/translations.cpp" line="76"/>
<source>Restart Panda3DS for the new language to be used.</source>
<translation>Starta om Panda3DS för att det nya språket ska kunna användas.</translation>
</message>
<message>
<location filename="../../src/panda_qt/translations.cpp" line="82"/>
<source>Language change failed</source>
<translation>Språkändringen misslyckades</translation>
</message>
<message>
<location filename="../../src/panda_qt/translations.cpp" line="83"/>
<source>The language you selected is not included in Panda3DS. If you&apos;re seeing this, someone messed up the language UI code...</source>
<translation>Det språk du valde ingår inte i Panda3DS. Om du ser detta, har någon rört till koden för språkgränssnittet...</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="20"/>
<source>Alber</source>
<translation>Alber</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="38"/>
<source>File</source>
<translation>Arkiv</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="39"/>
<source>Emulation</source>
<translation>Emulering</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="40"/>
<source>Tools</source>
<translation>Verktyg</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="41"/>
<source>About</source>
<translation>Om</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="44"/>
<source>Load game</source>
<translation>Läs in spel</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="45"/>
<source>Load Lua script</source>
<translation>Läs in Lua-skript</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="46"/>
<source>Open Panda3DS folder</source>
<translation>Öppna Panda3DS-mappen</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="55"/>
<source>Pause</source>
<translation>Pausa</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="56"/>
<source>Resume</source>
<translation>Återuppta</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="57"/>
<source>Reset</source>
<translation>Starta om</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="58"/>
<source>Configure</source>
<translation>Konfigurera</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="64"/>
<source>Dump RomFS</source>
<translation>Dumpa RomFS</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="65"/>
<source>Open Lua Editor</source>
<translation>Öppna Lua-redigeraren</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="66"/>
<source>Open Cheats Editor</source>
<translation>Öppna fuskredigeraren</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="67"/>
<source>Open Patch Window</source>
<translation>Öppna patchfönstret</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="68"/>
<source>Open Shader Editor</source>
<translation>Öppna shader-redigeraren</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="69"/>
<source>Dump loaded DSP firmware</source>
<translation>Dumpa inläst DSP-firmware</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="78"/>
<source>About Panda3DS</source>
<translation>Om Panda3DS</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="195"/>
<source>Select 3DS ROM to load</source>
<translation>Välj 3DS ROM att läsa in</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="196"/>
<source>Nintendo 3DS ROMs (*.3ds *.cci *.cxi *.app *.ncch *.3dsx *.elf *.axf)</source>
<translation>Nintendo 3DS ROM (*.3ds *.cci *.cxi *.app *.ncch *.3dsx *.elf *.axf)</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="209"/>
<source>Select Lua script to load</source>
<translation>Välj Lua-skript som ska läsas in</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="209"/>
<source>Lua scripts (*.lua *.txt)</source>
<translation>Lua-skript (*.lua *.txt)</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="272"/>
<source>Select folder to dump RomFS files to</source>
<translation>Välj mapp för att dumpa RomFS-filer till</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="288"/>
<source>Invalid format for RomFS dumping</source>
<translation>Ogiltigt format för RomFS-dumpning</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="289"/>
<source>The currently loaded app is not in a format that supports RomFS</source>
<translation>Den aktuella appen är inte i ett format som stöder RomFS</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="292"/>
<location filename="../../src/panda_qt/main_window.cpp" line="323"/>
<location filename="../../src/panda_qt/main_window.cpp" line="336"/>
<source>OK</source>
<translation>Ok</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="299"/>
<source>No RomFS found</source>
<translation>Ingen RomFS hittades</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="299"/>
<source>No RomFS partition was found in the loaded app</source>
<translation>Ingen RomFS-partition hittades i den inlästa appen</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="305"/>
<source>Select file</source>
<translation>Välj fil</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="305"/>
<source>DSP firmware file (*.cdc)</source>
<translation>DSP firmware-fil (*.cdc)</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="320"/>
<source>No DSP firmware loaded</source>
<translation>Ingen firmware för DSP inläst</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="320"/>
<source>The currently loaded app has not uploaded a firmware to the DSP</source>
<translation>Den aktuella appen har inte skickat upp någon firmware till DSP:n</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="331"/>
<source>Failed to open output file</source>
<translation>Misslyckades med att öppna utdatafilen</translation>
</message>
<message>
<location filename="../../src/panda_qt/main_window.cpp" line="332"/>
<source>The currently loaded DSP firmware could not be written to the selected file. Please make sure you have permission to access this file</source>
<translation>Den aktuella DSP-firmware som lästes in kunde inte skrivas till den valda filen. Kontrollera att du har behörighet att komma åt den här filen</translation>
</message>
</context>
<context>
<name>PatchWindow</name>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="15"/>
<source>ROM patcher</source>
<translation>ROM-patchare</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="23"/>
<source>Select input file</source>
<translation>Välj inmatningsfil</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="24"/>
<location filename="../../src/panda_qt/patch_window.cpp" line="36"/>
<source>Select</source>
<translation>Välj</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="35"/>
<location filename="../../src/panda_qt/patch_window.cpp" line="63"/>
<source>Select patch file</source>
<translation>Välj patchfil</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="47"/>
<source>Apply patch</source>
<translation>Applicera patch</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="56"/>
<source>Select file to patch</source>
<translation>Välj fil som ska patchas</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="56"/>
<location filename="../../src/panda_qt/patch_window.cpp" line="80"/>
<source>All files (*.*)</source>
<translation>Alla filer (*.*)</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="63"/>
<source>Patch files (*.ips *.ups *.bps)</source>
<translation>Patch-filer (*.ips *.ups *.bps)</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="71"/>
<source>Paths not provided correctly</source>
<translation>Sökvägar anges inte korrekt</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="71"/>
<source>Please provide paths for both the input file and the patch file</source>
<translation>Ange sökvägar för både indatafilen och patchfilen</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="80"/>
<source>Select file</source>
<translation>Välj fil</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="84"/>
<source>No output path</source>
<translation>Ingen sökväg för utmatning</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="84"/>
<source>No path was provided for the output file, no patching was done</source>
<translation>Ingen sökväg angavs för utdatafilen, ingen patchning gjordes</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="99"/>
<source>Unknown patch format</source>
<translation>Okänt patchformat</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="99"/>
<source>Unknown format for patch file. Currently IPS, UPS and BPS are supported</source>
<translation>Okänt format för patchfil. För närvarande stöds IPS, UPS och BPS</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="108"/>
<source>Failed to open input files</source>
<translation>Misslyckades med att öppna indatafiler</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="108"/>
<source>Make sure they&apos;re in a directory Panda3DS has access to</source>
<translation>Se till att de finns i en katalog som Panda3DS har tillgång till</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="135"/>
<source>Patching Success</source>
<translation>Patchning lyckades</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="135"/>
<source>Your file was patched successfully.</source>
<translation>Din fil patchades.</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="141"/>
<source>Checksum mismatch</source>
<translation>Kontrollsumman stämmer inte överens</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="142"/>
<source>Patch was applied successfully but a checksum mismatch was detected. The input or output files might not be correct</source>
<translation>Patchen applicerades men en avvikelse i kontrollsumman upptäcktes. Inmatnings- eller utdatafilerna kanske inte är korrekta</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="146"/>
<source>Patching error</source>
<translation>Fel vid patchning</translation>
</message>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="146"/>
<source>An error occured while patching</source>
<translation>Ett fel uppstod vid patchning</translation>
</message>
</context>
<context>
<name>PatchWindow::PatchWindow</name>
<message>
<location filename="../../src/panda_qt/patch_window.cpp" line="153"/>
<source>OK</source>
<translation>Ok</translation>
</message>
</context>
<context>
<name>ShaderEditorWindow</name>
<message>
<location filename="../../src/panda_qt/shader_editor.cpp" line="26"/>
<source>Reload shader</source>
<translation>Läs om shader</translation>
</message>
</context>
<context>
<name>TextEditorWindow</name>
<message>
<location filename="../../src/panda_qt/text_editor.cpp" line="12"/>
<source>Lua Editor</source>
<translation>Lua-redigerare</translation>
</message>
<message>
<location filename="../../src/panda_qt/text_editor.cpp" line="27"/>
<source>Load script</source>
<translation>Läs in skript</translation>
</message>
</context>
</TS>

View file

@ -2,8 +2,8 @@
namespace PICA::ShaderGen {
// Graphics API this shader is targetting
enum class API { GL, GLES, Vulkan, Metal };
enum class API { GL, GLES, Vulkan };
// Shading language to use
enum class Language { GLSL, MSL };
} // namespace PICA::ShaderGen
// Shading language to use (Only GLSL for the time being)
enum class Language { GLSL };
} // namespace PICA::ShaderGen

View file

@ -1,9 +0,0 @@
#pragma once
#if defined(__LIBRETRO__) && defined(USE_LIBRETRO_AUDIO_DEVICE)
#include "audio/libretro_audio_device.hpp"
using AudioDevice = LibretroAudioDevice;
#else
#include "audio/miniaudio_device.hpp"
using AudioDevice = MiniAudioDevice;
#endif

View file

@ -1,36 +0,0 @@
#pragma once
#include <array>
#include "config.hpp"
#include "helpers.hpp"
#include "ring_buffer.hpp"
class AudioDeviceInterface {
protected:
static constexpr usize maxFrameCount = 0x2000;
using Samples = Common::RingBuffer<s16, maxFrameCount * 2>;
using RenderBatchCallback = usize (*)(const s16*, usize);
Samples* samples = nullptr;
const AudioDeviceConfig& audioSettings;
// Store the last stereo sample we output. We play this when underruning to avoid pops.
std::array<s16, 2> lastStereoSample{};
public:
AudioDeviceInterface(Samples* samples, const AudioDeviceConfig& audioSettings) : samples(samples), audioSettings(audioSettings) {}
bool running = false;
Samples* getSamples() { return samples; }
// If safe is on, we create a null audio device
virtual void init(Samples& samples, bool safe = false) = 0;
virtual void close() = 0;
virtual void start() = 0;
virtual void stop() = 0;
// Only used for audio devices that render multiple audio frames in one go, eg the libretro audio device.
virtual void renderBatch(RenderBatchCallback callback) {}
};

View file

@ -1,61 +0,0 @@
#pragma once
#include <cstring>
#include "audio/audio_device_interface.hpp"
class LibretroAudioDevice final : public AudioDeviceInterface {
bool initialized = false;
public:
LibretroAudioDevice(const AudioDeviceConfig& audioSettings) : AudioDeviceInterface(nullptr, audioSettings), initialized(false) {
running = false;
}
void init(Samples& samples, bool safe = false) override {
this->samples = &samples;
initialized = true;
running = false;
}
void close() override {
initialized = false;
running = false;
};
void start() override { running = true; }
void stop() override { running = false; };
void renderBatch(RenderBatchCallback callback) override {
if (running) {
static constexpr usize sampleRate = 32768; // 3DS samples per second
static constexpr usize frameCount = sampleRate / 60; // 3DS samples per video frame
static constexpr usize channelCount = 2;
static s16 audioBuffer[frameCount * channelCount];
usize samplesWritten = 0;
samplesWritten += samples->pop(audioBuffer, frameCount * channelCount);
// Get the last sample for underrun handling
if (samplesWritten != 0) {
std::memcpy(&lastStereoSample[0], &audioBuffer[(samplesWritten - 1) * 2], sizeof(lastStereoSample));
}
// If underruning, copy the last output sample
{
s16* pointer = &audioBuffer[samplesWritten * 2];
s16 l = lastStereoSample[0];
s16 r = lastStereoSample[1];
for (usize i = samplesWritten; i < frameCount; i++) {
*pointer++ = l;
*pointer++ = r;
}
}
callback(audioBuffer, sizeof(audioBuffer) / (channelCount * sizeof(s16)));
}
}
bool isInitialized() const { return initialized; }
};

View file

@ -3,31 +3,39 @@
#include <string>
#include <vector>
#include "audio/audio_device_interface.hpp"
#include "config.hpp"
#include "helpers.hpp"
#include "miniaudio.h"
#include "ring_buffer.hpp"
class MiniAudioDevice final : public AudioDeviceInterface {
class MiniAudioDevice {
using Samples = Common::RingBuffer<ma_int16, 0x2000 * 2>;
static constexpr ma_uint32 sampleRate = 32768; // 3DS sample rate
static constexpr ma_uint32 channelCount = 2; // Audio output is stereo
bool initialized = false;
ma_device device;
ma_context context;
ma_device_config deviceConfig;
Samples* samples = nullptr;
const AudioDeviceConfig& audioSettings;
bool initialized = false;
bool running = false;
// Store the last stereo sample we output. We play this when underruning to avoid pops.
std::array<s16, 2> lastStereoSample;
std::vector<std::string> audioDevices;
public:
MiniAudioDevice(const AudioDeviceConfig& audioSettings);
// If safe is on, we create a null audio device
void init(Samples& samples, bool safe = false) override;
void close() override;
void init(Samples& samples, bool safe = false);
void close();
void start() override;
void stop() override;
void start();
void stop();
bool isInitialized() const { return initialized; }
};

View file

@ -55,13 +55,6 @@ struct EmulatorConfig {
static constexpr bool audioEnabledDefault = false;
#endif
// We default to OpenGL on all platforms other than iOS
#if defined(PANDA3DS_IOS)
static constexpr RendererType rendererDefault = RendererType::Metal;
#else
static constexpr RendererType rendererDefault = RendererType::OpenGL;
#endif
bool shaderJitEnabled = shaderJitDefault;
bool useUbershaders = ubershaderDefault;
bool accelerateShaders = accelerateShadersDefault;
@ -72,7 +65,7 @@ struct EmulatorConfig {
bool forceShadergenForLights = true;
int lightShadergenThreshold = 1;
RendererType rendererType = rendererDefault;
RendererType rendererType = RendererType::OpenGL;
Audio::DSPCore::Type dspType = Audio::DSPCore::Type::HLE;
bool sdCardInserted = true;

View file

@ -181,7 +181,5 @@ class CPU {
void addTicks(u64 ticks) { env.AddTicks(ticks); }
void clearCache() { jit->ClearCache(); }
void clearCacheRange(u32 start, u32 size) { jit->InvalidateCacheRange(start, size); }
void runFrame();
};

View file

@ -7,8 +7,8 @@
#include <span>
#include "PICA/gpu.hpp"
#include "audio/audio_device.hpp"
#include "audio/dsp_core.hpp"
#include "audio/miniaudio_device.hpp"
#include "cheats.hpp"
#include "config.hpp"
#include "cpu.hpp"
@ -48,14 +48,14 @@ class Emulator {
Scheduler scheduler;
Crypto::AESEngine aesEngine;
AudioDevice audioDevice;
MiniAudioDevice audioDevice;
Cheats cheats;
public:
static constexpr u32 width = 400;
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
ROMType romType = ROMType::None;
bool running = false; // Is the emulator running a game?
bool running = false; // Is the emulator running a game?
private:
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
@ -89,6 +89,7 @@ class Emulator {
~Emulator();
void step();
void render();
void reset(ReloadOption reload);
void runFrame();
// Poll the scheduler for events
@ -126,7 +127,6 @@ class Emulator {
LuaManager& getLua() { return lua; }
Scheduler& getScheduler() { return scheduler; }
Memory& getMemory() { return memory; }
AudioDeviceInterface& getAudioDevice() { return audioDevice; }
RendererType getRendererType() const { return config.rendererType; }
Renderer* getRenderer() { return gpu.getRenderer(); }

View file

@ -11,7 +11,6 @@ struct FrontendSettings {
Dark = 2,
GreetingsCat = 3,
Cream = 4,
Oled = 5,
};
// Different panda-themed window icons
@ -21,7 +20,6 @@ struct FrontendSettings {
Rnap = 2,
Rcow = 3,
SkyEmu = 4,
Runpog = 5,
};
Theme theme = Theme::Dark;

View file

@ -1,7 +0,0 @@
#pragma once
#include <Foundation/Foundation.h>
#include <QuartzCore/QuartzCore.h>
void iosCreateEmulator();
void iosLoadROM(NSString* pathNS);
void iosRunFrame(CAMetalLayer* layer);

View file

@ -175,8 +175,6 @@ public:
void svcSignalEvent();
void svcSetTimer();
void svcSleepThread();
void svcInvalidateInstructionCacheRange();
void svcInvalidateEntireInstructionCache();
void connectToPort();
void outputDebugString();
void waitSynchronization1();
@ -252,6 +250,4 @@ public:
void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
void clearInstructionCache();
void clearInstructionCacheRange(u32 start, u32 size);
u32 getSharedFontVaddr();
};

View file

@ -19,7 +19,7 @@ struct ResourceLimitValues {
// APPLICATION resource limit
static constexpr ResourceLimitValues appResourceLimits = {
.maxPriority = 0x18,
.maxCommit = 64_MB + 16_MB, // We're currently giving 80MB to all apps. TODO: Implement extended memory properly
.maxCommit = 0x4000000,
.maxThreads = 0x20,
.maxEvents = 0x20,
.maxMutexes = 0x20,
@ -33,7 +33,7 @@ static constexpr ResourceLimitValues appResourceLimits = {
// SYS_APPLET resource limit
static constexpr ResourceLimitValues sysAppletResourceLimits = {
.maxPriority = 0x4,
.maxCommit = 0x5E00000 - 16_MB,
.maxCommit = 0x5E00000,
.maxThreads = 0x1D,
.maxEvents = 0xB,
.maxMutexes = 0x8,

View file

@ -132,7 +132,7 @@ public:
static constexpr u32 totalPageCount = 1 << (32 - pageShift);
static constexpr u32 FCRAM_SIZE = u32(128_MB);
static constexpr u32 FCRAM_APPLICATION_SIZE = u32(80_MB);
static constexpr u32 FCRAM_APPLICATION_SIZE = u32(64_MB);
static constexpr u32 FCRAM_PAGE_COUNT = FCRAM_SIZE / pageSize;
static constexpr u32 FCRAM_APPLICATION_PAGE_COUNT = FCRAM_APPLICATION_SIZE / pageSize;

View file

@ -53,7 +53,6 @@ class Renderer {
EmulatorConfig* emulatorConfig = nullptr;
void doSoftwareTextureCopy(u32 inputAddr, u32 outputAddr, u32 copySize, u32 inputWidth, u32 inputGap, u32 outputWidth, u32 outputGap);
public:
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs);
virtual ~Renderer();
@ -82,14 +81,6 @@ class Renderer {
virtual std::string getUbershader() { return ""; }
virtual void setUbershader(const std::string& shader) {}
// Only relevant for OpenGL renderer and other OpenGL-based backends (eg software)
// Called to notify the core to use OpenGL ES and not desktop GL
virtual void setupGLES() {}
// Only relevant for Metal renderer on iOS
// Passes a SwiftUI MTKView's layer (CAMetalLayer) to the renderer
virtual void setMTKLayer(void* layer) {};
// This function is called on every draw call before parsing vertex data.
// It is responsible for things like looking up which vertex/fragment shaders to use, recompiling them if they don't exist, choosing between
// ubershaders and shadergen, and so on.

View file

@ -4,7 +4,6 @@
// Stuff like whether specific extensions are supported, and potentially things like OpenGL context information
namespace OpenGL {
struct Driver {
bool usingGLES = false;
bool supportsExtFbFetch = false;
bool supportsArmFbFetch = false;

View file

@ -40,7 +40,7 @@ class RendererGL final : public Renderer {
OpenGL::VertexArray hwShaderVAO;
OpenGL::VertexBuffer vbo;
// Data
// Data
struct {
// TEV configuration uniform locations
GLint textureEnvSourceLoc = -1;
@ -157,7 +157,6 @@ class RendererGL final : public Renderer {
void initGraphicsContextInternal();
void accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel);
void compileDisplayShader();
public:
RendererGL(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs)
@ -170,15 +169,14 @@ class RendererGL final : public Renderer {
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override; // Clear a GPU buffer in VRAM
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override; // Perform display transfer
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override; // Draw the given vertices
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override; // Draw the given vertices
void deinitGraphicsContext() override;
virtual bool supportsShaderReload() override { return true; }
virtual std::string getUbershader() override;
virtual void setUbershader(const std::string& shader) override;
virtual bool prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) override;
virtual void setupGLES() override;
std::optional<ColourBuffer> getColourBuffer(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound = true);
// Note: The caller is responsible for deleting the currently bound FBO before calling this

View file

@ -57,7 +57,7 @@ namespace Metal {
} else if (std::is_same<Format_t, PICA::DepthFmt>::value) {
pixelFormat = PICA::toMTLPixelFormatDepth((PICA::DepthFmt)format);
} else {
Helpers::panic("Invalid format type");
panic("Invalid format type");
}
MTL::TextureDescriptor* descriptor = MTL::TextureDescriptor::alloc()->init();

View file

@ -8,9 +8,8 @@
#include "boost/icl/interval.hpp"
#include "helpers.hpp"
#include "math_util.hpp"
#include "renderer_mtl/pica_to_mtl.hpp"
// TODO: remove dependency on OpenGL
#include "opengl.hpp"
#include "renderer_mtl/pica_to_mtl.hpp"
template <typename T>
using Interval = boost::icl::right_open_interval<T>;
@ -28,8 +27,7 @@ namespace Metal {
// Range of VRAM taken up by buffer
Interval<u32> range;
PICA::MTLPixelFormatInfo formatInfo;
MTL::Texture* base = nullptr;
PICA::PixelFormatInfo formatInfo;
MTL::Texture* texture = nullptr;
MTL::SamplerState* sampler = nullptr;
@ -54,7 +52,22 @@ namespace Metal {
void free();
u64 sizeInBytes();
u8 decodeTexelU8(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data);
u16 decodeTexelU16(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data);
u32 decodeTexelU32(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data);
// Get the morton interleave offset of a texel based on its U and V values
static u32 mortonInterleave(u32 u, u32 v);
// Get the byte offset of texel (u, v) in the texture
static u32 getSwizzledOffset(u32 u, u32 v, u32 width, u32 bytesPerPixel);
static u32 getSwizzledOffset_4bpp(u32 u, u32 v, u32 width);
// Returns the format of this texture as a string
std::string_view formatToString() { return PICA::textureFormatToString(format); }
// Returns the texel at coordinates (u, v) of an ETC1(A4) texture
// TODO: Make hasAlpha a template parameter
u32 getTexelETC(bool hasAlpha, u32 u, u32 v, u32 width, std::span<const u8> data);
u32 decodeETC(u32 alpha, u32 u, u32 v, u64 colourData);
};
} // namespace Metal

View file

@ -3,28 +3,31 @@
#include <Metal/Metal.hpp>
#include "PICA/regs.hpp"
// TODO: remove dependency on OpenGL
#include "opengl.hpp"
namespace PICA {
struct MTLPixelFormatInfo {
struct PixelFormatInfo {
MTL::PixelFormat pixelFormat;
size_t bytesPerTexel;
void (*decoder)(OpenGL::uvec2, u32, u32, std::span<const u8>, u8*);
bool needsSwizzle = false;
MTL::TextureSwizzleChannels swizzle{
.red = MTL::TextureSwizzleRed,
.green = MTL::TextureSwizzleGreen,
.blue = MTL::TextureSwizzleBlue,
.alpha = MTL::TextureSwizzleAlpha,
};
};
extern MTLPixelFormatInfo mtlPixelFormatInfos[14];
constexpr PixelFormatInfo pixelFormatInfos[14] = {
{MTL::PixelFormatRGBA8Unorm, 4}, // RGBA8
{MTL::PixelFormatRGBA8Unorm, 4}, // RGB8
{MTL::PixelFormatBGR5A1Unorm, 2}, // RGBA5551
{MTL::PixelFormatB5G6R5Unorm, 2}, // RGB565
{MTL::PixelFormatABGR4Unorm, 2}, // RGBA4
{MTL::PixelFormatRGBA8Unorm, 4}, // IA8
{MTL::PixelFormatRG8Unorm, 2}, // RG8
{MTL::PixelFormatRGBA8Unorm, 4}, // I8
{MTL::PixelFormatA8Unorm, 1}, // A8
{MTL::PixelFormatABGR4Unorm, 2}, // IA4
{MTL::PixelFormatABGR4Unorm, 2}, // I4
{MTL::PixelFormatA8Unorm, 1}, // A4
{MTL::PixelFormatRGBA8Unorm, 4}, // ETC1
{MTL::PixelFormatRGBA8Unorm, 4}, // ETC1A4
};
void checkForMTLPixelFormatSupport(MTL::Device* device);
inline MTLPixelFormatInfo getMTLPixelFormatInfo(TextureFmt format) { return mtlPixelFormatInfos[static_cast<int>(format)]; }
inline PixelFormatInfo getPixelFormatInfo(TextureFmt format) { return pixelFormatInfos[static_cast<int>(format)]; }
inline MTL::PixelFormat toMTLPixelFormatColor(ColorFmt format) {
switch (format) {
@ -32,11 +35,7 @@ namespace PICA {
case ColorFmt::RGB8: return MTL::PixelFormatRGBA8Unorm;
case ColorFmt::RGBA5551: return MTL::PixelFormatRGBA8Unorm; // TODO: use MTL::PixelFormatBGR5A1Unorm?
case ColorFmt::RGB565: return MTL::PixelFormatRGBA8Unorm; // TODO: use MTL::PixelFormatB5G6R5Unorm?
#ifdef PANDA3DS_IOS
case ColorFmt::RGBA4: return MTL::PixelFormatRGBA8Unorm; // IOS + Metal doesn't support AGBR4 properly, at least on simulator
#else
case ColorFmt::RGBA4: return MTL::PixelFormatABGR4Unorm;
#endif
}
}

View file

@ -42,13 +42,11 @@ class RendererMTL final : public Renderer {
virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {}
#endif
virtual void setMTKLayer(void* layer) override;
private:
CA::MetalLayer* metalLayer = nullptr;
CA::MetalLayer* metalLayer;
MTL::Device* device = nullptr;
MTL::CommandQueue* commandQueue = nullptr;
MTL::Device* device;
MTL::CommandQueue* commandQueue;
Metal::CommandEncoder commandEncoder;
@ -100,7 +98,6 @@ class RendererMTL final : public Renderer {
void endRenderPass() {
if (renderCommandEncoder) {
renderCommandEncoder->endEncoding();
renderCommandEncoder->release();
renderCommandEncoder = nullptr;
}
}

View file

@ -1,24 +0,0 @@
#pragma once
#include "helpers.hpp"
// TODO: remove dependency on OpenGL
#include "opengl.hpp"
void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);

View file

@ -23,7 +23,6 @@ class CFGService {
void getConfigInfoBlk2(u32 messagePointer);
void getConfigInfoBlk8(u32 messagePointer, u32 commandWord);
void getCountryCodeID(u32 messagePointer);
void getCountryCodeString(u32 messagePointer);
void getLocalFriendCodeSeed(u32 messagePointer);
void getRegionCanadaUSA(u32 messagePointer);
void getSystemModel(u32 messagePointer);

View file

@ -35,7 +35,7 @@ Panda3DS is still in the early stages of development. Many games boot, many don'
For documenting game compatibility, make sure to visit the [games list repository](https://github.com/Panda3DS-emu/Panda3DS-Games-List). For miscellaneous issues or more technical issues, feel free to use this repo's issues tab.
# Why?
The 3DS emulation scene is already pretty mature, with offerings such as Citra which can offer a great playing experience for most games in the library, [Corgi3DS](https://github.com/PSI-Rockin/Corgi3DS), an innovative LLE emulator, or [Mikage](https://mikage.app/). However, there's always room for more emulators! While Panda3DS was initially a mere curiosity, there's many different concepts I would like to explore with it in the future, such as:
The 3DS emulation scene is already pretty mature, with offerings such as [Citra](https://github.com/citra-emu/citra) which can offer a great playing experience for most games in the library, [Corgi3DS](https://github.com/PSI-Rockin/Corgi3DS), an innovative LLE emulator, or [Mikage](https://mikage.app/). However, there's always room for more emulators! While Panda3DS was initially a mere curiosity, there's many different concepts I would like to explore with it in the future, such as:
- Virtualization. What motivated the creation of this emulator was actually a discussion on whether it is possible to get fast 3DS emulation on low-end hardware such as the Raspberry Pi 4, using the KVM API. At the moment, Panda3DS is powered by Dynarmic rather than using virtualization, but this is definitely a concept I want to explore in the future.
@ -113,12 +113,11 @@ Panda3DS also supports controller input using the SDL2 GameController API.
- [SkyEmu](https://github.com/skylersaleh/SkyEmu): A seagull-themed low-level GameBoy, GameBoy Color, GameBoy Advance and Nintendo DS emulator that is designed to be easy to use, cross platform and accurate.
- [NanoBoyAdvance](https://github.com/nba-emu/NanoBoyAdvance): A Game Boy Advance emulator focusing on hardware research and cycle-accurate emulation
- [Dust](https://github.com/kelpsyberry/dust): Nintendo DS emulator for desktop devices and the web
- [felix86](https://github.com/OFFTKP/felix86): A new x86-64 → RISC-V Linux userspace emulator
- [ChonkyStation](https://github.com/liuk7071/ChonkyStation): Work-in-progress PlayStation emulator
- [ChonkyStation 3](https://github.com/liuk7071/ChonkyStation3): Experimental HLE PS3 emulator for Windows, MacOS and Linux
- [MelonDS](https://github.com/melonDS-emu/melonDS): "DS emulator, sorta" - Arisotura
- [Kaizen](https://github.com/SimoneN64/Kaizen): Experimental work-in-progress low-level N64 emulator
- [ChonkyStation](https://github.com/liuk7071/ChonkyStation): Work-in-progress PlayStation emulator
- [shadPS4](https://github.com/shadps4-emu/shadPS4): Work-in-progress PS4 emulator by the founder of PCSX, PCSX2 and more
- [Hydra](https://github.com/hydra-emu/hydra): Cross-platform GameBoy, NES, N64 and Chip-8 emulator
- [Tanuki3DS](https://github.com/burhanr13/Tanuki3DS/): A new 3DS emulator for MacOS and Linux
# Support
If you find this project exciting and want to support the founder, check out [his Patreon](https://www.patreon.com/wheremyfoodat) or [Ko-fi](https://ko-fi.com/wheremyfoodat)

View file

@ -27,7 +27,6 @@ void EmulatorConfig::load() {
return;
}
printf("Loading existing configuration file %s\n", path.string().c_str());
toml::value data;
try {
@ -72,14 +71,14 @@ void EmulatorConfig::load() {
auto gpu = gpuResult.unwrap();
// Get renderer
auto rendererName = toml::find_or<std::string>(gpu, "Renderer", Renderer::typeToString(rendererDefault));
auto rendererName = toml::find_or<std::string>(gpu, "Renderer", "OpenGL");
auto configRendererType = Renderer::typeFromString(rendererName);
if (configRendererType.has_value()) {
rendererType = configRendererType.value();
} else {
Helpers::warn("Invalid renderer specified: %s\n", rendererName.c_str());
rendererType = rendererDefault;
rendererType = RendererType::OpenGL;
}
shaderJitEnabled = toml::find_or<toml::boolean>(gpu, "EnableShaderJIT", shaderJitDefault);

View file

@ -284,7 +284,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
break;
case VertexShaderOpDescriptorIndex: {
shaderUnit.vs.setOpDescriptorIndex(newValue);
shaderUnit.vs.setOpDescriptorIndex(value);
break;
}
@ -301,7 +301,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
}
case VertexBoolUniform: {
shaderUnit.vs.uploadBoolUniform(newValue & 0xffff);
shaderUnit.vs.uploadBoolUniform(value & 0xffff);
break;
}
@ -309,7 +309,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
case VertexIntUniform1:
case VertexIntUniform2:
case VertexIntUniform3: {
shaderUnit.vs.uploadIntUniform(index - VertexIntUniform0, newValue);
shaderUnit.vs.uploadIntUniform(index - VertexIntUniform0, value);
break;
}
@ -326,7 +326,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
}
case VertexShaderEntrypoint: {
shaderUnit.vs.entrypoint = newValue & 0xffff;
shaderUnit.vs.entrypoint = value & 0xffff;
break;
}
@ -336,13 +336,13 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
break;
*/
case VertexShaderTransferIndex: shaderUnit.vs.setBufferIndex(newValue); break;
case VertexShaderTransferIndex: shaderUnit.vs.setBufferIndex(value); break;
// Command lists can write to the command processor registers and change the command list stream
// Several games are known to do this, including New Super Mario Bros 2 and Super Mario 3D Land
case CmdBufTrigger0:
case CmdBufTrigger1: {
if (newValue != 0) { // A non-zero value triggers command list processing
if (value != 0) { // A non-zero value triggers command list processing
int bufferIndex = index - CmdBufTrigger0; // Index of the command buffer to execute (0 or 1)
u32 addr = (regs[CmdBufAddr0 + bufferIndex] & 0xfffffff) << 3;
u32 size = (regs[CmdBufSize0 + bufferIndex] & 0xfffff) << 3;

View file

@ -7,9 +7,8 @@
#include "helpers.hpp"
MiniAudioDevice::MiniAudioDevice(const AudioDeviceConfig& audioSettings) : AudioDeviceInterface(nullptr, audioSettings), initialized(false) {
running = false;
}
MiniAudioDevice::MiniAudioDevice(const AudioDeviceConfig& audioSettings)
: initialized(false), running(false), samples(nullptr), audioSettings(audioSettings) {}
void MiniAudioDevice::init(Samples& samples, bool safe) {
this->samples = &samples;
@ -213,4 +212,4 @@ void MiniAudioDevice::close() {
ma_device_uninit(&device);
ma_context_uninit(&context);
}
}
}

View file

@ -69,10 +69,6 @@ void Kernel::serviceSVC(u32 svc) {
case 0x3A: getResourceLimitCurrentValues(); break;
case 0x3B: getThreadContext(); break;
case 0x3D: outputDebugString(); break;
// Luma SVCs
case 0x93: svcInvalidateInstructionCacheRange(); break;
case 0x94: svcInvalidateEntireInstructionCache(); break;
default: Helpers::panic("Unimplemented svc: %X @ %08X", svc, regs[15]); break;
}
@ -302,23 +298,6 @@ void Kernel::duplicateHandle() {
}
void Kernel::clearInstructionCache() { cpu.clearCache(); }
void Kernel::clearInstructionCacheRange(u32 start, u32 size) { cpu.clearCacheRange(start, size); }
void Kernel::svcInvalidateInstructionCacheRange() {
const u32 start = regs[0];
const u32 size = regs[1];
logSVC("svcInvalidateInstructionCacheRange(start = %08X, size = %08X)\n", start, size);
clearInstructionCacheRange(start, size);
regs[0] = Result::Success;
}
void Kernel::svcInvalidateEntireInstructionCache() {
logSVC("svcInvalidateEntireInstructionCache()\n");
clearInstructionCache();
regs[0] = Result::Success;
}
namespace SystemInfoType {
enum : u32 {

View file

@ -122,10 +122,7 @@ void Kernel::mapMemoryBlock() {
}
if (KernelHandles::isSharedMemHandle(block)) {
if (block == KernelHandles::FontSharedMemHandle && addr == 0) {
addr = getSharedFontVaddr();
}
if (block == KernelHandles::FontSharedMemHandle && addr == 0) addr = 0x18000000;
u8* ptr = mem.mapSharedMemory(block, addr, myPerms, otherPerms); // Map shared memory block
// Pass pointer to shared memory to the appropriate service
@ -219,8 +216,3 @@ void Kernel::unmapMemoryBlock() {
Helpers::warn("Stubbed svcUnmapMemoryBlock!");
regs[0] = Result::Success;
}
u32 Kernel::getSharedFontVaddr() {
// Place shared font at the very beginning of system FCRAM
return mem.getLinearHeapVaddr() + Memory::FCRAM_APPLICATION_SIZE;
}

View file

@ -51,12 +51,17 @@ void RendererGL::reset() {
gl.useProgram(oldProgram); // Switch to old GL program
}
#ifdef USING_GLES
fragShaderGen.setTarget(PICA::ShaderGen::API::GLES, PICA::ShaderGen::Language::GLSL);
#endif
}
void RendererGL::initGraphicsContextInternal() {
gl.reset();
auto gl_resources = cmrc::RendererGL::get_filesystem();
auto vertexShaderSource = gl_resources.open("opengl_vertex_shader.vert");
auto fragmentShaderSource = gl_resources.open("opengl_fragment_shader.frag");
@ -65,7 +70,16 @@ void RendererGL::initGraphicsContextInternal() {
triangleProgram.create({vert, frag});
initUbershader(triangleProgram);
compileDisplayShader();
auto displayVertexShaderSource = gl_resources.open("opengl_display.vert");
auto displayFragmentShaderSource = gl_resources.open("opengl_display.frag");
OpenGL::Shader vertDisplay({displayVertexShaderSource.begin(), displayVertexShaderSource.size()}, OpenGL::Vertex);
OpenGL::Shader fragDisplay({displayFragmentShaderSource.begin(), displayFragmentShaderSource.size()}, OpenGL::Fragment);
displayProgram.create({vertDisplay, fragDisplay});
gl.useProgram(displayProgram);
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
// Create stream buffers for vertex, index and uniform buffers
static constexpr usize hwIndexBufferSize = 2_MB;
static constexpr usize hwVertexBufferSize = 16_MB;
@ -177,7 +191,6 @@ void RendererGL::initGraphicsContextInternal() {
}
reset();
fragShaderGen.setTarget(driverInfo.usingGLES ? PICA::ShaderGen::API::GLES : PICA::ShaderGen::API::GL, PICA::ShaderGen::Language::GLSL);
// Populate our driver info structure
driverInfo.supportsExtFbFetch = (GLAD_GL_EXT_shader_framebuffer_fetch != 0);
@ -792,8 +805,6 @@ void RendererGL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32
shutUpCounter++;
printf("RendererGL::TextureCopy failed to locate src framebuffer!\n");
}
doSoftwareTextureCopy(inputAddr, outputAddr, copySize, inputWidth, inputGap, outputWidth, outputGap);
return;
}
@ -839,9 +850,9 @@ OpenGL::Program& RendererGL::getSpecializedShader() {
PICA::FragmentConfig fsConfig(regs);
// If we're not on GLES, ignore the logic op configuration and don't generate redundant shaders for it, since we use hw logic ops
if (!driverInfo.usingGLES) {
fsConfig.outConfig.logicOpMode = PICA::LogicOpMode(0);
}
#ifndef USING_GLES
fsConfig.outConfig.logicOpMode = PICA::LogicOpMode(0);
#endif
OpenGL::Shader& fragShader = shaderCache.fragmentShaderCache[fsConfig];
if (!fragShader.exists()) {
@ -999,7 +1010,7 @@ bool RendererGL::prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration*
std::string picaShaderSource = PICA::ShaderGen::decompileShader(
shaderUnit.vs, *emulatorConfig, shaderUnit.vs.entrypoint,
driverInfo.usingGLES ? PICA::ShaderGen::API::GLES : PICA::ShaderGen::API::GL, PICA::ShaderGen::Language::GLSL
Helpers::isAndroid() ? PICA::ShaderGen::API::GLES : PICA::ShaderGen::API::GL, PICA::ShaderGen::Language::GLSL
);
// Empty source means compilation error, if the source is not empty then we convert the recompiled PICA code into a valid shader and upload
@ -1145,19 +1156,6 @@ void RendererGL::initUbershader(OpenGL::Program& program) {
glUniform1i(OpenGL::uniformLocation(program, "u_tex_luts"), 3);
}
void RendererGL::compileDisplayShader() {
auto gl_resources = cmrc::RendererGL::get_filesystem();
auto displayVertexShaderSource = driverInfo.usingGLES ? gl_resources.open("opengl_es_display.vert") : gl_resources.open("opengl_display.vert");
auto displayFragmentShaderSource = driverInfo.usingGLES ? gl_resources.open("opengl_es_display.frag") : gl_resources.open("opengl_display.frag");
OpenGL::Shader vertDisplay({displayVertexShaderSource.begin(), displayVertexShaderSource.size()}, OpenGL::Vertex);
OpenGL::Shader fragDisplay({displayFragmentShaderSource.begin(), displayFragmentShaderSource.size()}, OpenGL::Fragment);
displayProgram.create({vertDisplay, fragDisplay});
gl.useProgram(displayProgram);
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
}
void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) {
u32 buffer = 0; // Vertex buffer index for non-fixed attributes
u32 attrCount = 0;
@ -1252,20 +1250,4 @@ void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAccele
);
}
}
}
void RendererGL::setupGLES() {
driverInfo.usingGLES = true;
// OpenGL ES hardware is typically way too slow to use the ubershader (eg RPi, mobile phones, handhelds) or has other issues with it.
// So, display a warning and turn them off on OpenGL ES.
if (emulatorConfig->useUbershaders) {
emulatorConfig->useUbershaders = false;
Helpers::warn("Ubershaders enabled on OpenGL ES. This usually results in a worse experience, turning it off...");
}
// Stub out logic operations so that calling them doesn't crash the emulator
if (!glLogicOp) {
glLogicOp = [](GLenum) {};
}
}
}

View file

@ -0,0 +1,116 @@
#include <algorithm>
#include "colour.hpp"
#include "renderer_mtl/mtl_texture.hpp"
#include "renderer_mtl/renderer_mtl.hpp"
using namespace Helpers;
namespace Metal {
static constexpr u32 signExtend3To32(u32 val) {
return (u32)(s32(val) << 29 >> 29);
}
u32 Texture::getTexelETC(bool hasAlpha, u32 u, u32 v, u32 width, std::span<const u8> data) {
// Pixel offset of the 8x8 tile based on u, v and the width of the texture
u32 offs = ((u & ~7) * 8) + ((v & ~7) * width);
if (!hasAlpha) {
offs >>= 1;
}
// In-tile offsets for u/v
u &= 7;
v &= 7;
// ETC1(A4) also subdivide the 8x8 tile to 4 4x4 tiles
// Each tile is 8 bytes for ETC1, but since ETC1A4 has 4 alpha bits per pixel, that becomes 16 bytes
const u32 subTileSize = hasAlpha ? 16 : 8;
const u32 subTileIndex = (u / 4) + 2 * (v / 4); // Which of the 4 subtiles is this texel in?
// In-subtile offsets for u/v
u &= 3;
v &= 3;
offs += subTileSize * subTileIndex;
u32 alpha;
const u64* ptr = reinterpret_cast<const u64*>(data.data() + offs); // Cast to u64*
if (hasAlpha) {
// First 64 bits of the 4x4 subtile are alpha data
const u64 alphaData = *ptr++;
alpha = Colour::convert4To8Bit((alphaData >> (4 * (u * 4 + v))) & 0xf);
} else {
alpha = 0xff; // ETC1 without alpha uses ff for every pixel
}
// Next 64 bits of the subtile are colour data
u64 colourData = *ptr;
return decodeETC(alpha, u, v, colourData);
}
u32 Texture::decodeETC(u32 alpha, u32 u, u32 v, u64 colourData) {
static constexpr u32 modifiers[8][2] = {
{2, 8}, {5, 17}, {9, 29}, {13, 42}, {18, 60}, {24, 80}, {33, 106}, {47, 183},
};
// Parse colour data for 4x4 block
const u32 subindices = getBits<0, 16, u32>(colourData);
const u32 negationFlags = getBits<16, 16, u32>(colourData);
const bool flip = getBit<32>(colourData);
const bool diffMode = getBit<33>(colourData);
// Note: index1 is indeed stored on the higher bits, with index2 in the lower bits
const u32 tableIndex1 = getBits<37, 3, u32>(colourData);
const u32 tableIndex2 = getBits<34, 3, u32>(colourData);
const u32 texelIndex = u * 4 + v; // Index of the texel in the block
if (flip) std::swap(u, v);
s32 r, g, b;
if (diffMode) {
r = getBits<59, 5, s32>(colourData);
g = getBits<51, 5, s32>(colourData);
b = getBits<43, 5, s32>(colourData);
if (u >= 2) {
r += signExtend3To32(getBits<56, 3, u32>(colourData));
g += signExtend3To32(getBits<48, 3, u32>(colourData));
b += signExtend3To32(getBits<40, 3, u32>(colourData));
}
// Expand from 5 to 8 bits per channel
r = Colour::convert5To8Bit(r);
g = Colour::convert5To8Bit(g);
b = Colour::convert5To8Bit(b);
} else {
if (u < 2) {
r = getBits<60, 4, s32>(colourData);
g = getBits<52, 4, s32>(colourData);
b = getBits<44, 4, s32>(colourData);
} else {
r = getBits<56, 4, s32>(colourData);
g = getBits<48, 4, s32>(colourData);
b = getBits<40, 4, s32>(colourData);
}
// Expand from 4 to 8 bits per channel
r = Colour::convert4To8Bit(r);
g = Colour::convert4To8Bit(g);
b = Colour::convert4To8Bit(b);
}
const u32 index = (u < 2) ? tableIndex1 : tableIndex2;
s32 modifier = modifiers[index][(subindices >> texelIndex) & 1];
if (((negationFlags >> texelIndex) & 1) != 0) {
modifier = -modifier;
}
r = std::clamp(r + modifier, 0, 255);
g = std::clamp(g + modifier, 0, 255);
b = std::clamp(b + modifier, 0, 255);
return (alpha << 24) | (u32(b) << 16) | (u32(g) << 8) | u32(r);
}
} // namespace Metal

View file

@ -1,18 +1,16 @@
#include "renderer_mtl/mtl_texture.hpp"
#include <fmt/format.h>
#include <array>
#include <memory>
#include "colour.hpp"
#include "renderer_mtl/objc_helper.hpp"
using namespace Helpers;
namespace Metal {
void Texture::allocate() {
formatInfo = PICA::getMTLPixelFormatInfo(format);
formatInfo = PICA::getPixelFormatInfo(format);
MTL::TextureDescriptor* descriptor = MTL::TextureDescriptor::alloc()->init();
descriptor->setTextureType(MTL::TextureType2D);
@ -22,14 +20,11 @@ namespace Metal {
descriptor->setUsage(MTL::TextureUsageShaderRead);
descriptor->setStorageMode(MTL::StorageModeShared); // TODO: use private + staging buffers?
texture = device->newTexture(descriptor);
texture->setLabel(toNSString(fmt::format("Base texture {} {}x{}", std::string(PICA::textureFormatToString(format)), size.u(), size.v())));
texture->setLabel(toNSString(
"Texture " + std::string(PICA::textureFormatToString(format)) + " " + std::to_string(size.u()) + "x" + std::to_string(size.v())
));
descriptor->release();
if (formatInfo.needsSwizzle) {
base = texture;
texture = base->newTextureView(formatInfo.pixelFormat, MTL::TextureType2D, NS::Range(0, 1), NS::Range(0, 1), formatInfo.swizzle);
}
setNewConfig(config);
}
@ -63,11 +58,6 @@ namespace Metal {
if (texture) {
texture->release();
}
if (base) {
base->release();
}
if (sampler) {
sampler->release();
}
@ -109,19 +99,210 @@ namespace Metal {
}
}
// u and v are the UVs of the relevant texel
// Texture data is stored interleaved in Morton order, ie in a Z - order curve as shown here
// https://en.wikipedia.org/wiki/Z-order_curve
// Textures are split into 8x8 tiles.This function returns the in - tile offset depending on the u & v of the texel
// The in - tile offset is the sum of 2 offsets, one depending on the value of u % 8 and the other on the value of y % 8
// As documented in this picture https ://en.wikipedia.org/wiki/File:Moser%E2%80%93de_Bruijn_addition.svg
u32 Texture::mortonInterleave(u32 u, u32 v) {
static constexpr u32 xOffsets[] = {0, 1, 4, 5, 16, 17, 20, 21};
static constexpr u32 yOffsets[] = {0, 2, 8, 10, 32, 34, 40, 42};
return xOffsets[u & 7] + yOffsets[v & 7];
}
// Get the byte offset of texel (u, v) in the texture
u32 Texture::getSwizzledOffset(u32 u, u32 v, u32 width, u32 bytesPerPixel) {
u32 offset = ((u & ~7) * 8) + ((v & ~7) * width); // Offset of the 8x8 tile the texel belongs to
offset += mortonInterleave(u, v); // Add the in-tile offset of the texel
return offset * bytesPerPixel;
}
// Same as the above code except we need to divide by 2 because 4 bits is smaller than a byte
u32 Texture::getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) {
u32 offset = ((u & ~7) * 8) + ((v & ~7) * width); // Offset of the 8x8 tile the texel belongs to
offset += mortonInterleave(u, v); // Add the in-tile offset of the texel
return offset / 2;
}
u8 Texture::decodeTexelU8(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data) {
switch (fmt) {
case PICA::TextureFmt::A4: {
const u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
// For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates
u8 alpha = data[offset] >> ((u % 2) ? 4 : 0);
alpha = Colour::convert4To8Bit(getBits<0, 4>(alpha));
// A8
return alpha;
}
case PICA::TextureFmt::A8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 alpha = data[offset];
// A8
return alpha;
}
default: Helpers::panic("[Texture::DecodeTexel] Unimplemented format = %d", static_cast<int>(fmt));
}
}
u16 Texture::decodeTexelU16(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data) {
switch (fmt) {
case PICA::TextureFmt::RG8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
constexpr u8 b = 0;
const u8 g = data[offset];
const u8 r = data[offset + 1];
// RG8
return (g << 8) | r;
}
case PICA::TextureFmt::RGBA4: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
u16 texel = u16(data[offset]) | (u16(data[offset + 1]) << 8);
u8 alpha = getBits<0, 4, u8>(texel);
u8 b = getBits<4, 4, u8>(texel);
u8 g = getBits<8, 4, u8>(texel);
u8 r = getBits<12, 4, u8>(texel);
// ABGR4
return (r << 12) | (g << 8) | (b << 4) | alpha;
}
case PICA::TextureFmt::RGBA5551: {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(data[offset]) | (u16(data[offset + 1]) << 8);
u8 alpha = getBit<0>(texel) ? 0xff : 0;
u8 b = getBits<1, 5, u8>(texel);
u8 g = getBits<6, 5, u8>(texel);
u8 r = getBits<11, 5, u8>(texel);
// BGR5A1
return (alpha << 15) | (r << 10) | (g << 5) | b;
}
case PICA::TextureFmt::RGB565: {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(data[offset]) | (u16(data[offset + 1]) << 8);
const u8 b = getBits<0, 5, u8>(texel);
const u8 g = getBits<5, 6, u8>(texel);
const u8 r = getBits<11, 5, u8>(texel);
// B5G6R5
return (r << 11) | (g << 5) | b;
}
case PICA::TextureFmt::IA4: {
const u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 texel = data[offset];
const u8 alpha = texel & 0xf;
const u8 intensity = texel >> 4;
// ABGR4
return (intensity << 12) | (intensity << 8) | (intensity << 4) | alpha;
}
case PICA::TextureFmt::I4: {
u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
// For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates
u8 intensity = data[offset] >> ((u % 2) ? 4 : 0);
intensity = getBits<0, 4>(intensity);
// ABGR4
return (intensity << 12) | (intensity << 8) | (intensity << 4) | 0xff;
}
default: Helpers::panic("[Texture::DecodeTexel] Unimplemented format = %d", static_cast<int>(fmt));
}
}
u32 Texture::decodeTexelU32(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data) {
switch (fmt) {
case PICA::TextureFmt::RGB8: {
const u32 offset = getSwizzledOffset(u, v, size.u(), 3);
const u8 b = data[offset];
const u8 g = data[offset + 1];
const u8 r = data[offset + 2];
// RGBA8
return (0xff << 24) | (b << 16) | (g << 8) | r;
}
case PICA::TextureFmt::RGBA8: {
const u32 offset = getSwizzledOffset(u, v, size.u(), 4);
const u8 alpha = data[offset];
const u8 b = data[offset + 1];
const u8 g = data[offset + 2];
const u8 r = data[offset + 3];
// RGBA8
return (alpha << 24) | (b << 16) | (g << 8) | r;
}
case PICA::TextureFmt::I8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 intensity = data[offset];
// RGBA8
return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity;
}
case PICA::TextureFmt::IA8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
// Same as I8 except each pixel gets its own alpha value too
const u8 alpha = data[offset];
const u8 intensity = data[offset + 1];
// RGBA8
return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity;
}
case PICA::TextureFmt::ETC1: return getTexelETC(false, u, v, size.u(), data);
case PICA::TextureFmt::ETC1A4: return getTexelETC(true, u, v, size.u(), data);
default: Helpers::panic("[Texture::DecodeTexel] Unimplemented format = %d", static_cast<int>(fmt));
}
}
void Texture::decodeTexture(std::span<const u8> data) {
std::unique_ptr<u8[]> decodedData(new u8[u64(size.u()) * u64(size.v()) * formatInfo.bytesPerTexel]);
// This pointer will be incremented by our texture decoders
u8* decodePtr = decodedData.get();
std::vector<u8> decoded;
decoded.reserve(u64(size.u()) * u64(size.v()) * formatInfo.bytesPerTexel);
// Decode texels line by line
for (u32 v = 0; v < size.v(); v++) {
for (u32 u = 0; u < size.u(); u++) {
formatInfo.decoder(size, u, v, data, decodePtr);
decodePtr += formatInfo.bytesPerTexel;
if (formatInfo.bytesPerTexel == 1) {
u8 texel = decodeTexelU8(u, v, format, data);
decoded.push_back(texel);
} else if (formatInfo.bytesPerTexel == 2) {
u16 texel = decodeTexelU16(u, v, format, data);
decoded.push_back((texel & 0x00ff) >> 0);
decoded.push_back((texel & 0xff00) >> 8);
} else if (formatInfo.bytesPerTexel == 4) {
u32 texel = decodeTexelU32(u, v, format, data);
decoded.push_back((texel & 0x000000ff) >> 0);
decoded.push_back((texel & 0x0000ff00) >> 8);
decoded.push_back((texel & 0x00ff0000) >> 16);
decoded.push_back((texel & 0xff000000) >> 24);
} else {
Helpers::panic("[Texture::decodeTexture] Unimplemented bytesPerTexel (%u)", formatInfo.bytesPerTexel);
}
}
}
texture->replaceRegion(MTL::Region(0, 0, size.u(), size.v()), 0, 0, decodedData.get(), formatInfo.bytesPerTexel * size.u(), 0);
texture->replaceRegion(MTL::Region(0, 0, size.u(), size.v()), 0, 0, decoded.data(), formatInfo.bytesPerTexel * size.u(), 0);
}
} // namespace Metal

View file

@ -1,62 +0,0 @@
#include "renderer_mtl/pica_to_mtl.hpp"
#include "renderer_mtl/texture_decoder.hpp"
using namespace Helpers;
namespace PICA {
MTLPixelFormatInfo mtlPixelFormatInfos[14] = {
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelABGR8ToRGBA8}, // RGBA8
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelBGR8ToRGBA8}, // RGB8
{MTL::PixelFormatBGR5A1Unorm, 2, decodeTexelA1BGR5ToBGR5A1}, // RGBA5551
{MTL::PixelFormatB5G6R5Unorm, 2, decodeTexelB5G6R5ToB5G6R5}, // RGB565
{MTL::PixelFormatABGR4Unorm, 2, decodeTexelABGR4ToABGR4}, // RGBA4
{MTL::PixelFormatRG8Unorm,
2,
decodeTexelAI8ToRG8,
true,
{
.red = MTL::TextureSwizzleRed,
.green = MTL::TextureSwizzleRed,
.blue = MTL::TextureSwizzleRed,
.alpha = MTL::TextureSwizzleGreen,
}}, // IA8
{MTL::PixelFormatRG8Unorm, 2, decodeTexelGR8ToRG8}, // RG8
{MTL::PixelFormatR8Unorm,
1,
decodeTexelI8ToR8,
true,
{.red = MTL::TextureSwizzleRed, .green = MTL::TextureSwizzleRed, .blue = MTL::TextureSwizzleRed, .alpha = MTL::TextureSwizzleOne}}, // I8
{MTL::PixelFormatA8Unorm, 1, decodeTexelA8ToA8}, // A8
{MTL::PixelFormatABGR4Unorm, 2, decodeTexelAI4ToABGR4}, // IA4
{MTL::PixelFormatR8Unorm,
1,
decodeTexelI4ToR8,
true,
{.red = MTL::TextureSwizzleRed, .green = MTL::TextureSwizzleRed, .blue = MTL::TextureSwizzleRed, .alpha = MTL::TextureSwizzleOne}}, // I4
{MTL::PixelFormatA8Unorm, 1, decodeTexelA4ToA8}, // A4
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelETC1ToRGBA8}, // ETC1
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelETC1A4ToRGBA8}, // ETC1A4
};
void checkForMTLPixelFormatSupport(MTL::Device* device) {
if (!device->supportsFamily(MTL::GPUFamilyApple1)) {
mtlPixelFormatInfos[2] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelA1BGR5ToRGBA8};
mtlPixelFormatInfos[3] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelB5G6R5ToRGBA8};
mtlPixelFormatInfos[4] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelABGR4ToRGBA8};
mtlPixelFormatInfos[9] = {
MTL::PixelFormatRG8Unorm,
2,
decodeTexelAI4ToRG8,
true,
{
.red = MTL::TextureSwizzleRed,
.green = MTL::TextureSwizzleRed,
.blue = MTL::TextureSwizzleRed,
.alpha = MTL::TextureSwizzleGreen,
}
};
}
}
} // namespace PICA

View file

@ -30,6 +30,7 @@ PICA::ColorFmt ToColorFormat(u32 format) {
}
MTL::Library* loadLibrary(MTL::Device* device, const cmrc::file& shaderSource) {
// MTL::CompileOptions* compileOptions = MTL::CompileOptions::alloc()->init();
NS::Error* error = nullptr;
MTL::Library* library = device->newLibrary(Metal::createDispatchData(shaderSource.begin(), shaderSource.size()), &error);
// MTL::Library* library = device->newLibrary(NS::String::string(source.c_str(), NS::ASCIIStringEncoding), compileOptions, &error);
@ -55,18 +56,12 @@ void RendererMTL::reset() {
colorRenderTargetCache.reset();
}
void RendererMTL::setMTKLayer(void* layer) {
metalLayer = (CA::MetalLayer*)layer;
}
void RendererMTL::display() {
CA::MetalDrawable* drawable = metalLayer->nextDrawable();
if (!drawable) {
return;
}
MTL::Texture* texture = drawable->texture();
using namespace PICA::ExternalRegs;
// Top screen
@ -92,13 +87,13 @@ void RendererMTL::display() {
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
MTL::RenderPassColorAttachmentDescriptor* colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
colorAttachment->setTexture(texture);
colorAttachment->setTexture(drawable->texture());
colorAttachment->setLoadAction(MTL::LoadActionClear);
colorAttachment->setClearColor(MTL::ClearColor{0.0f, 0.0f, 0.0f, 1.0f});
colorAttachment->setStoreAction(MTL::StoreActionStore);
nextRenderPassName = "Display";
beginRenderPassIfNeeded(renderPassDescriptor, false, texture);
beginRenderPassIfNeeded(renderPassDescriptor, false, drawable->texture());
renderCommandEncoder->setRenderPipelineState(displayPipeline);
renderCommandEncoder->setFragmentSamplerState(nearestSampler, 0);
@ -124,22 +119,17 @@ void RendererMTL::display() {
// Inform the vertex buffer cache that the frame ended
vertexBufferCache.endFrame();
// Release
drawable->release();
}
void RendererMTL::initGraphicsContext(SDL_Window* window) {
// On iOS, the SwiftUI side handles the MetalLayer
#ifdef PANDA3DS_IOS
device = MTL::CreateSystemDefaultDevice();
#else
// TODO: what should be the type of the view?
void* view = SDL_Metal_CreateView(window);
metalLayer = (CA::MetalLayer*)SDL_Metal_GetLayer(view);
device = MTL::CreateSystemDefaultDevice();
metalLayer->setDevice(device);
#endif
checkForMTLPixelFormatSupport(device);
commandQueue = device->newCommandQueue();
// Textures
@ -436,7 +426,7 @@ void RendererMTL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32
// Find the source surface.
auto srcFramebuffer = getColorRenderTarget(inputAddr, PICA::ColorFmt::RGBA8, copyStride, copyHeight, false);
if (!srcFramebuffer) {
doSoftwareTextureCopy(inputAddr, outputAddr, copySize, inputWidth, inputGap, outputWidth, outputGap);
Helpers::warn("RendererMTL::TextureCopy failed to locate src framebuffer!\n");
return;
}
nextRenderPassName = "Clear before texture copy";

View file

@ -1,334 +0,0 @@
#include "renderer_mtl/texture_decoder.hpp"
#include <array>
#include <string>
#include "colour.hpp"
#include "math_util.hpp"
using namespace Helpers;
// u and v are the UVs of the relevant texel
// Texture data is stored interleaved in Morton order, ie in a Z - order curve as shown here
// https://en.wikipedia.org/wiki/Z-order_curve
// Textures are split into 8x8 tiles.This function returns the in - tile offset depending on the u & v of the texel
// The in - tile offset is the sum of 2 offsets, one depending on the value of u % 8 and the other on the value of y % 8
// As documented in this picture https ://en.wikipedia.org/wiki/File:Moser%E2%80%93de_Bruijn_addition.svg
u32 mortonInterleave(u32 u, u32 v) {
static constexpr u32 xOffsets[] = {0, 1, 4, 5, 16, 17, 20, 21};
static constexpr u32 yOffsets[] = {0, 2, 8, 10, 32, 34, 40, 42};
return xOffsets[u & 7] + yOffsets[v & 7];
}
// Get the byte offset of texel (u, v) in the texture
u32 getSwizzledOffset(u32 u, u32 v, u32 width, u32 bytesPerPixel) {
u32 offset = ((u & ~7) * 8) + ((v & ~7) * width); // Offset of the 8x8 tile the texel belongs to
offset += mortonInterleave(u, v); // Add the in-tile offset of the texel
return offset * bytesPerPixel;
}
// Same as the above code except we need to divide by 2 because 4 bits is smaller than a byte
u32 getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) {
u32 offset = ((u & ~7) * 8) + ((v & ~7) * width); // Offset of the 8x8 tile the texel belongs to
offset += mortonInterleave(u, v); // Add the in-tile offset of the texel
return offset / 2;
}
void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 4);
const u8 alpha = inData[offset];
const u8 b = inData[offset + 1];
const u8 g = inData[offset + 2];
const u8 r = inData[offset + 3];
*outData++ = r;
*outData++ = g;
*outData++ = b;
*outData++ = alpha;
}
void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 3);
const u8 b = inData[offset];
const u8 g = inData[offset + 1];
const u8 r = inData[offset + 2];
*outData++ = r;
*outData++ = g;
*outData++ = b;
*outData++ = 0xff;
}
void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8);
u8 alpha = getBit<0>(texel);
u8 b = getBits<1, 5, u8>(texel);
u8 g = getBits<6, 5, u8>(texel);
u8 r = getBits<11, 5, u8>(texel);
u16 outTexel = (alpha << 15) | (r << 10) | (g << 5) | b;
*outData++ = outTexel & 0xff;
*outData++ = (outTexel >> 8) & 0xff;
}
void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8);
u8 alpha = getBit<0>(texel) ? 0xff : 0;
u8 b = Colour::convert5To8Bit(getBits<1, 5, u8>(texel));
u8 g = Colour::convert5To8Bit(getBits<6, 5, u8>(texel));
u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel));
*outData++ = r;
*outData++ = g;
*outData++ = b;
*outData++ = alpha;
}
void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8);
*outData++ = texel & 0xff;
*outData++ = (texel >> 8) & 0xff;
}
void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8);
const u8 b = Colour::convert5To8Bit(getBits<0, 5, u8>(texel));
const u8 g = Colour::convert6To8Bit(getBits<5, 6, u8>(texel));
const u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel));
*outData++ = r;
*outData++ = g;
*outData++ = b;
*outData++ = 0xff;
}
void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8);
u8 alpha = getBits<0, 4, u8>(texel);
u8 b = getBits<4, 4, u8>(texel);
u8 g = getBits<8, 4, u8>(texel);
u8 r = getBits<12, 4, u8>(texel);
*outData++ = (b << 4) | alpha;
*outData++ = (r << 4) | g;
}
void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8);
u8 alpha = Colour::convert4To8Bit(getBits<0, 4, u8>(texel));
u8 b = Colour::convert4To8Bit(getBits<4, 4, u8>(texel));
u8 g = Colour::convert4To8Bit(getBits<8, 4, u8>(texel));
u8 r = Colour::convert4To8Bit(getBits<12, 4, u8>(texel));
*outData++ = r;
*outData++ = g;
*outData++ = b;
*outData++ = alpha;
}
void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
// Same as I8 except each pixel gets its own alpha value too
const u8 alpha = inData[offset];
const u8 intensity = inData[offset + 1];
*outData++ = intensity;
*outData++ = alpha;
}
void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
constexpr u8 b = 0;
const u8 g = inData[offset];
const u8 r = inData[offset + 1];
*outData++ = r;
*outData++ = g;
}
void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 intensity = inData[offset];
*outData++ = intensity;
}
void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 alpha = inData[offset];
*outData++ = alpha;
}
void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 texel = inData[offset];
const u8 alpha = texel & 0xf;
const u8 intensity = texel >> 4;
*outData++ = (intensity << 4) | intensity;
*outData++ = (alpha << 4) | intensity;
}
void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 texel = inData[offset];
const u8 alpha = Colour::convert4To8Bit(texel & 0xf);
const u8 intensity = Colour::convert4To8Bit(texel >> 4);
*outData++ = intensity;
*outData++ = alpha;
}
void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
// For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates
u8 intensity = inData[offset] >> ((u % 2) ? 4 : 0);
intensity = Colour::convert4To8Bit(getBits<0, 4>(intensity));
*outData++ = intensity;
}
void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
// For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates
u8 alpha = inData[offset] >> ((u % 2) ? 4 : 0);
alpha = Colour::convert4To8Bit(getBits<0, 4>(alpha));
*outData++ = alpha;
}
static constexpr u32 signExtend3To32(u32 val) { return (u32)(s32(val) << 29 >> 29); }
void decodeETC(u32 u, u32 v, u64 colourData, u32 alpha, u8* outData) {
static constexpr u32 modifiers[8][2] = {
{2, 8}, {5, 17}, {9, 29}, {13, 42}, {18, 60}, {24, 80}, {33, 106}, {47, 183},
};
// Parse colour data for 4x4 block
const u32 subindices = getBits<0, 16, u32>(colourData);
const u32 negationFlags = getBits<16, 16, u32>(colourData);
const bool flip = getBit<32>(colourData);
const bool diffMode = getBit<33>(colourData);
// Note: index1 is indeed stored on the higher bits, with index2 in the lower bits
const u32 tableIndex1 = getBits<37, 3, u32>(colourData);
const u32 tableIndex2 = getBits<34, 3, u32>(colourData);
const u32 texelIndex = u * 4 + v; // Index of the texel in the block
if (flip) std::swap(u, v);
s32 r, g, b;
if (diffMode) {
r = getBits<59, 5, s32>(colourData);
g = getBits<51, 5, s32>(colourData);
b = getBits<43, 5, s32>(colourData);
if (u >= 2) {
r += signExtend3To32(getBits<56, 3, u32>(colourData));
g += signExtend3To32(getBits<48, 3, u32>(colourData));
b += signExtend3To32(getBits<40, 3, u32>(colourData));
}
// Expand from 5 to 8 bits per channel
r = Colour::convert5To8Bit(r);
g = Colour::convert5To8Bit(g);
b = Colour::convert5To8Bit(b);
} else {
if (u < 2) {
r = getBits<60, 4, s32>(colourData);
g = getBits<52, 4, s32>(colourData);
b = getBits<44, 4, s32>(colourData);
} else {
r = getBits<56, 4, s32>(colourData);
g = getBits<48, 4, s32>(colourData);
b = getBits<40, 4, s32>(colourData);
}
// Expand from 4 to 8 bits per channel
r = Colour::convert4To8Bit(r);
g = Colour::convert4To8Bit(g);
b = Colour::convert4To8Bit(b);
}
const u32 index = (u < 2) ? tableIndex1 : tableIndex2;
s32 modifier = modifiers[index][(subindices >> texelIndex) & 1];
if (((negationFlags >> texelIndex) & 1) != 0) {
modifier = -modifier;
}
r = std::clamp(r + modifier, 0, 255);
g = std::clamp(g + modifier, 0, 255);
b = std::clamp(b + modifier, 0, 255);
*outData++ = r;
*outData++ = g;
*outData++ = b;
*outData++ = alpha;
}
template <bool hasAlpha>
void getTexelETC(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
// Pixel offset of the 8x8 tile based on u, v and the width of the texture
u32 offs = ((u & ~7) * 8) + ((v & ~7) * size.u());
if (!hasAlpha) {
offs >>= 1;
}
// In-tile offsets for u/v
u &= 7;
v &= 7;
// ETC1(A4) also subdivide the 8x8 tile to 4 4x4 tiles
// Each tile is 8 bytes for ETC1, but since ETC1A4 has 4 alpha bits per pixel, that becomes 16 bytes
const u32 subTileSize = hasAlpha ? 16 : 8;
const u32 subTileIndex = (u / 4) + 2 * (v / 4); // Which of the 4 subtiles is this texel in?
// In-subtile offsets for u/v
u &= 3;
v &= 3;
offs += subTileSize * subTileIndex;
u32 alpha;
const u64* ptr = reinterpret_cast<const u64*>(inData.data() + offs); // Cast to u64*
if (hasAlpha) {
// First 64 bits of the 4x4 subtile are alpha data
const u64 alphaData = *ptr++;
alpha = Colour::convert4To8Bit((alphaData >> (4 * (u * 4 + v))) & 0xf);
} else {
alpha = 0xff; // ETC1 without alpha uses ff for every pixel
}
// Next 64 bits of the subtile are colour data
u64 colourData = *ptr;
decodeETC(u, v, colourData, alpha, outData);
}
void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
getTexelETC<false>(size, u, v, inData, outData);
}
void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
getTexelETC<true>(size, u, v, inData, outData);
}

View file

@ -885,17 +885,10 @@ void RendererVK::display() {
}
}
// DynamicLoader is in a different namespace in different versions of Vulkan-Hpp
#if VK_HEADER_VERSION >= 301
using VulkanDynamicLoader = vk::detail::DynamicLoader;
#else
using VulkanDynamicLoader = vk::DynamicLoader;
#endif
void RendererVK::initGraphicsContext(SDL_Window* window) {
targetWindow = window;
// Resolve all instance function pointers
static VulkanDynamicLoader dl;
static vk::DynamicLoader dl;
VULKAN_HPP_DEFAULT_DISPATCHER.init(dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"));
// Create Instance
@ -1595,4 +1588,4 @@ void RendererVK::deinitGraphicsContext() {
// TODO: Make it so that depth and colour buffers get written back to 3DS memory
printf("RendererVK::DeinitGraphicsContext called\n");
}
}

View file

@ -391,7 +391,7 @@ void APTService::setScreencapPostPermission(u32 messagePointer) {
void APTService::getSharedFont(u32 messagePointer) {
log("APT::GetSharedFont\n");
const u32 fontVaddr = kernel.getSharedFontVaddr();
constexpr u32 fontVaddr = 0x18000000;
mem.write32(messagePointer, IPC::responseHeader(0x44, 2, 2));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, fontVaddr);

View file

@ -18,7 +18,6 @@ namespace CFGCommands {
GetSystemModel = 0x00050000,
TranslateCountryInfo = 0x00080080,
GetCountryCodeString = 0x00090040,
GetCountryCodeID = 0x000A0040,
IsFangateSupported = 0x000B0000,
SetConfigInfoBlk4 = 0x04020082,
@ -51,7 +50,6 @@ void CFGService::handleSyncRequest(u32 messagePointer, CFGService::Type type) {
if (type != Type::NOR) {
switch (command) {
case CFGCommands::GetConfigInfoBlk2: [[likely]] getConfigInfoBlk2(messagePointer); break;
case CFGCommands::GetCountryCodeString: getCountryCodeString(messagePointer); break;
case CFGCommands::GetCountryCodeID: getCountryCodeID(messagePointer); break;
case CFGCommands::GetRegionCanadaUSA: getRegionCanadaUSA(messagePointer); break;
case CFGCommands::GetSystemModel: getSystemModel(messagePointer); break;
@ -317,24 +315,6 @@ void CFGService::getCountryCodeID(u32 messagePointer) {
}
}
void CFGService::getCountryCodeString(u32 messagePointer) {
const u16 id = mem.read16(messagePointer + 4);
log("CFG::getCountryCodeString (id = %04X)\n", id);
mem.write32(messagePointer, IPC::responseHeader(0x09, 2, 0));
for (auto [string, code] : countryCodeToTableIDMap) {
if (code == id) {
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, u32(string));
return;
}
}
// Code is not a valid country code, return an appropriate error
mem.write32(messagePointer + 4, 0xD90103FA);
}
void CFGService::secureInfoGetByte101(u32 messagePointer) {
log("CFG::SecureInfoGetByte101\n");

View file

@ -19,11 +19,7 @@ void HTTPService::handleSyncRequest(u32 messagePointer) {
case HTTPCommands::CreateRootCertChain: createRootCertChain(messagePointer); break;
case HTTPCommands::Initialize: initialize(messagePointer); break;
case HTTPCommands::RootCertChainAddDefaultCert: rootCertChainAddDefaultCert(messagePointer); break;
default:
Helpers::warn("HTTP service requested. Command: %08X\n", command);
mem.write32(messagePointer + 4, Result::FailurePlaceholder);
break;
default: Helpers::panic("HTTP service requested. Command: %08X\n", command);
}
}

View file

@ -22,7 +22,6 @@ namespace CROHeader {
NameOffset = 0x084,
NextCRO = 0x088,
PrevCRO = 0x08C,
FixedSize = 0x98,
OnUnresolved = 0x0AC,
CodeOffset = 0x0B0,
DataOffset = 0x0B8,
@ -168,10 +167,6 @@ public:
return mem.read32(croPointer + CROHeader::PrevCRO);
}
u32 getFixedSize() {
return mem.read32(croPointer + CROHeader::FixedSize);
}
void setNextCRO(u32 nextCRO) {
mem.write32(croPointer + CROHeader::NextCRO, nextCRO);
}
@ -1253,7 +1248,8 @@ void LDRService::initialize(u32 messagePointer) {
Helpers::panic("Failed to rebase CRS");
}
kernel.clearInstructionCacheRange(mapVaddr, size);
kernel.clearInstructionCache();
loadedCRS = mapVaddr;
mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 0));
@ -1282,6 +1278,8 @@ void LDRService::linkCRO(u32 messagePointer) {
Helpers::panic("Failed to link CRO");
}
kernel.clearInstructionCache();
mem.write32(messagePointer, IPC::responseHeader(0x6, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}
@ -1348,7 +1346,8 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
// TODO: add fixing
cro.fix(fixLevel);
kernel.clearInstructionCacheRange(mapVaddr, size);
kernel.clearInstructionCache();
if (isNew) {
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0));
@ -1378,6 +1377,7 @@ void LDRService::unloadCRO(u32 messagePointer) {
}
CRO cro(mem, mapVaddr, true);
cro.unregisterCRO(loadedCRS);
if (!cro.unlink(loadedCRS)) {
@ -1388,7 +1388,8 @@ void LDRService::unloadCRO(u32 messagePointer) {
Helpers::panic("Failed to unrebase CRO");
}
kernel.clearInstructionCacheRange(mapVaddr, cro.getFixedSize());
kernel.clearInstructionCache();
mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}

View file

@ -105,18 +105,13 @@ std::filesystem::path Emulator::getConfigPath() {
if constexpr (Helpers::isAndroid()) {
return getAndroidAppPath() / "config.toml";
} else {
std::filesystem::path localPath = std::filesystem::current_path() / "config.toml";
if (std::filesystem::exists(localPath)) {
return localPath;
} else {
return getAppDataRoot() / "config.toml";
}
return std::filesystem::current_path() / "config.toml";
}
}
#endif
void Emulator::step() {}
void Emulator::render() {}
// Only resume if a ROM is properly loaded
void Emulator::resume() {
@ -473,4 +468,4 @@ void Emulator::reloadSettings() {
}
}
#endif
}
}

View file

@ -11,7 +11,7 @@ FrontendSettings::Theme FrontendSettings::themeFromString(std::string inString)
std::transform(inString.begin(), inString.end(), inString.begin(), [](unsigned char c) { return std::tolower(c); });
static const std::unordered_map<std::string, Theme> map = {
{"system", Theme::System}, {"light", Theme::Light}, {"dark", Theme::Dark}, {"greetingscat", Theme::GreetingsCat}, {"cream", Theme::Cream}, {"oled", Theme::Oled}
{"system", Theme::System}, {"light", Theme::Light}, {"dark", Theme::Dark}, {"greetingscat", Theme::GreetingsCat}, {"cream", Theme::Cream},
};
if (auto search = map.find(inString); search != map.end()) {
@ -28,7 +28,6 @@ const char* FrontendSettings::themeToString(Theme theme) {
case Theme::Light: return "light";
case Theme::GreetingsCat: return "greetingscat";
case Theme::Cream: return "cream";
case Theme::Oled: return "oled";
case Theme::Dark:
default: return "dark";
@ -40,7 +39,7 @@ FrontendSettings::WindowIcon FrontendSettings::iconFromString(std::string inStri
static const std::unordered_map<std::string, WindowIcon> map = {
{"rpog", WindowIcon::Rpog}, {"rsyn", WindowIcon::Rsyn}, {"rcow", WindowIcon::Rcow},
{"rnap", WindowIcon::Rnap}, {"skyemu", WindowIcon::SkyEmu}, {"runpog", WindowIcon::Runpog},
{"rnap", WindowIcon::Rnap}, {"skyemu", WindowIcon::SkyEmu},
};
if (auto search = map.find(inString); search != map.end()) {
@ -57,7 +56,6 @@ const char* FrontendSettings::iconToString(WindowIcon icon) {
case WindowIcon::Rcow: return "rcow";
case WindowIcon::Rnap: return "rnap";
case WindowIcon::SkyEmu: return "skyemu";
case WindowIcon::Runpog: return "runpog";
case WindowIcon::Rpog:
default: return "rpog";

View file

@ -1,6 +1,4 @@
#include <metal_stdlib>
#include <TargetConditionals.h>
using namespace metal;
struct BasicVertexOut {
@ -221,6 +219,12 @@ struct Globals {
uint GPUREG_LIGHTING_LUTINPUT_SELECT;
uint GPUREG_LIGHTi_CONFIG;
// HACK
//bool lightingEnabled;
//uint8_t lightingNumLights;
//uint32_t lightingConfig1;
//uint16_t alphaControl;
float3 normal;
};
@ -651,16 +655,15 @@ float4 performLogicOp(LogicOp logicOp, float4 s, float4 d) {
return as_type<float4>(performLogicOpU(logicOp, as_type<uint4>(s), as_type<uint4>(d)));
}
// iOS simulator doesn't support fb fetch, so don't enable it
#ifndef TARGET_OS_SIMULATOR
#define PREVIOUS_COLOR_DECL float4 prevColor [[color(0)]],
#else
#define PREVIOUS_COLOR_DECL
#endif
fragment float4 fragmentDraw(DrawVertexOut in [[stage_in]], PREVIOUS_COLOR_DECL constant PicaRegs& picaRegs [[buffer(0)]], constant FragTEV& tev [[buffer(1)]], constant LogicOp& logicOp [[buffer(2)]], constant uint2& lutSlices [[buffer(3)]], texture2d<float> tex0 [[texture(0)]], texture2d<float> tex1 [[texture(1)]], texture2d<float> tex2 [[texture(2)]], texture2d_array<float> texLightingLut [[texture(3)]], texture1d_array<float> texFogLut [[texture(4)]], sampler samplr0 [[sampler(0)]], sampler samplr1 [[sampler(1)]], sampler samplr2 [[sampler(2)]], sampler linearSampler [[sampler(3)]]) {
fragment float4 fragmentDraw(DrawVertexOut in [[stage_in]], float4 prevColor [[color(0)]], constant PicaRegs& picaRegs [[buffer(0)]], constant FragTEV& tev [[buffer(1)]], constant LogicOp& logicOp [[buffer(2)]], constant uint2& lutSlices [[buffer(3)]], texture2d<float> tex0 [[texture(0)]], texture2d<float> tex1 [[texture(1)]], texture2d<float> tex2 [[texture(2)]], texture2d_array<float> texLightingLut [[texture(3)]], texture1d_array<float> texFogLut [[texture(4)]], sampler samplr0 [[sampler(0)]], sampler samplr1 [[sampler(1)]], sampler samplr2 [[sampler(2)]], sampler linearSampler [[sampler(3)]]) {
Globals globals;
// HACK
//globals.lightingEnabled = picaRegs.read(0x008Fu) != 0u;
//globals.lightingNumLights = picaRegs.read(0x01C2u);
//globals.lightingConfig1 = picaRegs.read(0x01C4u);
//globals.alphaControl = picaRegs.read(0x104);
globals.tevSources[0] = in.color;
if (lightingEnabled) {
calcLighting(globals, in, picaRegs, texLightingLut, lutSlices.x, linearSampler, globals.tevSources[1], globals.tevSources[2]);
@ -752,9 +755,5 @@ fragment float4 fragmentDraw(DrawVertexOut in [[stage_in]], PREVIOUS_COLOR_DECL
}
}
#ifndef TARGET_OS_SIMULATOR
return performLogicOp(logicOp, color, prevColor);
#else
return performLogicOp(logicOp, color, float4(0.0));
#endif
}
}

View file

@ -1,10 +0,0 @@
#version 310 es
precision mediump float;
in vec2 UV;
out vec4 FragColor;
uniform sampler2D u_texture;
void main() {
FragColor = texture(u_texture, UV);
}

View file

@ -1,25 +0,0 @@
#version 310 es
precision mediump float;
out vec2 UV;
void main() {
const vec4 positions[4] = vec4[](
vec4(-1.0, 1.0, 1.0, 1.0), // Top-left
vec4(1.0, 1.0, 1.0, 1.0), // Top-right
vec4(-1.0, -1.0, 1.0, 1.0), // Bottom-left
vec4(1.0, -1.0, 1.0, 1.0) // Bottom-right
);
// The 3DS displays both screens' framebuffer rotated 90 deg counter clockwise
// So we adjust our texcoords accordingly
const vec2 texcoords[4] = vec2[](
vec2(1.0, 1.0), // Top-right
vec2(1.0, 0.0), // Bottom-right
vec2(0.0, 1.0), // Top-left
vec2(0.0, 0.0) // Bottom-left
);
gl_Position = positions[gl_VertexID];
UV = texcoords[gl_VertexID];
}

View file

@ -118,7 +118,6 @@ void HydraCore::resetContext() {
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
Helpers::panic("OpenGL ES init failed");
}
emulator->getRenderer()->setupGLES();
#else
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
Helpers::panic("OpenGL init failed");

View file

@ -1,38 +0,0 @@
#import <Foundation/Foundation.h>
extern "C" {
#include "ios_driver.h"
}
// Apple's Foundation headers define some macros globablly that create issues with our own code, so remove the definitions
#undef ABS
#undef NO
#include <memory>
#include "emulator.hpp"
// The Objective-C++ bridge functions must be exported without name mangling in order for the SwiftUI frontend to be able to call them
#define IOS_EXPORT extern "C" __attribute__((visibility("default")))
std::unique_ptr<Emulator> emulator = nullptr;
HIDService* hidService = nullptr;
IOS_EXPORT void iosCreateEmulator() {
printf("Creating emulator\n");
emulator = std::make_unique<Emulator>();
hidService = &emulator->getServiceManager().getHID();
emulator->initGraphicsContext(nullptr);
}
IOS_EXPORT void iosRunFrame(CAMetalLayer* layer) {
void* layerBridged = (__bridge void*)layer;
emulator->getRenderer()->setMTKLayer(layerBridged);
emulator->runFrame();
}
IOS_EXPORT void iosLoadROM(NSString* pathNS) {
auto path = std::filesystem::path([pathNS UTF8String]);
emulator->loadROM(path);
}

View file

@ -78,7 +78,6 @@ AlberFunction(void, Initialize)(JNIEnv* env, jobject obj) {
}
__android_log_print(ANDROID_LOG_INFO, "AlberDriver", "OpenGL ES %d.%d", GLVersion.major, GLVersion.minor);
emulator->getRenderer()->setupGLES();
emulator->initGraphicsContext(nullptr);
}
@ -154,6 +153,7 @@ int AndroidUtils::openDocument(const char* path, const char* perms) {
jstring uri = env->NewStringUTF(path);
jstring jmode = env->NewStringUTF(perms);
jint result = env->CallStaticIntMethod(alberClass, alberClassOpenDocument, uri, jmode);
env->DeleteLocalRef(uri);

View file

@ -17,8 +17,7 @@ static retro_input_state_t inputStateCallback;
static retro_hw_render_callback hwRender;
static std::filesystem::path savePath;
static bool screenTouched = false;
static bool usingGLES = false;
static bool screenTouched;
std::unique_ptr<Emulator> emulator;
RendererGL* renderer;
@ -36,19 +35,15 @@ static void* getGLProcAddress(const char* name) {
}
static void videoResetContext() {
if (usingGLES) {
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
Helpers::panic("OpenGL ES init failed");
}
emulator->getRenderer()->setupGLES();
#ifdef USING_GLES
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
Helpers::panic("OpenGL ES init failed");
}
else {
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
Helpers::panic("OpenGL init failed");
}
#else
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
Helpers::panic("OpenGL init failed");
}
#endif
emulator->initGraphicsContext(nullptr);
}
@ -78,7 +73,6 @@ static bool setHWRender(retro_hw_context_type type) {
hwRender.version_minor = 1;
if (envCallback(RETRO_ENVIRONMENT_SET_HW_RENDER, &hwRender)) {
usingGLES = true;
return true;
}
break;
@ -389,8 +383,6 @@ void retro_run() {
emulator->runFrame();
videoCallback(RETRO_HW_FRAME_BUFFER_VALID, emulator->width, emulator->height, 0);
// Call audio batch callback
emulator->getAudioDevice().renderBatch(audioBatchCallback);
}
void retro_set_controller_port_device(uint port, uint device) {}

View file

@ -4,6 +4,4 @@
#define MA_NO_ENCODING
#define MINIAUDIO_IMPLEMENTATION
#ifndef PANDA3DS_IOS
#include "miniaudio.h"
#endif
#include "miniaudio.h"

View file

@ -1,8 +0,0 @@
// We do not need the ability to be able to encode or decode audio files for the time being
// So we disable said functionality to make the executable smaller.
#define MA_NO_DECODING
#define MA_NO_ENCODING
#define MINIAUDIO_IMPLEMENTATION
// On iOS we have to compile miniaudio as Obj-C
#include "miniaudio.h"

View file

@ -71,7 +71,6 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, MainWindowCallback win
themeSelect->addItem(tr("Dark"));
themeSelect->addItem(tr("Greetings Cat"));
themeSelect->addItem(tr("Cream"));
themeSelect->addItem(tr("OLED"));
themeSelect->setCurrentIndex(static_cast<int>(config.frontendSettings.theme));
connect(themeSelect, &QComboBox::currentIndexChanged, this, [&](int index) {
config.frontendSettings.theme = static_cast<Theme>(index);
@ -87,7 +86,6 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, MainWindowCallback win
iconSelect->addItem(tr("Sleepy panda"));
iconSelect->addItem(tr("Cow panda"));
iconSelect->addItem(tr("The penguin from SkyEmu"));
iconSelect->addItem(tr("Unpog"));
iconSelect->setCurrentIndex(static_cast<int>(config.frontendSettings.icon));
connect(iconSelect, &QComboBox::currentIndexChanged, this, [&](int index) {
@ -439,34 +437,6 @@ void ConfigWindow::setTheme(Theme theme) {
break;
}
case Theme::Oled: {
QApplication::setStyle(QStyleFactory::create("Fusion"));
QPalette p;
p.setColor(QPalette::Window, Qt::black);
p.setColor(QPalette::WindowText, Qt::white);
p.setColor(QPalette::Base, Qt::black);
p.setColor(QPalette::AlternateBase, Qt::black);
p.setColor(QPalette::ToolTipBase, Qt::black);
p.setColor(QPalette::ToolTipText, Qt::white);
p.setColor(QPalette::Text, Qt::white);
p.setColor(QPalette::Button, QColor(5, 5, 5));
p.setColor(QPalette::ButtonText, Qt::white);
p.setColor(QPalette::BrightText, Qt::red);
p.setColor(QPalette::Link, QColor(42, 130, 218));
p.setColor(QPalette::Highlight, QColor(42, 130, 218));
p.setColor(QPalette::HighlightedText, Qt::black);
qApp->setPalette(p);
qApp->setStyleSheet("QLineEdit {"
"background-color: #000000; color: #ffffff; border: 1px solid #a0a0a0; "
"border-radius: 4px; padding: 5px; }"
"QCheckBox::indicator:unchecked {"
"border: 1px solid #808080; border-radius: 4px; }");
break;
}
case Theme::System: {
qApp->setPalette(this->style()->standardPalette());
qApp->setStyle(QStyleFactory::create("WindowsVista"));
@ -484,7 +454,6 @@ void ConfigWindow::setIcon(WindowIcon icon) {
case WindowIcon::Rnap: updateIcon(":/docs/img/rnap_icon.png"); break;
case WindowIcon::Rcow: updateIcon(":/docs/img/rcow_icon.png"); break;
case WindowIcon::SkyEmu: updateIcon(":/docs/img/skyemu_icon.png"); break;
case WindowIcon::Runpog: updateIcon(":/docs/img/runpog_icon.png"); break;
case WindowIcon::Rpog:
default: updateIcon(":/docs/img/rpog_icon.png"); break;

View file

@ -7,5 +7,6 @@ int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow window(&app);
window.show();
return app.exec();
}

View file

@ -22,13 +22,14 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
// Enable drop events for loading ROMs
setAcceptDrops(true);
resize(800, 240 * 4);
show();
// We pass a callback to the screen widget that will be triggered every time we resize the screen
screen = new ScreenWidget([this](u32 width, u32 height) { handleScreenResize(width, height); }, this);
setCentralWidget(screen);
screen->show();
appRunning = true;
// Set our menu bar up
menuBar = new QMenuBar(nullptr);
@ -139,10 +140,6 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
glContext->MakeCurrent();
glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0);
if (glContext->IsGLES()) {
emu->getRenderer()->setupGLES();
}
emu->initGraphicsContext(glContext);
} else if (usingVk) {
Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!");
@ -698,4 +695,4 @@ void MainWindow::setupControllerSensors(SDL_GameController* controller) {
if (haveAccelerometer) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
}
}
}

View file

@ -29,7 +29,6 @@ ScreenWidget::ScreenWidget(ResizeCallback resizeCallback, QWidget* parent) : QWi
setAttribute(Qt::WA_KeyCompression, false);
setFocusPolicy(Qt::StrongFocus);
setMouseTracking(true);
show();
if (!createGLContext()) {
Helpers::panic("Failed to create GL context for display");
@ -61,12 +60,11 @@ void ScreenWidget::resizeSurface(u32 width, u32 height) {
}
bool ScreenWidget::createGLContext() {
// List of GL context versions we will try. Anything 4.1+ is good for desktop OpenGL, and 3.1+ for OpenGL ES
static constexpr std::array<GL::Context::Version, 8> versionsToTry = {
// List of GL context versions we will try. Anything 4.1+ is good
static constexpr std::array<GL::Context::Version, 6> versionsToTry = {
GL::Context::Version{GL::Context::Profile::Core, 4, 6}, GL::Context::Version{GL::Context::Profile::Core, 4, 5},
GL::Context::Version{GL::Context::Profile::Core, 4, 4}, GL::Context::Version{GL::Context::Profile::Core, 4, 3},
GL::Context::Version{GL::Context::Profile::Core, 4, 2}, GL::Context::Version{GL::Context::Profile::Core, 4, 1},
GL::Context::Version{GL::Context::Profile::ES, 3, 2}, GL::Context::Version{GL::Context::Profile::ES, 3, 1},
};
std::optional<WindowInfo> windowInfo = getWindowInfo();
@ -74,10 +72,6 @@ bool ScreenWidget::createGLContext() {
this->windowInfo = *windowInfo;
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
if (glContext == nullptr) {
return false;
}
glContext->DoneCurrent();
}
@ -85,7 +79,7 @@ bool ScreenWidget::createGLContext() {
}
qreal ScreenWidget::devicePixelRatioFromScreen() const {
const QScreen* screenForRatio = windowHandle()->screen();
const QScreen* screenForRatio = window()->windowHandle()->screen();
if (!screenForRatio) {
screenForRatio = QGuiApplication::primaryScreen();
}

View file

@ -46,13 +46,12 @@ struct LanguageInfo {
// Please keep this list mostly in alphabetical order.
// Also, for Unicode characters in language names, use Unicode keycodes instead of writing out the name,
// as some compilers/toolchains may not enjoy Unicode in source files.
static std::array<LanguageInfo, 6> languages = {
static std::array<LanguageInfo, 5> languages = {
LanguageInfo(QStringLiteral(u"English"), "en"), // English
LanguageInfo(QStringLiteral(u"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"), "el"), // Greek
LanguageInfo(QStringLiteral(u"Espa\u00F1ol"), "es"), // Spanish
LanguageInfo(QStringLiteral(u"Nederlands"), "nl"), // Dutch
LanguageInfo(QStringLiteral(u"Portugu\u00EAs (Brasil)"), "pt_br"), // Portuguese (Brazilian)
LanguageInfo(QStringLiteral(u"Svenska"), "sv"), // Swedish
LanguageInfo(QStringLiteral(u"Portugu\u00EAs (Brasil)"), "pt_br") // Portuguese (Brazilian)
};
QComboBox* ConfigWindow::createLanguageSelect() {

View file

@ -71,27 +71,11 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
glContext = SDL_GL_CreateContext(window);
if (glContext == nullptr) {
Helpers::warn("OpenGL context creation failed: %s\nTrying again with OpenGL ES.", SDL_GetError());
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
}
// Some low end devices (eg RPi, emulation handhelds) don't support desktop GL, but only OpenGL ES, so fall back to that if GL context
// creation failed
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
glContext = SDL_GL_CreateContext(window);
if (glContext == nullptr) {
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
}
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
Helpers::panic("OpenGL init failed");
}
emu.getRenderer()->setupGLES();
} else {
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
Helpers::panic("OpenGL init failed");
}
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
Helpers::panic("OpenGL init failed");
}
SDL_GL_SetSwapInterval(config.vsyncEnabled ? 1 : 0);

View file

@ -1,2 +0,0 @@
libAlber.dylib
Alber/Headers/ios_driver.h

View file

@ -1,7 +0,0 @@
#pragma once
#include <Foundation/Foundation.h>
#include <QuartzCore/QuartzCore.h>
void iosCreateEmulator();
void iosLoadROM(NSString* pathNS);
void iosRunFrame(CAMetalLayer* layer);

View file

@ -1,5 +0,0 @@
module AlberDriver {
umbrella "Headers" // for multiple files
link "libAlber"
export *
}

View file

@ -1,587 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 70;
objects = {
/* Begin PBXBuildFile section */
4F798C782D8747B000F5D23F /* libAlber.dylib in Copy Files */ = {isa = PBXBuildFile; fileRef = 4F798C772D8747B000F5D23F /* libAlber.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
4F798C7A2D8747F400F5D23F /* libAlber.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F798C792D8747B800F5D23F /* libAlber.dylib */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
4F6E8FD32D77C0140025DD0D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4F6E8FBA2D77C0120025DD0D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4F6E8FC12D77C0120025DD0D;
remoteInfo = Pandios;
};
4F6E8FDD2D77C0140025DD0D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4F6E8FBA2D77C0120025DD0D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4F6E8FC12D77C0120025DD0D;
remoteInfo = Pandios;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
4F9EEBE82D78898B00E0B72D /* Copy Files */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
4F798C782D8747B000F5D23F /* libAlber.dylib in Copy Files */,
);
name = "Copy Files";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
4F6E8FC22D77C0120025DD0D /* Pandios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Pandios.app; sourceTree = BUILT_PRODUCTS_DIR; };
4F6E8FD22D77C0140025DD0D /* PandiosTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PandiosTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4F6E8FDC2D77C0140025DD0D /* PandiosUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PandiosUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4F798C772D8747B000F5D23F /* libAlber.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libAlber.dylib; path = ../../build/libAlber.dylib; sourceTree = "<group>"; };
4F798C792D8747B800F5D23F /* libAlber.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libAlber.dylib; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
4F6E8FC42D77C0120025DD0D /* Pandios */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Pandios; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
4F6E8FCF2D77C0140025DD0D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
4F6E8FD92D77C0140025DD0D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
4F9EEBF82D78963D00E0B72D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4F798C7A2D8747F400F5D23F /* libAlber.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
4F6E8FB92D77C0120025DD0D = {
isa = PBXGroup;
children = (
4F798C772D8747B000F5D23F /* libAlber.dylib */,
4F6E8FC42D77C0120025DD0D /* Pandios */,
4F9EEBF62D7895D700E0B72D /* Frameworks */,
4F6E8FC32D77C0120025DD0D /* Products */,
);
sourceTree = "<group>";
};
4F6E8FC32D77C0120025DD0D /* Products */ = {
isa = PBXGroup;
children = (
4F6E8FC22D77C0120025DD0D /* Pandios.app */,
4F6E8FD22D77C0140025DD0D /* PandiosTests.xctest */,
4F6E8FDC2D77C0140025DD0D /* PandiosUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
4F9EEBF62D7895D700E0B72D /* Frameworks */ = {
isa = PBXGroup;
children = (
4F798C792D8747B800F5D23F /* libAlber.dylib */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
4F6E8FC12D77C0120025DD0D /* Pandios */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4F6E8FE62D77C0140025DD0D /* Build configuration list for PBXNativeTarget "Pandios" */;
buildPhases = (
4F6E8FBE2D77C0120025DD0D /* Sources */,
4F6E8FC02D77C0120025DD0D /* Resources */,
4F9EEBE82D78898B00E0B72D /* Copy Files */,
4F9EEBF82D78963D00E0B72D /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
4F6E8FC42D77C0120025DD0D /* Pandios */,
);
name = Pandios;
packageProductDependencies = (
);
productName = Pandios;
productReference = 4F6E8FC22D77C0120025DD0D /* Pandios.app */;
productType = "com.apple.product-type.application";
};
4F6E8FD12D77C0140025DD0D /* PandiosTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4F6E8FE92D77C0140025DD0D /* Build configuration list for PBXNativeTarget "PandiosTests" */;
buildPhases = (
4F6E8FCE2D77C0140025DD0D /* Sources */,
4F6E8FCF2D77C0140025DD0D /* Frameworks */,
4F6E8FD02D77C0140025DD0D /* Resources */,
);
buildRules = (
);
dependencies = (
4F6E8FD42D77C0140025DD0D /* PBXTargetDependency */,
);
name = PandiosTests;
packageProductDependencies = (
);
productName = PandiosTests;
productReference = 4F6E8FD22D77C0140025DD0D /* PandiosTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
4F6E8FDB2D77C0140025DD0D /* PandiosUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4F6E8FEC2D77C0140025DD0D /* Build configuration list for PBXNativeTarget "PandiosUITests" */;
buildPhases = (
4F6E8FD82D77C0140025DD0D /* Sources */,
4F6E8FD92D77C0140025DD0D /* Frameworks */,
4F6E8FDA2D77C0140025DD0D /* Resources */,
);
buildRules = (
);
dependencies = (
4F6E8FDE2D77C0140025DD0D /* PBXTargetDependency */,
);
name = PandiosUITests;
packageProductDependencies = (
);
productName = PandiosUITests;
productReference = 4F6E8FDC2D77C0140025DD0D /* PandiosUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
4F6E8FBA2D77C0120025DD0D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1620;
LastUpgradeCheck = 1620;
TargetAttributes = {
4F6E8FC12D77C0120025DD0D = {
CreatedOnToolsVersion = 16.2;
};
4F6E8FD12D77C0140025DD0D = {
CreatedOnToolsVersion = 16.2;
TestTargetID = 4F6E8FC12D77C0120025DD0D;
};
4F6E8FDB2D77C0140025DD0D = {
CreatedOnToolsVersion = 16.2;
TestTargetID = 4F6E8FC12D77C0120025DD0D;
};
};
};
buildConfigurationList = 4F6E8FBD2D77C0120025DD0D /* Build configuration list for PBXProject "Pandios" */;
compatibilityVersion = "Xcode 16.0.Superseded.1";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 4F6E8FB92D77C0120025DD0D;
minimizedProjectReferenceProxies = 1;
productRefGroup = 4F6E8FC32D77C0120025DD0D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
4F6E8FC12D77C0120025DD0D /* Pandios */,
4F6E8FD12D77C0140025DD0D /* PandiosTests */,
4F6E8FDB2D77C0140025DD0D /* PandiosUITests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
4F6E8FC02D77C0120025DD0D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
4F6E8FD02D77C0140025DD0D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
4F6E8FDA2D77C0140025DD0D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
4F6E8FBE2D77C0120025DD0D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
4F6E8FCE2D77C0140025DD0D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
4F6E8FD82D77C0140025DD0D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
4F6E8FD42D77C0140025DD0D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4F6E8FC12D77C0120025DD0D /* Pandios */;
targetProxy = 4F6E8FD32D77C0140025DD0D /* PBXContainerItemProxy */;
};
4F6E8FDE2D77C0140025DD0D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4F6E8FC12D77C0120025DD0D /* Pandios */;
targetProxy = 4F6E8FDD2D77C0140025DD0D /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
4F6E8FE42D77C0140025DD0D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
4F6E8FE52D77C0140025DD0D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
4F6E8FE72D77C0140025DD0D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Pandios/Preview Content\"";
DEVELOPMENT_TEAM = 877A43U8RR;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = Alber.Pandios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_INCLUDE_PATHS = "$(PROJECT_DIR)/Alber";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
4F6E8FE82D77C0140025DD0D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Pandios/Preview Content\"";
DEVELOPMENT_TEAM = 877A43U8RR;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = Alber.Pandios;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_INCLUDE_PATHS = "$(PROJECT_DIR)/Alber";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
4F6E8FEA2D77C0140025DD0D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = Alber.PandiosTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Pandios.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Pandios";
};
name = Debug;
};
4F6E8FEB2D77C0140025DD0D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = Alber.PandiosTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Pandios.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Pandios";
};
name = Release;
};
4F6E8FED2D77C0140025DD0D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = Alber.PandiosUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = Pandios;
};
name = Debug;
};
4F6E8FEE2D77C0140025DD0D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = Alber.PandiosUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = Pandios;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
4F6E8FBD2D77C0120025DD0D /* Build configuration list for PBXProject "Pandios" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4F6E8FE42D77C0140025DD0D /* Debug */,
4F6E8FE52D77C0140025DD0D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4F6E8FE62D77C0140025DD0D /* Build configuration list for PBXNativeTarget "Pandios" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4F6E8FE72D77C0140025DD0D /* Debug */,
4F6E8FE82D77C0140025DD0D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4F6E8FE92D77C0140025DD0D /* Build configuration list for PBXNativeTarget "PandiosTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4F6E8FEA2D77C0140025DD0D /* Debug */,
4F6E8FEB2D77C0140025DD0D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4F6E8FEC2D77C0140025DD0D /* Build configuration list for PBXNativeTarget "PandiosUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4F6E8FED2D77C0140025DD0D /* Debug */,
4F6E8FEE2D77C0140025DD0D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 4F6E8FBA2D77C0120025DD0D /* Project object */;
}

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View file

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Pandios.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>

View file

@ -1,11 +0,0 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -1,35 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -1,95 +0,0 @@
import AlberDriver
import SwiftUI
import MetalKit
import Darwin
var emulatorLock = NSLock()
class DocumentViewController: UIViewController, DocumentDelegate {
var documentPicker: DocumentPicker!
override func viewDidLoad() {
super.viewDidLoad()
/// set up the document picker
documentPicker = DocumentPicker(presentationController: self, delegate: self)
/// When the view loads (ie user opens the app) show the file picker
show()
}
/// callback from the document picker
func didPickDocument(document: Document?) {
if let pickedDoc = document {
let fileURL = pickedDoc.fileURL
print("Loading ROM", fileURL)
emulatorLock.lock()
iosLoadROM(fileURL.path(percentEncoded: false))
emulatorLock.unlock()
}
}
func show() {
documentPicker.displayPicker()
}
}
struct DocumentView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> DocumentViewController {
return DocumentViewController()
}
func updateUIViewController(_ uiViewController: DocumentViewController, context: Context) {
// No update needed
}
}
struct ContentView: UIViewRepresentable {
@State var showFileImporter = true
/*
func makeCoordinator() -> Renderer {
Renderer(self)
}
*/
func makeUIView(context: UIViewRepresentableContext<ContentView>) -> MTKView {
let mtkView = MTKView()
mtkView.preferredFramesPerSecond = 60
mtkView.enableSetNeedsDisplay = true
mtkView.isPaused = true
if let metalDevice = MTLCreateSystemDefaultDevice() {
mtkView.device = metalDevice
}
mtkView.framebufferOnly = false
mtkView.drawableSize = mtkView.frame.size
let dispatchQueue = DispatchQueue(label: "QueueIdentification", qos: .background)
let metalLayer = mtkView.layer as! CAMetalLayer;
dispatchQueue.async{
iosCreateEmulator()
while (true) {
emulatorLock.lock()
iosRunFrame(metalLayer);
emulatorLock.unlock()
}
}
return mtkView
}
func updateUIView(_ uiView: MTKView, context: UIViewRepresentableContext<ContentView>) {
print("Updating MTKView");
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
DocumentView();
ContentView();
}
}

View file

@ -1,75 +0,0 @@
// From https://gist.github.com/aheze/dbc7f9b452e4f86f2d8fe278b3c5001f
// DocumentPicker.swift
import UIKit
import MobileCoreServices
import UniformTypeIdentifiers
protocol DocumentDelegate: AnyObject {
func didPickDocument(document: Document?)
}
class Document: UIDocument {
var data: Data?
override func contents(forType typeName: String) throws -> Any {
guard let data = data else { return Data() }
return try NSKeyedArchiver.archivedData(withRootObject:data,
requiringSecureCoding: true)
}
override func load(fromContents contents: Any, ofType typeName:
String?) throws {
guard let data = contents as? Data else { return }
self.data = data
}
}
open class DocumentPicker: NSObject {
private var pickerController: UIDocumentPickerViewController?
private weak var presentationController: UIViewController?
private weak var delegate: DocumentDelegate?
private var pickedDocument: Document?
init(presentationController: UIViewController, delegate: DocumentDelegate) {
super.init()
self.presentationController = presentationController
self.delegate = delegate
}
public func displayPicker() {
self.pickerController = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.data])
self.pickerController!.delegate = self
self.presentationController?.present(self.pickerController!, animated: true)
}
}
extension DocumentPicker: UIDocumentPickerDelegate {
/// delegate method, when the user selects a file
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first else {
return
}
documentFromURL(pickedURL: url)
delegate?.didPickDocument(document: pickedDocument)
}
/// delegate method, when the user cancels
public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
delegate?.didPickDocument(document: nil)
}
private func documentFromURL(pickedURL: URL) {
/// start accessing the resource
let shouldStopAccessing = pickedURL.startAccessingSecurityScopedResource()
defer {
if shouldStopAccessing {
pickedURL.stopAccessingSecurityScopedResource()
}
}
NSFileCoordinator().coordinate(readingItemAt: pickedURL, error: NSErrorPointer.none) { (readURL) in
let document = Document(fileURL: readURL)
pickedDocument = document
}
}
}

View file

@ -1,11 +0,0 @@
import SwiftUI
@main
struct PandiosApp: App {
var body: some Scene {
WindowGroup {
ContentView()
DocumentView()
}
}
}

View file

@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -1,37 +0,0 @@
#!/bin/bash
# Settings for the SwiftUI frontend
ARCH=arm64
CONFIGURATION=Release
SDK=iphonesimulator
# Settings for the emulator core
EMULATOR_BUILD_TYPE=Release
# Simulator settings
RUN_SIMULATOR=false
# Fail on error
set -e
# Go to the parent directory and build the emulator core
cd ../..
cmake -B build -DENABLE_VULKAN=OFF -DBUILD_HYDRA_CORE=ON -DENABLE_USER_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=third_party/ios_toolchain/ios.toolchain.cmake -DPLATFORM=SIMULATORARM64 -DDEPLOYMENT_TARGET="13.0"
cmake --build build --config ${EMULATOR_BUILD_TYPE}
# Copy the bridging header and emulator dylib to the iOS folder
cp ./include/ios_driver.h ./src/pandios/Alber/Headers/ios_driver.h
cp ./build/libAlber.dylib ./src/pandios/
# Come back to the iOS directory, build the SwiftUI xcode project and link them together
cd src/pandios
xcodebuild build -configuration ${CONFIGURATION} -sdk ${SDK} -arch ${ARCH}
# To run the app in the simulator:
# Boot the iPhone, install the app on the iphone, then open the sim & launch the app
if [ "$RUN_SIMULATOR" = true ] ; then
xcrun simctl boot "iPhone 16 Pro"
xcrun simctl install "iPhone 16 Pro" "build/Release-iphonesimulator/Pandios.app"
open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app
xcrun simctl launch --console booted "Alber.Pandios"
fi

View file

@ -38,7 +38,6 @@ public class AppDataDocumentProvider extends DocumentsProvider {
Document.COLUMN_DISPLAY_NAME,
Document.COLUMN_MIME_TYPE,
Document.COLUMN_LAST_MODIFIED,
Document.COLUMN_FLAGS,
Document.COLUMN_SIZE
};
@ -102,7 +101,7 @@ public class AppDataDocumentProvider extends DocumentsProvider {
}
cursor.newRow()
.add(Document.COLUMN_DOCUMENT_ID, obtainDocumentId(file))
.add(Document.COLUMN_MIME_TYPE, file.isDirectory() ? Document.MIME_TYPE_DIR : "application/octet-stream")
.add(Document.COLUMN_MIME_TYPE, file.isDirectory() ? Document.MIME_TYPE_DIR : "application/octect-stream")
.add(Document.COLUMN_FLAGS, flags)
.add(Document.COLUMN_LAST_MODIFIED, file.lastModified())
.add(Document.COLUMN_DISPLAY_NAME, file.getName())
@ -158,13 +157,8 @@ public class AppDataDocumentProvider extends DocumentsProvider {
}
}
@Override
public void removeDocument(String documentId, String parentDocumentId) throws FileNotFoundException {
deleteDocument(documentId);
}
@Override
public ParcelFileDescriptor openDocument(String documentId, String mode, @Nullable CancellationSignal signal) throws FileNotFoundException {
return ParcelFileDescriptor.open(obtainFile(documentId), ParcelFileDescriptor.parseMode(mode));
}
}
}

View file

@ -3,8 +3,6 @@
#include <algorithm>
#include <unordered_map>
#include "PICA/gpu.hpp"
Renderer::Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs)
: gpu(gpu), regs(internalRegs), externalRegs(externalRegs) {}
Renderer::~Renderer() {}
@ -41,39 +39,3 @@ const char* Renderer::typeToString(RendererType rendererType) {
default: return "Invalid";
}
}
void Renderer::doSoftwareTextureCopy(u32 inputAddr, u32 outputAddr, u32 copySize, u32 inputWidth, u32 inputGap, u32 outputWidth, u32 outputGap) {
u8* inputPointer = gpu.getPointerPhys<u8>(inputAddr);
u8* outputPointer = gpu.getPointerPhys<u8>(outputAddr);
if (inputPointer == nullptr || outputPointer == nullptr) {
return;
}
u32 inputBytesLeft = inputWidth;
u32 outputBytesLeft = outputWidth;
u32 copyBytesLeft = copySize;
while (copyBytesLeft > 0) {
const u32 bytes = std::min<u32>({inputBytesLeft, outputBytesLeft, copyBytesLeft});
std::memcpy(outputPointer, inputPointer, bytes);
inputPointer += bytes;
outputPointer += bytes;
inputBytesLeft -= bytes;
outputBytesLeft -= bytes;
copyBytesLeft -= bytes;
// Apply input and output gap when an input or output line ends
if (inputBytesLeft == 0) {
inputBytesLeft = inputWidth;
inputPointer += inputGap;
}
if (outputBytesLeft == 0) {
outputBytesLeft = outputWidth;
outputPointer += outputGap;
}
}
}

2
third_party/SDL2 vendored

@ -1 +1 @@
Subproject commit f48a96a976b50d1faae70598e71bfaf8f4526347
Subproject commit 379d4780559690a9836444aeb5637f60953947be

View file

@ -1,945 +0,0 @@
# This file is part of the ios-cmake project. It was retrieved from
# https://github.com/leetal/ios-cmake.git, which is a fork of
# https://github.com/gerstrong/ios-cmake.git, which is a fork of
# https://github.com/cristeab/ios-cmake.git, which is a fork of
# https://code.google.com/p/ios-cmake/. Which in turn is based off of
# the Platform/Darwin.cmake and Platform/UnixPaths.cmake files which
# are included with CMake 2.8.4
#
# The ios-cmake project is licensed under the new BSD license.
#
# Copyright (c) 2014, Bogdan Cristea and LTE Engineering Software,
# Kitware, Inc., Insight Software Consortium. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# This file is based off of the Platform/Darwin.cmake and
# Platform/UnixPaths.cmake files which are included with CMake 2.8.4
# It has been altered for iOS development.
#
# Updated by Alex Stewart (alexs.mac@gmail.com)
#
# *****************************************************************************
# Now maintained by Alexander Widerberg (widerbergaren [at] gmail.com)
# under the BSD-3-Clause license
# https://github.com/leetal/ios-cmake
# *****************************************************************************
#
# INFORMATION / HELP
#
# The following options control the behaviour of this toolchain:
#
# PLATFORM: (default "OS64")
# OS = Build for iPhoneOS.
# OS64 = Build for arm64 iphoneOS.
# OS64COMBINED = Build for arm64 x86_64 iphoneOS. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY)
# SIMULATOR = Build for x86 i386 iphoneOS Simulator.
# SIMULATOR64 = Build for x86_64 iphoneOS Simulator.
# SIMULATORARM64 = Build for arm64 iphoneOS Simulator.
# TVOS = Build for arm64 tvOS.
# TVOSCOMBINED = Build for arm64 x86_64 tvOS. Combined into FAT STATIC lib (supported on 3.14+ of CMake with "-G Xcode" argument ONLY)
# SIMULATOR_TVOS = Build for x86_64 tvOS Simulator.
# WATCHOS = Build for armv7k arm64_32 for watchOS.
# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS. Combined into FAT STATIC lib (supported on 3.14+ of CMake with "-G Xcode" argument ONLY)
# SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator.
# MAC = Build for x86_64 macOS.
# MAC_ARM64 = Build for Apple Silicon macOS.
# MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS).
# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS
# MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS).
# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS
#
# CMAKE_OSX_SYSROOT: Path to the SDK to use. By default this is
# automatically determined from PLATFORM and xcodebuild, but
# can also be manually specified (although this should not be required).
#
# CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform
# being compiled for. By default this is automatically determined from
# CMAKE_OSX_SYSROOT, but can also be manually specified (although this should
# not be required).
#
# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 2.0 on watchOS and 9.0 on tvOS+iOS
#
# ENABLE_BITCODE: (1|0) Enables or disables bitcode support. Default 1 (true)
#
# ENABLE_ARC: (1|0) Enables or disables ARC support. Default 1 (true, ARC enabled by default)
#
# ENABLE_VISIBILITY: (1|0) Enables or disables symbol visibility support. Default 0 (false, visibility hidden by default)
#
# ENABLE_STRICT_TRY_COMPILE: (1|0) Enables or disables strict try_compile() on all Check* directives (will run linker
# to actually check if linking is possible). Default 0 (false, will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY)
#
# ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM
# OS = armv7 armv7s arm64 (if applicable)
# OS64 = arm64 (if applicable)
# SIMULATOR = i386
# SIMULATOR64 = x86_64
# SIMULATORARM64 = arm64
# TVOS = arm64
# SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated)
# WATCHOS = armv7k arm64_32 (if applicable)
# SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated)
# MAC = x86_64
# MAC_ARM64 = arm64
# MAC_CATALYST = x86_64
# MAC_CATALYST_ARM64 = arm64
#
# This toolchain defines the following properties (available via get_property()) for use externally:
#
# PLATFORM: The currently targeted platform.
# XCODE_VERSION: Version number (not including Build version) of Xcode detected.
# SDK_VERSION: Version of SDK being used.
# OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM).
# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" are overridden, this will *NOT* be set!
#
# This toolchain defines the following macros for use externally:
#
# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE XCODE_VARIANT)
# A convenience macro for setting xcode specific properties on targets.
# Available variants are: All, Release, RelWithDebInfo, Debug, MinSizeRel
# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1" "all").
#
# find_host_package (PROGRAM ARGS)
# A macro used to find executable programs on the host system, not within the
# environment. Thanks to the android-cmake project for providing the
# command.
#
cmake_minimum_required(VERSION 3.8.0)
# CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds.
if(DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN})
return()
endif()
set(ENV{_IOS_TOOLCHAIN_HAS_RUN} true)
###############################################################################
# OPTIONS #
###############################################################################
option(DROP_32_BIT "Drops the 32-bit targets universally." YES)
###############################################################################
# END OPTIONS #
###############################################################################
# List of supported platform values
list(APPEND _supported_platforms
"OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64"
"TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS"
"WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS"
"MAC" "MAC_ARM64"
"MAC_CATALYST" "MAC_CATALYST_ARM64")
# Cache what generator is used
set(USED_CMAKE_GENERATOR "${CMAKE_GENERATOR}")
# Check if using a CMake version capable of building combined FAT builds (simulator and target slices combined in one static lib)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14")
set(MODERN_CMAKE YES)
endif()
# Get the Xcode version being used.
# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs.
# Workaround: On first run (in which cache variables are always accessible), set an intermediary environment variable.
#
# NOTE: This pattern is used i many places in this toolchain to speed up checks of all sorts
if(DEFINED XCODE_VERSION_INT)
# Environment variables are always preserved.
set(ENV{_XCODE_VERSION_INT} "${XCODE_VERSION_INT}")
elseif(DEFINED ENV{_XCODE_VERSION_INT})
set(XCODE_VERSION_INT "$ENV{_XCODE_VERSION_INT}")
elseif(NOT DEFINED XCODE_VERSION_INT)
find_program(XCODEBUILD_EXECUTABLE xcodebuild)
if(NOT XCODEBUILD_EXECUTABLE)
message(FATAL_ERROR "xcodebuild not found. Please install either the standalone commandline tools or Xcode.")
endif()
execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version
OUTPUT_VARIABLE XCODE_VERSION_INT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX MATCH "Xcode [0-9\\.]+" XCODE_VERSION_INT "${XCODE_VERSION_INT}")
string(REGEX REPLACE "Xcode ([0-9\\.]+)" "\\1" XCODE_VERSION_INT "${XCODE_VERSION_INT}")
set(XCODE_VERSION_INT "${XCODE_VERSION_INT}" CACHE INTERNAL "")
endif()
# Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur)
# if you don't set a deployment target it will be set the way you only get 64-bit builds
if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0)
# Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...)
set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64")
endif()
# Check if the platform variable is set
if(DEFINED PLATFORM)
# Environment variables are always preserved.
set(ENV{_PLATFORM} "${PLATFORM}")
elseif(DEFINED ENV{_PLATFORM})
set(PLATFORM "$ENV{_PLATFORM}")
elseif(NOT DEFINED PLATFORM)
message(FATAL_ERROR "PLATFORM argument not set. Bailing configure since I don't know what target you want to build for!")
endif ()
if(PLATFORM MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode")
message(FATAL_ERROR "The combined builds support requires Xcode to be used as generator via '-G Xcode' command-line argument in CMake")
endif()
# Safeguard that the platform value is set and is one of the supported values
list(FIND _supported_platforms ${PLATFORM} contains_PLATFORM)
if("${contains_PLATFORM}" EQUAL "-1")
string(REPLACE ";" "\n * " _supported_platforms_formatted "${_supported_platforms}")
message(FATAL_ERROR " Invalid PLATFORM specified! Current value: ${PLATFORM}.\n"
" Supported PLATFORM values: \n * ${_supported_platforms_formatted}")
endif()
# Check if Apple Silicon is supported
if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5")
message(FATAL_ERROR "Apple Silicon builds requires a minimum of CMake 3.19.5")
endif()
# Touch toolchain variable to suppress "unused variable" warning.
# This happens if CMake is invoked with the same command line the second time.
if(CMAKE_TOOLCHAIN_FILE)
endif()
# Fix for PThread library not in path
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
# Specify minimum version of deployment target.
if(NOT DEFINED DEPLOYMENT_TARGET)
if (PLATFORM MATCHES "WATCHOS")
# Unless specified, SDK version 4.0 is used by default as minimum target version (watchOS).
set(DEPLOYMENT_TARGET "4.0")
elseif(PLATFORM STREQUAL "MAC")
# Unless specified, SDK version 10.13 (High sierra) is used by default as minimum target version (macos).
set(DEPLOYMENT_TARGET "10.13")
elseif(PLATFORM STREQUAL "MAC_ARM64")
# Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version (macos on arm).
set(DEPLOYMENT_TARGET "11.0")
elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64")
# Unless specified, SDK version 13.0 is used by default as minimum target version (mac catalyst minimum requirement).
set(DEPLOYMENT_TARGET "13.0")
else()
# Unless specified, SDK version 11.0 is used by default as minimum target version (iOS, tvOS).
set(DEPLOYMENT_TARGET "11.0")
endif()
message(STATUS "[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!")
elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES "^MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.0")
message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.0!")
endif()
# Store the DEPLOYMENT_TARGET in the cache
set(DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}" CACHE INTERNAL "")
# Handle the case where we are targeting iOS and a version above 10.3.4 (32-bit support dropped officially)
if(PLATFORM STREQUAL "OS" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4)
set(PLATFORM "OS64")
message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.")
elseif(PLATFORM STREQUAL "SIMULATOR" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4)
set(PLATFORM "SIMULATOR64")
message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.")
endif()
set(PLATFORM_INT "${PLATFORM}")
if(DEFINED ARCHS)
string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}")
endif()
# Determine the platform name and architectures for use in xcodebuild commands
# from the specified PLATFORM_INT name.
if(PLATFORM_INT STREQUAL "OS")
set(SDK_NAME iphoneos)
if(NOT ARCHS)
set(ARCHS armv7 armv7s arm64)
set(APPLE_TARGET_TRIPLE_INT arm-apple-ios$${DEPLOYMENT_TARGET})
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})
endif()
elseif(PLATFORM_INT STREQUAL "OS64")
set(SDK_NAME iphoneos)
if(NOT ARCHS)
if (XCODE_VERSION_INT VERSION_GREATER 10.0)
set(ARCHS arm64) # Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missung bitcode markers for example
else()
set(ARCHS arm64)
endif()
set(APPLE_TARGET_TRIPLE_INT aarch64-apple-ios${DEPLOYMENT_TARGET})
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})
endif()
elseif(PLATFORM_INT STREQUAL "OS64COMBINED")
set(SDK_NAME iphoneos)
if(MODERN_CMAKE)
if(NOT ARCHS)
if (XCODE_VERSION_INT VERSION_GREATER 10.0)
set(ARCHS arm64 x86_64) # Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missung bitcode markers for example
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64")
else()
set(ARCHS arm64 x86_64)
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64")
endif()
set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET})
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})
endif()
else()
message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work")
endif()
elseif(PLATFORM_INT STREQUAL "SIMULATOR")
set(SDK_NAME iphonesimulator)
if(NOT ARCHS)
set(ARCHS i386)
set(APPLE_TARGET_TRIPLE_INT i386-apple-ios${DEPLOYMENT_TARGET}-simulator)
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator)
endif()
message(DEPRECATION "SIMULATOR IS DEPRECATED. Consider using SIMULATOR64 instead.")
elseif(PLATFORM_INT STREQUAL "SIMULATOR64")
set(SDK_NAME iphonesimulator)
if(NOT ARCHS)
set(ARCHS x86_64)
set(APPLE_TARGET_TRIPLE_INT x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator)
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator)
endif()
elseif(PLATFORM_INT STREQUAL "SIMULATORARM64")
set(SDK_NAME iphonesimulator)
if(NOT ARCHS)
set(ARCHS arm64)
set(APPLE_TARGET_TRIPLE_INT aarch64-apple-ios${DEPLOYMENT_TARGET}-simulator)
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator)
endif()
elseif(PLATFORM_INT STREQUAL "TVOS")
set(SDK_NAME appletvos)
if(NOT ARCHS)
set(ARCHS arm64)
set(APPLE_TARGET_TRIPLE_INT aarch64-apple-tvos${DEPLOYMENT_TARGET})
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET})
endif()
elseif (PLATFORM_INT STREQUAL "TVOSCOMBINED")
set(SDK_NAME appletvos)
if(MODERN_CMAKE)
if(NOT ARCHS)
set(ARCHS arm64 x86_64)
set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-tvos${DEPLOYMENT_TARGET})
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] "arm64")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64")
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET})
endif()
else()
message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the TVOSCOMBINED setting work")
endif()
elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS")
set(SDK_NAME appletvsimulator)
if(NOT ARCHS)
set(ARCHS x86_64)
set(APPLE_TARGET_TRIPLE_INT x86_64-apple-tvos${DEPLOYMENT_TARGET}-simulator)
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator)
endif()
elseif(PLATFORM_INT STREQUAL "WATCHOS")
set(SDK_NAME watchos)
if(NOT ARCHS)
if (XCODE_VERSION_INT VERSION_GREATER 10.0)
set(ARCHS armv7k arm64_32)
set(APPLE_TARGET_TRIPLE_INT aarch64_32-apple-watchos${DEPLOYMENT_TARGET})
else()
set(ARCHS armv7k)
set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos${DEPLOYMENT_TARGET})
endif()
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET})
endif()
elseif(PLATFORM_INT STREQUAL "WATCHOSCOMBINED")
set(SDK_NAME watchos)
if(MODERN_CMAKE)
if(NOT ARCHS)
if (XCODE_VERSION_INT VERSION_GREATER 10.0)
set(ARCHS armv7k arm64_32 i386)
set(APPLE_TARGET_TRIPLE_INT aarch64_32-i386-apple-watchos${DEPLOYMENT_TARGET})
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k arm64_32")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k arm64_32")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386")
else()
set(ARCHS armv7k i386)
set(APPLE_TARGET_TRIPLE_INT arm-i386-apple-watchos${DEPLOYMENT_TARGET})
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386")
endif()
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET})
endif()
else()
message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the WATCHOSCOMBINED setting work")
endif()
elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS")
set(SDK_NAME watchsimulator)
if(NOT ARCHS)
set(ARCHS i386)
set(APPLE_TARGET_TRIPLE_INT i386-apple-watchos${DEPLOYMENT_TARGET}-simulator)
else()
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator)
endif()
elseif(PLATFORM_INT STREQUAL "MAC" OR PLATFORM_INT STREQUAL "MAC_CATALYST")
set(SDK_NAME macosx)
if(NOT ARCHS)
set(ARCHS x86_64)
endif()
string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}")
if(PLATFORM_INT STREQUAL "MAC")
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET})
elseif(PLATFORM_INT STREQUAL "MAC_CATALYST")
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi)
endif()
elseif(PLATFORM_INT MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$")
set(SDK_NAME macosx)
if(NOT ARCHS)
set(ARCHS arm64)
endif()
string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}")
if(PLATFORM_INT STREQUAL "MAC_ARM64")
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET})
elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_ARM64")
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi)
endif()
else()
message(FATAL_ERROR "Invalid PLATFORM: ${PLATFORM_INT}")
endif()
if(MODERN_CMAKE AND PLATFORM_INT MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode")
message(FATAL_ERROR "The COMBINED options only work with Xcode generator, -G Xcode")
endif()
if(CMAKE_GENERATOR MATCHES "Xcode" AND PLATFORM_INT MATCHES "^MAC_CATALYST")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "macosx")
set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-maccatalyst")
if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET)
set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "10.15")
else()
set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}")
endif()
elseif(CMAKE_GENERATOR MATCHES "Xcode")
set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}")
if(NOT PLATFORM_INT MATCHES ".*COMBINED")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS}")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS}")
endif()
endif()
# If user did not specify the SDK root to use, then query xcodebuild for it.
if(DEFINED CMAKE_OSX_SYSROOT_INT)
# Environment variables are always preserved.
set(ENV{_CMAKE_OSX_SYSROOT_INT} "${CMAKE_OSX_SYSROOT_INT}")
elseif(DEFINED ENV{_CMAKE_OSX_SYSROOT_INT})
set(CMAKE_OSX_SYSROOT_INT "$ENV{_CMAKE_OSX_SYSROOT_INT}")
elseif(NOT DEFINED CMAKE_OSX_SYSROOT_INT)
execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version -sdk ${SDK_NAME} Path
OUTPUT_VARIABLE CMAKE_OSX_SYSROOT_INT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if (NOT DEFINED CMAKE_OSX_SYSROOT_INT AND NOT DEFINED CMAKE_OSX_SYSROOT)
message(SEND_ERROR "Please make sure that Xcode is installed and that the toolchain"
"is pointing to the correct path. Please run:"
"sudo xcode-select -s /Applications/Xcode.app/Contents/Developer"
"and see if that fixes the problem for you.")
message(FATAL_ERROR "Invalid CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT} "
"does not exist.")
elseif(DEFINED CMAKE_OSX_SYSROOT_INT)
set(CMAKE_OSX_SYSROOT_INT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "")
# Specify the location or name of the platform SDK to be used in CMAKE_OSX_SYSROOT.
set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "")
endif()
# Use bitcode or not
if(NOT DEFINED ENABLE_BITCODE AND NOT ARCHS MATCHES "((^|;|, )(i386|x86_64))+")
# Unless specified, enable bitcode support by default
message(STATUS "[DEFAULTS] Enabling bitcode support by default. ENABLE_BITCODE not provided!")
set(ENABLE_BITCODE TRUE)
elseif(NOT DEFINED ENABLE_BITCODE)
message(STATUS "[DEFAULTS] Disabling bitcode support by default on simulators. ENABLE_BITCODE not provided for override!")
set(ENABLE_BITCODE FALSE)
endif()
set(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL
"Whether or not to enable bitcode" FORCE)
# Use ARC or not
if(NOT DEFINED ENABLE_ARC)
# Unless specified, enable ARC support by default
set(ENABLE_ARC TRUE)
message(STATUS "[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!")
endif()
set(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL "Whether or not to enable ARC" FORCE)
# Use hidden visibility or not
if(NOT DEFINED ENABLE_VISIBILITY)
# Unless specified, disable symbols visibility by default
set(ENABLE_VISIBILITY FALSE)
message(STATUS "[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!")
endif()
set(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL "Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)" FORCE)
# Set strict compiler checks or not
if(NOT DEFINED ENABLE_STRICT_TRY_COMPILE)
# Unless specified, disable strict try_compile()
set(ENABLE_STRICT_TRY_COMPILE FALSE)
message(STATUS "[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!")
endif()
set(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL
"Whether or not to use strict compiler checks" FORCE)
# Get the SDK version information.
if(DEFINED SDK_VERSION)
# Environment variables are always preserved.
set(ENV{_SDK_VERSION} "${SDK_VERSION}")
elseif(DEFINED ENV{_SDK_VERSION})
set(SDK_VERSION "$ENV{_SDK_VERSION}")
elseif(NOT DEFINED SDK_VERSION)
execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -sdk ${CMAKE_OSX_SYSROOT_INT} -version SDKVersion
OUTPUT_VARIABLE SDK_VERSION
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
# Find the Developer root for the specific iOS platform being compiled for
# from CMAKE_OSX_SYSROOT. Should be ../../ from SDK specified in
# CMAKE_OSX_SYSROOT. There does not appear to be a direct way to obtain
# this information from xcrun or xcodebuild.
if (NOT DEFINED CMAKE_DEVELOPER_ROOT AND NOT CMAKE_GENERATOR MATCHES "Xcode")
get_filename_component(PLATFORM_SDK_DIR ${CMAKE_OSX_SYSROOT_INT} PATH)
get_filename_component(CMAKE_DEVELOPER_ROOT ${PLATFORM_SDK_DIR} PATH)
if (NOT EXISTS "${CMAKE_DEVELOPER_ROOT}")
message(FATAL_ERROR "Invalid CMAKE_DEVELOPER_ROOT: ${CMAKE_DEVELOPER_ROOT} does not exist.")
endif()
endif()
# Find the C & C++ compilers for the specified SDK.
if(DEFINED CMAKE_C_COMPILER)
# Environment variables are always preserved.
set(ENV{_CMAKE_C_COMPILER} "${CMAKE_C_COMPILER}")
elseif(DEFINED ENV{_CMAKE_C_COMPILER})
set(CMAKE_C_COMPILER "$ENV{_CMAKE_C_COMPILER}")
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
elseif(NOT DEFINED CMAKE_C_COMPILER)
execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang
OUTPUT_VARIABLE CMAKE_C_COMPILER
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
endif()
if(DEFINED CMAKE_CXX_COMPILER)
# Environment variables are always preserved.
set(ENV{_CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER}")
elseif(DEFINED ENV{_CMAKE_CXX_COMPILER})
set(CMAKE_CXX_COMPILER "$ENV{_CMAKE_CXX_COMPILER}")
elseif(NOT DEFINED CMAKE_CXX_COMPILER)
execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang++
OUTPUT_VARIABLE CMAKE_CXX_COMPILER
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
# Find (Apple's) libtool.
if(DEFINED BUILD_LIBTOOL)
# Environment variables are always preserved.
set(ENV{_BUILD_LIBTOOL} "${BUILD_LIBTOOL}")
elseif(DEFINED ENV{_BUILD_LIBTOOL})
set(BUILD_LIBTOOL "$ENV{_BUILD_LIBTOOL}")
elseif(NOT DEFINED BUILD_LIBTOOL)
execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find libtool
OUTPUT_VARIABLE BUILD_LIBTOOL
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
# Find the toolchain's provided install_name_tool if none is found on the host
if(DEFINED CMAKE_INSTALL_NAME_TOOL)
# Environment variables are always preserved.
set(ENV{_CMAKE_INSTALL_NAME_TOOL} "${CMAKE_INSTALL_NAME_TOOL}")
elseif(DEFINED ENV{_CMAKE_INSTALL_NAME_TOOL})
set(CMAKE_INSTALL_NAME_TOOL "$ENV{_CMAKE_INSTALL_NAME_TOOL}")
elseif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find install_name_tool
OUTPUT_VARIABLE CMAKE_INSTALL_NAME_TOOL_INT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL_INT} CACHE INTERNAL "")
endif()
# Configure libtool to be used instead of ar + ranlib to build static libraries.
# This is required on Xcode 7+, but should also work on previous versions of
# Xcode.
get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(lang ${languages})
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o <TARGET> <LINK_FLAGS> <OBJECTS> " CACHE INTERNAL "")
endforeach()
# CMake 3.14+ support building for iOS, watchOS and tvOS out of the box.
if(MODERN_CMAKE)
if(SDK_NAME MATCHES "iphone")
set(CMAKE_SYSTEM_NAME iOS)
elseif(SDK_NAME MATCHES "macosx")
set(CMAKE_SYSTEM_NAME Darwin)
elseif(SDK_NAME MATCHES "appletv")
set(CMAKE_SYSTEM_NAME tvOS)
elseif(SDK_NAME MATCHES "watch")
set(CMAKE_SYSTEM_NAME watchOS)
endif()
# Provide flags for a combined FAT library build on newer CMake versions
if(PLATFORM_INT MATCHES ".*COMBINED")
set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO")
set(CMAKE_IOS_INSTALL_COMBINED YES)
message(STATUS "Will combine built (static) artifacts into FAT lib...")
endif()
elseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.10")
# Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified
set(CMAKE_SYSTEM_NAME iOS)
elseif(NOT DEFINED CMAKE_SYSTEM_NAME)
# Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified
set(CMAKE_SYSTEM_NAME Darwin)
endif()
# Standard settings.
set(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL "")
set(UNIX TRUE CACHE BOOL "")
set(APPLE TRUE CACHE BOOL "")
if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64")
set(IOS FALSE CACHE BOOL "")
set(MACOS TRUE CACHE BOOL "")
elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64")
set(IOS TRUE CACHE BOOL "")
set(MACOS TRUE CACHE BOOL "")
else()
set(IOS TRUE CACHE BOOL "")
endif()
set(CMAKE_AR ar CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB ranlib CACHE FILEPATH "" FORCE)
set(CMAKE_STRIP strip CACHE FILEPATH "" FORCE)
# Set the architectures for which to build.
set(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL "")
# Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks
if(NOT ENABLE_STRICT_TRY_COMPILE_INT)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
endif()
# All iOS/Darwin specific settings - some may be redundant.
set(CMAKE_MACOSX_BUNDLE YES)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
set(CMAKE_SHARED_LIBRARY_PREFIX "lib")
set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
set(CMAKE_SHARED_MODULE_PREFIX "lib")
set(CMAKE_SHARED_MODULE_SUFFIX ".so")
set(CMAKE_C_COMPILER_ABI ELF)
set(CMAKE_CXX_COMPILER_ABI ELF)
set(CMAKE_C_HAS_ISYSROOT 1)
set(CMAKE_CXX_HAS_ISYSROOT 1)
set(CMAKE_MODULE_EXISTS 1)
set(CMAKE_DL_LIBS "")
set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ")
set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}")
set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}")
if(ARCHS MATCHES "((^|;|, )(arm64|arm64e|x86_64))+")
set(CMAKE_C_SIZEOF_DATA_PTR 8)
set(CMAKE_CXX_SIZEOF_DATA_PTR 8)
if(ARCHS MATCHES "((^|;|, )(arm64|arm64e))+")
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
else()
set(CMAKE_SYSTEM_PROCESSOR "x86_64")
endif()
else()
set(CMAKE_C_SIZEOF_DATA_PTR 4)
set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
set(CMAKE_SYSTEM_PROCESSOR "arm")
endif()
# Note that only Xcode 7+ supports the newer more specific:
# -m${SDK_NAME}-version-min flags, older versions of Xcode use:
# -m(ios/ios-simulator)-version-min instead.
if(${CMAKE_VERSION} VERSION_LESS "3.11")
if(PLATFORM_INT STREQUAL "OS" OR PLATFORM_INT STREQUAL "OS64")
if(XCODE_VERSION_INT VERSION_LESS 7.0)
set(SDK_NAME_VERSION_FLAGS
"-mios-version-min=${DEPLOYMENT_TARGET}")
else()
# Xcode 7.0+ uses flags we can build directly from SDK_NAME.
set(SDK_NAME_VERSION_FLAGS
"-m${SDK_NAME}-version-min=${DEPLOYMENT_TARGET}")
endif()
elseif(PLATFORM_INT STREQUAL "TVOS")
set(SDK_NAME_VERSION_FLAGS
"-mtvos-version-min=${DEPLOYMENT_TARGET}")
elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS")
set(SDK_NAME_VERSION_FLAGS
"-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}")
elseif(PLATFORM_INT STREQUAL "WATCHOS")
set(SDK_NAME_VERSION_FLAGS
"-mwatchos-version-min=${DEPLOYMENT_TARGET}")
elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS")
set(SDK_NAME_VERSION_FLAGS
"-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}")
elseif(PLATFORM_INT STREQUAL "MAC")
set(SDK_NAME_VERSION_FLAGS
"-mmacosx-version-min=${DEPLOYMENT_TARGET}")
else()
# SIMULATOR or SIMULATOR64 both use -mios-simulator-version-min.
set(SDK_NAME_VERSION_FLAGS
"-mios-simulator-version-min=${DEPLOYMENT_TARGET}")
endif()
elseif(NOT PLATFORM_INT MATCHES "^MAC_CATALYST")
# Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets
set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET})
endif()
if(DEFINED APPLE_TARGET_TRIPLE_INT)
set(APPLE_TARGET_TRIPLE ${APPLE_TARGET_TRIPLE_INT} CACHE INTERNAL "")
set(CMAKE_C_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})
set(CMAKE_CXX_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})
set(CMAKE_ASM_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})
endif()
if(PLATFORM_INT MATCHES "^MAC_CATALYST")
set(C_TARGET_FLAGS "-isystem ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/usr/include -iframework ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks")
endif()
if(ENABLE_BITCODE_INT)
set(BITCODE "-fembed-bitcode")
set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")
set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")
else()
set(BITCODE "")
set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
endif()
if(ENABLE_ARC_INT)
set(FOBJC_ARC "-fobjc-arc")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES")
else()
set(FOBJC_ARC "-fno-objc-arc")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO")
endif()
if(NOT ENABLE_VISIBILITY_INT)
foreach(lang ${languages})
set(CMAKE_${lang}_VISIBILITY_PRESET "hidden" CACHE INTERNAL "")
endforeach()
set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES")
set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden")
else()
foreach(lang ${languages})
set(CMAKE_${lang}_VISIBILITY_PRESET "default" CACHE INTERNAL "")
endforeach()
set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO")
set(VISIBILITY "-fvisibility=default")
endif()
if(DEFINED APPLE_TARGET_TRIPLE)
set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}")
endif()
#Check if Xcode generator is used, since that will handle these flags automagically
if(CMAKE_GENERATOR MATCHES "Xcode")
message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as generator.")
else()
# Hidden visibility is required for C++ on iOS.
set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} -fobjc-abi-version=2 ${FOBJC_ARC} ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} -fobjc-abi-version=2 ${FOBJC_ARC} ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS} -DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS} -DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -arch ${CMAKE_OSX_ARCHITECTURES} ${APPLE_TARGET_TRIPLE_FLAG}")
endif()
## Print status messages to inform of the current state
message(STATUS "Configuring ${SDK_NAME} build for platform: ${PLATFORM_INT}, architecture(s): ${ARCHS}")
message(STATUS "Using SDK: ${CMAKE_OSX_SYSROOT_INT}")
message(STATUS "Using C compiler: ${CMAKE_C_COMPILER}")
message(STATUS "Using CXX compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "Using libtool: ${BUILD_LIBTOOL}")
message(STATUS "Using install name tool: ${CMAKE_INSTALL_NAME_TOOL}")
if(DEFINED APPLE_TARGET_TRIPLE)
message(STATUS "Autoconf target triple: ${APPLE_TARGET_TRIPLE}")
endif()
message(STATUS "Using minimum deployment version: ${DEPLOYMENT_TARGET}"
" (SDK version: ${SDK_VERSION})")
if(MODERN_CMAKE)
message(STATUS "Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!")
endif()
if(CMAKE_GENERATOR MATCHES "Xcode")
message(STATUS "Using Xcode version: ${XCODE_VERSION_INT}")
endif()
message(STATUS "CMake version: ${CMAKE_VERSION}")
if(DEFINED SDK_NAME_VERSION_FLAGS)
message(STATUS "Using version flags: ${SDK_NAME_VERSION_FLAGS}")
endif()
message(STATUS "Using a data_ptr size of: ${CMAKE_CXX_SIZEOF_DATA_PTR}")
if(ENABLE_BITCODE_INT)
message(STATUS "Bitcode: Enabled")
else()
message(STATUS "Bitcode: Disabled")
endif()
if(ENABLE_ARC_INT)
message(STATUS "ARC: Enabled")
else()
message(STATUS "ARC: Disabled")
endif()
if(ENABLE_VISIBILITY_INT)
message(STATUS "Hiding symbols: Disabled")
else()
message(STATUS "Hiding symbols: Enabled")
endif()
# Set global properties
set_property(GLOBAL PROPERTY PLATFORM "${PLATFORM}")
set_property(GLOBAL PROPERTY APPLE_TARGET_TRIPLE "${APPLE_TARGET_TRIPLE_INT}")
set_property(GLOBAL PROPERTY SDK_VERSION "${SDK_VERSION}")
set_property(GLOBAL PROPERTY XCODE_VERSION "${XCODE_VERSION_INT}")
set_property(GLOBAL PROPERTY OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
# Export configurable variables for the try_compile() command.
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
PLATFORM
XCODE_VERSION_INT
SDK_VERSION
DEPLOYMENT_TARGET
CMAKE_DEVELOPER_ROOT
CMAKE_OSX_SYSROOT_INT
ENABLE_BITCODE
ENABLE_ARC
CMAKE_ASM_COMPILER
CMAKE_C_COMPILER
CMAKE_C_COMPILER_TARGET
CMAKE_CXX_COMPILER
CMAKE_CXX_COMPILER_TARGET
BUILD_LIBTOOL
CMAKE_INSTALL_NAME_TOOL
CMAKE_C_FLAGS
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_RELEASE
CMAKE_C_LINK_FLAGS
CMAKE_CXX_LINK_FLAGS
CMAKE_ASM_FLAGS
)
set(CMAKE_PLATFORM_HAS_INSTALLNAME 1)
set(CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks")
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -Wl,-headerpad_max_install_names")
set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,")
set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".tbd" ".dylib" ".so" ".a")
set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name")
# Set the find root to the SDK developer roots.
# Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds.
if(NOT PLATFORM_INT STREQUAL "MAC" AND NOT PLATFORM_INT STREQUAL "MAC_ARM64")
list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "")
set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib" CACHE INTERNAL "")
endif()
# Default to searching for frameworks first.
set(CMAKE_FIND_FRAMEWORK FIRST)
# Set up the default search directories for frameworks.
if(PLATFORM_INT MATCHES "^MAC_CATALYST")
set(CMAKE_FRAMEWORK_PATH
${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks
${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks
${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks
${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "")
else()
set(CMAKE_FRAMEWORK_PATH
${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks
${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks
${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "")
endif()
# By default, search both the specified iOS SDK and the remainder of the host filesystem.
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "")
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL "")
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL "")
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL "")
endif()
#
# Some helper-macros below to simplify and beautify the CMakeFile
#
# This little macro lets you set any Xcode specific property.
macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE XCODE_RELVERSION)
set(XCODE_RELVERSION_I "${XCODE_RELVERSION}")
if(XCODE_RELVERSION_I STREQUAL "All")
set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} "${XCODE_VALUE}")
else()
set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY}[variant=${XCODE_RELVERSION_I}] "${XCODE_VALUE}")
endif()
endmacro(set_xcode_property)
# This macro lets you find executable programs on the host system.
macro(find_host_package)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER)
set(_TOOLCHAIN_IOS ${IOS})
set(IOS FALSE)
find_package(${ARGN})
set(IOS ${_TOOLCHAIN_IOS})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
endmacro(find_host_package)