diff --git a/.github/gles.patch b/.github/gles.patch
index 548b243d..b16733b5 100644
--- a/.github/gles.patch
+++ b/.github/gles.patch
@@ -1,25 +1,3 @@
-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
diff --git a/.github/workflows/Android_Build.yml b/.github/workflows/Android_Build.yml
index b7e64f5f..37a5eb45 100644
--- a/.github/workflows/Android_Build.yml
+++ b/.github/workflows/Android_Build.yml
@@ -23,6 +23,9 @@ 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:
@@ -34,7 +37,7 @@ jobs:
${{ runner.os }}-pandroid-x86_64-
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -47,7 +50,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
+ 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
- name: Build
run: |
@@ -88,6 +91,9 @@ 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:
@@ -99,7 +105,7 @@ jobs:
${{ runner.os }}-pandroid-arm64-
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -112,7 +118,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"
+ 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
- name: Build
run: |
diff --git a/.github/workflows/HTTP_Build.yml b/.github/workflows/HTTP_Build.yml
index c4f7cfee..11bf27eb 100644
--- a/.github/workflows/HTTP_Build.yml
+++ b/.github/workflows/HTTP_Build.yml
@@ -30,7 +30,7 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
diff --git a/.github/workflows/Hydra_Build.yml b/.github/workflows/Hydra_Build.yml
index 6827fffe..dbdfbf1b 100644
--- a/.github/workflows/Hydra_Build.yml
+++ b/.github/workflows/Hydra_Build.yml
@@ -20,7 +20,7 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -55,7 +55,7 @@ jobs:
${{github.workspace}}/docs/libretro/panda3ds_libretro.info
MacOS:
- runs-on: macos-13
+ runs-on: macos-latest
steps:
- uses: actions/checkout@v4
@@ -63,7 +63,7 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -116,7 +116,7 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -163,7 +163,7 @@ 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@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -180,3 +180,36 @@ 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
diff --git a/.github/workflows/Linux_AppImage_Build.yml b/.github/workflows/Linux_AppImage_Build.yml
index 3c5af88a..9e46072f 100644
--- a/.github/workflows/Linux_AppImage_Build.yml
+++ b/.github/workflows/Linux_AppImage_Build.yml
@@ -33,7 +33,7 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
diff --git a/.github/workflows/Linux_Build.yml b/.github/workflows/Linux_Build.yml
index 61f7eafa..d0ddfecf 100644
--- a/.github/workflows/Linux_Build.yml
+++ b/.github/workflows/Linux_Build.yml
@@ -33,7 +33,7 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
diff --git a/.github/workflows/MacOS_Build.yml b/.github/workflows/MacOS_Build.yml
index a0c09bbf..a405e788 100644
--- a/.github/workflows/MacOS_Build.yml
+++ b/.github/workflows/MacOS_Build.yml
@@ -17,7 +17,7 @@ jobs:
arch: [x86_64, arm64]
name: MacOS-${{ matrix.arch }}
- runs-on: macos-13
+ runs-on: macos-latest
steps:
- uses: actions/checkout@v4
@@ -25,7 +25,7 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -61,7 +61,7 @@ jobs:
MacOS-Universal:
name: MacOS-Universal
needs: [build]
- runs-on: macos-13
+ runs-on: macos-latest
steps:
- name: Download x86_64
diff --git a/.github/workflows/Qt_Build.yml b/.github/workflows/Qt_Build.yml
index ebd856c6..3db1e4f3 100644
--- a/.github/workflows/Qt_Build.yml
+++ b/.github/workflows/Qt_Build.yml
@@ -26,7 +26,7 @@ jobs:
version: 6.2.0
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -56,7 +56,7 @@ jobs:
arch: [x86_64, arm64]
name: MacOS-${{ matrix.arch }}
- runs-on: macos-13
+ runs-on: macos-latest
steps:
- uses: actions/checkout@v4
@@ -64,7 +64,7 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
@@ -109,7 +109,7 @@ jobs:
MacOS-Universal:
name: MacOS-Universal
needs: [MacOS]
- runs-on: macos-13
+ runs-on: macos-latest
steps:
- name: Download x86_64
@@ -162,7 +162,7 @@ jobs:
sudo ./llvm.sh 17
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
diff --git a/.github/workflows/Windows_Build.yml b/.github/workflows/Windows_Build.yml
index 5497c3ef..caa3d806 100644
--- a/.github/workflows/Windows_Build.yml
+++ b/.github/workflows/Windows_Build.yml
@@ -24,7 +24,7 @@ jobs:
run: git submodule update --init --recursive
- name: Setup Vulkan SDK
- uses: humbletim/setup-vulkan-sdk@v1.2.0
+ uses: humbletim/setup-vulkan-sdk@main
with:
vulkan-query-version: latest
vulkan-use-cache: true
diff --git a/.github/workflows/iOS_Build.yml b/.github/workflows/iOS_Build.yml
new file mode 100644
index 00000000..7d7e604b
--- /dev/null
+++ b/.github/workflows/iOS_Build.yml
@@ -0,0 +1,39 @@
+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: latest
+ vulkan-use-cache: true
+ vulkan-components: Vulkan-Headers, Vulkan-Loader, SPIRV-Tools, Glslang
+
+ - name: Build core and frontend
+ run: cd src/pandios && ./build.sh
diff --git a/.gitmodules b/.gitmodules
index 9fcd8d60..c8ced6e4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,9 +1,6 @@
[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
@@ -79,9 +76,10 @@
[submodule "third_party/fdk-aac"]
path = third_party/fdk-aac
url = https://github.com/Panda3DS-emu/fdk-aac/
-[submodule "third_party/cryptoppwin"]
- path = third_party/cryptoppwin
- url = https://github.com/shadps4-emu/ext-cryptoppwin
[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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dc529482..9c8571ec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,7 @@ 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)
@@ -63,6 +64,14 @@ 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)
@@ -79,6 +88,10 @@ 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)
@@ -88,7 +101,7 @@ endif()
# Generate versioning files
find_package(Git)
-set(PANDA3DS_VERSION "0.8")
+set(PANDA3DS_VERSION "0.9")
if(NOT EXISTS ${CMAKE_BINARY_DIR}/include/version.hpp.in)
file(WRITE ${CMAKE_BINARY_DIR}/include/version.hpp.in "#define PANDA3DS_VERSION \"\${PANDA3DS_VERSION}\"")
@@ -97,22 +110,29 @@ endif()
if(GIT_FOUND AND ENABLE_GIT_VERSIONING)
execute_process(
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
- OUTPUT_VARIABLE PANDA3DS_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE
- )
- execute_process(
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags
OUTPUT_VARIABLE git_version_tag OUTPUT_STRIP_TRAILING_WHITESPACE
)
- 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)
+ execute_process(
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
+ OUTPUT_VARIABLE git_version_rev 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}")
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/)
@@ -140,12 +160,15 @@ 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)
@@ -304,8 +327,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/miniaudio.cpp src/renderdoc.cpp
- src/frontend_settings.cpp
+ src/discord_rpc.cpp src/lua.cpp src/memory_mapped_file.cpp src/renderdoc.cpp
+ src/frontend_settings.cpp src/miniaudio/miniaudio.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
@@ -390,9 +413,19 @@ 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/services/news_s.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/services/news_s.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
@@ -422,16 +455,22 @@ if(ENABLE_LUAJIT AND NOT ANDROID)
target_link_libraries(AlberCore PRIVATE uv_a)
endif()
+set(GL_CONTEXT_SOURCE_FILES "")
+
if(ENABLE_QT_GUI)
- set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/window_info.cpp third_party/duckstation/gl/context.cpp)
+ set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/window_info.cpp third_party/duckstation/gl/context.cpp)
if(APPLE)
- set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_agl.mm)
+ set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_agl.mm)
elseif(WIN32)
- set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_wgl.cpp)
+ set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_wgl.cpp)
else()
- 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)
+ 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()
endif()
endif()
@@ -445,7 +484,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})
+source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES} ${GL_CONTEXT_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
@@ -460,8 +499,9 @@ 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.frag
- src/host_shaders/opengl_display.vert src/host_shaders/opengl_vertex_shader.vert
+ 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/host_shaders/opengl_fragment_shader.frag
)
@@ -474,8 +514,10 @@ if(ENABLE_OPENGL)
resources_renderer_gl
NAMESPACE RendererGL
WHENCE "src/host_shaders/"
- "src/host_shaders/opengl_display.frag"
"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/host_shaders/opengl_fragment_shader.frag"
)
@@ -562,14 +604,16 @@ 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
@@ -583,15 +627,26 @@ 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 macosx metal -gline-tables-only -frecord-sources -o ${SHADER_IR} -c ${SHADER_SOURCE}
+ COMMAND xcrun -sdk ${MetalSDK} 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 macosx metallib -o ${SHADER_METALLIB} ${SHADER_IR}
+ COMMAND xcrun -sdk ${MetalSDK} metallib -o ${SHADER_METALLIB} ${SHADER_IR}
DEPENDS ${SHADER_IR}
VERBATIM)
set(RENDERER_MTL_HOST_SHADERS_SOURCES ${RENDERER_MTL_HOST_SHADERS_SOURCES} ${SHADER_METALLIB})
@@ -620,7 +675,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 PRIVATE "-framework Metal" "-framework Foundation" "-framework QuartzCore" resources_renderer_mtl)
+ target_link_libraries(AlberCore PUBLIC "-framework Metal" "-framework Foundation" "-framework QuartzCore" resources_renderer_mtl)
endif()
source_group("Header Files\\Core" FILES ${HEADER_FILES})
@@ -726,11 +781,14 @@ 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/rnap_icon.png docs/img/rcow_icon.png docs/img/skyemu_icon.png docs/img/runpog_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)
+ 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_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS})
@@ -751,11 +809,17 @@ 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} ${APP_RESOURCES})
+ target_sources(Alber PRIVATE ${FRONTEND_SOURCE_FILES} ${FRONTEND_HEADER_FILES} ${GL_CONTEXT_SOURCE_FILES} ${APP_RESOURCES})
elseif(BUILD_HYDRA_CORE)
target_compile_definitions(AlberCore PRIVATE PANDA3DS_HYDRA_CORE=1)
include_directories(third_party/hydra_core/include)
- add_library(Alber SHARED src/hydra_core.cpp)
+
+ 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})
target_link_libraries(Alber PUBLIC AlberCore)
elseif(BUILD_LIBRETRO_CORE)
include_directories(third_party/libretro/include)
diff --git a/docs/img/runpog_icon.png b/docs/img/runpog_icon.png
new file mode 100644
index 00000000..6ef33f4a
Binary files /dev/null and b/docs/img/runpog_icon.png differ
diff --git a/docs/translations/sv.ts b/docs/translations/sv.ts
new file mode 100644
index 00000000..21f573dc
--- /dev/null
+++ b/docs/translations/sv.ts
@@ -0,0 +1,774 @@
+
+
+
+ sv
+
+ Daniel Nylander <github@danielnylander.se>
+
+
+
+ Poedit 3.5
+ 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
+
+ AboutWindow
+
+
+ About Panda3DS
+ Om Panda3DS
+
+
+
+ Panda3DS is a free and open source Nintendo 3DS emulator, for Windows, MacOS and Linux
+ Panda3DS är en Nintendo 3DS-emulator med fri och öppen källkod för Windows, MacOS och Linux
+
+
+
+ Visit panda3ds.com for help with Panda3DS and links to our official support sites.
+ Besök panda3ds.com för att få hjälp med Panda3DS och länkar till våra officiella supportwebbplatser.
+
+
+
+ Panda3DS is developed by volunteers in their spare time. Below is a list of some of these volunteers who've agreed to be listed here, in no particular order.<br>If you think you should be listed here too, please inform us<br><br>- Peach (wheremyfoodat)<br>- noumidev<br>- liuk707<br>- Wunk<br>- marysaka<br>- Sky<br>- merryhime<br>- TGP17<br>- Shadow<br>
+ Panda3DS utvecklas av volontärer på deras fritid. Nedan finns en lista över några av dessa volontärer som har gått med på att listas här, utan någon särskild ordning.<br>Om du tycker att du också borde listas här, informera oss<br><br>- Peach (wheremyfoodat)<br>- noumidev<br>- liuk707<br>- Wunk<br>- marysaka<br>- Sky<br>- merryhime<br>- TGP17<br>- Shadow<br>
+
+
+
+ CheatEditDialog
+
+
+ Edit Cheat
+ Redigera fusk
+
+
+
+ Cheat name
+ Fusknamn
+
+
+
+ CheatEntryWidget
+
+
+ Edit
+ Redigera
+
+
+
+ CheatsWindow
+
+
+ Cheats
+ Fusk
+
+
+
+ Add
+ Lägg till
+
+
+
+ Remove
+ Ta bort
+
+
+
+ ConfigWindow
+
+
+ Configuration
+ Konfiguration
+
+
+
+ Interface Settings
+ Inställningar för gränssnitt
+
+
+
+ System
+ System
+
+
+
+ Light
+ Ljus
+
+
+
+ Dark
+ Mörk
+
+
+
+ Greetings Cat
+ Hälsningskatt
+
+
+
+ Cream
+ Grädde
+
+
+
+ Color theme
+ Färgtema
+
+
+
+ Happy panda
+ Glad panda
+
+
+
+ Happy panda (colourful)
+ Glad panda (färgglad)
+
+
+
+ Sleepy panda
+ Sömnig panda
+
+
+
+ Cow panda
+ Ko-panda
+
+
+
+ The penguin from SkyEmu
+ Pingvinen från SkyEmu
+
+
+
+ Window icon
+ Fönsterikon
+
+
+
+ Language
+ Språk
+
+
+
+ Show version on window title
+ Visa version på fönstertitel
+
+
+
+
+ Alber v%1
+ Alber v%1
+
+
+
+ Alber
+ Alber
+
+
+
+ Remember window position
+ Kom ihåg fönstrets position
+
+
+
+ General Settings
+ Allmänna inställningar
+
+
+
+ Browse...
+ Bläddra...
+
+
+
+ Select Directory
+ Välj katalog
+
+
+
+ Default ROMs path
+ Standardsökväg för ROMar
+
+
+
+ Enable Discord RPC
+ Aktivera Discord RPC
+
+
+
+ Use portable build
+ Använd portabelt bygge
+
+
+
+ Print version in console output
+ Skriv ut versionen i konsolutmatningen
+
+
+
+ Graphics Settings
+ Grafikinställningar
+
+
+
+
+ Null
+ Null
+
+
+
+ OpenGL
+ OpenGL
+
+
+
+ Vulkan
+ Vulkan
+
+
+
+ GPU renderer
+ GPU-rendering
+
+
+
+ Enable Renderdoc
+ Aktivera Renderdoc
+
+
+
+ Enable shader JIT
+ Aktivera shader JIT
+
+
+
+ Enable VSync
+ Aktivera VSync
+
+
+
+ Use ubershaders (No stutter, maybe slower)
+ Använda ubershaders (inga hackningar, kanske långsammare)
+
+
+
+ Accurate shader multiplication
+ Korrekt multiplicering av shaders
+
+
+
+ Accelerate shaders
+ Snabbare shaders
+
+
+
+ Force shadergen when rendering lights
+ Tvinga fram shadergen vid rendering av ljus
+
+
+
+ Light threshold for forcing shadergen
+ Ljuströskel för att tvinga shadergen
+
+
+
+ Audio Settings
+ Ljudinställningar
+
+
+
+ LLE
+ LLE
+
+
+
+ HLE
+ HLE
+
+
+
+ DSP emulation
+ DSP-emulering
+
+
+
+ Enable audio
+ Aktivera ljud
+
+
+
+ Enable AAC audio
+ Aktivera AAC-ljud
+
+
+
+ Print DSP firmware
+ Skriv ut firmware för DSP
+
+
+
+ Mute audio device
+ Stäng av ljudet på audioenheten
+
+
+
+ Cubic
+ Kubisk
+
+
+
+ Linear
+ Linjär
+
+
+
+ Volume curve
+ Volymkurva
+
+
+
+ Audio device volume
+ Ljudenhetens volym
+
+
+
+ Battery Settings
+ Batteriinställningar
+
+
+
+ Battery percentage
+ Batteriprocent
+
+
+
+ Charger plugged
+ Laddaren är ansluten
+
+
+
+ SD Card Settings
+ Inställningar för SD-kort
+
+
+
+ Enable virtual SD card
+ Aktivera virtuellt SD-kort
+
+
+
+ Write protect virtual SD card
+ Skrivskydd för virtuellt SD-kort
+
+
+
+ Interface
+ Gränssnitt
+
+
+
+ User Interface settings
+ Inställningar för användargränssnitt
+
+
+
+ General
+ Allmänt
+
+
+
+ General emulator settings
+ Allmänna inställningar för emulatorn
+
+
+
+ Graphics
+ Grafik
+
+
+
+ Graphics emulation and output settings
+ Inställningar för grafikemulering och utdata
+
+
+
+ Audio
+ Ljud
+
+
+
+ Audio emulation and output settings
+ Inställningar för ljudemulering och utdata
+
+
+
+ Battery
+ Batteri
+
+
+
+ Battery emulation settings
+ Inställningar för batteriemulering
+
+
+
+ SD Card
+ SD-kort
+
+
+
+ SD Card emulation settings
+ Inställningar för emulering av SD-kort
+
+
+
+ Language change successful
+ Språkändringen lyckades
+
+
+
+ Restart Panda3DS for the new language to be used.
+ Starta om Panda3DS för att det nya språket ska kunna användas.
+
+
+
+ Language change failed
+ Språkändringen misslyckades
+
+
+
+ The language you selected is not included in Panda3DS. If you're seeing this, someone messed up the language UI code...
+ 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...
+
+
+
+ MainWindow
+
+
+ Alber
+ Alber
+
+
+
+ File
+ Arkiv
+
+
+
+ Emulation
+ Emulering
+
+
+
+ Tools
+ Verktyg
+
+
+
+ About
+ Om
+
+
+
+ Load game
+ Läs in spel
+
+
+
+ Load Lua script
+ Läs in Lua-skript
+
+
+
+ Open Panda3DS folder
+ Öppna Panda3DS-mappen
+
+
+
+ Pause
+ Pausa
+
+
+
+ Resume
+ Återuppta
+
+
+
+ Reset
+ Starta om
+
+
+
+ Configure
+ Konfigurera
+
+
+
+ Dump RomFS
+ Dumpa RomFS
+
+
+
+ Open Lua Editor
+ Öppna Lua-redigeraren
+
+
+
+ Open Cheats Editor
+ Öppna fuskredigeraren
+
+
+
+ Open Patch Window
+ Öppna patchfönstret
+
+
+
+ Open Shader Editor
+ Öppna shader-redigeraren
+
+
+
+ Dump loaded DSP firmware
+ Dumpa inläst DSP-firmware
+
+
+
+ About Panda3DS
+ Om Panda3DS
+
+
+
+ Select 3DS ROM to load
+ Välj 3DS ROM att läsa in
+
+
+
+ Nintendo 3DS ROMs (*.3ds *.cci *.cxi *.app *.ncch *.3dsx *.elf *.axf)
+ Nintendo 3DS ROM (*.3ds *.cci *.cxi *.app *.ncch *.3dsx *.elf *.axf)
+
+
+
+ Select Lua script to load
+ Välj Lua-skript som ska läsas in
+
+
+
+ Lua scripts (*.lua *.txt)
+ Lua-skript (*.lua *.txt)
+
+
+
+ Select folder to dump RomFS files to
+ Välj mapp för att dumpa RomFS-filer till
+
+
+
+ Invalid format for RomFS dumping
+ Ogiltigt format för RomFS-dumpning
+
+
+
+ The currently loaded app is not in a format that supports RomFS
+ Den aktuella appen är inte i ett format som stöder RomFS
+
+
+
+
+
+ OK
+ Ok
+
+
+
+ No RomFS found
+ Ingen RomFS hittades
+
+
+
+ No RomFS partition was found in the loaded app
+ Ingen RomFS-partition hittades i den inlästa appen
+
+
+
+ Select file
+ Välj fil
+
+
+
+ DSP firmware file (*.cdc)
+ DSP firmware-fil (*.cdc)
+
+
+
+ No DSP firmware loaded
+ Ingen firmware för DSP inläst
+
+
+
+ The currently loaded app has not uploaded a firmware to the DSP
+ Den aktuella appen har inte skickat upp någon firmware till DSP:n
+
+
+
+ Failed to open output file
+ Misslyckades med att öppna utdatafilen
+
+
+
+ The currently loaded DSP firmware could not be written to the selected file. Please make sure you have permission to access this file
+ 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
+
+
+
+ PatchWindow
+
+
+ ROM patcher
+ ROM-patchare
+
+
+
+ Select input file
+ Välj inmatningsfil
+
+
+
+
+ Select
+ Välj
+
+
+
+
+ Select patch file
+ Välj patchfil
+
+
+
+ Apply patch
+ Applicera patch
+
+
+
+ Select file to patch
+ Välj fil som ska patchas
+
+
+
+
+ All files (*.*)
+ Alla filer (*.*)
+
+
+
+ Patch files (*.ips *.ups *.bps)
+ Patch-filer (*.ips *.ups *.bps)
+
+
+
+ Paths not provided correctly
+ Sökvägar anges inte korrekt
+
+
+
+ Please provide paths for both the input file and the patch file
+ Ange sökvägar för både indatafilen och patchfilen
+
+
+
+ Select file
+ Välj fil
+
+
+
+ No output path
+ Ingen sökväg för utmatning
+
+
+
+ No path was provided for the output file, no patching was done
+ Ingen sökväg angavs för utdatafilen, ingen patchning gjordes
+
+
+
+ Unknown patch format
+ Okänt patchformat
+
+
+
+ Unknown format for patch file. Currently IPS, UPS and BPS are supported
+ Okänt format för patchfil. För närvarande stöds IPS, UPS och BPS
+
+
+
+ Failed to open input files
+ Misslyckades med att öppna indatafiler
+
+
+
+ Make sure they're in a directory Panda3DS has access to
+ Se till att de finns i en katalog som Panda3DS har tillgång till
+
+
+
+ Patching Success
+ Patchning lyckades
+
+
+
+ Your file was patched successfully.
+ Din fil patchades.
+
+
+
+ Checksum mismatch
+ Kontrollsumman stämmer inte överens
+
+
+
+ Patch was applied successfully but a checksum mismatch was detected. The input or output files might not be correct
+ Patchen applicerades men en avvikelse i kontrollsumman upptäcktes. Inmatnings- eller utdatafilerna kanske inte är korrekta
+
+
+
+ Patching error
+ Fel vid patchning
+
+
+
+ An error occured while patching
+ Ett fel uppstod vid patchning
+
+
+
+ PatchWindow::PatchWindow
+
+
+ OK
+ Ok
+
+
+
+ ShaderEditorWindow
+
+
+ Reload shader
+ Läs om shader
+
+
+
+ TextEditorWindow
+
+
+ Lua Editor
+ Lua-redigerare
+
+
+
+ Load script
+ Läs in skript
+
+
+
diff --git a/include/PICA/shader_gen_types.hpp b/include/PICA/shader_gen_types.hpp
index 1877227f..b069f71f 100644
--- a/include/PICA/shader_gen_types.hpp
+++ b/include/PICA/shader_gen_types.hpp
@@ -2,8 +2,8 @@
namespace PICA::ShaderGen {
// Graphics API this shader is targetting
- enum class API { GL, GLES, Vulkan };
+ enum class API { GL, GLES, Vulkan, Metal };
- // Shading language to use (Only GLSL for the time being)
- enum class Language { GLSL };
-} // namespace PICA::ShaderGen
\ No newline at end of file
+ // Shading language to use
+ enum class Language { GLSL, MSL };
+} // namespace PICA::ShaderGen
diff --git a/include/audio/audio_device.hpp b/include/audio/audio_device.hpp
new file mode 100644
index 00000000..966fd667
--- /dev/null
+++ b/include/audio/audio_device.hpp
@@ -0,0 +1,9 @@
+#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
\ No newline at end of file
diff --git a/include/audio/audio_device_interface.hpp b/include/audio/audio_device_interface.hpp
new file mode 100644
index 00000000..de70c77a
--- /dev/null
+++ b/include/audio/audio_device_interface.hpp
@@ -0,0 +1,36 @@
+#pragma once
+#include
+
+#include "config.hpp"
+#include "helpers.hpp"
+#include "ring_buffer.hpp"
+
+class AudioDeviceInterface {
+ protected:
+ static constexpr usize maxFrameCount = 0x2000;
+
+ using Samples = Common::RingBuffer;
+ 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 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) {}
+};
\ No newline at end of file
diff --git a/include/audio/libretro_audio_device.hpp b/include/audio/libretro_audio_device.hpp
new file mode 100644
index 00000000..9c6d19f8
--- /dev/null
+++ b/include/audio/libretro_audio_device.hpp
@@ -0,0 +1,61 @@
+#pragma once
+#include
+
+#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; }
+};
diff --git a/include/audio/miniaudio_device.hpp b/include/audio/miniaudio_device.hpp
index 0363aa44..5cf7c801 100644
--- a/include/audio/miniaudio_device.hpp
+++ b/include/audio/miniaudio_device.hpp
@@ -3,39 +3,31 @@
#include
#include
-#include "config.hpp"
-#include "helpers.hpp"
+#include "audio/audio_device_interface.hpp"
#include "miniaudio.h"
-#include "ring_buffer.hpp"
-class MiniAudioDevice {
- using Samples = Common::RingBuffer;
+class MiniAudioDevice final : public AudioDeviceInterface {
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 lastStereoSample;
std::vector audioDevices;
public:
MiniAudioDevice(const AudioDeviceConfig& audioSettings);
// If safe is on, we create a null audio device
- void init(Samples& samples, bool safe = false);
- void close();
+ void init(Samples& samples, bool safe = false) override;
+ void close() override;
- void start();
- void stop();
+ void start() override;
+ void stop() override;
bool isInitialized() const { return initialized; }
};
\ No newline at end of file
diff --git a/include/config.hpp b/include/config.hpp
index 6041286d..5e1bd8a7 100644
--- a/include/config.hpp
+++ b/include/config.hpp
@@ -5,6 +5,7 @@
#include "audio/dsp_core.hpp"
#include "frontend_settings.hpp"
#include "renderer.hpp"
+#include "services/region_codes.hpp"
struct AudioDeviceConfig {
// Audio curve to use for volumes between 0-100
@@ -48,9 +49,26 @@ struct EmulatorConfig {
#endif
static constexpr bool accelerateShadersDefault = true;
+#if defined(__LIBRETRO__)
+ static constexpr bool audioEnabledDefault = true;
+#else
+ 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
+
+ static constexpr bool hashTexturesDefault = true;
+
bool shaderJitEnabled = shaderJitDefault;
bool useUbershaders = ubershaderDefault;
bool accelerateShaders = accelerateShadersDefault;
+ bool hashTextures = hashTexturesDefault;
+
bool accurateShaderMul = false;
bool discordRpcEnabled = false;
@@ -58,14 +76,14 @@ struct EmulatorConfig {
bool forceShadergenForLights = true;
int lightShadergenThreshold = 1;
- RendererType rendererType = RendererType::OpenGL;
+ RendererType rendererType = rendererDefault;
Audio::DSPCore::Type dspType = Audio::DSPCore::Type::HLE;
bool sdCardInserted = true;
bool sdWriteProtected = false;
bool usePortableBuild = false;
- bool audioEnabled = false;
+ bool audioEnabled = audioEnabledDefault;
bool vsyncEnabled = true;
bool aacEnabled = true; // Enable AAC audio?
@@ -77,6 +95,8 @@ struct EmulatorConfig {
// Default to 3% battery to make users suffer
int batteryPercentage = 3;
+ LanguageCodes systemLanguage = LanguageCodes::English;
+
// Default ROM path to open in Qt and misc frontends
std::filesystem::path defaultRomPath = "";
std::filesystem::path filePath;
@@ -104,4 +124,7 @@ struct EmulatorConfig {
EmulatorConfig(const std::filesystem::path& path);
void load();
void save();
+
+ static LanguageCodes languageCodeFromString(std::string inString);
+ static const char* languageCodeToString(LanguageCodes code);
};
\ No newline at end of file
diff --git a/include/cpu_dynarmic.hpp b/include/cpu_dynarmic.hpp
index 43f31d30..24358533 100644
--- a/include/cpu_dynarmic.hpp
+++ b/include/cpu_dynarmic.hpp
@@ -181,5 +181,7 @@ 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();
};
\ No newline at end of file
diff --git a/include/emulator.hpp b/include/emulator.hpp
index cf231328..326eb232 100644
--- a/include/emulator.hpp
+++ b/include/emulator.hpp
@@ -7,8 +7,8 @@
#include
#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;
- MiniAudioDevice audioDevice;
+ AudioDevice 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,7 +89,6 @@ class Emulator {
~Emulator();
void step();
- void render();
void reset(ReloadOption reload);
void runFrame();
// Poll the scheduler for events
@@ -127,6 +126,7 @@ 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(); }
diff --git a/include/frontend_settings.hpp b/include/frontend_settings.hpp
index ae967879..083b8c7d 100644
--- a/include/frontend_settings.hpp
+++ b/include/frontend_settings.hpp
@@ -11,6 +11,7 @@ struct FrontendSettings {
Dark = 2,
GreetingsCat = 3,
Cream = 4,
+ Oled = 5,
};
// Different panda-themed window icons
@@ -20,6 +21,7 @@ struct FrontendSettings {
Rnap = 2,
Rcow = 3,
SkyEmu = 4,
+ Runpog = 5,
};
Theme theme = Theme::Dark;
diff --git a/include/ios_driver.h b/include/ios_driver.h
new file mode 100644
index 00000000..7f783970
--- /dev/null
+++ b/include/ios_driver.h
@@ -0,0 +1,7 @@
+#pragma once
+#include
+#include
+
+void iosCreateEmulator();
+void iosLoadROM(NSString* pathNS);
+void iosRunFrame(CAMetalLayer* layer);
\ No newline at end of file
diff --git a/include/ipc.hpp b/include/ipc.hpp
index 204b2e9c..07a77f02 100644
--- a/include/ipc.hpp
+++ b/include/ipc.hpp
@@ -5,7 +5,7 @@ namespace IPC {
namespace BufferType {
enum : std::uint32_t {
Send = 1,
- Receive,
+ Receive = 2,
};
}
diff --git a/include/kernel/handles.hpp b/include/kernel/handles.hpp
index 5cb7d8a4..58b8beff 100644
--- a/include/kernel/handles.hpp
+++ b/include/kernel/handles.hpp
@@ -20,6 +20,7 @@ namespace KernelHandles {
CFG_U, // CFG service (Console & region info)
CFG_I,
CFG_S, // Used by most system apps in lieu of cfg:u
+ CFG_NOR, // Used by system settings app
CSND, // Plays audio directly from PCM samples
DLP_SRVR, // Download Play: Server. Used for network play.
DSP, // DSP service (Used for audio decoding and output)
@@ -39,9 +40,10 @@ namespace KernelHandles {
NIM_U, // Updates
NDM, // ?????
NS_S, // Nintendo Shell service
+ NWM_EXT, // ?????
NWM_UDS, // Local multiplayer
NEWS_S, // news:u on steroids
- NEWS_U, // This service literally has 1 command (AddNotification) and I don't even understand what it does
+ NEWS_U, // This service literally has 1 command (AddNotification)
PTM_U, // PTM service (Used for accessing various console info, such as battery, shell and pedometer state)
PTM_SYSM, // PTM system service
PTM_PLAY, // PTM Play service, used for retrieving play history
@@ -85,6 +87,8 @@ namespace KernelHandles {
case CECD: return "CECD";
case CFG_U: return "CFG:U";
case CFG_I: return "CFG:I";
+ case CFG_S: return "CFG:S";
+ case CFG_NOR: return "CFG:NOR";
case CSND: return "CSND";
case DSP: return "DSP";
case DLP_SRVR: return "DLP::SRVR";
@@ -102,6 +106,7 @@ namespace KernelHandles {
case NDM: return "NDM";
case NEWS_S: return "NEWS_S";
case NEWS_U: return "NEWS_U";
+ case NWM_EXT: return "nwm::EXT";
case NWM_UDS: return "nwm::UDS";
case NFC: return "NFC";
case NIM_AOC: return "NIM:AOC";
@@ -109,6 +114,7 @@ namespace KernelHandles {
case PTM_U: return "PTM:U";
case PTM_SYSM: return "PTM:SYSM";
case PTM_PLAY: return "PTM:PLAY";
+ case PTM_GETS: return "PTM:GETS";
case SOC: return "SOC";
case SSL: return "SSL";
case Y2R: return "Y2R";
diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp
index abc508ac..3f20b5e1 100644
--- a/include/kernel/kernel.hpp
+++ b/include/kernel/kernel.hpp
@@ -175,6 +175,8 @@ public:
void svcSignalEvent();
void svcSetTimer();
void svcSleepThread();
+ void svcInvalidateInstructionCacheRange();
+ void svcInvalidateEntireInstructionCache();
void connectToPort();
void outputDebugString();
void waitSynchronization1();
@@ -250,4 +252,6 @@ public:
void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
void clearInstructionCache();
+ void clearInstructionCacheRange(u32 start, u32 size);
+ u32 getSharedFontVaddr();
};
\ No newline at end of file
diff --git a/include/kernel/resource_limits.hpp b/include/kernel/resource_limits.hpp
index 85f1a59b..fe1154ff 100644
--- a/include/kernel/resource_limits.hpp
+++ b/include/kernel/resource_limits.hpp
@@ -19,7 +19,7 @@ struct ResourceLimitValues {
// APPLICATION resource limit
static constexpr ResourceLimitValues appResourceLimits = {
.maxPriority = 0x18,
- .maxCommit = 0x4000000,
+ .maxCommit = 64_MB + 16_MB, // We're currently giving 80MB to all apps. TODO: Implement extended memory properly
.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,
+ .maxCommit = 0x5E00000 - 16_MB,
.maxThreads = 0x1D,
.maxEvents = 0xB,
.maxMutexes = 0x8,
diff --git a/include/memory.hpp b/include/memory.hpp
index bd002c54..b1dd09de 100644
--- a/include/memory.hpp
+++ b/include/memory.hpp
@@ -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(64_MB);
+ static constexpr u32 FCRAM_APPLICATION_SIZE = u32(80_MB);
static constexpr u32 FCRAM_PAGE_COUNT = FCRAM_SIZE / pageSize;
static constexpr u32 FCRAM_APPLICATION_PAGE_COUNT = FCRAM_APPLICATION_SIZE / pageSize;
diff --git a/include/renderer.hpp b/include/renderer.hpp
index bc5dfac6..0798184d 100644
--- a/include/renderer.hpp
+++ b/include/renderer.hpp
@@ -51,8 +51,12 @@ class Renderer {
u32 outputWindowWidth = 400;
u32 outputWindowHeight = 240 * 2;
+ // Should hw renderers hash textures? Stored separately from emulatorConfig because we'll be accessing it constantly, might be merged eventually
+ bool hashTextures = false;
+
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& internalRegs, const std::array& externalRegs);
virtual ~Renderer();
@@ -81,6 +85,14 @@ 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.
@@ -114,4 +126,5 @@ class Renderer {
}
void setConfig(EmulatorConfig* config) { emulatorConfig = config; }
+ void setHashTextures(bool setting) { hashTextures = setting; }
};
diff --git a/include/renderer_gl/gl_driver.hpp b/include/renderer_gl/gl_driver.hpp
index a15c061f..4a0b3727 100644
--- a/include/renderer_gl/gl_driver.hpp
+++ b/include/renderer_gl/gl_driver.hpp
@@ -4,6 +4,7 @@
// 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;
diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp
index fab239f2..a862cd26 100644
--- a/include/renderer_gl/renderer_gl.hpp
+++ b/include/renderer_gl/renderer_gl.hpp
@@ -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,6 +157,7 @@ class RendererGL final : public Renderer {
void initGraphicsContextInternal();
void accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel);
+ void compileDisplayShader();
public:
RendererGL(GPU& gpu, const std::array& internalRegs, const std::array& externalRegs)
@@ -169,14 +170,15 @@ 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 vertices) override; // Draw the given vertices
+ void drawVertices(PICA::PrimType primType, std::span 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 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
diff --git a/include/renderer_gl/textures.hpp b/include/renderer_gl/textures.hpp
index 4c6ca2dd..9663c2b4 100644
--- a/include/renderer_gl/textures.hpp
+++ b/include/renderer_gl/textures.hpp
@@ -1,6 +1,8 @@
#pragma once
#include
#include
+
+#include "PICA/pica_hash.hpp"
#include "PICA/regs.hpp"
#include "boost/icl/interval.hpp"
#include "helpers.hpp"
@@ -11,55 +13,55 @@ template
using Interval = boost::icl::right_open_interval;
struct Texture {
- u32 location;
- u32 config; // Magnification/minification filter, wrapping configs, etc
- PICA::TextureFmt format;
- OpenGL::uvec2 size;
- bool valid;
+ using Hash = PICAHash::HashType;
- // Range of VRAM taken up by buffer
- Interval range;
- // OpenGL resources allocated to buffer
- OpenGL::Texture texture;
+ u32 location;
+ u32 config; // Magnification/minification filter, wrapping configs, etc
+ Hash hash = Hash(0);
- Texture() : valid(false) {}
+ PICA::TextureFmt format;
+ OpenGL::uvec2 size;
+ bool valid;
- Texture(u32 loc, PICA::TextureFmt format, u32 x, u32 y, u32 config, bool valid = true)
- : location(loc), format(format), size({x, y}), config(config), valid(valid) {
+ // Range of VRAM taken up by buffer
+ Interval range;
+ // OpenGL resources allocated to buffer
+ OpenGL::Texture texture;
- u64 endLoc = (u64)loc + sizeInBytes();
- // Check if start and end are valid here
- range = Interval(loc, (u32)endLoc);
- }
+ Texture() : valid(false) {}
- // For 2 textures to "match" we only care about their locations, formats, and dimensions to match
- // For other things, such as filtering mode, etc, we can just switch the attributes of the cached texture
- bool matches(Texture& other) {
- return location == other.location && format == other.format &&
- size.x() == other.size.x() && size.y() == other.size.y();
- }
+ Texture(u32 loc, PICA::TextureFmt format, u32 x, u32 y, u32 config, bool valid = true)
+ : location(loc), format(format), size({x, y}), config(config), valid(valid) {
+ u64 endLoc = (u64)loc + sizeInBytes();
+ // Check if start and end are valid here
+ range = Interval(loc, (u32)endLoc);
+ }
- void allocate();
- void setNewConfig(u32 newConfig);
- void decodeTexture(std::span data);
- void free();
- u64 sizeInBytes();
+ // For 2 textures to "match" we only care about their locations, formats, and dimensions to match
+ // For other things, such as filtering mode, etc, we can just switch the attributes of the cached texture
+ bool matches(Texture& other) {
+ return location == other.location && hash == other.hash && format == other.format && size.x() == other.size.x() && size.y() == other.size.y();
+ }
- u32 decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, std::span data);
+ void allocate();
+ void setNewConfig(u32 newConfig);
+ void decodeTexture(std::span data);
+ void free();
+ u64 sizeInBytes();
- // 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);
+ u32 decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, std::span data);
- // Returns the format of this texture as a string
- std::string_view formatToString() {
- return PICA::textureFormatToString(format);
- }
+ // 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 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 data);
- u32 decodeETC(u32 alpha, u32 u, u32 v, u64 colourData);
+ // 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 data);
+ u32 decodeETC(u32 alpha, u32 u, u32 v, u64 colourData);
};
diff --git a/include/renderer_mtl/mtl_render_target.hpp b/include/renderer_mtl/mtl_render_target.hpp
index 8f80ea64..65f921da 100644
--- a/include/renderer_mtl/mtl_render_target.hpp
+++ b/include/renderer_mtl/mtl_render_target.hpp
@@ -57,7 +57,7 @@ namespace Metal {
} else if (std::is_same::value) {
pixelFormat = PICA::toMTLPixelFormatDepth((PICA::DepthFmt)format);
} else {
- panic("Invalid format type");
+ Helpers::panic("Invalid format type");
}
MTL::TextureDescriptor* descriptor = MTL::TextureDescriptor::alloc()->init();
diff --git a/include/renderer_mtl/mtl_texture.hpp b/include/renderer_mtl/mtl_texture.hpp
index 93103091..b6989434 100644
--- a/include/renderer_mtl/mtl_texture.hpp
+++ b/include/renderer_mtl/mtl_texture.hpp
@@ -4,22 +4,28 @@
#include
#include
+#include "PICA/pica_hash.hpp"
#include "PICA/regs.hpp"
#include "boost/icl/interval.hpp"
#include "helpers.hpp"
#include "math_util.hpp"
-#include "opengl.hpp"
#include "renderer_mtl/pica_to_mtl.hpp"
+// TODO: remove dependency on OpenGL
+#include "opengl.hpp"
template
using Interval = boost::icl::right_open_interval;
namespace Metal {
struct Texture {
+ using Hash = PICAHash::HashType;
+
MTL::Device* device;
u32 location;
u32 config; // Magnification/minification filter, wrapping configs, etc
+ Hash hash = Hash(0);
+
PICA::TextureFmt format;
OpenGL::uvec2 size;
bool valid;
@@ -27,7 +33,8 @@ namespace Metal {
// Range of VRAM taken up by buffer
Interval range;
- PICA::PixelFormatInfo formatInfo;
+ PICA::MTLPixelFormatInfo formatInfo;
+ MTL::Texture* base = nullptr;
MTL::Texture* texture = nullptr;
MTL::SamplerState* sampler = nullptr;
@@ -43,7 +50,8 @@ namespace Metal {
// For 2 textures to "match" we only care about their locations, formats, and dimensions to match
// For other things, such as filtering mode, etc, we can just switch the attributes of the cached texture
bool matches(Texture& other) {
- return location == other.location && format == other.format && size.x() == other.size.x() && size.y() == other.size.y();
+ return location == other.location && hash == other.hash && format == other.format && size.x() == other.size.x() &&
+ size.y() == other.size.y();
}
void allocate();
@@ -52,22 +60,7 @@ namespace Metal {
void free();
u64 sizeInBytes();
- u8 decodeTexelU8(u32 u, u32 v, PICA::TextureFmt fmt, std::span data);
- u16 decodeTexelU16(u32 u, u32 v, PICA::TextureFmt fmt, std::span data);
- u32 decodeTexelU32(u32 u, u32 v, PICA::TextureFmt fmt, std::span 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 data);
- u32 decodeETC(u32 alpha, u32 u, u32 v, u64 colourData);
};
} // namespace Metal
diff --git a/include/renderer_mtl/pica_to_mtl.hpp b/include/renderer_mtl/pica_to_mtl.hpp
index 715088b4..d4c6dc7c 100644
--- a/include/renderer_mtl/pica_to_mtl.hpp
+++ b/include/renderer_mtl/pica_to_mtl.hpp
@@ -3,31 +3,28 @@
#include
#include "PICA/regs.hpp"
+// TODO: remove dependency on OpenGL
+#include "opengl.hpp"
namespace PICA {
- struct PixelFormatInfo {
+ struct MTLPixelFormatInfo {
MTL::PixelFormat pixelFormat;
size_t bytesPerTexel;
+ void (*decoder)(OpenGL::uvec2, u32, u32, std::span, u8*);
+
+ bool needsSwizzle = false;
+ MTL::TextureSwizzleChannels swizzle{
+ .red = MTL::TextureSwizzleRed,
+ .green = MTL::TextureSwizzleGreen,
+ .blue = MTL::TextureSwizzleBlue,
+ .alpha = MTL::TextureSwizzleAlpha,
+ };
};
- 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
- };
+ extern MTLPixelFormatInfo mtlPixelFormatInfos[14];
- inline PixelFormatInfo getPixelFormatInfo(TextureFmt format) { return pixelFormatInfos[static_cast(format)]; }
+ void checkForMTLPixelFormatSupport(MTL::Device* device);
+ inline MTLPixelFormatInfo getMTLPixelFormatInfo(TextureFmt format) { return mtlPixelFormatInfos[static_cast(format)]; }
inline MTL::PixelFormat toMTLPixelFormatColor(ColorFmt format) {
switch (format) {
@@ -35,7 +32,11 @@ 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
}
}
diff --git a/include/renderer_mtl/renderer_mtl.hpp b/include/renderer_mtl/renderer_mtl.hpp
index bd5c3bf1..10fac7cd 100644
--- a/include/renderer_mtl/renderer_mtl.hpp
+++ b/include/renderer_mtl/renderer_mtl.hpp
@@ -42,11 +42,13 @@ class RendererMTL final : public Renderer {
virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override {}
#endif
- private:
- CA::MetalLayer* metalLayer;
+ virtual void setMTKLayer(void* layer) override;
- MTL::Device* device;
- MTL::CommandQueue* commandQueue;
+ private:
+ CA::MetalLayer* metalLayer = nullptr;
+
+ MTL::Device* device = nullptr;
+ MTL::CommandQueue* commandQueue = nullptr;
Metal::CommandEncoder commandEncoder;
@@ -98,6 +100,7 @@ class RendererMTL final : public Renderer {
void endRenderPass() {
if (renderCommandEncoder) {
renderCommandEncoder->endEncoding();
+ renderCommandEncoder->release();
renderCommandEncoder = nullptr;
}
}
diff --git a/include/renderer_mtl/texture_decoder.hpp b/include/renderer_mtl/texture_decoder.hpp
new file mode 100644
index 00000000..376231c0
--- /dev/null
+++ b/include/renderer_mtl/texture_decoder.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "helpers.hpp"
+// TODO: remove dependency on OpenGL
+#include "opengl.hpp"
+
+void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
+void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData);
diff --git a/include/renderer_vk/vk_debug.hpp b/include/renderer_vk/vk_debug.hpp
index ed712269..0cf3f938 100644
--- a/include/renderer_vk/vk_debug.hpp
+++ b/include/renderer_vk/vk_debug.hpp
@@ -9,8 +9,8 @@
namespace Vulkan {
VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(
- VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType,
- const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData
+ vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, vk::DebugUtilsMessageTypeFlagsEXT messageType,
+ const vk::DebugUtilsMessengerCallbackDataEXT* callbackData, void* userData
);
void setObjectName(vk::Device device, vk::ObjectType objectType, const void* objectHandle, const char* format, ...);
diff --git a/include/services/cfg.hpp b/include/services/cfg.hpp
index 0feb6db3..bac2cd87 100644
--- a/include/services/cfg.hpp
+++ b/include/services/cfg.hpp
@@ -1,6 +1,7 @@
#pragma once
#include
+#include "config.hpp"
#include "helpers.hpp"
#include "logger.hpp"
#include "memory.hpp"
@@ -11,6 +12,8 @@ class CFGService {
using Handle = HorizonHandle;
Memory& mem;
+ const EmulatorConfig& settings;
+
CountryCodes country = CountryCodes::US; // Default to USA
MAKE_LOG_FUNCTION(log, cfgLogger)
@@ -18,8 +21,9 @@ class CFGService {
// Service functions
void getConfigInfoBlk2(u32 messagePointer);
- void getConfigInfoBlk8(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);
@@ -29,6 +33,11 @@ class CFGService {
void setConfigInfoBlk4(u32 messagePointer);
void updateConfigNANDSavegame(u32 messagePointer);
void translateCountryInfo(u32 messagePointer);
+ void isFangateSupported(u32 messagePointer);
+
+ // cfg:nor functions
+ void norInitialize(u32 messagePointer);
+ void norReadData(u32 messagePointer);
void getConfigInfo(u32 output, u32 blockID, u32 size, u32 permissionMask);
@@ -40,7 +49,7 @@ class CFGService {
NOR, // cfg:nor
};
- CFGService(Memory& mem) : mem(mem) {}
+ CFGService(Memory& mem, const EmulatorConfig& settings) : mem(mem), settings(settings) {}
void reset();
void handleSyncRequest(u32 messagePointer, Type type);
};
\ No newline at end of file
diff --git a/include/services/gsp_gpu.hpp b/include/services/gsp_gpu.hpp
index 8294565b..4ac8e747 100644
--- a/include/services/gsp_gpu.hpp
+++ b/include/services/gsp_gpu.hpp
@@ -121,4 +121,4 @@ class GPUService {
std::memset(ptr, 0, 0x1000);
}
}
-};
+};
\ No newline at end of file
diff --git a/include/services/gsp_lcd.hpp b/include/services/gsp_lcd.hpp
index 302771ff..7dbdae8f 100644
--- a/include/services/gsp_lcd.hpp
+++ b/include/services/gsp_lcd.hpp
@@ -6,9 +6,6 @@
#include "result/result.hpp"
class LCDService {
- using Handle = HorizonHandle;
-
- Handle handle = KernelHandles::LCD;
Memory& mem;
MAKE_LOG_FUNCTION(log, gspLCDLogger)
diff --git a/include/services/ns.hpp b/include/services/ns.hpp
index 3acf87a0..cb00e49b 100644
--- a/include/services/ns.hpp
+++ b/include/services/ns.hpp
@@ -6,20 +6,20 @@
#include "result/result.hpp"
class NSService {
- Memory& mem;
+ Memory& mem;
MAKE_LOG_FUNCTION(log, nsLogger)
- // Service commands
- void launchTitle(u32 messagePointer);
+ // Service commands
+ void launchTitle(u32 messagePointer);
-public:
- enum class Type {
- S, // ns:s
- P, // ns:p
- C, // ns:c
- };
+ public:
+ enum class Type {
+ S, // ns:s
+ P, // ns:p
+ C, // ns:c
+ };
- NSService(Memory& mem) : mem(mem) {}
- void reset();
+ NSService(Memory& mem) : mem(mem) {}
+ void reset();
void handleSyncRequest(u32 messagePointer, Type type);
};
diff --git a/readme.md b/readme.md
index 7ffb7384..438a2b95 100644
--- a/readme.md
+++ b/readme.md
@@ -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](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:
+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:
- 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,11 +113,12 @@ 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)
diff --git a/src/config.cpp b/src/config.cpp
index 73b5d664..59f10bd5 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -6,6 +6,7 @@
#include
#include