summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.travis-deps.sh13
-rw-r--r--.travis.yml2
-rw-r--r--CMakeLists.txt29
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--README.md10
-rw-r--r--appveyor.yml4
-rw-r--r--externals/cmake-modules/FindSDL2.cmake224
-rw-r--r--externals/cmake-modules/WindowsCopyFiles.cmake28
-rw-r--r--externals/glad/include/glad/glad.h923
-rw-r--r--externals/glad/src/glad.c52
-rw-r--r--externals/glfw-3.1.1.bin/COPYING.txt22
-rw-r--r--externals/glfw-3.1.1.bin/include/GLFW/glfw3.h3340
-rw-r--r--externals/glfw-3.1.1.bin/include/GLFW/glfw3native.h356
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3.dllbin196839 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3dll.abin54834 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-i686/libglfw3.abin89732 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3.dllbin235754 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3dll.abin53500 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-x86_64/libglfw3.abin97354 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.dllbin47104 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.libbin150616 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3dll.libbin19984 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.dllbin53248 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.libbin196774 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3dll.libbin19602 -> 0 bytes
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/audio_core/CMakeLists.txt16
-rw-r--r--src/audio_core/audio_core.cpp53
-rw-r--r--src/audio_core/audio_core.h26
-rw-r--r--src/audio_core/hle/dsp.cpp42
-rw-r--r--src/audio_core/hle/dsp.h539
-rw-r--r--src/audio_core/hle/pipe.cpp159
-rw-r--r--src/audio_core/hle/pipe.h57
-rw-r--r--src/audio_core/sink.h34
-rw-r--r--src/citra/CMakeLists.txt21
-rw-r--r--src/citra/citra.cpp4
-rw-r--r--src/citra/config.cpp60
-rw-r--r--src/citra/config.h10
-rw-r--r--src/citra/default_ini.h2
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp168
-rw-r--r--src/citra/emu_window/emu_window_glfw.h54
-rw-r--r--src/citra/emu_window/emu_window_sdl2.cpp167
-rw-r--r--src/citra/emu_window/emu_window_sdl2.h64
-rw-r--r--src/citra_qt/CMakeLists.txt27
-rw-r--r--src/citra_qt/debugger/callstack.cpp12
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.cpp1
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp1
-rw-r--r--src/citra_qt/debugger/graphics_tracing.cpp2
-rw-r--r--src/citra_qt/debugger/graphics_vertex_shader.cpp6
-rw-r--r--src/citra_qt/debugger/registers.cpp8
-rw-r--r--src/citra_qt/main.cpp89
-rw-r--r--src/citra_qt/main.h10
-rw-r--r--src/common/bit_field.h44
-rw-r--r--src/common/color.h16
-rw-r--r--src/common/common_funcs.h10
-rw-r--r--src/common/emu_window.cpp4
-rw-r--r--src/common/file_util.cpp20
-rw-r--r--src/common/key_map.h14
-rw-r--r--src/common/logging/backend.cpp4
-rw-r--r--src/common/logging/backend.h20
-rw-r--r--src/common/logging/log.h4
-rw-r--r--src/common/x64/emitter.cpp4
-rw-r--r--src/common/x64/emitter.h113
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/arm/arm_interface.h11
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp18
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp8
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp549
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.h4
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h32
-rw-r--r--src/core/core.cpp18
-rw-r--r--src/core/core.h7
-rw-r--r--src/core/file_sys/archive_backend.cpp8
-rw-r--r--src/core/file_sys/archive_backend.h8
-rw-r--r--src/core/file_sys/disk_archive.cpp6
-rw-r--r--src/core/hle/function_wrappers.h4
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp25
-rw-r--r--src/core/hle/kernel/memory.cpp5
-rw-r--r--src/core/hle/kernel/process.cpp8
-rw-r--r--src/core/hle/kernel/process.h1
-rw-r--r--src/core/hle/kernel/shared_memory.cpp21
-rw-r--r--src/core/hle/kernel/shared_memory.h7
-rw-r--r--src/core/hle/kernel/thread.cpp2
-rw-r--r--src/core/hle/kernel/timer.cpp6
-rw-r--r--src/core/hle/kernel/vm_manager.cpp7
-rw-r--r--src/core/hle/kernel/vm_manager.h5
-rw-r--r--src/core/hle/result.h67
-rw-r--r--src/core/hle/service/ac_u.cpp20
-rw-r--r--src/core/hle/service/act_u.cpp8
-rw-r--r--src/core/hle/service/am/am.cpp4
-rw-r--r--src/core/hle/service/am/am.h6
-rw-r--r--src/core/hle/service/am/am_app.cpp1
-rw-r--r--src/core/hle/service/am/am_net.cpp31
-rw-r--r--src/core/hle/service/am/am_sys.cpp16
-rw-r--r--src/core/hle/service/am/am_u.cpp29
-rw-r--r--src/core/hle/service/apt/apt.cpp2
-rw-r--r--src/core/hle/service/apt/apt_a.cpp1
-rw-r--r--src/core/hle/service/apt/apt_s.cpp8
-rw-r--r--src/core/hle/service/apt/apt_u.cpp9
-rw-r--r--src/core/hle/service/boss/boss.cpp4
-rw-r--r--src/core/hle/service/boss/boss.h3
-rw-r--r--src/core/hle/service/boss/boss_p.cpp2
-rw-r--r--src/core/hle/service/boss/boss_u.cpp5
-rw-r--r--src/core/hle/service/cam/cam.cpp286
-rw-r--r--src/core/hle/service/cam/cam.h417
-rw-r--r--src/core/hle/service/cam/cam_c.cpp2
-rw-r--r--src/core/hle/service/cam/cam_q.cpp2
-rw-r--r--src/core/hle/service/cam/cam_s.cpp2
-rw-r--r--src/core/hle/service/cam/cam_u.cpp44
-rw-r--r--src/core/hle/service/cecd/cecd.cpp4
-rw-r--r--src/core/hle/service/cecd/cecd.h3
-rw-r--r--src/core/hle/service/cecd/cecd_s.cpp2
-rw-r--r--src/core/hle/service/cecd/cecd_u.cpp9
-rw-r--r--src/core/hle/service/cfg/cfg.cpp27
-rw-r--r--src/core/hle/service/cfg/cfg.h9
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp1
-rw-r--r--src/core/hle/service/cfg/cfg_s.cpp1
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp1
-rw-r--r--src/core/hle/service/csnd_snd.cpp7
-rw-r--r--src/core/hle/service/dsp_dsp.cpp311
-rw-r--r--src/core/hle/service/dsp_dsp.h12
-rw-r--r--src/core/hle/service/err_f.cpp3
-rw-r--r--src/core/hle/service/frd/frd.cpp4
-rw-r--r--src/core/hle/service/frd/frd.h3
-rw-r--r--src/core/hle/service/frd/frd_a.cpp2
-rw-r--r--src/core/hle/service/frd/frd_u.cpp45
-rw-r--r--src/core/hle/service/fs/fs_user.cpp196
-rw-r--r--src/core/hle/service/gsp_gpu.cpp16
-rw-r--r--src/core/hle/service/gsp_lcd.cpp13
-rw-r--r--src/core/hle/service/hid/hid.cpp3
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp1
-rw-r--r--src/core/hle/service/hid/hid_user.cpp3
-rw-r--r--src/core/hle/service/http_c.cpp13
-rw-r--r--src/core/hle/service/ir/ir.cpp73
-rw-r--r--src/core/hle/service/ir/ir.h53
-rw-r--r--src/core/hle/service/ir/ir_rst.cpp1
-rw-r--r--src/core/hle/service/ir/ir_u.cpp2
-rw-r--r--src/core/hle/service/ir/ir_user.cpp41
-rw-r--r--src/core/hle/service/ldr_ro.cpp2
-rw-r--r--src/core/hle/service/mic_u.cpp11
-rw-r--r--src/core/hle/service/ndm_u.cpp19
-rw-r--r--src/core/hle/service/news/news.cpp4
-rw-r--r--src/core/hle/service/news/news.h3
-rw-r--r--src/core/hle/service/news/news_s.cpp13
-rw-r--r--src/core/hle/service/news/news_u.cpp2
-rw-r--r--src/core/hle/service/nim/nim.cpp5
-rw-r--r--src/core/hle/service/nim/nim.h6
-rw-r--r--src/core/hle/service/nim/nim_aoc.cpp2
-rw-r--r--src/core/hle/service/nim/nim_s.cpp5
-rw-r--r--src/core/hle/service/nim/nim_u.cpp1
-rw-r--r--src/core/hle/service/ns_s.cpp16
-rw-r--r--src/core/hle/service/nwm_uds.cpp20
-rw-r--r--src/core/hle/service/pm_app.cpp5
-rw-r--r--src/core/hle/service/ptm/ptm.cpp4
-rw-r--r--src/core/hle/service/ptm/ptm.h7
-rw-r--r--src/core/hle/service/ptm/ptm_play.cpp1
-rw-r--r--src/core/hle/service/ptm/ptm_sysm.cpp4
-rw-r--r--src/core/hle/service/ptm/ptm_u.cpp3
-rw-r--r--src/core/hle/service/soc_u.cpp32
-rw-r--r--src/core/hle/service/srv.cpp2
-rw-r--r--src/core/hle/service/ssl_c.cpp16
-rw-r--r--src/core/hle/service/y2r_u.cpp27
-rw-r--r--src/core/hle/svc.cpp37
-rw-r--r--src/core/hw/gpu.cpp34
-rw-r--r--src/core/loader/elf.cpp6
-rw-r--r--src/core/loader/loader.cpp6
-rw-r--r--src/core/loader/ncch.cpp3
-rw-r--r--src/core/memory.cpp88
-rw-r--r--src/core/memory_setup.h7
-rw-r--r--src/core/mmio.h34
-rw-r--r--src/core/system.cpp15
-rw-r--r--src/core/system.h9
-rw-r--r--src/video_core/CMakeLists.txt7
-rw-r--r--src/video_core/clipper.cpp13
-rw-r--r--src/video_core/clipper.h2
-rw-r--r--src/video_core/command_processor.cpp136
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp17
-rw-r--r--src/video_core/debug_utils/debug_utils.h3
-rw-r--r--src/video_core/pica.cpp523
-rw-r--r--src/video_core/pica.h429
-rw-r--r--src/video_core/pica_state.h60
-rw-r--r--src/video_core/pica_types.h146
-rw-r--r--src/video_core/primitive_assembly.cpp21
-rw-r--r--src/video_core/primitive_assembly.h10
-rw-r--r--src/video_core/rasterizer.cpp17
-rw-r--r--src/video_core/rasterizer_interface.h (renamed from src/video_core/hwrasterizer_base.h)19
-rw-r--r--src/video_core/renderer_base.cpp29
-rw-r--r--src/video_core/renderer_base.h24
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp456
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h181
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp225
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.h2
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp17
-rw-r--r--src/video_core/renderer_opengl/gl_state.h5
-rw-r--r--src/video_core/renderer_opengl/pica_to_gl.h12
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp82
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h2
-rw-r--r--src/video_core/shader/shader.cpp9
-rw-r--r--src/video_core/shader/shader.h32
-rw-r--r--src/video_core/shader/shader_interpreter.cpp4
-rw-r--r--src/video_core/shader/shader_jit_x64.cpp16
-rw-r--r--src/video_core/shader/shader_jit_x64.h2
-rw-r--r--src/video_core/swrasterizer.cpp16
-rw-r--r--src/video_core/swrasterizer.h26
-rw-r--r--src/video_core/video_core.cpp23
-rw-r--r--src/video_core/video_core.h7
209 files changed, 6613 insertions, 5914 deletions
diff --git a/.travis-deps.sh b/.travis-deps.sh
index 4b907abb3..bab90d307 100755
--- a/.travis-deps.sh
+++ b/.travis-deps.sh
@@ -13,18 +13,13 @@ if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
| tar -xz -C $HOME/.local --strip-components=1
(
- git clone https://github.com/glfw/glfw.git --branch 3.1.1 --depth 1
- mkdir glfw/build && cd glfw/build
- cmake -DBUILD_SHARED_LIBS=ON \
- -DGLFW_BUILD_EXAMPLES=OFF \
- -DGLFW_BUILD_TESTS=OFF \
- -DCMAKE_INSTALL_PREFIX=$HOME/.local \
- ..
+ wget http://libsdl.org/release/SDL2-2.0.4.tar.gz -O - | tar xz
+ cd SDL2-2.0.4
+ ./configure --prefix=$HOME/.local
make -j4 && make install
)
-
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew update > /dev/null # silence the very verbose output
- brew install qt5 glfw3
+ brew install qt5 sdl2
gem install xcpretty
fi
diff --git a/.travis.yml b/.travis.yml
index 4d21257bc..2e875cccf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,8 +18,6 @@ addons:
- gcc-4.9
- g++-4.9
- xorg-dev
- - libglu1-mesa-dev
- - libxcursor-dev
- lib32stdc++6 # For CMake
- lftp # To upload builds
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b8a981711..d6a4a915a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,8 +35,8 @@ endfunction()
project(citra)
-option(ENABLE_GLFW "Enable the GLFW frontend" ON)
-option(CITRA_USE_BUNDLED_GLFW "Download bundled GLFW binaries" OFF)
+option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
+option(CITRA_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" OFF)
option(ENABLE_QT "Enable the Qt frontend" ON)
option(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" OFF)
@@ -135,34 +135,29 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/cmake-modules")
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
-if (ENABLE_GLFW)
- if (CITRA_USE_BUNDLED_GLFW)
+if (ENABLE_SDL2)
+ if (CITRA_USE_BUNDLED_SDL2)
# Detect toolchain and platform
if (MSVC14 AND ARCHITECTURE_x86_64)
- set(GLFW_VER "glfw-3.1.1-msvc2015_64")
- elseif (MSVC12 AND ARCHITECTURE_x86_64)
- set(GLFW_VER "glfw-3.1.1-msvc2013_64")
+ set(SDL2_VER "SDL2-2.0.4")
else()
- message(FATAL_ERROR "No bundled GLFW binaries for your toolchain. Disable CITRA_USE_BUNDLED_GLFW and provide your own.")
+ message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable CITRA_USE_BUNDLED_SDL2 and provide your own.")
endif()
- if (DEFINED GLFW_VER)
- download_bundled_external("glfw/" ${GLFW_VER} GLFW_PREFIX)
+ if (DEFINED SDL2_VER)
+ download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX)
endif()
- set(GLFW_INCLUDE_DIRS "${GLFW_PREFIX}/include" CACHE PATH "Path to GLFW3 headers")
- set(GLFW_LIBRARY_DIRS "${GLFW_PREFIX}/lib" CACHE PATH "Path to GLFW3 libraries")
- set(GLFW_LIBRARIES glfw3)
+ set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers")
+ set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library")
+ set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll")
else()
- find_package(PkgConfig REQUIRED)
- pkg_search_module(GLFW REQUIRED glfw3)
+ find_package(SDL2 REQUIRED)
endif()
endif()
IF (APPLE)
FIND_LIBRARY(COCOA_LIBRARY Cocoa) # Umbrella framework for everything GUI-related
- FIND_LIBRARY(IOKIT_LIBRARY IOKit) # GLFW dependency
- FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo) # GLFW dependency
set(PLATFORM_LIBRARIES iconv ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 28b8b4031..c2735f564 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,3 +1,11 @@
+# Reporting Issues
+
+**The issue tracker is not a support forum.** Unless you can provide precise *technical information* regarding an issue, you *should not post in it*. If you need support, first read the [FAQ](https://github.com/citra-emu/citra/wiki/FAQ) and then either visit our IRC channel or ask in a general emulation forum such as [/r/emulation](https://www.reddit.com/r/emulation/). If you post support questions, generic messages to the developers or vague reports without technical details, they will be closed and locked.
+
+If you believe you have a valid issue report, please post text or a screenshot from the log (the console window that opens alongside Citra) and build version (hex string visible in the titlebar and zip filename), as well as your hardware and software information if applicable.
+
+While issues about specific games not booting are valid bugs, we are currently not interested in them unless you have several games which fail with the same or similar messages. (In which case please file only a single issue about it.) There are too many non-working games right now to file individual issues for every one of them.
+
# Contributing
Citra is a brand new project, so we have a great opportunity to keep things clean and well organized early on. As such, coding style is very important when making commits. They aren't very strict rules since we want to be flexible and we understand that under certain circumstances some of them can be counterproductive. Just try to follow as many of them as possible:
diff --git a/README.md b/README.md
index 0d9e52396..a27acbc15 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+**BEFORE FILING AN ISSUE, READ THE RELEVANT SECTION IN THE [CONTRIBUTING](https://github.com/citra-emu/citra/blob/master/CONTRIBUTING.md#reporting-issues) FILE!!!**
+
Citra Emulator
==============
[![Travis CI Build Status](https://travis-ci.org/citra-emu/citra.svg)](https://travis-ci.org/citra-emu/citra)
@@ -7,6 +9,8 @@ Citra is an experimental open-source Nintendo 3DS emulator/debugger written in C
Citra is licensed under the GPLv2 (or any later version). Refer to the license.txt file included. Please read the [FAQ](https://github.com/citra-emu/citra/wiki/FAQ) before getting started with the project.
+Check out our [website](https://citra-emu.org/)!
+
For development discussion, please join us @ #citra on freenode.
### Development
@@ -15,9 +19,9 @@ If you want to contribute please take a look at the [Contributor's Guide](CONTRI
### Building
-* __Windows__: [Windows Build](https://github.com/citra-emu/citra/wiki/Windows-Build)
-* __Linux__: [Linux Build](https://github.com/citra-emu/citra/wiki/Linux-Build)
-* __OSX__: [OS X Build](https://github.com/citra-emu/citra/wiki/OS-X-Build)
+* __Windows__: [Windows Build](https://github.com/citra-emu/citra/wiki/Building-For-Windows)
+* __Linux__: [Linux Build](https://github.com/citra-emu/citra/wiki/Building-For-Linux)
+* __OSX__: [OS X Build](https://github.com/citra-emu/citra/wiki/Building-For-OS-X)
### Support
diff --git a/appveyor.yml b/appveyor.yml
index d05cc2213..1edd7041f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,6 +5,8 @@ environment:
BUILD_PASSWORD:
secure: EXGNlWKJsCtbeImEJ5EP9qrxZ+EqUFfNy+CP61nDOMA=
+os: Visual Studio 2015
+
platform:
- x64
@@ -17,7 +19,7 @@ install:
before_build:
- mkdir build
- cd build
- - cmake -G "Visual Studio 14 Win64" -DCITRA_USE_BUNDLED_GLFW=1 -DCITRA_USE_BUNDLED_QT=1 ..
+ - cmake -G "Visual Studio 14 2015 Win64" -DCITRA_USE_BUNDLED_QT=1 -DCITRA_USE_BUNDLED_SDL2=1 ..
- cd ..
after_build:
diff --git a/externals/cmake-modules/FindSDL2.cmake b/externals/cmake-modules/FindSDL2.cmake
new file mode 100644
index 000000000..0af86840a
--- /dev/null
+++ b/externals/cmake-modules/FindSDL2.cmake
@@ -0,0 +1,224 @@
+
+# This module defines
+# SDL2_LIBRARY, the name of the library to link against
+# SDL2_FOUND, if false, do not try to link to SDL2
+# SDL2_INCLUDE_DIR, where to find SDL.h
+#
+# This module responds to the the flag:
+# SDL2_BUILDING_LIBRARY
+# If this is defined, then no SDL2main will be linked in because
+# only applications need main().
+# Otherwise, it is assumed you are building an application and this
+# module will attempt to locate and set the the proper link flags
+# as part of the returned SDL2_LIBRARY variable.
+#
+# Don't forget to include SDLmain.h and SDLmain.m your project for the
+# OS X framework based version. (Other versions link to -lSDL2main which
+# this module will try to find on your behalf.) Also for OS X, this
+# module will automatically add the -framework Cocoa on your behalf.
+#
+#
+# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
+# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
+# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
+# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
+# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
+# as appropriate. These values are used to generate the final SDL2_LIBRARY
+# variable, but when these values are unset, SDL2_LIBRARY does not get created.
+#
+#
+# $SDL2DIR is an environment variable that would
+# correspond to the ./configure --prefix=$SDL2DIR
+# used in building SDL2.
+# l.e.galup 9-20-02
+#
+# Modified by Eric Wing.
+# Added code to assist with automated building by using environmental variables
+# and providing a more controlled/consistent search behavior.
+# Added new modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+# Also corrected the header search path to follow "proper" SDL guidelines.
+# Added a search for SDL2main which is needed by some platforms.
+# Added a search for threads which is needed by some platforms.
+# Added needed compile switches for MinGW.
+#
+# On OSX, this will prefer the Framework version (if found) over others.
+# People will have to manually change the cache values of
+# SDL2_LIBRARY to override this selection or set the CMake environment
+# CMAKE_INCLUDE_PATH to modify the search paths.
+#
+# Note that the header path has changed from SDL2/SDL.h to just SDL.h
+# This needed to change because "proper" SDL convention
+# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
+# reasons because not all systems place things in SDL2/ (see FreeBSD).
+
+#=============================================================================
+# Copyright 2003-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License").
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# CMake - Cross Platform Makefile Generator
+# Copyright 2000-2016 Kitware, Inc.
+# Copyright 2000-2011 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * 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.
+#
+# * Neither the names of Kitware, Inc., the Insight Software Consortium,
+# nor the names of their 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.
+#
+# ------------------------------------------------------------------------------
+#
+# The above copyright and license notice applies to distributions of
+# CMake in source and binary form. Some source files contain additional
+# notices of original copyright by their contributors; see each source
+# for details. Third-party software packages supplied with CMake under
+# compatible licenses provide their own copyright notices documented in
+# corresponding subdirectories.
+#
+# ------------------------------------------------------------------------------
+#
+# CMake was initially developed by Kitware with the following sponsorship:
+#
+# * National Library of Medicine at the National Institutes of Health
+# as part of the Insight Segmentation and Registration Toolkit (ITK).
+#
+# * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
+# Visualization Initiative.
+#
+# * National Alliance for Medical Image Computing (NAMIC) is funded by the
+# National Institutes of Health through the NIH Roadmap for Medical Research,
+# Grant U54 EB005149.
+#
+# * Kitware, Inc.
+#
+
+message("<FindSDL2.cmake>")
+
+SET(SDL2_SEARCH_PATHS
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local
+ /usr
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt
+ ${SDL2_PATH}
+)
+
+FIND_LIBRARY(SDL2_LIBRARY_TEMP
+ NAMES SDL2
+ HINTS
+ $ENV{SDL2DIR}
+ PATH_SUFFIXES lib64 lib
+ PATHS ${SDL2_SEARCH_PATHS}
+)
+
+IF(SDL2_LIBRARY_TEMP)
+ FIND_PATH(SDL2_INCLUDE_DIR SDL.h
+ HINTS
+ $ENV{SDL2DIR}
+ PATH_SUFFIXES include/SDL2 include
+ PATHS ${SDL2_SEARCH_PATHS}
+ )
+
+ IF(NOT SDL2_BUILDING_LIBRARY)
+ IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
+ # Non-OS X framework versions expect you to also dynamically link to
+ # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
+ # seem to provide SDL2main for compatibility even though they don't
+ # necessarily need it.
+ FIND_LIBRARY(SDL2MAIN_LIBRARY
+ NAMES SDL2main
+ HINTS
+ $ENV{SDL2DIR}
+ PATH_SUFFIXES lib64 lib
+ PATHS ${SDL2_SEARCH_PATHS}
+ )
+ ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
+ ENDIF(NOT SDL2_BUILDING_LIBRARY)
+
+ # SDL2 may require threads on your system.
+ # The Apple build may not need an explicit flag because one of the
+ # frameworks may already provide it.
+ # But for non-OSX systems, I will use the CMake Threads package.
+ IF(NOT APPLE)
+ FIND_PACKAGE(Threads)
+ ENDIF(NOT APPLE)
+
+ # MinGW needs an additional library, mwindows
+ # It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
+ # (Actually on second look, I think it only needs one of the m* libraries.)
+ IF(MINGW)
+ SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
+ ENDIF(MINGW)
+
+ # For SDL2main
+ IF(NOT SDL2_BUILDING_LIBRARY)
+ IF(SDL2MAIN_LIBRARY)
+ SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
+ ENDIF(SDL2MAIN_LIBRARY)
+ ENDIF(NOT SDL2_BUILDING_LIBRARY)
+
+ # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
+ # CMake doesn't display the -framework Cocoa string in the UI even
+ # though it actually is there if I modify a pre-used variable.
+ # I think it has something to do with the CACHE STRING.
+ # So I use a temporary variable until the end so I can set the
+ # "real" variable in one-shot.
+ IF(APPLE)
+ SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
+ ENDIF(APPLE)
+
+ # For threads, as mentioned Apple doesn't need this.
+ # In fact, there seems to be a problem if I used the Threads package
+ # and try using this line, so I'm just skipping it entirely for OS X.
+ IF(NOT APPLE)
+ SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
+ ENDIF(NOT APPLE)
+
+ # For MinGW library
+ IF(MINGW)
+ SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
+ ENDIF(MINGW)
+
+ # Set the final string here so the GUI reflects the final state.
+ SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
+
+ # Unset the temp variable to INTERNAL so it is not seen in the CMake GUI
+ UNSET(SDL2_LIBRARY_TEMP)
+ENDIF(SDL2_LIBRARY_TEMP)
+
+message("</FindSDL2.cmake>")
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
diff --git a/externals/cmake-modules/WindowsCopyFiles.cmake b/externals/cmake-modules/WindowsCopyFiles.cmake
new file mode 100644
index 000000000..cd0c2ce47
--- /dev/null
+++ b/externals/cmake-modules/WindowsCopyFiles.cmake
@@ -0,0 +1,28 @@
+# Copyright 2016 Citra Emulator Project
+# Licensed under GPLv2 or any later version
+# Refer to the license.txt file included.
+
+# This file provides the function windows_copy_files.
+# This is only valid on Windows.
+
+# Include guard
+if(__windows_copy_files)
+ return()
+endif()
+set(__windows_copy_files YES)
+
+# Any number of files to copy from SOURCE_DIR to DEST_DIR can be specified after DEST_DIR.
+# This copying happens post-build.
+function(windows_copy_files TARGET SOURCE_DIR DEST_DIR)
+ # windows commandline expects the / to be \ so switch them
+ string(REPLACE "/" "\\\\" SOURCE_DIR ${SOURCE_DIR})
+ string(REPLACE "/" "\\\\" DEST_DIR ${DEST_DIR})
+
+ # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output
+ # cmake adds an extra check for command success which doesn't work too well with robocopy
+ # so trick it into thinking the command was successful with the || cmd /c "exit /b 0"
+ add_custom_command(TARGET ${TARGET} POST_BUILD
+ COMMAND if not exist ${DEST_DIR} mkdir ${DEST_DIR} 2> nul
+ COMMAND robocopy ${SOURCE_DIR} ${DEST_DIR} ${ARGN} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0"
+ )
+endfunction() \ No newline at end of file
diff --git a/externals/glad/include/glad/glad.h b/externals/glad/include/glad/glad.h
index 678a5287a..6bd025683 100644
--- a/externals/glad/include/glad/glad.h
+++ b/externals/glad/include/glad/glad.h
@@ -1024,73 +1024,73 @@ typedef GLintptr GLvdpauSurfaceNV;
#ifndef GL_VERSION_1_0
#define GL_VERSION_1_0 1
GLAPI int GLAD_GL_VERSION_1_0;
-typedef void (APIENTRYP PFNGLCULLFACEPROC)(GLenum);
+typedef void (APIENTRYP PFNGLCULLFACEPROC)(GLenum mode);
GLAPI PFNGLCULLFACEPROC glad_glCullFace;
#define glCullFace glad_glCullFace
-typedef void (APIENTRYP PFNGLFRONTFACEPROC)(GLenum);
+typedef void (APIENTRYP PFNGLFRONTFACEPROC)(GLenum mode);
GLAPI PFNGLFRONTFACEPROC glad_glFrontFace;
#define glFrontFace glad_glFrontFace
-typedef void (APIENTRYP PFNGLHINTPROC)(GLenum, GLenum);
+typedef void (APIENTRYP PFNGLHINTPROC)(GLenum target, GLenum mode);
GLAPI PFNGLHINTPROC glad_glHint;
#define glHint glad_glHint
-typedef void (APIENTRYP PFNGLLINEWIDTHPROC)(GLfloat);
+typedef void (APIENTRYP PFNGLLINEWIDTHPROC)(GLfloat width);
GLAPI PFNGLLINEWIDTHPROC glad_glLineWidth;
#define glLineWidth glad_glLineWidth
-typedef void (APIENTRYP PFNGLPOINTSIZEPROC)(GLfloat);
+typedef void (APIENTRYP PFNGLPOINTSIZEPROC)(GLfloat size);
GLAPI PFNGLPOINTSIZEPROC glad_glPointSize;
#define glPointSize glad_glPointSize
-typedef void (APIENTRYP PFNGLPOLYGONMODEPROC)(GLenum, GLenum);
+typedef void (APIENTRYP PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
GLAPI PFNGLPOLYGONMODEPROC glad_glPolygonMode;
#define glPolygonMode glad_glPolygonMode
-typedef void (APIENTRYP PFNGLSCISSORPROC)(GLint, GLint, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
GLAPI PFNGLSCISSORPROC glad_glScissor;
#define glScissor glad_glScissor
-typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC)(GLenum, GLenum, GLfloat);
+typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
GLAPI PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
#define glTexParameterf glad_glTexParameterf
-typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC)(GLenum, GLenum, const GLfloat*);
+typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat* params);
GLAPI PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
#define glTexParameterfv glad_glTexParameterfv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC)(GLenum, GLenum, GLint);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
GLAPI PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
#define glTexParameteri glad_glTexParameteri
-typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC)(GLenum, GLenum, const GLint*);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint* params);
GLAPI PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
#define glTexParameteriv glad_glTexParameteriv
-typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const void*);
+typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
GLAPI PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
#define glTexImage1D glad_glTexImage1D
-typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void*);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
GLAPI PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
#define glTexImage2D glad_glTexImage2D
-typedef void (APIENTRYP PFNGLDRAWBUFFERPROC)(GLenum);
+typedef void (APIENTRYP PFNGLDRAWBUFFERPROC)(GLenum buf);
GLAPI PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
#define glDrawBuffer glad_glDrawBuffer
-typedef void (APIENTRYP PFNGLCLEARPROC)(GLbitfield);
+typedef void (APIENTRYP PFNGLCLEARPROC)(GLbitfield mask);
GLAPI PFNGLCLEARPROC glad_glClear;
#define glClear glad_glClear
-typedef void (APIENTRYP PFNGLCLEARCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
GLAPI PFNGLCLEARCOLORPROC glad_glClearColor;
#define glClearColor glad_glClearColor
-typedef void (APIENTRYP PFNGLCLEARSTENCILPROC)(GLint);
+typedef void (APIENTRYP PFNGLCLEARSTENCILPROC)(GLint s);
GLAPI PFNGLCLEARSTENCILPROC glad_glClearStencil;
#define glClearStencil glad_glClearStencil
-typedef void (APIENTRYP PFNGLCLEARDEPTHPROC)(GLdouble);
+typedef void (APIENTRYP PFNGLCLEARDEPTHPROC)(GLdouble depth);
GLAPI PFNGLCLEARDEPTHPROC glad_glClearDepth;
#define glClearDepth glad_glClearDepth
-typedef void (APIENTRYP PFNGLSTENCILMASKPROC)(GLuint);
+typedef void (APIENTRYP PFNGLSTENCILMASKPROC)(GLuint mask);
GLAPI PFNGLSTENCILMASKPROC glad_glStencilMask;
#define glStencilMask glad_glStencilMask
-typedef void (APIENTRYP PFNGLCOLORMASKPROC)(GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (APIENTRYP PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
GLAPI PFNGLCOLORMASKPROC glad_glColorMask;
#define glColorMask glad_glColorMask
-typedef void (APIENTRYP PFNGLDEPTHMASKPROC)(GLboolean);
+typedef void (APIENTRYP PFNGLDEPTHMASKPROC)(GLboolean flag);
GLAPI PFNGLDEPTHMASKPROC glad_glDepthMask;
#define glDepthMask glad_glDepthMask
-typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum);
+typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap);
GLAPI PFNGLDISABLEPROC glad_glDisable;
#define glDisable glad_glDisable
-typedef void (APIENTRYP PFNGLENABLEPROC)(GLenum);
+typedef void (APIENTRYP PFNGLENABLEPROC)(GLenum cap);
GLAPI PFNGLENABLEPROC glad_glEnable;
#define glEnable glad_glEnable
typedef void (APIENTRYP PFNGLFINISHPROC)();
@@ -1099,1130 +1099,1130 @@ GLAPI PFNGLFINISHPROC glad_glFinish;
typedef void (APIENTRYP PFNGLFLUSHPROC)();
GLAPI PFNGLFLUSHPROC glad_glFlush;
#define glFlush glad_glFlush
-typedef void (APIENTRYP PFNGLBLENDFUNCPROC)(GLenum, GLenum);
+typedef void (APIENTRYP PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
GLAPI PFNGLBLENDFUNCPROC glad_glBlendFunc;
#define glBlendFunc glad_glBlendFunc
-typedef void (APIENTRYP PFNGLLOGICOPPROC)(GLenum);
+typedef void (APIENTRYP PFNGLLOGICOPPROC)(GLenum opcode);
GLAPI PFNGLLOGICOPPROC glad_glLogicOp;
#define glLogicOp glad_glLogicOp
-typedef void (APIENTRYP PFNGLSTENCILFUNCPROC)(GLenum, GLint, GLuint);
+typedef void (APIENTRYP PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
GLAPI PFNGLSTENCILFUNCPROC glad_glStencilFunc;
#define glStencilFunc glad_glStencilFunc
-typedef void (APIENTRYP PFNGLSTENCILOPPROC)(GLenum, GLenum, GLenum);
+typedef void (APIENTRYP PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
GLAPI PFNGLSTENCILOPPROC glad_glStencilOp;
#define glStencilOp glad_glStencilOp
-typedef void (APIENTRYP PFNGLDEPTHFUNCPROC)(GLenum);
+typedef void (APIENTRYP PFNGLDEPTHFUNCPROC)(GLenum func);
GLAPI PFNGLDEPTHFUNCPROC glad_glDepthFunc;
#define glDepthFunc glad_glDepthFunc
-typedef void (APIENTRYP PFNGLPIXELSTOREFPROC)(GLenum, GLfloat);
+typedef void (APIENTRYP PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
GLAPI PFNGLPIXELSTOREFPROC glad_glPixelStoref;
#define glPixelStoref glad_glPixelStoref
-typedef void (APIENTRYP PFNGLPIXELSTOREIPROC)(GLenum, GLint);
+typedef void (APIENTRYP PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
GLAPI PFNGLPIXELSTOREIPROC glad_glPixelStorei;
#define glPixelStorei glad_glPixelStorei
-typedef void (APIENTRYP PFNGLREADBUFFERPROC)(GLenum);
+typedef void (APIENTRYP PFNGLREADBUFFERPROC)(GLenum src);
GLAPI PFNGLREADBUFFERPROC glad_glReadBuffer;
#define glReadBuffer glad_glReadBuffer
-typedef void (APIENTRYP PFNGLREADPIXELSPROC)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, void*);
+typedef void (APIENTRYP PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
GLAPI PFNGLREADPIXELSPROC glad_glReadPixels;
#define glReadPixels glad_glReadPixels
-typedef void (APIENTRYP PFNGLGETBOOLEANVPROC)(GLenum, GLboolean*);
+typedef void (APIENTRYP PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean* data);
GLAPI PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
#define glGetBooleanv glad_glGetBooleanv
-typedef void (APIENTRYP PFNGLGETDOUBLEVPROC)(GLenum, GLdouble*);
+typedef void (APIENTRYP PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble* data);
GLAPI PFNGLGETDOUBLEVPROC glad_glGetDoublev;
#define glGetDoublev glad_glGetDoublev
typedef GLenum (APIENTRYP PFNGLGETERRORPROC)();
GLAPI PFNGLGETERRORPROC glad_glGetError;
#define glGetError glad_glGetError
-typedef void (APIENTRYP PFNGLGETFLOATVPROC)(GLenum, GLfloat*);
+typedef void (APIENTRYP PFNGLGETFLOATVPROC)(GLenum pname, GLfloat* data);
GLAPI PFNGLGETFLOATVPROC glad_glGetFloatv;
#define glGetFloatv glad_glGetFloatv
-typedef void (APIENTRYP PFNGLGETINTEGERVPROC)(GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETINTEGERVPROC)(GLenum pname, GLint* data);
GLAPI PFNGLGETINTEGERVPROC glad_glGetIntegerv;
#define glGetIntegerv glad_glGetIntegerv
-typedef const GLubyte* (APIENTRYP PFNGLGETSTRINGPROC)(GLenum);
+typedef const GLubyte* (APIENTRYP PFNGLGETSTRINGPROC)(GLenum name);
GLAPI PFNGLGETSTRINGPROC glad_glGetString;
#define glGetString glad_glGetString
-typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC)(GLenum, GLint, GLenum, GLenum, void*);
+typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
GLAPI PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
#define glGetTexImage glad_glGetTexImage
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC)(GLenum, GLenum, GLfloat*);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat* params);
GLAPI PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
#define glGetTexParameterfv glad_glGetTexParameterfv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC)(GLenum, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint* params);
GLAPI PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
#define glGetTexParameteriv glad_glGetTexParameteriv
-typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum, GLint, GLenum, GLfloat*);
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat* params);
GLAPI PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
-typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum, GLint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint* params);
GLAPI PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
-typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC)(GLenum);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC)(GLenum cap);
GLAPI PFNGLISENABLEDPROC glad_glIsEnabled;
#define glIsEnabled glad_glIsEnabled
-typedef void (APIENTRYP PFNGLDEPTHRANGEPROC)(GLdouble, GLdouble);
+typedef void (APIENTRYP PFNGLDEPTHRANGEPROC)(GLdouble near, GLdouble far);
GLAPI PFNGLDEPTHRANGEPROC glad_glDepthRange;
#define glDepthRange glad_glDepthRange
-typedef void (APIENTRYP PFNGLVIEWPORTPROC)(GLint, GLint, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
GLAPI PFNGLVIEWPORTPROC glad_glViewport;
#define glViewport glad_glViewport
#endif
#ifndef GL_VERSION_1_1
#define GL_VERSION_1_1 1
GLAPI int GLAD_GL_VERSION_1_1;
-typedef void (APIENTRYP PFNGLDRAWARRAYSPROC)(GLenum, GLint, GLsizei);
+typedef void (APIENTRYP PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
GLAPI PFNGLDRAWARRAYSPROC glad_glDrawArrays;
#define glDrawArrays glad_glDrawArrays
-typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC)(GLenum, GLsizei, GLenum, const void*);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void* indices);
GLAPI PFNGLDRAWELEMENTSPROC glad_glDrawElements;
#define glDrawElements glad_glDrawElements
-typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC)(GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
GLAPI PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
#define glPolygonOffset glad_glPolygonOffset
-typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
GLAPI PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
#define glCopyTexImage1D glad_glCopyTexImage1D
-typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
GLAPI PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
#define glCopyTexImage2D glad_glCopyTexImage2D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
GLAPI PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
GLAPI PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const void*);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
GLAPI PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
#define glTexSubImage1D glad_glTexSubImage1D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void*);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
GLAPI PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
#define glTexSubImage2D glad_glTexSubImage2D
-typedef void (APIENTRYP PFNGLBINDTEXTUREPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
GLAPI PFNGLBINDTEXTUREPROC glad_glBindTexture;
#define glBindTexture glad_glBindTexture
-typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint* textures);
GLAPI PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
#define glDeleteTextures glad_glDeleteTextures
-typedef void (APIENTRYP PFNGLGENTEXTURESPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENTEXTURESPROC)(GLsizei n, GLuint* textures);
GLAPI PFNGLGENTEXTURESPROC glad_glGenTextures;
#define glGenTextures glad_glGenTextures
-typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC)(GLuint texture);
GLAPI PFNGLISTEXTUREPROC glad_glIsTexture;
#define glIsTexture glad_glIsTexture
#endif
#ifndef GL_VERSION_1_2
#define GL_VERSION_1_2 1
GLAPI int GLAD_GL_VERSION_1_2;
-typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void*);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices);
GLAPI PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
#define glDrawRangeElements glad_glDrawRangeElements
-typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void*);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
GLAPI PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
#define glTexImage3D glad_glTexImage3D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void*);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
GLAPI PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
#define glTexSubImage3D glad_glTexSubImage3D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
GLAPI PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
#endif
#ifndef GL_VERSION_1_3
#define GL_VERSION_1_3 1
GLAPI int GLAD_GL_VERSION_1_3;
-typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum);
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture);
GLAPI PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
#define glActiveTexture glad_glActiveTexture
-typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC)(GLfloat, GLboolean);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
GLAPI PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
#define glSampleCoverage glad_glSampleCoverage
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
GLAPI PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
#define glCompressedTexImage3D glad_glCompressedTexImage3D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
GLAPI PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
#define glCompressedTexImage2D glad_glCompressedTexImage2D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
GLAPI PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
#define glCompressedTexImage1D glad_glCompressedTexImage1D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
-typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum, GLint, void*);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void* img);
GLAPI PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
#define glGetCompressedTexImage glad_glGetCompressedTexImage
#endif
#ifndef GL_VERSION_1_4
#define GL_VERSION_1_4 1
GLAPI int GLAD_GL_VERSION_1_4;
-typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
GLAPI PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
#define glBlendFuncSeparate glad_glBlendFuncSeparate
-typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC)(GLenum, const GLint*, const GLsizei*, GLsizei);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint* first, const GLsizei* count, GLsizei drawcount);
GLAPI PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
#define glMultiDrawArrays glad_glMultiDrawArrays
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC)(GLenum, const GLsizei*, GLenum, const void**, GLsizei);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei* count, GLenum type, const void** indices, GLsizei drawcount);
GLAPI PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
#define glMultiDrawElements glad_glMultiDrawElements
-typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC)(GLenum, GLfloat);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
GLAPI PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
#define glPointParameterf glad_glPointParameterf
-typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC)(GLenum, const GLfloat*);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat* params);
GLAPI PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
#define glPointParameterfv glad_glPointParameterfv
-typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC)(GLenum, GLint);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
GLAPI PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
#define glPointParameteri glad_glPointParameteri
-typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC)(GLenum, const GLint*);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint* params);
GLAPI PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
#define glPointParameteriv glad_glPointParameteriv
-typedef void (APIENTRYP PFNGLBLENDCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
GLAPI PFNGLBLENDCOLORPROC glad_glBlendColor;
#define glBlendColor glad_glBlendColor
-typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC)(GLenum);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC)(GLenum mode);
GLAPI PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
#define glBlendEquation glad_glBlendEquation
#endif
#ifndef GL_VERSION_1_5
#define GL_VERSION_1_5 1
GLAPI int GLAD_GL_VERSION_1_5;
-typedef void (APIENTRYP PFNGLGENQUERIESPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENQUERIESPROC)(GLsizei n, GLuint* ids);
GLAPI PFNGLGENQUERIESPROC glad_glGenQueries;
#define glGenQueries glad_glGenQueries
-typedef void (APIENTRYP PFNGLDELETEQUERIESPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint* ids);
GLAPI PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
#define glDeleteQueries glad_glDeleteQueries
-typedef GLboolean (APIENTRYP PFNGLISQUERYPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC)(GLuint id);
GLAPI PFNGLISQUERYPROC glad_glIsQuery;
#define glIsQuery glad_glIsQuery
-typedef void (APIENTRYP PFNGLBEGINQUERYPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
GLAPI PFNGLBEGINQUERYPROC glad_glBeginQuery;
#define glBeginQuery glad_glBeginQuery
-typedef void (APIENTRYP PFNGLENDQUERYPROC)(GLenum);
+typedef void (APIENTRYP PFNGLENDQUERYPROC)(GLenum target);
GLAPI PFNGLENDQUERYPROC glad_glEndQuery;
#define glEndQuery glad_glEndQuery
-typedef void (APIENTRYP PFNGLGETQUERYIVPROC)(GLenum, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint* params);
GLAPI PFNGLGETQUERYIVPROC glad_glGetQueryiv;
#define glGetQueryiv glad_glGetQueryiv
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC)(GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint* params);
GLAPI PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
#define glGetQueryObjectiv glad_glGetQueryObjectiv
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC)(GLuint, GLenum, GLuint*);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint* params);
GLAPI PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
-typedef void (APIENTRYP PFNGLBINDBUFFERPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
GLAPI PFNGLBINDBUFFERPROC glad_glBindBuffer;
#define glBindBuffer glad_glBindBuffer
-typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint* buffers);
GLAPI PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
#define glDeleteBuffers glad_glDeleteBuffers
-typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei n, GLuint* buffers);
GLAPI PFNGLGENBUFFERSPROC glad_glGenBuffers;
#define glGenBuffers glad_glGenBuffers
-typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC)(GLuint buffer);
GLAPI PFNGLISBUFFERPROC glad_glIsBuffer;
#define glIsBuffer glad_glIsBuffer
-typedef void (APIENTRYP PFNGLBUFFERDATAPROC)(GLenum, GLsizeiptr, const void*, GLenum);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
GLAPI PFNGLBUFFERDATAPROC glad_glBufferData;
#define glBufferData glad_glBufferData
-typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, const void*);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
GLAPI PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
#define glBufferSubData glad_glBufferSubData
-typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, void*);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void* data);
GLAPI PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
#define glGetBufferSubData glad_glGetBufferSubData
-typedef void* (APIENTRYP PFNGLMAPBUFFERPROC)(GLenum, GLenum);
+typedef void* (APIENTRYP PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
GLAPI PFNGLMAPBUFFERPROC glad_glMapBuffer;
#define glMapBuffer glad_glMapBuffer
-typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC)(GLenum);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC)(GLenum target);
GLAPI PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
#define glUnmapBuffer glad_glUnmapBuffer
-typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint* params);
GLAPI PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
#define glGetBufferParameteriv glad_glGetBufferParameteriv
-typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum, GLenum, void**);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void** params);
GLAPI PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
#define glGetBufferPointerv glad_glGetBufferPointerv
#endif
#ifndef GL_VERSION_2_0
#define GL_VERSION_2_0 1
GLAPI int GLAD_GL_VERSION_2_0;
-typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum, GLenum);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
GLAPI PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
#define glBlendEquationSeparate glad_glBlendEquationSeparate
-typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC)(GLsizei, const GLenum*);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum* bufs);
GLAPI PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
#define glDrawBuffers glad_glDrawBuffers
-typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
GLAPI PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
#define glStencilOpSeparate glad_glStencilOpSeparate
-typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC)(GLenum, GLenum, GLint, GLuint);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
GLAPI PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
#define glStencilFuncSeparate glad_glStencilFuncSeparate
-typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
GLAPI PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
#define glStencilMaskSeparate glad_glStencilMaskSeparate
-typedef void (APIENTRYP PFNGLATTACHSHADERPROC)(GLuint, GLuint);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
GLAPI PFNGLATTACHSHADERPROC glad_glAttachShader;
#define glAttachShader glad_glAttachShader
-typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC)(GLuint, GLuint, const GLchar*);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar* name);
GLAPI PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
#define glBindAttribLocation glad_glBindAttribLocation
-typedef void (APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader);
GLAPI PFNGLCOMPILESHADERPROC glad_glCompileShader;
#define glCompileShader glad_glCompileShader
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC)();
GLAPI PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
#define glCreateProgram glad_glCreateProgram
-typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC)(GLenum);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC)(GLenum type);
GLAPI PFNGLCREATESHADERPROC glad_glCreateShader;
#define glCreateShader glad_glCreateShader
-typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program);
GLAPI PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
#define glDeleteProgram glad_glDeleteProgram
-typedef void (APIENTRYP PFNGLDELETESHADERPROC)(GLuint);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader);
GLAPI PFNGLDELETESHADERPROC glad_glDeleteShader;
#define glDeleteShader glad_glDeleteShader
-typedef void (APIENTRYP PFNGLDETACHSHADERPROC)(GLuint, GLuint);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
GLAPI PFNGLDETACHSHADERPROC glad_glDetachShader;
#define glDetachShader glad_glDetachShader
-typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
GLAPI PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
-typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
GLAPI PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
-typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC)(GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
GLAPI PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
#define glGetActiveAttrib glad_glGetActiveAttrib
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC)(GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
GLAPI PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
#define glGetActiveUniform glad_glGetActiveUniform
-typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC)(GLuint, GLsizei, GLsizei*, GLuint*);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders);
GLAPI PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
#define glGetAttachedShaders glad_glGetAttachedShaders
-typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint, const GLchar*);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar* name);
GLAPI PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
#define glGetAttribLocation glad_glGetAttribLocation
-typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint* params);
GLAPI PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
#define glGetProgramiv glad_glGetProgramiv
-typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint, GLsizei, GLsizei*, GLchar*);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
GLAPI PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
#define glGetProgramInfoLog glad_glGetProgramInfoLog
-typedef void (APIENTRYP PFNGLGETSHADERIVPROC)(GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint* params);
GLAPI PFNGLGETSHADERIVPROC glad_glGetShaderiv;
#define glGetShaderiv glad_glGetShaderiv
-typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint, GLsizei, GLsizei*, GLchar*);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
GLAPI PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
#define glGetShaderInfoLog glad_glGetShaderInfoLog
-typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC)(GLuint, GLsizei, GLsizei*, GLchar*);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* source);
GLAPI PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
#define glGetShaderSource glad_glGetShaderSource
-typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint, const GLchar*);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar* name);
GLAPI PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
#define glGetUniformLocation glad_glGetUniformLocation
-typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC)(GLuint, GLint, GLfloat*);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat* params);
GLAPI PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
#define glGetUniformfv glad_glGetUniformfv
-typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC)(GLuint, GLint, GLint*);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint* params);
GLAPI PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
#define glGetUniformiv glad_glGetUniformiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC)(GLuint, GLenum, GLdouble*);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble* params);
GLAPI PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
#define glGetVertexAttribdv glad_glGetVertexAttribdv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC)(GLuint, GLenum, GLfloat*);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat* params);
GLAPI PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
#define glGetVertexAttribfv glad_glGetVertexAttribfv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC)(GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint* params);
GLAPI PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
#define glGetVertexAttribiv glad_glGetVertexAttribiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint, GLenum, void**);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void** pointer);
GLAPI PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
-typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC)(GLuint program);
GLAPI PFNGLISPROGRAMPROC glad_glIsProgram;
#define glIsProgram glad_glIsProgram
-typedef GLboolean (APIENTRYP PFNGLISSHADERPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC)(GLuint shader);
GLAPI PFNGLISSHADERPROC glad_glIsShader;
#define glIsShader glad_glIsShader
-typedef void (APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program);
GLAPI PFNGLLINKPROGRAMPROC glad_glLinkProgram;
#define glLinkProgram glad_glLinkProgram
-typedef void (APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint, GLsizei, const GLchar**, const GLint*);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
GLAPI PFNGLSHADERSOURCEPROC glad_glShaderSource;
#define glShaderSource glad_glShaderSource
-typedef void (APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program);
GLAPI PFNGLUSEPROGRAMPROC glad_glUseProgram;
#define glUseProgram glad_glUseProgram
-typedef void (APIENTRYP PFNGLUNIFORM1FPROC)(GLint, GLfloat);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
GLAPI PFNGLUNIFORM1FPROC glad_glUniform1f;
#define glUniform1f glad_glUniform1f
-typedef void (APIENTRYP PFNGLUNIFORM2FPROC)(GLint, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
GLAPI PFNGLUNIFORM2FPROC glad_glUniform2f;
#define glUniform2f glad_glUniform2f
-typedef void (APIENTRYP PFNGLUNIFORM3FPROC)(GLint, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
GLAPI PFNGLUNIFORM3FPROC glad_glUniform3f;
#define glUniform3f glad_glUniform3f
-typedef void (APIENTRYP PFNGLUNIFORM4FPROC)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
GLAPI PFNGLUNIFORM4FPROC glad_glUniform4f;
#define glUniform4f glad_glUniform4f
-typedef void (APIENTRYP PFNGLUNIFORM1IPROC)(GLint, GLint);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
GLAPI PFNGLUNIFORM1IPROC glad_glUniform1i;
#define glUniform1i glad_glUniform1i
-typedef void (APIENTRYP PFNGLUNIFORM2IPROC)(GLint, GLint, GLint);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
GLAPI PFNGLUNIFORM2IPROC glad_glUniform2i;
#define glUniform2i glad_glUniform2i
-typedef void (APIENTRYP PFNGLUNIFORM3IPROC)(GLint, GLint, GLint, GLint);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
GLAPI PFNGLUNIFORM3IPROC glad_glUniform3i;
#define glUniform3i glad_glUniform3i
-typedef void (APIENTRYP PFNGLUNIFORM4IPROC)(GLint, GLint, GLint, GLint, GLint);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
GLAPI PFNGLUNIFORM4IPROC glad_glUniform4i;
#define glUniform4i glad_glUniform4i
-typedef void (APIENTRYP PFNGLUNIFORM1FVPROC)(GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat* value);
GLAPI PFNGLUNIFORM1FVPROC glad_glUniform1fv;
#define glUniform1fv glad_glUniform1fv
-typedef void (APIENTRYP PFNGLUNIFORM2FVPROC)(GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat* value);
GLAPI PFNGLUNIFORM2FVPROC glad_glUniform2fv;
#define glUniform2fv glad_glUniform2fv
-typedef void (APIENTRYP PFNGLUNIFORM3FVPROC)(GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat* value);
GLAPI PFNGLUNIFORM3FVPROC glad_glUniform3fv;
#define glUniform3fv glad_glUniform3fv
-typedef void (APIENTRYP PFNGLUNIFORM4FVPROC)(GLint, GLsizei, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat* value);
GLAPI PFNGLUNIFORM4FVPROC glad_glUniform4fv;
#define glUniform4fv glad_glUniform4fv
-typedef void (APIENTRYP PFNGLUNIFORM1IVPROC)(GLint, GLsizei, const GLint*);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint* value);
GLAPI PFNGLUNIFORM1IVPROC glad_glUniform1iv;
#define glUniform1iv glad_glUniform1iv
-typedef void (APIENTRYP PFNGLUNIFORM2IVPROC)(GLint, GLsizei, const GLint*);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint* value);
GLAPI PFNGLUNIFORM2IVPROC glad_glUniform2iv;
#define glUniform2iv glad_glUniform2iv
-typedef void (APIENTRYP PFNGLUNIFORM3IVPROC)(GLint, GLsizei, const GLint*);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint* value);
GLAPI PFNGLUNIFORM3IVPROC glad_glUniform3iv;
#define glUniform3iv glad_glUniform3iv
-typedef void (APIENTRYP PFNGLUNIFORM4IVPROC)(GLint, GLsizei, const GLint*);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint* value);
GLAPI PFNGLUNIFORM4IVPROC glad_glUniform4iv;
#define glUniform4iv glad_glUniform4iv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
#define glUniformMatrix2fv glad_glUniformMatrix2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
#define glUniformMatrix3fv glad_glUniformMatrix3fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
#define glUniformMatrix4fv glad_glUniformMatrix4fv
-typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC)(GLuint);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC)(GLuint program);
GLAPI PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
#define glValidateProgram glad_glValidateProgram
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC)(GLuint, GLdouble);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
GLAPI PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
#define glVertexAttrib1d glad_glVertexAttrib1d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC)(GLuint, const GLdouble*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble* v);
GLAPI PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
#define glVertexAttrib1dv glad_glVertexAttrib1dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC)(GLuint, GLfloat);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
GLAPI PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
#define glVertexAttrib1f glad_glVertexAttrib1f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC)(GLuint, const GLfloat*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat* v);
GLAPI PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
#define glVertexAttrib1fv glad_glVertexAttrib1fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC)(GLuint, GLshort);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
GLAPI PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
#define glVertexAttrib1s glad_glVertexAttrib1s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC)(GLuint, const GLshort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort* v);
GLAPI PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
#define glVertexAttrib1sv glad_glVertexAttrib1sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC)(GLuint, GLdouble, GLdouble);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
GLAPI PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
#define glVertexAttrib2d glad_glVertexAttrib2d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC)(GLuint, const GLdouble*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble* v);
GLAPI PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
#define glVertexAttrib2dv glad_glVertexAttrib2dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC)(GLuint, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
GLAPI PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
#define glVertexAttrib2f glad_glVertexAttrib2f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC)(GLuint, const GLfloat*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat* v);
GLAPI PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
#define glVertexAttrib2fv glad_glVertexAttrib2fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC)(GLuint, GLshort, GLshort);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
GLAPI PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
#define glVertexAttrib2s glad_glVertexAttrib2s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC)(GLuint, const GLshort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort* v);
GLAPI PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
#define glVertexAttrib2sv glad_glVertexAttrib2sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC)(GLuint, GLdouble, GLdouble, GLdouble);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
GLAPI PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
#define glVertexAttrib3d glad_glVertexAttrib3d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC)(GLuint, const GLdouble*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble* v);
GLAPI PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
#define glVertexAttrib3dv glad_glVertexAttrib3dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC)(GLuint, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
GLAPI PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
#define glVertexAttrib3f glad_glVertexAttrib3f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC)(GLuint, const GLfloat*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat* v);
GLAPI PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
#define glVertexAttrib3fv glad_glVertexAttrib3fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC)(GLuint, GLshort, GLshort, GLshort);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
GLAPI PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
#define glVertexAttrib3s glad_glVertexAttrib3s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC)(GLuint, const GLshort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort* v);
GLAPI PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
#define glVertexAttrib3sv glad_glVertexAttrib3sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC)(GLuint, const GLbyte*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte* v);
GLAPI PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC)(GLuint, const GLint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint* v);
GLAPI PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC)(GLuint, const GLshort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort* v);
GLAPI PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
GLAPI PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC)(GLuint, const GLubyte*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte* v);
GLAPI PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC)(GLuint, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint* v);
GLAPI PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC)(GLuint, const GLushort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort* v);
GLAPI PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC)(GLuint, const GLbyte*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte* v);
GLAPI PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
#define glVertexAttrib4bv glad_glVertexAttrib4bv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
GLAPI PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
#define glVertexAttrib4d glad_glVertexAttrib4d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC)(GLuint, const GLdouble*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble* v);
GLAPI PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
#define glVertexAttrib4dv glad_glVertexAttrib4dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
GLAPI PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
#define glVertexAttrib4f glad_glVertexAttrib4f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC)(GLuint, const GLfloat*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat* v);
GLAPI PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
#define glVertexAttrib4fv glad_glVertexAttrib4fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC)(GLuint, const GLint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint* v);
GLAPI PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
#define glVertexAttrib4iv glad_glVertexAttrib4iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC)(GLuint, GLshort, GLshort, GLshort, GLshort);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
GLAPI PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
#define glVertexAttrib4s glad_glVertexAttrib4s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC)(GLuint, const GLshort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort* v);
GLAPI PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
#define glVertexAttrib4sv glad_glVertexAttrib4sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC)(GLuint, const GLubyte*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte* v);
GLAPI PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC)(GLuint, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint* v);
GLAPI PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC)(GLuint, const GLushort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort* v);
GLAPI PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
#define glVertexAttrib4usv glad_glVertexAttrib4usv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
GLAPI PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
#define glVertexAttribPointer glad_glVertexAttribPointer
#endif
#ifndef GL_VERSION_2_1
#define GL_VERSION_2_1 1
GLAPI int GLAD_GL_VERSION_2_1;
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
GLAPI PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
#endif
#ifndef GL_VERSION_3_0
#define GL_VERSION_3_0 1
GLAPI int GLAD_GL_VERSION_3_0;
-typedef void (APIENTRYP PFNGLCOLORMASKIPROC)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (APIENTRYP PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
GLAPI PFNGLCOLORMASKIPROC glad_glColorMaski;
#define glColorMaski glad_glColorMaski
-typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC)(GLenum, GLuint, GLboolean*);
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean* data);
GLAPI PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
#define glGetBooleani_v glad_glGetBooleani_v
-typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC)(GLenum, GLuint, GLint*);
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint* data);
GLAPI PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
#define glGetIntegeri_v glad_glGetIntegeri_v
-typedef void (APIENTRYP PFNGLENABLEIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLENABLEIPROC)(GLenum target, GLuint index);
GLAPI PFNGLENABLEIPROC glad_glEnablei;
#define glEnablei glad_glEnablei
-typedef void (APIENTRYP PFNGLDISABLEIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLDISABLEIPROC)(GLenum target, GLuint index);
GLAPI PFNGLDISABLEIPROC glad_glDisablei;
#define glDisablei glad_glDisablei
-typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC)(GLenum, GLuint);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
GLAPI PFNGLISENABLEDIPROC glad_glIsEnabledi;
#define glIsEnabledi glad_glIsEnabledi
-typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum);
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
GLAPI PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
#define glBeginTransformFeedback glad_glBeginTransformFeedback
typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC)();
GLAPI PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
#define glEndTransformFeedback glad_glEndTransformFeedback
-typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
GLAPI PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
#define glBindBufferRange glad_glBindBufferRange
-typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC)(GLenum, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
GLAPI PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
#define glBindBufferBase glad_glBindBufferBase
-typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint, GLsizei, const GLchar**, GLenum);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar** varyings, GLenum bufferMode);
GLAPI PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
-typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint, GLuint, GLsizei, GLsizei*, GLsizei*, GLenum*, GLchar*);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
GLAPI PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
-typedef void (APIENTRYP PFNGLCLAMPCOLORPROC)(GLenum, GLenum);
+typedef void (APIENTRYP PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
GLAPI PFNGLCLAMPCOLORPROC glad_glClampColor;
#define glClampColor glad_glClampColor
-typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC)(GLuint, GLenum);
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
GLAPI PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
#define glBeginConditionalRender glad_glBeginConditionalRender
typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC)();
GLAPI PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
#define glEndConditionalRender glad_glEndConditionalRender
-typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint, GLint, GLenum, GLsizei, const void*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
#define glVertexAttribIPointer glad_glVertexAttribIPointer
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC)(GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint* params);
GLAPI PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint, GLenum, GLuint*);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint* params);
GLAPI PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC)(GLuint, GLint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
GLAPI PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
#define glVertexAttribI1i glad_glVertexAttribI1i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC)(GLuint, GLint, GLint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
GLAPI PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
#define glVertexAttribI2i glad_glVertexAttribI2i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC)(GLuint, GLint, GLint, GLint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
GLAPI PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
#define glVertexAttribI3i glad_glVertexAttribI3i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC)(GLuint, GLint, GLint, GLint, GLint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
GLAPI PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
#define glVertexAttribI4i glad_glVertexAttribI4i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC)(GLuint, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
GLAPI PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
#define glVertexAttribI1ui glad_glVertexAttribI1ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC)(GLuint, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
GLAPI PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
#define glVertexAttribI2ui glad_glVertexAttribI2ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC)(GLuint, GLuint, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
GLAPI PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
#define glVertexAttribI3ui glad_glVertexAttribI3ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC)(GLuint, GLuint, GLuint, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
GLAPI PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
#define glVertexAttribI4ui glad_glVertexAttribI4ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC)(GLuint, const GLint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint* v);
GLAPI PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
#define glVertexAttribI1iv glad_glVertexAttribI1iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC)(GLuint, const GLint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint* v);
GLAPI PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
#define glVertexAttribI2iv glad_glVertexAttribI2iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC)(GLuint, const GLint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint* v);
GLAPI PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
#define glVertexAttribI3iv glad_glVertexAttribI3iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC)(GLuint, const GLint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint* v);
GLAPI PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
#define glVertexAttribI4iv glad_glVertexAttribI4iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC)(GLuint, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint* v);
GLAPI PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC)(GLuint, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint* v);
GLAPI PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC)(GLuint, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint* v);
GLAPI PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC)(GLuint, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint* v);
GLAPI PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC)(GLuint, const GLbyte*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte* v);
GLAPI PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
#define glVertexAttribI4bv glad_glVertexAttribI4bv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC)(GLuint, const GLshort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort* v);
GLAPI PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
#define glVertexAttribI4sv glad_glVertexAttribI4sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC)(GLuint, const GLubyte*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte* v);
GLAPI PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC)(GLuint, const GLushort*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort* v);
GLAPI PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
#define glVertexAttribI4usv glad_glVertexAttribI4usv
-typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC)(GLuint, GLint, GLuint*);
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint* params);
GLAPI PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
#define glGetUniformuiv glad_glGetUniformuiv
-typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC)(GLuint, GLuint, const GLchar*);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar* name);
GLAPI PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
#define glBindFragDataLocation glad_glBindFragDataLocation
-typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC)(GLuint, const GLchar*);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar* name);
GLAPI PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
#define glGetFragDataLocation glad_glGetFragDataLocation
-typedef void (APIENTRYP PFNGLUNIFORM1UIPROC)(GLint, GLuint);
+typedef void (APIENTRYP PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
GLAPI PFNGLUNIFORM1UIPROC glad_glUniform1ui;
#define glUniform1ui glad_glUniform1ui
-typedef void (APIENTRYP PFNGLUNIFORM2UIPROC)(GLint, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
GLAPI PFNGLUNIFORM2UIPROC glad_glUniform2ui;
#define glUniform2ui glad_glUniform2ui
-typedef void (APIENTRYP PFNGLUNIFORM3UIPROC)(GLint, GLuint, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
GLAPI PFNGLUNIFORM3UIPROC glad_glUniform3ui;
#define glUniform3ui glad_glUniform3ui
-typedef void (APIENTRYP PFNGLUNIFORM4UIPROC)(GLint, GLuint, GLuint, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
GLAPI PFNGLUNIFORM4UIPROC glad_glUniform4ui;
#define glUniform4ui glad_glUniform4ui
-typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC)(GLint, GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint* value);
GLAPI PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
#define glUniform1uiv glad_glUniform1uiv
-typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC)(GLint, GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint* value);
GLAPI PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
#define glUniform2uiv glad_glUniform2uiv
-typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC)(GLint, GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint* value);
GLAPI PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
#define glUniform3uiv glad_glUniform3uiv
-typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC)(GLint, GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint* value);
GLAPI PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
#define glUniform4uiv glad_glUniform4uiv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC)(GLenum, GLenum, const GLint*);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint* params);
GLAPI PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
#define glTexParameterIiv glad_glTexParameterIiv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC)(GLenum, GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint* params);
GLAPI PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
#define glTexParameterIuiv glad_glTexParameterIuiv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC)(GLenum, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint* params);
GLAPI PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
#define glGetTexParameterIiv glad_glGetTexParameterIiv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC)(GLenum, GLenum, GLuint*);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint* params);
GLAPI PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC)(GLenum, GLint, const GLint*);
+typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint* value);
GLAPI PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
#define glClearBufferiv glad_glClearBufferiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC)(GLenum, GLint, const GLuint*);
+typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint* value);
GLAPI PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
#define glClearBufferuiv glad_glClearBufferuiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC)(GLenum, GLint, const GLfloat*);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat* value);
GLAPI PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
#define glClearBufferfv glad_glClearBufferfv
-typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC)(GLenum, GLint, GLfloat, GLint);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
GLAPI PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
#define glClearBufferfi glad_glClearBufferfi
-typedef const GLubyte* (APIENTRYP PFNGLGETSTRINGIPROC)(GLenum, GLuint);
+typedef const GLubyte* (APIENTRYP PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
GLAPI PFNGLGETSTRINGIPROC glad_glGetStringi;
#define glGetStringi glad_glGetStringi
-typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
GLAPI PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
#define glIsRenderbuffer glad_glIsRenderbuffer
-typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
GLAPI PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
#define glBindRenderbuffer glad_glBindRenderbuffer
-typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint* renderbuffers);
GLAPI PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
-typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint* renderbuffers);
GLAPI PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
#define glGenRenderbuffers glad_glGenRenderbuffers
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC)(GLenum, GLenum, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
GLAPI PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
#define glRenderbufferStorage glad_glRenderbufferStorage
-typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint* params);
GLAPI PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
-typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
GLAPI PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
#define glIsFramebuffer glad_glIsFramebuffer
-typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
GLAPI PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
#define glBindFramebuffer glad_glBindFramebuffer
-typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint* framebuffers);
GLAPI PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
#define glDeleteFramebuffers glad_glDeleteFramebuffers
-typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint* framebuffers);
GLAPI PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
#define glGenFramebuffers glad_glGenFramebuffers
-typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
GLAPI PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
GLAPI PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
#define glFramebufferTexture1D glad_glFramebufferTexture1D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
GLAPI PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
#define glFramebufferTexture2D glad_glFramebufferTexture2D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLint);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
GLAPI PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
#define glFramebufferTexture3D glad_glFramebufferTexture3D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum, GLenum, GLenum, GLuint);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
GLAPI PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
-typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum, GLenum, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint* params);
GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
-typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC)(GLenum);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC)(GLenum target);
GLAPI PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
#define glGenerateMipmap glad_glGenerateMipmap
-typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
GLAPI PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
#define glBlitFramebuffer glad_glBlitFramebuffer
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum, GLenum, GLuint, GLint, GLint);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
GLAPI PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
-typedef void* (APIENTRYP PFNGLMAPBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
+typedef void* (APIENTRYP PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
GLAPI PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
#define glMapBufferRange glad_glMapBufferRange
-typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
GLAPI PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
-typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint);
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint array);
GLAPI PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
#define glBindVertexArray glad_glBindVertexArray
-typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint* arrays);
GLAPI PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
#define glDeleteVertexArrays glad_glDeleteVertexArrays
-typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint* arrays);
GLAPI PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
#define glGenVertexArrays glad_glGenVertexArrays
-typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC)(GLuint array);
GLAPI PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
#define glIsVertexArray glad_glIsVertexArray
#endif
#ifndef GL_VERSION_3_1
#define GL_VERSION_3_1 1
GLAPI int GLAD_GL_VERSION_3_1;
-typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum, GLint, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
GLAPI PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
#define glDrawArraysInstanced glad_glDrawArraysInstanced
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum, GLsizei, GLenum, const void*, GLsizei);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount);
GLAPI PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
#define glDrawElementsInstanced glad_glDrawElementsInstanced
-typedef void (APIENTRYP PFNGLTEXBUFFERPROC)(GLenum, GLenum, GLuint);
+typedef void (APIENTRYP PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
GLAPI PFNGLTEXBUFFERPROC glad_glTexBuffer;
#define glTexBuffer glad_glTexBuffer
-typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
GLAPI PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
-typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr);
+typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
GLAPI PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
#define glCopyBufferSubData glad_glCopyBufferSubData
-typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC)(GLuint, GLsizei, const GLchar**, GLuint*);
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar** uniformNames, GLuint* uniformIndices);
GLAPI PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
#define glGetUniformIndices glad_glGetUniformIndices
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint, GLsizei, const GLuint*, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
GLAPI PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei*, GLchar*);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformName);
GLAPI PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
#define glGetActiveUniformName glad_glGetActiveUniformName
-typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint, const GLchar*);
+typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar* uniformBlockName);
GLAPI PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint, GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
GLAPI PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei*, GLchar*);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
GLAPI PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
-typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint, GLuint, GLuint);
+typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLAPI PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
#define glUniformBlockBinding glad_glUniformBlockBinding
#endif
#ifndef GL_VERSION_3_2
#define GL_VERSION_3_2 1
GLAPI int GLAD_GL_VERSION_3_2;
-typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const void*, GLint);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex);
GLAPI PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
-typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void*, GLint);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices, GLint basevertex);
GLAPI PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex);
GLAPI PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum, const GLsizei*, GLenum, const void**, GLsizei, const GLint*);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei* count, GLenum type, const void** indices, GLsizei drawcount, const GLint* basevertex);
GLAPI PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
-typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC)(GLenum);
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
GLAPI PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
#define glProvokingVertex glad_glProvokingVertex
-typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC)(GLenum, GLbitfield);
+typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
GLAPI PFNGLFENCESYNCPROC glad_glFenceSync;
#define glFenceSync glad_glFenceSync
-typedef GLboolean (APIENTRYP PFNGLISSYNCPROC)(GLsync);
+typedef GLboolean (APIENTRYP PFNGLISSYNCPROC)(GLsync sync);
GLAPI PFNGLISSYNCPROC glad_glIsSync;
#define glIsSync glad_glIsSync
-typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync);
+typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync sync);
GLAPI PFNGLDELETESYNCPROC glad_glDeleteSync;
#define glDeleteSync glad_glDeleteSync
-typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync, GLbitfield, GLuint64);
+typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
GLAPI PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
#define glClientWaitSync glad_glClientWaitSync
-typedef void (APIENTRYP PFNGLWAITSYNCPROC)(GLsync, GLbitfield, GLuint64);
+typedef void (APIENTRYP PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
GLAPI PFNGLWAITSYNCPROC glad_glWaitSync;
#define glWaitSync glad_glWaitSync
-typedef void (APIENTRYP PFNGLGETINTEGER64VPROC)(GLenum, GLint64*);
+typedef void (APIENTRYP PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64* data);
GLAPI PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
#define glGetInteger64v glad_glGetInteger64v
-typedef void (APIENTRYP PFNGLGETSYNCIVPROC)(GLsync, GLenum, GLsizei, GLsizei*, GLint*);
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
GLAPI PFNGLGETSYNCIVPROC glad_glGetSynciv;
#define glGetSynciv glad_glGetSynciv
-typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC)(GLenum, GLuint, GLint64*);
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64* data);
GLAPI PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
#define glGetInteger64i_v glad_glGetInteger64i_v
-typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum, GLenum, GLint64*);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64* params);
GLAPI PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum, GLenum, GLuint, GLint);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
GLAPI PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
#define glFramebufferTexture glad_glFramebufferTexture
-typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
GLAPI PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
#define glTexImage2DMultisample glad_glTexImage2DMultisample
-typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
GLAPI PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
#define glTexImage3DMultisample glad_glTexImage3DMultisample
-typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC)(GLenum, GLuint, GLfloat*);
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat* val);
GLAPI PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
#define glGetMultisamplefv glad_glGetMultisamplefv
-typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC)(GLuint, GLbitfield);
+typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
GLAPI PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
#define glSampleMaski glad_glSampleMaski
#endif
#ifndef GL_VERSION_3_3
#define GL_VERSION_3_3 1
GLAPI int GLAD_GL_VERSION_3_3;
-typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint, GLuint, GLuint, const GLchar*);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar* name);
GLAPI PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
-typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC)(GLuint, const GLchar*);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar* name);
GLAPI PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
#define glGetFragDataIndex glad_glGetFragDataIndex
-typedef void (APIENTRYP PFNGLGENSAMPLERSPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint* samplers);
GLAPI PFNGLGENSAMPLERSPROC glad_glGenSamplers;
#define glGenSamplers glad_glGenSamplers
-typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint* samplers);
GLAPI PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
#define glDeleteSamplers glad_glDeleteSamplers
-typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC)(GLuint sampler);
GLAPI PFNGLISSAMPLERPROC glad_glIsSampler;
#define glIsSampler glad_glIsSampler
-typedef void (APIENTRYP PFNGLBINDSAMPLERPROC)(GLuint, GLuint);
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
GLAPI PFNGLBINDSAMPLERPROC glad_glBindSampler;
#define glBindSampler glad_glBindSampler
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
GLAPI PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
#define glSamplerParameteri glad_glSamplerParameteri
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC)(GLuint, GLenum, const GLint*);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint* param);
GLAPI PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
#define glSamplerParameteriv glad_glSamplerParameteriv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC)(GLuint, GLenum, GLfloat);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
GLAPI PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
#define glSamplerParameterf glad_glSamplerParameterf
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC)(GLuint, GLenum, const GLfloat*);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat* param);
GLAPI PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
#define glSamplerParameterfv glad_glSamplerParameterfv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, const GLint*);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint* param);
GLAPI PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
#define glSamplerParameterIiv glad_glSamplerParameterIiv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint* param);
GLAPI PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint* params);
GLAPI PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, GLint*);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint* params);
GLAPI PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint, GLenum, GLfloat*);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat* params);
GLAPI PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, GLuint*);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint* params);
GLAPI PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
-typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC)(GLuint, GLenum);
+typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
GLAPI PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
#define glQueryCounter glad_glQueryCounter
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC)(GLuint, GLenum, GLint64*);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64* params);
GLAPI PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC)(GLuint, GLenum, GLuint64*);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64* params);
GLAPI PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
-typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC)(GLuint, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
GLAPI PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
#define glVertexAttribDivisor glad_glVertexAttribDivisor
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
GLAPI PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
#define glVertexAttribP1ui glad_glVertexAttribP1ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC)(GLuint, GLenum, GLboolean, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
GLAPI PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
GLAPI PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
#define glVertexAttribP2ui glad_glVertexAttribP2ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC)(GLuint, GLenum, GLboolean, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
GLAPI PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
GLAPI PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
#define glVertexAttribP3ui glad_glVertexAttribP3ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC)(GLuint, GLenum, GLboolean, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
GLAPI PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
GLAPI PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
#define glVertexAttribP4ui glad_glVertexAttribP4ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC)(GLuint, GLenum, GLboolean, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
GLAPI PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
-typedef void (APIENTRYP PFNGLVERTEXP2UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value);
GLAPI PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
#define glVertexP2ui glad_glVertexP2ui
-typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint* value);
GLAPI PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
#define glVertexP2uiv glad_glVertexP2uiv
-typedef void (APIENTRYP PFNGLVERTEXP3UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value);
GLAPI PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
#define glVertexP3ui glad_glVertexP3ui
-typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint* value);
GLAPI PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
#define glVertexP3uiv glad_glVertexP3uiv
-typedef void (APIENTRYP PFNGLVERTEXP4UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value);
GLAPI PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
#define glVertexP4ui glad_glVertexP4ui
-typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint* value);
GLAPI PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
#define glVertexP4uiv glad_glVertexP4uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords);
GLAPI PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
#define glTexCoordP1ui glad_glTexCoordP1ui
-typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint* coords);
GLAPI PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
#define glTexCoordP1uiv glad_glTexCoordP1uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords);
GLAPI PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
#define glTexCoordP2ui glad_glTexCoordP2ui
-typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint* coords);
GLAPI PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
#define glTexCoordP2uiv glad_glTexCoordP2uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords);
GLAPI PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
#define glTexCoordP3ui glad_glTexCoordP3ui
-typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint* coords);
GLAPI PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
#define glTexCoordP3uiv glad_glTexCoordP3uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords);
GLAPI PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
#define glTexCoordP4ui glad_glTexCoordP4ui
-typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint* coords);
GLAPI PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
#define glTexCoordP4uiv glad_glTexCoordP4uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC)(GLenum, GLenum, GLuint);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords);
GLAPI PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC)(GLenum, GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint* coords);
GLAPI PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC)(GLenum, GLenum, GLuint);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords);
GLAPI PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC)(GLenum, GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint* coords);
GLAPI PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC)(GLenum, GLenum, GLuint);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords);
GLAPI PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC)(GLenum, GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint* coords);
GLAPI PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC)(GLenum, GLenum, GLuint);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords);
GLAPI PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC)(GLenum, GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint* coords);
GLAPI PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
-typedef void (APIENTRYP PFNGLNORMALP3UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords);
GLAPI PFNGLNORMALP3UIPROC glad_glNormalP3ui;
#define glNormalP3ui glad_glNormalP3ui
-typedef void (APIENTRYP PFNGLNORMALP3UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint* coords);
GLAPI PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
#define glNormalP3uiv glad_glNormalP3uiv
-typedef void (APIENTRYP PFNGLCOLORP3UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLCOLORP3UIPROC)(GLenum type, GLuint color);
GLAPI PFNGLCOLORP3UIPROC glad_glColorP3ui;
#define glColorP3ui glad_glColorP3ui
-typedef void (APIENTRYP PFNGLCOLORP3UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint* color);
GLAPI PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
#define glColorP3uiv glad_glColorP3uiv
-typedef void (APIENTRYP PFNGLCOLORP4UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLCOLORP4UIPROC)(GLenum type, GLuint color);
GLAPI PFNGLCOLORP4UIPROC glad_glColorP4ui;
#define glColorP4ui glad_glColorP4ui
-typedef void (APIENTRYP PFNGLCOLORP4UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint* color);
GLAPI PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
#define glColorP4uiv glad_glColorP4uiv
-typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color);
GLAPI PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
-typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC)(GLenum, const GLuint*);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint* color);
GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
#endif
#ifndef GL_ES_VERSION_2_0
#define GL_ES_VERSION_2_0 1
GLAPI int GLAD_GL_ES_VERSION_2_0;
-typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC)(GLfloat);
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC)(GLfloat d);
GLAPI PFNGLCLEARDEPTHFPROC glad_glClearDepthf;
#define glClearDepthf glad_glClearDepthf
-typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC)(GLfloat, GLfloat);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f);
GLAPI PFNGLDEPTHRANGEFPROC glad_glDepthRangef;
#define glDepthRangef glad_glDepthRangef
-typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum, GLenum, GLint*, GLint*);
+typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
GLAPI PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat;
#define glGetShaderPrecisionFormat glad_glGetShaderPrecisionFormat
typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC)();
GLAPI PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler;
#define glReleaseShaderCompiler glad_glReleaseShaderCompiler
-typedef void (APIENTRYP PFNGLSHADERBINARYPROC)(GLsizei, const GLuint*, GLenum, const void*, GLsizei);
+typedef void (APIENTRYP PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length);
GLAPI PFNGLSHADERBINARYPROC glad_glShaderBinary;
#define glShaderBinary glad_glShaderBinary
#endif
#ifndef GL_ES_VERSION_3_0
#define GL_ES_VERSION_3_0 1
GLAPI int GLAD_GL_ES_VERSION_3_0;
-typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum, GLuint);
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum target, GLuint id);
GLAPI PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback;
#define glBindTransformFeedback glad_glBindTransformFeedback
-typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei, const GLuint*);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei n, const GLuint* ids);
GLAPI PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks;
#define glDeleteTransformFeedbacks glad_glDeleteTransformFeedbacks
-typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei, GLuint*);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint* ids);
GLAPI PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks;
#define glGenTransformFeedbacks glad_glGenTransformFeedbacks
-typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC)(GLuint);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC)(GLuint id);
GLAPI PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback;
#define glIsTransformFeedback glad_glIsTransformFeedback
typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC)();
@@ -2231,31 +2231,186 @@ GLAPI PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback;
typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC)();
GLAPI PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback;
#define glResumeTransformFeedback glad_glResumeTransformFeedback
-typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC)(GLuint, GLsizei, GLsizei*, GLenum*, void*);
+typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC)(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary);
GLAPI PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary;
#define glGetProgramBinary glad_glGetProgramBinary
-typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC)(GLuint, GLenum, const void*, GLsizei);
+typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC)(GLuint program, GLenum binaryFormat, const void* binary, GLsizei length);
GLAPI PFNGLPROGRAMBINARYPROC glad_glProgramBinary;
#define glProgramBinary glad_glProgramBinary
-typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC)(GLuint program, GLenum pname, GLint value);
GLAPI PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri;
#define glProgramParameteri glad_glProgramParameteri
-typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum*);
+typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum* attachments);
GLAPI PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer;
#define glInvalidateFramebuffer glad_glInvalidateFramebuffer
-typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum*, GLint, GLint, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
GLAPI PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer;
#define glInvalidateSubFramebuffer glad_glInvalidateSubFramebuffer
-typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
GLAPI PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D;
#define glTexStorage2D glad_glTexStorage2D
-typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
GLAPI PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D;
#define glTexStorage3D glad_glTexStorage3D
-typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC)(GLenum, GLenum, GLenum, GLsizei, GLint*);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
GLAPI PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ;
#define glGetInternalformativ glad_glGetInternalformativ
#endif
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245
+#define GL_DEBUG_SOURCE_API_KHR 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A
+#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B
+#define GL_DEBUG_TYPE_ERROR_KHR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250
+#define GL_DEBUG_TYPE_OTHER_KHR 0x8251
+#define GL_DEBUG_TYPE_MARKER_KHR 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D
+#define GL_BUFFER_KHR 0x82E0
+#define GL_SHADER_KHR 0x82E1
+#define GL_PROGRAM_KHR 0x82E2
+#define GL_VERTEX_ARRAY_KHR 0x8074
+#define GL_QUERY_KHR 0x82E3
+#define GL_PROGRAM_PIPELINE_KHR 0x82E4
+#define GL_SAMPLER_KHR 0x82E6
+#define GL_MAX_LABEL_LENGTH_KHR 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147
+#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148
+#define GL_DEBUG_OUTPUT_KHR 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002
+#define GL_STACK_OVERFLOW_KHR 0x0503
+#define GL_STACK_UNDERFLOW_KHR 0x0504
+#define GL_DISPLAY_LIST 0x82E7
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+GLAPI int GLAD_GL_KHR_debug;
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+GLAPI PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
+#define glDebugMessageControl glad_glDebugMessageControl
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf);
+GLAPI PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
+#define glDebugMessageInsert glad_glDebugMessageInsert
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC callback, const void* userParam);
+GLAPI PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
+#define glDebugMessageCallback glad_glDebugMessageCallback
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC)(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog);
+GLAPI PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
+#define glGetDebugMessageLog glad_glGetDebugMessageLog
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC)(GLenum source, GLuint id, GLsizei length, const GLchar* message);
+GLAPI PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
+#define glPushDebugGroup glad_glPushDebugGroup
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC)();
+GLAPI PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
+#define glPopDebugGroup glad_glPopDebugGroup
+typedef void (APIENTRYP PFNGLOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei length, const GLchar* label);
+GLAPI PFNGLOBJECTLABELPROC glad_glObjectLabel;
+#define glObjectLabel glad_glObjectLabel
+typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label);
+GLAPI PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
+#define glGetObjectLabel glad_glGetObjectLabel
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC)(const void* ptr, GLsizei length, const GLchar* label);
+GLAPI PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
+#define glObjectPtrLabel glad_glObjectPtrLabel
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC)(const void* ptr, GLsizei bufSize, GLsizei* length, GLchar* label);
+GLAPI PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
+#define glGetObjectPtrLabel glad_glGetObjectPtrLabel
+typedef void (APIENTRYP PFNGLGETPOINTERVPROC)(GLenum pname, void** params);
+GLAPI PFNGLGETPOINTERVPROC glad_glGetPointerv;
+#define glGetPointerv glad_glGetPointerv
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+GLAPI PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR;
+#define glDebugMessageControlKHR glad_glDebugMessageControlKHR
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf);
+GLAPI PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR;
+#define glDebugMessageInsertKHR glad_glDebugMessageInsertKHR
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC)(GLDEBUGPROCKHR callback, const void* userParam);
+GLAPI PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR;
+#define glDebugMessageCallbackKHR glad_glDebugMessageCallbackKHR
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog);
+GLAPI PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR;
+#define glGetDebugMessageLogKHR glad_glGetDebugMessageLogKHR
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC)(GLenum source, GLuint id, GLsizei length, const GLchar* message);
+GLAPI PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR;
+#define glPushDebugGroupKHR glad_glPushDebugGroupKHR
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC)();
+GLAPI PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR;
+#define glPopDebugGroupKHR glad_glPopDebugGroupKHR
+typedef void (APIENTRYP PFNGLOBJECTLABELKHRPROC)(GLenum identifier, GLuint name, GLsizei length, const GLchar* label);
+GLAPI PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR;
+#define glObjectLabelKHR glad_glObjectLabelKHR
+typedef void (APIENTRYP PFNGLGETOBJECTLABELKHRPROC)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label);
+GLAPI PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR;
+#define glGetObjectLabelKHR glad_glGetObjectLabelKHR
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELKHRPROC)(const void* ptr, GLsizei length, const GLchar* label);
+GLAPI PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR;
+#define glObjectPtrLabelKHR glad_glObjectPtrLabelKHR
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC)(const void* ptr, GLsizei bufSize, GLsizei* length, GLchar* label);
+GLAPI PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR;
+#define glGetObjectPtrLabelKHR glad_glGetObjectPtrLabelKHR
+typedef void (APIENTRYP PFNGLGETPOINTERVKHRPROC)(GLenum pname, void** params);
+GLAPI PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR;
+#define glGetPointervKHR glad_glGetPointervKHR
+#endif
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+GLAPI int GLAD_GL_KHR_debug;
+#endif
#ifdef __cplusplus
}
diff --git a/externals/glad/src/glad.c b/externals/glad/src/glad.c
index 014b54383..6af737acc 100644
--- a/externals/glad/src/glad.c
+++ b/externals/glad/src/glad.c
@@ -595,6 +595,29 @@ PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
PFNGLFRONTFACEPROC glad_glFrontFace;
+int GLAD_GL_KHR_debug;
+PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
+PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
+PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
+PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
+PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
+PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
+PFNGLOBJECTLABELPROC glad_glObjectLabel;
+PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
+PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
+PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
+PFNGLGETPOINTERVPROC glad_glGetPointerv;
+PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR;
+PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR;
+PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR;
+PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR;
+PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR;
+PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR;
+PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR;
+PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR;
+PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR;
+PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR;
+PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR;
static void load_GL_VERSION_1_0(GLADloadproc load) {
if(!GLAD_GL_VERSION_1_0) return;
glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
@@ -1008,8 +1031,34 @@ static void load_GL_VERSION_3_3(GLADloadproc load) {
glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)load("glSecondaryColorP3ui");
glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)load("glSecondaryColorP3uiv");
}
+static void load_GL_KHR_debug(GLADloadproc load) {
+ if(!GLAD_GL_KHR_debug) return;
+ glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)load("glDebugMessageControl");
+ glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)load("glDebugMessageInsert");
+ glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)load("glDebugMessageCallback");
+ glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)load("glGetDebugMessageLog");
+ glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)load("glPushDebugGroup");
+ glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)load("glPopDebugGroup");
+ glad_glObjectLabel = (PFNGLOBJECTLABELPROC)load("glObjectLabel");
+ glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)load("glGetObjectLabel");
+ glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)load("glObjectPtrLabel");
+ glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)load("glGetObjectPtrLabel");
+ glad_glGetPointerv = (PFNGLGETPOINTERVPROC)load("glGetPointerv");
+ glad_glDebugMessageControlKHR = (PFNGLDEBUGMESSAGECONTROLKHRPROC)load("glDebugMessageControlKHR");
+ glad_glDebugMessageInsertKHR = (PFNGLDEBUGMESSAGEINSERTKHRPROC)load("glDebugMessageInsertKHR");
+ glad_glDebugMessageCallbackKHR = (PFNGLDEBUGMESSAGECALLBACKKHRPROC)load("glDebugMessageCallbackKHR");
+ glad_glGetDebugMessageLogKHR = (PFNGLGETDEBUGMESSAGELOGKHRPROC)load("glGetDebugMessageLogKHR");
+ glad_glPushDebugGroupKHR = (PFNGLPUSHDEBUGGROUPKHRPROC)load("glPushDebugGroupKHR");
+ glad_glPopDebugGroupKHR = (PFNGLPOPDEBUGGROUPKHRPROC)load("glPopDebugGroupKHR");
+ glad_glObjectLabelKHR = (PFNGLOBJECTLABELKHRPROC)load("glObjectLabelKHR");
+ glad_glGetObjectLabelKHR = (PFNGLGETOBJECTLABELKHRPROC)load("glGetObjectLabelKHR");
+ glad_glObjectPtrLabelKHR = (PFNGLOBJECTPTRLABELKHRPROC)load("glObjectPtrLabelKHR");
+ glad_glGetObjectPtrLabelKHR = (PFNGLGETOBJECTPTRLABELKHRPROC)load("glGetObjectPtrLabelKHR");
+ glad_glGetPointervKHR = (PFNGLGETPOINTERVKHRPROC)load("glGetPointervKHR");
+}
static void find_extensionsGL(void) {
get_exts();
+ GLAD_GL_KHR_debug = has_ext("GL_KHR_debug");
}
static void find_coreGL(void) {
@@ -1086,6 +1135,7 @@ int gladLoadGLLoader(GLADloadproc load) {
load_GL_VERSION_3_3(load);
find_extensionsGL();
+ load_GL_KHR_debug(load);
return GLVersion.major != 0 || GLVersion.minor != 0;
}
@@ -1343,6 +1393,7 @@ static void load_GL_ES_VERSION_3_0(GLADloadproc load) {
}
static void find_extensionsGLES2(void) {
get_exts();
+ GLAD_GL_KHR_debug = has_ext("GL_KHR_debug");
}
static void find_coreGLES2(void) {
@@ -1399,6 +1450,7 @@ int gladLoadGLES2Loader(GLADloadproc load) {
load_GL_ES_VERSION_3_0(load);
find_extensionsGLES2();
+ load_GL_KHR_debug(load);
return GLVersion.major != 0 || GLVersion.minor != 0;
}
diff --git a/externals/glfw-3.1.1.bin/COPYING.txt b/externals/glfw-3.1.1.bin/COPYING.txt
deleted file mode 100644
index b30c70158..000000000
--- a/externals/glfw-3.1.1.bin/COPYING.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (c) 2002-2006 Marcus Geelnard
-Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would
- be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and must not
- be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
- distribution.
-
diff --git a/externals/glfw-3.1.1.bin/include/GLFW/glfw3.h b/externals/glfw-3.1.1.bin/include/GLFW/glfw3.h
deleted file mode 100644
index 009fa755f..000000000
--- a/externals/glfw-3.1.1.bin/include/GLFW/glfw3.h
+++ /dev/null
@@ -1,3340 +0,0 @@
-/*************************************************************************
- * GLFW 3.1 - www.glfw.org
- * A library for OpenGL, window and input
- *------------------------------------------------------------------------
- * Copyright (c) 2002-2006 Marcus Geelnard
- * Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would
- * be appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
- *
- *************************************************************************/
-
-#ifndef _glfw3_h_
-#define _glfw3_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*************************************************************************
- * Doxygen documentation
- *************************************************************************/
-
-/*! @defgroup context Context handling
- *
- * This is the reference documentation for context related functions. For more
- * information, see the @ref context.
- */
-/*! @defgroup init Initialization, version and errors
- *
- * This is the reference documentation for initialization and termination of
- * the library, version management and error handling. For more information,
- * see the @ref intro.
- */
-/*! @defgroup input Input handling
- *
- * This is the reference documentation for input related functions and types.
- * For more information, see the @ref input.
- */
-/*! @defgroup monitor Monitor handling
- *
- * This is the reference documentation for monitor related functions and types.
- * For more information, see the @ref monitor.
- */
-/*! @defgroup window Window handling
- *
- * This is the reference documentation for window related functions and types,
- * including creation, deletion and event polling. For more information, see
- * the @ref window.
- */
-
-
-/*************************************************************************
- * Compiler- and platform-specific preprocessor work
- *************************************************************************/
-
-/* If we are we on Windows, we want a single define for it.
- */
-#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
- #define _WIN32
-#endif /* _WIN32 */
-
-/* It is customary to use APIENTRY for OpenGL function pointer declarations on
- * all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
- */
-#ifndef APIENTRY
- #ifdef _WIN32
- #define APIENTRY __stdcall
- #else
- #define APIENTRY
- #endif
-#endif /* APIENTRY */
-
-/* Some Windows OpenGL headers need this.
- */
-#if !defined(WINGDIAPI) && defined(_WIN32)
- #define WINGDIAPI __declspec(dllimport)
- #define GLFW_WINGDIAPI_DEFINED
-#endif /* WINGDIAPI */
-
-/* Some Windows GLU headers need this.
- */
-#if !defined(CALLBACK) && defined(_WIN32)
- #define CALLBACK __stdcall
- #define GLFW_CALLBACK_DEFINED
-#endif /* CALLBACK */
-
-/* Most Windows GLU headers need wchar_t.
- * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h.
- */
-#if !defined(GLFW_INCLUDE_NONE)
- #include <stddef.h>
-#endif
-
-/* Include the chosen client API headers.
- */
-#if defined(__APPLE_CC__)
- #if defined(GLFW_INCLUDE_GLCOREARB)
- #include <OpenGL/gl3.h>
- #if defined(GLFW_INCLUDE_GLEXT)
- #include <OpenGL/gl3ext.h>
- #endif
- #elif !defined(GLFW_INCLUDE_NONE)
- #if !defined(GLFW_INCLUDE_GLEXT)
- #define GL_GLEXT_LEGACY
- #endif
- #include <OpenGL/gl.h>
- #endif
- #if defined(GLFW_INCLUDE_GLU)
- #include <OpenGL/glu.h>
- #endif
-#else
- #if defined(GLFW_INCLUDE_GLCOREARB)
- #include <GL/glcorearb.h>
- #elif defined(GLFW_INCLUDE_ES1)
- #include <GLES/gl.h>
- #if defined(GLFW_INCLUDE_GLEXT)
- #include <GLES/glext.h>
- #endif
- #elif defined(GLFW_INCLUDE_ES2)
- #include <GLES2/gl2.h>
- #if defined(GLFW_INCLUDE_GLEXT)
- #include <GLES2/gl2ext.h>
- #endif
- #elif defined(GLFW_INCLUDE_ES3)
- #include <GLES3/gl3.h>
- #if defined(GLFW_INCLUDE_GLEXT)
- #include <GLES3/gl2ext.h>
- #endif
- #elif defined(GLFW_INCLUDE_ES31)
- #include <GLES3/gl31.h>
- #if defined(GLFW_INCLUDE_GLEXT)
- #include <GLES3/gl2ext.h>
- #endif
- #elif !defined(GLFW_INCLUDE_NONE)
- #include <GL/gl.h>
- #if defined(GLFW_INCLUDE_GLEXT)
- #include <GL/glext.h>
- #endif
- #endif
- #if defined(GLFW_INCLUDE_GLU)
- #include <GL/glu.h>
- #endif
-#endif
-
-#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
- /* GLFW_DLL must be defined by applications that are linking against the DLL
- * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW
- * configuration header when compiling the DLL version of the library.
- */
- #error "You may not have both GLFW_DLL and _GLFW_BUILD_DLL defined"
-#endif
-
-/* GLFWAPI is used to declare public API functions for export
- * from the DLL / shared library / dynamic library.
- */
-#if defined(_WIN32) && defined(_GLFW_BUILD_DLL)
- /* We are building GLFW as a Win32 DLL */
- #define GLFWAPI __declspec(dllexport)
-#elif defined(_WIN32) && defined(GLFW_DLL)
- /* We are calling GLFW as a Win32 DLL */
- #define GLFWAPI __declspec(dllimport)
-#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)
- /* We are building GLFW as a shared / dynamic library */
- #define GLFWAPI __attribute__((visibility("default")))
-#else
- /* We are building or calling GLFW as a static library */
- #define GLFWAPI
-#endif
-
-
-/*************************************************************************
- * GLFW API tokens
- *************************************************************************/
-
-/*! @name GLFW version macros
- * @{ */
-/*! @brief The major version number of the GLFW library.
- *
- * This is incremented when the API is changed in non-compatible ways.
- * @ingroup init
- */
-#define GLFW_VERSION_MAJOR 3
-/*! @brief The minor version number of the GLFW library.
- *
- * This is incremented when features are added to the API but it remains
- * backward-compatible.
- * @ingroup init
- */
-#define GLFW_VERSION_MINOR 1
-/*! @brief The revision number of the GLFW library.
- *
- * This is incremented when a bug fix release is made that does not contain any
- * API changes.
- * @ingroup init
- */
-#define GLFW_VERSION_REVISION 1
-/*! @} */
-
-/*! @name Key and button actions
- * @{ */
-/*! @brief The key or mouse button was released.
- *
- * The key or mouse button was released.
- *
- * @ingroup input
- */
-#define GLFW_RELEASE 0
-/*! @brief The key or mouse button was pressed.
- *
- * The key or mouse button was pressed.
- *
- * @ingroup input
- */
-#define GLFW_PRESS 1
-/*! @brief The key was held down until it repeated.
- *
- * The key was held down until it repeated.
- *
- * @ingroup input
- */
-#define GLFW_REPEAT 2
-/*! @} */
-
-/*! @defgroup keys Keyboard keys
- *
- * See [key input](@ref input_key) for how these are used.
- *
- * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60),
- * but re-arranged to map to 7-bit ASCII for printable keys (function keys are
- * put in the 256+ range).
- *
- * The naming of the key codes follow these rules:
- * - The US keyboard layout is used
- * - Names of printable alpha-numeric characters are used (e.g. "A", "R",
- * "3", etc.)
- * - For non-alphanumeric characters, Unicode:ish names are used (e.g.
- * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not
- * correspond to the Unicode standard (usually for brevity)
- * - Keys that lack a clear US mapping are named "WORLD_x"
- * - For non-printable keys, custom names are used (e.g. "F4",
- * "BACKSPACE", etc.)
- *
- * @ingroup input
- * @{
- */
-
-/* The unknown key */
-#define GLFW_KEY_UNKNOWN -1
-
-/* Printable keys */
-#define GLFW_KEY_SPACE 32
-#define GLFW_KEY_APOSTROPHE 39 /* ' */
-#define GLFW_KEY_COMMA 44 /* , */
-#define GLFW_KEY_MINUS 45 /* - */
-#define GLFW_KEY_PERIOD 46 /* . */
-#define GLFW_KEY_SLASH 47 /* / */
-#define GLFW_KEY_0 48
-#define GLFW_KEY_1 49
-#define GLFW_KEY_2 50
-#define GLFW_KEY_3 51
-#define GLFW_KEY_4 52
-#define GLFW_KEY_5 53
-#define GLFW_KEY_6 54
-#define GLFW_KEY_7 55
-#define GLFW_KEY_8 56
-#define GLFW_KEY_9 57
-#define GLFW_KEY_SEMICOLON 59 /* ; */
-#define GLFW_KEY_EQUAL 61 /* = */
-#define GLFW_KEY_A 65
-#define GLFW_KEY_B 66
-#define GLFW_KEY_C 67
-#define GLFW_KEY_D 68
-#define GLFW_KEY_E 69
-#define GLFW_KEY_F 70
-#define GLFW_KEY_G 71
-#define GLFW_KEY_H 72
-#define GLFW_KEY_I 73
-#define GLFW_KEY_J 74
-#define GLFW_KEY_K 75
-#define GLFW_KEY_L 76
-#define GLFW_KEY_M 77
-#define GLFW_KEY_N 78
-#define GLFW_KEY_O 79
-#define GLFW_KEY_P 80
-#define GLFW_KEY_Q 81
-#define GLFW_KEY_R 82
-#define GLFW_KEY_S 83
-#define GLFW_KEY_T 84
-#define GLFW_KEY_U 85
-#define GLFW_KEY_V 86
-#define GLFW_KEY_W 87
-#define GLFW_KEY_X 88
-#define GLFW_KEY_Y 89
-#define GLFW_KEY_Z 90
-#define GLFW_KEY_LEFT_BRACKET 91 /* [ */
-#define GLFW_KEY_BACKSLASH 92 /* \ */
-#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */
-#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
-#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
-#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
-
-/* Function keys */
-#define GLFW_KEY_ESCAPE 256
-#define GLFW_KEY_ENTER 257
-#define GLFW_KEY_TAB 258
-#define GLFW_KEY_BACKSPACE 259
-#define GLFW_KEY_INSERT 260
-#define GLFW_KEY_DELETE 261
-#define GLFW_KEY_RIGHT 262
-#define GLFW_KEY_LEFT 263
-#define GLFW_KEY_DOWN 264
-#define GLFW_KEY_UP 265
-#define GLFW_KEY_PAGE_UP 266
-#define GLFW_KEY_PAGE_DOWN 267
-#define GLFW_KEY_HOME 268
-#define GLFW_KEY_END 269
-#define GLFW_KEY_CAPS_LOCK 280
-#define GLFW_KEY_SCROLL_LOCK 281
-#define GLFW_KEY_NUM_LOCK 282
-#define GLFW_KEY_PRINT_SCREEN 283
-#define GLFW_KEY_PAUSE 284
-#define GLFW_KEY_F1 290
-#define GLFW_KEY_F2 291
-#define GLFW_KEY_F3 292
-#define GLFW_KEY_F4 293
-#define GLFW_KEY_F5 294
-#define GLFW_KEY_F6 295
-#define GLFW_KEY_F7 296
-#define GLFW_KEY_F8 297
-#define GLFW_KEY_F9 298
-#define GLFW_KEY_F10 299
-#define GLFW_KEY_F11 300
-#define GLFW_KEY_F12 301
-#define GLFW_KEY_F13 302
-#define GLFW_KEY_F14 303
-#define GLFW_KEY_F15 304
-#define GLFW_KEY_F16 305
-#define GLFW_KEY_F17 306
-#define GLFW_KEY_F18 307
-#define GLFW_KEY_F19 308
-#define GLFW_KEY_F20 309
-#define GLFW_KEY_F21 310
-#define GLFW_KEY_F22 311
-#define GLFW_KEY_F23 312
-#define GLFW_KEY_F24 313
-#define GLFW_KEY_F25 314
-#define GLFW_KEY_KP_0 320
-#define GLFW_KEY_KP_1 321
-#define GLFW_KEY_KP_2 322
-#define GLFW_KEY_KP_3 323
-#define GLFW_KEY_KP_4 324
-#define GLFW_KEY_KP_5 325
-#define GLFW_KEY_KP_6 326
-#define GLFW_KEY_KP_7 327
-#define GLFW_KEY_KP_8 328
-#define GLFW_KEY_KP_9 329
-#define GLFW_KEY_KP_DECIMAL 330
-#define GLFW_KEY_KP_DIVIDE 331
-#define GLFW_KEY_KP_MULTIPLY 332
-#define GLFW_KEY_KP_SUBTRACT 333
-#define GLFW_KEY_KP_ADD 334
-#define GLFW_KEY_KP_ENTER 335
-#define GLFW_KEY_KP_EQUAL 336
-#define GLFW_KEY_LEFT_SHIFT 340
-#define GLFW_KEY_LEFT_CONTROL 341
-#define GLFW_KEY_LEFT_ALT 342
-#define GLFW_KEY_LEFT_SUPER 343
-#define GLFW_KEY_RIGHT_SHIFT 344
-#define GLFW_KEY_RIGHT_CONTROL 345
-#define GLFW_KEY_RIGHT_ALT 346
-#define GLFW_KEY_RIGHT_SUPER 347
-#define GLFW_KEY_MENU 348
-#define GLFW_KEY_LAST GLFW_KEY_MENU
-
-/*! @} */
-
-/*! @defgroup mods Modifier key flags
- *
- * See [key input](@ref input_key) for how these are used.
- *
- * @ingroup input
- * @{ */
-
-/*! @brief If this bit is set one or more Shift keys were held down.
- */
-#define GLFW_MOD_SHIFT 0x0001
-/*! @brief If this bit is set one or more Control keys were held down.
- */
-#define GLFW_MOD_CONTROL 0x0002
-/*! @brief If this bit is set one or more Alt keys were held down.
- */
-#define GLFW_MOD_ALT 0x0004
-/*! @brief If this bit is set one or more Super keys were held down.
- */
-#define GLFW_MOD_SUPER 0x0008
-
-/*! @} */
-
-/*! @defgroup buttons Mouse buttons
- *
- * See [mouse button input](@ref input_mouse_button) for how these are used.
- *
- * @ingroup input
- * @{ */
-#define GLFW_MOUSE_BUTTON_1 0
-#define GLFW_MOUSE_BUTTON_2 1
-#define GLFW_MOUSE_BUTTON_3 2
-#define GLFW_MOUSE_BUTTON_4 3
-#define GLFW_MOUSE_BUTTON_5 4
-#define GLFW_MOUSE_BUTTON_6 5
-#define GLFW_MOUSE_BUTTON_7 6
-#define GLFW_MOUSE_BUTTON_8 7
-#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
-#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
-#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
-#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
-/*! @} */
-
-/*! @defgroup joysticks Joysticks
- *
- * See [joystick input](@ref joystick) for how these are used.
- *
- * @ingroup input
- * @{ */
-#define GLFW_JOYSTICK_1 0
-#define GLFW_JOYSTICK_2 1
-#define GLFW_JOYSTICK_3 2
-#define GLFW_JOYSTICK_4 3
-#define GLFW_JOYSTICK_5 4
-#define GLFW_JOYSTICK_6 5
-#define GLFW_JOYSTICK_7 6
-#define GLFW_JOYSTICK_8 7
-#define GLFW_JOYSTICK_9 8
-#define GLFW_JOYSTICK_10 9
-#define GLFW_JOYSTICK_11 10
-#define GLFW_JOYSTICK_12 11
-#define GLFW_JOYSTICK_13 12
-#define GLFW_JOYSTICK_14 13
-#define GLFW_JOYSTICK_15 14
-#define GLFW_JOYSTICK_16 15
-#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16
-/*! @} */
-
-/*! @defgroup errors Error codes
- *
- * See [error handling](@ref error_handling) for how these are used.
- *
- * @ingroup init
- * @{ */
-/*! @brief GLFW has not been initialized.
- *
- * This occurs if a GLFW function was called that may not be called unless the
- * library is [initialized](@ref intro_init).
- *
- * @par Analysis
- * Application programmer error. Initialize GLFW before calling any function
- * that requires initialization.
- */
-#define GLFW_NOT_INITIALIZED 0x00010001
-/*! @brief No context is current for this thread.
- *
- * This occurs if a GLFW function was called that needs and operates on the
- * current OpenGL or OpenGL ES context but no context is current on the calling
- * thread. One such function is @ref glfwSwapInterval.
- *
- * @par Analysis
- * Application programmer error. Ensure a context is current before calling
- * functions that require a current context.
- */
-#define GLFW_NO_CURRENT_CONTEXT 0x00010002
-/*! @brief One of the arguments to the function was an invalid enum value.
- *
- * One of the arguments to the function was an invalid enum value, for example
- * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref
- * glfwGetWindowAttrib.
- *
- * @par Analysis
- * Application programmer error. Fix the offending call.
- */
-#define GLFW_INVALID_ENUM 0x00010003
-/*! @brief One of the arguments to the function was an invalid value.
- *
- * One of the arguments to the function was an invalid value, for example
- * requesting a non-existent OpenGL or OpenGL ES version like 2.7.
- *
- * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead
- * result in a @ref GLFW_VERSION_UNAVAILABLE error.
- *
- * @par Analysis
- * Application programmer error. Fix the offending call.
- */
-#define GLFW_INVALID_VALUE 0x00010004
-/*! @brief A memory allocation failed.
- *
- * A memory allocation failed.
- *
- * @par Analysis
- * A bug in GLFW or the underlying operating system. Report the bug to our
- * [issue tracker](https://github.com/glfw/glfw/issues).
- */
-#define GLFW_OUT_OF_MEMORY 0x00010005
-/*! @brief GLFW could not find support for the requested client API on the
- * system.
- *
- * GLFW could not find support for the requested client API on the system. If
- * emitted by functions other than @ref glfwCreateWindow, no supported client
- * API was found.
- *
- * @par Analysis
- * The installed graphics driver does not support the requested client API, or
- * does not support it via the chosen context creation backend. Below are
- * a few examples.
- *
- * @par
- * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
- * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via
- * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
- * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
- * driver.
- */
-#define GLFW_API_UNAVAILABLE 0x00010006
-/*! @brief The requested OpenGL or OpenGL ES version is not available.
- *
- * The requested OpenGL or OpenGL ES version (including any requested context
- * or framebuffer hints) is not available on this machine.
- *
- * @par Analysis
- * The machine does not support your requirements. If your application is
- * sufficiently flexible, downgrade your requirements and try again.
- * Otherwise, inform the user that their machine does not match your
- * requirements.
- *
- * @par
- * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0
- * comes out before the 4.x series gets that far, also fail with this error and
- * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions
- * will exist.
- */
-#define GLFW_VERSION_UNAVAILABLE 0x00010007
-/*! @brief A platform-specific error occurred that does not match any of the
- * more specific categories.
- *
- * A platform-specific error occurred that does not match any of the more
- * specific categories.
- *
- * @par Analysis
- * A bug or configuration error in GLFW, the underlying operating system or
- * its drivers, or a lack of required resources. Report the issue to our
- * [issue tracker](https://github.com/glfw/glfw/issues).
- */
-#define GLFW_PLATFORM_ERROR 0x00010008
-/*! @brief The requested format is not supported or available.
- *
- * If emitted during window creation, the requested pixel format is not
- * supported.
- *
- * If emitted when querying the clipboard, the contents of the clipboard could
- * not be converted to the requested format.
- *
- * @par Analysis
- * If emitted during window creation, one or more
- * [hard constraints](@ref window_hints_hard) did not match any of the
- * available pixel formats. If your application is sufficiently flexible,
- * downgrade your requirements and try again. Otherwise, inform the user that
- * their machine does not match your requirements.
- *
- * @par
- * If emitted when querying the clipboard, ignore the error or report it to
- * the user, as appropriate.
- */
-#define GLFW_FORMAT_UNAVAILABLE 0x00010009
-/*! @} */
-
-#define GLFW_FOCUSED 0x00020001
-#define GLFW_ICONIFIED 0x00020002
-#define GLFW_RESIZABLE 0x00020003
-#define GLFW_VISIBLE 0x00020004
-#define GLFW_DECORATED 0x00020005
-#define GLFW_AUTO_ICONIFY 0x00020006
-#define GLFW_FLOATING 0x00020007
-
-#define GLFW_RED_BITS 0x00021001
-#define GLFW_GREEN_BITS 0x00021002
-#define GLFW_BLUE_BITS 0x00021003
-#define GLFW_ALPHA_BITS 0x00021004
-#define GLFW_DEPTH_BITS 0x00021005
-#define GLFW_STENCIL_BITS 0x00021006
-#define GLFW_ACCUM_RED_BITS 0x00021007
-#define GLFW_ACCUM_GREEN_BITS 0x00021008
-#define GLFW_ACCUM_BLUE_BITS 0x00021009
-#define GLFW_ACCUM_ALPHA_BITS 0x0002100A
-#define GLFW_AUX_BUFFERS 0x0002100B
-#define GLFW_STEREO 0x0002100C
-#define GLFW_SAMPLES 0x0002100D
-#define GLFW_SRGB_CAPABLE 0x0002100E
-#define GLFW_REFRESH_RATE 0x0002100F
-#define GLFW_DOUBLEBUFFER 0x00021010
-
-#define GLFW_CLIENT_API 0x00022001
-#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002
-#define GLFW_CONTEXT_VERSION_MINOR 0x00022003
-#define GLFW_CONTEXT_REVISION 0x00022004
-#define GLFW_CONTEXT_ROBUSTNESS 0x00022005
-#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
-#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007
-#define GLFW_OPENGL_PROFILE 0x00022008
-#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
-
-#define GLFW_OPENGL_API 0x00030001
-#define GLFW_OPENGL_ES_API 0x00030002
-
-#define GLFW_NO_ROBUSTNESS 0
-#define GLFW_NO_RESET_NOTIFICATION 0x00031001
-#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002
-
-#define GLFW_OPENGL_ANY_PROFILE 0
-#define GLFW_OPENGL_CORE_PROFILE 0x00032001
-#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002
-
-#define GLFW_CURSOR 0x00033001
-#define GLFW_STICKY_KEYS 0x00033002
-#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
-
-#define GLFW_CURSOR_NORMAL 0x00034001
-#define GLFW_CURSOR_HIDDEN 0x00034002
-#define GLFW_CURSOR_DISABLED 0x00034003
-
-#define GLFW_ANY_RELEASE_BEHAVIOR 0
-#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
-#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
-
-/*! @defgroup shapes Standard cursor shapes
- *
- * See [standard cursor creation](@ref cursor_standard) for how these are used.
- *
- * @ingroup input
- * @{ */
-
-/*! @brief The regular arrow cursor shape.
- *
- * The regular arrow cursor.
- */
-#define GLFW_ARROW_CURSOR 0x00036001
-/*! @brief The text input I-beam cursor shape.
- *
- * The text input I-beam cursor shape.
- */
-#define GLFW_IBEAM_CURSOR 0x00036002
-/*! @brief The crosshair shape.
- *
- * The crosshair shape.
- */
-#define GLFW_CROSSHAIR_CURSOR 0x00036003
-/*! @brief The hand shape.
- *
- * The hand shape.
- */
-#define GLFW_HAND_CURSOR 0x00036004
-/*! @brief The horizontal resize arrow shape.
- *
- * The horizontal resize arrow shape.
- */
-#define GLFW_HRESIZE_CURSOR 0x00036005
-/*! @brief The vertical resize arrow shape.
- *
- * The vertical resize arrow shape.
- */
-#define GLFW_VRESIZE_CURSOR 0x00036006
-/*! @} */
-
-#define GLFW_CONNECTED 0x00040001
-#define GLFW_DISCONNECTED 0x00040002
-
-#define GLFW_DONT_CARE -1
-
-
-/*************************************************************************
- * GLFW API types
- *************************************************************************/
-
-/*! @brief Client API function pointer type.
- *
- * Generic function pointer used for returning client API function pointers
- * without forcing a cast from a regular pointer.
- *
- * @ingroup context
- */
-typedef void (*GLFWglproc)(void);
-
-/*! @brief Opaque monitor object.
- *
- * Opaque monitor object.
- *
- * @ingroup monitor
- */
-typedef struct GLFWmonitor GLFWmonitor;
-
-/*! @brief Opaque window object.
- *
- * Opaque window object.
- *
- * @ingroup window
- */
-typedef struct GLFWwindow GLFWwindow;
-
-/*! @brief Opaque cursor object.
- *
- * Opaque cursor object.
- *
- * @ingroup cursor
- */
-typedef struct GLFWcursor GLFWcursor;
-
-/*! @brief The function signature for error callbacks.
- *
- * This is the function signature for error callback functions.
- *
- * @param[in] error An [error code](@ref errors).
- * @param[in] description A UTF-8 encoded string describing the error.
- *
- * @sa glfwSetErrorCallback
- *
- * @ingroup init
- */
-typedef void (* GLFWerrorfun)(int,const char*);
-
-/*! @brief The function signature for window position callbacks.
- *
- * This is the function signature for window position callback functions.
- *
- * @param[in] window The window that was moved.
- * @param[in] xpos The new x-coordinate, in screen coordinates, of the
- * upper-left corner of the client area of the window.
- * @param[in] ypos The new y-coordinate, in screen coordinates, of the
- * upper-left corner of the client area of the window.
- *
- * @sa glfwSetWindowPosCallback
- *
- * @ingroup window
- */
-typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);
-
-/*! @brief The function signature for window resize callbacks.
- *
- * This is the function signature for window size callback functions.
- *
- * @param[in] window The window that was resized.
- * @param[in] width The new width, in screen coordinates, of the window.
- * @param[in] height The new height, in screen coordinates, of the window.
- *
- * @sa glfwSetWindowSizeCallback
- *
- * @ingroup window
- */
-typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);
-
-/*! @brief The function signature for window close callbacks.
- *
- * This is the function signature for window close callback functions.
- *
- * @param[in] window The window that the user attempted to close.
- *
- * @sa glfwSetWindowCloseCallback
- *
- * @ingroup window
- */
-typedef void (* GLFWwindowclosefun)(GLFWwindow*);
-
-/*! @brief The function signature for window content refresh callbacks.
- *
- * This is the function signature for window refresh callback functions.
- *
- * @param[in] window The window whose content needs to be refreshed.
- *
- * @sa glfwSetWindowRefreshCallback
- *
- * @ingroup window
- */
-typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
-
-/*! @brief The function signature for window focus/defocus callbacks.
- *
- * This is the function signature for window focus callback functions.
- *
- * @param[in] window The window that gained or lost input focus.
- * @param[in] focused `GL_TRUE` if the window was given input focus, or
- * `GL_FALSE` if it lost it.
- *
- * @sa glfwSetWindowFocusCallback
- *
- * @ingroup window
- */
-typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
-
-/*! @brief The function signature for window iconify/restore callbacks.
- *
- * This is the function signature for window iconify/restore callback
- * functions.
- *
- * @param[in] window The window that was iconified or restored.
- * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE`
- * if it was restored.
- *
- * @sa glfwSetWindowIconifyCallback
- *
- * @ingroup window
- */
-typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
-
-/*! @brief The function signature for framebuffer resize callbacks.
- *
- * This is the function signature for framebuffer resize callback
- * functions.
- *
- * @param[in] window The window whose framebuffer was resized.
- * @param[in] width The new width, in pixels, of the framebuffer.
- * @param[in] height The new height, in pixels, of the framebuffer.
- *
- * @sa glfwSetFramebufferSizeCallback
- *
- * @ingroup window
- */
-typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
-
-/*! @brief The function signature for mouse button callbacks.
- *
- * This is the function signature for mouse button callback functions.
- *
- * @param[in] window The window that received the event.
- * @param[in] button The [mouse button](@ref buttons) that was pressed or
- * released.
- * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.
- * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
- * held down.
- *
- * @sa glfwSetMouseButtonCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
-
-/*! @brief The function signature for cursor position callbacks.
- *
- * This is the function signature for cursor position callback functions.
- *
- * @param[in] window The window that received the event.
- * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor.
- * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor.
- *
- * @sa glfwSetCursorPosCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
-
-/*! @brief The function signature for cursor enter/leave callbacks.
- *
- * This is the function signature for cursor enter/leave callback functions.
- *
- * @param[in] window The window that received the event.
- * @param[in] entered `GL_TRUE` if the cursor entered the window's client
- * area, or `GL_FALSE` if it left it.
- *
- * @sa glfwSetCursorEnterCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
-
-/*! @brief The function signature for scroll callbacks.
- *
- * This is the function signature for scroll callback functions.
- *
- * @param[in] window The window that received the event.
- * @param[in] xoffset The scroll offset along the x-axis.
- * @param[in] yoffset The scroll offset along the y-axis.
- *
- * @sa glfwSetScrollCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
-
-/*! @brief The function signature for keyboard key callbacks.
- *
- * This is the function signature for keyboard key callback functions.
- *
- * @param[in] window The window that received the event.
- * @param[in] key The [keyboard key](@ref keys) that was pressed or released.
- * @param[in] scancode The system-specific scancode of the key.
- * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
- * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
- * held down.
- *
- * @sa glfwSetKeyCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);
-
-/*! @brief The function signature for Unicode character callbacks.
- *
- * This is the function signature for Unicode character callback functions.
- *
- * @param[in] window The window that received the event.
- * @param[in] codepoint The Unicode code point of the character.
- *
- * @sa glfwSetCharCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);
-
-/*! @brief The function signature for Unicode character with modifiers
- * callbacks.
- *
- * This is the function signature for Unicode character with modifiers callback
- * functions. It is called for each input character, regardless of what
- * modifier keys are held down.
- *
- * @param[in] window The window that received the event.
- * @param[in] codepoint The Unicode code point of the character.
- * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
- * held down.
- *
- * @sa glfwSetCharModsCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
-
-/*! @brief The function signature for file drop callbacks.
- *
- * This is the function signature for file drop callbacks.
- *
- * @param[in] window The window that received the event.
- * @param[in] count The number of dropped files.
- * @param[in] paths The UTF-8 encoded file and/or directory path names.
- *
- * @sa glfwSetDropCallback
- *
- * @ingroup input
- */
-typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
-
-/*! @brief The function signature for monitor configuration callbacks.
- *
- * This is the function signature for monitor configuration callback functions.
- *
- * @param[in] monitor The monitor that was connected or disconnected.
- * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
- *
- * @sa glfwSetMonitorCallback
- *
- * @ingroup monitor
- */
-typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
-
-/*! @brief Video mode type.
- *
- * This describes a single video mode.
- *
- * @ingroup monitor
- */
-typedef struct GLFWvidmode
-{
- /*! The width, in screen coordinates, of the video mode.
- */
- int width;
- /*! The height, in screen coordinates, of the video mode.
- */
- int height;
- /*! The bit depth of the red channel of the video mode.
- */
- int redBits;
- /*! The bit depth of the green channel of the video mode.
- */
- int greenBits;
- /*! The bit depth of the blue channel of the video mode.
- */
- int blueBits;
- /*! The refresh rate, in Hz, of the video mode.
- */
- int refreshRate;
-} GLFWvidmode;
-
-/*! @brief Gamma ramp.
- *
- * This describes the gamma ramp for a monitor.
- *
- * @sa glfwGetGammaRamp glfwSetGammaRamp
- *
- * @ingroup monitor
- */
-typedef struct GLFWgammaramp
-{
- /*! An array of value describing the response of the red channel.
- */
- unsigned short* red;
- /*! An array of value describing the response of the green channel.
- */
- unsigned short* green;
- /*! An array of value describing the response of the blue channel.
- */
- unsigned short* blue;
- /*! The number of elements in each array.
- */
- unsigned int size;
-} GLFWgammaramp;
-
-/*! @brief Image data.
- */
-typedef struct GLFWimage
-{
- /*! The width, in pixels, of this image.
- */
- int width;
- /*! The height, in pixels, of this image.
- */
- int height;
- /*! The pixel data of this image, arranged left-to-right, top-to-bottom.
- */
- unsigned char* pixels;
-} GLFWimage;
-
-
-/*************************************************************************
- * GLFW API functions
- *************************************************************************/
-
-/*! @brief Initializes the GLFW library.
- *
- * This function initializes the GLFW library. Before most GLFW functions can
- * be used, GLFW must be initialized, and before an application terminates GLFW
- * should be terminated in order to free any resources allocated during or
- * after initialization.
- *
- * If this function fails, it calls @ref glfwTerminate before returning. If it
- * succeeds, you should call @ref glfwTerminate before the application exits.
- *
- * Additional calls to this function after successful initialization but before
- * termination will return `GL_TRUE` immediately.
- *
- * @return `GL_TRUE` if successful, or `GL_FALSE` if an
- * [error](@ref error_handling) occurred.
- *
- * @remarks __OS X:__ This function will change the current directory of the
- * application to the `Contents/Resources` subdirectory of the application's
- * bundle, if present. This can be disabled with a
- * [compile-time option](@ref compile_options_osx).
- *
- * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to
- * `"C"` then the environment's locale will be applied to that category. This
- * is done because character input will not function when `LC_CTYPE` is set to
- * `"C"`. If another locale was set before this function was called, it will
- * be left untouched.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref intro_init
- * @sa glfwTerminate
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup init
- */
-GLFWAPI int glfwInit(void);
-
-/*! @brief Terminates the GLFW library.
- *
- * This function destroys all remaining windows and cursors, restores any
- * modified gamma ramps and frees any other allocated resources. Once this
- * function is called, you must again call @ref glfwInit successfully before
- * you will be able to use most GLFW functions.
- *
- * If GLFW has been successfully initialized, this function should be called
- * before the application exits. If initialization fails, there is no need to
- * call this function, as it is called by @ref glfwInit before it returns
- * failure.
- *
- * @remarks This function may be called before @ref glfwInit.
- *
- * @warning No window's context may be current on another thread when this
- * function is called.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref intro_init
- * @sa glfwInit
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup init
- */
-GLFWAPI void glfwTerminate(void);
-
-/*! @brief Retrieves the version of the GLFW library.
- *
- * This function retrieves the major, minor and revision numbers of the GLFW
- * library. It is intended for when you are using GLFW as a shared library and
- * want to ensure that you are using the minimum required version.
- *
- * Any or all of the version arguments may be `NULL`. This function always
- * succeeds.
- *
- * @param[out] major Where to store the major version number, or `NULL`.
- * @param[out] minor Where to store the minor version number, or `NULL`.
- * @param[out] rev Where to store the revision number, or `NULL`.
- *
- * @remarks This function may be called before @ref glfwInit.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref intro_version
- * @sa glfwGetVersionString
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup init
- */
-GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);
-
-/*! @brief Returns a string describing the compile-time configuration.
- *
- * This function returns the compile-time generated
- * [version string](@ref intro_version_string) of the GLFW library binary. It
- * describes the version, platform, compiler and any platform-specific
- * compile-time options.
- *
- * __Do not use the version string__ to parse the GLFW library version. The
- * @ref glfwGetVersion function already provides the version of the running
- * library binary.
- *
- * This function always succeeds.
- *
- * @return The GLFW version string.
- *
- * @remarks This function may be called before @ref glfwInit.
- *
- * @par Pointer Lifetime
- * The returned string is static and compile-time generated.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref intro_version
- * @sa glfwGetVersion
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup init
- */
-GLFWAPI const char* glfwGetVersionString(void);
-
-/*! @brief Sets the error callback.
- *
- * This function sets the error callback, which is called with an error code
- * and a human-readable description each time a GLFW error occurs.
- *
- * The error callback is called on the thread where the error occurred. If you
- * are using GLFW from multiple threads, your error callback needs to be
- * written accordingly.
- *
- * Because the description string may have been generated specifically for that
- * error, it is not guaranteed to be valid after the callback has returned. If
- * you wish to use it after the callback returns, you need to make a copy.
- *
- * Once set, the error callback remains set even after the library has been
- * terminated.
- *
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set.
- *
- * @remarks This function may be called before @ref glfwInit.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref error_handling
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup init
- */
-GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);
-
-/*! @brief Returns the currently connected monitors.
- *
- * This function returns an array of handles for all currently connected
- * monitors.
- *
- * @param[out] count Where to store the number of monitors in the returned
- * array. This is set to zero if an error occurred.
- * @return An array of monitor handles, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Pointer Lifetime
- * The returned array is allocated and freed by GLFW. You should not free it
- * yourself. It is guaranteed to be valid only until the monitor configuration
- * changes or the library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_monitors
- * @sa @ref monitor_event
- * @sa glfwGetPrimaryMonitor
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);
-
-/*! @brief Returns the primary monitor.
- *
- * This function returns the primary monitor. This is usually the monitor
- * where elements like the Windows task bar or the OS X menu bar is located.
- *
- * @return The primary monitor, or `NULL` if an [error](@ref error_handling)
- * occurred.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_monitors
- * @sa glfwGetMonitors
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);
-
-/*! @brief Returns the position of the monitor's viewport on the virtual screen.
- *
- * This function returns the position, in screen coordinates, of the upper-left
- * corner of the specified monitor.
- *
- * Any or all of the position arguments may be `NULL`. If an error occurs, all
- * non-`NULL` position arguments will be set to zero.
- *
- * @param[in] monitor The monitor to query.
- * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.
- * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_properties
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
-
-/*! @brief Returns the physical size of the monitor.
- *
- * This function returns the size, in millimetres, of the display area of the
- * specified monitor.
- *
- * Some systems do not provide accurate monitor size information, either
- * because the monitor
- * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data)
- * data is incorrect or because the driver does not report it accurately.
- *
- * Any or all of the size arguments may be `NULL`. If an error occurs, all
- * non-`NULL` size arguments will be set to zero.
- *
- * @param[in] monitor The monitor to query.
- * @param[out] widthMM Where to store the width, in millimetres, of the
- * monitor's display area, or `NULL`.
- * @param[out] heightMM Where to store the height, in millimetres, of the
- * monitor's display area, or `NULL`.
- *
- * @remarks __Windows:__ The OS calculates the returned physical size from the
- * current resolution and system DPI instead of querying the monitor EDID data.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_properties
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM);
-
-/*! @brief Returns the name of the specified monitor.
- *
- * This function returns a human-readable name, encoded as UTF-8, of the
- * specified monitor. The name typically reflects the make and model of the
- * monitor and is not guaranteed to be unique among the connected monitors.
- *
- * @param[in] monitor The monitor to query.
- * @return The UTF-8 encoded name of the monitor, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Pointer Lifetime
- * The returned string is allocated and freed by GLFW. You should not free it
- * yourself. It is valid until the specified monitor is disconnected or the
- * library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_properties
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
-
-/*! @brief Sets the monitor configuration callback.
- *
- * This function sets the monitor configuration callback, or removes the
- * currently set callback. This is called when a monitor is connected to or
- * disconnected from the system.
- *
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @bug __X11:__ This callback is not yet called on monitor configuration
- * changes.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_event
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun);
-
-/*! @brief Returns the available video modes for the specified monitor.
- *
- * This function returns an array of all video modes supported by the specified
- * monitor. The returned array is sorted in ascending order, first by color
- * bit depth (the sum of all channel depths) and then by resolution area (the
- * product of width and height).
- *
- * @param[in] monitor The monitor to query.
- * @param[out] count Where to store the number of video modes in the returned
- * array. This is set to zero if an error occurred.
- * @return An array of video modes, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Pointer Lifetime
- * The returned array is allocated and freed by GLFW. You should not free it
- * yourself. It is valid until the specified monitor is disconnected, this
- * function is called again for that monitor or the library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_modes
- * @sa glfwGetVideoMode
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Changed to return an array of modes for a specific monitor.
- *
- * @ingroup monitor
- */
-GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count);
-
-/*! @brief Returns the current mode of the specified monitor.
- *
- * This function returns the current video mode of the specified monitor. If
- * you have created a full screen window for that monitor, the return value
- * will depend on whether that window is iconified.
- *
- * @param[in] monitor The monitor to query.
- * @return The current mode of the monitor, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Pointer Lifetime
- * The returned array is allocated and freed by GLFW. You should not free it
- * yourself. It is valid until the specified monitor is disconnected or the
- * library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_modes
- * @sa glfwGetVideoModes
- *
- * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`.
- *
- * @ingroup monitor
- */
-GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
-
-/*! @brief Generates a gamma ramp and sets it for the specified monitor.
- *
- * This function generates a 256-element gamma ramp from the specified exponent
- * and then calls @ref glfwSetGammaRamp with it. The value must be a finite
- * number greater than zero.
- *
- * @param[in] monitor The monitor whose gamma ramp to set.
- * @param[in] gamma The desired exponent.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_gamma
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
-
-/*! @brief Returns the current gamma ramp for the specified monitor.
- *
- * This function returns the current gamma ramp of the specified monitor.
- *
- * @param[in] monitor The monitor to query.
- * @return The current gamma ramp, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Pointer Lifetime
- * The returned structure and its arrays are allocated and freed by GLFW. You
- * should not free them yourself. They are valid until the specified monitor
- * is disconnected, this function is called again for that monitor or the
- * library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_gamma
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
-
-/*! @brief Sets the current gamma ramp for the specified monitor.
- *
- * This function sets the current gamma ramp for the specified monitor. The
- * original gamma ramp for that monitor is saved by GLFW the first time this
- * function is called and is restored by @ref glfwTerminate.
- *
- * @param[in] monitor The monitor whose gamma ramp to set.
- * @param[in] ramp The gamma ramp to use.
- *
- * @remarks Gamma ramp sizes other than 256 are not supported by all platforms
- * or graphics hardware.
- *
- * @remarks __Windows:__ The gamma ramp size must be 256.
- *
- * @par Pointer Lifetime
- * The specified gamma ramp is copied before this function returns.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref monitor_gamma
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup monitor
- */
-GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);
-
-/*! @brief Resets all window hints to their default values.
- *
- * This function resets all window hints to their
- * [default values](@ref window_hints_values).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_hints
- * @sa glfwWindowHint
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwDefaultWindowHints(void);
-
-/*! @brief Sets the specified window hint to the desired value.
- *
- * This function sets hints for the next call to @ref glfwCreateWindow. The
- * hints, once set, retain their values until changed by a call to @ref
- * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is
- * terminated.
- *
- * @param[in] target The [window hint](@ref window_hints) to set.
- * @param[in] hint The new value of the window hint.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_hints
- * @sa glfwDefaultWindowHints
- *
- * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`.
- *
- * @ingroup window
- */
-GLFWAPI void glfwWindowHint(int target, int hint);
-
-/*! @brief Creates a window and its associated context.
- *
- * This function creates a window and its associated OpenGL or OpenGL ES
- * context. Most of the options controlling how the window and its context
- * should be created are specified with [window hints](@ref window_hints).
- *
- * Successful creation does not change which context is current. Before you
- * can use the newly created context, you need to
- * [make it current](@ref context_current). For information about the `share`
- * parameter, see @ref context_sharing.
- *
- * The created window, framebuffer and context may differ from what you
- * requested, as not all parameters and hints are
- * [hard constraints](@ref window_hints_hard). This includes the size of the
- * window, especially for full screen windows. To query the actual attributes
- * of the created window, framebuffer and context, use queries like @ref
- * glfwGetWindowAttrib and @ref glfwGetWindowSize.
- *
- * To create a full screen window, you need to specify the monitor the window
- * will cover. If no monitor is specified, windowed mode will be used. Unless
- * you have a way for the user to choose a specific monitor, it is recommended
- * that you pick the primary monitor. For more information on how to query
- * connected monitors, see @ref monitor_monitors.
- *
- * For full screen windows, the specified size becomes the resolution of the
- * window's _desired video mode_. As long as a full screen window has input
- * focus, the supported video mode most closely matching the desired video mode
- * is set for the specified monitor. For more information about full screen
- * windows, including the creation of so called _windowed full screen_ or
- * _borderless full screen_ windows, see @ref window_windowed_full_screen.
- *
- * By default, newly created windows use the placement recommended by the
- * window system. To create the window at a specific position, make it
- * initially invisible using the [GLFW_VISIBLE](@ref window_hints_wnd) window
- * hint, set its [position](@ref window_pos) and then [show](@ref window_hide)
- * it.
- *
- * If a full screen window has input focus, the screensaver is prohibited from
- * starting.
- *
- * Window systems put limits on window sizes. Very large or very small window
- * dimensions may be overridden by the window system on creation. Check the
- * actual [size](@ref window_size) after creation.
- *
- * The [swap interval](@ref buffer_swap) is not set during window creation and
- * the initial value may vary depending on driver settings and defaults.
- *
- * @param[in] width The desired width, in screen coordinates, of the window.
- * This must be greater than zero.
- * @param[in] height The desired height, in screen coordinates, of the window.
- * This must be greater than zero.
- * @param[in] title The initial, UTF-8 encoded window title.
- * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use
- * windowed mode.
- * @param[in] share The window whose context to share resources with, or `NULL`
- * to not share resources.
- * @return The handle of the created window, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @remarks __Windows:__ Window creation will fail if the Microsoft GDI
- * software OpenGL implementation is the only one available.
- *
- * @remarks __Windows:__ If the executable has an icon resource named
- * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is
- * present, the `IDI_WINLOGO` icon will be used instead.
- *
- * @remarks __Windows:__ The context to share resources with may not be current
- * on any other thread.
- *
- * @remarks __OS X:__ The GLFW window has no icon, as it is not a document
- * window, but the dock icon will be the same as the application bundle's icon.
- * For more information on bundles, see the
- * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
- * in the Mac Developer Library.
- *
- * @remarks __OS X:__ The first time a window is created the menu bar is
- * populated with common commands like Hide, Quit and About. The About entry
- * opens a minimal about dialog with information from the application's bundle.
- * The menu bar can be disabled with a
- * [compile-time option](@ref compile_options_osx).
- *
- * @remarks __OS X:__ On OS X 10.10 and later the window frame will not be
- * rendered at full resolution on Retina displays unless the
- * `NSHighResolutionCapable` key is enabled in the application bundle's
- * `Info.plist`. For more information, see
- * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
- * in the Mac Developer Library.
- *
- * @remarks __X11:__ There is no mechanism for setting the window icon yet.
- *
- * @remarks __X11:__ Some window managers will not respect the placement of
- * initially hidden windows.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_creation
- * @sa glfwDestroyWindow
- *
- * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`.
- *
- * @ingroup window
- */
-GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
-
-/*! @brief Destroys the specified window and its context.
- *
- * This function destroys the specified window and its context. On calling
- * this function, no further callbacks will be called for that window.
- *
- * If the context of the specified window is current on the main thread, it is
- * detached before being destroyed.
- *
- * @param[in] window The window to destroy.
- *
- * @note The context of the specified window must not be current on any other
- * thread when this function is called.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_creation
- * @sa glfwCreateWindow
- *
- * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`.
- *
- * @ingroup window
- */
-GLFWAPI void glfwDestroyWindow(GLFWwindow* window);
-
-/*! @brief Checks the close flag of the specified window.
- *
- * This function returns the value of the close flag of the specified window.
- *
- * @param[in] window The window to query.
- * @return The value of the close flag.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @sa @ref window_close
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI int glfwWindowShouldClose(GLFWwindow* window);
-
-/*! @brief Sets the close flag of the specified window.
- *
- * This function sets the value of the close flag of the specified window.
- * This can be used to override the user's attempt to close the window, or
- * to signal that it should be closed.
- *
- * @param[in] window The window whose flag to change.
- * @param[in] value The new value.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @sa @ref window_close
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
-
-/*! @brief Sets the title of the specified window.
- *
- * This function sets the window title, encoded as UTF-8, of the specified
- * window.
- *
- * @param[in] window The window whose title to change.
- * @param[in] title The UTF-8 encoded window title.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_title
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup window
- */
-GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
-
-/*! @brief Retrieves the position of the client area of the specified window.
- *
- * This function retrieves the position, in screen coordinates, of the
- * upper-left corner of the client area of the specified window.
- *
- * Any or all of the position arguments may be `NULL`. If an error occurs, all
- * non-`NULL` position arguments will be set to zero.
- *
- * @param[in] window The window to query.
- * @param[out] xpos Where to store the x-coordinate of the upper-left corner of
- * the client area, or `NULL`.
- * @param[out] ypos Where to store the y-coordinate of the upper-left corner of
- * the client area, or `NULL`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_pos
- * @sa glfwSetWindowPos
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
-
-/*! @brief Sets the position of the client area of the specified window.
- *
- * This function sets the position, in screen coordinates, of the upper-left
- * corner of the client area of the specified windowed mode window. If the
- * window is a full screen window, this function does nothing.
- *
- * __Do not use this function__ to move an already visible window unless you
- * have very good reasons for doing so, as it will confuse and annoy the user.
- *
- * The window manager may put limits on what positions are allowed. GLFW
- * cannot and should not override these limits.
- *
- * @param[in] window The window to query.
- * @param[in] xpos The x-coordinate of the upper-left corner of the client area.
- * @param[in] ypos The y-coordinate of the upper-left corner of the client area.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_pos
- * @sa glfwGetWindowPos
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup window
- */
-GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
-
-/*! @brief Retrieves the size of the client area of the specified window.
- *
- * This function retrieves the size, in screen coordinates, of the client area
- * of the specified window. If you wish to retrieve the size of the
- * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
- *
- * Any or all of the size arguments may be `NULL`. If an error occurs, all
- * non-`NULL` size arguments will be set to zero.
- *
- * @param[in] window The window whose size to retrieve.
- * @param[out] width Where to store the width, in screen coordinates, of the
- * client area, or `NULL`.
- * @param[out] height Where to store the height, in screen coordinates, of the
- * client area, or `NULL`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_size
- * @sa glfwSetWindowSize
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup window
- */
-GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
-
-/*! @brief Sets the size of the client area of the specified window.
- *
- * This function sets the size, in screen coordinates, of the client area of
- * the specified window.
- *
- * For full screen windows, this function selects and switches to the resolution
- * closest to the specified size, without affecting the window's context. As
- * the context is unaffected, the bit depths of the framebuffer remain
- * unchanged.
- *
- * The window manager may put limits on what sizes are allowed. GLFW cannot
- * and should not override these limits.
- *
- * @param[in] window The window to resize.
- * @param[in] width The desired width of the specified window.
- * @param[in] height The desired height of the specified window.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_size
- * @sa glfwGetWindowSize
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup window
- */
-GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height);
-
-/*! @brief Retrieves the size of the framebuffer of the specified window.
- *
- * This function retrieves the size, in pixels, of the framebuffer of the
- * specified window. If you wish to retrieve the size of the window in screen
- * coordinates, see @ref glfwGetWindowSize.
- *
- * Any or all of the size arguments may be `NULL`. If an error occurs, all
- * non-`NULL` size arguments will be set to zero.
- *
- * @param[in] window The window whose framebuffer to query.
- * @param[out] width Where to store the width, in pixels, of the framebuffer,
- * or `NULL`.
- * @param[out] height Where to store the height, in pixels, of the framebuffer,
- * or `NULL`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_fbsize
- * @sa glfwSetFramebufferSizeCallback
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height);
-
-/*! @brief Retrieves the size of the frame of the window.
- *
- * This function retrieves the size, in screen coordinates, of each edge of the
- * frame of the specified window. This size includes the title bar, if the
- * window has one. The size of the frame may vary depending on the
- * [window-related hints](@ref window_hints_wnd) used to create it.
- *
- * Because this function retrieves the size of each window frame edge and not
- * the offset along a particular coordinate axis, the retrieved values will
- * always be zero or positive.
- *
- * Any or all of the size arguments may be `NULL`. If an error occurs, all
- * non-`NULL` size arguments will be set to zero.
- *
- * @param[in] window The window whose frame size to query.
- * @param[out] left Where to store the size, in screen coordinates, of the left
- * edge of the window frame, or `NULL`.
- * @param[out] top Where to store the size, in screen coordinates, of the top
- * edge of the window frame, or `NULL`.
- * @param[out] right Where to store the size, in screen coordinates, of the
- * right edge of the window frame, or `NULL`.
- * @param[out] bottom Where to store the size, in screen coordinates, of the
- * bottom edge of the window frame, or `NULL`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_size
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup window
- */
-GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom);
-
-/*! @brief Iconifies the specified window.
- *
- * This function iconifies (minimizes) the specified window if it was
- * previously restored. If the window is already iconified, this function does
- * nothing.
- *
- * If the specified window is a full screen window, the original monitor
- * resolution is restored until the window is restored.
- *
- * @param[in] window The window to iconify.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_iconify
- * @sa glfwRestoreWindow
- *
- * @since Added in GLFW 2.1.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup window
- */
-GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
-
-/*! @brief Restores the specified window.
- *
- * This function restores the specified window if it was previously iconified
- * (minimized). If the window is already restored, this function does nothing.
- *
- * If the specified window is a full screen window, the resolution chosen for
- * the window is restored on the selected monitor.
- *
- * @param[in] window The window to restore.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_iconify
- * @sa glfwIconifyWindow
- *
- * @since Added in GLFW 2.1.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup window
- */
-GLFWAPI void glfwRestoreWindow(GLFWwindow* window);
-
-/*! @brief Makes the specified window visible.
- *
- * This function makes the specified window visible if it was previously
- * hidden. If the window is already visible or is in full screen mode, this
- * function does nothing.
- *
- * @param[in] window The window to make visible.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_hide
- * @sa glfwHideWindow
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwShowWindow(GLFWwindow* window);
-
-/*! @brief Hides the specified window.
- *
- * This function hides the specified window if it was previously visible. If
- * the window is already hidden or is in full screen mode, this function does
- * nothing.
- *
- * @param[in] window The window to hide.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_hide
- * @sa glfwShowWindow
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwHideWindow(GLFWwindow* window);
-
-/*! @brief Returns the monitor that the window uses for full screen mode.
- *
- * This function returns the handle of the monitor that the specified window is
- * in full screen on.
- *
- * @param[in] window The window to query.
- * @return The monitor, or `NULL` if the window is in windowed mode or an error
- * occurred.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_monitor
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
-
-/*! @brief Returns an attribute of the specified window.
- *
- * This function returns the value of an attribute of the specified window or
- * its OpenGL or OpenGL ES context.
- *
- * @param[in] window The window to query.
- * @param[in] attrib The [window attribute](@ref window_attribs) whose value to
- * return.
- * @return The value of the attribute, or zero if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_attribs
- *
- * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and
- * `glfwGetGLVersion`.
- *
- * @ingroup window
- */
-GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
-
-/*! @brief Sets the user pointer of the specified window.
- *
- * This function sets the user-defined pointer of the specified window. The
- * current value is retained until the window is destroyed. The initial value
- * is `NULL`.
- *
- * @param[in] window The window whose pointer to set.
- * @param[in] pointer The new value.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @sa @ref window_userptr
- * @sa glfwGetWindowUserPointer
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer);
-
-/*! @brief Returns the user pointer of the specified window.
- *
- * This function returns the current value of the user-defined pointer of the
- * specified window. The initial value is `NULL`.
- *
- * @param[in] window The window whose pointer to return.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @sa @ref window_userptr
- * @sa glfwSetWindowUserPointer
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
-
-/*! @brief Sets the position callback for the specified window.
- *
- * This function sets the position callback of the specified window, which is
- * called when the window is moved. The callback is provided with the screen
- * position of the upper-left corner of the client area of the window.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_pos
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun cbfun);
-
-/*! @brief Sets the size callback for the specified window.
- *
- * This function sets the size callback of the specified window, which is
- * called when the window is resized. The callback is provided with the size,
- * in screen coordinates, of the client area of the window.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_size
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter. Updated callback signature.
- *
- * @ingroup window
- */
-GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun cbfun);
-
-/*! @brief Sets the close callback for the specified window.
- *
- * This function sets the close callback of the specified window, which is
- * called when the user attempts to close the window, for example by clicking
- * the close widget in the title bar.
- *
- * The close flag is set before this callback is called, but you can modify it
- * at any time with @ref glfwSetWindowShouldClose.
- *
- * The close callback is not triggered by @ref glfwDestroyWindow.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @remarks __OS X:__ Selecting Quit from the application menu will
- * trigger the close callback for all windows.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_close
- *
- * @since Added in GLFW 2.5.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter. Updated callback signature.
- *
- * @ingroup window
- */
-GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun cbfun);
-
-/*! @brief Sets the refresh callback for the specified window.
- *
- * This function sets the refresh callback of the specified window, which is
- * called when the client area of the window needs to be redrawn, for example
- * if the window has been exposed after having been covered by another window.
- *
- * On compositing window systems such as Aero, Compiz or Aqua, where the window
- * contents are saved off-screen, this callback may be called only very
- * infrequently or never at all.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_refresh
- *
- * @since Added in GLFW 2.5.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter. Updated callback signature.
- *
- * @ingroup window
- */
-GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun cbfun);
-
-/*! @brief Sets the focus callback for the specified window.
- *
- * This function sets the focus callback of the specified window, which is
- * called when the window gains or loses input focus.
- *
- * After the focus callback is called for a window that lost input focus,
- * synthetic key and mouse button release events will be generated for all such
- * that had been pressed. For more information, see @ref glfwSetKeyCallback
- * and @ref glfwSetMouseButtonCallback.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_focus
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun);
-
-/*! @brief Sets the iconify callback for the specified window.
- *
- * This function sets the iconification callback of the specified window, which
- * is called when the window is iconified or restored.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_iconify
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun);
-
-/*! @brief Sets the framebuffer resize callback for the specified window.
- *
- * This function sets the framebuffer resize callback of the specified window,
- * which is called when the framebuffer of the specified window is resized.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref window_fbsize
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup window
- */
-GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
-
-/*! @brief Processes all pending events.
- *
- * This function processes only those events that are already in the event
- * queue and then returns immediately. Processing events will cause the window
- * and input callbacks associated with those events to be called.
- *
- * On some platforms, a window move, resize or menu operation will cause event
- * processing to block. This is due to how event processing is designed on
- * those platforms. You can use the
- * [window refresh callback](@ref window_refresh) to redraw the contents of
- * your window when necessary during such operations.
- *
- * On some platforms, certain events are sent directly to the application
- * without going through the event queue, causing callbacks to be called
- * outside of a call to one of the event processing functions.
- *
- * Event processing is not required for joystick input to work.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref events
- * @sa glfwWaitEvents
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup window
- */
-GLFWAPI void glfwPollEvents(void);
-
-/*! @brief Waits until events are queued and processes them.
- *
- * This function puts the calling thread to sleep until at least one event is
- * available in the event queue. Once one or more events are available,
- * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue
- * are processed and the function then returns immediately. Processing events
- * will cause the window and input callbacks associated with those events to be
- * called.
- *
- * Since not all events are associated with callbacks, this function may return
- * without a callback having been called even if you are monitoring all
- * callbacks.
- *
- * On some platforms, a window move, resize or menu operation will cause event
- * processing to block. This is due to how event processing is designed on
- * those platforms. You can use the
- * [window refresh callback](@ref window_refresh) to redraw the contents of
- * your window when necessary during such operations.
- *
- * On some platforms, certain callbacks may be called outside of a call to one
- * of the event processing functions.
- *
- * If no windows exist, this function returns immediately. For synchronization
- * of threads in applications that do not create windows, use your threading
- * library of choice.
- *
- * Event processing is not required for joystick input to work.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref events
- * @sa glfwPollEvents
- *
- * @since Added in GLFW 2.5.
- *
- * @ingroup window
- */
-GLFWAPI void glfwWaitEvents(void);
-
-/*! @brief Posts an empty event to the event queue.
- *
- * This function posts an empty event from the current thread to the event
- * queue, causing @ref glfwWaitEvents to return.
- *
- * If no windows exist, this function returns immediately. For synchronization
- * of threads in applications that do not create windows, use your threading
- * library of choice.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref events
- * @sa glfwWaitEvents
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup window
- */
-GLFWAPI void glfwPostEmptyEvent(void);
-
-/*! @brief Returns the value of an input option for the specified window.
- *
- * This function returns the value of an input option for the specified window.
- * The mode must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
- * `GLFW_STICKY_MOUSE_BUTTONS`.
- *
- * @param[in] window The window to query.
- * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
- * `GLFW_STICKY_MOUSE_BUTTONS`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa glfwSetInputMode
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup input
- */
-GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
-
-/*! @brief Sets an input option for the specified window.
- *
- * This function sets an input mode option for the specified window. The mode
- * must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
- * `GLFW_STICKY_MOUSE_BUTTONS`.
- *
- * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
- * modes:
- * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally.
- * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client
- * area of the window but does not restrict the cursor from leaving.
- * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual
- * and unlimited cursor movement. This is useful for implementing for
- * example 3D camera controls.
- *
- * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to
- * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are
- * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`
- * the next time it is called even if the key had been released before the
- * call. This is useful when you are only interested in whether keys have been
- * pressed but not when or in which order.
- *
- * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either
- * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If
- * sticky mouse buttons are enabled, a mouse button press will ensure that @ref
- * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if
- * the mouse button had been released before the call. This is useful when you
- * are only interested in whether mouse buttons have been pressed but not when
- * or in which order.
- *
- * @param[in] window The window whose input mode to set.
- * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
- * `GLFW_STICKY_MOUSE_BUTTONS`.
- * @param[in] value The new value of the specified input mode.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa glfwGetInputMode
- *
- * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`.
- *
- * @ingroup input
- */
-GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
-
-/*! @brief Returns the last reported state of a keyboard key for the specified
- * window.
- *
- * This function returns the last state reported for the specified key to the
- * specified window. The returned state is one of `GLFW_PRESS` or
- * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to
- * the key callback.
- *
- * If the `GLFW_STICKY_KEYS` input mode is enabled, this function returns
- * `GLFW_PRESS` the first time you call it for a key that was pressed, even if
- * that key has already been released.
- *
- * The key functions deal with physical keys, with [key tokens](@ref keys)
- * named after their use on the standard US keyboard layout. If you want to
- * input text, use the Unicode character callback instead.
- *
- * The [modifier key bit masks](@ref mods) are not key tokens and cannot be
- * used with this function.
- *
- * @param[in] window The desired window.
- * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is
- * not a valid key for this function.
- * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref input_key
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup input
- */
-GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
-
-/*! @brief Returns the last reported state of a mouse button for the specified
- * window.
- *
- * This function returns the last state reported for the specified mouse button
- * to the specified window. The returned state is one of `GLFW_PRESS` or
- * `GLFW_RELEASE`.
- *
- * If the `GLFW_STICKY_MOUSE_BUTTONS` input mode is enabled, this function
- * `GLFW_PRESS` the first time you call it for a mouse button that was pressed,
- * even if that mouse button has already been released.
- *
- * @param[in] window The desired window.
- * @param[in] button The desired [mouse button](@ref buttons).
- * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref input_mouse_button
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup input
- */
-GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
-
-/*! @brief Retrieves the position of the cursor relative to the client area of
- * the window.
- *
- * This function returns the position of the cursor, in screen coordinates,
- * relative to the upper-left corner of the client area of the specified
- * window.
- *
- * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
- * position is unbounded and limited only by the minimum and maximum values of
- * a `double`.
- *
- * The coordinate can be converted to their integer equivalents with the
- * `floor` function. Casting directly to an integer type works for positive
- * coordinates, but fails for negative ones.
- *
- * Any or all of the position arguments may be `NULL`. If an error occurs, all
- * non-`NULL` position arguments will be set to zero.
- *
- * @param[in] window The desired window.
- * @param[out] xpos Where to store the cursor x-coordinate, relative to the
- * left edge of the client area, or `NULL`.
- * @param[out] ypos Where to store the cursor y-coordinate, relative to the to
- * top edge of the client area, or `NULL`.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_pos
- * @sa glfwSetCursorPos
- *
- * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`.
- *
- * @ingroup input
- */
-GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
-
-/*! @brief Sets the position of the cursor, relative to the client area of the
- * window.
- *
- * This function sets the position, in screen coordinates, of the cursor
- * relative to the upper-left corner of the client area of the specified
- * window. The window must have input focus. If the window does not have
- * input focus when this function is called, it fails silently.
- *
- * __Do not use this function__ to implement things like camera controls. GLFW
- * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the
- * cursor, transparently re-centers it and provides unconstrained cursor
- * motion. See @ref glfwSetInputMode for more information.
- *
- * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is
- * unconstrained and limited only by the minimum and maximum values of
- * a `double`.
- *
- * @param[in] window The desired window.
- * @param[in] xpos The desired x-coordinate, relative to the left edge of the
- * client area.
- * @param[in] ypos The desired y-coordinate, relative to the top edge of the
- * client area.
- *
- * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it
- * may take a moment for the window focus event to arrive. This means you will
- * not be able to set the cursor position directly after window creation.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_pos
- * @sa glfwGetCursorPos
- *
- * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`.
- *
- * @ingroup input
- */
-GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
-
-/*! @brief Creates a custom cursor.
- *
- * Creates a new custom cursor image that can be set for a window with @ref
- * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.
- * Any remaining cursors are destroyed by @ref glfwTerminate.
- *
- * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They
- * are arranged canonically as packed sequential rows, starting from the
- * top-left corner.
- *
- * The cursor hotspot is specified in pixels, relative to the upper-left corner
- * of the cursor image. Like all other coordinate systems in GLFW, the X-axis
- * points to the right and the Y-axis points down.
- *
- * @param[in] image The desired cursor image.
- * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot.
- * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.
- *
- * @return The handle of the created cursor, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Pointer Lifetime
- * The specified image data is copied before this function returns.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_object
- * @sa glfwDestroyCursor
- * @sa glfwCreateStandardCursor
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup input
- */
-GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);
-
-/*! @brief Creates a cursor with a standard shape.
- *
- * Returns a cursor with a [standard shape](@ref shapes), that can be set for
- * a window with @ref glfwSetCursor.
- *
- * @param[in] shape One of the [standard shapes](@ref shapes).
- *
- * @return A new cursor ready to use or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_object
- * @sa glfwCreateCursor
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup input
- */
-GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);
-
-/*! @brief Destroys a cursor.
- *
- * This function destroys a cursor previously created with @ref
- * glfwCreateCursor. Any remaining cursors will be destroyed by @ref
- * glfwTerminate.
- *
- * @param[in] cursor The cursor object to destroy.
- *
- * @par Reentrancy
- * This function may not be called from a callback.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_object
- * @sa glfwCreateCursor
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup input
- */
-GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);
-
-/*! @brief Sets the cursor for the window.
- *
- * This function sets the cursor image to be used when the cursor is over the
- * client area of the specified window. The set cursor will only be visible
- * when the [cursor mode](@ref cursor_mode) of the window is
- * `GLFW_CURSOR_NORMAL`.
- *
- * On some platforms, the set cursor may not be visible unless the window also
- * has input focus.
- *
- * @param[in] window The window to set the cursor for.
- * @param[in] cursor The cursor to set, or `NULL` to switch back to the default
- * arrow cursor.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_object
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup input
- */
-GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
-
-/*! @brief Sets the key callback.
- *
- * This function sets the key callback of the specified window, which is called
- * when a key is pressed, repeated or released.
- *
- * The key functions deal with physical keys, with layout independent
- * [key tokens](@ref keys) named after their values in the standard US keyboard
- * layout. If you want to input text, use the
- * [character callback](@ref glfwSetCharCallback) instead.
- *
- * When a window loses input focus, it will generate synthetic key release
- * events for all pressed keys. You can tell these events from user-generated
- * events by the fact that the synthetic ones are generated after the focus
- * loss event has been processed, i.e. after the
- * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
- *
- * The scancode of a key is specific to that platform or sometimes even to that
- * machine. Scancodes are intended to allow users to bind keys that don't have
- * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their
- * state is not saved and so it cannot be queried with @ref glfwGetKey.
- *
- * Sometimes GLFW needs to generate synthetic key events, in which case the
- * scancode may be zero.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new key callback, or `NULL` to remove the currently
- * set callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref input_key
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter. Updated callback signature.
- *
- * @ingroup input
- */
-GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
-
-/*! @brief Sets the Unicode character callback.
- *
- * This function sets the character callback of the specified window, which is
- * called when a Unicode character is input.
- *
- * The character callback is intended for Unicode text input. As it deals with
- * characters, it is keyboard layout dependent, whereas the
- * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1
- * to physical keys, as a key may produce zero, one or more characters. If you
- * want to know whether a specific physical key was pressed or released, see
- * the key callback instead.
- *
- * The character callback behaves as system text input normally does and will
- * not be called if modifier keys are held down that would prevent normal text
- * input on that platform, for example a Super (Command) key on OS X or Alt key
- * on Windows. There is a
- * [character with modifiers callback](@ref glfwSetCharModsCallback) that
- * receives these events.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref input_char
- *
- * @since Added in GLFW 2.4.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter. Updated callback signature.
- *
- * @ingroup input
- */
-GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);
-
-/*! @brief Sets the Unicode character with modifiers callback.
- *
- * This function sets the character with modifiers callback of the specified
- * window, which is called when a Unicode character is input regardless of what
- * modifier keys are used.
- *
- * The character with modifiers callback is intended for implementing custom
- * Unicode character input. For regular Unicode text input, see the
- * [character callback](@ref glfwSetCharCallback). Like the character
- * callback, the character with modifiers callback deals with characters and is
- * keyboard layout dependent. Characters do not map 1:1 to physical keys, as
- * a key may produce zero, one or more characters. If you want to know whether
- * a specific physical key was pressed or released, see the
- * [key callback](@ref glfwSetKeyCallback) instead.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or an
- * error occurred.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref input_char
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup input
- */
-GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun);
-
-/*! @brief Sets the mouse button callback.
- *
- * This function sets the mouse button callback of the specified window, which
- * is called when a mouse button is pressed or released.
- *
- * When a window loses input focus, it will generate synthetic mouse button
- * release events for all pressed mouse buttons. You can tell these events
- * from user-generated events by the fact that the synthetic ones are generated
- * after the focus loss event has been processed, i.e. after the
- * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref input_mouse_button
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter. Updated callback signature.
- *
- * @ingroup input
- */
-GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun);
-
-/*! @brief Sets the cursor position callback.
- *
- * This function sets the cursor position callback of the specified window,
- * which is called when the cursor is moved. The callback is provided with the
- * position, in screen coordinates, relative to the upper-left corner of the
- * client area of the window.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_pos
- *
- * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`.
- *
- * @ingroup input
- */
-GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun cbfun);
-
-/*! @brief Sets the cursor enter/exit callback.
- *
- * This function sets the cursor boundary crossing callback of the specified
- * window, which is called when the cursor enters or leaves the client area of
- * the window.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new callback, or `NULL` to remove the currently set
- * callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref cursor_enter
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup input
- */
-GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun cbfun);
-
-/*! @brief Sets the scroll callback.
- *
- * This function sets the scroll callback of the specified window, which is
- * called when a scrolling device is used, such as a mouse wheel or scrolling
- * area of a touchpad.
- *
- * The scroll callback receives all scrolling input, like that from a mouse
- * wheel or a touchpad scrolling area.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently
- * set callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref scrolling
- *
- * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`.
- *
- * @ingroup input
- */
-GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun);
-
-/*! @brief Sets the file drop callback.
- *
- * This function sets the file drop callback of the specified window, which is
- * called when one or more dragged files are dropped on the window.
- *
- * Because the path array and its strings may have been generated specifically
- * for that event, they are not guaranteed to be valid after the callback has
- * returned. If you wish to use them after the callback returns, you need to
- * make a deep copy.
- *
- * @param[in] window The window whose callback to set.
- * @param[in] cbfun The new file drop callback, or `NULL` to remove the
- * currently set callback.
- * @return The previously set callback, or `NULL` if no callback was set or the
- * library had not been [initialized](@ref intro_init).
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref path_drop
- *
- * @since Added in GLFW 3.1.
- *
- * @ingroup input
- */
-GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
-
-/*! @brief Returns whether the specified joystick is present.
- *
- * This function returns whether the specified joystick is present.
- *
- * @param[in] joy The [joystick](@ref joysticks) to query.
- * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref joystick
- *
- * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`.
- *
- * @ingroup input
- */
-GLFWAPI int glfwJoystickPresent(int joy);
-
-/*! @brief Returns the values of all axes of the specified joystick.
- *
- * This function returns the values of all axes of the specified joystick.
- * Each element in the array is a value between -1.0 and 1.0.
- *
- * @param[in] joy The [joystick](@ref joysticks) to query.
- * @param[out] count Where to store the number of axis values in the returned
- * array. This is set to zero if an error occurred.
- * @return An array of axis values, or `NULL` if the joystick is not present.
- *
- * @par Pointer Lifetime
- * The returned array is allocated and freed by GLFW. You should not free it
- * yourself. It is valid until the specified joystick is disconnected, this
- * function is called again for that joystick or the library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref joystick_axis
- *
- * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`.
- *
- * @ingroup input
- */
-GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);
-
-/*! @brief Returns the state of all buttons of the specified joystick.
- *
- * This function returns the state of all buttons of the specified joystick.
- * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
- *
- * @param[in] joy The [joystick](@ref joysticks) to query.
- * @param[out] count Where to store the number of button states in the returned
- * array. This is set to zero if an error occurred.
- * @return An array of button states, or `NULL` if the joystick is not present.
- *
- * @par Pointer Lifetime
- * The returned array is allocated and freed by GLFW. You should not free it
- * yourself. It is valid until the specified joystick is disconnected, this
- * function is called again for that joystick or the library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref joystick_button
- *
- * @since Added in GLFW 2.2.
- *
- * @par
- * __GLFW 3:__ Changed to return a dynamic array.
- *
- * @ingroup input
- */
-GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);
-
-/*! @brief Returns the name of the specified joystick.
- *
- * This function returns the name, encoded as UTF-8, of the specified joystick.
- * The returned string is allocated and freed by GLFW. You should not free it
- * yourself.
- *
- * @param[in] joy The [joystick](@ref joysticks) to query.
- * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick
- * is not present.
- *
- * @par Pointer Lifetime
- * The returned string is allocated and freed by GLFW. You should not free it
- * yourself. It is valid until the specified joystick is disconnected, this
- * function is called again for that joystick or the library is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref joystick_name
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup input
- */
-GLFWAPI const char* glfwGetJoystickName(int joy);
-
-/*! @brief Sets the clipboard to the specified string.
- *
- * This function sets the system clipboard to the specified, UTF-8 encoded
- * string.
- *
- * @param[in] window The window that will own the clipboard contents.
- * @param[in] string A UTF-8 encoded string.
- *
- * @par Pointer Lifetime
- * The specified string is copied before this function returns.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref clipboard
- * @sa glfwGetClipboardString
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup input
- */
-GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
-
-/*! @brief Returns the contents of the clipboard as a string.
- *
- * This function returns the contents of the system clipboard, if it contains
- * or is convertible to a UTF-8 encoded string.
- *
- * @param[in] window The window that will request the clipboard contents.
- * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
- * if an [error](@ref error_handling) occurred.
- *
- * @par Pointer Lifetime
- * The returned string is allocated and freed by GLFW. You should not free it
- * yourself. It is valid until the next call to @ref
- * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
- * is terminated.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref clipboard
- * @sa glfwSetClipboardString
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup input
- */
-GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
-
-/*! @brief Returns the value of the GLFW timer.
- *
- * This function returns the value of the GLFW timer. Unless the timer has
- * been set using @ref glfwSetTime, the timer measures time elapsed since GLFW
- * was initialized.
- *
- * The resolution of the timer is system dependent, but is usually on the order
- * of a few micro- or nanoseconds. It uses the highest-resolution monotonic
- * time source on each supported platform.
- *
- * @return The current value, in seconds, or zero if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @sa @ref time
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup input
- */
-GLFWAPI double glfwGetTime(void);
-
-/*! @brief Sets the GLFW timer.
- *
- * This function sets the value of the GLFW timer. It then continues to count
- * up from that value. The value must be a positive finite number less than
- * or equal to 18446744073.0, which is approximately 584.5 years.
- *
- * @param[in] time The new value, in seconds.
- *
- * @remarks The upper limit of the timer is calculated as
- * floor((2<sup>64</sup> - 1) / 10<sup>9</sup>) and is due to implementations
- * storing nanoseconds in 64 bits. The limit may be increased in the future.
- *
- * @par Thread Safety
- * This function may only be called from the main thread.
- *
- * @sa @ref time
- *
- * @since Added in GLFW 2.2.
- *
- * @ingroup input
- */
-GLFWAPI void glfwSetTime(double time);
-
-/*! @brief Makes the context of the specified window current for the calling
- * thread.
- *
- * This function makes the OpenGL or OpenGL ES context of the specified window
- * current on the calling thread. A context can only be made current on
- * a single thread at a time and each thread can have only a single current
- * context at a time.
- *
- * By default, making a context non-current implicitly forces a pipeline flush.
- * On machines that support `GL_KHR_context_flush_control`, you can control
- * whether a context performs this flush by setting the
- * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint.
- *
- * @param[in] window The window whose context to make current, or `NULL` to
- * detach the current context.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref context_current
- * @sa glfwGetCurrentContext
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup context
- */
-GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);
-
-/*! @brief Returns the window whose context is current on the calling thread.
- *
- * This function returns the window whose OpenGL or OpenGL ES context is
- * current on the calling thread.
- *
- * @return The window whose context is current, or `NULL` if no window's
- * context is current.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref context_current
- * @sa glfwMakeContextCurrent
- *
- * @since Added in GLFW 3.0.
- *
- * @ingroup context
- */
-GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
-
-/*! @brief Swaps the front and back buffers of the specified window.
- *
- * This function swaps the front and back buffers of the specified window. If
- * the swap interval is greater than zero, the GPU driver waits the specified
- * number of screen updates before swapping the buffers.
- *
- * @param[in] window The window whose buffers to swap.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref buffer_swap
- * @sa glfwSwapInterval
- *
- * @since Added in GLFW 1.0.
- *
- * @par
- * __GLFW 3:__ Added window handle parameter.
- *
- * @ingroup window
- */
-GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
-
-/*! @brief Sets the swap interval for the current context.
- *
- * This function sets the swap interval for the current context, i.e. the
- * number of screen updates to wait from the time @ref glfwSwapBuffers was
- * called before swapping the buffers and returning. This is sometimes called
- * _vertical synchronization_, _vertical retrace synchronization_ or just
- * _vsync_.
- *
- * Contexts that support either of the `WGL_EXT_swap_control_tear` and
- * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals,
- * which allow the driver to swap even if a frame arrives a little bit late.
- * You can check for the presence of these extensions using @ref
- * glfwExtensionSupported. For more information about swap tearing, see the
- * extension specifications.
- *
- * A context must be current on the calling thread. Calling this function
- * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
- *
- * @param[in] interval The minimum number of screen updates to wait for
- * until the buffers are swapped by @ref glfwSwapBuffers.
- *
- * @remarks This function is not called during context creation, leaving the
- * swap interval set to whatever is the default on that platform. This is done
- * because some swap interval extensions used by GLFW do not allow the swap
- * interval to be reset to zero once it has been set to a non-zero value.
- *
- * @remarks Some GPU drivers do not honor the requested swap interval, either
- * because of a user setting that overrides the application's request or due to
- * bugs in the driver.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref buffer_swap
- * @sa glfwSwapBuffers
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup context
- */
-GLFWAPI void glfwSwapInterval(int interval);
-
-/*! @brief Returns whether the specified extension is available.
- *
- * This function returns whether the specified
- * [client API extension](@ref context_glext) is supported by the current
- * OpenGL or OpenGL ES context. It searches both for OpenGL and OpenGL ES
- * extension and platform-specific context creation API extensions.
- *
- * A context must be current on the calling thread. Calling this function
- * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
- *
- * As this functions retrieves and searches one or more extension strings each
- * call, it is recommended that you cache its results if it is going to be used
- * frequently. The extension strings will not change during the lifetime of
- * a context, so there is no danger in doing this.
- *
- * @param[in] extension The ASCII encoded name of the extension.
- * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref context_glext
- * @sa glfwGetProcAddress
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup context
- */
-GLFWAPI int glfwExtensionSupported(const char* extension);
-
-/*! @brief Returns the address of the specified function for the current
- * context.
- *
- * This function returns the address of the specified
- * [core or extension function](@ref context_glext), if it is supported
- * by the current context.
- *
- * A context must be current on the calling thread. Calling this function
- * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
- *
- * @param[in] procname The ASCII encoded name of the function.
- * @return The address of the function, or `NULL` if the function is
- * unavailable or an [error](@ref error_handling) occurred.
- *
- * @remarks The addresses of a given function is not guaranteed to be the same
- * between contexts.
- *
- * @remarks This function may return a non-`NULL` address despite the
- * associated version or extension not being available. Always check the
- * context version or extension string presence first.
- *
- * @par Pointer Lifetime
- * The returned function pointer is valid until the context is destroyed or the
- * library is terminated.
- *
- * @par Thread Safety
- * This function may be called from any thread.
- *
- * @sa @ref context_glext
- * @sa glfwExtensionSupported
- *
- * @since Added in GLFW 1.0.
- *
- * @ingroup context
- */
-GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
-
-
-/*************************************************************************
- * Global definition cleanup
- *************************************************************************/
-
-/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
-
-#ifdef GLFW_WINGDIAPI_DEFINED
- #undef WINGDIAPI
- #undef GLFW_WINGDIAPI_DEFINED
-#endif
-
-#ifdef GLFW_CALLBACK_DEFINED
- #undef CALLBACK
- #undef GLFW_CALLBACK_DEFINED
-#endif
-
-/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _glfw3_h_ */
-
diff --git a/externals/glfw-3.1.1.bin/include/GLFW/glfw3native.h b/externals/glfw-3.1.1.bin/include/GLFW/glfw3native.h
deleted file mode 100644
index b3ce7482d..000000000
--- a/externals/glfw-3.1.1.bin/include/GLFW/glfw3native.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/*************************************************************************
- * GLFW 3.1 - www.glfw.org
- * A library for OpenGL, window and input
- *------------------------------------------------------------------------
- * Copyright (c) 2002-2006 Marcus Geelnard
- * Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would
- * be appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
- *
- *************************************************************************/
-
-#ifndef _glfw3_native_h_
-#define _glfw3_native_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*************************************************************************
- * Doxygen documentation
- *************************************************************************/
-
-/*! @defgroup native Native access
- *
- * **By using the native access functions you assert that you know what you're
- * doing and how to fix problems caused by using them. If you don't, you
- * shouldn't be using them.**
- *
- * Before the inclusion of @ref glfw3native.h, you must define exactly one
- * window system API macro and exactly one context creation API macro. Failure
- * to do this will cause a compile-time error.
- *
- * The available window API macros are:
- * * `GLFW_EXPOSE_NATIVE_WIN32`
- * * `GLFW_EXPOSE_NATIVE_COCOA`
- * * `GLFW_EXPOSE_NATIVE_X11`
- *
- * The available context API macros are:
- * * `GLFW_EXPOSE_NATIVE_WGL`
- * * `GLFW_EXPOSE_NATIVE_NSGL`
- * * `GLFW_EXPOSE_NATIVE_GLX`
- * * `GLFW_EXPOSE_NATIVE_EGL`
- *
- * These macros select which of the native access functions that are declared
- * and which platform-specific headers to include. It is then up your (by
- * definition platform-specific) code to handle which of these should be
- * defined.
- */
-
-
-/*************************************************************************
- * System headers and types
- *************************************************************************/
-
-#if defined(GLFW_EXPOSE_NATIVE_WIN32)
- // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
- // example to allow applications to correctly declare a GL_ARB_debug_output
- // callback) but windows.h assumes no one will define APIENTRY before it does
- #undef APIENTRY
- #include <windows.h>
-#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
- #include <ApplicationServices/ApplicationServices.h>
- #if defined(__OBJC__)
- #import <Cocoa/Cocoa.h>
- #else
- typedef void* id;
- #endif
-#elif defined(GLFW_EXPOSE_NATIVE_X11)
- #include <X11/Xlib.h>
- #include <X11/extensions/Xrandr.h>
-#else
- #error "No window API selected"
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_WGL)
- /* WGL is declared by windows.h */
-#elif defined(GLFW_EXPOSE_NATIVE_NSGL)
- /* NSGL is declared by Cocoa.h */
-#elif defined(GLFW_EXPOSE_NATIVE_GLX)
- #include <GL/glx.h>
-#elif defined(GLFW_EXPOSE_NATIVE_EGL)
- #include <EGL/egl.h>
-#else
- #error "No context API selected"
-#endif
-
-
-/*************************************************************************
- * Functions
- *************************************************************************/
-
-#if defined(GLFW_EXPOSE_NATIVE_WIN32)
-/*! @brief Returns the adapter device name of the specified monitor.
- *
- * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
- * of the specified monitor, or `NULL` if an [error](@ref error_handling)
- * occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.1.
- *
- * @ingroup native
- */
-GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
-
-/*! @brief Returns the display device name of the specified monitor.
- *
- * @return The UTF-8 encoded display device name (for example
- * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.1.
- *
- * @ingroup native
- */
-GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
-
-/*! @brief Returns the `HWND` of the specified window.
- *
- * @return The `HWND` of the specified window, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_WGL)
-/*! @brief Returns the `HGLRC` of the specified window.
- *
- * @return The `HGLRC` of the specified window, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_COCOA)
-/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
- *
- * @return The `CGDirectDisplayID` of the specified monitor, or
- * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.1.
- *
- * @ingroup native
- */
-GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
-
-/*! @brief Returns the `NSWindow` of the specified window.
- *
- * @return The `NSWindow` of the specified window, or `nil` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_NSGL)
-/*! @brief Returns the `NSOpenGLContext` of the specified window.
- *
- * @return The `NSOpenGLContext` of the specified window, or `nil` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_X11)
-/*! @brief Returns the `Display` used by GLFW.
- *
- * @return The `Display` used by GLFW, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI Display* glfwGetX11Display(void);
-
-/*! @brief Returns the `RRCrtc` of the specified monitor.
- *
- * @return The `RRCrtc` of the specified monitor, or `None` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.1.
- *
- * @ingroup native
- */
-GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
-
-/*! @brief Returns the `RROutput` of the specified monitor.
- *
- * @return The `RROutput` of the specified monitor, or `None` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.1.
- *
- * @ingroup native
- */
-GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
-
-/*! @brief Returns the `Window` of the specified window.
- *
- * @return The `Window` of the specified window, or `None` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_GLX)
-/*! @brief Returns the `GLXContext` of the specified window.
- *
- * @return The `GLXContext` of the specified window, or `NULL` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_EGL)
-/*! @brief Returns the `EGLDisplay` used by GLFW.
- *
- * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
-
-/*! @brief Returns the `EGLContext` of the specified window.
- *
- * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
-
-/*! @brief Returns the `EGLSurface` of the specified window.
- *
- * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
- * [error](@ref error_handling) occurred.
- *
- * @par Thread Safety
- * This function may be called from any thread. Access is not synchronized.
- *
- * @par History
- * Added in GLFW 3.0.
- *
- * @ingroup native
- */
-GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _glfw3_native_h_ */
-
diff --git a/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3.dll b/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3.dll
deleted file mode 100644
index 84c2e1bc2..000000000
--- a/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3dll.a b/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3dll.a
deleted file mode 100644
index dc593d062..000000000
--- a/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3dll.a
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-mingw-i686/libglfw3.a b/externals/glfw-3.1.1.bin/lib-mingw-i686/libglfw3.a
deleted file mode 100644
index 59eae0868..000000000
--- a/externals/glfw-3.1.1.bin/lib-mingw-i686/libglfw3.a
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3.dll b/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3.dll
deleted file mode 100644
index 437918eda..000000000
--- a/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3dll.a b/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3dll.a
deleted file mode 100644
index be08358ab..000000000
--- a/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3dll.a
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-mingw-x86_64/libglfw3.a b/externals/glfw-3.1.1.bin/lib-mingw-x86_64/libglfw3.a
deleted file mode 100644
index e9e7be933..000000000
--- a/externals/glfw-3.1.1.bin/lib-mingw-x86_64/libglfw3.a
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.dll b/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.dll
deleted file mode 100644
index f15748d7a..000000000
--- a/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.lib b/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.lib
deleted file mode 100644
index 6a5a85a1d..000000000
--- a/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3dll.lib b/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3dll.lib
deleted file mode 100644
index 248a5cadf..000000000
--- a/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3dll.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.dll b/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.dll
deleted file mode 100644
index cba172f64..000000000
--- a/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.lib b/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.lib
deleted file mode 100644
index efdd64332..000000000
--- a/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3dll.lib b/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3dll.lib
deleted file mode 100644
index 49ed2bb67..000000000
--- a/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3dll.lib
+++ /dev/null
Binary files differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cb09f3cd1..de4fe716a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -4,7 +4,8 @@ include_directories(.)
add_subdirectory(common)
add_subdirectory(core)
add_subdirectory(video_core)
-if (ENABLE_GLFW)
+add_subdirectory(audio_core)
+if (ENABLE_SDL2)
add_subdirectory(citra)
endif()
if (ENABLE_QT)
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
new file mode 100644
index 000000000..b0d1c7eb6
--- /dev/null
+++ b/src/audio_core/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(SRCS
+ audio_core.cpp
+ hle/dsp.cpp
+ hle/pipe.cpp
+ )
+
+set(HEADERS
+ audio_core.h
+ hle/dsp.h
+ hle/pipe.h
+ sink.h
+ )
+
+create_directory_groups(${SRCS} ${HEADERS})
+
+add_library(audio_core STATIC ${SRCS} ${HEADERS}) \ No newline at end of file
diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp
new file mode 100644
index 000000000..894f46990
--- /dev/null
+++ b/src/audio_core/audio_core.cpp
@@ -0,0 +1,53 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "audio_core/audio_core.h"
+#include "audio_core/hle/dsp.h"
+
+#include "core/core_timing.h"
+#include "core/hle/kernel/vm_manager.h"
+#include "core/hle/service/dsp_dsp.h"
+
+namespace AudioCore {
+
+// Audio Ticks occur about every 5 miliseconds.
+static int tick_event; ///< CoreTiming event
+static constexpr u64 audio_frame_ticks = 1310252ull; ///< Units: ARM11 cycles
+
+static void AudioTickCallback(u64 /*userdata*/, int cycles_late) {
+ if (DSP::HLE::Tick()) {
+ // HACK: We're not signaling the interrups when they should be, but just firing them all off together.
+ // It should be only (interrupt_id = 2, channel_id = 2) that's signalled here.
+ // TODO(merry): Understand when the other interrupts are fired.
+ DSP_DSP::SignalAllInterrupts();
+ }
+
+ // Reschedule recurrent event
+ CoreTiming::ScheduleEvent(audio_frame_ticks - cycles_late, tick_event);
+}
+
+/// Initialise Audio
+void Init() {
+ DSP::HLE::Init();
+
+ tick_event = CoreTiming::RegisterEvent("AudioCore::tick_event", AudioTickCallback);
+ CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event);
+}
+
+/// Add DSP address spaces to Process's address space.
+void AddAddressSpace(Kernel::VMManager& address_space) {
+ auto r0_vma = address_space.MapBackingMemory(DSP::HLE::region0_base, reinterpret_cast<u8*>(&DSP::HLE::g_region0), sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO).MoveFrom();
+ address_space.Reprotect(r0_vma, Kernel::VMAPermission::ReadWrite);
+
+ auto r1_vma = address_space.MapBackingMemory(DSP::HLE::region1_base, reinterpret_cast<u8*>(&DSP::HLE::g_region1), sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO).MoveFrom();
+ address_space.Reprotect(r1_vma, Kernel::VMAPermission::ReadWrite);
+}
+
+/// Shutdown Audio
+void Shutdown() {
+ CoreTiming::UnscheduleEvent(tick_event, 0);
+ DSP::HLE::Shutdown();
+}
+
+} //namespace
diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h
new file mode 100644
index 000000000..64c330914
--- /dev/null
+++ b/src/audio_core/audio_core.h
@@ -0,0 +1,26 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Kernel {
+class VMManager;
+}
+
+namespace AudioCore {
+
+constexpr int num_sources = 24;
+constexpr int samples_per_frame = 160; ///< Samples per audio frame at native sample rate
+constexpr int native_sample_rate = 32728; ///< 32kHz
+
+/// Initialise Audio Core
+void Init();
+
+/// Add DSP address spaces to a Process.
+void AddAddressSpace(Kernel::VMManager& vm_manager);
+
+/// Shutdown Audio Core
+void Shutdown();
+
+} // namespace
diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp
new file mode 100644
index 000000000..c89356edc
--- /dev/null
+++ b/src/audio_core/hle/dsp.cpp
@@ -0,0 +1,42 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "audio_core/hle/dsp.h"
+#include "audio_core/hle/pipe.h"
+
+namespace DSP {
+namespace HLE {
+
+SharedMemory g_region0;
+SharedMemory g_region1;
+
+void Init() {
+ DSP::HLE::ResetPipes();
+}
+
+void Shutdown() {
+}
+
+bool Tick() {
+ return true;
+}
+
+SharedMemory& CurrentRegion() {
+ // The region with the higher frame counter is chosen unless there is wraparound.
+
+ if (g_region0.frame_counter == 0xFFFFu && g_region1.frame_counter != 0xFFFEu) {
+ // Wraparound has occured.
+ return g_region1;
+ }
+
+ if (g_region1.frame_counter == 0xFFFFu && g_region0.frame_counter != 0xFFFEu) {
+ // Wraparound has occured.
+ return g_region0;
+ }
+
+ return (g_region0.frame_counter > g_region1.frame_counter) ? g_region0 : g_region1;
+}
+
+} // namespace HLE
+} // namespace DSP
diff --git a/src/audio_core/hle/dsp.h b/src/audio_core/hle/dsp.h
new file mode 100644
index 000000000..376436c29
--- /dev/null
+++ b/src/audio_core/hle/dsp.h
@@ -0,0 +1,539 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cstddef>
+#include <type_traits>
+
+#include "audio_core/audio_core.h"
+
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/swap.h"
+
+namespace DSP {
+namespace HLE {
+
+// The application-accessible region of DSP memory consists of two parts.
+// Both are marked as IO and have Read/Write permissions.
+//
+// First Region: 0x1FF50000 (Size: 0x8000)
+// Second Region: 0x1FF70000 (Size: 0x8000)
+//
+// The DSP reads from each region alternately based on the frame counter for each region much like a
+// double-buffer. The frame counter is located as the very last u16 of each region and is incremented
+// each audio tick.
+
+struct SharedMemory;
+
+constexpr VAddr region0_base = 0x1FF50000;
+extern SharedMemory g_region0;
+
+constexpr VAddr region1_base = 0x1FF70000;
+extern SharedMemory g_region1;
+
+/**
+ * The DSP is native 16-bit. The DSP also appears to be big-endian. When reading 32-bit numbers from
+ * its memory regions, the higher and lower 16-bit halves are swapped compared to the little-endian
+ * layout of the ARM11. Hence from the ARM11's point of view the memory space appears to be
+ * middle-endian.
+ *
+ * Unusually this does not appear to be an issue for floating point numbers. The DSP makes the more
+ * sensible choice of keeping that little-endian. There are also some exceptions such as the
+ * IntermediateMixSamples structure, which is little-endian.
+ *
+ * This struct implements the conversion to and from this middle-endianness.
+ */
+struct u32_dsp {
+ u32_dsp() = default;
+ operator u32() const {
+ return Convert(storage);
+ }
+ void operator=(u32 new_value) {
+ storage = Convert(new_value);
+ }
+private:
+ static constexpr u32 Convert(u32 value) {
+ return (value << 16) | (value >> 16);
+ }
+ u32_le storage;
+};
+#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
+static_assert(std::is_trivially_copyable<u32_dsp>::value, "u32_dsp isn't trivially copyable");
+#endif
+
+// There are 15 structures in each memory region. A table of them in the order they appear in memory
+// is presented below:
+//
+// # First Region DSP Address Purpose Control
+// 5 0x8400 DSP Status DSP
+// 9 0x8410 DSP Debug Info DSP
+// 6 0x8540 Final Mix Samples DSP
+// 2 0x8680 Source Status [24] DSP
+// 8 0x8710 Compressor Table Application
+// 4 0x9430 DSP Configuration Application
+// 7 0x9492 Intermediate Mix Samples DSP + App
+// 1 0x9E92 Source Configuration [24] Application
+// 3 0xA792 Source ADPCM Coefficients [24] Application
+// 10 0xA912 Surround Sound Related
+// 11 0xAA12 Surround Sound Related
+// 12 0xAAD2 Surround Sound Related
+// 13 0xAC52 Surround Sound Related
+// 14 0xAC5C Surround Sound Related
+// 0 0xBFFF Frame Counter Application
+//
+// #: This refers to the order in which they appear in the DspPipe::Audio DSP pipe.
+// See also: DSP::HLE::PipeRead.
+//
+// Note that the above addresses do vary slightly between audio firmwares observed; the addresses are
+// not fixed in stone. The addresses above are only an examplar; they're what this implementation
+// does and provides to applications.
+//
+// Application requests the DSP service to convert DSP addresses into ARM11 virtual addresses using the
+// ConvertProcessAddressFromDspDram service call. Applications seem to derive the addresses for the
+// second region via:
+// second_region_dsp_addr = first_region_dsp_addr | 0x10000
+//
+// Applications maintain most of its own audio state, the memory region is used mainly for
+// communication and not storage of state.
+//
+// In the documentation below, filter and effect transfer functions are specified in the z domain.
+// (If you are more familiar with the Laplace transform, z = exp(sT). The z domain is the digital
+// frequency domain, just like how the s domain is the analog frequency domain.)
+
+#define INSERT_PADDING_DSPWORDS(num_words) INSERT_PADDING_BYTES(2 * (num_words))
+
+// GCC versions < 5.0 do not implement std::is_trivially_copyable.
+// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable.
+#if (__GNUC__ >= 5) || defined(__clang__)
+ #define ASSERT_DSP_STRUCT(name, size) \
+ static_assert(std::is_standard_layout<name>::value, "DSP structure " #name " doesn't use standard layout"); \
+ static_assert(std::is_trivially_copyable<name>::value, "DSP structure " #name " isn't trivially copyable"); \
+ static_assert(sizeof(name) == (size), "Unexpected struct size for DSP structure " #name)
+#else
+ #define ASSERT_DSP_STRUCT(name, size) \
+ static_assert(std::is_standard_layout<name>::value, "DSP structure " #name " doesn't use standard layout"); \
+ static_assert(sizeof(name) == (size), "Unexpected struct size for DSP structure " #name)
+#endif
+
+struct SourceConfiguration {
+ struct Configuration {
+ /// These dirty flags are set by the application when it updates the fields in this struct.
+ /// The DSP clears these each audio frame.
+ union {
+ u32_le dirty_raw;
+
+ BitField<2, 1, u32_le> adpcm_coefficients_dirty;
+ BitField<3, 1, u32_le> partial_embedded_buffer_dirty; ///< Tends to be set when a looped buffer is queued.
+
+ BitField<16, 1, u32_le> enable_dirty;
+ BitField<17, 1, u32_le> interpolation_dirty;
+ BitField<18, 1, u32_le> rate_multiplier_dirty;
+ BitField<19, 1, u32_le> buffer_queue_dirty;
+ BitField<20, 1, u32_le> loop_related_dirty;
+ BitField<21, 1, u32_le> play_position_dirty; ///< Tends to also be set when embedded buffer is updated.
+ BitField<22, 1, u32_le> filters_enabled_dirty;
+ BitField<23, 1, u32_le> simple_filter_dirty;
+ BitField<24, 1, u32_le> biquad_filter_dirty;
+ BitField<25, 1, u32_le> gain_0_dirty;
+ BitField<26, 1, u32_le> gain_1_dirty;
+ BitField<27, 1, u32_le> gain_2_dirty;
+ BitField<28, 1, u32_le> sync_dirty;
+ BitField<29, 1, u32_le> reset_flag;
+
+ BitField<31, 1, u32_le> embedded_buffer_dirty;
+ };
+
+ // Gain control
+
+ /**
+ * Gain is between 0.0-1.0. This determines how much will this source appear on
+ * each of the 12 channels that feed into the intermediate mixers.
+ * Each of the three intermediate mixers is fed two left and two right channels.
+ */
+ float_le gain[3][4];
+
+ // Interpolation
+
+ /// Multiplier for sample rate. Resampling occurs with the selected interpolation method.
+ float_le rate_multiplier;
+
+ enum class InterpolationMode : u8 {
+ None = 0,
+ Linear = 1,
+ Polyphase = 2
+ };
+
+ InterpolationMode interpolation_mode;
+ INSERT_PADDING_BYTES(1); ///< Interpolation related
+
+ // Filters
+
+ /**
+ * This is the simplest normalized first-order digital recursive filter.
+ * The transfer function of this filter is:
+ * H(z) = b0 / (1 + a1 z^-1)
+ * Values are signed fixed point with 15 fractional bits.
+ */
+ struct SimpleFilter {
+ s16_le b0;
+ s16_le a1;
+ };
+
+ /**
+ * This is a normalised biquad filter (second-order).
+ * The transfer function of this filter is:
+ * H(z) = (b0 + b1 z^-1 + b2 z^-2) / (1 - a1 z^-1 - a2 z^-2)
+ * Nintendo chose to negate the feedbackward coefficients. This differs from standard notation
+ * as in: https://ccrma.stanford.edu/~jos/filters/Direct_Form_I.html
+ * Values are signed fixed point with 14 fractional bits.
+ */
+ struct BiquadFilter {
+ s16_le b0;
+ s16_le b1;
+ s16_le b2;
+ s16_le a1;
+ s16_le a2;
+ };
+
+ union {
+ u16_le filters_enabled;
+ BitField<0, 1, u16_le> simple_filter_enabled;
+ BitField<1, 1, u16_le> biquad_filter_enabled;
+ };
+
+ SimpleFilter simple_filter;
+ BiquadFilter biquad_filter;
+
+ // Buffer Queue
+
+ /// A buffer of audio data from the application, along with metadata about it.
+ struct Buffer {
+ /// Physical memory address of the start of the buffer
+ u32_dsp physical_address;
+
+ /// This is length in terms of samples.
+ /// Note that in different buffer formats a sample takes up different number of bytes.
+ u32_dsp length;
+
+ /// ADPCM Predictor (4 bits) and Scale (4 bits)
+ union {
+ u16_le adpcm_ps;
+ BitField<0, 4, u16_le> adpcm_scale;
+ BitField<4, 4, u16_le> adpcm_predictor;
+ };
+
+ /// ADPCM Historical Samples (y[n-1] and y[n-2])
+ u16_le adpcm_yn[2];
+
+ /// This is non-zero when the ADPCM values above are to be updated.
+ u8 adpcm_dirty;
+
+ /// Is a looping buffer.
+ u8 is_looping;
+
+ /// This value is shown in SourceStatus::previous_buffer_id when this buffer has finished.
+ /// This allows the emulated application to tell what buffer is currently playing
+ u16_le buffer_id;
+
+ INSERT_PADDING_DSPWORDS(1);
+ };
+
+ u16_le buffers_dirty; ///< Bitmap indicating which buffers are dirty (bit i -> buffers[i])
+ Buffer buffers[4]; ///< Queued Buffers
+
+ // Playback controls
+
+ u32_dsp loop_related;
+ u8 enable;
+ INSERT_PADDING_BYTES(1);
+ u16_le sync; ///< Application-side sync (See also: SourceStatus::sync)
+ u32_dsp play_position; ///< Position. (Units: number of samples)
+ INSERT_PADDING_DSPWORDS(2);
+
+ // Embedded Buffer
+ // This buffer is often the first buffer to be used when initiating audio playback,
+ // after which the buffer queue is used.
+
+ u32_dsp physical_address;
+
+ /// This is length in terms of samples.
+ /// Note a sample takes up different number of bytes in different buffer formats.
+ u32_dsp length;
+
+ enum class MonoOrStereo : u16_le {
+ Mono = 1,
+ Stereo = 2
+ };
+
+ enum class Format : u16_le {
+ PCM8 = 0,
+ PCM16 = 1,
+ ADPCM = 2
+ };
+
+ union {
+ u16_le flags1_raw;
+ BitField<0, 2, MonoOrStereo> mono_or_stereo;
+ BitField<2, 2, Format> format;
+ BitField<5, 1, u16_le> fade_in;
+ };
+
+ /// ADPCM Predictor (4 bit) and Scale (4 bit)
+ union {
+ u16_le adpcm_ps;
+ BitField<0, 4, u16_le> adpcm_scale;
+ BitField<4, 4, u16_le> adpcm_predictor;
+ };
+
+ /// ADPCM Historical Samples (y[n-1] and y[n-2])
+ u16_le adpcm_yn[2];
+
+ union {
+ u16_le flags2_raw;
+ BitField<0, 1, u16_le> adpcm_dirty; ///< Has the ADPCM info above been changed?
+ BitField<1, 1, u16_le> is_looping; ///< Is this a looping buffer?
+ };
+
+ /// Buffer id of embedded buffer (used as a buffer id in SourceStatus to reference this buffer).
+ u16_le buffer_id;
+ };
+
+ Configuration config[AudioCore::num_sources];
+};
+ASSERT_DSP_STRUCT(SourceConfiguration::Configuration, 192);
+ASSERT_DSP_STRUCT(SourceConfiguration::Configuration::Buffer, 20);
+
+struct SourceStatus {
+ struct Status {
+ u8 is_enabled; ///< Is this channel enabled? (Doesn't have to be playing anything.)
+ u8 previous_buffer_id_dirty; ///< Non-zero when previous_buffer_id changes
+ u16_le sync; ///< Is set by the DSP to the value of SourceConfiguration::sync
+ u32_dsp buffer_position; ///< Number of samples into the current buffer
+ u16_le previous_buffer_id; ///< Updated when a buffer finishes playing
+ INSERT_PADDING_DSPWORDS(1);
+ };
+
+ Status status[AudioCore::num_sources];
+};
+ASSERT_DSP_STRUCT(SourceStatus::Status, 12);
+
+struct DspConfiguration {
+ /// These dirty flags are set by the application when it updates the fields in this struct.
+ /// The DSP clears these each audio frame.
+ union {
+ u32_le dirty_raw;
+
+ BitField<8, 1, u32_le> mixer1_enabled_dirty;
+ BitField<9, 1, u32_le> mixer2_enabled_dirty;
+ BitField<10, 1, u32_le> delay_effect_0_dirty;
+ BitField<11, 1, u32_le> delay_effect_1_dirty;
+ BitField<12, 1, u32_le> reverb_effect_0_dirty;
+ BitField<13, 1, u32_le> reverb_effect_1_dirty;
+
+ BitField<16, 1, u32_le> volume_0_dirty;
+
+ BitField<24, 1, u32_le> volume_1_dirty;
+ BitField<25, 1, u32_le> volume_2_dirty;
+ BitField<26, 1, u32_le> output_format_dirty;
+ BitField<27, 1, u32_le> limiter_enabled_dirty;
+ BitField<28, 1, u32_le> headphones_connected_dirty;
+ };
+
+ /// The DSP has three intermediate audio mixers. This controls the volume level (0.0-1.0) for each at the final mixer
+ float_le volume[3];
+
+ INSERT_PADDING_DSPWORDS(3);
+
+ enum class OutputFormat : u16_le {
+ Mono = 0,
+ Stereo = 1,
+ Surround = 2
+ };
+
+ OutputFormat output_format;
+
+ u16_le limiter_enabled; ///< Not sure of the exact gain equation for the limiter.
+ u16_le headphones_connected; ///< Application updates the DSP on headphone status.
+ INSERT_PADDING_DSPWORDS(4); ///< TODO: Surround sound related
+ INSERT_PADDING_DSPWORDS(2); ///< TODO: Intermediate mixer 1/2 related
+ u16_le mixer1_enabled;
+ u16_le mixer2_enabled;
+
+ /**
+ * This is delay with feedback.
+ * Transfer function:
+ * H(z) = a z^-N / (1 - b z^-1 + a g z^-N)
+ * where
+ * N = frame_count * samples_per_frame
+ * g, a and b are fixed point with 7 fractional bits
+ */
+ struct DelayEffect {
+ /// These dirty flags are set by the application when it updates the fields in this struct.
+ /// The DSP clears these each audio frame.
+ union {
+ u16_le dirty_raw;
+ BitField<0, 1, u16_le> enable_dirty;
+ BitField<1, 1, u16_le> work_buffer_address_dirty;
+ BitField<2, 1, u16_le> other_dirty; ///< Set when anything else has been changed
+ };
+
+ u16_le enable;
+ INSERT_PADDING_DSPWORDS(1);
+ u16_le outputs;
+ u32_dsp work_buffer_address; ///< The application allocates a block of memory for the DSP to use as a work buffer.
+ u16_le frame_count; ///< Frames to delay by
+
+ // Coefficients
+ s16_le g; ///< Fixed point with 7 fractional bits
+ s16_le a; ///< Fixed point with 7 fractional bits
+ s16_le b; ///< Fixed point with 7 fractional bits
+ };
+
+ DelayEffect delay_effect[2];
+
+ struct ReverbEffect {
+ INSERT_PADDING_DSPWORDS(26); ///< TODO
+ };
+
+ ReverbEffect reverb_effect[2];
+
+ INSERT_PADDING_DSPWORDS(4);
+};
+ASSERT_DSP_STRUCT(DspConfiguration, 196);
+ASSERT_DSP_STRUCT(DspConfiguration::DelayEffect, 20);
+ASSERT_DSP_STRUCT(DspConfiguration::ReverbEffect, 52);
+
+struct AdpcmCoefficients {
+ /// Coefficients are signed fixed point with 11 fractional bits.
+ /// Each source has 16 coefficients associated with it.
+ s16_le coeff[AudioCore::num_sources][16];
+};
+ASSERT_DSP_STRUCT(AdpcmCoefficients, 768);
+
+struct DspStatus {
+ u16_le unknown;
+ u16_le dropped_frames;
+ INSERT_PADDING_DSPWORDS(0xE);
+};
+ASSERT_DSP_STRUCT(DspStatus, 32);
+
+/// Final mixed output in PCM16 stereo format, what you hear out of the speakers.
+/// When the application writes to this region it has no effect.
+struct FinalMixSamples {
+ s16_le pcm16[2 * AudioCore::samples_per_frame];
+};
+ASSERT_DSP_STRUCT(FinalMixSamples, 640);
+
+/// DSP writes output of intermediate mixers 1 and 2 here.
+/// Writes to this region by the application edits the output of the intermediate mixers.
+/// This seems to be intended to allow the application to do custom effects on the ARM11.
+/// Values that exceed s16 range will be clipped by the DSP after further processing.
+struct IntermediateMixSamples {
+ struct Samples {
+ s32_le pcm32[4][AudioCore::samples_per_frame]; ///< Little-endian as opposed to DSP middle-endian.
+ };
+
+ Samples mix1;
+ Samples mix2;
+};
+ASSERT_DSP_STRUCT(IntermediateMixSamples, 5120);
+
+/// Compressor table
+struct Compressor {
+ INSERT_PADDING_DSPWORDS(0xD20); ///< TODO
+};
+
+/// There is no easy way to implement this in a HLE implementation.
+struct DspDebug {
+ INSERT_PADDING_DSPWORDS(0x130);
+};
+ASSERT_DSP_STRUCT(DspDebug, 0x260);
+
+struct SharedMemory {
+ /// Padding
+ INSERT_PADDING_DSPWORDS(0x400);
+
+ DspStatus dsp_status;
+
+ DspDebug dsp_debug;
+
+ FinalMixSamples final_samples;
+
+ SourceStatus source_statuses;
+
+ Compressor compressor;
+
+ DspConfiguration dsp_configuration;
+
+ IntermediateMixSamples intermediate_mix_samples;
+
+ SourceConfiguration source_configurations;
+
+ AdpcmCoefficients adpcm_coefficients;
+
+ struct {
+ INSERT_PADDING_DSPWORDS(0x100);
+ } unknown10;
+
+ struct {
+ INSERT_PADDING_DSPWORDS(0xC0);
+ } unknown11;
+
+ struct {
+ INSERT_PADDING_DSPWORDS(0x180);
+ } unknown12;
+
+ struct {
+ INSERT_PADDING_DSPWORDS(0xA);
+ } unknown13;
+
+ struct {
+ INSERT_PADDING_DSPWORDS(0x13A3);
+ } unknown14;
+
+ u16_le frame_counter;
+};
+ASSERT_DSP_STRUCT(SharedMemory, 0x8000);
+
+// Structures must have an offset that is a multiple of two.
+static_assert(offsetof(SharedMemory, frame_counter) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, source_configurations) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, source_statuses) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, adpcm_coefficients) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, dsp_configuration) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, dsp_status) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, final_samples) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, intermediate_mix_samples) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, compressor) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, dsp_debug) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, unknown10) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, unknown11) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, unknown12) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, unknown13) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+static_assert(offsetof(SharedMemory, unknown14) % 2 == 0, "Structures in DSP::HLE::SharedMemory must be 2-byte aligned");
+
+#undef INSERT_PADDING_DSPWORDS
+#undef ASSERT_DSP_STRUCT
+
+/// Initialize DSP hardware
+void Init();
+
+/// Shutdown DSP hardware
+void Shutdown();
+
+/**
+ * Perform processing and updates state of current shared memory buffer.
+ * This function is called every audio tick before triggering the audio interrupt.
+ * @return Whether an audio interrupt should be triggered this frame.
+ */
+bool Tick();
+
+/// Returns a mutable reference to the current region. Current region is selected based on the frame counter.
+SharedMemory& CurrentRegion();
+
+} // namespace HLE
+} // namespace DSP
diff --git a/src/audio_core/hle/pipe.cpp b/src/audio_core/hle/pipe.cpp
new file mode 100644
index 000000000..9381883b4
--- /dev/null
+++ b/src/audio_core/hle/pipe.cpp
@@ -0,0 +1,159 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <array>
+#include <vector>
+
+#include "audio_core/hle/dsp.h"
+#include "audio_core/hle/pipe.h"
+
+#include "common/assert.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+
+namespace DSP {
+namespace HLE {
+
+static DspState dsp_state = DspState::Off;
+
+static std::array<std::vector<u8>, static_cast<size_t>(DspPipe::DspPipe_MAX)> pipe_data;
+
+void ResetPipes() {
+ for (auto& data : pipe_data) {
+ data.clear();
+ }
+ dsp_state = DspState::Off;
+}
+
+std::vector<u8> PipeRead(DspPipe pipe_number, u32 length) {
+ if (pipe_number >= DspPipe::DspPipe_MAX) {
+ LOG_ERROR(Audio_DSP, "pipe_number = %u invalid", pipe_number);
+ return {};
+ }
+
+ std::vector<u8>& data = pipe_data[static_cast<size_t>(pipe_number)];
+
+ if (length > data.size()) {
+ LOG_WARNING(Audio_DSP, "pipe_number = %u is out of data, application requested read of %u but %zu remain",
+ pipe_number, length, data.size());
+ length = data.size();
+ }
+
+ if (length == 0)
+ return {};
+
+ std::vector<u8> ret(data.begin(), data.begin() + length);
+ data.erase(data.begin(), data.begin() + length);
+ return ret;
+}
+
+size_t GetPipeReadableSize(DspPipe pipe_number) {
+ if (pipe_number >= DspPipe::DspPipe_MAX) {
+ LOG_ERROR(Audio_DSP, "pipe_number = %u invalid", pipe_number);
+ return 0;
+ }
+
+ return pipe_data[static_cast<size_t>(pipe_number)].size();
+}
+
+static void WriteU16(DspPipe pipe_number, u16 value) {
+ std::vector<u8>& data = pipe_data[static_cast<size_t>(pipe_number)];
+ // Little endian
+ data.emplace_back(value & 0xFF);
+ data.emplace_back(value >> 8);
+}
+
+static void AudioPipeWriteStructAddresses() {
+ // These struct addresses are DSP dram addresses.
+ // See also: DSP_DSP::ConvertProcessAddressFromDspDram
+ static const std::array<u16, 15> struct_addresses = {
+ 0x8000 + offsetof(SharedMemory, frame_counter) / 2,
+ 0x8000 + offsetof(SharedMemory, source_configurations) / 2,
+ 0x8000 + offsetof(SharedMemory, source_statuses) / 2,
+ 0x8000 + offsetof(SharedMemory, adpcm_coefficients) / 2,
+ 0x8000 + offsetof(SharedMemory, dsp_configuration) / 2,
+ 0x8000 + offsetof(SharedMemory, dsp_status) / 2,
+ 0x8000 + offsetof(SharedMemory, final_samples) / 2,
+ 0x8000 + offsetof(SharedMemory, intermediate_mix_samples) / 2,
+ 0x8000 + offsetof(SharedMemory, compressor) / 2,
+ 0x8000 + offsetof(SharedMemory, dsp_debug) / 2,
+ 0x8000 + offsetof(SharedMemory, unknown10) / 2,
+ 0x8000 + offsetof(SharedMemory, unknown11) / 2,
+ 0x8000 + offsetof(SharedMemory, unknown12) / 2,
+ 0x8000 + offsetof(SharedMemory, unknown13) / 2,
+ 0x8000 + offsetof(SharedMemory, unknown14) / 2
+ };
+
+ // Begin with a u16 denoting the number of structs.
+ WriteU16(DspPipe::Audio, struct_addresses.size());
+ // Then write the struct addresses.
+ for (u16 addr : struct_addresses) {
+ WriteU16(DspPipe::Audio, addr);
+ }
+}
+
+void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) {
+ switch (pipe_number) {
+ case DspPipe::Audio: {
+ if (buffer.size() != 4) {
+ LOG_ERROR(Audio_DSP, "DspPipe::Audio: Unexpected buffer length %zu was written", buffer.size());
+ return;
+ }
+
+ enum class StateChange {
+ Initalize = 0,
+ Shutdown = 1,
+ Wakeup = 2,
+ Sleep = 3
+ };
+
+ // The difference between Initialize and Wakeup is that Input state is maintained
+ // when sleeping but isn't when turning it off and on again. (TODO: Implement this.)
+ // Waking up from sleep garbles some of the structs in the memory region. (TODO:
+ // Implement this.) Applications store away the state of these structs before
+ // sleeping and reset it back after wakeup on behalf of the DSP.
+
+ switch (static_cast<StateChange>(buffer[0])) {
+ case StateChange::Initalize:
+ LOG_INFO(Audio_DSP, "Application has requested initialization of DSP hardware");
+ ResetPipes();
+ AudioPipeWriteStructAddresses();
+ dsp_state = DspState::On;
+ break;
+ case StateChange::Shutdown:
+ LOG_INFO(Audio_DSP, "Application has requested shutdown of DSP hardware");
+ dsp_state = DspState::Off;
+ break;
+ case StateChange::Wakeup:
+ LOG_INFO(Audio_DSP, "Application has requested wakeup of DSP hardware");
+ ResetPipes();
+ AudioPipeWriteStructAddresses();
+ dsp_state = DspState::On;
+ break;
+ case StateChange::Sleep:
+ LOG_INFO(Audio_DSP, "Application has requested sleep of DSP hardware");
+ UNIMPLEMENTED();
+ dsp_state = DspState::Sleeping;
+ break;
+ default:
+ LOG_ERROR(Audio_DSP, "Application has requested unknown state transition of DSP hardware %hhu", buffer[0]);
+ dsp_state = DspState::Off;
+ break;
+ }
+
+ return;
+ }
+ default:
+ LOG_CRITICAL(Audio_DSP, "pipe_number = %u unimplemented", pipe_number);
+ UNIMPLEMENTED();
+ return;
+ }
+}
+
+DspState GetDspState() {
+ return dsp_state;
+}
+
+} // namespace HLE
+} // namespace DSP
diff --git a/src/audio_core/hle/pipe.h b/src/audio_core/hle/pipe.h
new file mode 100644
index 000000000..382d35e87
--- /dev/null
+++ b/src/audio_core/hle/pipe.h
@@ -0,0 +1,57 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cstddef>
+#include <vector>
+
+#include "common/common_types.h"
+
+namespace DSP {
+namespace HLE {
+
+/// Reset the pipes by setting pipe positions back to the beginning.
+void ResetPipes();
+
+enum class DspPipe {
+ Debug = 0,
+ Dma = 1,
+ Audio = 2,
+ Binary = 3,
+ DspPipe_MAX
+};
+
+/**
+ * Read a DSP pipe.
+ * @param pipe_number The Pipe ID
+ * @param length How much data to request.
+ * @return The data read from the pipe. The size of this vector can be less than the length requested.
+ */
+std::vector<u8> PipeRead(DspPipe pipe_number, u32 length);
+
+/**
+ * How much data is left in pipe
+ * @param pipe_number The Pipe ID
+ * @return The amount of data remaning in the pipe. This is the maximum length PipeRead will return.
+ */
+size_t GetPipeReadableSize(DspPipe pipe_number);
+
+/**
+ * Write to a DSP pipe.
+ * @param pipe_number The Pipe ID
+ * @param buffer The data to write to the pipe.
+ */
+void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer);
+
+enum class DspState {
+ Off,
+ On,
+ Sleeping
+};
+/// Get the state of the DSP
+DspState GetDspState();
+
+} // namespace HLE
+} // namespace DSP
diff --git a/src/audio_core/sink.h b/src/audio_core/sink.h
new file mode 100644
index 000000000..cad21a85e
--- /dev/null
+++ b/src/audio_core/sink.h
@@ -0,0 +1,34 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+
+#include "common/common_types.h"
+
+namespace AudioCore {
+
+/**
+ * This class is an interface for an audio sink. An audio sink accepts samples in stereo signed PCM16 format to be output.
+ * Sinks *do not* handle resampling and expect the correct sample rate. They are dumb outputs.
+ */
+class Sink {
+public:
+ virtual ~Sink() = default;
+
+ /// The native rate of this sink. The sink expects to be fed samples that respect this. (Units: samples/sec)
+ virtual unsigned GetNativeSampleRate() const = 0;
+
+ /**
+ * Feed stereo samples to sink.
+ * @param samples Samples in interleaved stereo PCM16 format. Size of vector must be multiple of two.
+ */
+ virtual void EnqueueSamples(const std::vector<s16>& samples) = 0;
+
+ /// Samples enqueued that have not been played yet.
+ virtual std::size_t SamplesInQueue() const = 0;
+};
+
+} // namespace
diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt
index e7f8a17f9..fa615deb9 100644
--- a/src/citra/CMakeLists.txt
+++ b/src/citra/CMakeLists.txt
@@ -1,11 +1,11 @@
set(SRCS
- emu_window/emu_window_glfw.cpp
+ emu_window/emu_window_sdl2.cpp
citra.cpp
config.cpp
citra.rc
)
set(HEADERS
- emu_window/emu_window_glfw.h
+ emu_window/emu_window_sdl2.h
config.h
default_ini.h
resource.h
@@ -13,12 +13,11 @@ set(HEADERS
create_directory_groups(${SRCS} ${HEADERS})
-include_directories(${GLFW_INCLUDE_DIRS})
-link_directories(${GLFW_LIBRARY_DIRS})
+include_directories(${SDL2_INCLUDE_DIR})
add_executable(citra ${SRCS} ${HEADERS})
-target_link_libraries(citra core video_core common)
-target_link_libraries(citra ${GLFW_LIBRARIES} ${OPENGL_gl_LIBRARY} inih glad)
+target_link_libraries(citra core video_core audio_core common)
+target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad)
if (MSVC)
target_link_libraries(citra getopt)
endif()
@@ -27,3 +26,13 @@ target_link_libraries(citra ${PLATFORM_LIBRARIES})
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD")
install(TARGETS citra RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
endif()
+
+if (MSVC)
+ include(WindowsCopyFiles)
+
+ set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
+
+ windows_copy_files(citra ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll)
+
+ unset(DLL_DEST)
+endif()
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp
index c96fc1374..415b98a05 100644
--- a/src/citra/citra.cpp
+++ b/src/citra/citra.cpp
@@ -27,7 +27,7 @@
#include "core/loader/loader.h"
#include "citra/config.h"
-#include "citra/emu_window/emu_window_glfw.h"
+#include "citra/emu_window/emu_window_sdl2.h"
#include "video_core/video_core.h"
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
GDBStub::ToggleServer(Settings::values.use_gdbstub);
GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port));
- EmuWindow_GLFW* emu_window = new EmuWindow_GLFW;
+ EmuWindow_SDL2* emu_window = new EmuWindow_SDL2;
VideoCore::g_hw_renderer_enabled = Settings::values.use_hw_renderer;
VideoCore::g_shader_jit_enabled = Settings::values.use_shader_jit;
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 2f13c29a2..9034b188e 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -2,14 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#define GLFW_INCLUDE_NONE
-#include <GLFW/glfw3.h>
#include <inih/cpp/INIReader.h>
+#include <SDL.h>
+
#include "citra/default_ini.h"
#include "common/file_util.h"
#include "common/logging/log.h"
+#include "common/make_unique.h"
#include "core/settings.h"
@@ -17,21 +18,22 @@
Config::Config() {
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
- glfw_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "glfw-config.ini";
- glfw_config = new INIReader(glfw_config_loc);
+ sdl2_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "sdl2-config.ini";
+ sdl2_config = Common::make_unique<INIReader>(sdl2_config_loc);
Reload();
}
-bool Config::LoadINI(INIReader* config, const char* location, const std::string& default_contents, bool retry) {
- if (config->ParseError() < 0) {
+bool Config::LoadINI(const std::string& default_contents, bool retry) {
+ const char* location = this->sdl2_config_loc.c_str();
+ if (sdl2_config->ParseError() < 0) {
if (retry) {
LOG_WARNING(Config, "Failed to load %s. Creating file from defaults...", location);
FileUtil::CreateFullPath(location);
FileUtil::WriteStringToFile(true, default_contents, location);
- *config = INIReader(location); // Reopen file
+ sdl2_config = Common::make_unique<INIReader>(location); // Reopen file
- return LoadINI(config, location, default_contents, false);
+ return LoadINI(default_contents, false);
}
LOG_ERROR(Config, "Failed.");
return false;
@@ -41,51 +43,47 @@ bool Config::LoadINI(INIReader* config, const char* location, const std::string&
}
static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = {
- GLFW_KEY_A, GLFW_KEY_S, GLFW_KEY_Z, GLFW_KEY_X,
- GLFW_KEY_Q, GLFW_KEY_W, GLFW_KEY_1, GLFW_KEY_2,
- GLFW_KEY_M, GLFW_KEY_N, GLFW_KEY_B,
- GLFW_KEY_T, GLFW_KEY_G, GLFW_KEY_F, GLFW_KEY_H,
- GLFW_KEY_UP, GLFW_KEY_DOWN, GLFW_KEY_LEFT, GLFW_KEY_RIGHT,
- GLFW_KEY_I, GLFW_KEY_K, GLFW_KEY_J, GLFW_KEY_L
+ SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X,
+ SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_1, SDL_SCANCODE_2,
+ SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_B,
+ SDL_SCANCODE_T, SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H,
+ SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT,
+ SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L
};
void Config::ReadValues() {
// Controls
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
Settings::values.input_mappings[Settings::NativeInput::All[i]] =
- glfw_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]);
+ sdl2_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]);
}
// Core
- Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0);
+ Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0);
// Renderer
- Settings::values.use_hw_renderer = glfw_config->GetBoolean("Renderer", "use_hw_renderer", false);
- Settings::values.use_shader_jit = glfw_config->GetBoolean("Renderer", "use_shader_jit", true);
+ Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", false);
+ Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true);
- Settings::values.bg_red = (float)glfw_config->GetReal("Renderer", "bg_red", 1.0);
- Settings::values.bg_green = (float)glfw_config->GetReal("Renderer", "bg_green", 1.0);
- Settings::values.bg_blue = (float)glfw_config->GetReal("Renderer", "bg_blue", 1.0);
+ Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 1.0);
+ Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0);
+ Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 1.0);
// Data Storage
- Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true);
+ Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true);
// System Region
- Settings::values.region_value = glfw_config->GetInteger("System Region", "region_value", 1);
+ Settings::values.region_value = sdl2_config->GetInteger("System Region", "region_value", 1);
// Miscellaneous
- Settings::values.log_filter = glfw_config->Get("Miscellaneous", "log_filter", "*:Info");
+ Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info");
// Debugging
- Settings::values.use_gdbstub = glfw_config->GetBoolean("Debugging", "use_gdbstub", false);
- Settings::values.gdbstub_port = glfw_config->GetInteger("Debugging", "gdbstub_port", 24689);
+ Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false);
+ Settings::values.gdbstub_port = sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689);
}
void Config::Reload() {
- LoadINI(glfw_config, glfw_config_loc.c_str(), DefaultINI::glfw_config_file);
+ LoadINI(DefaultINI::sdl2_config_file);
ReadValues();
}
-
-Config::~Config() {
- delete glfw_config;
-}
diff --git a/src/citra/config.h b/src/citra/config.h
index c326ec669..52a478146 100644
--- a/src/citra/config.h
+++ b/src/citra/config.h
@@ -4,19 +4,19 @@
#pragma once
+#include <memory>
#include <string>
-class INIReader;
+#include <inih/cpp/INIReader.h>
class Config {
- INIReader* glfw_config;
- std::string glfw_config_loc;
+ std::unique_ptr<INIReader> sdl2_config;
+ std::string sdl2_config_loc;
- bool LoadINI(INIReader* config, const char* location, const std::string& default_contents="", bool retry=true);
+ bool LoadINI(const std::string& default_contents="", bool retry=true);
void ReadValues();
public:
Config();
- ~Config();
void Reload();
};
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 5ba40a8ed..c9b490a00 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -6,7 +6,7 @@
namespace DefaultINI {
-const char* glfw_config_file = R"(
+const char* sdl2_config_file = R"(
[Controls]
pad_start =
pad_select =
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp
deleted file mode 100644
index 9453b1f48..000000000
--- a/src/citra/emu_window/emu_window_glfw.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <cstdlib>
-#include <string>
-
-// Let’s use our own GL header, instead of one from GLFW.
-#include <glad/glad.h>
-#define GLFW_INCLUDE_NONE
-#include <GLFW/glfw3.h>
-
-#include "common/assert.h"
-#include "common/key_map.h"
-#include "common/logging/log.h"
-#include "common/scm_rev.h"
-#include "common/string_util.h"
-
-#include "video_core/video_core.h"
-
-#include "core/settings.h"
-#include "core/hle/service/hid/hid.h"
-
-#include "citra/emu_window/emu_window_glfw.h"
-
-EmuWindow_GLFW* EmuWindow_GLFW::GetEmuWindow(GLFWwindow* win) {
- return static_cast<EmuWindow_GLFW*>(glfwGetWindowUserPointer(win));
-}
-
-void EmuWindow_GLFW::OnMouseButtonEvent(GLFWwindow* win, int button, int action, int mods) {
- if (button == GLFW_MOUSE_BUTTON_LEFT) {
- auto emu_window = GetEmuWindow(win);
- auto layout = emu_window->GetFramebufferLayout();
- double x, y;
- glfwGetCursorPos(win, &x, &y);
-
- if (action == GLFW_PRESS)
- emu_window->TouchPressed(static_cast<unsigned>(x), static_cast<unsigned>(y));
- else if (action == GLFW_RELEASE)
- emu_window->TouchReleased();
- }
-}
-
-void EmuWindow_GLFW::OnCursorPosEvent(GLFWwindow* win, double x, double y) {
- GetEmuWindow(win)->TouchMoved(static_cast<unsigned>(std::max(x, 0.0)), static_cast<unsigned>(std::max(y, 0.0)));
-}
-
-/// Called by GLFW when a key event occurs
-void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) {
- auto emu_window = GetEmuWindow(win);
- int keyboard_id = emu_window->keyboard_id;
-
- if (action == GLFW_PRESS) {
- emu_window->KeyPressed({key, keyboard_id});
- } else if (action == GLFW_RELEASE) {
- emu_window->KeyReleased({key, keyboard_id});
- }
-}
-
-/// Whether the window is still open, and a close request hasn't yet been sent
-const bool EmuWindow_GLFW::IsOpen() {
- return glfwWindowShouldClose(m_render_window) == 0;
-}
-
-void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) {
- GetEmuWindow(win)->NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height));
-}
-
-void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) {
- // NOTE: GLFW provides no proper way to set a minimal window size.
- // Hence, we just ignore the corresponding EmuWindow hint.
- OnFramebufferResizeEvent(win, width, height);
-}
-
-/// EmuWindow_GLFW constructor
-EmuWindow_GLFW::EmuWindow_GLFW() {
- keyboard_id = KeyMap::NewDeviceId();
-
- ReloadSetKeymaps();
-
- glfwSetErrorCallback([](int error, const char *desc){
- LOG_ERROR(Frontend, "GLFW 0x%08x: %s", error, desc);
- });
-
- // Initialize the window
- if(glfwInit() != GL_TRUE) {
- LOG_CRITICAL(Frontend, "Failed to initialize GLFW! Exiting...");
- exit(1);
- }
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- // GLFW on OSX requires these window hints to be set to create a 3.2+ GL context.
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
- std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
- m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth,
- (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight),
- window_title.c_str(), nullptr, nullptr);
-
- if (m_render_window == nullptr) {
- LOG_CRITICAL(Frontend, "Failed to create GLFW window! Exiting...");
- exit(1);
- }
-
- glfwSetWindowUserPointer(m_render_window, this);
-
- // Notify base interface about window state
- int width, height;
- glfwGetFramebufferSize(m_render_window, &width, &height);
- OnFramebufferResizeEvent(m_render_window, width, height);
-
- glfwGetWindowSize(m_render_window, &width, &height);
- OnClientAreaResizeEvent(m_render_window, width, height);
-
- // Setup callbacks
- glfwSetKeyCallback(m_render_window, OnKeyEvent);
- glfwSetMouseButtonCallback(m_render_window, OnMouseButtonEvent);
- glfwSetCursorPosCallback(m_render_window, OnCursorPosEvent);
- glfwSetFramebufferSizeCallback(m_render_window, OnFramebufferResizeEvent);
- glfwSetWindowSizeCallback(m_render_window, OnClientAreaResizeEvent);
-
- DoneCurrent();
-}
-
-/// EmuWindow_GLFW destructor
-EmuWindow_GLFW::~EmuWindow_GLFW() {
- glfwTerminate();
-}
-
-/// Swap buffers to display the next frame
-void EmuWindow_GLFW::SwapBuffers() {
- glfwSwapBuffers(m_render_window);
-}
-
-/// Polls window events
-void EmuWindow_GLFW::PollEvents() {
- glfwPollEvents();
-}
-
-/// Makes the GLFW OpenGL context current for the caller thread
-void EmuWindow_GLFW::MakeCurrent() {
- glfwMakeContextCurrent(m_render_window);
-}
-
-/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
-void EmuWindow_GLFW::DoneCurrent() {
- glfwMakeContextCurrent(nullptr);
-}
-
-void EmuWindow_GLFW::ReloadSetKeymaps() {
- for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
- KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]);
- }
-}
-
-void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) {
- std::pair<int,int> current_size;
- glfwGetWindowSize(m_render_window, &current_size.first, &current_size.second);
-
- DEBUG_ASSERT((int)minimal_size.first > 0 && (int)minimal_size.second > 0);
- int new_width = std::max(current_size.first, (int)minimal_size.first);
- int new_height = std::max(current_size.second, (int)minimal_size.second);
-
- if (current_size != std::make_pair(new_width, new_height))
- glfwSetWindowSize(m_render_window, new_width, new_height);
-}
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h
deleted file mode 100644
index 7ccd5e6aa..000000000
--- a/src/citra/emu_window/emu_window_glfw.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <utility>
-
-#include "common/emu_window.h"
-
-struct GLFWwindow;
-
-class EmuWindow_GLFW : public EmuWindow {
-public:
- EmuWindow_GLFW();
- ~EmuWindow_GLFW();
-
- /// Swap buffers to display the next frame
- void SwapBuffers() override;
-
- /// Polls window events
- void PollEvents() override;
-
- /// Makes the graphics context current for the caller thread
- void MakeCurrent() override;
-
- /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
- void DoneCurrent() override;
-
- static void OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods);
-
- static void OnMouseButtonEvent(GLFWwindow* window, int button, int action, int mods);
-
- static void OnCursorPosEvent(GLFWwindow* window, double x, double y);
-
- /// Whether the window is still open, and a close request hasn't yet been sent
- const bool IsOpen();
-
- static void OnClientAreaResizeEvent(GLFWwindow* win, int width, int height);
-
- static void OnFramebufferResizeEvent(GLFWwindow* win, int width, int height);
-
- void ReloadSetKeymaps() override;
-
-private:
- void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override;
-
- static EmuWindow_GLFW* GetEmuWindow(GLFWwindow* win);
-
- GLFWwindow* m_render_window; ///< Internal GLFW render window
-
- /// Device id of keyboard for use with KeyMap
- int keyboard_id;
-};
diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp
new file mode 100644
index 000000000..1fed82e78
--- /dev/null
+++ b/src/citra/emu_window/emu_window_sdl2.cpp
@@ -0,0 +1,167 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <cstdlib>
+#include <string>
+
+#define SDL_MAIN_HANDLED
+#include <SDL.h>
+
+#include "common/key_map.h"
+#include "common/logging/log.h"
+#include "common/scm_rev.h"
+#include "common/string_util.h"
+
+#include "core/settings.h"
+#include "core/hle/service/hid/hid.h"
+
+#include "citra/emu_window/emu_window_sdl2.h"
+
+#include "video_core/video_core.h"
+
+void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
+ TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
+}
+
+void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
+ if (button != SDL_BUTTON_LEFT)
+ return;
+
+ if (state == SDL_PRESSED) {
+ TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
+ } else {
+ TouchReleased();
+ }
+}
+
+void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
+ if (state == SDL_PRESSED) {
+ KeyPressed({ key, keyboard_id });
+ } else if (state == SDL_RELEASED) {
+ KeyReleased({ key, keyboard_id });
+ }
+}
+
+bool EmuWindow_SDL2::IsOpen() const {
+ return is_open;
+}
+
+void EmuWindow_SDL2::OnResize() {
+ int width, height;
+
+ SDL_GetWindowSize(render_window, &width, &height);
+
+ NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height));
+}
+
+EmuWindow_SDL2::EmuWindow_SDL2() {
+ keyboard_id = KeyMap::NewDeviceId();
+
+ ReloadSetKeymaps();
+
+ SDL_SetMainReady();
+
+ // Initialize the window
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
+ exit(1);
+ }
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
+ render_window = SDL_CreateWindow(window_title.c_str(),
+ SDL_WINDOWPOS_UNDEFINED, // x position
+ SDL_WINDOWPOS_UNDEFINED, // y position
+ VideoCore::kScreenTopWidth,
+ VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight,
+ SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+
+ if (render_window == nullptr) {
+ LOG_CRITICAL(Frontend, "Failed to create SDL2 window! Exiting...");
+ exit(1);
+ }
+
+ gl_context = SDL_GL_CreateContext(render_window);
+
+ if (gl_context == nullptr) {
+ LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context! Exiting...");
+ exit(1);
+ }
+
+ OnResize();
+ OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
+ SDL_PumpEvents();
+
+ DoneCurrent();
+}
+
+EmuWindow_SDL2::~EmuWindow_SDL2() {
+ SDL_GL_DeleteContext(gl_context);
+ SDL_Quit();
+}
+
+void EmuWindow_SDL2::SwapBuffers() {
+ SDL_GL_SwapWindow(render_window);
+}
+
+void EmuWindow_SDL2::PollEvents() {
+ SDL_Event event;
+
+ // SDL_PollEvent returns 0 when there are no more events in the event queue
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_WINDOWEVENT:
+ switch (event.window.event) {
+ case SDL_WINDOWEVENT_SIZE_CHANGED:
+ case SDL_WINDOWEVENT_RESIZED:
+ case SDL_WINDOWEVENT_MAXIMIZED:
+ case SDL_WINDOWEVENT_RESTORED:
+ case SDL_WINDOWEVENT_MINIMIZED:
+ OnResize();
+ break;
+ case SDL_WINDOWEVENT_CLOSE:
+ is_open = false;
+ break;
+ }
+ break;
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state);
+ break;
+ case SDL_MOUSEMOTION:
+ OnMouseMotion(event.motion.x, event.motion.y);
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y);
+ break;
+ case SDL_QUIT:
+ is_open = false;
+ break;
+ }
+ }
+}
+
+void EmuWindow_SDL2::MakeCurrent() {
+ SDL_GL_MakeCurrent(render_window, gl_context);
+}
+
+void EmuWindow_SDL2::DoneCurrent() {
+ SDL_GL_MakeCurrent(render_window, nullptr);
+}
+
+void EmuWindow_SDL2::ReloadSetKeymaps() {
+ for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
+ KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, Service::HID::pad_mapping[i]);
+ }
+}
+
+void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) {
+ SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
+}
diff --git a/src/citra/emu_window/emu_window_sdl2.h b/src/citra/emu_window/emu_window_sdl2.h
new file mode 100644
index 000000000..77279f022
--- /dev/null
+++ b/src/citra/emu_window/emu_window_sdl2.h
@@ -0,0 +1,64 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <utility>
+
+#include "common/emu_window.h"
+
+struct SDL_Window;
+
+class EmuWindow_SDL2 : public EmuWindow {
+public:
+ EmuWindow_SDL2();
+ ~EmuWindow_SDL2();
+
+ /// Swap buffers to display the next frame
+ void SwapBuffers() override;
+
+ /// Polls window events
+ void PollEvents() override;
+
+ /// Makes the graphics context current for the caller thread
+ void MakeCurrent() override;
+
+ /// Releases the GL context from the caller thread
+ void DoneCurrent() override;
+
+ /// Whether the window is still open, and a close request hasn't yet been sent
+ bool IsOpen() const;
+
+ /// Load keymap from configuration
+ void ReloadSetKeymaps() override;
+
+private:
+ /// Called by PollEvents when a key is pressed or released.
+ void OnKeyEvent(int key, u8 state);
+
+ /// Called by PollEvents when the mouse moves.
+ void OnMouseMotion(s32 x, s32 y);
+
+ /// Called by PollEvents when a mouse button is pressed or released
+ void OnMouseButton(u32 button, u8 state, s32 x, s32 y);
+
+ /// Called by PollEvents when any event that may cause the window to be resized occurs
+ void OnResize();
+
+ /// Called when a configuration change affects the minimal size of the window
+ void OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) override;
+
+ /// Is the window still open?
+ bool is_open = true;
+
+ /// Internal SDL2 render window
+ SDL_Window* render_window;
+
+ using SDL_GLContext = void *;
+ /// The OpenGL context associated with the window
+ SDL_GLContext gl_context;
+
+ /// Device id of keyboard for use with KeyMap
+ int keyboard_id;
+};
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index bbf6ae001..9b3eb2cd6 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -79,7 +79,7 @@ if (APPLE)
else()
add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})
endif()
-target_link_libraries(citra-qt core video_core common qhexedit)
+target_link_libraries(citra-qt core video_core audio_core common qhexedit)
target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
target_link_libraries(citra-qt ${PLATFORM_LIBRARIES})
@@ -88,9 +88,14 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD")
endif()
if (Qt5_FOUND AND MSVC)
+ include(WindowsCopyFiles)
+
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
- set(Qt5_DLLS
+ set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
+ set(PLATFORMS ${DLL_DEST}platforms/)
+
+ windows_copy_files(citra-qt ${Qt5_DLL_DIR} ${DLL_DEST}
icudt*.dll
icuin*.dll
icuuc*.dll
@@ -99,24 +104,8 @@ if (Qt5_FOUND AND MSVC)
Qt5OpenGL$<$<CONFIG:Debug>:d>.*
Qt5Widgets$<$<CONFIG:Debug>:d>.*
)
- set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
- set(PLATFORMS ${DLL_DEST}platforms/)
+ windows_copy_files(citra-qt ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
- # windows commandline expects the / to be \ so switch them
- string(REPLACE "/" "\\\\" Qt5_DLL_DIR ${Qt5_DLL_DIR})
- string(REPLACE "/" "\\\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR})
- string(REPLACE "/" "\\\\" DLL_DEST ${DLL_DEST})
- string(REPLACE "/" "\\\\" PLATFORMS ${PLATFORMS})
-
- # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output
- # cmake adds an extra check for command success which doesn't work too well with robocopy
- # so trick it into thinking the command was successful with the || cmd /c "exit /b 0"
- add_custom_command(TARGET citra-qt POST_BUILD
- COMMAND robocopy ${Qt5_DLL_DIR} ${DLL_DEST} ${Qt5_DLLS} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0"
- COMMAND if not exist ${PLATFORMS} mkdir ${PLATFORMS} 2> nul
- COMMAND robocopy ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.* /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0"
- )
- unset(Qt5_DLLS)
unset(Qt5_DLL_DIR)
unset(Qt5_PLATFORMS_DIR)
unset(DLL_DEST)
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
index d45eed179..793944639 100644
--- a/src/citra_qt/debugger/callstack.cpp
+++ b/src/citra_qt/debugger/callstack.cpp
@@ -29,18 +29,16 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)
void CallstackWidget::OnDebugModeEntered()
{
- ARM_Interface* app_core = Core::g_app_core;
-
- u32 sp = app_core->GetReg(13); //stack pointer
- u32 ret_addr, call_addr, func_addr;
+ // Stack pointer
+ const u32 sp = Core::g_app_core->GetReg(13);
Clear();
int counter = 0;
for (u32 addr = 0x10000000; addr >= sp; addr -= 4)
{
- ret_addr = Memory::Read32(addr);
- call_addr = ret_addr - 4; //get call address???
+ const u32 ret_addr = Memory::Read32(addr);
+ const u32 call_addr = ret_addr - 4; //get call address???
if (Memory::GetPointer(call_addr) == nullptr)
break;
@@ -60,7 +58,7 @@ void CallstackWidget::OnDebugModeEntered()
// Pre-compute the left-shift and the prefetch offset
i_offset <<= 2;
i_offset += 8;
- func_addr = call_addr + i_offset;
+ const u32 func_addr = call_addr + i_offset;
callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0'))));
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp
index ab97c8d2d..5186d2b44 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.cpp
+++ b/src/citra_qt/debugger/graphics_cmdlists.cpp
@@ -21,6 +21,7 @@
#include "common/vector_math.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/debug_utils/debug_utils.h"
QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) {
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index 80b32eaff..c30e75933 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -18,6 +18,7 @@
#include "core/hw/gpu.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/utils.h"
GraphicsFramebufferWidget::GraphicsFramebufferWidget(std::shared_ptr<Pica::DebugContext> debug_context,
diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics_tracing.cpp
index b0bc782df..e06498744 100644
--- a/src/citra_qt/debugger/graphics_tracing.cpp
+++ b/src/citra_qt/debugger/graphics_tracing.cpp
@@ -22,7 +22,7 @@
#include "nihstro/float24.h"
#include "video_core/pica.h"
-
+#include "video_core/pica_state.h"
GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context,
QWidget* parent)
diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp
index a5a5fe6b0..4b676f1b1 100644
--- a/src/citra_qt/debugger/graphics_vertex_shader.cpp
+++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp
@@ -19,6 +19,8 @@
#include "citra_qt/debugger/graphics_vertex_shader.h"
#include "citra_qt/util/util.h"
+#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/shader/shader.h"
using nihstro::OpCode;
@@ -496,8 +498,8 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d
// Reload widget state
for (int attr = 0; attr < num_attributes; ++attr) {
unsigned source_attr = shader_config.input_register_map.GetRegisterForAttribute(attr);
- input_data_mapping[source_attr]->setText(QString("-> v%1").arg(attr));
- input_data_container[source_attr]->setVisible(true);
+ input_data_mapping[attr]->setText(QString("-> v%1").arg(source_attr));
+ input_data_container[attr]->setVisible(true);
}
// Only show input attributes which are used as input to the shader
for (unsigned int attr = num_attributes; attr < 16; ++attr) {
diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp
index 6100d67c5..1bd0bfebc 100644
--- a/src/citra_qt/debugger/registers.cpp
+++ b/src/citra_qt/debugger/registers.cpp
@@ -59,16 +59,14 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) {
}
void RegistersWidget::OnDebugModeEntered() {
- ARM_Interface* app_core = Core::g_app_core;
-
- if (app_core == nullptr)
+ if (!Core::g_app_core)
return;
for (int i = 0; i < core_registers->childCount(); ++i)
- core_registers->child(i)->setText(1, QString("0x%1").arg(app_core->GetReg(i), 8, 16, QLatin1Char('0')));
+ core_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0')));
for (int i = 0; i < vfp_registers->childCount(); ++i)
- vfp_registers->child(i)->setText(1, QString("0x%1").arg(app_core->GetVFPReg(i), 8, 16, QLatin1Char('0')));
+ vfp_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0')));
UpdateCPSRValues();
UpdateVFPSystemRegisterValues();
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index d6c27f0df..57adbc136 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <clocale>
#include <thread>
#include <QDesktopWidget>
@@ -171,6 +172,8 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
}
UpdateRecentFiles();
+ confirm_before_closing = settings.value("confirmClose", true).toBool();
+
// Setup connections
connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)));
connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()));
@@ -208,7 +211,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
show();
- game_list->PopulateAsync(settings.value("gameListRootDir").toString(), settings.value("gameListDeepScan").toBool());
+ game_list->PopulateAsync(settings.value("gameListRootDir", ".").toString(), settings.value("gameListDeepScan", false).toBool());
QStringList args = QApplication::arguments();
if (args.length() >= 2) {
@@ -246,22 +249,73 @@ void GMainWindow::OnDisplayTitleBars(bool show)
}
}
-void GMainWindow::BootGame(const std::string& filename) {
- LOG_INFO(Frontend, "Citra starting...");
-
+bool GMainWindow::InitializeSystem() {
// Shutdown previous session if the emu thread is still active...
if (emu_thread != nullptr)
ShutdownGame();
// Initialize the core emulation
- System::Init(render_window);
+ System::Result system_result = System::Init(render_window);
+ if (System::Result::Success != system_result) {
+ switch (system_result) {
+ case System::Result::ErrorInitVideoCore:
+ QMessageBox::critical(this, tr("Error while starting Citra!"),
+ tr("Failed to initialize the video core!\n\n"
+ "Please ensure that your GPU supports OpenGL 3.3 and that you have the latest graphics driver."));
+ break;
+
+ default:
+ QMessageBox::critical(this, tr("Error while starting Citra!"),
+ tr("Unknown error (please check the log)!"));
+ break;
+ }
+ return false;
+ }
+ return true;
+}
- // Load the game
- if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) {
+bool GMainWindow::LoadROM(const std::string& filename) {
+ Loader::ResultStatus result = Loader::LoadFile(filename);
+ if (Loader::ResultStatus::Success != result) {
LOG_CRITICAL(Frontend, "Failed to load ROM!");
System::Shutdown();
- return;
+
+ switch (result) {
+ case Loader::ResultStatus::ErrorEncrypted: {
+ // Build the MessageBox ourselves to have clickable link
+ QMessageBox popup_error;
+ popup_error.setTextFormat(Qt::RichText);
+ popup_error.setWindowTitle(tr("Error while loading ROM!"));
+ popup_error.setText(tr("The game that you are trying to load must be decrypted before being used with Citra.<br/><br/>"
+ "For more information on dumping and decrypting games, please see: <a href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://citra-emu.org/wiki/Dumping-Game-Cartridges</a>"));
+ popup_error.setIcon(QMessageBox::Critical);
+ popup_error.exec();
+ break;
+ }
+ case Loader::ResultStatus::ErrorInvalidFormat:
+ QMessageBox::critical(this, tr("Error while loading ROM!"),
+ tr("The ROM format is not supported."));
+ break;
+ case Loader::ResultStatus::Error:
+
+ default:
+ QMessageBox::critical(this, tr("Error while loading ROM!"),
+ tr("Unknown error!"));
+ break;
+ }
+ return false;
}
+ return true;
+}
+
+void GMainWindow::BootGame(const std::string& filename) {
+ LOG_INFO(Frontend, "Citra starting...");
+
+ if (!InitializeSystem())
+ return;
+
+ if (!LoadROM(filename))
+ return;
// Create and start the emulation thread
emu_thread = Common::make_unique<EmuThread>(render_window);
@@ -497,7 +551,22 @@ void GMainWindow::OnConfigure() {
//GControllerConfigDialog* dialog = new GControllerConfigDialog(controller_ports, this);
}
+bool GMainWindow::ConfirmClose() {
+ if (emu_thread == nullptr || !confirm_before_closing)
+ return true;
+
+ auto answer = QMessageBox::question(this, tr("Citra"),
+ tr("Are you sure you want to close Citra?"),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+ return answer != QMessageBox::No;
+}
+
void GMainWindow::closeEvent(QCloseEvent* event) {
+ if (!ConfirmClose()) {
+ event->ignore();
+ return;
+ }
+
// Save window layout
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra");
@@ -512,6 +581,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
settings.setValue("singleWindowMode", ui.action_Single_Window_Mode->isChecked());
settings.setValue("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked());
settings.setValue("firstStart", false);
+ settings.setValue("confirmClose", confirm_before_closing);
game_list->SaveInterfaceLayout(settings);
SaveHotkeys(settings);
@@ -545,6 +615,9 @@ int main(int argc, char* argv[]) {
QApplication::setAttribute(Qt::AA_X11InitThreads);
QApplication app(argc, argv);
+ // Qt changes the locale and causes issues in float conversion using std::to_string() when generating shaders
+ setlocale(LC_ALL, "C");
+
GMainWindow main_window;
// After settings have been loaded by GMainWindow, apply the filter
log_filter.ParseFilterString(Settings::values.log_filter);
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index f6d429cd9..945aea0cd 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -59,6 +59,8 @@ signals:
void EmulationStopping();
private:
+ bool InitializeSystem();
+ bool LoadROM(const std::string& filename);
void BootGame(const std::string& filename);
void ShutdownGame();
@@ -82,6 +84,13 @@ private:
*/
void UpdateRecentFiles();
+ /**
+ * If the emulation is running,
+ * asks the user if he really want to close the emulator
+ *
+ * @return true if the user confirmed
+ */
+ bool ConfirmClose();
void closeEvent(QCloseEvent* event) override;
private slots:
@@ -122,6 +131,7 @@ private:
GPUCommandListWidget* graphicsCommandsWidget;
QAction* actions_recent_files[max_recent_files_item];
+ bool confirm_before_closing;
};
#endif // _CITRA_QT_MAIN_HXX_
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 66689f398..371eb17a1 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -115,29 +115,24 @@ template<std::size_t position, std::size_t bits, typename T>
struct BitField
{
private:
- // This constructor might be considered ambiguous:
- // Would it initialize the storage or just the bitfield?
- // Hence, delete it. Use the assignment operator to set bitfield values!
- BitField(T val) = delete;
+ // We hide the copy assigment operator here, because the default copy
+ // assignment would copy the full storage value, rather than just the bits
+ // relevant to this particular bit field.
+ // We don't delete it because we want BitField to be trivially copyable.
+ BitField& operator=(const BitField&) = default;
public:
+ // This constructor and assignment operator might be considered ambiguous:
+ // Would they initialize the storage or just the bitfield?
+ // Hence, delete them. Use the Assign method to set bitfield values!
+ BitField(T val) = delete;
+ BitField& operator=(T val) = delete;
+
// Force default constructor to be created
// so that we can use this within unions
BitField() = default;
- // We explicitly delete the copy assigment operator here, because the
- // default copy assignment would copy the full storage value, rather than
- // just the bits relevant to this particular bit field.
- BitField& operator=(const BitField&) = delete;
-
- FORCE_INLINE BitField& operator=(T val)
- {
- Assign(val);
- return *this;
- }
-
- FORCE_INLINE operator T() const
- {
+ FORCE_INLINE operator T() const {
return Value();
}
@@ -145,8 +140,7 @@ public:
storage = (storage & ~GetMask()) | (((StorageType)value << position) & GetMask());
}
- FORCE_INLINE T Value() const
- {
+ FORCE_INLINE T Value() const {
if (std::numeric_limits<T>::is_signed)
{
std::size_t shift = 8 * sizeof(T)-bits;
@@ -159,8 +153,7 @@ public:
}
// TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
- FORCE_INLINE bool ToBool() const
- {
+ FORCE_INLINE bool ToBool() const {
return Value() != 0;
}
@@ -176,8 +169,7 @@ private:
// Unsigned version of StorageType
typedef typename std::make_unsigned<StorageType>::type StorageTypeU;
- FORCE_INLINE StorageType GetMask() const
- {
+ FORCE_INLINE StorageType GetMask() const {
return (((StorageTypeU)~0) >> (8 * sizeof(T)-bits)) << position;
}
@@ -189,6 +181,10 @@ private:
static_assert(position < 8 * sizeof(T), "Invalid position");
static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
static_assert(bits > 0, "Invalid number of bits");
- static_assert(std::is_standard_layout<T>::value, "Invalid base type");
+ static_assert(std::is_pod<T>::value, "Invalid base type");
};
#pragma pack()
+
+#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
+static_assert(std::is_trivially_copyable<BitField<0, 1, u32>>::value, "BitField must be trivially copyable");
+#endif
diff --git a/src/common/color.h b/src/common/color.h
index eb199e308..908879ea6 100644
--- a/src/common/color.h
+++ b/src/common/color.h
@@ -11,42 +11,42 @@
namespace Color {
/// Convert a 1-bit color component to 8 bit
-inline u8 Convert1To8(u8 value) {
+constexpr u8 Convert1To8(u8 value) {
return value * 255;
}
/// Convert a 4-bit color component to 8 bit
-inline u8 Convert4To8(u8 value) {
+constexpr u8 Convert4To8(u8 value) {
return (value << 4) | value;
}
/// Convert a 5-bit color component to 8 bit
-inline u8 Convert5To8(u8 value) {
+constexpr u8 Convert5To8(u8 value) {
return (value << 3) | (value >> 2);
}
/// Convert a 6-bit color component to 8 bit
-inline u8 Convert6To8(u8 value) {
+constexpr u8 Convert6To8(u8 value) {
return (value << 2) | (value >> 4);
}
/// Convert a 8-bit color component to 1 bit
-inline u8 Convert8To1(u8 value) {
+constexpr u8 Convert8To1(u8 value) {
return value >> 7;
}
/// Convert a 8-bit color component to 4 bit
-inline u8 Convert8To4(u8 value) {
+constexpr u8 Convert8To4(u8 value) {
return value >> 4;
}
/// Convert a 8-bit color component to 5 bit
-inline u8 Convert8To5(u8 value) {
+constexpr u8 Convert8To5(u8 value) {
return value >> 3;
}
/// Convert a 8-bit color component to 6 bit
-inline u8 Convert8To6(u8 value) {
+constexpr u8 Convert8To6(u8 value) {
return value >> 2;
}
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index ed20c3629..aa6aff7b9 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -18,19 +18,11 @@
#define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)]
#define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)]
+// Inlining
#ifdef _WIN32
- // Alignment
#define FORCE_INLINE __forceinline
- #define MEMORY_ALIGNED16(x) __declspec(align(16)) x
- #define MEMORY_ALIGNED32(x) __declspec(align(32)) x
- #define MEMORY_ALIGNED64(x) __declspec(align(64)) x
- #define MEMORY_ALIGNED128(x) __declspec(align(128)) x
#else
#define FORCE_INLINE inline __attribute__((always_inline))
- #define MEMORY_ALIGNED16(x) __attribute__((aligned(16))) x
- #define MEMORY_ALIGNED32(x) __attribute__((aligned(32))) x
- #define MEMORY_ALIGNED64(x) __attribute__((aligned(64))) x
- #define MEMORY_ALIGNED128(x) __attribute__((aligned(128))) x
#endif
#ifndef _MSC_VER
diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp
index b69b05cb9..b2807354a 100644
--- a/src/common/emu_window.cpp
+++ b/src/common/emu_window.cpp
@@ -55,14 +55,14 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
(framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top);
touch_pressed = true;
- pad_state.touch = 1;
+ pad_state.touch.Assign(1);
}
void EmuWindow::TouchReleased() {
touch_pressed = false;
touch_x = 0;
touch_y = 0;
- pad_state.touch = 0;
+ pad_state.touch.Assign(0);
}
void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 4c7113390..c3061479a 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -427,6 +427,9 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo
// How many files + directories we found
unsigned found_entries = 0;
+ // Save the status of callback function
+ bool callback_error = false;
+
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
@@ -454,9 +457,11 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo
if (virtual_name == "." || virtual_name == "..")
continue;
- unsigned ret_entries;
- if (!callback(&ret_entries, directory, virtual_name))
+ unsigned ret_entries = 0;
+ if (!callback(&ret_entries, directory, virtual_name)) {
+ callback_error = true;
break;
+ }
found_entries += ret_entries;
#ifdef _WIN32
@@ -467,9 +472,14 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo
closedir(dirp);
#endif
- // num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it
- if (num_entries_out != nullptr)
- *num_entries_out = found_entries;
+ if (!callback_error) {
+ // num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it
+ if (num_entries_out != nullptr)
+ *num_entries_out = found_entries;
+ return true;
+ } else {
+ return false;
+ }
}
unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry)
diff --git a/src/common/key_map.h b/src/common/key_map.h
index 0ecec714f..68f7e2f99 100644
--- a/src/common/key_map.h
+++ b/src/common/key_map.h
@@ -4,6 +4,7 @@
#pragma once
+#include <tuple>
#include "core/hle/service/hid/hid.h"
namespace KeyMap {
@@ -15,15 +16,14 @@ struct HostDeviceKey {
int key_code;
int device_id; ///< Uniquely identifies a host device
- bool operator < (const HostDeviceKey &other) const {
- if (device_id == other.device_id) {
- return key_code < other.key_code;
- }
- return device_id < other.device_id;
+ bool operator<(const HostDeviceKey &other) const {
+ return std::tie(key_code, device_id) <
+ std::tie(other.key_code, other.device_id);
}
- bool operator == (const HostDeviceKey &other) const {
- return device_id == other.device_id && key_code == other.key_code;
+ bool operator==(const HostDeviceKey &other) const {
+ return std::tie(key_code, device_id) ==
+ std::tie(other.key_code, other.device_id);
}
};
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 21a9ae8d0..54291429a 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -44,10 +44,12 @@ namespace Log {
SUB(Service, LDR) \
SUB(Service, NIM) \
SUB(Service, NWM) \
+ SUB(Service, CAM) \
SUB(Service, CFG) \
SUB(Service, DSP) \
SUB(Service, HID) \
SUB(Service, SOC) \
+ SUB(Service, IR) \
SUB(Service, Y2R) \
CLS(HW) \
SUB(HW, Memory) \
@@ -57,6 +59,8 @@ namespace Log {
CLS(Render) \
SUB(Render, Software) \
SUB(Render, OpenGL) \
+ CLS(Audio) \
+ SUB(Audio, DSP) \
CLS(Loader)
// GetClassName is a macro defined by Windows.h, grrr...
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index c1f4d08e4..795d42ebd 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -27,25 +27,9 @@ struct Entry {
std::string message;
Entry() = default;
+ Entry(Entry&& o) = default;
- // TODO(yuriks) Use defaulted move constructors once MSVC supports them
-#define MOVE(member) member(std::move(o.member))
- Entry(Entry&& o)
- : MOVE(timestamp), MOVE(log_class), MOVE(log_level),
- MOVE(location), MOVE(message)
- {}
-#undef MOVE
-
- Entry& operator=(const Entry&& o) {
-#define MOVE(member) member = std::move(o.member)
- MOVE(timestamp);
- MOVE(log_class);
- MOVE(log_level);
- MOVE(location);
- MOVE(message);
-#undef MOVE
- return *this;
- }
+ Entry& operator=(Entry&& o) = default;
};
/**
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 43f0c59e4..4b01805ae 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -59,10 +59,12 @@ enum class Class : ClassType {
Service_LDR, ///< The LDR (3ds dll loader) service
Service_NIM, ///< The NIM (Network interface manager) service
Service_NWM, ///< The NWM (Network wlan manager) service
+ Service_CAM, ///< The CAM (Camera) service
Service_CFG, ///< The CFG (Configuration) service
Service_DSP, ///< The DSP (DSP control) service
Service_HID, ///< The HID (Human interface device) service
Service_SOC, ///< The SOC (Socket) service
+ Service_IR, ///< The IR service
Service_Y2R, ///< The Y2R (YUV to RGB conversion) service
HW, ///< Low-level hardware emulation
HW_Memory, ///< Memory-map and address translation
@@ -72,6 +74,8 @@ enum class Class : ClassType {
Render, ///< Emulator video output and hardware acceleration
Render_Software, ///< Software renderer backend
Render_OpenGL, ///< OpenGL backend
+ Audio, ///< Emulator audio output
+ Audio_DSP, ///< The HLE implementation of the DSP
Loader, ///< ROM loader
Count ///< Total number of logging classes
diff --git a/src/common/x64/emitter.cpp b/src/common/x64/emitter.cpp
index 939df210e..1dcf2416c 100644
--- a/src/common/x64/emitter.cpp
+++ b/src/common/x64/emitter.cpp
@@ -225,14 +225,14 @@ void OpArg::WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp
// do we need any VEX fields that only appear in the three-byte form?
if (X == 1 && B == 1 && W == 0 && mmmmm == 1)
{
- u8 RvvvvLpp = (R << 7) | (vvvv << 3) | (L << 1) | pp;
+ u8 RvvvvLpp = (R << 7) | (vvvv << 3) | (L << 2) | pp;
emit->Write8(0xC5);
emit->Write8(RvvvvLpp);
}
else
{
u8 RXBmmmmm = (R << 7) | (X << 6) | (B << 5) | mmmmm;
- u8 WvvvvLpp = (W << 7) | (vvvv << 3) | (L << 1) | pp;
+ u8 WvvvvLpp = (W << 7) | (vvvv << 3) | (L << 2) | pp;
emit->Write8(0xC4);
emit->Write8(RXBmmmmm);
emit->Write8(WvvvvLpp);
diff --git a/src/common/x64/emitter.h b/src/common/x64/emitter.h
index 2dd0dc94e..7c6548fb5 100644
--- a/src/common/x64/emitter.h
+++ b/src/common/x64/emitter.h
@@ -157,45 +157,37 @@ class XEmitter;
// RIP addressing does not benefit from micro op fusion on Core arch
struct OpArg
{
- OpArg() {} // dummy op arg, used for storage
- OpArg(u64 _offset, int _scale, X64Reg rmReg = RAX, X64Reg scaledReg = RAX)
+ friend class XEmitter;
+
+ constexpr OpArg() = default; // dummy op arg, used for storage
+ constexpr OpArg(u64 offset_, int scale_, X64Reg rmReg = RAX, X64Reg scaledReg = RAX)
+ : scale(static_cast<u8>(scale_))
+ , offsetOrBaseReg(static_cast<u16>(rmReg))
+ , indexReg(static_cast<u16>(scaledReg))
+ , offset(offset_)
{
- operandReg = 0;
- scale = (u8)_scale;
- offsetOrBaseReg = (u16)rmReg;
- indexReg = (u16)scaledReg;
- //if scale == 0 never mind offsetting
- offset = _offset;
}
- bool operator==(const OpArg &b) const
+
+ constexpr bool operator==(const OpArg &b) const
{
- return operandReg == b.operandReg && scale == b.scale && offsetOrBaseReg == b.offsetOrBaseReg &&
- indexReg == b.indexReg && offset == b.offset;
+ return operandReg == b.operandReg &&
+ scale == b.scale &&
+ offsetOrBaseReg == b.offsetOrBaseReg &&
+ indexReg == b.indexReg &&
+ offset == b.offset;
}
+
void WriteRex(XEmitter *emit, int opBits, int bits, int customOp = -1) const;
void WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp, int mmmmm, int W = 0) const;
void WriteRest(XEmitter *emit, int extraBytes=0, X64Reg operandReg=INVALID_REG, bool warn_64bit_offset = true) const;
- void WriteFloatModRM(XEmitter *emit, FloatOp op);
void WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg operandReg, int bits);
- // This one is public - must be written to
- u64 offset; // use RIP-relative as much as possible - 64-bit immediates are not available.
- u16 operandReg;
-
void WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &operand, int bits) const;
- bool IsImm() const {return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64;}
- bool IsSimpleReg() const {return scale == SCALE_NONE;}
- bool IsSimpleReg(X64Reg reg) const
- {
- if (!IsSimpleReg())
- return false;
- return GetSimpleReg() == reg;
- }
- bool CanDoOpWith(const OpArg &other) const
+ constexpr bool IsImm() const { return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64; }
+ constexpr bool IsSimpleReg() const { return scale == SCALE_NONE; }
+ constexpr bool IsSimpleReg(X64Reg reg) const
{
- if (IsSimpleReg()) return true;
- if (!IsSimpleReg() && !other.IsSimpleReg() && !other.IsImm()) return false;
- return true;
+ return IsSimpleReg() && GetSimpleReg() == reg;
}
int GetImmBits() const
@@ -220,16 +212,15 @@ struct OpArg
}
}
- X64Reg GetSimpleReg() const
+ constexpr X64Reg GetSimpleReg() const
{
- if (scale == SCALE_NONE)
- return (X64Reg)offsetOrBaseReg;
- else
- return INVALID_REG;
+ return scale == SCALE_NONE
+ ? static_cast<X64Reg>(offsetOrBaseReg)
+ : INVALID_REG;
}
- u32 GetImmValue() const {
- return (u32)offset;
+ constexpr u32 GetImmValue() const {
+ return static_cast<u32>(offset);
}
// For loops.
@@ -238,56 +229,60 @@ struct OpArg
}
private:
- u8 scale;
- u16 offsetOrBaseReg;
- u16 indexReg;
+ u8 scale = 0;
+ u16 offsetOrBaseReg = 0;
+ u16 indexReg = 0;
+ u64 offset = 0; // use RIP-relative as much as possible - 64-bit immediates are not available.
+ u16 operandReg = 0;
};
-inline OpArg M(const void *ptr) {return OpArg((u64)ptr, (int)SCALE_RIP);}
template <typename T>
-inline OpArg M(const T *ptr) {return OpArg((u64)(const void *)ptr, (int)SCALE_RIP);}
-inline OpArg R(X64Reg value) {return OpArg(0, SCALE_NONE, value);}
-inline OpArg MatR(X64Reg value) {return OpArg(0, SCALE_ATREG, value);}
+inline OpArg M(const T *ptr) { return OpArg(reinterpret_cast<u64>(ptr), static_cast<int>(SCALE_RIP)); }
+constexpr OpArg R(X64Reg value) { return OpArg(0, SCALE_NONE, value); }
+constexpr OpArg MatR(X64Reg value) { return OpArg(0, SCALE_ATREG, value); }
-inline OpArg MDisp(X64Reg value, int offset)
+constexpr OpArg MDisp(X64Reg value, int offset)
{
- return OpArg((u32)offset, SCALE_ATREG, value);
+ return OpArg(static_cast<u32>(offset), SCALE_ATREG, value);
}
-inline OpArg MComplex(X64Reg base, X64Reg scaled, int scale, int offset)
+constexpr OpArg MComplex(X64Reg base, X64Reg scaled, int scale, int offset)
{
return OpArg(offset, scale, base, scaled);
}
-inline OpArg MScaled(X64Reg scaled, int scale, int offset)
+constexpr OpArg MScaled(X64Reg scaled, int scale, int offset)
{
- if (scale == SCALE_1)
- return OpArg(offset, SCALE_ATREG, scaled);
- else
- return OpArg(offset, scale | 0x20, RAX, scaled);
+ return scale == SCALE_1
+ ? OpArg(offset, SCALE_ATREG, scaled)
+ : OpArg(offset, scale | 0x20, RAX, scaled);
}
-inline OpArg MRegSum(X64Reg base, X64Reg offset)
+constexpr OpArg MRegSum(X64Reg base, X64Reg offset)
{
return MComplex(base, offset, 1, 0);
}
-inline OpArg Imm8 (u8 imm) {return OpArg(imm, SCALE_IMM8);}
-inline OpArg Imm16(u16 imm) {return OpArg(imm, SCALE_IMM16);} //rarely used
-inline OpArg Imm32(u32 imm) {return OpArg(imm, SCALE_IMM32);}
-inline OpArg Imm64(u64 imm) {return OpArg(imm, SCALE_IMM64);}
-inline OpArg UImmAuto(u32 imm) {
+constexpr OpArg Imm8 (u8 imm) { return OpArg(imm, SCALE_IMM8); }
+constexpr OpArg Imm16(u16 imm) { return OpArg(imm, SCALE_IMM16); } //rarely used
+constexpr OpArg Imm32(u32 imm) { return OpArg(imm, SCALE_IMM32); }
+constexpr OpArg Imm64(u64 imm) { return OpArg(imm, SCALE_IMM64); }
+constexpr OpArg UImmAuto(u32 imm) {
return OpArg(imm, imm >= 128 ? SCALE_IMM32 : SCALE_IMM8);
}
-inline OpArg SImmAuto(s32 imm) {
+constexpr OpArg SImmAuto(s32 imm) {
return OpArg(imm, (imm >= 128 || imm < -128) ? SCALE_IMM32 : SCALE_IMM8);
}
+template <typename T>
+OpArg ImmPtr(const T* imm)
+{
#ifdef _ARCH_64
-inline OpArg ImmPtr(const void* imm) {return Imm64((u64)imm);}
+ return Imm64(reinterpret_cast<u64>(imm));
#else
-inline OpArg ImmPtr(const void* imm) {return Imm32((u32)imm);}
+ return Imm32(reinterpret_cast<u32>(imm));
#endif
+}
inline u32 PtrOffset(const void* ptr, const void* base)
{
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index d21f198e5..35b61dada 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -252,6 +252,7 @@ set(HEADERS
tracer/citrace.h
memory.h
memory_setup.h
+ mmio.h
settings.h
system.h
)
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 5cffe513c..533067d4f 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -14,10 +14,6 @@ namespace Core {
/// Generic ARM11 CPU interface
class ARM_Interface : NonCopyable {
public:
- ARM_Interface() {
- num_instructions = 0;
- }
-
virtual ~ARM_Interface() {
}
@@ -146,11 +142,11 @@ public:
virtual void PrepareReschedule() = 0;
/// Getter for num_instructions
- u64 GetNumInstructions() {
+ u64 GetNumInstructions() const {
return num_instructions;
}
- s64 down_count; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop
+ s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop
protected:
@@ -162,6 +158,5 @@ protected:
private:
- u64 num_instructions; ///< Number of instructions executed
-
+ u64 num_instructions = 0; ///< Number of instructions executed
};
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index 76408e9fa..5ad1f1c29 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -738,23 +738,23 @@ std::string ARM_Disasm::DisassembleMemHalf(u32 insn)
if (is_immed) {
if (is_pre) {
if (offset == 0) {
- return Common::StringFromFormat("%s%sh\tr%d, [r%d]", opname, cond_to_str(cond), rd, rn);
+ return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), width, rd, rn);
} else {
- return Common::StringFromFormat("%s%sh\tr%d, [r%d, #%s%u]%s",
- opname, cond_to_str(cond), rd, rn, minus, offset, bang);
+ return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s",
+ opname, cond_to_str(cond), width, rd, rn, minus, offset, bang);
}
} else {
- return Common::StringFromFormat("%s%sh\tr%d, [r%d], #%s%u",
- opname, cond_to_str(cond), rd, rn, minus, offset);
+ return Common::StringFromFormat("%s%s%s\tr%d, [r%d], #%s%u",
+ opname, cond_to_str(cond), width, rd, rn, minus, offset);
}
}
if (is_pre) {
- return Common::StringFromFormat("%s%sh\tr%d, [r%d, %sr%d]%s",
- opname, cond_to_str(cond), rd, rn, minus, rm, bang);
+ return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s",
+ opname, cond_to_str(cond), width, rd, rn, minus, rm, bang);
} else {
- return Common::StringFromFormat("%s%sh\tr%d, [r%d], %sr%d",
- opname, cond_to_str(cond), rd, rn, minus, rm);
+ return Common::StringFromFormat("%s%s%s\tr%d, [r%d], %sr%d",
+ opname, cond_to_str(cond), width, rd, rn, minus, rm);
}
}
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index ee4288314..8cd6755cb 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -6,10 +6,9 @@
#include "core/arm/skyeye_common/armsupp.h"
const InstructionSetEncodingItem arm_instruction[] = {
- { "vmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }},
- { "vmls", 7, ARMVFP2, { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }},
- { "vnmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }},
- { "vnmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
+ { "vmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
+ { "vmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
+ { "vnmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
{ "vnmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
{ "vnmul", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
{ "vmul", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
@@ -211,7 +210,6 @@ const InstructionSetEncodingItem arm_exclusion_code[] = {
{ "vmla", 0, ARMVFP2, { 0 }},
{ "vmls", 0, ARMVFP2, { 0 }},
{ "vnmla", 0, ARMVFP2, { 0 }},
- { "vnmla", 0, ARMVFP2, { 0 }},
{ "vnmls", 0, ARMVFP2, { 0 }},
{ "vnmul", 0, ARMVFP2, { 0 }},
{ "vmul", 0, ARMVFP2, { 0 }},
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 96c88c83a..5f8826034 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -51,7 +51,7 @@ enum {
typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
-static bool CondPassed(ARMul_State* cpu, unsigned int cond) {
+static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
const bool n_flag = cpu->NFlag != 0;
const bool z_flag = cpu->ZFlag != 0;
const bool c_flag = cpu->CFlag != 0;
@@ -1623,9 +1623,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index)
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index)
@@ -1646,9 +1643,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index)
DEBUG_MSG;
}
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index)
@@ -1703,9 +1697,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index)
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index)
@@ -1720,9 +1711,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index)
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index)
@@ -1737,9 +1725,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index)
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
@@ -2597,9 +2582,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index)
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index)
@@ -2645,9 +2627,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index)
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index)
@@ -2669,9 +2648,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index)
DEBUG_MSG;
}
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
@@ -2685,9 +2661,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index)
@@ -2729,9 +2702,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
inst_cream->inst = inst;
inst_cream->get_addr = get_calc_addr_op(inst);
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index)
@@ -2757,9 +2727,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index)
DEBUG_MSG;
}
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index)
@@ -2808,9 +2775,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index)
inst_cream->Rd = BITS(inst, 12, 15);
inst_cream->Rm = BITS(inst, 0, 3);
- if (inst_cream->Rd == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){
@@ -2825,9 +2789,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){
inst_cream->Rd = BITS(inst, 12, 15);
inst_cream->Rm = BITS(inst, 0, 3);
- if (inst_cream->Rd == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
return inst_base;
}
static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){
@@ -2915,9 +2876,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
inst_cream->shifter_operand = BITS(inst, 0, 11);
inst_cream->shtop_func = get_shtop(inst);
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
return inst_base;
}
@@ -3244,7 +3202,6 @@ const transop_fp_t arm_instruction_trans[] = {
INTERPRETER_TRANSLATE(vmla),
INTERPRETER_TRANSLATE(vmls),
INTERPRETER_TRANSLATE(vnmla),
- INTERPRETER_TRANSLATE(vnmla),
INTERPRETER_TRANSLATE(vnmls),
INTERPRETER_TRANSLATE(vnmul),
INTERPRETER_TRANSLATE(vmul),
@@ -3636,209 +3593,208 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
case 0: goto VMLA_INST; \
case 1: goto VMLS_INST; \
case 2: goto VNMLA_INST; \
- case 3: goto VNMLA_INST; \
- case 4: goto VNMLS_INST; \
- case 5: goto VNMUL_INST; \
- case 6: goto VMUL_INST; \
- case 7: goto VADD_INST; \
- case 8: goto VSUB_INST; \
- case 9: goto VDIV_INST; \
- case 10: goto VMOVI_INST; \
- case 11: goto VMOVR_INST; \
- case 12: goto VABS_INST; \
- case 13: goto VNEG_INST; \
- case 14: goto VSQRT_INST; \
- case 15: goto VCMP_INST; \
- case 16: goto VCMP2_INST; \
- case 17: goto VCVTBDS_INST; \
- case 18: goto VCVTBFF_INST; \
- case 19: goto VCVTBFI_INST; \
- case 20: goto VMOVBRS_INST; \
- case 21: goto VMSR_INST; \
- case 22: goto VMOVBRC_INST; \
- case 23: goto VMRS_INST; \
- case 24: goto VMOVBCR_INST; \
- case 25: goto VMOVBRRSS_INST; \
- case 26: goto VMOVBRRD_INST; \
- case 27: goto VSTR_INST; \
- case 28: goto VPUSH_INST; \
- case 29: goto VSTM_INST; \
- case 30: goto VPOP_INST; \
- case 31: goto VLDR_INST; \
- case 32: goto VLDM_INST ; \
- case 33: goto SRS_INST; \
- case 34: goto RFE_INST; \
- case 35: goto BKPT_INST; \
- case 36: goto BLX_INST; \
- case 37: goto CPS_INST; \
- case 38: goto PLD_INST; \
- case 39: goto SETEND_INST; \
- case 40: goto CLREX_INST; \
- case 41: goto REV16_INST; \
- case 42: goto USAD8_INST; \
- case 43: goto SXTB_INST; \
- case 44: goto UXTB_INST; \
- case 45: goto SXTH_INST; \
- case 46: goto SXTB16_INST; \
- case 47: goto UXTH_INST; \
- case 48: goto UXTB16_INST; \
- case 49: goto CPY_INST; \
- case 50: goto UXTAB_INST; \
- case 51: goto SSUB8_INST; \
- case 52: goto SHSUB8_INST; \
- case 53: goto SSUBADDX_INST; \
- case 54: goto STREX_INST; \
- case 55: goto STREXB_INST; \
- case 56: goto SWP_INST; \
- case 57: goto SWPB_INST; \
- case 58: goto SSUB16_INST; \
- case 59: goto SSAT16_INST; \
- case 60: goto SHSUBADDX_INST; \
- case 61: goto QSUBADDX_INST; \
- case 62: goto SHADDSUBX_INST; \
- case 63: goto SHADD8_INST; \
- case 64: goto SHADD16_INST; \
- case 65: goto SEL_INST; \
- case 66: goto SADDSUBX_INST; \
- case 67: goto SADD8_INST; \
- case 68: goto SADD16_INST; \
- case 69: goto SHSUB16_INST; \
- case 70: goto UMAAL_INST; \
- case 71: goto UXTAB16_INST; \
- case 72: goto USUBADDX_INST; \
- case 73: goto USUB8_INST; \
- case 74: goto USUB16_INST; \
- case 75: goto USAT16_INST; \
- case 76: goto USADA8_INST; \
- case 77: goto UQSUBADDX_INST; \
- case 78: goto UQSUB8_INST; \
- case 79: goto UQSUB16_INST; \
- case 80: goto UQADDSUBX_INST; \
- case 81: goto UQADD8_INST; \
- case 82: goto UQADD16_INST; \
- case 83: goto SXTAB_INST; \
- case 84: goto UHSUBADDX_INST; \
- case 85: goto UHSUB8_INST; \
- case 86: goto UHSUB16_INST; \
- case 87: goto UHADDSUBX_INST; \
- case 88: goto UHADD8_INST; \
- case 89: goto UHADD16_INST; \
- case 90: goto UADDSUBX_INST; \
- case 91: goto UADD8_INST; \
- case 92: goto UADD16_INST; \
- case 93: goto SXTAH_INST; \
- case 94: goto SXTAB16_INST; \
- case 95: goto QADD8_INST; \
- case 96: goto BXJ_INST; \
- case 97: goto CLZ_INST; \
- case 98: goto UXTAH_INST; \
- case 99: goto BX_INST; \
- case 100: goto REV_INST; \
- case 101: goto BLX_INST; \
- case 102: goto REVSH_INST; \
- case 103: goto QADD_INST; \
- case 104: goto QADD16_INST; \
- case 105: goto QADDSUBX_INST; \
- case 106: goto LDREX_INST; \
- case 107: goto QDADD_INST; \
- case 108: goto QDSUB_INST; \
- case 109: goto QSUB_INST; \
- case 110: goto LDREXB_INST; \
- case 111: goto QSUB8_INST; \
- case 112: goto QSUB16_INST; \
- case 113: goto SMUAD_INST; \
- case 114: goto SMMUL_INST; \
- case 115: goto SMUSD_INST; \
- case 116: goto SMLSD_INST; \
- case 117: goto SMLSLD_INST; \
- case 118: goto SMMLA_INST; \
- case 119: goto SMMLS_INST; \
- case 120: goto SMLALD_INST; \
- case 121: goto SMLAD_INST; \
- case 122: goto SMLAW_INST; \
- case 123: goto SMULW_INST; \
- case 124: goto PKHTB_INST; \
- case 125: goto PKHBT_INST; \
- case 126: goto SMUL_INST; \
- case 127: goto SMLALXY_INST; \
- case 128: goto SMLA_INST; \
- case 129: goto MCRR_INST; \
- case 130: goto MRRC_INST; \
- case 131: goto CMP_INST; \
- case 132: goto TST_INST; \
- case 133: goto TEQ_INST; \
- case 134: goto CMN_INST; \
- case 135: goto SMULL_INST; \
- case 136: goto UMULL_INST; \
- case 137: goto UMLAL_INST; \
- case 138: goto SMLAL_INST; \
- case 139: goto MUL_INST; \
- case 140: goto MLA_INST; \
- case 141: goto SSAT_INST; \
- case 142: goto USAT_INST; \
- case 143: goto MRS_INST; \
- case 144: goto MSR_INST; \
- case 145: goto AND_INST; \
- case 146: goto BIC_INST; \
- case 147: goto LDM_INST; \
- case 148: goto EOR_INST; \
- case 149: goto ADD_INST; \
- case 150: goto RSB_INST; \
- case 151: goto RSC_INST; \
- case 152: goto SBC_INST; \
- case 153: goto ADC_INST; \
- case 154: goto SUB_INST; \
- case 155: goto ORR_INST; \
- case 156: goto MVN_INST; \
- case 157: goto MOV_INST; \
- case 158: goto STM_INST; \
- case 159: goto LDM_INST; \
- case 160: goto LDRSH_INST; \
- case 161: goto STM_INST; \
- case 162: goto LDM_INST; \
- case 163: goto LDRSB_INST; \
- case 164: goto STRD_INST; \
- case 165: goto LDRH_INST; \
- case 166: goto STRH_INST; \
- case 167: goto LDRD_INST; \
- case 168: goto STRT_INST; \
- case 169: goto STRBT_INST; \
- case 170: goto LDRBT_INST; \
- case 171: goto LDRT_INST; \
- case 172: goto MRC_INST; \
- case 173: goto MCR_INST; \
+ case 3: goto VNMLS_INST; \
+ case 4: goto VNMUL_INST; \
+ case 5: goto VMUL_INST; \
+ case 6: goto VADD_INST; \
+ case 7: goto VSUB_INST; \
+ case 8: goto VDIV_INST; \
+ case 9: goto VMOVI_INST; \
+ case 10: goto VMOVR_INST; \
+ case 11: goto VABS_INST; \
+ case 12: goto VNEG_INST; \
+ case 13: goto VSQRT_INST; \
+ case 14: goto VCMP_INST; \
+ case 15: goto VCMP2_INST; \
+ case 16: goto VCVTBDS_INST; \
+ case 17: goto VCVTBFF_INST; \
+ case 18: goto VCVTBFI_INST; \
+ case 19: goto VMOVBRS_INST; \
+ case 20: goto VMSR_INST; \
+ case 21: goto VMOVBRC_INST; \
+ case 22: goto VMRS_INST; \
+ case 23: goto VMOVBCR_INST; \
+ case 24: goto VMOVBRRSS_INST; \
+ case 25: goto VMOVBRRD_INST; \
+ case 26: goto VSTR_INST; \
+ case 27: goto VPUSH_INST; \
+ case 28: goto VSTM_INST; \
+ case 29: goto VPOP_INST; \
+ case 30: goto VLDR_INST; \
+ case 31: goto VLDM_INST ; \
+ case 32: goto SRS_INST; \
+ case 33: goto RFE_INST; \
+ case 34: goto BKPT_INST; \
+ case 35: goto BLX_INST; \
+ case 36: goto CPS_INST; \
+ case 37: goto PLD_INST; \
+ case 38: goto SETEND_INST; \
+ case 39: goto CLREX_INST; \
+ case 40: goto REV16_INST; \
+ case 41: goto USAD8_INST; \
+ case 42: goto SXTB_INST; \
+ case 43: goto UXTB_INST; \
+ case 44: goto SXTH_INST; \
+ case 45: goto SXTB16_INST; \
+ case 46: goto UXTH_INST; \
+ case 47: goto UXTB16_INST; \
+ case 48: goto CPY_INST; \
+ case 49: goto UXTAB_INST; \
+ case 50: goto SSUB8_INST; \
+ case 51: goto SHSUB8_INST; \
+ case 52: goto SSUBADDX_INST; \
+ case 53: goto STREX_INST; \
+ case 54: goto STREXB_INST; \
+ case 55: goto SWP_INST; \
+ case 56: goto SWPB_INST; \
+ case 57: goto SSUB16_INST; \
+ case 58: goto SSAT16_INST; \
+ case 59: goto SHSUBADDX_INST; \
+ case 60: goto QSUBADDX_INST; \
+ case 61: goto SHADDSUBX_INST; \
+ case 62: goto SHADD8_INST; \
+ case 63: goto SHADD16_INST; \
+ case 64: goto SEL_INST; \
+ case 65: goto SADDSUBX_INST; \
+ case 66: goto SADD8_INST; \
+ case 67: goto SADD16_INST; \
+ case 68: goto SHSUB16_INST; \
+ case 69: goto UMAAL_INST; \
+ case 70: goto UXTAB16_INST; \
+ case 71: goto USUBADDX_INST; \
+ case 72: goto USUB8_INST; \
+ case 73: goto USUB16_INST; \
+ case 74: goto USAT16_INST; \
+ case 75: goto USADA8_INST; \
+ case 76: goto UQSUBADDX_INST; \
+ case 77: goto UQSUB8_INST; \
+ case 78: goto UQSUB16_INST; \
+ case 79: goto UQADDSUBX_INST; \
+ case 80: goto UQADD8_INST; \
+ case 81: goto UQADD16_INST; \
+ case 82: goto SXTAB_INST; \
+ case 83: goto UHSUBADDX_INST; \
+ case 84: goto UHSUB8_INST; \
+ case 85: goto UHSUB16_INST; \
+ case 86: goto UHADDSUBX_INST; \
+ case 87: goto UHADD8_INST; \
+ case 88: goto UHADD16_INST; \
+ case 89: goto UADDSUBX_INST; \
+ case 90: goto UADD8_INST; \
+ case 91: goto UADD16_INST; \
+ case 92: goto SXTAH_INST; \
+ case 93: goto SXTAB16_INST; \
+ case 94: goto QADD8_INST; \
+ case 95: goto BXJ_INST; \
+ case 96: goto CLZ_INST; \
+ case 97: goto UXTAH_INST; \
+ case 98: goto BX_INST; \
+ case 99: goto REV_INST; \
+ case 100: goto BLX_INST; \
+ case 101: goto REVSH_INST; \
+ case 102: goto QADD_INST; \
+ case 103: goto QADD16_INST; \
+ case 104: goto QADDSUBX_INST; \
+ case 105: goto LDREX_INST; \
+ case 106: goto QDADD_INST; \
+ case 107: goto QDSUB_INST; \
+ case 108: goto QSUB_INST; \
+ case 109: goto LDREXB_INST; \
+ case 110: goto QSUB8_INST; \
+ case 111: goto QSUB16_INST; \
+ case 112: goto SMUAD_INST; \
+ case 113: goto SMMUL_INST; \
+ case 114: goto SMUSD_INST; \
+ case 115: goto SMLSD_INST; \
+ case 116: goto SMLSLD_INST; \
+ case 117: goto SMMLA_INST; \
+ case 118: goto SMMLS_INST; \
+ case 119: goto SMLALD_INST; \
+ case 120: goto SMLAD_INST; \
+ case 121: goto SMLAW_INST; \
+ case 122: goto SMULW_INST; \
+ case 123: goto PKHTB_INST; \
+ case 124: goto PKHBT_INST; \
+ case 125: goto SMUL_INST; \
+ case 126: goto SMLALXY_INST; \
+ case 127: goto SMLA_INST; \
+ case 128: goto MCRR_INST; \
+ case 129: goto MRRC_INST; \
+ case 130: goto CMP_INST; \
+ case 131: goto TST_INST; \
+ case 132: goto TEQ_INST; \
+ case 133: goto CMN_INST; \
+ case 134: goto SMULL_INST; \
+ case 135: goto UMULL_INST; \
+ case 136: goto UMLAL_INST; \
+ case 137: goto SMLAL_INST; \
+ case 138: goto MUL_INST; \
+ case 139: goto MLA_INST; \
+ case 140: goto SSAT_INST; \
+ case 141: goto USAT_INST; \
+ case 142: goto MRS_INST; \
+ case 143: goto MSR_INST; \
+ case 144: goto AND_INST; \
+ case 145: goto BIC_INST; \
+ case 146: goto LDM_INST; \
+ case 147: goto EOR_INST; \
+ case 148: goto ADD_INST; \
+ case 149: goto RSB_INST; \
+ case 150: goto RSC_INST; \
+ case 151: goto SBC_INST; \
+ case 152: goto ADC_INST; \
+ case 153: goto SUB_INST; \
+ case 154: goto ORR_INST; \
+ case 155: goto MVN_INST; \
+ case 156: goto MOV_INST; \
+ case 157: goto STM_INST; \
+ case 158: goto LDM_INST; \
+ case 159: goto LDRSH_INST; \
+ case 160: goto STM_INST; \
+ case 161: goto LDM_INST; \
+ case 162: goto LDRSB_INST; \
+ case 163: goto STRD_INST; \
+ case 164: goto LDRH_INST; \
+ case 165: goto STRH_INST; \
+ case 166: goto LDRD_INST; \
+ case 167: goto STRT_INST; \
+ case 168: goto STRBT_INST; \
+ case 169: goto LDRBT_INST; \
+ case 170: goto LDRT_INST; \
+ case 171: goto MRC_INST; \
+ case 172: goto MCR_INST; \
+ case 173: goto MSR_INST; \
case 174: goto MSR_INST; \
case 175: goto MSR_INST; \
case 176: goto MSR_INST; \
case 177: goto MSR_INST; \
- case 178: goto MSR_INST; \
- case 179: goto LDRB_INST; \
- case 180: goto STRB_INST; \
- case 181: goto LDR_INST; \
- case 182: goto LDRCOND_INST ; \
- case 183: goto STR_INST; \
- case 184: goto CDP_INST; \
- case 185: goto STC_INST; \
- case 186: goto LDC_INST; \
- case 187: goto LDREXD_INST; \
- case 188: goto STREXD_INST; \
- case 189: goto LDREXH_INST; \
- case 190: goto STREXH_INST; \
- case 191: goto NOP_INST; \
- case 192: goto YIELD_INST; \
- case 193: goto WFE_INST; \
- case 194: goto WFI_INST; \
- case 195: goto SEV_INST; \
- case 196: goto SWI_INST; \
- case 197: goto BBL_INST; \
- case 198: goto B_2_THUMB ; \
- case 199: goto B_COND_THUMB ; \
- case 200: goto BL_1_THUMB ; \
- case 201: goto BL_2_THUMB ; \
- case 202: goto BLX_1_THUMB ; \
- case 203: goto DISPATCH; \
- case 204: goto INIT_INST_LENGTH; \
- case 205: goto END; \
+ case 178: goto LDRB_INST; \
+ case 179: goto STRB_INST; \
+ case 180: goto LDR_INST; \
+ case 181: goto LDRCOND_INST ; \
+ case 182: goto STR_INST; \
+ case 183: goto CDP_INST; \
+ case 184: goto STC_INST; \
+ case 185: goto LDC_INST; \
+ case 186: goto LDREXD_INST; \
+ case 187: goto STREXD_INST; \
+ case 188: goto LDREXH_INST; \
+ case 189: goto STREXH_INST; \
+ case 190: goto NOP_INST; \
+ case 191: goto YIELD_INST; \
+ case 192: goto WFE_INST; \
+ case 193: goto WFI_INST; \
+ case 194: goto SEV_INST; \
+ case 195: goto SWI_INST; \
+ case 196: goto BBL_INST; \
+ case 197: goto B_2_THUMB ; \
+ case 198: goto B_COND_THUMB ; \
+ case 199: goto BL_1_THUMB ; \
+ case 200: goto BL_2_THUMB ; \
+ case 201: goto BLX_1_THUMB ; \
+ case 202: goto DISPATCH; \
+ case 203: goto INIT_INST_LENGTH; \
+ case 204: goto END; \
}
#endif
@@ -3865,7 +3821,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
// to a clunky switch statement.
#if defined __GNUC__ || defined __clang__
void *InstLabel[] = {
- &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST,
+ &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST,
&&VDIV_INST, &&VMOVI_INST, &&VMOVR_INST, &&VABS_INST, &&VNEG_INST, &&VSQRT_INST, &&VCMP_INST, &&VCMP2_INST, &&VCVTBDS_INST,
&&VCVTBFF_INST, &&VCVTBFI_INST, &&VMOVBRS_INST, &&VMSR_INST, &&VMOVBRC_INST, &&VMRS_INST, &&VMOVBCR_INST, &&VMOVBRRSS_INST,
&&VMOVBRRD_INST, &&VSTR_INST, &&VPUSH_INST, &&VSTM_INST, &&VPOP_INST, &&VLDR_INST, &&VLDM_INST,
@@ -4477,11 +4433,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
inst_cream->get_addr(cpu, inst_cream->inst, addr);
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr);
-
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
@@ -4494,12 +4445,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr);
+ const u32 dest_index = BITS(inst_cream->inst, 12, 15);
+ const u32 previous_mode = cpu->Mode;
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
+ cpu->ChangePrivilegeMode(USER32MODE);
+ const u8 value = cpu->ReadMemory8(addr);
+ cpu->ChangePrivilegeMode(previous_mode);
+
+ cpu->Reg[dest_index] = value;
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
@@ -4535,10 +4488,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->SetExclusiveMemoryAddress(read_addr);
RD = cpu->ReadMemory32(read_addr);
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(generic_arm_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
@@ -4554,10 +4503,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->SetExclusiveMemoryAddress(read_addr);
RD = cpu->ReadMemory8(read_addr);
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(generic_arm_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
@@ -4573,10 +4518,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->SetExclusiveMemoryAddress(read_addr);
RD = cpu->ReadMemory16(read_addr);
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(generic_arm_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
@@ -4593,11 +4534,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = cpu->ReadMemory32(read_addr);
RD2 = cpu->ReadMemory32(read_addr + 4);
-
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(generic_arm_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
@@ -4611,10 +4547,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
inst_cream->get_addr(cpu, inst_cream->inst, addr);
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
@@ -4631,10 +4563,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
value |= 0xffffff00;
}
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
@@ -4652,10 +4580,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
value |= 0xffff0000;
}
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
@@ -4668,13 +4592,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = cpu->ReadMemory32(addr);
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
+ const u32 dest_index = BITS(inst_cream->inst, 12, 15);
+ const u32 previous_mode = cpu->Mode;
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
+ cpu->ChangePrivilegeMode(USER32MODE);
+ const u32 value = cpu->ReadMemory32(addr);
+ cpu->ChangePrivilegeMode(previous_mode);
+
+ cpu->Reg[dest_index] = value;
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
@@ -4731,10 +4656,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
UPDATE_NFLAG(RD);
UPDATE_ZFLAG(RD);
}
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(mla_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mla_inst));
@@ -4773,18 +4694,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
- unsigned int inst = inst_cream->inst;
- if (inst_cream->Rd == 15) {
- DEBUG_MSG;
- }
- if (inst_cream->inst == 0xeef04a10) {
- // Undefined instruction fmrx
- RD = 0x20000000;
- CITRA_IGNORE_EXIT(-1);
- goto END;
- } else {
- if (inst_cream->cp_num == 15)
- RD = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
+ if (inst_cream->cp_num == 15) {
+ const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
+
+ if (inst_cream->Rd == 15) {
+ cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000);
+ LOAD_NZCVT;
+ } else {
+ RD = value;
+ }
}
}
cpu->Reg[15] += cpu->GetInstructionSize();
@@ -4883,10 +4801,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
UPDATE_NFLAG(RD);
UPDATE_ZFLAG(RD);
}
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(mul_inst));
- goto DISPATCH;
- }
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mul_inst));
@@ -6061,8 +5975,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
+
+ const u32 previous_mode = cpu->Mode;
+ const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
+
+ cpu->ChangePrivilegeMode(USER32MODE);
cpu->WriteMemory8(addr, value);
+ cpu->ChangePrivilegeMode(previous_mode);
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
@@ -6196,8 +6115,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
+ const u32 previous_mode = cpu->Mode;
+ const u32 rt_index = BITS(inst_cream->inst, 12, 15);
+
+ u32 value = cpu->Reg[rt_index];
+ if (rt_index == 15)
+ value += 2 * cpu->GetInstructionSize();
+
+ cpu->ChangePrivilegeMode(USER32MODE);
cpu->WriteMemory32(addr, value);
+ cpu->ChangePrivilegeMode(previous_mode);
}
cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h
index 13bef17fc..8eb694fee 100644
--- a/src/core/arm/dyncom/arm_dyncom_run.h
+++ b/src/core/arm/dyncom/arm_dyncom_run.h
@@ -30,7 +30,7 @@
* @return If the PC is being read, then the word-aligned PC value is returned.
* If the PC is not being read, then the value stored in the register is returned.
*/
-static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) {
+inline u32 CHECK_READ_REG15_WA(const ARMul_State* cpu, int Rn) {
return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
}
@@ -43,6 +43,6 @@ static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) {
* @return If the PC is being read, then the incremented PC value is returned.
* If the PC is not being read, then the values stored in the register is returned.
*/
-static inline u32 CHECK_READ_REG15(ARMul_State* cpu, int Rn) {
+inline u32 CHECK_READ_REG15(const ARMul_State* cpu, int Rn) {
return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
index 447974363..c1be3c735 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.h
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.h
@@ -38,7 +38,7 @@ enum class ThumbDecodeStatus {
// Translates a Thumb mode instruction into its ARM equivalent.
ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
-static inline u32 GetThumbInstruction(u32 instr, u32 address) {
+inline u32 GetThumbInstruction(u32 instr, u32 address) {
// Normally you would need to handle instruction endianness,
// however, it is fixed to little-endian on the MPCore, so
// there's no need to check for this beforehand.
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 91a8d4d57..210972917 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -85,7 +85,7 @@ enum : u32 {
#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00)
-static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
+inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
{
if (shift) {
if (shift < 32)
@@ -96,7 +96,7 @@ static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
return val;
}
-static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
+inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
{
if (shift) {
if (shift < 64)
@@ -107,7 +107,7 @@ static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
return val;
}
-static inline u32 vfp_hi64to32jamming(u64 val)
+inline u32 vfp_hi64to32jamming(u64 val)
{
u32 v;
u32 highval = val >> 32;
@@ -121,7 +121,7 @@ static inline u32 vfp_hi64to32jamming(u64 val)
return v;
}
-static inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
+inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
{
*resl = nl + ml;
*resh = nh + mh;
@@ -129,7 +129,7 @@ static inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
*resh += 1;
}
-static inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
+inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
{
*resl = nl - ml;
*resh = nh - mh;
@@ -137,7 +137,7 @@ static inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
*resh -= 1;
}
-static inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
+inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
{
u32 nh, nl, mh, ml;
u64 rh, rma, rmb, rl;
@@ -164,20 +164,20 @@ static inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
*resh = rh;
}
-static inline void shift64left(u64* resh, u64* resl, u64 n)
+inline void shift64left(u64* resh, u64* resl, u64 n)
{
*resh = n >> 63;
*resl = n << 1;
}
-static inline u64 vfp_hi64multiply64(u64 n, u64 m)
+inline u64 vfp_hi64multiply64(u64 n, u64 m)
{
u64 rh, rl;
mul64to128(&rh, &rl, n, m);
return rh | (rl != 0);
}
-static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
+inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
{
u64 mh, ml, remh, reml, termh, terml, z;
@@ -249,7 +249,7 @@ enum : u32 {
VFP_SNAN = (VFP_NAN|VFP_NAN_SIGNAL)
};
-static inline int vfp_single_type(vfp_single* s)
+inline int vfp_single_type(const vfp_single* s)
{
int type = VFP_NUMBER;
if (s->exponent == 255) {
@@ -271,7 +271,7 @@ static inline int vfp_single_type(vfp_single* s)
// Unpack a single-precision float. Note that this returns the magnitude
// of the single-precision float mantissa with the 1. if necessary,
// aligned to bit 30.
-static inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
+inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
{
s->sign = vfp_single_packed_sign(val) >> 16,
s->exponent = vfp_single_packed_exponent(val);
@@ -293,7 +293,7 @@ static inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
// Re-pack a single-precision float. This assumes that the float is
// already normalised such that the MSB is bit 30, _not_ bit 31.
-static inline s32 vfp_single_pack(vfp_single* s)
+inline s32 vfp_single_pack(const vfp_single* s)
{
u32 val = (s->sign << 16) +
(s->exponent << VFP_SINGLE_MANTISSA_BITS) +
@@ -335,7 +335,7 @@ struct vfp_double {
#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
-static inline int vfp_double_type(vfp_double* s)
+inline int vfp_double_type(const vfp_double* s)
{
int type = VFP_NUMBER;
if (s->exponent == 2047) {
@@ -357,7 +357,7 @@ static inline int vfp_double_type(vfp_double* s)
// Unpack a double-precision float. Note that this returns the magnitude
// of the double-precision float mantissa with the 1. if necessary,
// aligned to bit 62.
-static inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
+inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
{
s->sign = vfp_double_packed_sign(val) >> 48;
s->exponent = vfp_double_packed_exponent(val);
@@ -379,7 +379,7 @@ static inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
// Re-pack a double-precision float. This assumes that the float is
// already normalised such that the MSB is bit 30, _not_ bit 31.
-static inline s64 vfp_double_pack(vfp_double* s)
+inline s64 vfp_double_pack(const vfp_double* s)
{
u64 val = ((u64)s->sign << 48) +
((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
@@ -415,7 +415,7 @@ struct op {
u32 flags;
};
-static inline u32 fls(u32 x)
+inline u32 fls(u32 x)
{
int r = 32;
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 219b03af4..84d6c392e 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -2,6 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <memory>
+
+#include "common/make_unique.h"
#include "common/logging/log.h"
#include "core/core.h"
@@ -17,8 +20,8 @@
namespace Core {
-ARM_Interface* g_app_core = nullptr; ///< ARM11 application core
-ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core
+std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core
+std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core
/// Run the core CPU loop
void RunLoop(int tight_loop) {
@@ -70,17 +73,16 @@ void Stop() {
}
/// Initialize the core
-int Init() {
- g_sys_core = new ARM_DynCom(USER32MODE);
- g_app_core = new ARM_DynCom(USER32MODE);
+void Init() {
+ g_sys_core = Common::make_unique<ARM_DynCom>(USER32MODE);
+ g_app_core = Common::make_unique<ARM_DynCom>(USER32MODE);
LOG_DEBUG(Core, "Initialized OK");
- return 0;
}
void Shutdown() {
- delete g_app_core;
- delete g_sys_core;
+ g_app_core.reset();
+ g_sys_core.reset();
LOG_DEBUG(Core, "Shutdown OK");
}
diff --git a/src/core/core.h b/src/core/core.h
index 491230a74..ad26dca3f 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -4,6 +4,7 @@
#pragma once
+#include <memory>
#include "common/common_types.h"
class ARM_Interface;
@@ -23,8 +24,8 @@ struct ThreadContext {
u32 fpexc;
};
-extern ARM_Interface* g_app_core; ///< ARM11 application core
-extern ARM_Interface* g_sys_core; ///< ARM11 system (OS) core
+extern std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core
+extern std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -51,7 +52,7 @@ void Halt(const char *msg);
void Stop();
/// Initialize the core
-int Init();
+void Init();
/// Shutdown the core
void Shutdown();
diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp
index 3f81447df..97adf0e12 100644
--- a/src/core/file_sys/archive_backend.cpp
+++ b/src/core/file_sys/archive_backend.cpp
@@ -43,7 +43,7 @@ Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) {
}
}
-const std::string Path::DebugStr() const {
+std::string Path::DebugStr() const {
switch (GetType()) {
case Invalid:
default:
@@ -66,7 +66,7 @@ const std::string Path::DebugStr() const {
}
}
-const std::string Path::AsString() const {
+std::string Path::AsString() const {
switch (GetType()) {
case Char:
return string;
@@ -83,7 +83,7 @@ const std::string Path::AsString() const {
}
}
-const std::u16string Path::AsU16Str() const {
+std::u16string Path::AsU16Str() const {
switch (GetType()) {
case Char:
return Common::UTF8ToUTF16(string);
@@ -99,7 +99,7 @@ const std::u16string Path::AsU16Str() const {
}
}
-const std::vector<u8> Path::AsBinary() const {
+std::vector<u8> Path::AsBinary() const {
switch (GetType()) {
case Binary:
return binary;
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index e7a59a1ed..601e95d8c 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -49,11 +49,11 @@ public:
* Gets the string representation of the path for debugging
* @return String representation of the path for debugging
*/
- const std::string DebugStr() const;
+ std::string DebugStr() const;
- const std::string AsString() const;
- const std::u16string AsU16Str() const;
- const std::vector<u8> AsBinary() const;
+ std::string AsString() const;
+ std::u16string AsU16Str() const;
+ std::vector<u8> AsBinary() const;
private:
LowPathType type;
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
index 0ba502200..a51416774 100644
--- a/src/core/file_sys/disk_archive.cpp
+++ b/src/core/file_sys/disk_archive.cpp
@@ -139,7 +139,7 @@ bool DiskFile::Close() const {
////////////////////////////////////////////////////////////////////////////////////////////////////
-DiskDirectory::DiskDirectory(const DiskArchive& archive, const Path& path) {
+DiskDirectory::DiskDirectory(const DiskArchive& archive, const Path& path) : directory() {
// TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
// the root directory we set while opening the archive.
// For example, opening /../../usr/bin can give the emulated program your installed programs.
@@ -149,7 +149,9 @@ DiskDirectory::DiskDirectory(const DiskArchive& archive, const Path& path) {
bool DiskDirectory::Open() {
if (!FileUtil::IsDirectory(path))
return false;
- FileUtil::ScanDirectoryTree(path, directory);
+ unsigned size = FileUtil::ScanDirectoryTree(path, directory);
+ directory.size = size;
+ directory.isDirectory = true;
children_iterator = directory.children.begin();
return true;
}
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 3501e45db..882a51df1 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -188,6 +188,10 @@ template<ResultCode func(s64*, Handle, u32)> void Wrap() {
FuncReturn(retval);
}
+template<ResultCode func(Handle, u32)> void Wrap() {
+ FuncReturn(func(PARAM(0), PARAM(1)).raw);
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u32
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 195286422..5c3c47acf 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -45,30 +45,32 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
// Wait current thread (acquire the arbiter)...
case ArbitrationType::WaitIfLessThan:
- if ((s32)Memory::Read32(address) <= value) {
+ if ((s32)Memory::Read32(address) < value) {
Kernel::WaitCurrentThread_ArbitrateAddress(address);
}
break;
case ArbitrationType::WaitIfLessThanWithTimeout:
- if ((s32)Memory::Read32(address) <= value) {
+ if ((s32)Memory::Read32(address) < value) {
Kernel::WaitCurrentThread_ArbitrateAddress(address);
GetCurrentThread()->WakeAfterDelay(nanoseconds);
}
break;
case ArbitrationType::DecrementAndWaitIfLessThan:
{
- s32 memory_value = Memory::Read32(address) - 1;
- Memory::Write32(address, memory_value);
- if (memory_value <= value) {
+ s32 memory_value = Memory::Read32(address);
+ if (memory_value < value) {
+ // Only change the memory value if the thread should wait
+ Memory::Write32(address, (s32)memory_value - 1);
Kernel::WaitCurrentThread_ArbitrateAddress(address);
}
break;
}
case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout:
{
- s32 memory_value = Memory::Read32(address) - 1;
- Memory::Write32(address, memory_value);
- if (memory_value <= value) {
+ s32 memory_value = Memory::Read32(address);
+ if (memory_value < value) {
+ // Only change the memory value if the thread should wait
+ Memory::Write32(address, (s32)memory_value - 1);
Kernel::WaitCurrentThread_ArbitrateAddress(address);
GetCurrentThread()->WakeAfterDelay(nanoseconds);
}
@@ -82,6 +84,13 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
HLE::Reschedule(__func__);
+ // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep
+ if (type == ArbitrationType::WaitIfLessThanWithTimeout ||
+ type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) {
+
+ return ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
+ ErrorSummary::StatusChanged, ErrorLevel::Info);
+ }
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 0cfb43fc7..862643448 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -7,6 +7,8 @@
#include <utility>
#include <vector>
+#include "audio_core/audio_core.h"
+
#include "common/common_types.h"
#include "common/logging/log.h"
@@ -107,7 +109,6 @@ struct MemoryArea {
static MemoryArea memory_areas[] = {
{SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory
{VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM)
- {DSP_RAM_VADDR, DSP_RAM_SIZE, "DSP RAM"}, // DSP memory
{TLS_AREA_VADDR, TLS_AREA_SIZE, "TLS Area"}, // TLS memory
};
@@ -133,6 +134,8 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) {
auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR,
(u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom();
address_space.Reprotect(shared_page_vma, VMAPermission::Read);
+
+ AudioCore::AddAddressSpace(address_space);
}
} // namespace
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index d148efde2..24b266eae 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -35,7 +35,7 @@ SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) {
process->codeset = std::move(code_set);
process->flags.raw = 0;
- process->flags.memory_region = MemoryRegion::APPLICATION;
+ process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
Memory::InitLegacyAddressSpace(process->vm_manager);
return process;
@@ -130,9 +130,11 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority);
}
+VAddr Process::GetLinearHeapAreaAddress() const {
+ return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR;
+}
VAddr Process::GetLinearHeapBase() const {
- return (kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR)
- + memory_region->base;
+ return GetLinearHeapAreaAddress() + memory_region->base;
}
VAddr Process::GetLinearHeapLimit() const {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 60e17f251..6d2ca96a2 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -143,6 +143,7 @@ public:
/// Bitmask of the used TLS slots
std::bitset<300> used_tls_slots;
+ VAddr GetLinearHeapAreaAddress() const;
VAddr GetLinearHeapBase() const;
VAddr GetLinearHeapLimit() const;
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 1f477664b..d90f0f00f 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -39,6 +39,12 @@ ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
}
+ // TODO(Subv): Return E0E01BEE when permissions and other_permissions don't
+ // match what was specified when the memory block was created.
+
+ // TODO(Subv): Return E0E01BEE when address should be 0.
+ // Note: Find out when that's the case.
+
if (fixed_address != 0) {
if (address != 0 && address != fixed_address) {
LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s: fixed_addres is 0x%08X!",
@@ -74,6 +80,21 @@ ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
return RESULT_SUCCESS;
}
+ResultCode SharedMemory::Unmap(VAddr address) {
+ if (base_address == 0) {
+ // TODO(Subv): Verify what actually happens when you want to unmap a memory block that
+ // was originally mapped with address = 0
+ return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
+ }
+
+ if (base_address != address)
+ return ResultCode(ErrorDescription::WrongAddress, ErrorModule::OS, ErrorSummary::InvalidState, ErrorLevel::Usage);
+
+ base_address = 0;
+
+ return RESULT_SUCCESS;
+}
+
u8* SharedMemory::GetPointer(u32 offset) {
if (base_address != 0)
return Memory::GetPointer(base_address + offset);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 35b550d12..b51049ad0 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -53,6 +53,13 @@ public:
ResultCode Map(VAddr address, MemoryPermission permissions, MemoryPermission other_permissions);
/**
+ * Unmaps a shared memory block from the specified address in system memory
+ * @param address Address in system memory where the shared memory block is mapped
+ * @return Result code of the unmap operation
+ */
+ ResultCode Unmap(VAddr address);
+
+ /**
* Gets a pointer to the shared memory block
* @param offset Offset from the start of the shared memory block to get pointer
* @return Pointer to the shared memory block from the specified offset
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index c08fc1c7a..bf32f653d 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -300,7 +300,7 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
thread->waitsynch_waited = false;
- if (thread->status == THREADSTATUS_WAIT_SYNCH) {
+ if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
ErrorSummary::StatusChanged, ErrorLevel::Info));
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 08b3ea8c0..ce6bbd719 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -42,6 +42,9 @@ bool Timer::ShouldWait() {
void Timer::Acquire() {
ASSERT_MSG( !ShouldWait(), "object unavailable!");
+
+ if (reset_type == RESETTYPE_ONESHOT)
+ signaled = false;
}
void Timer::Set(s64 initial, s64 interval) {
@@ -84,9 +87,6 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
// Resume all waiting threads
timer->WakeupAllWaitingThreads();
- if (timer->reset_type == RESETTYPE_ONESHOT)
- timer->signaled = false;
-
if (timer->interval_delay != 0) {
// Reschedule the timer with the interval delay
u64 interval_microseconds = timer->interval_delay / 1000;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 2610acf76..1e289f38a 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -8,6 +8,7 @@
#include "core/hle/kernel/vm_manager.h"
#include "core/memory_setup.h"
+#include "core/mmio.h"
namespace Kernel {
@@ -104,7 +105,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * m
return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
}
-ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state) {
+ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) {
// This is the appropriately sized VMA that will turn into our allocation.
CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
VirtualMemoryArea& final_vma = vma_handle->second;
@@ -114,6 +115,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u3
final_vma.permissions = VMAPermission::ReadWrite;
final_vma.meminfo_state = state;
final_vma.paddr = paddr;
+ final_vma.mmio_handler = mmio_handler;
UpdatePageTableForVMA(final_vma);
return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
@@ -330,8 +332,7 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
Memory::MapMemoryRegion(vma.base, vma.size, vma.backing_memory);
break;
case VMAType::MMIO:
- // TODO(yuriks): Add support for MMIO handlers.
- Memory::MapIoRegion(vma.base, vma.size);
+ Memory::MapIoRegion(vma.base, vma.size, vma.mmio_handler);
break;
}
}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 4e95f1f0c..91d40655b 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -11,6 +11,7 @@
#include "common/common_types.h"
#include "core/hle/result.h"
+#include "core/mmio.h"
namespace Kernel {
@@ -92,6 +93,7 @@ struct VirtualMemoryArea {
// Settings for type = MMIO
/// Physical address of the register area this VMA maps to.
PAddr paddr = 0;
+ Memory::MMIORegionPointer mmio_handler = nullptr;
/// Tests if this area can be merged to the right with `next`.
bool CanBeMergedWith(const VirtualMemoryArea& next) const;
@@ -168,8 +170,9 @@ public:
* @param paddr The physical address where the registers are present.
* @param size Size of the mapping.
* @param state MemoryState tag to attach to the VMA.
+ * @param mmio_handler The handler that will implement read and write for this MMIO region.
*/
- ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state);
+ ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler);
/// Unmaps a range of addresses, splitting VMAs as necessary.
ResultCode UnmapRange(VAddr target, u32 size);
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index cb2d681e0..69613fbbb 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -18,6 +18,7 @@
/// Detailed description of the error. This listing is likely incomplete.
enum class ErrorDescription : u32 {
Success = 0,
+ WrongAddress = 53,
FS_NotFound = 100,
FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive
InvalidSection = 1000,
@@ -192,10 +193,10 @@ union ResultCode {
explicit ResultCode(u32 raw) : raw(raw) {}
ResultCode(ErrorDescription description_, ErrorModule module_,
ErrorSummary summary_, ErrorLevel level_) : raw(0) {
- description = description_;
- module = module_;
- summary = summary_;
- level = level_;
+ description.Assign(description_);
+ module.Assign(module_);
+ summary.Assign(summary_);
+ level.Assign(level_);
}
ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; }
@@ -268,7 +269,6 @@ public:
: result_code(error_code)
{
ASSERT(error_code.IsError());
- UpdateDebugPtr();
}
/**
@@ -286,40 +286,37 @@ public:
: result_code(o.result_code)
{
if (!o.empty()) {
- new (&storage) T(*o.GetPointer());
+ new (&object) T(o.object);
}
- UpdateDebugPtr();
}
ResultVal(ResultVal&& o)
: result_code(o.result_code)
{
if (!o.empty()) {
- new (&storage) T(std::move(*o.GetPointer()));
+ new (&object) T(std::move(o.object));
}
- UpdateDebugPtr();
}
~ResultVal() {
if (!empty()) {
- GetPointer()->~T();
+ object.~T();
}
}
ResultVal& operator=(const ResultVal& o) {
if (!empty()) {
if (!o.empty()) {
- *GetPointer() = *o.GetPointer();
+ object = o.object;
} else {
- GetPointer()->~T();
+ object.~T();
}
} else {
if (!o.empty()) {
- new (&storage) T(*o.GetPointer());
+ new (&object) T(o.object);
}
}
result_code = o.result_code;
- UpdateDebugPtr();
return *this;
}
@@ -332,11 +329,10 @@ public:
void emplace(ResultCode success_code, Args&&... args) {
ASSERT(success_code.IsSuccess());
if (!empty()) {
- GetPointer()->~T();
+ object.~T();
}
- new (&storage) T(std::forward<Args>(args)...);
+ new (&object) T(std::forward<Args>(args)...);
result_code = success_code;
- UpdateDebugPtr();
}
/// Returns true if the `ResultVal` contains an error code and no value.
@@ -349,15 +345,15 @@ public:
ResultCode Code() const { return result_code; }
- const T& operator* () const { return *GetPointer(); }
- T& operator* () { return *GetPointer(); }
- const T* operator->() const { return GetPointer(); }
- T* operator->() { return GetPointer(); }
+ const T& operator* () const { return object; }
+ T& operator* () { return object; }
+ const T* operator->() const { return &object; }
+ T* operator->() { return &object; }
/// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
template <typename U>
T ValueOr(U&& value) const {
- return !empty() ? *GetPointer() : std::move(value);
+ return !empty() ? object : std::move(value);
}
/// Asserts that the result succeeded and returns a reference to it.
@@ -371,31 +367,10 @@ public:
}
private:
- typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType;
-
- StorageType storage;
+ // A union is used to allocate the storage for the value, while allowing us to construct and
+ // destruct it at will.
+ union { T object; };
ResultCode result_code;
-#ifdef _DEBUG
- // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the
- // need to cast `storage` to a pointer or pay attention to `result_code`.
- const T* debug_ptr;
-#endif
-
- void UpdateDebugPtr() {
-#ifdef _DEBUG
- debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage));
-#endif
- }
-
- const T* GetPointer() const {
- ASSERT(!empty());
- return static_cast<const T*>(static_cast<const void*>(&storage));
- }
-
- T* GetPointer() {
- ASSERT(!empty());
- return static_cast<T*>(static_cast<void*>(&storage));
- }
};
/**
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index f8aab6bc7..d67325506 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include "common/logging/log.h"
-#include "core/hle/hle.h"
#include "core/hle/service/ac_u.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -23,12 +22,27 @@ static void GetWifiStatus(Service::Interface* self) {
// TODO(purpasmart96): This function is only a stub,
// it returns a valid result without implementing full functionality.
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 0; // Connection type set to none
LOG_WARNING(Service_AC, "(STUBBED) called");
}
+/**
+ * AC_U::IsConnected service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : bool, is connected
+ */
+static void IsConnected(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = false; // Not connected to ac:u service
+
+ LOG_WARNING(Service_AC, "(STUBBED) called");
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010000, nullptr, "CreateDefaultConfig"},
{0x00040006, nullptr, "ConnectAsync"},
@@ -45,7 +59,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x002D0082, nullptr, "SetRequestEulaVersion"},
{0x00300004, nullptr, "RegisterDisconnectEvent"},
{0x003C0042, nullptr, "GetAPSSIDList"},
- {0x003E0042, nullptr, "IsConnected"},
+ {0x003E0042, IsConnected, "IsConnected"},
{0x00400042, nullptr, "SetClientVersion"},
};
diff --git a/src/core/hle/service/act_u.cpp b/src/core/hle/service/act_u.cpp
index 57f49c91f..b23d17fba 100644
--- a/src/core/hle/service/act_u.cpp
+++ b/src/core/hle/service/act_u.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/act_u.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -10,14 +9,15 @@
namespace ACT_U {
-// Empty arrays are illegal -- commented out until an entry is added.
-//const Interface::FunctionInfo FunctionTable[] = { };
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000600C2, nullptr, "GetAccountDataBlock"},
+};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Interface class
Interface::Interface() {
- //Register(FunctionTable);
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 7ae4859a7..06be9940e 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -10,10 +10,6 @@
#include "core/hle/service/am/am_net.h"
#include "core/hle/service/am/am_sys.h"
-#include "core/hle/hle.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-
namespace Service {
namespace AM {
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 0b78f5393..15e63bc7b 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -4,10 +4,10 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/service.h"
-
namespace Service {
+
+class Interface;
+
namespace AM {
/**
diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp
index f40a87cb4..16c76a1eb 100644
--- a/src/core/hle/service/am/am_app.cpp
+++ b/src/core/hle/service/am/am_app.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/am_app.h"
diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp
index aa391f3b2..065e04118 100644
--- a/src/core/hle/service/am/am_net.cpp
+++ b/src/core/hle/service/am/am_net.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/am_net.h"
@@ -10,6 +9,36 @@ namespace Service {
namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
+ {0x00020082, GetTitleIDList, "GetTitleIDList"},
+ {0x00030084, nullptr, "ListTitles"},
+ {0x000400C0, nullptr, "DeleteApplicationTitle"},
+ {0x000500C0, nullptr, "GetTitleProductCode"},
+ {0x00080000, nullptr, "TitleIDListGetTotal3"},
+ {0x00090082, nullptr, "GetTitleIDList3"},
+ {0x000A0000, nullptr, "GetDeviceID"},
+ {0x000D0084, nullptr, "ListTitles2"},
+ {0x00140040, nullptr, "FinishInstallToMedia"},
+ {0x00180080, nullptr, "InitializeTitleDatabase"},
+ {0x00190040, nullptr, "ReloadDBS"},
+ {0x001A00C0, nullptr, "GetDSiWareExportSize"},
+ {0x001B0144, nullptr, "ExportDSiWare"},
+ {0x001C0084, nullptr, "ImportDSiWare"},
+ {0x00230080, nullptr, "TitleIDListGetTotal2"},
+ {0x002400C2, nullptr, "GetTitleIDList2"},
+ {0x04010080, nullptr, "InstallFIRM"},
+ {0x04020040, nullptr, "StartInstallCIADB0"},
+ {0x04030000, nullptr, "StartInstallCIADB1"},
+ {0x04040002, nullptr, "AbortCIAInstall"},
+ {0x04050002, nullptr, "CloseCIAFinalizeInstall"},
+ {0x04060002, nullptr, "CloseCIA"},
+ {0x040700C2, nullptr, "FinalizeTitlesInstall"},
+ {0x04080042, nullptr, "GetCiaFileInfo"},
+ {0x040E00C2, nullptr, "InstallTitlesFinish"},
+ {0x040F0000, nullptr, "InstallNATIVEFIRM"},
+ {0x041000C0, nullptr, "DeleteTitle"},
+ {0x04120000, nullptr, "Initialize"},
+ {0x041700C0, nullptr, "MigrateAGBtoSAV"},
{0x08010000, nullptr, "OpenTicket"},
{0x08020002, nullptr, "TicketAbortInstall"},
{0x08030002, nullptr, "TicketFinalizeInstall"},
diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp
index 864fc14df..e38812297 100644
--- a/src/core/hle/service/am/am_sys.cpp
+++ b/src/core/hle/service/am/am_sys.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/am_sys.h"
@@ -12,6 +11,21 @@ namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
{0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
{0x00020082, GetTitleIDList, "GetTitleIDList"},
+ {0x00030084, nullptr, "ListTitles"},
+ {0x000400C0, nullptr, "DeleteApplicationTitle"},
+ {0x000500C0, nullptr, "GetTitleProductCode"},
+ {0x00080000, nullptr, "TitleIDListGetTotal3"},
+ {0x00090082, nullptr, "GetTitleIDList3"},
+ {0x000A0000, nullptr, "GetDeviceID"},
+ {0x000D0084, nullptr, "ListTitles2"},
+ {0x00140040, nullptr, "FinishInstallToMedia"},
+ {0x00180080, nullptr, "InitializeTitleDatabase"},
+ {0x00190040, nullptr, "ReloadDBS"},
+ {0x001A00C0, nullptr, "GetDSiWareExportSize"},
+ {0x001B0144, nullptr, "ExportDSiWare"},
+ {0x001C0084, nullptr, "ImportDSiWare"},
+ {0x00230080, nullptr, "TitleIDListGetTotal2"},
+ {0x002400C2, nullptr, "GetTitleIDList2"}
};
AM_SYS_Interface::AM_SYS_Interface() {
diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp
index 6bf84b36b..c0392b754 100644
--- a/src/core/hle/service/am/am_u.cpp
+++ b/src/core/hle/service/am/am_u.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/am_u.h"
@@ -12,6 +11,34 @@ namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
{0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
{0x00020082, GetTitleIDList, "GetTitleIDList"},
+ {0x00030084, nullptr, "ListTitles"},
+ {0x000400C0, nullptr, "DeleteApplicationTitle"},
+ {0x000500C0, nullptr, "GetTitleProductCode"},
+ {0x00080000, nullptr, "TitleIDListGetTotal3"},
+ {0x00090082, nullptr, "GetTitleIDList3"},
+ {0x000A0000, nullptr, "GetDeviceID"},
+ {0x000D0084, nullptr, "ListTitles2"},
+ {0x00140040, nullptr, "FinishInstallToMedia"},
+ {0x00180080, nullptr, "InitializeTitleDatabase"},
+ {0x00190040, nullptr, "ReloadDBS"},
+ {0x001A00C0, nullptr, "GetDSiWareExportSize"},
+ {0x001B0144, nullptr, "ExportDSiWare"},
+ {0x001C0084, nullptr, "ImportDSiWare"},
+ {0x00230080, nullptr, "TitleIDListGetTotal2"},
+ {0x002400C2, nullptr, "GetTitleIDList2"},
+ {0x04010080, nullptr, "InstallFIRM"},
+ {0x04020040, nullptr, "StartInstallCIADB0"},
+ {0x04030000, nullptr, "StartInstallCIADB1"},
+ {0x04040002, nullptr, "AbortCIAInstall"},
+ {0x04050002, nullptr, "CloseCIAFinalizeInstall"},
+ {0x04060002, nullptr, "CloseCIA"},
+ {0x040700C2, nullptr, "FinalizeTitlesInstall"},
+ {0x04080042, nullptr, "GetCiaFileInfo"},
+ {0x040E00C2, nullptr, "InstallTitlesFinish"},
+ {0x040F0000, nullptr, "InstallNATIVEFIRM"},
+ {0x041000C0, nullptr, "DeleteTitle"},
+ {0x04120000, nullptr, "Initialize"},
+ {0x041700C0, nullptr, "MigrateAGBtoSAV"}
};
AM_U_Interface::AM_U_Interface() {
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index feb579778..98c72fc32 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -14,12 +14,10 @@
#include "core/hle/service/apt/apt_u.h"
#include "core/hle/service/fs/archive.h"
-#include "core/hle/hle.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/kernel/thread.h"
namespace Service {
namespace APT {
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index 22800c56f..0c6a77305 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/apt/apt.h"
#include "core/hle/service/apt/apt_a.h"
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp
index 3ac6ff94f..7f6e81a63 100644
--- a/src/core/hle/service/apt/apt_s.cpp
+++ b/src/core/hle/service/apt/apt_s.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
#include "core/hle/service/apt/apt.h"
#include "core/hle/service/apt/apt_s.h"
@@ -91,6 +89,12 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x004E0000, nullptr, "HardwareResetAsync"},
{0x004F0080, nullptr, "SetApplicationCpuTimeLimit"},
{0x00500040, nullptr, "GetApplicationCpuTimeLimit"},
+ {0x00510080, nullptr, "GetStartupArgument"},
+ {0x00520104, nullptr, "Wrap1"},
+ {0x00530104, nullptr, "Unwrap1"},
+ {0x00580002, nullptr, "GetProgramID"},
+ {0x01010000, nullptr, "CheckNew3DSApp"},
+ {0x01020000, nullptr, "CheckNew3DS"}
};
APT_S_Interface::APT_S_Interface() {
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index 2e9d1f4b4..b13b51549 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -2,9 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-
-#include "common/file_util.h"
-
#include "core/hle/service/apt/apt.h"
#include "core/hle/service/apt/apt_u.h"
@@ -92,6 +89,12 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x004E0000, nullptr, "HardwareResetAsync"},
{0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
{0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
+ {0x00510080, nullptr, "GetStartupArgument"},
+ {0x00520104, nullptr, "Wrap1"},
+ {0x00530104, nullptr, "Unwrap1"},
+ {0x00580002, nullptr, "GetProgramID"},
+ {0x01010000, nullptr, "CheckNew3DSApp"},
+ {0x01020000, nullptr, "CheckNew3DS"}
};
APT_U_Interface::APT_U_Interface() {
diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp
index d38140f19..419ec976e 100644
--- a/src/core/hle/service/boss/boss.cpp
+++ b/src/core/hle/service/boss/boss.cpp
@@ -7,10 +7,6 @@
#include "core/hle/service/boss/boss_p.h"
#include "core/hle/service/boss/boss_u.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/hle.h"
-
namespace Service {
namespace BOSS {
diff --git a/src/core/hle/service/boss/boss.h b/src/core/hle/service/boss/boss.h
index a6942ada6..d3b5d7101 100644
--- a/src/core/hle/service/boss/boss.h
+++ b/src/core/hle/service/boss/boss.h
@@ -4,9 +4,6 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/service.h"
-
namespace Service {
namespace BOSS {
diff --git a/src/core/hle/service/boss/boss_p.cpp b/src/core/hle/service/boss/boss_p.cpp
index 089f5f186..c498abe4e 100644
--- a/src/core/hle/service/boss/boss_p.cpp
+++ b/src/core/hle/service/boss/boss_p.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/boss/boss.h"
#include "core/hle/service/boss/boss_p.h"
namespace Service {
diff --git a/src/core/hle/service/boss/boss_u.cpp b/src/core/hle/service/boss/boss_u.cpp
index ed978b963..d59babe71 100644
--- a/src/core/hle/service/boss/boss_u.cpp
+++ b/src/core/hle/service/boss/boss_u.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/boss/boss.h"
#include "core/hle/service/boss/boss_u.h"
namespace Service {
@@ -11,6 +9,9 @@ namespace BOSS {
const Interface::FunctionInfo FunctionTable[] = {
{0x00020100, nullptr, "GetStorageInfo"},
+ {0x000C0082, nullptr, "UnregisterTask"},
+ {0x001E0042, nullptr, "CancelTask"},
+ {0x00330042, nullptr, "StartBgImmediate"},
};
BOSS_U_Interface::BOSS_U_Interface() {
diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp
index 4f34b699b..4d714037f 100644
--- a/src/core/hle/service/cam/cam.cpp
+++ b/src/core/hle/service/cam/cam.cpp
@@ -4,20 +4,287 @@
#include "common/logging/log.h"
-#include "core/hle/service/service.h"
+#include "core/hle/kernel/event.h"
#include "core/hle/service/cam/cam.h"
#include "core/hle/service/cam/cam_c.h"
#include "core/hle/service/cam/cam_q.h"
#include "core/hle/service/cam/cam_s.h"
#include "core/hle/service/cam/cam_u.h"
-
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/hle.h"
+#include "core/hle/service/service.h"
namespace Service {
namespace CAM {
+static const u32 TRANSFER_BYTES = 5 * 1024;
+
+static Kernel::SharedPtr<Kernel::Event> completion_event_cam1;
+static Kernel::SharedPtr<Kernel::Event> completion_event_cam2;
+static Kernel::SharedPtr<Kernel::Event> interrupt_error_event;
+static Kernel::SharedPtr<Kernel::Event> vsync_interrupt_error_event;
+
+void StartCapture(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
+}
+
+void StopCapture(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x2, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
+}
+
+void GetVsyncInterruptEvent(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x5, 1, 2);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = IPC::MoveHandleDesc();
+ cmd_buff[3] = Kernel::g_handle_table.Create(vsync_interrupt_error_event).MoveFrom();
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
+}
+
+void GetBufferErrorInterruptEvent(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x6, 1, 2);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = IPC::MoveHandleDesc();
+ cmd_buff[3] = Kernel::g_handle_table.Create(interrupt_error_event).MoveFrom();
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
+}
+
+void SetReceiving(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ VAddr dest = cmd_buff[1];
+ u8 port = cmd_buff[2] & 0xFF;
+ u32 image_size = cmd_buff[3];
+ u16 trans_unit = cmd_buff[4] & 0xFFFF;
+
+ Kernel::Event* completion_event = (Port)port == Port::Cam2 ?
+ completion_event_cam2.get() : completion_event_cam1.get();
+
+ completion_event->Signal();
+
+ cmd_buff[0] = IPC::MakeHeader(0x7, 1, 2);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = IPC::MoveHandleDesc();
+ cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom();
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d",
+ dest, port, image_size, trans_unit);
+}
+
+void SetTransferLines(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+ u16 transfer_lines = cmd_buff[2] & 0xFFFF;
+ u16 width = cmd_buff[3] & 0xFFFF;
+ u16 height = cmd_buff[4] & 0xFFFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d",
+ port, transfer_lines, width, height);
+}
+
+void GetMaxLines(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u16 width = cmd_buff[1] & 0xFFFF;
+ u16 height = cmd_buff[2] & 0xFFFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = TRANSFER_BYTES / (2 * width);
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d",
+ width, height, cmd_buff[2]);
+}
+
+void GetTransferBytes(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = TRANSFER_BYTES;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
+}
+
+void SetTrimming(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+ bool trim = (cmd_buff[2] & 0xFF) != 0;
+
+ cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trim=%d", port, trim);
+}
+
+void SetTrimmingParamsCenter(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 port = cmd_buff[1] & 0xFF;
+ s16 trimW = cmd_buff[2] & 0xFFFF;
+ s16 trimH = cmd_buff[3] & 0xFFFF;
+ s16 camW = cmd_buff[4] & 0xFFFF;
+ s16 camH = cmd_buff[5] & 0xFFFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d",
+ port, trimW, trimH, camW, camH);
+}
+
+void Activate(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 cam_select = cmd_buff[1] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d",
+ cam_select);
+}
+
+void FlipImage(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 cam_select = cmd_buff[1] & 0xFF;
+ u8 flip = cmd_buff[2] & 0xFF;
+ u8 context = cmd_buff[3] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d",
+ cam_select, flip, context);
+}
+
+void SetSize(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 cam_select = cmd_buff[1] & 0xFF;
+ u8 size = cmd_buff[2] & 0xFF;
+ u8 context = cmd_buff[3] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d",
+ cam_select, size, context);
+}
+
+void SetFrameRate(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 cam_select = cmd_buff[1] & 0xFF;
+ u8 frame_rate = cmd_buff[2] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d",
+ cam_select, frame_rate);
+}
+
+void GetStereoCameraCalibrationData(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ // Default values taken from yuriks' 3DS. Valid data is required here or games using the
+ // calibration get stuck in an infinite CPU loop.
+ StereoCameraCalibrationData data = {};
+ data.isValidRotationXY = 0;
+ data.scale = 1.001776f;
+ data.rotationZ = 0.008322907f;
+ data.translationX = -87.70484f;
+ data.translationY = -7.640977f;
+ data.rotationX = 0.0f;
+ data.rotationY = 0.0f;
+ data.angleOfViewRight = 64.66875f;
+ data.angleOfViewLeft = 64.76067f;
+ data.distanceToChart = 250.0f;
+ data.distanceCameras = 35.0f;
+ data.imageWidth = 640;
+ data.imageHeight = 480;
+
+ cmd_buff[0] = IPC::MakeHeader(0x2B, 17, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ memcpy(&cmd_buff[2], &data, sizeof(data));
+
+ LOG_TRACE(Service_CAM, "called");
+}
+
+void GetSuitableY2rStandardCoefficient(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[0] = IPC::MakeHeader(0x36, 2, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = 0;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called");
+}
+
+void PlayShutterSound(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 sound_id = cmd_buff[1] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0x38, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called, sound_id=%d", sound_id);
+}
+
+void DriverInitialize(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ completion_event_cam1->Clear();
+ completion_event_cam2->Clear();
+ interrupt_error_event->Clear();
+ vsync_interrupt_error_event->Clear();
+
+ cmd_buff[0] = IPC::MakeHeader(0x39, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called");
+}
+
+void DriverFinalize(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[0] = IPC::MakeHeader(0x3A, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_CAM, "(STUBBED) called");
+}
+
void Init() {
using namespace Kernel;
@@ -25,9 +292,18 @@ void Init() {
AddService(new CAM_Q_Interface);
AddService(new CAM_S_Interface);
AddService(new CAM_U_Interface);
+
+ completion_event_cam1 = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::completion_event_cam1");
+ completion_event_cam2 = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::completion_event_cam2");
+ interrupt_error_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::interrupt_error_event");
+ vsync_interrupt_error_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "CAM_U::vsync_interrupt_error_event");
}
void Shutdown() {
+ completion_event_cam1 = nullptr;
+ completion_event_cam2 = nullptr;
+ interrupt_error_event = nullptr;
+ vsync_interrupt_error_event = nullptr;
}
} // namespace CAM
diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h
index edd524841..2f4923728 100644
--- a/src/core/hle/service/cam/cam.h
+++ b/src/core/hle/service/cam/cam.h
@@ -4,12 +4,429 @@
#pragma once
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/swap.h"
+
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/service.h"
namespace Service {
namespace CAM {
+enum class Port : u8 {
+ None = 0,
+ Cam1 = 1,
+ Cam2 = 2,
+ Both = Cam1 | Cam2
+};
+
+enum class CameraSelect : u8 {
+ None = 0,
+ Out1 = 1,
+ In1 = 2,
+ Out2 = 4,
+ In1Out1 = Out1 | In1,
+ Out1Out2 = Out1 | Out2,
+ In1Out2 = In1 | Out2,
+ All = Out1 | In1 | Out2
+};
+
+enum class Effect : u8 {
+ None = 0,
+ Mono = 1,
+ Sepia = 2,
+ Negative = 3,
+ Negafilm = 4,
+ Sepia01 = 5
+};
+
+enum class Context : u8 {
+ None = 0,
+ A = 1,
+ B = 2,
+ Both = A | B
+};
+
+enum class Flip : u8 {
+ None = 0,
+ Horizontal = 1,
+ Vertical = 2,
+ Reverse = 3
+};
+
+enum class Size : u8 {
+ VGA = 0,
+ QVGA = 1,
+ QQVGA = 2,
+ CIF = 3,
+ QCIF = 4,
+ DS_LCD = 5,
+ DS_LCDx4 = 6,
+ CTR_TOP_LCD = 7,
+ CTR_BOTTOM_LCD = QVGA
+};
+
+enum class FrameRate : u8 {
+ Rate_15 = 0,
+ Rate_15_To_5 = 1,
+ Rate_15_To_2 = 2,
+ Rate_10 = 3,
+ Rate_8_5 = 4,
+ Rate_5 = 5,
+ Rate_20 = 6,
+ Rate_20_To_5 = 7,
+ Rate_30 = 8,
+ Rate_30_To_5 = 9,
+ Rate_15_To_10 = 10,
+ Rate_20_To_10 = 11,
+ Rate_30_To_10 = 12
+};
+
+enum class ShutterSoundType : u8 {
+ Normal = 0,
+ Movie = 1,
+ MovieEnd = 2
+};
+
+enum class WhiteBalance : u8 {
+ BalanceAuto = 0,
+ Balance3200K = 1,
+ Balance4150K = 2,
+ Balance5200K = 3,
+ Balance6000K = 4,
+ Balance7000K = 5,
+ BalanceMax = 6,
+ BalanceNormal = BalanceAuto,
+ BalanceTungsten = Balance3200K,
+ BalanceWhiteFluorescentLight = Balance4150K,
+ BalanceDaylight = Balance5200K,
+ BalanceCloudy = Balance6000K,
+ BalanceHorizon = Balance6000K,
+ BalanceShade = Balance7000K
+};
+
+enum class PhotoMode : u8 {
+ Normal = 0,
+ Portrait = 1,
+ Landscape = 2,
+ Nightview = 3,
+ Letter0 = 4
+};
+
+enum class LensCorrection : u8 {
+ Off = 0,
+ On70 = 1,
+ On90 = 2,
+ Dark = Off,
+ Normal = On70,
+ Bright = On90
+};
+
+enum class Contrast : u8 {
+ Pattern01 = 1,
+ Pattern02 = 2,
+ Pattern03 = 3,
+ Pattern04 = 4,
+ Pattern05 = 5,
+ Pattern06 = 6,
+ Pattern07 = 7,
+ Pattern08 = 8,
+ Pattern09 = 9,
+ Pattern10 = 10,
+ Pattern11 = 11,
+ Low = Pattern05,
+ Normal = Pattern06,
+ High = Pattern07
+};
+
+enum class OutputFormat : u8 {
+ YUV422 = 0,
+ RGB565 = 1
+};
+
+/// Stereo camera calibration data.
+struct StereoCameraCalibrationData {
+ u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid.
+ INSERT_PADDING_BYTES(3);
+ float_le scale; ///< Scale to match the left camera image with the right.
+ float_le rotationZ; ///< Z axis rotation to match the left camera image with the right.
+ float_le translationX; ///< X axis translation to match the left camera image with the right.
+ float_le translationY; ///< Y axis translation to match the left camera image with the right.
+ float_le rotationX; ///< X axis rotation to match the left camera image with the right.
+ float_le rotationY; ///< Y axis rotation to match the left camera image with the right.
+ float_le angleOfViewRight; ///< Right camera angle of view.
+ float_le angleOfViewLeft; ///< Left camera angle of view.
+ float_le distanceToChart; ///< Distance between cameras and measurement chart.
+ float_le distanceCameras; ///< Distance between left and right cameras.
+ s16_le imageWidth; ///< Image width.
+ s16_le imageHeight; ///< Image height.
+ INSERT_PADDING_BYTES(16);
+};
+static_assert(sizeof(StereoCameraCalibrationData) == 64, "StereoCameraCalibrationData structure size is wrong");
+
+struct PackageParameterCameraSelect {
+ CameraSelect camera;
+ s8 exposure;
+ WhiteBalance white_balance;
+ s8 sharpness;
+ bool auto_exposure;
+ bool auto_white_balance;
+ FrameRate frame_rate;
+ PhotoMode photo_mode;
+ Contrast contrast;
+ LensCorrection lens_correction;
+ bool noise_filter;
+ u8 padding;
+ s16 auto_exposure_window_x;
+ s16 auto_exposure_window_y;
+ s16 auto_exposure_window_width;
+ s16 auto_exposure_window_height;
+ s16 auto_white_balance_window_x;
+ s16 auto_white_balance_window_y;
+ s16 auto_white_balance_window_width;
+ s16 auto_white_balance_window_height;
+};
+
+static_assert(sizeof(PackageParameterCameraSelect) == 28, "PackageParameterCameraSelect structure size is wrong");
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00010040
+ * 1: u8 Camera port (`Port` enum)
+ * Outputs:
+ * 0: 0x00010040
+ * 1: ResultCode
+ */
+void StartCapture(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00020040
+ * 1: u8 Camera port (`Port` enum)
+ * Outputs:
+ * 0: 0x00020040
+ * 1: ResultCode
+ */
+void StopCapture(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00050040
+ * 1: u8 Camera port (`Port` enum)
+ * Outputs:
+ * 0: 0x00050042
+ * 1: ResultCode
+ * 2: Descriptor: Handle
+ * 3: Event handle
+ */
+void GetVsyncInterruptEvent(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00060040
+ * 1: u8 Camera port (`Port` enum)
+ * Outputs:
+ * 0: 0x00060042
+ * 1: ResultCode
+ * 2: Descriptor: Handle
+ * 3: Event handle
+ */
+void GetBufferErrorInterruptEvent(Service::Interface* self);
+
+/**
+ * Sets the target buffer to receive a frame of image data and starts the transfer. Each camera
+ * port has its own event to signal the end of the transfer.
+ *
+ * Inputs:
+ * 0: 0x00070102
+ * 1: Destination address in calling process
+ * 2: u8 Camera port (`Port` enum)
+ * 3: Image size (in bytes?)
+ * 4: u16 Transfer unit size (in bytes?)
+ * 5: Descriptor: Handle
+ * 6: Handle to destination process
+ * Outputs:
+ * 0: 0x00070042
+ * 1: ResultCode
+ * 2: Descriptor: Handle
+ * 3: Handle to event signalled when transfer finishes
+ */
+void SetReceiving(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00090100
+ * 1: u8 Camera port (`Port` enum)
+ * 2: u16 Number of lines to transfer
+ * 3: u16 Width
+ * 4: u16 Height
+ * Outputs:
+ * 0: 0x00090040
+ * 1: ResultCode
+ */
+void SetTransferLines(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x000A0080
+ * 1: u16 Width
+ * 2: u16 Height
+ * Outputs:
+ * 0: 0x000A0080
+ * 1: ResultCode
+ * 2: Maximum number of lines that fit in the buffer(?)
+ */
+void GetMaxLines(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x000C0040
+ * 1: u8 Camera port (`Port` enum)
+ * Outputs:
+ * 0: 0x000C0080
+ * 1: ResultCode
+ * 2: Total number of bytes for each frame with current settings(?)
+ */
+void GetTransferBytes(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x000E0080
+ * 1: u8 Camera port (`Port` enum)
+ * 2: u8 bool Enable trimming if true
+ * Outputs:
+ * 0: 0x000E0040
+ * 1: ResultCode
+ */
+void SetTrimming(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00120140
+ * 1: u8 Camera port (`Port` enum)
+ * 2: s16 Trim width(?)
+ * 3: s16 Trim height(?)
+ * 4: s16 Camera width(?)
+ * 5: s16 Camera height(?)
+ * Outputs:
+ * 0: 0x00120040
+ * 1: ResultCode
+ */
+void SetTrimmingParamsCenter(Service::Interface* self);
+
+/**
+ * Selects up to two physical cameras to enable.
+ * Inputs:
+ * 0: 0x00130040
+ * 1: u8 Cameras to activate (`CameraSelect` enum)
+ * Outputs:
+ * 0: 0x00130040
+ * 1: ResultCode
+ */
+void Activate(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x001D00C0
+ * 1: u8 Camera select (`CameraSelect` enum)
+ * 2: u8 Type of flipping to perform (`Flip` enum)
+ * 3: u8 Context (`Context` enum)
+ * Outputs:
+ * 0: 0x001D0040
+ * 1: ResultCode
+ */
+void FlipImage(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x001F00C0
+ * 1: u8 Camera select (`CameraSelect` enum)
+ * 2: u8 Camera frame resolution (`Size` enum)
+ * 3: u8 Context id (`Context` enum)
+ * Outputs:
+ * 0: 0x001F0040
+ * 1: ResultCode
+ */
+void SetSize(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00200080
+ * 1: u8 Camera select (`CameraSelect` enum)
+ * 2: u8 Camera framerate (`FrameRate` enum)
+ * Outputs:
+ * 0: 0x00200040
+ * 1: ResultCode
+ */
+void SetFrameRate(Service::Interface* self);
+
+/**
+ * Returns calibration data relating the outside cameras to eachother, for use in AR applications.
+ *
+ * Inputs:
+ * 0: 0x002B0000
+ * Outputs:
+ * 0: 0x002B0440
+ * 1: ResultCode
+ * 2-17: `StereoCameraCalibrationData` structure with calibration values
+ */
+void GetStereoCameraCalibrationData(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00360000
+ * Outputs:
+ * 0: 0x00360080
+ * 1: ResultCode
+ * 2: ?
+ */
+void GetSuitableY2rStandardCoefficient(Service::Interface* self);
+
+/**
+ * Unknown
+ * Inputs:
+ * 0: 0x00380040
+ * 1: u8 Sound ID
+ * Outputs:
+ * 0: 0x00380040
+ * 1: ResultCode
+ */
+void PlayShutterSound(Service::Interface* self);
+
+/**
+ * Initializes the camera driver. Must be called before using other functions.
+ * Inputs:
+ * 0: 0x00390000
+ * Outputs:
+ * 0: 0x00390040
+ * 1: ResultCode
+ */
+void DriverInitialize(Service::Interface* self);
+
+/**
+ * Shuts down the camera driver.
+ * Inputs:
+ * 0: 0x003A0000
+ * Outputs:
+ * 0: 0x003A0040
+ * 1: ResultCode
+ */
+void DriverFinalize(Service::Interface* self);
+
/// Initialize CAM service(s)
void Init();
diff --git a/src/core/hle/service/cam/cam_c.cpp b/src/core/hle/service/cam/cam_c.cpp
index d35adcb9f..8fa7abc85 100644
--- a/src/core/hle/service/cam/cam_c.cpp
+++ b/src/core/hle/service/cam/cam_c.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/cam/cam.h"
#include "core/hle/service/cam/cam_c.h"
namespace Service {
diff --git a/src/core/hle/service/cam/cam_q.cpp b/src/core/hle/service/cam/cam_q.cpp
index c2760a102..d3ba91e9d 100644
--- a/src/core/hle/service/cam/cam_q.cpp
+++ b/src/core/hle/service/cam/cam_q.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/cam/cam.h"
#include "core/hle/service/cam/cam_q.h"
namespace Service {
diff --git a/src/core/hle/service/cam/cam_s.cpp b/src/core/hle/service/cam/cam_s.cpp
index aefbf7df4..2a13984d8 100644
--- a/src/core/hle/service/cam/cam_s.cpp
+++ b/src/core/hle/service/cam/cam_s.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/cam/cam.h"
#include "core/hle/service/cam/cam_s.h"
namespace Service {
diff --git a/src/core/hle/service/cam/cam_u.cpp b/src/core/hle/service/cam/cam_u.cpp
index 55083e0c7..a1070ebb2 100644
--- a/src/core/hle/service/cam/cam_u.cpp
+++ b/src/core/hle/service/cam/cam_u.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/cam/cam.h"
#include "core/hle/service/cam/cam_u.h"
@@ -10,25 +9,25 @@ namespace Service {
namespace CAM {
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010040, nullptr, "StartCapture"},
- {0x00020040, nullptr, "StopCapture"},
+ {0x00010040, StartCapture, "StartCapture"},
+ {0x00020040, StopCapture, "StopCapture"},
{0x00030040, nullptr, "IsBusy"},
{0x00040040, nullptr, "ClearBuffer"},
- {0x00050040, nullptr, "GetVsyncInterruptEvent"},
- {0x00060040, nullptr, "GetBufferErrorInterruptEvent"},
- {0x00070102, nullptr, "SetReceiving"},
+ {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"},
+ {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"},
+ {0x00070102, SetReceiving, "SetReceiving"},
{0x00080040, nullptr, "IsFinishedReceiving"},
- {0x00090100, nullptr, "SetTransferLines"},
- {0x000A0080, nullptr, "GetMaxLines"},
+ {0x00090100, SetTransferLines, "SetTransferLines"},
+ {0x000A0080, GetMaxLines, "GetMaxLines"},
{0x000B0100, nullptr, "SetTransferBytes"},
- {0x000C0040, nullptr, "GetTransferBytes"},
+ {0x000C0040, GetTransferBytes, "GetTransferBytes"},
{0x000D0080, nullptr, "GetMaxBytes"},
- {0x000E0080, nullptr, "SetTrimming"},
+ {0x000E0080, SetTrimming, "SetTrimming"},
{0x000F0040, nullptr, "IsTrimming"},
{0x00100140, nullptr, "SetTrimmingParams"},
{0x00110040, nullptr, "GetTrimmingParams"},
- {0x00120140, nullptr, "SetTrimmingParamsCenter"},
- {0x00130040, nullptr, "Activate"},
+ {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"},
+ {0x00130040, Activate, "Activate"},
{0x00140080, nullptr, "SwitchContext"},
{0x00150080, nullptr, "SetExposure"},
{0x00160080, nullptr, "SetWhiteBalance"},
@@ -38,10 +37,10 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x001A0040, nullptr, "IsAutoExposure"},
{0x001B0080, nullptr, "SetAutoWhiteBalance"},
{0x001C0040, nullptr, "IsAutoWhiteBalance"},
- {0x001D00C0, nullptr, "FlipImage"},
+ {0x001D00C0, FlipImage, "FlipImage"},
{0x001E0200, nullptr, "SetDetailSize"},
- {0x001F00C0, nullptr, "SetSize"},
- {0x00200080, nullptr, "SetFrameRate"},
+ {0x001F00C0, SetSize, "SetSize"},
+ {0x00200080, SetFrameRate, "SetFrameRate"},
{0x00210080, nullptr, "SetPhotoMode"},
{0x002200C0, nullptr, "SetEffect"},
{0x00230080, nullptr, "SetContrast"},
@@ -52,17 +51,22 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00280080, nullptr, "SetNoiseFilter"},
{0x00290080, nullptr, "SynchronizeVsyncTiming"},
{0x002A0080, nullptr, "GetLatestVsyncTiming"},
- {0x002B0000, nullptr, "GetStereoCameraCalibrationData"},
+ {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"},
{0x002C0400, nullptr, "SetStereoCameraCalibrationData"},
+ {0x002D00C0, nullptr, "WriteRegisterI2c"},
+ {0x002E00C0, nullptr, "WriteMcuVariableI2c"},
+ {0x002F0080, nullptr, "ReadRegisterI2cExclusive"},
+ {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"},
{0x00310180, nullptr, "SetImageQualityCalibrationData"},
{0x00320000, nullptr, "GetImageQualityCalibrationData"},
{0x003302C0, nullptr, "SetPackageParameterWithoutContext"},
{0x00340140, nullptr, "SetPackageParameterWithContext"},
{0x003501C0, nullptr, "SetPackageParameterWithContextDetail"},
- {0x00360000, nullptr, "GetSuitableY2rStandardCoefficient"},
- {0x00380040, nullptr, "PlayShutterSound"},
- {0x00390000, nullptr, "DriverInitialize"},
- {0x003A0000, nullptr, "DriverFinalize"},
+ {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"},
+ {0x00370202, nullptr, "PlayShutterSoundWithWave"},
+ {0x00380040, PlayShutterSound, "PlayShutterSound"},
+ {0x00390000, DriverInitialize, "DriverInitialize"},
+ {0x003A0000, DriverFinalize, "DriverFinalize"},
{0x003B0000, nullptr, "GetActivatedCamera"},
{0x003C0000, nullptr, "GetSleepCamera"},
{0x003D0040, nullptr, "SetSleepCamera"},
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp
index db0e52b79..6d79ce9b4 100644
--- a/src/core/hle/service/cecd/cecd.cpp
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -9,10 +9,6 @@
#include "core/hle/service/cecd/cecd_s.h"
#include "core/hle/service/cecd/cecd_u.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/hle.h"
-
namespace Service {
namespace CECD {
diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h
index 32fd2045d..9e158521b 100644
--- a/src/core/hle/service/cecd/cecd.h
+++ b/src/core/hle/service/cecd/cecd.h
@@ -4,9 +4,6 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/service.h"
-
namespace Service {
namespace CECD {
diff --git a/src/core/hle/service/cecd/cecd_s.cpp b/src/core/hle/service/cecd/cecd_s.cpp
index 72d7e8d44..bfd821c07 100644
--- a/src/core/hle/service/cecd/cecd_s.cpp
+++ b/src/core/hle/service/cecd/cecd_s.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/cecd/cecd.h"
#include "core/hle/service/cecd/cecd_s.h"
namespace Service {
diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp
index 0a23bafbc..9b720a738 100644
--- a/src/core/hle/service/cecd/cecd_u.cpp
+++ b/src/core/hle/service/cecd/cecd_u.cpp
@@ -2,18 +2,17 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/cecd/cecd.h"
#include "core/hle/service/cecd/cecd_u.h"
namespace Service {
namespace CECD {
-// Empty arrays are illegal -- commented out until an entry is added.
-//const Interface::FunctionInfo FunctionTable[] = { };
+static const Interface::FunctionInfo FunctionTable[] = {
+ { 0x00120104, nullptr, "ReadSavedData" },
+};
CECD_U_Interface::CECD_U_Interface() {
- //Register(FunctionTable);
+ Register(FunctionTable);
}
} // namespace CECD
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index 56986a49e..4c82a58e4 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -4,13 +4,15 @@
#include <algorithm>
+#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
-#include "common/file_util.h"
+#include "common/swap.h"
#include "core/file_sys/archive_systemsavedata.h"
#include "core/file_sys/file_backend.h"
#include "core/settings.h"
+#include "core/hle/result.h"
#include "core/hle/service/cfg/cfg.h"
#include "core/hle/service/cfg/cfg_i.h"
#include "core/hle/service/cfg/cfg_s.h"
@@ -292,8 +294,8 @@ ResultCode DeleteConfigNANDSaveFile() {
ResultCode UpdateConfigNANDSavegame() {
FileSys::Mode mode = {};
- mode.write_flag = 1;
- mode.create_flag = 1;
+ mode.write_flag.Assign(1);
+ mode.create_flag.Assign(1);
FileSys::Path path("config");
@@ -333,6 +335,18 @@ ResultCode FormatConfig() {
res = CreateConfigInfoBlk(0x000A0000, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK);
if (!res.IsSuccess()) return res;
+ // 0x000A0000 - Profile username
+ struct {
+ u16_le username[10];
+ u8 unused[4];
+ u32_le wordfilter_version; // Unused by Citra
+ } profile_username = {};
+
+ std::u16string username_string = Common::UTF8ToUTF16("Citra");
+ std::copy(username_string.cbegin(), username_string.cend(), profile_username.username);
+ res = CreateConfigInfoBlk(0x000A0000, sizeof(profile_username), 0xE, &profile_username);
+ if (!res.IsSuccess()) return res;
+
// 0x000A0001 - Profile birthday
const u8 profile_birthday[2] = {3, 25}; // March 25th, 2014
res = CreateConfigInfoBlk(0x000A0001, sizeof(profile_birthday), 0xE, profile_birthday);
@@ -343,9 +357,10 @@ ResultCode FormatConfig() {
res = CreateConfigInfoBlk(0x000B0000, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO);
if (!res.IsSuccess()) return res;
- char16_t country_name_buffer[16][0x40] = {};
+ u16_le country_name_buffer[16][0x40] = {};
+ std::u16string region_name = Common::UTF8ToUTF16("Gensokyo");
for (size_t i = 0; i < 16; ++i) {
- Common::UTF8ToUTF16("Gensokyo").copy(country_name_buffer[i], 0x40);
+ std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]);
}
// 0x000B0001 - Localized names for the profile Country
res = CreateConfigInfoBlk(0x000B0001, sizeof(country_name_buffer), 0xE, country_name_buffer);
@@ -404,7 +419,7 @@ void Init() {
FileSys::Path config_path("config");
FileSys::Mode open_mode = {};
- open_mode.read_flag = 1;
+ open_mode.read_flag.Assign(1);
auto config_result = Service::FS::OpenFileFromArchive(*archive_result, config_path, open_mode);
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
index fc2a16a04..606ab99cf 100644
--- a/src/core/hle/service/cfg/cfg.h
+++ b/src/core/hle/service/cfg/cfg.h
@@ -5,10 +5,15 @@
#pragma once
#include <array>
-#include "core/hle/result.h"
-#include "core/hle/service/service.h"
+
+#include "common/common_types.h"
+
+union ResultCode;
namespace Service {
+
+class Interface;
+
namespace CFG {
enum SystemModel {
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 5aeadc084..0559a07b2 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/cfg/cfg.h"
#include "core/hle/service/cfg/cfg_i.h"
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp
index a329514a6..b03d290e5 100644
--- a/src/core/hle/service/cfg/cfg_s.cpp
+++ b/src/core/hle/service/cfg/cfg_s.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/cfg/cfg.h"
#include "core/hle/service/cfg/cfg_s.h"
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 18939750b..89ae96c9e 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/cfg/cfg.h"
#include "core/hle/service/cfg/cfg_u.h"
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 669659510..6318bf2a7 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -22,9 +22,10 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00060000, nullptr, "ReleaseSoundChannels"},
{0x00070000, nullptr, "AcquireCaptureDevice"},
{0x00080040, nullptr, "ReleaseCaptureDevice"},
- {0x00090082, nullptr, "FlushDCache"},
- {0x000A0082, nullptr, "StoreDCache"},
- {0x000B0082, nullptr, "InvalidateDCache"},
+ {0x00090082, nullptr, "FlushDataCache"},
+ {0x000A0082, nullptr, "StoreDataCache"},
+ {0x000B0082, nullptr, "InvalidateDataCache"},
+ {0x000C0000, nullptr, "Reset"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index ce5619069..3ba24d466 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -2,9 +2,13 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cinttypes>
+
+#include "audio_core/hle/pipe.h"
+
+#include "common/hash.h"
#include "common/logging/log.h"
-#include "core/hle/hle.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/dsp_dsp.h"
@@ -15,17 +19,30 @@ namespace DSP_DSP {
static u32 read_pipe_count;
static Kernel::SharedPtr<Kernel::Event> semaphore_event;
-static Kernel::SharedPtr<Kernel::Event> interrupt_event;
-void SignalInterrupt() {
- // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated
- // application that a DSP interrupt occurred, without specifying which one. Since we do not
- // emulate the DSP yet (and how it works is largely unknown), this is a work around to get games
- // that check the DSP interrupt signal event to run. We should figure out the different types of
- // DSP interrupts, and trigger them at the appropriate times.
+struct PairHash {
+ template <typename T, typename U>
+ std::size_t operator()(const std::pair<T, U> &x) const {
+ // TODO(yuriks): Replace with better hash combining function.
+ return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
+ }
+};
+
+/// Map of (audio interrupt number, channel number) to Kernel::Events. See: RegisterInterruptEvents
+static std::unordered_map<std::pair<u32, u32>, Kernel::SharedPtr<Kernel::Event>, PairHash> interrupt_events;
+
+// DSP Interrupts:
+// Interrupt #2 occurs every frame tick. Userland programs normally have a thread that's waiting
+// for an interrupt event. Immediately after this interrupt event, userland normally updates the
+// state in the next region and increments the relevant frame counter by two.
+void SignalAllInterrupts() {
+ // HACK: The other interrupts have currently unknown purpose, we trigger them each tick in any case.
+ for (auto& interrupt_event : interrupt_events)
+ interrupt_event.second->Signal();
+}
- if (interrupt_event != 0)
- interrupt_event->Signal();
+void SignalInterrupt(u32 interrupt, u32 channel) {
+ interrupt_events[std::make_pair(interrupt, channel)]->Signal();
}
/**
@@ -41,18 +58,18 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
u32 addr = cmd_buff[1];
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000);
- LOG_WARNING(Service_DSP, "(STUBBED) called with address 0x%08X", addr);
+ LOG_DEBUG(Service_DSP, "addr=0x%08X", addr);
}
/**
* DSP_DSP::LoadComponent service function
* Inputs:
* 1 : Size
- * 2 : Unknown (observed only half word used)
- * 3 : Unknown (observed only half word used)
+ * 2 : Program mask (observed only half word used)
+ * 3 : Data mask (observed only half word used)
* 4 : (size << 4) | 0xA
* 5 : Buffer address
* Outputs:
@@ -63,18 +80,28 @@ static void LoadComponent(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 size = cmd_buff[1];
- u32 unk1 = cmd_buff[2];
- u32 unk2 = cmd_buff[3];
- u32 new_size = cmd_buff[4];
+ u32 prog_mask = cmd_buff[2];
+ u32 data_mask = cmd_buff[3];
+ u32 desc = cmd_buff[4];
u32 buffer = cmd_buff[5];
- cmd_buff[1] = 0; // No error
+ cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2);
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
+ cmd_buff[3] = desc;
+ cmd_buff[4] = buffer;
// TODO(bunnei): Implement real DSP firmware loading
- LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, unk1=0x%08X, unk2=0x%08X, new_size=0x%X, buffer=0x%08X",
- size, unk1, unk2, new_size, buffer);
+ ASSERT(Memory::GetPointer(buffer) != nullptr);
+ ASSERT(size > 0x37C);
+
+ LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer), size));
+ // Some versions of the firmware have the location of DSP structures listed here.
+ LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer) + 0x340, 60));
+
+ LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X",
+ size, prog_mask, data_mask, buffer);
}
/**
@@ -115,15 +142,14 @@ static void FlushDataCache(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_DEBUG(Service_DSP, "(STUBBED) called address=0x%08X, size=0x%X, process=0x%08X",
- address, size, process);
+ LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process);
}
/**
* DSP_DSP::RegisterInterruptEvents service function
* Inputs:
- * 1 : Parameter 0 (purpose unknown)
- * 2 : Parameter 1 (purpose unknown)
+ * 1 : Interrupt Number
+ * 2 : Channel Number
* 4 : Interrupt event handle
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
@@ -131,37 +157,37 @@ static void FlushDataCache(Service::Interface* self) {
static void RegisterInterruptEvents(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 param0 = cmd_buff[1];
- u32 param1 = cmd_buff[2];
+ u32 interrupt = cmd_buff[1];
+ u32 channel = cmd_buff[2];
u32 event_handle = cmd_buff[4];
- auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
- if (evt != nullptr) {
- interrupt_event = evt;
- cmd_buff[1] = 0; // No error
+ if (event_handle) {
+ auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
+ if (evt) {
+ interrupt_events[std::make_pair(interrupt, channel)] = evt;
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ LOG_INFO(Service_DSP, "Registered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
+ } else {
+ LOG_CRITICAL(Service_DSP, "Invalid event handle! interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
+ ASSERT(false); // This should really be handled at a IPC translation layer.
+ }
} else {
- LOG_ERROR(Service_DSP, "called with invalid handle=%08X", cmd_buff[4]);
-
- // TODO(yuriks): An error should be returned from SendSyncRequest, not in the cmdbuf
- cmd_buff[1] = -1;
+ interrupt_events.erase(std::make_pair(interrupt, channel));
+ LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
}
-
- LOG_WARNING(Service_DSP, "(STUBBED) called param0=%u, param1=%u, event_handle=0x%08X", param0, param1, event_handle);
}
/**
- * DSP_DSP::WriteReg0x10 service function
+ * DSP_DSP::SetSemaphore service function
* Inputs:
* 1 : Unknown (observed only half word used)
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
-static void WriteReg0x10(Service::Interface* self) {
+static void SetSemaphore(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- SignalInterrupt();
-
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_DSP, "(STUBBED) called");
}
@@ -169,9 +195,9 @@ static void WriteReg0x10(Service::Interface* self) {
/**
* DSP_DSP::WriteProcessPipe service function
* Inputs:
- * 1 : Number
+ * 1 : Channel
* 2 : Size
- * 3 : (size <<14) | 0x402
+ * 3 : (size << 14) | 0x402
* 4 : Buffer
* Outputs:
* 0 : Return header
@@ -180,24 +206,36 @@ static void WriteReg0x10(Service::Interface* self) {
static void WriteProcessPipe(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 number = cmd_buff[1];
- u32 size = cmd_buff[2];
- u32 new_size = cmd_buff[3];
- u32 buffer = cmd_buff[4];
+ DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
+ u32 size = cmd_buff[2];
+ u32 buffer = cmd_buff[4];
+
+ ASSERT_MSG(IPC::StaticBufferDesc(size, 1) == cmd_buff[3], "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe, size, buffer);
+ ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
+
+ std::vector<u8> message(size);
+
+ for (size_t i = 0; i < size; i++) {
+ message[i] = Memory::Read8(buffer + i);
+ }
+
+ DSP::HLE::PipeWrite(pipe, message);
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_DSP, "(STUBBED) called number=%u, size=0x%X, new_size=0x%X, buffer=0x%08X",
- number, size, new_size, buffer);
+ LOG_DEBUG(Service_DSP, "pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
}
/**
* DSP_DSP::ReadPipeIfPossible service function
+ * A pipe is a means of communication between the ARM11 and DSP that occurs on
+ * hardware by writing to/reading from the DSP registers at 0x10203000.
+ * Pipes are used for initialisation. See also DSP::HLE::PipeRead.
* Inputs:
- * 1 : Unknown
+ * 1 : Pipe Number
* 2 : Unknown
* 3 : Size in bytes of read (observed only lower half word used)
- * 0x41 : Virtual address to read from DSP pipe to in memory
+ * 0x41 : Virtual address of memory buffer to write pipe contents to
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Number of bytes read from pipe
@@ -205,35 +243,82 @@ static void WriteProcessPipe(Service::Interface* self) {
static void ReadPipeIfPossible(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 unk1 = cmd_buff[1];
- u32 unk2 = cmd_buff[2];
- u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size
+ DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
+ u32 unknown = cmd_buff[2];
+ u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size
VAddr addr = cmd_buff[0x41];
- // Canned DSP responses that games expect. These were taken from HW by 3dmoo team.
- // TODO: Remove this hack :)
- static const std::array<u16, 16> canned_read_pipe = {{
- 0x000F, 0xBFFF, 0x9E8E, 0x8680, 0xA78E, 0x9430, 0x8400, 0x8540,
- 0x948E, 0x8710, 0x8410, 0xA90E, 0xAA0E, 0xAACE, 0xAC4E, 0xAC58
- }};
+ ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
- u32 initial_size = read_pipe_count;
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
+ std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
- for (unsigned offset = 0; offset < size; offset += sizeof(u16)) {
- if (read_pipe_count < canned_read_pipe.size()) {
- Memory::Write16(addr + offset, canned_read_pipe[read_pipe_count]);
- read_pipe_count++;
- } else {
- LOG_ERROR(Service_DSP, "canned read pipe log exceeded!");
- break;
- }
+ Memory::WriteBlock(addr, response.data(), response.size());
+
+ cmd_buff[2] = static_cast<u32>(response.size());
+ } else {
+ cmd_buff[2] = 0; // Return no data
}
- cmd_buff[1] = 0; // No error
- cmd_buff[2] = (read_pipe_count - initial_size) * sizeof(u16);
+ LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]);
+}
- LOG_WARNING(Service_DSP, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, size=0x%X, buffer=0x%08X",
- unk1, unk2, size, addr);
+/**
+ * DSP_DSP::ReadPipe service function
+ * Inputs:
+ * 1 : Pipe Number
+ * 2 : Unknown
+ * 3 : Size in bytes of read (observed only lower half word used)
+ * 0x41 : Virtual address of memory buffer to write pipe contents to
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Number of bytes read from pipe
+ */
+static void ReadPipe(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
+ u32 unknown = cmd_buff[2];
+ u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size
+ VAddr addr = cmd_buff[0x41];
+
+ ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
+
+ if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
+ std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
+
+ Memory::WriteBlock(addr, response.data(), response.size());
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = static_cast<u32>(response.size());
+ } else {
+ // No more data is in pipe. Hardware hangs in this case; this should never happen.
+ UNREACHABLE();
+ }
+
+ LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]);
+}
+
+/**
+ * DSP_DSP::GetPipeReadableSize service function
+ * Inputs:
+ * 1 : Pipe Number
+ * 2 : Unknown
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Number of bytes readable from pipe
+ */
+static void GetPipeReadableSize(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
+ u32 unknown = cmd_buff[2];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = DSP::HLE::GetPipeReadableSize(pipe);
+
+ LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, cmd_buff[2]);
}
/**
@@ -268,20 +353,86 @@ static void GetHeadphoneStatus(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 0; // Not using headphones?
- LOG_DEBUG(Service_DSP, "(STUBBED) called");
+ LOG_WARNING(Service_DSP, "(STUBBED) called");
+}
+
+/**
+ * DSP_DSP::RecvData service function
+ * This function reads a value out of a DSP register.
+ * Inputs:
+ * 1 : Register Number
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Value in the register
+ * Notes:
+ * This function has only been observed being called with a register number of 0.
+ */
+static void RecvData(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 register_number = cmd_buff[1];
+
+ ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
+
+ // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept.
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ switch (DSP::HLE::GetDspState()) {
+ case DSP::HLE::DspState::On:
+ cmd_buff[2] = 0;
+ break;
+ case DSP::HLE::DspState::Off:
+ case DSP::HLE::DspState::Sleeping:
+ cmd_buff[2] = 1;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ LOG_DEBUG(Service_DSP, "register_number=%u", register_number);
+}
+
+/**
+ * DSP_DSP::RecvDataIsReady service function
+ * This function checks whether a DSP register is ready to be read.
+ * Inputs:
+ * 1 : Register Number
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : non-zero == ready
+ * Note:
+ * This function has only been observed being called with a register number of 0.
+ */
+static void RecvDataIsReady(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 register_number = cmd_buff[1];
+
+ ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = 1; // Ready to read
+
+ LOG_DEBUG(Service_DSP, "register_number=%u", register_number);
}
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010040, nullptr, "RecvData"},
- {0x00020040, nullptr, "RecvDataIsReady"},
+ {0x00010040, RecvData, "RecvData"},
+ {0x00020040, RecvDataIsReady, "RecvDataIsReady"},
{0x00030080, nullptr, "SendData"},
{0x00040040, nullptr, "SendDataIsEmpty"},
- {0x00070040, WriteReg0x10, "WriteReg0x10"},
+ {0x000500C2, nullptr, "SendFifoEx"},
+ {0x000600C0, nullptr, "RecvFifoEx"},
+ {0x00070040, SetSemaphore, "SetSemaphore"},
{0x00080000, nullptr, "GetSemaphore"},
{0x00090040, nullptr, "ClearSemaphore"},
+ {0x000A0040, nullptr, "MaskSemaphore"},
{0x000B0000, nullptr, "CheckSemaphoreRequest"},
{0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
{0x000D0082, WriteProcessPipe, "WriteProcessPipe"},
+ {0x000E00C0, ReadPipe, "ReadPipe"},
+ {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"},
{0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"},
{0x001100C2, LoadComponent, "LoadComponent"},
{0x00120000, nullptr, "UnloadComponent"},
@@ -295,7 +446,10 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
{0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
{0x001C0082, nullptr, "SetIirFilterEQ"},
+ {0x001D00C0, nullptr, "ReadMultiEx_SPI2"},
+ {0x001E00C2, nullptr, "WriteMultiEx_SPI2"},
{0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"},
+ {0x00200040, nullptr, "ForceHeadphoneOut"},
{0x00210000, nullptr, "GetIsDspOccupied"},
};
@@ -304,7 +458,6 @@ const Interface::FunctionInfo FunctionTable[] = {
Interface::Interface() {
semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
- interrupt_event = nullptr;
read_pipe_count = 0;
Register(FunctionTable);
@@ -312,7 +465,7 @@ Interface::Interface() {
Interface::~Interface() {
semaphore_event = nullptr;
- interrupt_event = nullptr;
+ interrupt_events.clear();
}
} // namespace
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h
index b6f611db5..32b89e9bb 100644
--- a/src/core/hle/service/dsp_dsp.h
+++ b/src/core/hle/service/dsp_dsp.h
@@ -23,7 +23,15 @@ public:
}
};
-/// Signals that a DSP interrupt has occurred to userland code
-void SignalInterrupt();
+/// Signal all audio related interrupts.
+void SignalAllInterrupts();
+
+/**
+ * Signal a specific audio related interrupt based on interrupt id and channel id.
+ * @param interrupt_id The interrupt id
+ * @param channel_id The channel id
+ * The significance of various values of interrupt_id and channel_id is not yet known.
+ */
+void SignalInterrupt(u32 interrupt_id, u32 channel_id);
} // namespace
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index e8c06c1cf..5f9cf6e94 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -2,9 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/bit_field.h"
+#include "common/common_types.h"
#include "common/logging/log.h"
-#include "core/hle/hle.h"
#include "core/hle/service/err_f.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index 2911ab402..c13ffd9d2 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -7,10 +7,6 @@
#include "core/hle/service/frd/frd_a.h"
#include "core/hle/service/frd/frd_u.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/hle.h"
-
namespace Service {
namespace FRD {
diff --git a/src/core/hle/service/frd/frd.h b/src/core/hle/service/frd/frd.h
index 41f7a2f6b..f9f88b444 100644
--- a/src/core/hle/service/frd/frd.h
+++ b/src/core/hle/service/frd/frd.h
@@ -4,9 +4,6 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/service.h"
-
namespace Service {
namespace FRD {
diff --git a/src/core/hle/service/frd/frd_a.cpp b/src/core/hle/service/frd/frd_a.cpp
index 1c438a337..818d610f3 100644
--- a/src/core/hle/service/frd/frd_a.cpp
+++ b/src/core/hle/service/frd/frd_a.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/frd/frd.h"
#include "core/hle/service/frd/frd_a.h"
namespace Service {
diff --git a/src/core/hle/service/frd/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp
index 3a5897d06..2c6885377 100644
--- a/src/core/hle/service/frd/frd_u.cpp
+++ b/src/core/hle/service/frd/frd_u.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/frd/frd.h"
#include "core/hle/service/frd/frd_u.h"
namespace Service {
@@ -11,25 +9,58 @@ namespace FRD {
const Interface::FunctionInfo FunctionTable[] = {
{0x00010000, nullptr, "HasLoggedIn"},
+ {0x00020000, nullptr, "IsOnline"},
{0x00030000, nullptr, "Login"},
{0x00040000, nullptr, "Logout"},
- {0x00050000, nullptr, "GetFriendKey"},
+ {0x00050000, nullptr, "GetMyFriendKey"},
+ {0x00060000, nullptr, "GetMyPreference"},
+ {0x00070000, nullptr, "GetMyProfile"},
{0x00080000, nullptr, "GetMyPresence"},
{0x00090000, nullptr, "GetMyScreenName"},
- {0x00100040, nullptr, "GetPassword"},
+ {0x000A0000, nullptr, "GetMyMii"},
+ {0x000B0000, nullptr, "GetMyLocalAccountId"},
+ {0x000C0000, nullptr, "GetMyPlayingGame"},
+ {0x000D0000, nullptr, "GetMyFavoriteGame"},
+ {0x000E0000, nullptr, "GetMyNcPrincipalId"},
+ {0x000F0000, nullptr, "GetMyComment"},
+ {0x00100040, nullptr, "GetMyPassword"},
{0x00110080, nullptr, "GetFriendKeyList"},
+ {0x00120042, nullptr, "GetFriendPresence"},
+ {0x00130142, nullptr, "GetFriendScreenName"},
+ {0x00140044, nullptr, "GetFriendMii"},
+ {0x00150042, nullptr, "GetFriendProfile"},
+ {0x00160042, nullptr, "GetFriendRelationship"},
+ {0x00170042, nullptr, "GetFriendAttributeFlags"},
+ {0x00180044, nullptr, "GetFriendPlayingGame"},
{0x00190042, nullptr, "GetFriendFavoriteGame"},
{0x001A00C4, nullptr, "GetFriendInfo"},
- {0x001B0080, nullptr, "IsOnFriendList"},
- {0x001C0042, nullptr, "DecodeLocalFriendCode"},
- {0x001D0002, nullptr, "SetCurrentlyPlayingText"},
+ {0x001B0080, nullptr, "IsIncludedInFriendList"},
+ {0x001C0042, nullptr, "UnscrambleLocalFriendCode"},
+ {0x001D0002, nullptr, "UpdateGameModeDescription"},
+ {0x001E02C2, nullptr, "UpdateGameMode"},
+ {0x001F0042, nullptr, "SendInvitation"},
+ {0x00200002, nullptr, "AttachToEventNotification"},
+ {0x00210040, nullptr, "SetNotificationMask"},
+ {0x00220040, nullptr, "GetEventNotification"},
{0x00230000, nullptr, "GetLastResponseResult"},
+ {0x00240040, nullptr, "PrincipalIdToFriendCode"},
+ {0x00250080, nullptr, "FriendCodeToPrincipalId"},
+ {0x00260080, nullptr, "IsValidFriendCode"},
{0x00270040, nullptr, "ResultToErrorCode"},
{0x00280244, nullptr, "RequestGameAuthentication"},
{0x00290000, nullptr, "GetGameAuthenticationData"},
{0x002A0204, nullptr, "RequestServiceLocator"},
{0x002B0000, nullptr, "GetServiceLocatorData"},
+ {0x002C0002, nullptr, "DetectNatProperties"},
+ {0x002D0000, nullptr, "GetNatProperties"},
+ {0x002E0000, nullptr, "GetServerTimeInterval"},
+ {0x002F0040, nullptr, "AllowHalfAwake"},
+ {0x00300000, nullptr, "GetServerTypes"},
+ {0x00310082, nullptr, "GetFriendComment"},
{0x00320042, nullptr, "SetClientSdkVersion"},
+ {0x00330000, nullptr, "GetMyApproachContext"},
+ {0x00340046, nullptr, "AddFriendWithApproach"},
+ {0x00350082, nullptr, "DecryptApproachContext"},
};
FRD_U_Interface::FRD_U_Interface() {
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index b3fa89302..632620a56 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -708,96 +708,114 @@ static void GetPriority(Service::Interface* self) {
}
const Interface::FunctionInfo FunctionTable[] = {
- {0x000100C6, nullptr, "Dummy1"},
- {0x040100C4, nullptr, "Control"},
- {0x08010002, Initialize, "Initialize"},
- {0x080201C2, OpenFile, "OpenFile"},
- {0x08030204, OpenFileDirectly, "OpenFileDirectly"},
- {0x08040142, DeleteFile, "DeleteFile"},
- {0x08050244, RenameFile, "RenameFile"},
- {0x08060142, DeleteDirectory, "DeleteDirectory"},
- {0x08070142, nullptr, "DeleteDirectoryRecursively"},
- {0x08080202, CreateFile, "CreateFile"},
- {0x08090182, CreateDirectory, "CreateDirectory"},
- {0x080A0244, RenameDirectory, "RenameDirectory"},
- {0x080B0102, OpenDirectory, "OpenDirectory"},
- {0x080C00C2, OpenArchive, "OpenArchive"},
- {0x080D0144, nullptr, "ControlArchive"},
- {0x080E0080, CloseArchive, "CloseArchive"},
- {0x080F0180, FormatThisUserSaveData,"FormatThisUserSaveData"},
- {0x08100200, nullptr, "CreateSystemSaveData"},
- {0x08110040, nullptr, "DeleteSystemSaveData"},
- {0x08120080, GetFreeBytes, "GetFreeBytes"},
- {0x08130000, nullptr, "GetCardType"},
- {0x08140000, nullptr, "GetSdmcArchiveResource"},
- {0x08150000, nullptr, "GetNandArchiveResource"},
- {0x08160000, nullptr, "GetSdmcFatfsErro"},
- {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
- {0x08180000, IsSdmcWriteable, "IsSdmcWritable"},
- {0x08190042, nullptr, "GetSdmcCid"},
- {0x081A0042, nullptr, "GetNandCid"},
- {0x081B0000, nullptr, "GetSdmcSpeedInfo"},
- {0x081C0000, nullptr, "GetNandSpeedInfo"},
- {0x081D0042, nullptr, "GetSdmcLog"},
- {0x081E0042, nullptr, "GetNandLog"},
- {0x081F0000, nullptr, "ClearSdmcLog"},
- {0x08200000, nullptr, "ClearNandLog"},
- {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"},
- {0x08220000, nullptr, "CardSlotPowerOn"},
- {0x08230000, nullptr, "CardSlotPowerOff"},
- {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"},
- {0x08250040, nullptr, "CardNorDirectCommand"},
- {0x08260080, nullptr, "CardNorDirectCommandWithAddress"},
- {0x08270082, nullptr, "CardNorDirectRead"},
- {0x082800C2, nullptr, "CardNorDirectReadWithAddress"},
- {0x08290082, nullptr, "CardNorDirectWrite"},
- {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"},
- {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"},
- {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"},
- {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"},
- {0x082E0040, nullptr, "GetProductInfo"},
- {0x082F0040, nullptr, "GetProgramLaunchInfo"},
- {0x08300182, nullptr, "CreateExtSaveData"},
- {0x08310180, nullptr, "CreateSharedExtSaveData"},
- {0x08320102, nullptr, "ReadExtSaveDataIcon"},
- {0x08330082, nullptr, "EnumerateExtSaveData"},
- {0x08340082, nullptr, "EnumerateSharedExtSaveData"},
- {0x08350080, nullptr, "DeleteExtSaveData"},
- {0x08360080, nullptr, "DeleteSharedExtSaveData"},
- {0x08370040, nullptr, "SetCardSpiBaudRate"},
- {0x08380040, nullptr, "SetCardSpiBusMode"},
- {0x08390000, nullptr, "SendInitializeInfoTo9"},
- {0x083A0100, nullptr, "GetSpecialContentIndex"},
- {0x083B00C2, nullptr, "GetLegacyRomHeader"},
- {0x083C00C2, nullptr, "GetLegacyBannerData"},
- {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"},
- {0x083E00C2, nullptr, "QueryTotalQuotaSize"},
- {0x083F00C0, nullptr, "GetExtDataBlockSize"},
- {0x08400040, nullptr, "AbnegateAccessRight"},
- {0x08410000, nullptr, "DeleteSdmcRoot"},
- {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"},
- {0x08430000, nullptr, "InitializeCtrFileSystem"},
- {0x08440000, nullptr, "CreateSeed"},
- {0x084500C2, nullptr, "GetFormatInfo"},
- {0x08460102, nullptr, "GetLegacyRomHeader2"},
- {0x08470180, nullptr, "FormatCtrCardUserSaveData"},
- {0x08480042, nullptr, "GetSdmcCtrRootPath"},
- {0x08490040, nullptr, "GetArchiveResource"},
- {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
- {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
- {0x084C0242, FormatSaveData, "FormatSaveData"},
- {0x084D0102, nullptr, "GetLegacySubBannerData"},
- {0x084E0342, nullptr, "UpdateSha256Context"},
- {0x084F0102, nullptr, "ReadSpecialFile"},
- {0x08500040, nullptr, "GetSpecialFileSize"},
- {0x08510242, CreateExtSaveData, "CreateExtSaveData"},
- {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"},
- {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"},
- {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"},
- {0x08580000, nullptr, "GetMovableSedHashedKeyYRandomData"},
+ {0x000100C6, nullptr, "Dummy1"},
+ {0x040100C4, nullptr, "Control"},
+ {0x08010002, Initialize, "Initialize"},
+ {0x080201C2, OpenFile, "OpenFile"},
+ {0x08030204, OpenFileDirectly, "OpenFileDirectly"},
+ {0x08040142, DeleteFile, "DeleteFile"},
+ {0x08050244, RenameFile, "RenameFile"},
+ {0x08060142, DeleteDirectory, "DeleteDirectory"},
+ {0x08070142, nullptr, "DeleteDirectoryRecursively"},
+ {0x08080202, CreateFile, "CreateFile"},
+ {0x08090182, CreateDirectory, "CreateDirectory"},
+ {0x080A0244, RenameDirectory, "RenameDirectory"},
+ {0x080B0102, OpenDirectory, "OpenDirectory"},
+ {0x080C00C2, OpenArchive, "OpenArchive"},
+ {0x080D0144, nullptr, "ControlArchive"},
+ {0x080E0080, CloseArchive, "CloseArchive"},
+ {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"},
+ {0x08100200, nullptr, "CreateSystemSaveData"},
+ {0x08110040, nullptr, "DeleteSystemSaveData"},
+ {0x08120080, GetFreeBytes, "GetFreeBytes"},
+ {0x08130000, nullptr, "GetCardType"},
+ {0x08140000, nullptr, "GetSdmcArchiveResource"},
+ {0x08150000, nullptr, "GetNandArchiveResource"},
+ {0x08160000, nullptr, "GetSdmcFatfsError"},
+ {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
+ {0x08180000, IsSdmcWriteable, "IsSdmcWritable"},
+ {0x08190042, nullptr, "GetSdmcCid"},
+ {0x081A0042, nullptr, "GetNandCid"},
+ {0x081B0000, nullptr, "GetSdmcSpeedInfo"},
+ {0x081C0000, nullptr, "GetNandSpeedInfo"},
+ {0x081D0042, nullptr, "GetSdmcLog"},
+ {0x081E0042, nullptr, "GetNandLog"},
+ {0x081F0000, nullptr, "ClearSdmcLog"},
+ {0x08200000, nullptr, "ClearNandLog"},
+ {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"},
+ {0x08220000, nullptr, "CardSlotPowerOn"},
+ {0x08230000, nullptr, "CardSlotPowerOff"},
+ {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"},
+ {0x08250040, nullptr, "CardNorDirectCommand"},
+ {0x08260080, nullptr, "CardNorDirectCommandWithAddress"},
+ {0x08270082, nullptr, "CardNorDirectRead"},
+ {0x082800C2, nullptr, "CardNorDirectReadWithAddress"},
+ {0x08290082, nullptr, "CardNorDirectWrite"},
+ {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"},
+ {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"},
+ {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"},
+ {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"},
+ {0x082E0040, nullptr, "GetProductInfo"},
+ {0x082F0040, nullptr, "GetProgramLaunchInfo"},
+ {0x08300182, nullptr, "CreateExtSaveData"},
+ {0x08310180, nullptr, "CreateSharedExtSaveData"},
+ {0x08320102, nullptr, "ReadExtSaveDataIcon"},
+ {0x08330082, nullptr, "EnumerateExtSaveData"},
+ {0x08340082, nullptr, "EnumerateSharedExtSaveData"},
+ {0x08350080, nullptr, "DeleteExtSaveData"},
+ {0x08360080, nullptr, "DeleteSharedExtSaveData"},
+ {0x08370040, nullptr, "SetCardSpiBaudRate"},
+ {0x08380040, nullptr, "SetCardSpiBusMode"},
+ {0x08390000, nullptr, "SendInitializeInfoTo9"},
+ {0x083A0100, nullptr, "GetSpecialContentIndex"},
+ {0x083B00C2, nullptr, "GetLegacyRomHeader"},
+ {0x083C00C2, nullptr, "GetLegacyBannerData"},
+ {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"},
+ {0x083E00C2, nullptr, "QueryTotalQuotaSize"},
+ {0x083F00C0, nullptr, "GetExtDataBlockSize"},
+ {0x08400040, nullptr, "AbnegateAccessRight"},
+ {0x08410000, nullptr, "DeleteSdmcRoot"},
+ {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"},
+ {0x08430000, nullptr, "InitializeCtrFileSystem"},
+ {0x08440000, nullptr, "CreateSeed"},
+ {0x084500C2, nullptr, "GetFormatInfo"},
+ {0x08460102, nullptr, "GetLegacyRomHeader2"},
+ {0x08470180, nullptr, "FormatCtrCardUserSaveData"},
+ {0x08480042, nullptr, "GetSdmcCtrRootPath"},
+ {0x08490040, nullptr, "GetArchiveResource"},
+ {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
+ {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
+ {0x084C0242, FormatSaveData, "FormatSaveData"},
+ {0x084D0102, nullptr, "GetLegacySubBannerData"},
+ {0x084E0342, nullptr, "UpdateSha256Context"},
+ {0x084F0102, nullptr, "ReadSpecialFile"},
+ {0x08500040, nullptr, "GetSpecialFileSize"},
+ {0x08510242, CreateExtSaveData, "CreateExtSaveData"},
+ {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"},
+ {0x08530142, nullptr, "ReadExtSaveDataIcon"},
+ {0x085400C0, nullptr, "GetExtDataBlockSize"},
+ {0x08550102, nullptr, "EnumerateExtSaveData"},
+ {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"},
+ {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"},
+ {0x08580000, nullptr, "StartDeviceMoveAsSource"},
+ {0x08590200, nullptr, "StartDeviceMoveAsDestination"},
+ {0x085A00C0, nullptr, "SetArchivePriority"},
+ {0x085B0080, nullptr, "GetArchivePriority"},
+ {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"},
+ {0x085D01C0, nullptr, "SetFsCompatibilityInfo"},
+ {0x085E0040, nullptr, "ResetCardCompatibilityParameter"},
+ {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"},
+ {0x08600042, nullptr, "EnumerateSystemSaveData"},
{0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"},
- {0x08620040, SetPriority, "SetPriority"},
- {0x08630000, GetPriority, "GetPriority"},
+ {0x08620040, SetPriority, "SetPriority"},
+ {0x08630000, GetPriority, "GetPriority"},
+ {0x08640000, nullptr, "GetNandInfo"},
+ {0x08650140, nullptr, "SetSaveDataSecureValue"},
+ {0x086600C0, nullptr, "GetSaveDataSecureValue"},
+ {0x086700C4, nullptr, "ControlSecureSave"},
+ {0x08680000, nullptr, "GetMediaType"},
+ {0x08690000, nullptr, "GetNandEraseCount"},
+ {0x086A0082, nullptr, "ReadNandReport"}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 481da0c9f..2ace2cade 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -275,7 +275,7 @@ static void FlushDataCache(Service::Interface* self) {
u32 size = cmd_buff[2];
u32 process = cmd_buff[4];
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(Memory::VirtualToPhysicalAddress(address), size);
+ VideoCore::g_renderer->Rasterizer()->InvalidateRegion(Memory::VirtualToPhysicalAddress(address), size);
// TODO(purpasmart96): Verify return header on HW
@@ -320,7 +320,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
* @todo This probably does not belong in the GSP module, instead move to video_core
*/
void SignalInterrupt(InterruptId interrupt_id) {
- if (0 == g_interrupt_event) {
+ if (nullptr == g_interrupt_event) {
LOG_WARNING(Service_GSP, "cannot synchronize until GSP event has been created!");
return;
}
@@ -347,7 +347,7 @@ void SignalInterrupt(InterruptId interrupt_id) {
FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id);
if (info->is_dirty) {
SetBufferSwap(screen_id, info->framebuffer_info[info->index]);
- info->is_dirty = false;
+ info->is_dirty.Assign(false);
}
}
}
@@ -365,7 +365,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
// GX request DMA - typically used for copying memory from GSP heap to VRAM
case CommandId::REQUEST_DMA:
- VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
+ VideoCore::g_renderer->Rasterizer()->FlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
command.dma_request.size);
memcpy(Memory::GetPointer(command.dma_request.dest_address),
@@ -373,7 +373,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
command.dma_request.size);
SignalInterrupt(InterruptId::DMA);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
+ VideoCore::g_renderer->Rasterizer()->InvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
command.dma_request.size);
break;
@@ -467,7 +467,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
if (region.size == 0)
break;
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(
+ VideoCore::g_renderer->Rasterizer()->InvalidateRegion(
Memory::VirtualToPhysicalAddress(region.address), region.size);
}
break;
@@ -499,7 +499,7 @@ static void SetLcdForceBlack(Service::Interface* self) {
// Since data is already zeroed, there is no need to explicitly set
// the color to black (all zero).
- data.is_enabled = enable_black;
+ data.is_enabled.Assign(enable_black);
LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD
LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD
@@ -521,7 +521,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) {
ExecuteCommand(command_buffer->commands[i], thread_id);
// Indicates that command has completed
- command_buffer->number_commands = command_buffer->number_commands - 1;
+ command_buffer->number_commands.Assign(command_buffer->number_commands - 1);
}
}
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp
index 9e36732b4..c700c21c5 100644
--- a/src/core/hle/service/gsp_lcd.cpp
+++ b/src/core/hle/service/gsp_lcd.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "common/bit_field.h"
-
#include "core/hle/service/gsp_lcd.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -11,14 +9,19 @@
namespace GSP_LCD {
-/*const Interface::FunctionInfo FunctionTable[] = {
-};*/
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000F0000, nullptr, "PowerOnAllBacklights"},
+ {0x00100000, nullptr, "PowerOffAllBacklights"},
+ {0x00110040, nullptr, "PowerOnBacklight"},
+ {0x00120040, nullptr, "PowerOffBacklight"},
+ {0x00130040, nullptr, "SetLedForceOff"}
+};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Interface class
Interface::Interface() {
- //Register(FunctionTable);
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 2e1e5c3e9..11d7e69a1 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -13,7 +13,6 @@
#include "core/core_timing.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/hle.h"
#include "video_core/video_core.h"
@@ -106,7 +105,7 @@ void Update() {
bool pressed = false;
std::tie(touch_entry->x, touch_entry->y, pressed) = VideoCore::g_emu_window->GetTouchState();
- touch_entry->valid = pressed ? 1 : 0;
+ touch_entry->valid.Assign(pressed ? 1 : 0);
// TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
// supposedly is "Touch-screen entry, which contains the raw coordinate data prior to being
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index 532931ae0..c50f597eb 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/hid_spvr.h"
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index fbfb9e885..bbdde2abb 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/hid_user.h"
@@ -11,6 +10,8 @@ namespace HID {
const Interface::FunctionInfo FunctionTable[] = {
{0x000A0000, GetIPCHandles, "GetIPCHandles"},
+ {0x000B0000, nullptr, "StartAnalogStickCalibration"},
+ {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
{0x00110000, EnableAccelerometer, "EnableAccelerometer"},
{0x00120000, DisableAccelerometer, "DisableAccelerometer"},
{0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp
index 0a3aba0a0..0855ab227 100644
--- a/src/core/hle/service/http_c.cpp
+++ b/src/core/hle/service/http_c.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/http_c.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -47,10 +46,20 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00220040, nullptr, "GetResponseStatusCode"},
{0x002300C0, nullptr, "GetResponseStatusCodeTimeout"},
{0x00240082, nullptr, "AddTrustedRootCA"},
+ {0x00250080, nullptr, "AddDefaultCert"},
+ {0x00260080, nullptr, "SelectRootCertChain"},
+ {0x002700C4, nullptr, "SetClientCert"},
+ {0x002B0080, nullptr, "SetSSLOpt"},
+ {0x002C0080, nullptr, "SetSSLClearOpt"},
+ {0x002D0000, nullptr, "CreateRootCertChain"},
+ {0x002E0040, nullptr, "DestroyRootCertChain"},
+ {0x002F0082, nullptr, "RootCertChainAddCert"},
+ {0x00300080, nullptr, "RootCertChainAddDefaultCert"},
{0x00350186, nullptr, "SetDefaultProxy"},
{0x00360000, nullptr, "ClearDNSCache"},
{0x00370080, nullptr, "SetKeepAlive"},
- {0x003800C0, nullptr, "Finalize"},
+ {0x003800C0, nullptr, "SetPostDataTypeSize"},
+ {0x00390000, nullptr, "Finalize"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp
index adfbb258d..c2121cb2e 100644
--- a/src/core/hle/service/ir/ir.cpp
+++ b/src/core/hle/service/ir/ir.cpp
@@ -2,21 +2,22 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/shared_memory.h"
+
#include "core/hle/service/service.h"
#include "core/hle/service/ir/ir.h"
#include "core/hle/service/ir/ir_rst.h"
#include "core/hle/service/ir/ir_u.h"
#include "core/hle/service/ir/ir_user.h"
-#include "core/hle/hle.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-
namespace Service {
namespace IR {
static Kernel::SharedPtr<Kernel::Event> handle_event;
+static Kernel::SharedPtr<Kernel::Event> conn_status_event;
static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
+static Kernel::SharedPtr<Kernel::SharedMemory> transfer_shared_memory;
void GetHandles(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -27,6 +28,64 @@ void GetHandles(Service::Interface* self) {
cmd_buff[4] = Kernel::g_handle_table.Create(Service::IR::handle_event).MoveFrom();
}
+void InitializeIrNopShared(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 transfer_buff_size = cmd_buff[1];
+ u32 recv_buff_size = cmd_buff[2];
+ u32 unk1 = cmd_buff[3];
+ u32 send_buff_size = cmd_buff[4];
+ u32 unk2 = cmd_buff[5];
+ u8 baud_rate = cmd_buff[6] & 0xFF;
+ Handle handle = cmd_buff[8];
+
+ if(Kernel::g_handle_table.IsValid(handle)) {
+ transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle);
+ transfer_shared_memory->name = "IR:TransferSharedMemory";
+ }
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, "
+ "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X",
+ transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle);
+}
+
+void RequireConnection(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ conn_status_event->Signal();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
+void Disconnect(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
+void GetConnectionStatusEvent(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[3] = Kernel::g_handle_table.Create(Service::IR::conn_status_event).MoveFrom();
+
+ LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
+void FinalizeIrNop(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
void Init() {
using namespace Kernel;
@@ -36,15 +95,19 @@ void Init() {
using Kernel::MemoryPermission;
shared_memory = SharedMemory::Create(0x1000, Kernel::MemoryPermission::ReadWrite,
- Kernel::MemoryPermission::ReadWrite, "IR:SharedMemory");
+ Kernel::MemoryPermission::ReadWrite, "IR:SharedMemory");
+ transfer_shared_memory = nullptr;
// Create event handle(s)
handle_event = Event::Create(RESETTYPE_ONESHOT, "IR:HandleEvent");
+ conn_status_event = Event::Create(RESETTYPE_ONESHOT, "IR:ConnectionStatusEvent");
}
void Shutdown() {
+ transfer_shared_memory = nullptr;
shared_memory = nullptr;
handle_event = nullptr;
+ conn_status_event = nullptr;
}
} // namespace IR
diff --git a/src/core/hle/service/ir/ir.h b/src/core/hle/service/ir/ir.h
index c16d963e7..72d44ce60 100644
--- a/src/core/hle/service/ir/ir.h
+++ b/src/core/hle/service/ir/ir.h
@@ -4,10 +4,10 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/service.h"
-
namespace Service {
+
+class Interface;
+
namespace IR {
/**
@@ -20,6 +20,53 @@ namespace IR {
*/
void GetHandles(Interface* self);
+/**
+ * IR::InitializeIrNopShared service function
+ * Inputs:
+ * 1 : Size of transfer buffer
+ * 2 : Recv buffer size
+ * 3 : unknown
+ * 4 : Send buffer size
+ * 5 : unknown
+ * 6 : BaudRate (u8)
+ * 7 : 0
+ * 8 : Handle of transfer shared memory
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void InitializeIrNopShared(Interface* self);
+
+/**
+ * IR::FinalizeIrNop service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void FinalizeIrNop(Interface* self);
+
+/**
+ * IR::GetConnectionStatusEvent service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Connection Status Event handle
+ */
+void GetConnectionStatusEvent(Interface* self);
+
+/**
+ * IR::Disconnect service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void Disconnect(Interface* self);
+
+/**
+ * IR::RequireConnection service function
+ * Inputs:
+ * 1 : unknown (u8), looks like always 1
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void RequireConnection(Interface* self);
+
/// Initialize IR service
void Init();
diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp
index 96ae63420..c0300f109 100644
--- a/src/core/hle/service/ir/ir_rst.cpp
+++ b/src/core/hle/service/ir/ir_rst.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/ir/ir.h"
#include "core/hle/service/ir/ir_rst.h"
diff --git a/src/core/hle/service/ir/ir_u.cpp b/src/core/hle/service/ir/ir_u.cpp
index 1b1e3078b..96f76cb83 100644
--- a/src/core/hle/service/ir/ir_u.cpp
+++ b/src/core/hle/service/ir/ir_u.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/ir/ir.h"
#include "core/hle/service/ir/ir_u.h"
namespace Service {
diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp
index 8e3ff140f..06a601029 100644
--- a/src/core/hle/service/ir/ir_user.cpp
+++ b/src/core/hle/service/ir/ir_user.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/ir/ir.h"
#include "core/hle/service/ir/ir_user.h"
@@ -10,20 +9,32 @@ namespace Service {
namespace IR {
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010182, nullptr, "InitializeIrNop"},
- {0x00020000, nullptr, "FinalizeIrNop"},
- {0x00030000, nullptr, "ClearReceiveBuffer"},
- {0x00040000, nullptr, "ClearSendBuffer"},
- {0x00060040, nullptr, "RequireConnection"},
- {0x00090000, nullptr, "Disconnect"},
- {0x000A0000, nullptr, "GetReceiveEvent"},
- {0x000B0000, nullptr, "GetSendEvent"},
- {0x000C0000, nullptr, "GetConnectionStatusEvent"},
- {0x000D0042, nullptr, "SendIrNop"},
- {0x000E0042, nullptr, "SendIrNopLarge"},
- {0x00180182, nullptr, "InitializeIrNopShared"},
- {0x00190040, nullptr, "ReleaseReceivedData"},
- {0x001A0040, nullptr, "SetOwnMachineId"},
+ {0x00010182, nullptr, "InitializeIrNop"},
+ {0x00020000, FinalizeIrNop, "FinalizeIrNop"},
+ {0x00030000, nullptr, "ClearReceiveBuffer"},
+ {0x00040000, nullptr, "ClearSendBuffer"},
+ {0x000500C0, nullptr, "WaitConnection"},
+ {0x00060040, RequireConnection, "RequireConnection"},
+ {0x000702C0, nullptr, "AutoConnection"},
+ {0x00080000, nullptr, "AnyConnection"},
+ {0x00090000, Disconnect, "Disconnect"},
+ {0x000A0000, nullptr, "GetReceiveEvent"},
+ {0x000B0000, nullptr, "GetSendEvent"},
+ {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"},
+ {0x000D0042, nullptr, "SendIrNop"},
+ {0x000E0042, nullptr, "SendIrNopLarge"},
+ {0x000F0040, nullptr, "ReceiveIrnop"},
+ {0x00100042, nullptr, "ReceiveIrnopLarge"},
+ {0x00110040, nullptr, "GetLatestReceiveErrorResult"},
+ {0x00120040, nullptr, "GetLatestSendErrorResult"},
+ {0x00130000, nullptr, "GetConnectionStatus"},
+ {0x00140000, nullptr, "GetTryingToConnectStatus"},
+ {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"},
+ {0x00160000, nullptr, "GetSendSizeFreeAndUsed"},
+ {0x00170000, nullptr, "GetConnectionRole"},
+ {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"},
+ {0x00190040, nullptr, "ReleaseReceivedData"},
+ {0x001A0040, nullptr, "SetOwnMachineId"},
};
IR_User_Interface::IR_User_Interface() {
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp
index f84ce4d72..ecec2ce32 100644
--- a/src/core/hle/service/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -2,9 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/common_types.h"
#include "common/logging/log.h"
-#include "core/hle/hle.h"
#include "core/hle/service/ldr_ro.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 25e70d321..f792bc9cd 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/mic_u.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -18,14 +17,14 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00050000, nullptr, "StopSampling"},
{0x00060000, nullptr, "IsSampling"},
{0x00070000, nullptr, "GetEventHandle"},
- {0x00080040, nullptr, "SetControl"},
- {0x00090000, nullptr, "GetControl"},
- {0x000A0040, nullptr, "SetBias"},
- {0x000B0000, nullptr, "GetBias"},
+ {0x00080040, nullptr, "SetGain"},
+ {0x00090000, nullptr, "GetGain"},
+ {0x000A0040, nullptr, "SetPower"},
+ {0x000B0000, nullptr, "GetPower"},
{0x000C0042, nullptr, "size"},
{0x000D0040, nullptr, "SetClamp"},
{0x000E0000, nullptr, "GetClamp"},
- {0x000F0040, nullptr, "unknown_input1"},
+ {0x000F0040, nullptr, "SetAllowShellClosed"},
{0x00100040, nullptr, "unknown_input2"},
};
diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm_u.cpp
index df3c97193..8fdf1ef90 100644
--- a/src/core/hle/service/ndm_u.cpp
+++ b/src/core/hle/service/ndm_u.cpp
@@ -2,8 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "ndm_u.h"
+#include "core/hle/service/ndm_u.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace NDM_U
@@ -14,10 +13,26 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00010042, nullptr, "EnterExclusiveState"},
{0x00020002, nullptr, "LeaveExclusiveState"},
{0x00030000, nullptr, "QueryExclusiveMode"},
+ {0x00040002, nullptr, "LockState"},
+ {0x00050002, nullptr, "UnlockState"},
{0x00060040, nullptr, "SuspendDaemons"},
+ {0x00070040, nullptr, "ResumeDaemons"},
{0x00080040, nullptr, "DisableWifiUsage"},
{0x00090000, nullptr, "EnableWifiUsage"},
+ {0x000A0000, nullptr, "GetCurrentState"},
+ {0x000B0000, nullptr, "GetTargetState"},
+ {0x000C0000, nullptr, "<Stubbed>"},
+ {0x000D0040, nullptr, "QueryStatus"},
+ {0x000E0040, nullptr, "GetDaemonDisableCount"},
+ {0x000F0000, nullptr, "GetSchedulerDisableCount"},
+ {0x00100040, nullptr, "SetScanInterval"},
+ {0x00110000, nullptr, "GetScanInterval"},
+ {0x00120040, nullptr, "SetRetryInterval"},
+ {0x00130000, nullptr, "GetRetryInterval"},
{0x00140040, nullptr, "OverrideDefaultDaemons"},
+ {0x00150000, nullptr, "ResetDefaultDaemons"},
+ {0x00160000, nullptr, "GetDefaultDaemons"},
+ {0x00170000, nullptr, "ClearHalfAwakeMacFilter"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/news/news.cpp b/src/core/hle/service/news/news.cpp
index 63cbd3850..b3f500694 100644
--- a/src/core/hle/service/news/news.cpp
+++ b/src/core/hle/service/news/news.cpp
@@ -9,10 +9,6 @@
#include "core/hle/service/news/news_s.h"
#include "core/hle/service/news/news_u.h"
-#include "core/hle/hle.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-
namespace Service {
namespace NEWS {
diff --git a/src/core/hle/service/news/news.h b/src/core/hle/service/news/news.h
index b31ade255..46a3ffcb5 100644
--- a/src/core/hle/service/news/news.h
+++ b/src/core/hle/service/news/news.h
@@ -4,9 +4,6 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/service.h"
-
namespace Service {
namespace NEWS {
diff --git a/src/core/hle/service/news/news_s.cpp b/src/core/hle/service/news/news_s.cpp
index 2f8c37d9e..39b5a50f8 100644
--- a/src/core/hle/service/news/news_s.cpp
+++ b/src/core/hle/service/news/news_s.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/news/news.h"
#include "core/hle/service/news/news_s.h"
@@ -11,6 +10,18 @@ namespace NEWS {
const Interface::FunctionInfo FunctionTable[] = {
{0x000100C6, nullptr, "AddNotification"},
+ {0x00050000, nullptr, "GetTotalNotifications"},
+ {0x00060042, nullptr, "SetNewsDBHeader"},
+ {0x00070082, nullptr, "SetNotificationHeader"},
+ {0x00080082, nullptr, "SetNotificationMessage"},
+ {0x00090082, nullptr, "SetNotificationImage"},
+ {0x000A0042, nullptr, "GetNewsDBHeader"},
+ {0x000B0082, nullptr, "GetNotificationHeader"},
+ {0x000C0082, nullptr, "GetNotificationMessage"},
+ {0x000D0082, nullptr, "GetNotificationImage"},
+ {0x000E0040, nullptr, "SetInfoLEDPattern"},
+ {0x00120082, nullptr, "GetNotificationHeaderOther"},
+ {0x00130000, nullptr, "WriteNewsDBSavedata"},
};
NEWS_S_Interface::NEWS_S_Interface() {
diff --git a/src/core/hle/service/news/news_u.cpp b/src/core/hle/service/news/news_u.cpp
index 81f45a244..6b75cc24e 100644
--- a/src/core/hle/service/news/news_u.cpp
+++ b/src/core/hle/service/news/news_u.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/news/news.h"
#include "core/hle/service/news/news_u.h"
namespace Service {
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index 73b0ee52a..ed42464ce 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/hle/service/service.h"
@@ -10,10 +11,6 @@
#include "core/hle/service/nim/nim_s.h"
#include "core/hle/service/nim/nim_u.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/hle.h"
-
namespace Service {
namespace NIM {
diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h
index f7635c747..c3106f18b 100644
--- a/src/core/hle/service/nim/nim.h
+++ b/src/core/hle/service/nim/nim.h
@@ -4,10 +4,10 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/service.h"
-
namespace Service {
+
+class Interface;
+
namespace NIM {
/**
diff --git a/src/core/hle/service/nim/nim_aoc.cpp b/src/core/hle/service/nim/nim_aoc.cpp
index e6b1b6145..4a4818d57 100644
--- a/src/core/hle/service/nim/nim_aoc.cpp
+++ b/src/core/hle/service/nim/nim_aoc.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/nim/nim.h"
#include "core/hle/service/nim/nim_aoc.h"
namespace Service {
diff --git a/src/core/hle/service/nim/nim_s.cpp b/src/core/hle/service/nim/nim_s.cpp
index 5d8bc059f..dcaa0255a 100644
--- a/src/core/hle/service/nim/nim_s.cpp
+++ b/src/core/hle/service/nim/nim_s.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
-#include "core/hle/service/nim/nim.h"
#include "core/hle/service/nim/nim_s.h"
namespace Service {
@@ -11,6 +9,9 @@ namespace NIM {
const Interface::FunctionInfo FunctionTable[] = {
{0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"},
+ {0x0016020A, nullptr, "ListTitles"},
+ {0x002D0042, nullptr, "DownloadTickets"},
+ {0x00420240, nullptr, "StartDownload"},
};
NIM_S_Interface::NIM_S_Interface() {
diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp
index 066570a85..eae45ebc0 100644
--- a/src/core/hle/service/nim/nim_u.cpp
+++ b/src/core/hle/service/nim/nim_u.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/nim/nim.h"
#include "core/hle/service/nim/nim_u.h"
diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp
index 6b3ef6ece..072918d62 100644
--- a/src/core/hle/service/ns_s.cpp
+++ b/src/core/hle/service/ns_s.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
#include "core/hle/service/ns_s.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -12,7 +10,21 @@
namespace NS_S {
const Interface::FunctionInfo FunctionTable[] = {
+ {0x000100C0, nullptr, "LaunchFIRM"},
{0x000200C0, nullptr, "LaunchTitle"},
+ {0x00030000, nullptr, "TerminateApplication"},
+ {0x00040040, nullptr, "TerminateProcess"},
+ {0x000500C0, nullptr, "LaunchApplicationFIRM"},
+ {0x00060042, nullptr, "SetFIRMParams4A0"},
+ {0x00070042, nullptr, "CardUpdateInitialize"},
+ {0x00080000, nullptr, "CardUpdateShutdown"},
+ {0x000D0140, nullptr, "SetTWLBannerHMAC"},
+ {0x000E0000, nullptr, "ShutdownAsync"},
+ {0x00100180, nullptr, "RebootSystem"},
+ {0x00110100, nullptr, "TerminateTitle"},
+ {0x001200C0, nullptr, "SetApplicationCpuTimeLimit"},
+ {0x00150140, nullptr, "LaunchApplication"},
+ {0x00160000, nullptr, "RebootSystemClean"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index 18b22956f..dc80984b2 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -2,9 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/common_types.h"
#include "common/logging/log.h"
-#include "core/hle/hle.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/nwm_uds.h"
@@ -106,14 +106,32 @@ static void Initialize(Service::Interface* self) {
}
const Interface::FunctionInfo FunctionTable[] = {
+ {0x00020000, nullptr, "Scrap"},
{0x00030000, Shutdown, "Shutdown"},
+ {0x00040402, nullptr, "CreateNetwork"},
+ {0x00050040, nullptr, "EjectClient"},
+ {0x00060000, nullptr, "EjectSpectator"},
+ {0x00070080, nullptr, "UpdateNetworkAttribute"},
+ {0x00080000, nullptr, "DestroyNetwork"},
+ {0x000A0000, nullptr, "DisconnectNetwork"},
+ {0x000B0000, nullptr, "GetConnectionStatus"},
+ {0x000D0040, nullptr, "GetNodeInformation"},
{0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"},
{0x00100042, nullptr, "SetBeaconAdditionalData"},
+ {0x00110040, nullptr, "GetApplicationData"},
+ {0x00120100, nullptr, "Bind"},
+ {0x00130040, nullptr, "Unbind"},
{0x001400C0, nullptr, "RecvBroadcastDataFrame"},
+ {0x00150080, nullptr, "SetMaxSendDelay"},
+ {0x00170182, nullptr, "SendTo"},
+ {0x001A0000, nullptr, "GetChannel"},
{0x001B0302, Initialize, "Initialize"},
{0x001D0044, nullptr, "BeginHostingNetwork"},
{0x001E0084, nullptr, "ConnectToNetwork"},
{0x001F0006, nullptr, "DecryptBeaconData"},
+ {0x00200040, nullptr, "Flush"},
+ {0x00210080, nullptr, "SetProbeResponseParam"},
+ {0x00220402, nullptr, "ScanOnConnection"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
index 7420a62f4..05d01bc48 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/pm_app.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -19,6 +18,10 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00070042, nullptr, "GetFIRMLaunchParams"},
{0x00080100, nullptr, "GetTitleExheaderFlags"},
{0x00090042, nullptr, "SetFIRMLaunchParams"},
+ {0x000A0140, nullptr, "SetResourceLimit"},
+ {0x000B0140, nullptr, "GetResourceLimitMax"},
+ {0x000C0080, nullptr, "UnregisterProcess"},
+ {0x000D0240, nullptr, "LaunchTitleUpdate"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index 22c1093ff..6bdee4d9e 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -110,8 +110,8 @@ void Init() {
FileSys::Path gamecoin_path("gamecoin.dat");
FileSys::Mode open_mode = {};
- open_mode.write_flag = 1;
- open_mode.create_flag = 1;
+ open_mode.write_flag.Assign(1);
+ open_mode.create_flag.Assign(1);
// Open the file and write the default gamecoin information
auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode);
if (gamecoin_result.Succeeded()) {
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index f2e76441f..4cf7383d1 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -4,11 +4,12 @@
#pragma once
-#include <array>
-#include "core/hle/service/service.h"
-#include "core/hle/result.h"
+#include "common/common_types.h"
namespace Service {
+
+class Interface;
+
namespace PTM {
/// Charge levels used by PTM functions
diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp
index 7bb990193..ca5dd0403 100644
--- a/src/core/hle/service/ptm/ptm_play.cpp
+++ b/src/core/hle/service/ptm/ptm_play.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/ptm/ptm_play.h"
namespace Service {
diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp
index 655658f3b..fe76dd108 100644
--- a/src/core/hle/service/ptm/ptm_sysm.cpp
+++ b/src/core/hle/service/ptm/ptm_sysm.cpp
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/hle/hle.h"
#include "core/hle/service/ptm/ptm.h"
#include "core/hle/service/ptm/ptm_sysm.h"
@@ -39,7 +38,8 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x08110000, nullptr, "GetShellStatus"},
{0x08120000, nullptr, "IsShutdownByBatteryEmpty"},
{0x08130000, nullptr, "FormatSavedata"},
- {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}
+ {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"},
+ {0x08180040, nullptr, "ConfigureNew3DSCPU"},
};
PTM_Sysm_Interface::PTM_Sysm_Interface() {
diff --git a/src/core/hle/service/ptm/ptm_u.cpp b/src/core/hle/service/ptm/ptm_u.cpp
index 09dc38c3e..17e764866 100644
--- a/src/core/hle/service/ptm/ptm_u.cpp
+++ b/src/core/hle/service/ptm/ptm_u.cpp
@@ -2,9 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "common/logging/log.h"
-
-#include "core/hle/hle.h"
#include "core/hle/service/ptm/ptm.h"
#include "core/hle/service/ptm/ptm_u.h"
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index 633b66fe2..b52e52d4a 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -178,17 +178,17 @@ struct CTRPollFD {
static Events TranslateTo3DS(u32 input_event) {
Events ev = {};
if (input_event & POLLIN)
- ev.pollin = 1;
+ ev.pollin.Assign(1);
if (input_event & POLLPRI)
- ev.pollpri = 1;
+ ev.pollpri.Assign(1);
if (input_event & POLLHUP)
- ev.pollhup = 1;
+ ev.pollhup.Assign(1);
if (input_event & POLLERR)
- ev.pollerr = 1;
+ ev.pollerr.Assign(1);
if (input_event & POLLOUT)
- ev.pollout = 1;
+ ev.pollout.Assign(1);
if (input_event & POLLNVAL)
- ev.pollnval = 1;
+ ev.pollnval.Assign(1);
return ev;
}
@@ -552,13 +552,23 @@ static void RecvFrom(Service::Interface* self) {
u32 flags = cmd_buffer[3];
socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]);
- u8* output_buff = Memory::GetPointer(cmd_buffer[0x104 >> 2]);
+ struct
+ {
+ u32 output_buffer_descriptor;
+ u32 output_buffer_addr;
+ u32 address_buffer_descriptor;
+ u32 output_src_address_buffer;
+ } buffer_parameters;
+
+ std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters));
+
+ u8* output_buff = Memory::GetPointer(buffer_parameters.output_buffer_addr);
sockaddr src_addr;
socklen_t src_addr_len = sizeof(src_addr);
int ret = ::recvfrom(socket_handle, (char*)output_buff, len, flags, &src_addr, &src_addr_len);
- if (cmd_buffer[0x1A0 >> 2] != 0) {
- CTRSockAddr* ctr_src_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x1A0 >> 2]));
+ if (buffer_parameters.output_src_address_buffer != 0) {
+ CTRSockAddr* ctr_src_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(buffer_parameters.output_src_address_buffer));
*ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
}
@@ -732,7 +742,8 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x000C0082, Shutdown, "Shutdown"},
{0x000D0082, nullptr, "GetHostByName"},
{0x000E00C2, nullptr, "GetHostByAddr"},
- {0x000F0106, nullptr, "unknown_resolve_ip"},
+ {0x000F0106, nullptr, "GetAddrInfo"},
+ {0x00100102, nullptr, "GetNameInfo"},
{0x00110102, nullptr, "GetSockOpt"},
{0x00120104, nullptr, "SetSockOpt"},
{0x001300C2, Fcntl, "Fcntl"},
@@ -749,6 +760,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x001E0040, nullptr, "ICMPClose"},
{0x001F0040, nullptr, "GetResolverInfo"},
{0x00210002, nullptr, "CloseSockets"},
+ {0x00230040, nullptr, "AddGlobalSocket"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 3b8c7c0e4..41fc3437b 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -2,9 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/common_types.h"
#include "common/logging/log.h"
-#include "core/hle/hle.h"
#include "core/hle/service/srv.h"
#include "core/hle/kernel/event.h"
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index cabd18c80..14a4e98ec 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -4,7 +4,7 @@
#include <random>
-#include "core/hle/hle.h"
+#include "common/common_types.h"
#include "core/hle/service/ssl_c.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -62,10 +62,24 @@ static void GenerateRandomData(Service::Interface* self) {
const Interface::FunctionInfo FunctionTable[] = {
{0x00010002, Initialize, "Initialize"},
{0x000200C2, nullptr, "CreateContext"},
+ {0x00030000, nullptr, "CreateRootCertChain"},
+ {0x00040040, nullptr, "DestroyRootCertChain"},
{0x00050082, nullptr, "AddTrustedRootCA"},
+ {0x00060080, nullptr, "RootCertChainAddDefaultCert"},
+ {0x00070080, nullptr, "RootCertChainRemoveCert"},
+ {0x000E0040, nullptr, "OpenDefaultClientCertContext"},
+ {0x000F0040, nullptr, "CloseClientCertContext"},
{0x00110042, GenerateRandomData, "GenerateRandomData"},
+ {0x00120042, nullptr, "InitializeConnectionSession"},
+ {0x00130040, nullptr, "StartConnection"},
+ {0x00140040, nullptr, "StartConnectionGetOut"},
{0x00150082, nullptr, "Read"},
{0x00170082, nullptr, "Write"},
+ {0x00180080, nullptr, "ContextSetRootCertChain"},
+ {0x00190080, nullptr, "ContextSetClientCert"},
+ {0x001B0080, nullptr, "ContextClearOpt"},
+ {0x001E0040, nullptr, "DestroyContext"},
+ {0x001F0082, nullptr, "ContextInitSharedmem"}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index 6b1b71fe4..a495441a4 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -4,15 +4,15 @@
#include <cstring>
+#include "common/common_types.h"
#include "common/logging/log.h"
-#include "core/hle/hle.h"
#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/service/y2r_u.h"
#include "core/hw/y2r.h"
#include "video_core/renderer_base.h"
-#include "video_core/utils.h"
#include "video_core/video_core.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -267,7 +267,7 @@ static void StartConversion(Service::Interface* self) {
// dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
u32 total_output_size = conversion.input_lines *
(conversion.dst.transfer_unit + conversion.dst.gap);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(
+ VideoCore::g_renderer->Rasterizer()->InvalidateRegion(
Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
LOG_DEBUG(Service_Y2R, "called");
@@ -375,21 +375,41 @@ static void DriverFinalize(Service::Interface* self) {
const Interface::FunctionInfo FunctionTable[] = {
{0x00010040, SetInputFormat, "SetInputFormat"},
+ {0x00020000, nullptr, "GetInputFormat"},
{0x00030040, SetOutputFormat, "SetOutputFormat"},
+ {0x00040000, nullptr, "GetOutputFormat"},
{0x00050040, SetRotation, "SetRotation"},
+ {0x00060000, nullptr, "GetRotation"},
{0x00070040, SetBlockAlignment, "SetBlockAlignment"},
+ {0x00080000, nullptr, "GetBlockAlignment"},
+ {0x00090040, nullptr, "SetSpacialDithering"},
+ {0x000A0000, nullptr, "GetSpacialDithering"},
+ {0x000B0040, nullptr, "SetTemporalDithering"},
+ {0x000C0000, nullptr, "GetTemporalDithering"},
{0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"},
{0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"},
{0x00100102, SetSendingY, "SetSendingY"},
{0x00110102, SetSendingU, "SetSendingU"},
{0x00120102, SetSendingV, "SetSendingV"},
{0x00130102, SetSendingYUYV, "SetSendingYUYV"},
+ {0x00140000, nullptr, "IsFinishedSendingYuv"},
+ {0x00150000, nullptr, "IsFinishedSendingY"},
+ {0x00160000, nullptr, "IsFinishedSendingU"},
+ {0x00170000, nullptr, "IsFinishedSendingV"},
{0x00180102, SetReceiving, "SetReceiving"},
+ {0x00190000, nullptr, "IsFinishedReceiving"},
{0x001A0040, SetInputLineWidth, "SetInputLineWidth"},
+ {0x001B0000, nullptr, "GetInputLineWidth"},
{0x001C0040, SetInputLines, "SetInputLines"},
+ {0x001D0000, nullptr, "GetInputLines"},
{0x001E0100, SetCoefficient, "SetCoefficient"},
+ {0x001F0000, nullptr, "GetCoefficient"},
{0x00200040, SetStandardCoefficient, "SetStandardCoefficient"},
+ {0x00210040, nullptr, "GetStandardCoefficientParams"},
{0x00220040, SetAlpha, "SetAlpha"},
+ {0x00230000, nullptr, "GetAlpha"},
+ {0x00240200, nullptr, "SetDitheringWeightParams"},
+ {0x00250000, nullptr, "GetDitheringWeightParams"},
{0x00260000, StartConversion, "StartConversion"},
{0x00270000, StopConversion, "StopConversion"},
{0x00280000, IsBusyConversion, "IsBusyConversion"},
@@ -397,6 +417,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x002A0000, PingProcess, "PingProcess"},
{0x002B0000, DriverInitialize, "DriverInitialize"},
{0x002C0000, DriverFinalize, "DriverFinalize"},
+ {0x002D0000, nullptr, "GetPackageParameter"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 7f63ff505..7a39b101d 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -161,6 +161,8 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
handle, addr, permissions, other_permissions);
+ // TODO(Subv): The same process that created a SharedMemory object can not map it in its own address space
+
SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
if (shared_memory == nullptr)
return ERR_INVALID_HANDLE;
@@ -175,13 +177,27 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
case MemoryPermission::WriteExecute:
case MemoryPermission::ReadWriteExecute:
case MemoryPermission::DontCare:
- shared_memory->Map(addr, permissions_type,
+ return shared_memory->Map(addr, permissions_type,
static_cast<MemoryPermission>(other_permissions));
- break;
default:
LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
}
- return RESULT_SUCCESS;
+
+ return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
+}
+
+static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
+ using Kernel::SharedMemory;
+
+ LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X", handle, addr);
+
+ // TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
+
+ SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
+ if (shared_memory == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ return shared_memory->Unmap(addr);
}
/// Connect to an OS service given the port name, returns the handle to the port to out
@@ -470,6 +486,7 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point
}
switch (processor_id) {
+ case THREADPROCESSORID_ALL:
case THREADPROCESSORID_DEFAULT:
case THREADPROCESSORID_0:
case THREADPROCESSORID_1:
@@ -765,7 +782,13 @@ static s64 GetSystemTick() {
static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
u32 other_permission) {
using Kernel::SharedMemory;
- // TODO(Subv): Implement this function
+
+ if (size % Memory::PAGE_SIZE != 0)
+ return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
+
+ // TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
+
+ // TODO(Subv): Implement this function properly
using Kernel::MemoryPermission;
SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(size,
@@ -781,7 +804,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
using Kernel::MemoryRegion;
- LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u param=%d", process_handle, type, param);
+ LOG_TRACE(Kernel_SVC, "called type=%u param=%d", type, param);
switch ((SystemInfoType)type) {
case SystemInfoType::REGION_MEMORY_USAGE:
@@ -807,7 +830,7 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
}
break;
case SystemInfoType::KERNEL_ALLOCATED_PAGES:
- LOG_ERROR(Kernel_SVC, "unimplemented GetSystemInfo type=2 param=%d", type, param);
+ LOG_ERROR(Kernel_SVC, "unimplemented GetSystemInfo type=2 param=%d", param);
*out = 0;
break;
case SystemInfoType::KERNEL_SPAWNED_PIDS:
@@ -912,7 +935,7 @@ static const FunctionDef SVC_Table[] = {
{0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"},
{0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"},
{0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"},
- {0x20, nullptr, "UnmapMemoryBlock"},
+ {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"},
{0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"},
{0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"},
{0x23, HLE::Wrap<CloseHandle>, "CloseHandle"},
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index bc7bde903..7e2f9cdfa 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -17,7 +17,6 @@
#include "core/core_timing.h"
#include "core/hle/service/gsp_gpu.h"
-#include "core/hle/service/dsp_dsp.h"
#include "core/hle/service/hid/hid.h"
#include "core/hw/hw.h"
@@ -26,7 +25,7 @@
#include "core/tracer/recorder.h"
#include "video_core/command_processor.h"
-#include "video_core/hwrasterizer_base.h"
+#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
#include "video_core/utils.h"
#include "video_core/video_core.h"
@@ -141,13 +140,13 @@ inline void Write(u32 addr, const T data) {
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1);
}
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress());
+ VideoCore::g_renderer->Rasterizer()->InvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress());
}
// Reset "trigger" flag and set the "finish" flag
// NOTE: This was confirmed to happen on hardware even if "address_start" is zero.
- config.trigger = 0;
- config.finished = 1;
+ config.trigger.Assign(0);
+ config.finished.Assign(1);
}
break;
}
@@ -172,7 +171,7 @@ inline void Write(u32 addr, const T data) {
u32 output_gap = config.texture_copy.output_gap * 16;
size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap);
- VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), contiguous_input_size);
+ VideoCore::g_renderer->Rasterizer()->FlushRegion(config.GetPhysicalInputAddress(), contiguous_input_size);
u32 remaining_size = config.texture_copy.size;
u32 remaining_input = input_width;
@@ -205,7 +204,7 @@ inline void Write(u32 addr, const T data) {
config.flags);
size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), contiguous_output_size);
+ VideoCore::g_renderer->Rasterizer()->InvalidateRegion(config.GetPhysicalOutputAddress(), contiguous_output_size);
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
break;
@@ -232,7 +231,7 @@ inline void Write(u32 addr, const T data) {
u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format);
u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format);
- VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), input_size);
+ VideoCore::g_renderer->Rasterizer()->FlushRegion(config.GetPhysicalInputAddress(), input_size);
for (u32 y = 0; y < output_height; ++y) {
for (u32 x = 0; x < output_width; ++x) {
@@ -339,7 +338,7 @@ inline void Write(u32 addr, const T data) {
g_regs.display_transfer_config.trigger = 0;
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), output_size);
+ VideoCore::g_renderer->Rasterizer()->InvalidateRegion(config.GetPhysicalOutputAddress(), output_size);
}
break;
}
@@ -414,11 +413,6 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0);
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1);
- // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but
- // until we can emulate DSP interrupts, this is probably the only reasonable place to do
- // this. Certain games expect this to be periodically signaled.
- DSP_DSP::SignalInterrupt();
-
// Check for user input updates
Service::HID::Update();
@@ -444,16 +438,16 @@ void Init() {
framebuffer_sub.address_left1 = 0x1848F000;
framebuffer_sub.address_left2 = 0x184C7800;
- framebuffer_top.width = 240;
- framebuffer_top.height = 400;
+ framebuffer_top.width.Assign(240);
+ framebuffer_top.height.Assign(400);
framebuffer_top.stride = 3 * 240;
- framebuffer_top.color_format = Regs::PixelFormat::RGB8;
+ framebuffer_top.color_format.Assign(Regs::PixelFormat::RGB8);
framebuffer_top.active_fb = 0;
- framebuffer_sub.width = 240;
- framebuffer_sub.height = 320;
+ framebuffer_sub.width.Assign(240);
+ framebuffer_sub.height.Assign(320);
framebuffer_sub.stride = 3 * 240;
- framebuffer_sub.color_format = Regs::PixelFormat::RGB8;
+ framebuffer_sub.color_format.Assign(Regs::PixelFormat::RGB8);
framebuffer_sub.active_fb = 0;
last_skip_frame = false;
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 5d7264f12..69df94324 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -250,7 +250,7 @@ const char *ElfReader::GetSectionName(int section) const {
return nullptr;
int name_offset = sections[section].sh_name;
- const char* ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
+ const char* ptr = reinterpret_cast<const char*>(GetSectionDataPtr(header->e_shstrndx));
if (ptr)
return ptr + name_offset;
@@ -347,10 +347,10 @@ bool ElfReader::LoadSymbols() {
SectionID sec = GetSectionByName(".symtab");
if (sec != -1) {
int stringSection = sections[sec].sh_link;
- const char *stringBase = (const char *)GetSectionDataPtr(stringSection);
+ const char *stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection));
//We have a symbol table!
- Elf32_Sym* symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
+ const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec));
unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
for (unsigned sym = 0; sym < numSymbols; sym++) {
int size = symtab[sym].st_size;
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 6b88169e1..b1907cd55 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -137,11 +137,11 @@ ResultStatus LoadFile(const std::string& filename) {
AppLoader_NCCH app_loader(std::move(file), filename);
// Load application and RomFS
- if (ResultStatus::Success == app_loader.Load()) {
+ ResultStatus result = app_loader.Load();
+ if (ResultStatus::Success == result) {
Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
- return ResultStatus::Success;
}
- break;
+ return result;
}
// CIA file format...
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 68b3f546e..93f21bec2 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -255,7 +255,8 @@ ResultStatus AppLoader_NCCH::Load() {
priority = exheader_header.arm11_system_local_caps.priority;
resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category;
- LOG_INFO(Loader, "Name: %s" , exheader_header.codeset_info.name);
+ LOG_INFO(Loader, "Name: %s" , exheader_header.codeset_info.name);
+ LOG_INFO(Loader, "Program ID: %016X" , ncch_header.program_id);
LOG_DEBUG(Loader, "Code compressed: %s" , is_compressed ? "yes" : "no");
LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point);
LOG_DEBUG(Loader, "Code size: 0x%08X", code_size);
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index fc79c3ee9..7de5bd15d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -13,6 +13,7 @@
#include "core/hle/kernel/process.h"
#include "core/memory.h"
#include "core/memory_setup.h"
+#include "core/mmio.h"
namespace Memory {
@@ -25,6 +26,12 @@ enum class PageType {
Special,
};
+struct SpecialRegion {
+ VAddr base;
+ u32 size;
+ MMIORegionPointer handler;
+};
+
/**
* A (reasonably) fast way of allowing switchable and remappable process address spaces. It loosely
* mimics the way a real CPU page table works, but instead is optimized for minimal decoding and
@@ -41,8 +48,13 @@ struct PageTable {
std::array<u8*, NUM_ENTRIES> pointers;
/**
+ * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of type `Special`.
+ */
+ std::vector<SpecialRegion> special_regions;
+
+ /**
* Array of fine grained page attributes. If it is set to any value other than `Memory`, then
- * the corresponding entry in `pointer` MUST be set to null.
+ * the corresponding entry in `pointers` MUST be set to null.
*/
std::array<PageType, NUM_ENTRIES> attributes;
};
@@ -80,10 +92,12 @@ void MapMemoryRegion(VAddr base, u32 size, u8* target) {
MapPages(base / PAGE_SIZE, size / PAGE_SIZE, target, PageType::Memory);
}
-void MapIoRegion(VAddr base, u32 size) {
+void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler) {
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size);
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base);
MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special);
+
+ current_page_table->special_regions.emplace_back(SpecialRegion{base, size, mmio_handler});
}
void UnmapRegion(VAddr base, u32 size) {
@@ -92,6 +106,22 @@ void UnmapRegion(VAddr base, u32 size) {
MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Unmapped);
}
+/**
+ * This function should only be called for virtual addreses with attribute `PageType::Special`.
+ */
+static MMIORegionPointer GetMMIOHandler(VAddr vaddr) {
+ for (const auto& region : current_page_table->special_regions) {
+ if (vaddr >= region.base && vaddr < (region.base + region.size)) {
+ return region.handler;
+ }
+ }
+ ASSERT_MSG(false, "Mapped IO page without a handler @ %08X", vaddr);
+ return nullptr; // Should never happen
+}
+
+template<typename T>
+T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
+
template <typename T>
T Read(const VAddr vaddr) {
const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
@@ -108,14 +138,17 @@ T Read(const VAddr vaddr) {
return 0;
case PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
+ break;
case PageType::Special:
- LOG_ERROR(HW_Memory, "I/O reads aren't implemented yet @ %08X", vaddr);
- return 0;
+ return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
default:
UNREACHABLE();
}
}
+template<typename T>
+void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
+
template <typename T>
void Write(const VAddr vaddr, const T data) {
u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
@@ -131,9 +164,10 @@ void Write(const VAddr vaddr, const T data) {
return;
case PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
+ break;
case PageType::Special:
- LOG_ERROR(HW_Memory, "I/O writes aren't implemented yet @ %08X", vaddr);
- return;
+ WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
+ break;
default:
UNREACHABLE();
}
@@ -191,6 +225,46 @@ void WriteBlock(const VAddr addr, const u8* data, const size_t size) {
}
}
+template<>
+u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) {
+ return mmio_handler->Read8(addr);
+}
+
+template<>
+u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) {
+ return mmio_handler->Read16(addr);
+}
+
+template<>
+u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) {
+ return mmio_handler->Read32(addr);
+}
+
+template<>
+u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) {
+ return mmio_handler->Read64(addr);
+}
+
+template<>
+void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) {
+ mmio_handler->Write8(addr, data);
+}
+
+template<>
+void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) {
+ mmio_handler->Write16(addr, data);
+}
+
+template<>
+void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) {
+ mmio_handler->Write32(addr, data);
+}
+
+template<>
+void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) {
+ mmio_handler->Write64(addr, data);
+}
+
PAddr VirtualToPhysicalAddress(const VAddr addr) {
if (addr == 0) {
return 0;
@@ -217,7 +291,7 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) {
} else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
return addr - VRAM_PADDR + VRAM_VADDR;
} else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
- return addr - FCRAM_PADDR + Kernel::g_current_process->GetLinearHeapBase();
+ return addr - FCRAM_PADDR + Kernel::g_current_process->GetLinearHeapAreaAddress();
} else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
} else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h
index 84ff30120..05f70a1fe 100644
--- a/src/core/memory_setup.h
+++ b/src/core/memory_setup.h
@@ -23,10 +23,11 @@ void MapMemoryRegion(VAddr base, u32 size, u8* target);
/**
* Maps a region of the emulated process address space as a IO region.
- * @note Currently this can only be used to mark a region as being IO, since actual memory-mapped
- * IO isn't yet supported.
+ * @param base The address to start mapping at. Must be page-aligned.
+ * @param size The amount of bytes to map. Must be page-aligned.
+ * @param mmio_handler The handler that backs the mapping.
*/
-void MapIoRegion(VAddr base, u32 size);
+void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler);
void UnmapRegion(VAddr base, u32 size);
diff --git a/src/core/mmio.h b/src/core/mmio.h
new file mode 100644
index 000000000..06b555e98
--- /dev/null
+++ b/src/core/mmio.h
@@ -0,0 +1,34 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+
+#include "common/common_types.h"
+
+namespace Memory {
+
+/**
+ * Represents a device with memory mapped IO.
+ * A device may be mapped to multiple regions of memory.
+ */
+class MMIORegion {
+public:
+ virtual ~MMIORegion() = default;
+
+ virtual u8 Read8(VAddr addr) = 0;
+ virtual u16 Read16(VAddr addr) = 0;
+ virtual u32 Read32(VAddr addr) = 0;
+ virtual u64 Read64(VAddr addr) = 0;
+
+ virtual void Write8(VAddr addr, u8 data) = 0;
+ virtual void Write16(VAddr addr, u16 data) = 0;
+ virtual void Write32(VAddr addr, u32 data) = 0;
+ virtual void Write64(VAddr addr, u64 data) = 0;
+};
+
+using MMIORegionPointer = std::shared_ptr<MMIORegion>;
+
+};
diff --git a/src/core/system.cpp b/src/core/system.cpp
index 7e9c56538..4a4757af3 100644
--- a/src/core/system.cpp
+++ b/src/core/system.cpp
@@ -2,9 +2,12 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "audio_core/audio_core.h"
+
#include "core/core.h"
#include "core/core_timing.h"
#include "core/system.h"
+#include "core/gdbstub/gdbstub.h"
#include "core/hw/hw.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/kernel.h"
@@ -12,23 +15,27 @@
#include "video_core/video_core.h"
-#include "core/gdbstub/gdbstub.h"
-
namespace System {
-void Init(EmuWindow* emu_window) {
+Result Init(EmuWindow* emu_window) {
Core::Init();
CoreTiming::Init();
Memory::Init();
HW::Init();
Kernel::Init();
HLE::Init();
- VideoCore::Init(emu_window);
+ if (!VideoCore::Init(emu_window)) {
+ return Result::ErrorInitVideoCore;
+ }
+ AudioCore::Init();
GDBStub::Init();
+
+ return Result::Success;
}
void Shutdown() {
GDBStub::Shutdown();
+ AudioCore::Shutdown();
VideoCore::Shutdown();
HLE::Shutdown();
Kernel::Shutdown();
diff --git a/src/core/system.h b/src/core/system.h
index 59a75ca12..a4a627ea9 100644
--- a/src/core/system.h
+++ b/src/core/system.h
@@ -8,7 +8,14 @@ class EmuWindow;
namespace System {
-void Init(EmuWindow* emu_window);
+enum class Result {
+ Success, ///< Everything is fine
+ Error, ///< Something went wrong (no module specified)
+ ErrorInitCore, ///< Something went wrong during core init
+ ErrorInitVideoCore, ///< Something went wrong during video core init
+};
+
+Result Init(EmuWindow* emu_window);
void Shutdown();
}
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 2a924f4ad..76cfd4f7d 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -11,8 +11,10 @@ set(SRCS
pica.cpp
primitive_assembly.cpp
rasterizer.cpp
+ renderer_base.cpp
shader/shader.cpp
shader/shader_interpreter.cpp
+ swrasterizer.cpp
utils.cpp
video_core.cpp
)
@@ -30,13 +32,16 @@ set(HEADERS
clipper.h
command_processor.h
gpu_debugger.h
- hwrasterizer_base.h
pica.h
+ pica_state.h
+ pica_types.h
primitive_assembly.h
rasterizer.h
+ rasterizer_interface.h
renderer_base.h
shader/shader.h
shader/shader_interpreter.h
+ swrasterizer.h
utils.h
video_core.h
)
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp
index ed99c4f13..3d503486e 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -6,6 +6,7 @@
#include "video_core/clipper.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/rasterizer.h"
#include "video_core/shader/shader_interpreter.h"
@@ -59,15 +60,17 @@ static void InitScreenCoordinates(OutputVertex& vtx)
} viewport;
const auto& regs = g_state.regs;
- viewport.halfsize_x = float24::FromRawFloat24(regs.viewport_size_x);
- viewport.halfsize_y = float24::FromRawFloat24(regs.viewport_size_y);
+ viewport.halfsize_x = float24::FromRaw(regs.viewport_size_x);
+ viewport.halfsize_y = float24::FromRaw(regs.viewport_size_y);
viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.viewport_corner.x));
viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.viewport_corner.y));
- viewport.zscale = float24::FromRawFloat24(regs.viewport_depth_range);
- viewport.offset_z = float24::FromRawFloat24(regs.viewport_depth_far_plane);
+ viewport.zscale = float24::FromRaw(regs.viewport_depth_range);
+ viewport.offset_z = float24::FromRaw(regs.viewport_depth_far_plane);
float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w;
vtx.color *= inv_w;
+ vtx.view *= inv_w;
+ vtx.quat *= inv_w;
vtx.tc0 *= inv_w;
vtx.tc1 *= inv_w;
vtx.tc2 *= inv_w;
@@ -78,7 +81,7 @@ static void InitScreenCoordinates(OutputVertex& vtx)
vtx.screenpos[2] = viewport.offset_z + vtx.pos.z * inv_w * viewport.zscale;
}
-void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
+void ProcessTriangle(const OutputVertex &v0, const OutputVertex &v1, const OutputVertex &v2) {
using boost::container::static_vector;
// Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at
diff --git a/src/video_core/clipper.h b/src/video_core/clipper.h
index 6ed01e877..f85d8d4c9 100644
--- a/src/video_core/clipper.h
+++ b/src/video_core/clipper.h
@@ -14,7 +14,7 @@ namespace Clipper {
using Shader::OutputVertex;
-void ProcessTriangle(OutputVertex& v0, OutputVertex& v1, OutputVertex& v2);
+void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2);
} // namespace
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index bd1b09a4b..2274dfa66 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -15,6 +15,7 @@
#include "video_core/clipper.h"
#include "video_core/command_processor.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/primitive_assembly.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
@@ -73,6 +74,14 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D);
break;
+ case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.index, 0x232):
+ if (regs.vs_default_attributes_setup.index == 15) {
+ // Reset immediate primitive state
+ g_state.immediate.primitive_assembler.Reconfigure(regs.triangle_topology);
+ g_state.immediate.attribute_id = 0;
+ }
+ break;
+
// Load default vertex input attributes
case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[0], 0x233):
case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[1], 0x234):
@@ -98,21 +107,58 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
Math::Vec4<float24>& attribute = g_state.vs.default_attributes[setup.index];
// NOTE: The destination component order indeed is "backwards"
- attribute.w = float24::FromRawFloat24(default_attr_write_buffer[0] >> 8);
- attribute.z = float24::FromRawFloat24(((default_attr_write_buffer[0] & 0xFF) << 16) | ((default_attr_write_buffer[1] >> 16) & 0xFFFF));
- attribute.y = float24::FromRawFloat24(((default_attr_write_buffer[1] & 0xFFFF) << 8) | ((default_attr_write_buffer[2] >> 24) & 0xFF));
- attribute.x = float24::FromRawFloat24(default_attr_write_buffer[2] & 0xFFFFFF);
+ attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8);
+ attribute.z = float24::FromRaw(((default_attr_write_buffer[0] & 0xFF) << 16) | ((default_attr_write_buffer[1] >> 16) & 0xFFFF));
+ attribute.y = float24::FromRaw(((default_attr_write_buffer[1] & 0xFFFF) << 8) | ((default_attr_write_buffer[2] >> 24) & 0xFF));
+ attribute.x = float24::FromRaw(default_attr_write_buffer[2] & 0xFFFFFF);
LOG_TRACE(HW_GPU, "Set default VS attribute %x to (%f %f %f %f)", (int)setup.index,
attribute.x.ToFloat32(), attribute.y.ToFloat32(), attribute.z.ToFloat32(),
attribute.w.ToFloat32());
// TODO: Verify that this actually modifies the register!
- setup.index = setup.index + 1;
+ if (setup.index < 15) {
+ setup.index++;
+ } else {
+ // Put each attribute into an immediate input buffer.
+ // When all specified immediate attributes are present, the Vertex Shader is invoked and everything is
+ // sent to the primitive assembler.
+
+ auto& immediate_input = g_state.immediate.input;
+ auto& immediate_attribute_id = g_state.immediate.attribute_id;
+ const auto& attribute_config = regs.vertex_attributes;
+
+ immediate_input.attr[immediate_attribute_id++] = attribute;
+
+ if (immediate_attribute_id >= attribute_config.GetNumTotalAttributes()) {
+ immediate_attribute_id = 0;
+
+ Shader::UnitState<false> shader_unit;
+ Shader::Setup(shader_unit);
+
+ // Send to vertex shader
+ Shader::OutputVertex output = Shader::Run(shader_unit, immediate_input, attribute_config.GetNumTotalAttributes());
+
+ // Send to renderer
+ using Pica::Shader::OutputVertex;
+ auto AddTriangle = [](const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2) {
+ VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2);
+ };
+
+ g_state.immediate.primitive_assembler.SubmitVertex(output, AddTriangle);
+ }
+ }
}
break;
}
+ case PICA_REG_INDEX(gpu_mode):
+ if (regs.gpu_mode == Regs::GPUMode::Configuring && regs.vs_default_attributes_setup.index == 15) {
+ // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring
+ VideoCore::g_renderer->Rasterizer()->DrawTriangles();
+ }
+ break;
+
case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c):
case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d):
{
@@ -157,15 +203,25 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
// TODO: What happens if a loader overwrites a previous one's data?
for (unsigned component = 0; component < loader_config.component_count; ++component) {
- if (component >= 12)
+ if (component >= 12) {
LOG_ERROR(HW_GPU, "Overflow in the vertex attribute loader %u trying to load component %u", loader, component);
+ continue;
+ }
+
u32 attribute_index = loader_config.GetComponent(component);
- vertex_attribute_sources[attribute_index] = load_address;
- vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count);
- vertex_attribute_formats[attribute_index] = attribute_config.GetFormat(attribute_index);
- vertex_attribute_elements[attribute_index] = attribute_config.GetNumElements(attribute_index);
- vertex_attribute_element_size[attribute_index] = attribute_config.GetElementSizeInBytes(attribute_index);
- load_address += attribute_config.GetStride(attribute_index);
+ if (attribute_index < 12) {
+ vertex_attribute_sources[attribute_index] = load_address;
+ vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count);
+ vertex_attribute_formats[attribute_index] = attribute_config.GetFormat(attribute_index);
+ vertex_attribute_elements[attribute_index] = attribute_config.GetNumElements(attribute_index);
+ vertex_attribute_element_size[attribute_index] = attribute_config.GetElementSizeInBytes(attribute_index);
+ load_address += attribute_config.GetStride(attribute_index);
+ } else if (attribute_index < 16) {
+ // Attribute ids 12, 13, 14 and 15 signify 4, 8, 12 and 16-byte paddings, respectively
+ load_address += (attribute_index - 11) * 4;
+ } else {
+ UNREACHABLE(); // This is truly unreachable due to the number of bits for each component
+ }
}
}
@@ -336,19 +392,14 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
}
}
- if (Settings::values.use_hw_renderer) {
- // Send to hardware renderer
- static auto AddHWTriangle = [](const Pica::Shader::OutputVertex& v0,
- const Pica::Shader::OutputVertex& v1,
- const Pica::Shader::OutputVertex& v2) {
- VideoCore::g_renderer->hw_rasterizer->AddTriangle(v0, v1, v2);
- };
+ // Send to renderer
+ using Pica::Shader::OutputVertex;
+ auto AddTriangle = [](
+ const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2) {
+ VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2);
+ };
- primitive_assembler.SubmitVertex(output, AddHWTriangle);
- } else {
- // Send to triangle clipper
- primitive_assembler.SubmitVertex(output, Clipper::ProcessTriangle);
- }
+ primitive_assembler.SubmitVertex(output, AddTriangle);
}
for (auto& range : memory_accesses.ranges) {
@@ -356,9 +407,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
range.second, range.first);
}
- if (Settings::values.use_hw_renderer) {
- VideoCore::g_renderer->hw_rasterizer->DrawTriangles();
- }
+ VideoCore::g_renderer->Rasterizer()->DrawTriangles();
#if PICA_DUMP_GEOMETRY
geometry_dumper.Dump();
@@ -425,10 +474,10 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
uniform[3 - i] = float24::FromFloat32(*(float*)(&uniform_write_buffer[i]));
} else {
// TODO: Untested
- uniform.w = float24::FromRawFloat24(uniform_write_buffer[0] >> 8);
- uniform.z = float24::FromRawFloat24(((uniform_write_buffer[0] & 0xFF)<<16) | ((uniform_write_buffer[1] >> 16) & 0xFFFF));
- uniform.y = float24::FromRawFloat24(((uniform_write_buffer[1] & 0xFFFF)<<8) | ((uniform_write_buffer[2] >> 24) & 0xFF));
- uniform.x = float24::FromRawFloat24(uniform_write_buffer[2] & 0xFFFFFF);
+ uniform.w = float24::FromRaw(uniform_write_buffer[0] >> 8);
+ uniform.z = float24::FromRaw(((uniform_write_buffer[0] & 0xFF) << 16) | ((uniform_write_buffer[1] >> 16) & 0xFFFF));
+ uniform.y = float24::FromRaw(((uniform_write_buffer[1] & 0xFFFF) << 8) | ((uniform_write_buffer[2] >> 24) & 0xFF));
+ uniform.x = float24::FromRaw(uniform_write_buffer[2] & 0xFFFFFF);
}
LOG_TRACE(HW_GPU, "Set uniform %x to (%f %f %f %f)", (int)uniform_setup.index,
@@ -436,7 +485,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
uniform.w.ToFloat32());
// TODO: Verify that this actually modifies the register!
- uniform_setup.index = uniform_setup.index + 1;
+ uniform_setup.index.Assign(uniform_setup.index + 1);
}
break;
}
@@ -471,11 +520,29 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
break;
}
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[0], 0x1c8):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[1], 0x1c9):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[2], 0x1ca):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[3], 0x1cb):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[4], 0x1cc):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[5], 0x1cd):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[6], 0x1ce):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[7], 0x1cf):
+ {
+ auto& lut_config = regs.lighting.lut_config;
+
+ ASSERT_MSG(lut_config.index < 256, "lut_config.index exceeded maximum value of 255!");
+
+ g_state.lighting.luts[lut_config.type][lut_config.index].raw = value;
+ lut_config.index.Assign(lut_config.index + 1);
+ break;
+ }
+
default:
break;
}
- VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id);
+ VideoCore::g_renderer->Rasterizer()->NotifyPicaRegisterChanged(id);
if (g_debug_context)
g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id));
@@ -493,9 +560,8 @@ void ProcessCommandList(const u32* list, u32 size) {
u32 value = *g_state.cmd_list.current_ptr++;
const CommandHeader header = { *g_state.cmd_list.current_ptr++ };
- u32 cmd = header.cmd_id;
- WritePicaReg(cmd, value, header.parameter_mask);
+ WritePicaReg(header.cmd_id, value, header.parameter_mask);
for (unsigned i = 0; i < header.extra_data_length; ++i) {
u32 cmd = header.cmd_id + (header.group_commands ? i + 1 : 0);
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index f1cfa9361..271e81ca1 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -28,6 +28,7 @@
#include "core/settings.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/renderer_base.h"
#include "video_core/utils.h"
#include "video_core/video_core.h"
@@ -46,10 +47,8 @@ void DebugContext::OnEvent(Event event, void* data) {
{
std::unique_lock<std::mutex> lock(breakpoint_mutex);
- if (Settings::values.use_hw_renderer) {
- // Commit the hardware renderer's framebuffer so it will show on debug widgets
- VideoCore::g_renderer->hw_rasterizer->CommitFramebuffer();
- }
+ // Commit the hardware renderer's framebuffer so it will show on debug widgets
+ VideoCore::g_renderer->Rasterizer()->FlushFramebuffer();
// TODO: Should stop the CPU thread here once we multithread emulation.
@@ -115,7 +114,7 @@ void GeometryDumper::Dump() {
}
-void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, const State::ShaderSetup& setup, const Regs::VSOutputAttributes* output_attributes)
+void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, const Shader::ShaderSetup& setup, const Regs::VSOutputAttributes* output_attributes)
{
struct StuffToWrite {
u8* pointer;
@@ -203,11 +202,11 @@ void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, c
if (it == output_info_table.end()) {
output_info_table.emplace_back();
- output_info_table.back().type = type;
- output_info_table.back().component_mask = component_mask;
- output_info_table.back().id = i;
+ output_info_table.back().type.Assign(type);
+ output_info_table.back().component_mask.Assign(component_mask);
+ output_info_table.back().id.Assign(i);
} else {
- it->component_mask = it->component_mask | component_mask;
+ it->component_mask.Assign(it->component_mask | component_mask);
}
} catch (const std::out_of_range& ) {
DEBUG_ASSERT_MSG(false, "Unknown output attribute mapping");
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index 85762f5b4..795160a32 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -17,6 +17,7 @@
#include "core/tracer/recorder.h"
#include "video_core/pica.h"
+#include "video_core/shader/shader.h"
namespace Pica {
@@ -182,7 +183,7 @@ private:
};
void DumpShader(const std::string& filename, const Regs::ShaderConfig& config,
- const State::ShaderSetup& setup, const Regs::VSOutputAttributes* output_attributes);
+ const Shader::ShaderSetup& setup, const Regs::VSOutputAttributes* output_attributes);
// Utility class to log Pica commands.
diff --git a/src/video_core/pica.cpp b/src/video_core/pica.cpp
index 8c528989e..32ad72674 100644
--- a/src/video_core/pica.cpp
+++ b/src/video_core/pica.cpp
@@ -6,72 +6,481 @@
#include <unordered_map>
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/shader/shader.h"
namespace Pica {
State g_state;
+static const std::pair<u16, const char*> register_names[] = {
+ { 0x010, "GPUREG_FINALIZE" },
+
+ { 0x040, "GPUREG_FACECULLING_CONFIG" },
+ { 0x041, "GPUREG_VIEWPORT_WIDTH" },
+ { 0x042, "GPUREG_VIEWPORT_INVW" },
+ { 0x043, "GPUREG_VIEWPORT_HEIGHT" },
+ { 0x044, "GPUREG_VIEWPORT_INVH" },
+
+ { 0x047, "GPUREG_FRAGOP_CLIP" },
+ { 0x048, "GPUREG_FRAGOP_CLIP_DATA0" },
+ { 0x049, "GPUREG_FRAGOP_CLIP_DATA1" },
+ { 0x04A, "GPUREG_FRAGOP_CLIP_DATA2" },
+ { 0x04B, "GPUREG_FRAGOP_CLIP_DATA3" },
+
+ { 0x04D, "GPUREG_DEPTHMAP_SCALE" },
+ { 0x04E, "GPUREG_DEPTHMAP_OFFSET" },
+ { 0x04F, "GPUREG_SH_OUTMAP_TOTAL" },
+ { 0x050, "GPUREG_SH_OUTMAP_O0" },
+ { 0x051, "GPUREG_SH_OUTMAP_O1" },
+ { 0x052, "GPUREG_SH_OUTMAP_O2" },
+ { 0x053, "GPUREG_SH_OUTMAP_O3" },
+ { 0x054, "GPUREG_SH_OUTMAP_O4" },
+ { 0x055, "GPUREG_SH_OUTMAP_O5" },
+ { 0x056, "GPUREG_SH_OUTMAP_O6" },
+
+ { 0x061, "GPUREG_EARLYDEPTH_FUNC" },
+ { 0x062, "GPUREG_EARLYDEPTH_TEST1" },
+ { 0x063, "GPUREG_EARLYDEPTH_CLEAR" },
+ { 0x064, "GPUREG_SH_OUTATTR_MODE" },
+ { 0x065, "GPUREG_SCISSORTEST_MODE" },
+ { 0x066, "GPUREG_SCISSORTEST_POS" },
+ { 0x067, "GPUREG_SCISSORTEST_DIM" },
+ { 0x068, "GPUREG_VIEWPORT_XY" },
+
+ { 0x06A, "GPUREG_EARLYDEPTH_DATA" },
+
+ { 0x06D, "GPUREG_DEPTHMAP_ENABLE" },
+ { 0x06E, "GPUREG_RENDERBUF_DIM" },
+ { 0x06F, "GPUREG_SH_OUTATTR_CLOCK" },
+
+ { 0x080, "GPUREG_TEXUNIT_CONFIG" },
+ { 0x081, "GPUREG_TEXUNIT0_BORDER_COLOR" },
+ { 0x082, "GPUREG_TEXUNIT0_DIM" },
+ { 0x083, "GPUREG_TEXUNIT0_PARAM" },
+ { 0x084, "GPUREG_TEXUNIT0_LOD" },
+ { 0x085, "GPUREG_TEXUNIT0_ADDR1" },
+ { 0x086, "GPUREG_TEXUNIT0_ADDR2" },
+ { 0x087, "GPUREG_TEXUNIT0_ADDR3" },
+ { 0x088, "GPUREG_TEXUNIT0_ADDR4" },
+ { 0x089, "GPUREG_TEXUNIT0_ADDR5" },
+ { 0x08A, "GPUREG_TEXUNIT0_ADDR6" },
+ { 0x08B, "GPUREG_TEXUNIT0_SHADOW" },
+
+ { 0x08E, "GPUREG_TEXUNIT0_TYPE" },
+ { 0x08F, "GPUREG_LIGHTING_ENABLE0" },
+
+ { 0x091, "GPUREG_TEXUNIT1_BORDER_COLOR" },
+ { 0x092, "GPUREG_TEXUNIT1_DIM" },
+ { 0x093, "GPUREG_TEXUNIT1_PARAM" },
+ { 0x094, "GPUREG_TEXUNIT1_LOD" },
+ { 0x095, "GPUREG_TEXUNIT1_ADDR" },
+ { 0x096, "GPUREG_TEXUNIT1_TYPE" },
+
+ { 0x099, "GPUREG_TEXUNIT2_BORDER_COLOR" },
+ { 0x09A, "GPUREG_TEXUNIT2_DIM" },
+ { 0x09B, "GPUREG_TEXUNIT2_PARAM" },
+ { 0x09C, "GPUREG_TEXUNIT2_LOD" },
+ { 0x09D, "GPUREG_TEXUNIT2_ADDR" },
+ { 0x09E, "GPUREG_TEXUNIT2_TYPE" },
+
+ { 0x0A8, "GPUREG_TEXUNIT3_PROCTEX0" },
+ { 0x0A9, "GPUREG_TEXUNIT3_PROCTEX1" },
+ { 0x0AA, "GPUREG_TEXUNIT3_PROCTEX2" },
+ { 0x0AB, "GPUREG_TEXUNIT3_PROCTEX3" },
+ { 0x0AC, "GPUREG_TEXUNIT3_PROCTEX4" },
+ { 0x0AD, "GPUREG_TEXUNIT3_PROCTEX5" },
+
+ { 0x0AF, "GPUREG_PROCTEX_LUT" },
+ { 0x0B0, "GPUREG_PROCTEX_LUT_DATA0" },
+ { 0x0B1, "GPUREG_PROCTEX_LUT_DATA1" },
+ { 0x0B2, "GPUREG_PROCTEX_LUT_DATA2" },
+ { 0x0B3, "GPUREG_PROCTEX_LUT_DATA3" },
+ { 0x0B4, "GPUREG_PROCTEX_LUT_DATA4" },
+ { 0x0B5, "GPUREG_PROCTEX_LUT_DATA5" },
+ { 0x0B6, "GPUREG_PROCTEX_LUT_DATA6" },
+ { 0x0B7, "GPUREG_PROCTEX_LUT_DATA7" },
+
+ { 0x0C0, "GPUREG_TEXENV0_SOURCE" },
+ { 0x0C1, "GPUREG_TEXENV0_OPERAND" },
+ { 0x0C2, "GPUREG_TEXENV0_COMBINER" },
+ { 0x0C3, "GPUREG_TEXENV0_COLOR" },
+ { 0x0C4, "GPUREG_TEXENV0_SCALE" },
+
+ { 0x0C8, "GPUREG_TEXENV1_SOURCE" },
+ { 0x0C9, "GPUREG_TEXENV1_OPERAND" },
+ { 0x0CA, "GPUREG_TEXENV1_COMBINER" },
+ { 0x0CB, "GPUREG_TEXENV1_COLOR" },
+ { 0x0CC, "GPUREG_TEXENV1_SCALE" },
+
+ { 0x0D0, "GPUREG_TEXENV2_SOURCE" },
+ { 0x0D1, "GPUREG_TEXENV2_OPERAND" },
+ { 0x0D2, "GPUREG_TEXENV2_COMBINER" },
+ { 0x0D3, "GPUREG_TEXENV2_COLOR" },
+ { 0x0D4, "GPUREG_TEXENV2_SCALE" },
+
+ { 0x0D8, "GPUREG_TEXENV3_SOURCE" },
+ { 0x0D9, "GPUREG_TEXENV3_OPERAND" },
+ { 0x0DA, "GPUREG_TEXENV3_COMBINER" },
+ { 0x0DB, "GPUREG_TEXENV3_COLOR" },
+ { 0x0DC, "GPUREG_TEXENV3_SCALE" },
+
+ { 0x0E0, "GPUREG_TEXENV_UPDATE_BUFFER" },
+ { 0x0E1, "GPUREG_FOG_COLOR" },
+
+ { 0x0E4, "GPUREG_GAS_ATTENUATION" },
+ { 0x0E5, "GPUREG_GAS_ACCMAX" },
+ { 0x0E6, "GPUREG_FOG_LUT_INDEX" },
+
+ { 0x0E8, "GPUREG_FOG_LUT_DATA0" },
+ { 0x0E9, "GPUREG_FOG_LUT_DATA1" },
+ { 0x0EA, "GPUREG_FOG_LUT_DATA2" },
+ { 0x0EB, "GPUREG_FOG_LUT_DATA3" },
+ { 0x0EC, "GPUREG_FOG_LUT_DATA4" },
+ { 0x0ED, "GPUREG_FOG_LUT_DATA5" },
+ { 0x0EE, "GPUREG_FOG_LUT_DATA6" },
+ { 0x0EF, "GPUREG_FOG_LUT_DATA7" },
+ { 0x0F0, "GPUREG_TEXENV4_SOURCE" },
+ { 0x0F1, "GPUREG_TEXENV4_OPERAND" },
+ { 0x0F2, "GPUREG_TEXENV4_COMBINER" },
+ { 0x0F3, "GPUREG_TEXENV4_COLOR" },
+ { 0x0F4, "GPUREG_TEXENV4_SCALE" },
+
+ { 0x0F8, "GPUREG_TEXENV5_SOURCE" },
+ { 0x0F9, "GPUREG_TEXENV5_OPERAND" },
+ { 0x0FA, "GPUREG_TEXENV5_COMBINER" },
+ { 0x0FB, "GPUREG_TEXENV5_COLOR" },
+ { 0x0FC, "GPUREG_TEXENV5_SCALE" },
+ { 0x0FD, "GPUREG_TEXENV_BUFFER_COLOR" },
+
+ { 0x100, "GPUREG_COLOR_OPERATION" },
+ { 0x101, "GPUREG_BLEND_FUNC" },
+ { 0x102, "GPUREG_LOGIC_OP" },
+ { 0x103, "GPUREG_BLEND_COLOR" },
+ { 0x104, "GPUREG_FRAGOP_ALPHA_TEST" },
+ { 0x105, "GPUREG_STENCIL_TEST" },
+ { 0x106, "GPUREG_STENCIL_OP" },
+ { 0x107, "GPUREG_DEPTH_COLOR_MASK" },
+
+ { 0x110, "GPUREG_FRAMEBUFFER_INVALIDATE" },
+ { 0x111, "GPUREG_FRAMEBUFFER_FLUSH" },
+ { 0x112, "GPUREG_COLORBUFFER_READ" },
+ { 0x113, "GPUREG_COLORBUFFER_WRITE" },
+ { 0x114, "GPUREG_DEPTHBUFFER_READ" },
+ { 0x115, "GPUREG_DEPTHBUFFER_WRITE" },
+ { 0x116, "GPUREG_DEPTHBUFFER_FORMAT" },
+ { 0x117, "GPUREG_COLORBUFFER_FORMAT" },
+ { 0x118, "GPUREG_EARLYDEPTH_TEST2" },
+
+ { 0x11B, "GPUREG_FRAMEBUFFER_BLOCK32" },
+ { 0x11C, "GPUREG_DEPTHBUFFER_LOC" },
+ { 0x11D, "GPUREG_COLORBUFFER_LOC" },
+ { 0x11E, "GPUREG_FRAMEBUFFER_DIM" },
+
+ { 0x120, "GPUREG_GAS_LIGHT_XY" },
+ { 0x121, "GPUREG_GAS_LIGHT_Z" },
+ { 0x122, "GPUREG_GAS_LIGHT_Z_COLOR" },
+ { 0x123, "GPUREG_GAS_LUT_INDEX" },
+ { 0x124, "GPUREG_GAS_LUT_DATA" },
+
+ { 0x126, "GPUREG_GAS_DELTAZ_DEPTH" },
+
+ { 0x130, "GPUREG_FRAGOP_SHADOW" },
+
+ { 0x140, "GPUREG_LIGHT0_SPECULAR0" },
+ { 0x141, "GPUREG_LIGHT0_SPECULAR1" },
+ { 0x142, "GPUREG_LIGHT0_DIFFUSE" },
+ { 0x143, "GPUREG_LIGHT0_AMBIENT" },
+ { 0x144, "GPUREG_LIGHT0_XY" },
+ { 0x145, "GPUREG_LIGHT0_Z" },
+ { 0x146, "GPUREG_LIGHT0_SPOTDIR_XY" },
+ { 0x147, "GPUREG_LIGHT0_SPOTDIR_Z" },
+
+ { 0x149, "GPUREG_LIGHT0_CONFIG" },
+ { 0x14A, "GPUREG_LIGHT0_ATTENUATION_BIAS" },
+ { 0x14B, "GPUREG_LIGHT0_ATTENUATION_SCALE" },
+
+ { 0x150, "GPUREG_LIGHT1_SPECULAR0" },
+ { 0x151, "GPUREG_LIGHT1_SPECULAR1" },
+ { 0x152, "GPUREG_LIGHT1_DIFFUSE" },
+ { 0x153, "GPUREG_LIGHT1_AMBIENT" },
+ { 0x154, "GPUREG_LIGHT1_XY" },
+ { 0x155, "GPUREG_LIGHT1_Z" },
+ { 0x156, "GPUREG_LIGHT1_SPOTDIR_XY" },
+ { 0x157, "GPUREG_LIGHT1_SPOTDIR_Z" },
+
+ { 0x159, "GPUREG_LIGHT1_CONFIG" },
+ { 0x15A, "GPUREG_LIGHT1_ATTENUATION_BIAS" },
+ { 0x15B, "GPUREG_LIGHT1_ATTENUATION_SCALE" },
+
+ { 0x160, "GPUREG_LIGHT2_SPECULAR0" },
+ { 0x161, "GPUREG_LIGHT2_SPECULAR1" },
+ { 0x162, "GPUREG_LIGHT2_DIFFUSE" },
+ { 0x163, "GPUREG_LIGHT2_AMBIENT" },
+ { 0x164, "GPUREG_LIGHT2_XY" },
+ { 0x165, "GPUREG_LIGHT2_Z" },
+ { 0x166, "GPUREG_LIGHT2_SPOTDIR_XY" },
+ { 0x167, "GPUREG_LIGHT2_SPOTDIR_Z" },
+
+ { 0x169, "GPUREG_LIGHT2_CONFIG" },
+ { 0x16A, "GPUREG_LIGHT2_ATTENUATION_BIAS" },
+ { 0x16B, "GPUREG_LIGHT2_ATTENUATION_SCALE" },
+
+ { 0x170, "GPUREG_LIGHT3_SPECULAR0" },
+ { 0x171, "GPUREG_LIGHT3_SPECULAR1" },
+ { 0x172, "GPUREG_LIGHT3_DIFFUSE" },
+ { 0x173, "GPUREG_LIGHT3_AMBIENT" },
+ { 0x174, "GPUREG_LIGHT3_XY" },
+ { 0x175, "GPUREG_LIGHT3_Z" },
+ { 0x176, "GPUREG_LIGHT3_SPOTDIR_XY" },
+ { 0x177, "GPUREG_LIGHT3_SPOTDIR_Z" },
+
+ { 0x179, "GPUREG_LIGHT3_CONFIG" },
+ { 0x17A, "GPUREG_LIGHT3_ATTENUATION_BIAS" },
+ { 0x17B, "GPUREG_LIGHT3_ATTENUATION_SCALE" },
+
+ { 0x180, "GPUREG_LIGHT4_SPECULAR0" },
+ { 0x181, "GPUREG_LIGHT4_SPECULAR1" },
+ { 0x182, "GPUREG_LIGHT4_DIFFUSE" },
+ { 0x183, "GPUREG_LIGHT4_AMBIENT" },
+ { 0x184, "GPUREG_LIGHT4_XY" },
+ { 0x185, "GPUREG_LIGHT4_Z" },
+ { 0x186, "GPUREG_LIGHT4_SPOTDIR_XY" },
+ { 0x187, "GPUREG_LIGHT4_SPOTDIR_Z" },
+
+ { 0x189, "GPUREG_LIGHT4_CONFIG" },
+ { 0x18A, "GPUREG_LIGHT4_ATTENUATION_BIAS" },
+ { 0x18B, "GPUREG_LIGHT4_ATTENUATION_SCALE" },
+
+ { 0x190, "GPUREG_LIGHT5_SPECULAR0" },
+ { 0x191, "GPUREG_LIGHT5_SPECULAR1" },
+ { 0x192, "GPUREG_LIGHT5_DIFFUSE" },
+ { 0x193, "GPUREG_LIGHT5_AMBIENT" },
+ { 0x194, "GPUREG_LIGHT5_XY" },
+ { 0x195, "GPUREG_LIGHT5_Z" },
+ { 0x196, "GPUREG_LIGHT5_SPOTDIR_XY" },
+ { 0x197, "GPUREG_LIGHT5_SPOTDIR_Z" },
+
+ { 0x199, "GPUREG_LIGHT5_CONFIG" },
+ { 0x19A, "GPUREG_LIGHT5_ATTENUATION_BIAS" },
+ { 0x19B, "GPUREG_LIGHT5_ATTENUATION_SCALE" },
+
+ { 0x1A0, "GPUREG_LIGHT6_SPECULAR0" },
+ { 0x1A1, "GPUREG_LIGHT6_SPECULAR1" },
+ { 0x1A2, "GPUREG_LIGHT6_DIFFUSE" },
+ { 0x1A3, "GPUREG_LIGHT6_AMBIENT" },
+ { 0x1A4, "GPUREG_LIGHT6_XY" },
+ { 0x1A5, "GPUREG_LIGHT6_Z" },
+ { 0x1A6, "GPUREG_LIGHT6_SPOTDIR_XY" },
+ { 0x1A7, "GPUREG_LIGHT6_SPOTDIR_Z" },
+
+ { 0x1A9, "GPUREG_LIGHT6_CONFIG" },
+ { 0x1AA, "GPUREG_LIGHT6_ATTENUATION_BIAS" },
+ { 0x1AB, "GPUREG_LIGHT6_ATTENUATION_SCALE" },
+
+ { 0x1B0, "GPUREG_LIGHT7_SPECULAR0" },
+ { 0x1B1, "GPUREG_LIGHT7_SPECULAR1" },
+ { 0x1B2, "GPUREG_LIGHT7_DIFFUSE" },
+ { 0x1B3, "GPUREG_LIGHT7_AMBIENT" },
+ { 0x1B4, "GPUREG_LIGHT7_XY" },
+ { 0x1B5, "GPUREG_LIGHT7_Z" },
+ { 0x1B6, "GPUREG_LIGHT7_SPOTDIR_XY" },
+ { 0x1B7, "GPUREG_LIGHT7_SPOTDIR_Z" },
+
+ { 0x1B9, "GPUREG_LIGHT7_CONFIG" },
+ { 0x1BA, "GPUREG_LIGHT7_ATTENUATION_BIAS" },
+ { 0x1BB, "GPUREG_LIGHT7_ATTENUATION_SCALE" },
+
+ { 0x1C0, "GPUREG_LIGHTING_AMBIENT" },
+
+ { 0x1C2, "GPUREG_LIGHTING_NUM_LIGHTS" },
+ { 0x1C3, "GPUREG_LIGHTING_CONFIG0" },
+ { 0x1C4, "GPUREG_LIGHTING_CONFIG1" },
+ { 0x1C5, "GPUREG_LIGHTING_LUT_INDEX" },
+ { 0x1C6, "GPUREG_LIGHTING_ENABLE1" },
+
+ { 0x1C8, "GPUREG_LIGHTING_LUT_DATA0" },
+ { 0x1C9, "GPUREG_LIGHTING_LUT_DATA1" },
+ { 0x1CA, "GPUREG_LIGHTING_LUT_DATA2" },
+ { 0x1CB, "GPUREG_LIGHTING_LUT_DATA3" },
+ { 0x1CC, "GPUREG_LIGHTING_LUT_DATA4" },
+ { 0x1CD, "GPUREG_LIGHTING_LUT_DATA5" },
+ { 0x1CE, "GPUREG_LIGHTING_LUT_DATA6" },
+ { 0x1CF, "GPUREG_LIGHTING_LUT_DATA7" },
+ { 0x1D0, "GPUREG_LIGHTING_LUTINPUT_ABS" },
+ { 0x1D1, "GPUREG_LIGHTING_LUTINPUT_SELECT" },
+ { 0x1D2, "GPUREG_LIGHTING_LUTINPUT_SCALE" },
+
+ { 0x1D9, "GPUREG_LIGHTING_LIGHT_PERMUTATION" },
+
+ { 0x200, "GPUREG_ATTRIBBUFFERS_LOC" },
+ { 0x201, "GPUREG_ATTRIBBUFFERS_FORMAT_LOW" },
+ { 0x202, "GPUREG_ATTRIBBUFFERS_FORMAT_HIGH" },
+ { 0x203, "GPUREG_ATTRIBBUFFER0_OFFSET" },
+ { 0x204, "GPUREG_ATTRIBBUFFER0_CONFIG1" },
+ { 0x205, "GPUREG_ATTRIBBUFFER0_CONFIG2" },
+ { 0x206, "GPUREG_ATTRIBBUFFER1_OFFSET" },
+ { 0x207, "GPUREG_ATTRIBBUFFER1_CONFIG1" },
+ { 0x208, "GPUREG_ATTRIBBUFFER1_CONFIG2" },
+ { 0x209, "GPUREG_ATTRIBBUFFER2_OFFSET" },
+ { 0x20A, "GPUREG_ATTRIBBUFFER2_CONFIG1" },
+ { 0x20B, "GPUREG_ATTRIBBUFFER2_CONFIG2" },
+ { 0x20C, "GPUREG_ATTRIBBUFFER3_OFFSET" },
+ { 0x20D, "GPUREG_ATTRIBBUFFER3_CONFIG1" },
+ { 0x20E, "GPUREG_ATTRIBBUFFER3_CONFIG2" },
+ { 0x20F, "GPUREG_ATTRIBBUFFER4_OFFSET" },
+ { 0x210, "GPUREG_ATTRIBBUFFER4_CONFIG1" },
+ { 0x211, "GPUREG_ATTRIBBUFFER4_CONFIG2" },
+ { 0x212, "GPUREG_ATTRIBBUFFER5_OFFSET" },
+ { 0x213, "GPUREG_ATTRIBBUFFER5_CONFIG1" },
+ { 0x214, "GPUREG_ATTRIBBUFFER5_CONFIG2" },
+ { 0x215, "GPUREG_ATTRIBBUFFER6_OFFSET" },
+ { 0x216, "GPUREG_ATTRIBBUFFER6_CONFIG1" },
+ { 0x217, "GPUREG_ATTRIBBUFFER6_CONFIG2" },
+ { 0x218, "GPUREG_ATTRIBBUFFER7_OFFSET" },
+ { 0x219, "GPUREG_ATTRIBBUFFER7_CONFIG1" },
+ { 0x21A, "GPUREG_ATTRIBBUFFER7_CONFIG2" },
+ { 0x21B, "GPUREG_ATTRIBBUFFER8_OFFSET" },
+ { 0x21C, "GPUREG_ATTRIBBUFFER8_CONFIG1" },
+ { 0x21D, "GPUREG_ATTRIBBUFFER8_CONFIG2" },
+ { 0x21E, "GPUREG_ATTRIBBUFFER9_OFFSET" },
+ { 0x21F, "GPUREG_ATTRIBBUFFER9_CONFIG1" },
+ { 0x220, "GPUREG_ATTRIBBUFFER9_CONFIG2" },
+ { 0x221, "GPUREG_ATTRIBBUFFER10_OFFSET" },
+ { 0x222, "GPUREG_ATTRIBBUFFER10_CONFIG1" },
+ { 0x223, "GPUREG_ATTRIBBUFFER10_CONFIG2" },
+ { 0x224, "GPUREG_ATTRIBBUFFER11_OFFSET" },
+ { 0x225, "GPUREG_ATTRIBBUFFER11_CONFIG1" },
+ { 0x226, "GPUREG_ATTRIBBUFFER11_CONFIG2" },
+ { 0x227, "GPUREG_INDEXBUFFER_CONFIG" },
+ { 0x228, "GPUREG_NUMVERTICES" },
+ { 0x229, "GPUREG_GEOSTAGE_CONFIG" },
+ { 0x22A, "GPUREG_VERTEX_OFFSET" },
+
+ { 0x22D, "GPUREG_POST_VERTEX_CACHE_NUM" },
+ { 0x22E, "GPUREG_DRAWARRAYS" },
+ { 0x22F, "GPUREG_DRAWELEMENTS" },
+
+ { 0x231, "GPUREG_VTX_FUNC" },
+ { 0x232, "GPUREG_FIXEDATTRIB_INDEX" },
+ { 0x233, "GPUREG_FIXEDATTRIB_DATA0" },
+ { 0x234, "GPUREG_FIXEDATTRIB_DATA1" },
+ { 0x235, "GPUREG_FIXEDATTRIB_DATA2" },
+
+ { 0x238, "GPUREG_CMDBUF_SIZE0" },
+ { 0x239, "GPUREG_CMDBUF_SIZE1" },
+ { 0x23A, "GPUREG_CMDBUF_ADDR0" },
+ { 0x23B, "GPUREG_CMDBUF_ADDR1" },
+ { 0x23C, "GPUREG_CMDBUF_JUMP0" },
+ { 0x23D, "GPUREG_CMDBUF_JUMP1" },
+
+ { 0x242, "GPUREG_VSH_NUM_ATTR" },
+
+ { 0x244, "GPUREG_VSH_COM_MODE" },
+ { 0x245, "GPUREG_START_DRAW_FUNC0" },
+
+ { 0x24A, "GPUREG_VSH_OUTMAP_TOTAL1" },
+
+ { 0x251, "GPUREG_VSH_OUTMAP_TOTAL2" },
+ { 0x252, "GPUREG_GSH_MISC0" },
+ { 0x253, "GPUREG_GEOSTAGE_CONFIG2" },
+ { 0x254, "GPUREG_GSH_MISC1" },
+
+ { 0x25E, "GPUREG_PRIMITIVE_CONFIG" },
+ { 0x25F, "GPUREG_RESTART_PRIMITIVE" },
+
+ { 0x280, "GPUREG_GSH_BOOLUNIFORM" },
+ { 0x281, "GPUREG_GSH_INTUNIFORM_I0" },
+ { 0x282, "GPUREG_GSH_INTUNIFORM_I1" },
+ { 0x283, "GPUREG_GSH_INTUNIFORM_I2" },
+ { 0x284, "GPUREG_GSH_INTUNIFORM_I3" },
+
+ { 0x289, "GPUREG_GSH_INPUTBUFFER_CONFIG" },
+ { 0x28A, "GPUREG_GSH_ENTRYPOINT" },
+ { 0x28B, "GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW" },
+ { 0x28C, "GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH" },
+ { 0x28D, "GPUREG_GSH_OUTMAP_MASK" },
+
+ { 0x28F, "GPUREG_GSH_CODETRANSFER_END" },
+ { 0x290, "GPUREG_GSH_FLOATUNIFORM_INDEX" },
+ { 0x291, "GPUREG_GSH_FLOATUNIFORM_DATA0" },
+ { 0x292, "GPUREG_GSH_FLOATUNIFORM_DATA1" },
+ { 0x293, "GPUREG_GSH_FLOATUNIFORM_DATA2" },
+ { 0x294, "GPUREG_GSH_FLOATUNIFORM_DATA3" },
+ { 0x295, "GPUREG_GSH_FLOATUNIFORM_DATA4" },
+ { 0x296, "GPUREG_GSH_FLOATUNIFORM_DATA5" },
+ { 0x297, "GPUREG_GSH_FLOATUNIFORM_DATA6" },
+ { 0x298, "GPUREG_GSH_FLOATUNIFORM_DATA7" },
+
+ { 0x29B, "GPUREG_GSH_CODETRANSFER_INDEX" },
+ { 0x29C, "GPUREG_GSH_CODETRANSFER_DATA0" },
+ { 0x29D, "GPUREG_GSH_CODETRANSFER_DATA1" },
+ { 0x29E, "GPUREG_GSH_CODETRANSFER_DATA2" },
+ { 0x29F, "GPUREG_GSH_CODETRANSFER_DATA3" },
+ { 0x2A0, "GPUREG_GSH_CODETRANSFER_DATA4" },
+ { 0x2A1, "GPUREG_GSH_CODETRANSFER_DATA5" },
+ { 0x2A2, "GPUREG_GSH_CODETRANSFER_DATA6" },
+ { 0x2A3, "GPUREG_GSH_CODETRANSFER_DATA7" },
+
+ { 0x2A5, "GPUREG_GSH_OPDESCS_INDEX" },
+ { 0x2A6, "GPUREG_GSH_OPDESCS_DATA0" },
+ { 0x2A7, "GPUREG_GSH_OPDESCS_DATA1" },
+ { 0x2A8, "GPUREG_GSH_OPDESCS_DATA2" },
+ { 0x2A9, "GPUREG_GSH_OPDESCS_DATA3" },
+ { 0x2AA, "GPUREG_GSH_OPDESCS_DATA4" },
+ { 0x2AB, "GPUREG_GSH_OPDESCS_DATA5" },
+ { 0x2AC, "GPUREG_GSH_OPDESCS_DATA6" },
+ { 0x2AD, "GPUREG_GSH_OPDESCS_DATA7" },
+
+ { 0x2B0, "GPUREG_VSH_BOOLUNIFORM" },
+ { 0x2B1, "GPUREG_VSH_INTUNIFORM_I0" },
+ { 0x2B2, "GPUREG_VSH_INTUNIFORM_I1" },
+ { 0x2B3, "GPUREG_VSH_INTUNIFORM_I2" },
+ { 0x2B4, "GPUREG_VSH_INTUNIFORM_I3" },
+
+ { 0x2B9, "GPUREG_VSH_INPUTBUFFER_CONFIG" },
+ { 0x2BA, "GPUREG_VSH_ENTRYPOINT" },
+ { 0x2BB, "GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW" },
+ { 0x2BC, "GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH" },
+ { 0x2BD, "GPUREG_VSH_OUTMAP_MASK" },
+
+ { 0x2BF, "GPUREG_VSH_CODETRANSFER_END" },
+ { 0x2C0, "GPUREG_VSH_FLOATUNIFORM_INDEX" },
+ { 0x2C1, "GPUREG_VSH_FLOATUNIFORM_DATA0" },
+ { 0x2C2, "GPUREG_VSH_FLOATUNIFORM_DATA1" },
+ { 0x2C3, "GPUREG_VSH_FLOATUNIFORM_DATA2" },
+ { 0x2C4, "GPUREG_VSH_FLOATUNIFORM_DATA3" },
+ { 0x2C5, "GPUREG_VSH_FLOATUNIFORM_DATA4" },
+ { 0x2C6, "GPUREG_VSH_FLOATUNIFORM_DATA5" },
+ { 0x2C7, "GPUREG_VSH_FLOATUNIFORM_DATA6" },
+ { 0x2C8, "GPUREG_VSH_FLOATUNIFORM_DATA7" },
+
+ { 0x2CB, "GPUREG_VSH_CODETRANSFER_INDEX" },
+ { 0x2CC, "GPUREG_VSH_CODETRANSFER_DATA0" },
+ { 0x2CD, "GPUREG_VSH_CODETRANSFER_DATA1" },
+ { 0x2CE, "GPUREG_VSH_CODETRANSFER_DATA2" },
+ { 0x2CF, "GPUREG_VSH_CODETRANSFER_DATA3" },
+ { 0x2D0, "GPUREG_VSH_CODETRANSFER_DATA4" },
+ { 0x2D1, "GPUREG_VSH_CODETRANSFER_DATA5" },
+ { 0x2D2, "GPUREG_VSH_CODETRANSFER_DATA6" },
+ { 0x2D3, "GPUREG_VSH_CODETRANSFER_DATA7" },
+
+ { 0x2D5, "GPUREG_VSH_OPDESCS_INDEX" },
+ { 0x2D6, "GPUREG_VSH_OPDESCS_DATA0" },
+ { 0x2D7, "GPUREG_VSH_OPDESCS_DATA1" },
+ { 0x2D8, "GPUREG_VSH_OPDESCS_DATA2" },
+ { 0x2D9, "GPUREG_VSH_OPDESCS_DATA3" },
+ { 0x2DA, "GPUREG_VSH_OPDESCS_DATA4" },
+ { 0x2DB, "GPUREG_VSH_OPDESCS_DATA5" },
+ { 0x2DC, "GPUREG_VSH_OPDESCS_DATA6" },
+ { 0x2DD, "GPUREG_VSH_OPDESCS_DATA7" },
+};
+
std::string Regs::GetCommandName(int index) {
- static std::unordered_map<u32, std::string> map;
+ static std::unordered_map<u32, const char*> map;
if (map.empty()) {
- #define ADD_FIELD(name) \
- map.insert({static_cast<u32>(PICA_REG_INDEX(name)), #name}); \
- /* TODO: change to Regs::name when VS2015 and other compilers support it */ \
- for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \
- map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \
-
- ADD_FIELD(trigger_irq);
- ADD_FIELD(cull_mode);
- ADD_FIELD(viewport_size_x);
- ADD_FIELD(viewport_size_y);
- ADD_FIELD(viewport_depth_range);
- ADD_FIELD(viewport_depth_far_plane);
- ADD_FIELD(viewport_corner);
- ADD_FIELD(texture0_enable);
- ADD_FIELD(texture0);
- ADD_FIELD(texture0_format);
- ADD_FIELD(texture1);
- ADD_FIELD(texture1_format);
- ADD_FIELD(texture2);
- ADD_FIELD(texture2_format);
- ADD_FIELD(tev_stage0);
- ADD_FIELD(tev_stage1);
- ADD_FIELD(tev_stage2);
- ADD_FIELD(tev_stage3);
- ADD_FIELD(tev_combiner_buffer_input);
- ADD_FIELD(tev_stage4);
- ADD_FIELD(tev_stage5);
- ADD_FIELD(tev_combiner_buffer_color);
- ADD_FIELD(output_merger);
- ADD_FIELD(framebuffer);
- ADD_FIELD(vertex_attributes);
- ADD_FIELD(index_array);
- ADD_FIELD(num_vertices);
- ADD_FIELD(vertex_offset);
- ADD_FIELD(trigger_draw);
- ADD_FIELD(trigger_draw_indexed);
- ADD_FIELD(vs_default_attributes_setup);
- ADD_FIELD(command_buffer);
- ADD_FIELD(triangle_topology);
- ADD_FIELD(restart_primitive);
- ADD_FIELD(gs.bool_uniforms);
- ADD_FIELD(gs.int_uniforms);
- ADD_FIELD(gs.main_offset);
- ADD_FIELD(gs.input_register_map);
- ADD_FIELD(gs.uniform_setup);
- ADD_FIELD(gs.program);
- ADD_FIELD(gs.swizzle_patterns);
- ADD_FIELD(vs.bool_uniforms);
- ADD_FIELD(vs.int_uniforms);
- ADD_FIELD(vs.main_offset);
- ADD_FIELD(vs.input_register_map);
- ADD_FIELD(vs.uniform_setup);
- ADD_FIELD(vs.program);
- ADD_FIELD(vs.swizzle_patterns);
-
-#undef ADD_FIELD
+ map.insert(begin(register_names), end(register_names));
}
// Return empty string if no match is found
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 2f1b2dec4..2e0c33201 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -16,6 +16,8 @@
#include "common/vector_math.h"
#include "common/logging/log.h"
+#include "pica_types.h"
+
namespace Pica {
// Returns index corresponding to the Regs member labeled by field_name
@@ -239,7 +241,8 @@ struct Regs {
TextureConfig texture0;
INSERT_PADDING_WORDS(0x8);
BitField<0, 4, TextureFormat> texture0_format;
- INSERT_PADDING_WORDS(0x2);
+ BitField<0, 1, u32> fragment_lighting_enable;
+ INSERT_PADDING_WORDS(0x1);
TextureConfig texture1;
BitField<0, 4, TextureFormat> texture1_format;
INSERT_PADDING_WORDS(0x2);
@@ -641,7 +644,268 @@ struct Regs {
}
}
- INSERT_PADDING_WORDS(0xe0);
+ INSERT_PADDING_WORDS(0x20);
+
+ enum class LightingSampler {
+ Distribution0 = 0,
+ Distribution1 = 1,
+ Fresnel = 3,
+ ReflectBlue = 4,
+ ReflectGreen = 5,
+ ReflectRed = 6,
+ SpotlightAttenuation = 8,
+ DistanceAttenuation = 16,
+ };
+
+ /**
+ * Pica fragment lighting supports using different LUTs for each lighting component:
+ * Reflectance R, G, and B channels, distribution function for specular components 0 and 1,
+ * fresnel factor, and spotlight attenuation. Furthermore, which LUTs are used for each channel
+ * (or whether a channel is enabled at all) is specified by various pre-defined lighting
+ * configurations. With configurations that require more LUTs, more cycles are required on HW to
+ * perform lighting computations.
+ */
+ enum class LightingConfig {
+ Config0 = 0, ///< Reflect Red, Distribution 0, Spotlight
+ Config1 = 1, ///< Reflect Red, Fresnel, Spotlight
+ Config2 = 2, ///< Reflect Red, Distribution 0/1
+ Config3 = 3, ///< Distribution 0/1, Fresnel
+ Config4 = 4, ///< Reflect Red/Green/Blue, Distribution 0/1, Spotlight
+ Config5 = 5, ///< Reflect Red/Green/Blue, Distribution 0, Fresnel, Spotlight
+ Config6 = 6, ///< Reflect Red, Distribution 0/1, Fresnel, Spotlight
+ Config7 = 8, ///< Reflect Red/Green/Blue, Distribution 0/1, Fresnel, Spotlight
+ ///< NOTE: '8' is intentional, '7' does not appear to be a valid configuration
+ };
+
+ /// Selects which lighting components are affected by fresnel
+ enum class LightingFresnelSelector {
+ None = 0, ///< Fresnel is disabled
+ PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel
+ SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel
+ Both = PrimaryAlpha | SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel
+ };
+
+ /// Factor used to scale the output of a lighting LUT
+ enum class LightingScale {
+ Scale1 = 0, ///< Scale is 1x
+ Scale2 = 1, ///< Scale is 2x
+ Scale4 = 2, ///< Scale is 4x
+ Scale8 = 3, ///< Scale is 8x
+ Scale1_4 = 6, ///< Scale is 0.25x
+ Scale1_2 = 7, ///< Scale is 0.5x
+ };
+
+ enum class LightingLutInput {
+ NH = 0, // Cosine of the angle between the normal and half-angle vectors
+ VH = 1, // Cosine of the angle between the view and half-angle vectors
+ NV = 2, // Cosine of the angle between the normal and the view vector
+ LN = 3, // Cosine of the angle between the light and the normal vectors
+ };
+
+ enum class LightingBumpMode : u32 {
+ None = 0,
+ NormalMap = 1,
+ TangentMap = 2,
+ };
+
+ union LightColor {
+ BitField< 0, 10, u32> b;
+ BitField<10, 10, u32> g;
+ BitField<20, 10, u32> r;
+
+ Math::Vec3f ToVec3f() const {
+ // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color component
+ return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f);
+ }
+ };
+
+ /// Returns true if the specified lighting sampler is supported by the current Pica lighting configuration
+ static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) {
+ switch (sampler) {
+ case LightingSampler::Distribution0:
+ return (config != LightingConfig::Config1);
+
+ case LightingSampler::Distribution1:
+ return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && (config != LightingConfig::Config5);
+
+ case LightingSampler::Fresnel:
+ return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && (config != LightingConfig::Config4);
+
+ case LightingSampler::ReflectRed:
+ return (config != LightingConfig::Config3);
+
+ case LightingSampler::ReflectGreen:
+ case LightingSampler::ReflectBlue:
+ return (config == LightingConfig::Config4) || (config == LightingConfig::Config5) || (config == LightingConfig::Config7);
+ }
+ return false;
+ }
+
+ struct {
+ struct LightSrc {
+ LightColor specular_0; // material.specular_0 * light.specular_0
+ LightColor specular_1; // material.specular_1 * light.specular_1
+ LightColor diffuse; // material.diffuse * light.diffuse
+ LightColor ambient; // material.ambient * light.ambient
+
+ struct {
+ // Encoded as 16-bit floating point
+ union {
+ BitField< 0, 16, u32> x;
+ BitField<16, 16, u32> y;
+ };
+ union {
+ BitField< 0, 16, u32> z;
+ };
+
+ INSERT_PADDING_WORDS(0x3);
+
+ union {
+ BitField<0, 1, u32> directional;
+ BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0
+ };
+ };
+
+ BitField<0, 20, u32> dist_atten_bias;
+ BitField<0, 20, u32> dist_atten_scale;
+
+ INSERT_PADDING_WORDS(0x4);
+ };
+ static_assert(sizeof(LightSrc) == 0x10 * sizeof(u32), "LightSrc structure must be 0x10 words");
+
+ LightSrc light[8];
+ LightColor global_ambient; // Emission + (material.ambient * lighting.ambient)
+ INSERT_PADDING_WORDS(0x1);
+ BitField<0, 3, u32> num_lights; // Number of enabled lights - 1
+
+ union {
+ BitField< 2, 2, LightingFresnelSelector> fresnel_selector;
+ BitField< 4, 4, LightingConfig> config;
+ BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2
+ BitField<27, 1, u32> clamp_highlights;
+ BitField<28, 2, LightingBumpMode> bump_mode;
+ BitField<30, 1, u32> disable_bump_renorm;
+ };
+
+ union {
+ BitField<16, 1, u32> disable_lut_d0;
+ BitField<17, 1, u32> disable_lut_d1;
+ BitField<19, 1, u32> disable_lut_fr;
+ BitField<20, 1, u32> disable_lut_rr;
+ BitField<21, 1, u32> disable_lut_rg;
+ BitField<22, 1, u32> disable_lut_rb;
+
+ // Each bit specifies whether distance attenuation should be applied for the
+ // corresponding light
+
+ BitField<24, 1, u32> disable_dist_atten_light_0;
+ BitField<25, 1, u32> disable_dist_atten_light_1;
+ BitField<26, 1, u32> disable_dist_atten_light_2;
+ BitField<27, 1, u32> disable_dist_atten_light_3;
+ BitField<28, 1, u32> disable_dist_atten_light_4;
+ BitField<29, 1, u32> disable_dist_atten_light_5;
+ BitField<30, 1, u32> disable_dist_atten_light_6;
+ BitField<31, 1, u32> disable_dist_atten_light_7;
+ };
+
+ bool IsDistAttenDisabled(unsigned index) const {
+ const unsigned disable[] = { disable_dist_atten_light_0, disable_dist_atten_light_1,
+ disable_dist_atten_light_2, disable_dist_atten_light_3,
+ disable_dist_atten_light_4, disable_dist_atten_light_5,
+ disable_dist_atten_light_6, disable_dist_atten_light_7 };
+ return disable[index] != 0;
+ }
+
+ union {
+ BitField<0, 8, u32> index; ///< Index at which to set data in the LUT
+ BitField<8, 5, u32> type; ///< Type of LUT for which to set data
+ } lut_config;
+
+ BitField<0, 1, u32> disable;
+ INSERT_PADDING_WORDS(0x1);
+
+ // When data is written to any of these registers, it gets written to the lookup table of
+ // the selected type at the selected index, specified above in the `lut_config` register.
+ // With each write, `lut_config.index` is incremented. It does not matter which of these
+ // registers is written to, the behavior will be the same.
+ u32 lut_data[8];
+
+ // These are used to specify if absolute (abs) value should be used for each LUT index. When
+ // abs mode is disabled, LUT indexes are in the range of (-1.0, 1.0). Otherwise, they are in
+ // the range of (0.0, 1.0).
+ union {
+ BitField< 1, 1, u32> disable_d0;
+ BitField< 5, 1, u32> disable_d1;
+ BitField< 9, 1, u32> disable_sp;
+ BitField<13, 1, u32> disable_fr;
+ BitField<17, 1, u32> disable_rb;
+ BitField<21, 1, u32> disable_rg;
+ BitField<25, 1, u32> disable_rr;
+ } abs_lut_input;
+
+ union {
+ BitField< 0, 3, LightingLutInput> d0;
+ BitField< 4, 3, LightingLutInput> d1;
+ BitField< 8, 3, LightingLutInput> sp;
+ BitField<12, 3, LightingLutInput> fr;
+ BitField<16, 3, LightingLutInput> rb;
+ BitField<20, 3, LightingLutInput> rg;
+ BitField<24, 3, LightingLutInput> rr;
+ } lut_input;
+
+ union {
+ BitField< 0, 3, LightingScale> d0;
+ BitField< 4, 3, LightingScale> d1;
+ BitField< 8, 3, LightingScale> sp;
+ BitField<12, 3, LightingScale> fr;
+ BitField<16, 3, LightingScale> rb;
+ BitField<20, 3, LightingScale> rg;
+ BitField<24, 3, LightingScale> rr;
+
+ static float GetScale(LightingScale scale) {
+ switch (scale) {
+ case LightingScale::Scale1:
+ return 1.0f;
+ case LightingScale::Scale2:
+ return 2.0f;
+ case LightingScale::Scale4:
+ return 4.0f;
+ case LightingScale::Scale8:
+ return 8.0f;
+ case LightingScale::Scale1_4:
+ return 0.25f;
+ case LightingScale::Scale1_2:
+ return 0.5f;
+ }
+ return 0.0f;
+ }
+ } lut_scale;
+
+ INSERT_PADDING_WORDS(0x6);
+
+ union {
+ // There are 8 light enable "slots", corresponding to the total number of lights
+ // supported by Pica. For N enabled lights (specified by register 0x1c2, or 'src_num'
+ // above), the first N slots below will be set to integers within the range of 0-7,
+ // corresponding to the actual light that is enabled for each slot.
+
+ BitField< 0, 3, u32> slot_0;
+ BitField< 4, 3, u32> slot_1;
+ BitField< 8, 3, u32> slot_2;
+ BitField<12, 3, u32> slot_3;
+ BitField<16, 3, u32> slot_4;
+ BitField<20, 3, u32> slot_5;
+ BitField<24, 3, u32> slot_6;
+ BitField<28, 3, u32> slot_7;
+
+ unsigned GetNum(unsigned index) const {
+ const unsigned enable_slots[] = { slot_0, slot_1, slot_2, slot_3, slot_4, slot_5, slot_6, slot_7 };
+ return enable_slots[index];
+ }
+ } light_enable;
+ } lighting;
+
+ INSERT_PADDING_WORDS(0x26);
enum class VertexAttributeFormat : u64 {
BYTE = 0,
@@ -825,7 +1089,16 @@ struct Regs {
}
} command_buffer;
- INSERT_PADDING_WORDS(0x20);
+ INSERT_PADDING_WORDS(0x07);
+
+ enum class GPUMode : u32 {
+ Drawing = 0,
+ Configuring = 1
+ };
+
+ GPUMode gpu_mode;
+
+ INSERT_PADDING_WORDS(0x18);
enum class TriangleTopology : u32 {
List = 0,
@@ -990,6 +1263,7 @@ ASSERT_REG_POSITION(viewport_corner, 0x68);
ASSERT_REG_POSITION(texture0_enable, 0x80);
ASSERT_REG_POSITION(texture0, 0x81);
ASSERT_REG_POSITION(texture0_format, 0x8e);
+ASSERT_REG_POSITION(fragment_lighting_enable, 0x8f);
ASSERT_REG_POSITION(texture1, 0x91);
ASSERT_REG_POSITION(texture1_format, 0x96);
ASSERT_REG_POSITION(texture2, 0x99);
@@ -1004,6 +1278,7 @@ ASSERT_REG_POSITION(tev_stage5, 0xf8);
ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd);
ASSERT_REG_POSITION(output_merger, 0x100);
ASSERT_REG_POSITION(framebuffer, 0x110);
+ASSERT_REG_POSITION(lighting, 0x140);
ASSERT_REG_POSITION(vertex_attributes, 0x200);
ASSERT_REG_POSITION(index_array, 0x227);
ASSERT_REG_POSITION(num_vertices, 0x228);
@@ -1012,6 +1287,7 @@ ASSERT_REG_POSITION(trigger_draw, 0x22e);
ASSERT_REG_POSITION(trigger_draw_indexed, 0x22f);
ASSERT_REG_POSITION(vs_default_attributes_setup, 0x232);
ASSERT_REG_POSITION(command_buffer, 0x238);
+ASSERT_REG_POSITION(gpu_mode, 0x245);
ASSERT_REG_POSITION(triangle_topology, 0x25e);
ASSERT_REG_POSITION(restart_primitive, 0x25f);
ASSERT_REG_POSITION(gs, 0x280);
@@ -1026,157 +1302,10 @@ static_assert(sizeof(Regs::ShaderConfig) == 0x30 * sizeof(u32), "ShaderConfig st
static_assert(sizeof(Regs) <= 0x300 * sizeof(u32), "Register set structure larger than it should be");
static_assert(sizeof(Regs) >= 0x300 * sizeof(u32), "Register set structure smaller than it should be");
-struct float24 {
- static float24 FromFloat32(float val) {
- float24 ret;
- ret.value = val;
- return ret;
- }
-
- // 16 bit mantissa, 7 bit exponent, 1 bit sign
- // TODO: No idea if this works as intended
- static float24 FromRawFloat24(u32 hex) {
- float24 ret;
- if ((hex & 0xFFFFFF) == 0) {
- ret.value = 0;
- } else {
- u32 mantissa = hex & 0xFFFF;
- u32 exponent = (hex >> 16) & 0x7F;
- u32 sign = hex >> 23;
- ret.value = std::pow(2.0f, (float)exponent-63.0f) * (1.0f + mantissa * std::pow(2.0f, -16.f));
- if (sign)
- ret.value = -ret.value;
- }
- return ret;
- }
-
- static float24 Zero() {
- return FromFloat32(0.f);
- }
-
- // Not recommended for anything but logging
- float ToFloat32() const {
- return value;
- }
-
- float24 operator * (const float24& flt) const {
- if ((this->value == 0.f && !std::isnan(flt.value)) ||
- (flt.value == 0.f && !std::isnan(this->value)))
- // PICA gives 0 instead of NaN when multiplying by inf
- return Zero();
- return float24::FromFloat32(ToFloat32() * flt.ToFloat32());
- }
-
- float24 operator / (const float24& flt) const {
- return float24::FromFloat32(ToFloat32() / flt.ToFloat32());
- }
-
- float24 operator + (const float24& flt) const {
- return float24::FromFloat32(ToFloat32() + flt.ToFloat32());
- }
-
- float24 operator - (const float24& flt) const {
- return float24::FromFloat32(ToFloat32() - flt.ToFloat32());
- }
-
- float24& operator *= (const float24& flt) {
- if ((this->value == 0.f && !std::isnan(flt.value)) ||
- (flt.value == 0.f && !std::isnan(this->value)))
- // PICA gives 0 instead of NaN when multiplying by inf
- *this = Zero();
- else value *= flt.ToFloat32();
- return *this;
- }
-
- float24& operator /= (const float24& flt) {
- value /= flt.ToFloat32();
- return *this;
- }
-
- float24& operator += (const float24& flt) {
- value += flt.ToFloat32();
- return *this;
- }
-
- float24& operator -= (const float24& flt) {
- value -= flt.ToFloat32();
- return *this;
- }
-
- float24 operator - () const {
- return float24::FromFloat32(-ToFloat32());
- }
-
- bool operator < (const float24& flt) const {
- return ToFloat32() < flt.ToFloat32();
- }
-
- bool operator > (const float24& flt) const {
- return ToFloat32() > flt.ToFloat32();
- }
-
- bool operator >= (const float24& flt) const {
- return ToFloat32() >= flt.ToFloat32();
- }
-
- bool operator <= (const float24& flt) const {
- return ToFloat32() <= flt.ToFloat32();
- }
-
- bool operator == (const float24& flt) const {
- return ToFloat32() == flt.ToFloat32();
- }
-
- bool operator != (const float24& flt) const {
- return ToFloat32() != flt.ToFloat32();
- }
-
-private:
- // Stored as a regular float, merely for convenience
- // TODO: Perform proper arithmetic on this!
- float value;
-};
-static_assert(sizeof(float24) == sizeof(float), "Shader JIT assumes float24 is implemented as a 32-bit float");
-
-/// Struct used to describe current Pica state
-struct State {
- /// Pica registers
- Regs regs;
-
- /// Vertex shader memory
- struct ShaderSetup {
- struct {
- // The float uniforms are accessed by the shader JIT using SSE instructions, and are
- // therefore required to be 16-byte aligned.
- Math::Vec4<float24> MEMORY_ALIGNED16(f[96]);
-
- std::array<bool, 16> b;
- std::array<Math::Vec4<u8>, 4> i;
- } uniforms;
-
- Math::Vec4<float24> default_attributes[16];
-
- std::array<u32, 1024> program_code;
- std::array<u32, 1024> swizzle_data;
- };
-
- ShaderSetup vs;
- ShaderSetup gs;
-
- /// Current Pica command list
- struct {
- const u32* head_ptr;
- const u32* current_ptr;
- u32 length;
- } cmd_list;
-};
-
/// Initialize Pica state
void Init();
/// Shutdown Pica state
void Shutdown();
-extern State g_state; ///< Current Pica state
-
} // namespace
diff --git a/src/video_core/pica_state.h b/src/video_core/pica_state.h
new file mode 100644
index 000000000..c7616bc55
--- /dev/null
+++ b/src/video_core/pica_state.h
@@ -0,0 +1,60 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "video_core/pica.h"
+#include "video_core/primitive_assembly.h"
+#include "video_core/shader/shader.h"
+
+namespace Pica {
+
+/// Struct used to describe current Pica state
+struct State {
+ /// Pica registers
+ Regs regs;
+
+ Shader::ShaderSetup vs;
+ Shader::ShaderSetup gs;
+
+ struct {
+ union LutEntry {
+ // Used for raw access
+ u32 raw;
+
+ // LUT value, encoded as 12-bit fixed point, with 12 fraction bits
+ BitField< 0, 12, u32> value;
+
+ // Used by HW for efficient interpolation, Citra does not use these
+ BitField<12, 12, u32> difference;
+
+ float ToFloat() {
+ return static_cast<float>(value) / 4095.f;
+ }
+ };
+
+ std::array<std::array<LutEntry, 256>, 24> luts;
+ } lighting;
+
+ /// Current Pica command list
+ struct {
+ const u32* head_ptr;
+ const u32* current_ptr;
+ u32 length;
+ } cmd_list;
+
+ /// Struct used to describe immediate mode rendering state
+ struct ImmediateModeState {
+ Shader::InputVertex input;
+ // This is constructed with a dummy triangle topology
+ PrimitiveAssembler<Shader::OutputVertex> primitive_assembler;
+ int attribute_id = 0;
+
+ ImmediateModeState() : primitive_assembler(Regs::TriangleTopology::List) {}
+ } immediate;
+};
+
+extern State g_state; ///< Current Pica state
+
+} // namespace
diff --git a/src/video_core/pica_types.h b/src/video_core/pica_types.h
new file mode 100644
index 000000000..ecf45654b
--- /dev/null
+++ b/src/video_core/pica_types.h
@@ -0,0 +1,146 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cstring>
+
+#include "common/common_types.h"
+
+namespace Pica {
+
+/**
+ * Template class for converting arbitrary Pica float types to IEEE 754 32-bit single-precision
+ * floating point.
+ *
+ * When decoding, format is as follows:
+ * - The first `M` bits are the mantissa
+ * - The next `E` bits are the exponent
+ * - The last bit is the sign bit
+ *
+ * @todo Verify on HW if this conversion is sufficiently accurate.
+ */
+template<unsigned M, unsigned E>
+struct Float {
+public:
+ static Float<M, E> FromFloat32(float val) {
+ Float<M, E> ret;
+ ret.value = val;
+ return ret;
+ }
+
+ static Float<M, E> FromRaw(u32 hex) {
+ Float<M, E> res;
+
+ const int width = M + E + 1;
+ const int bias = 128 - (1 << (E - 1));
+ const int exponent = (hex >> M) & ((1 << E) - 1);
+ const unsigned mantissa = hex & ((1 << M) - 1);
+
+ if (hex & ((1 << (width - 1)) - 1))
+ hex = ((hex >> (E + M)) << 31) | (mantissa << (23 - M)) | ((exponent + bias) << 23);
+ else
+ hex = ((hex >> (E + M)) << 31);
+
+ std::memcpy(&res.value, &hex, sizeof(float));
+
+ return res;
+ }
+
+ static Float<M, E> Zero() {
+ return FromFloat32(0.f);
+ }
+
+ // Not recommended for anything but logging
+ float ToFloat32() const {
+ return value;
+ }
+
+ Float<M, E> operator * (const Float<M, E>& flt) const {
+ if ((this->value == 0.f && !std::isnan(flt.value)) ||
+ (flt.value == 0.f && !std::isnan(this->value)))
+ // PICA gives 0 instead of NaN when multiplying by inf
+ return Zero();
+ return Float<M, E>::FromFloat32(ToFloat32() * flt.ToFloat32());
+ }
+
+ Float<M, E> operator / (const Float<M, E>& flt) const {
+ return Float<M, E>::FromFloat32(ToFloat32() / flt.ToFloat32());
+ }
+
+ Float<M, E> operator + (const Float<M, E>& flt) const {
+ return Float<M, E>::FromFloat32(ToFloat32() + flt.ToFloat32());
+ }
+
+ Float<M, E> operator - (const Float<M, E>& flt) const {
+ return Float<M, E>::FromFloat32(ToFloat32() - flt.ToFloat32());
+ }
+
+ Float<M, E>& operator *= (const Float<M, E>& flt) {
+ if ((this->value == 0.f && !std::isnan(flt.value)) ||
+ (flt.value == 0.f && !std::isnan(this->value)))
+ // PICA gives 0 instead of NaN when multiplying by inf
+ *this = Zero();
+ else value *= flt.ToFloat32();
+ return *this;
+ }
+
+ Float<M, E>& operator /= (const Float<M, E>& flt) {
+ value /= flt.ToFloat32();
+ return *this;
+ }
+
+ Float<M, E>& operator += (const Float<M, E>& flt) {
+ value += flt.ToFloat32();
+ return *this;
+ }
+
+ Float<M, E>& operator -= (const Float<M, E>& flt) {
+ value -= flt.ToFloat32();
+ return *this;
+ }
+
+ Float<M, E> operator - () const {
+ return Float<M, E>::FromFloat32(-ToFloat32());
+ }
+
+ bool operator < (const Float<M, E>& flt) const {
+ return ToFloat32() < flt.ToFloat32();
+ }
+
+ bool operator > (const Float<M, E>& flt) const {
+ return ToFloat32() > flt.ToFloat32();
+ }
+
+ bool operator >= (const Float<M, E>& flt) const {
+ return ToFloat32() >= flt.ToFloat32();
+ }
+
+ bool operator <= (const Float<M, E>& flt) const {
+ return ToFloat32() <= flt.ToFloat32();
+ }
+
+ bool operator == (const Float<M, E>& flt) const {
+ return ToFloat32() == flt.ToFloat32();
+ }
+
+ bool operator != (const Float<M, E>& flt) const {
+ return ToFloat32() != flt.ToFloat32();
+ }
+
+private:
+ static const unsigned MASK = (1 << (M + E + 1)) - 1;
+ static const unsigned MANTISSA_MASK = (1 << M) - 1;
+ static const unsigned EXPONENT_MASK = (1 << E) - 1;
+
+ // Stored as a regular float, merely for convenience
+ // TODO: Perform proper arithmetic on this!
+ float value;
+};
+
+using float24 = Float<16, 7>;
+using float20 = Float<12, 7>;
+using float16 = Float<10, 5>;
+
+} // namespace Pica
diff --git a/src/video_core/primitive_assembly.cpp b/src/video_core/primitive_assembly.cpp
index 44a8dbfe9..0061690f1 100644
--- a/src/video_core/primitive_assembly.cpp
+++ b/src/video_core/primitive_assembly.cpp
@@ -39,13 +39,12 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(VertexType& vtx, TriangleHandl
buffer[buffer_index] = vtx;
- if (topology == Regs::TriangleTopology::Strip) {
- strip_ready |= (buffer_index == 1);
+ strip_ready |= (buffer_index == 1);
+
+ if (topology == Regs::TriangleTopology::Strip)
buffer_index = !buffer_index;
- } else if (topology == Regs::TriangleTopology::Fan) {
+ else if (topology == Regs::TriangleTopology::Fan)
buffer_index = 1;
- strip_ready = true;
- }
break;
default:
@@ -54,6 +53,18 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(VertexType& vtx, TriangleHandl
}
}
+template<typename VertexType>
+void PrimitiveAssembler<VertexType>::Reset() {
+ buffer_index = 0;
+ strip_ready = false;
+}
+
+template<typename VertexType>
+void PrimitiveAssembler<VertexType>::Reconfigure(Regs::TriangleTopology topology) {
+ Reset();
+ this->topology = topology;
+}
+
// explicitly instantiate use cases
template
struct PrimitiveAssembler<Shader::OutputVertex>;
diff --git a/src/video_core/primitive_assembly.h b/src/video_core/primitive_assembly.h
index 52d0ec8ff..cc6e5fde5 100644
--- a/src/video_core/primitive_assembly.h
+++ b/src/video_core/primitive_assembly.h
@@ -30,6 +30,16 @@ struct PrimitiveAssembler {
*/
void SubmitVertex(VertexType& vtx, TriangleHandler triangle_handler);
+ /**
+ * Resets the internal state of the PrimitiveAssembler.
+ */
+ void Reset();
+
+ /**
+ * Reconfigures the PrimitiveAssembler to use a different triangle topology.
+ */
+ void Reconfigure(Regs::TriangleTopology topology);
+
private:
Regs::TriangleTopology topology;
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index ecfdbc9e8..fd02aa652 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -15,6 +15,7 @@
#include "core/hw/gpu.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/rasterizer.h"
#include "video_core/utils.h"
#include "video_core/debug_utils/debug_utils.h"
@@ -857,12 +858,12 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
}
}
- // TODO: Does depth indeed only get written even if depth testing is enabled?
+ unsigned num_bits = Regs::DepthBitsPerPixel(regs.framebuffer.depth_format);
+ u32 z = (u32)((v0.screenpos[2].ToFloat32() * w0 +
+ v1.screenpos[2].ToFloat32() * w1 +
+ v2.screenpos[2].ToFloat32() * w2) * ((1 << num_bits) - 1) / wsum);
+
if (output_merger.depth_test_enable) {
- unsigned num_bits = Regs::DepthBitsPerPixel(regs.framebuffer.depth_format);
- u32 z = (u32)((v0.screenpos[2].ToFloat32() * w0 +
- v1.screenpos[2].ToFloat32() * w1 +
- v2.screenpos[2].ToFloat32() * w2) * ((1 << num_bits) - 1) / wsum);
u32 ref_z = GetDepth(x >> 4, y >> 4);
bool pass = false;
@@ -906,11 +907,11 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
UpdateStencil(stencil_test.action_depth_fail);
continue;
}
-
- if (output_merger.depth_write_enable)
- SetDepth(x >> 4, y >> 4, z);
}
+ if (output_merger.depth_write_enable)
+ SetDepth(x >> 4, y >> 4, z);
+
// The stencil depth_pass action is executed even if depth testing is disabled
if (stencil_action_enable)
UpdateStencil(stencil_test.action_depth_pass);
diff --git a/src/video_core/hwrasterizer_base.h b/src/video_core/rasterizer_interface.h
index 54b8892fb..008c5827b 100644
--- a/src/video_core/hwrasterizer_base.h
+++ b/src/video_core/rasterizer_interface.h
@@ -12,10 +12,11 @@ struct OutputVertex;
}
}
-class HWRasterizer {
+namespace VideoCore {
+
+class RasterizerInterface {
public:
- virtual ~HWRasterizer() {
- }
+ virtual ~RasterizerInterface() {}
/// Initialize API-specific GPU objects
virtual void InitObjects() = 0;
@@ -32,14 +33,16 @@ public:
virtual void DrawTriangles() = 0;
/// Commit the rasterizer's framebuffer contents immediately to the current 3DS memory framebuffer
- virtual void CommitFramebuffer() = 0;
+ virtual void FlushFramebuffer() = 0;
/// Notify rasterizer that the specified PICA register has been changed
virtual void NotifyPicaRegisterChanged(u32 id) = 0;
- /// Notify rasterizer that the specified 3DS memory region will be read from after this notification
- virtual void NotifyPreRead(PAddr addr, u32 size) = 0;
+ /// Notify rasterizer that any caches of the specified region should be flushed to 3DS memory.
+ virtual void FlushRegion(PAddr addr, u32 size) = 0;
- /// Notify rasterizer that a 3DS memory region has been changed
- virtual void NotifyFlush(PAddr addr, u32 size) = 0;
+ /// Notify rasterizer that any caches of the specified region should be discraded and reloaded from 3DS memory.
+ virtual void InvalidateRegion(PAddr addr, u32 size) = 0;
};
+
+}
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
new file mode 100644
index 000000000..6467ff723
--- /dev/null
+++ b/src/video_core/renderer_base.cpp
@@ -0,0 +1,29 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/make_unique.h"
+
+#include "core/settings.h"
+
+#include "video_core/renderer_base.h"
+#include "video_core/video_core.h"
+#include "video_core/swrasterizer.h"
+#include "video_core/renderer_opengl/gl_rasterizer.h"
+
+void RendererBase::RefreshRasterizerSetting() {
+ bool hw_renderer_enabled = VideoCore::g_hw_renderer_enabled;
+ if (rasterizer == nullptr || opengl_rasterizer_active != hw_renderer_enabled) {
+ opengl_rasterizer_active = hw_renderer_enabled;
+
+ if (hw_renderer_enabled) {
+ rasterizer = Common::make_unique<RasterizerOpenGL>();
+ } else {
+ rasterizer = Common::make_unique<VideoCore::SWRasterizer>();
+ }
+ rasterizer->InitObjects();
+ rasterizer->Reset();
+ }
+}
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 6587bcf27..f68091cc8 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -8,7 +8,7 @@
#include "common/common_types.h"
-#include "video_core/hwrasterizer_base.h"
+#include "video_core/rasterizer_interface.h"
class EmuWindow;
@@ -22,9 +22,6 @@ public:
kFramebuffer_Texture
};
- RendererBase() : m_current_fps(0), m_current_frame(0) {
- }
-
virtual ~RendererBase() {
}
@@ -38,7 +35,7 @@ public:
virtual void SetWindow(EmuWindow* window) = 0;
/// Initialize the renderer
- virtual void Init() = 0;
+ virtual bool Init() = 0;
/// Shutdown the renderer
virtual void ShutDown() = 0;
@@ -46,18 +43,25 @@ public:
// Getter/setter functions:
// ------------------------
- f32 GetCurrentframe() const {
+ f32 GetCurrentFPS() const {
return m_current_fps;
}
- int current_frame() const {
+ int GetCurrentFrame() const {
return m_current_frame;
}
- std::unique_ptr<HWRasterizer> hw_rasterizer;
+ VideoCore::RasterizerInterface* Rasterizer() const {
+ return rasterizer.get();
+ }
+
+ void RefreshRasterizerSetting();
protected:
- f32 m_current_fps; ///< Current framerate, should be set by the renderer
- int m_current_frame; ///< Current frame, should be set by the renderer
+ std::unique_ptr<VideoCore::RasterizerInterface> rasterizer;
+ f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
+ int m_current_frame = 0; ///< Current frame, should be set by the renderer
+private:
+ bool opengl_rasterizer_active = false;
};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 822739088..b3dc6aa19 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -19,6 +19,7 @@
#include "core/hw/gpu.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/utils.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_gen.h"
@@ -36,7 +37,7 @@ static bool IsPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) {
stage.GetAlphaMultiplier() == 1);
}
-RasterizerOpenGL::RasterizerOpenGL() : last_fb_color_addr(0), last_fb_depth_addr(0) { }
+RasterizerOpenGL::RasterizerOpenGL() : cached_fb_color_addr(0), cached_fb_depth_addr(0) { }
RasterizerOpenGL::~RasterizerOpenGL() { }
void RasterizerOpenGL::InitObjects() {
@@ -75,6 +76,12 @@ void RasterizerOpenGL::InitObjects() {
glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD1);
glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD2);
+ glVertexAttribPointer(GLShader::ATTRIBUTE_NORMQUAT, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, normquat));
+ glEnableVertexAttribArray(GLShader::ATTRIBUTE_NORMQUAT);
+
+ glVertexAttribPointer(GLShader::ATTRIBUTE_VIEW, 3, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, view));
+ glEnableVertexAttribArray(GLShader::ATTRIBUTE_VIEW);
+
SetShader();
// Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation
@@ -120,12 +127,26 @@ void RasterizerOpenGL::InitObjects() {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_color_texture.texture.handle, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fb_depth_texture.texture.handle, 0);
+ for (size_t i = 0; i < lighting_lut.size(); ++i) {
+ lighting_lut[i].Create();
+ state.lighting_lut[i].texture_1d = lighting_lut[i].handle;
+
+ glActiveTexture(GL_TEXTURE3 + i);
+ glBindTexture(GL_TEXTURE_1D, state.lighting_lut[i].texture_1d);
+
+ glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+ state.Apply();
+
ASSERT_MSG(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
"OpenGL rasterizer framebuffer setup failed, status %X", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
void RasterizerOpenGL::Reset() {
SyncCullMode();
+ SyncDepthModifiers();
SyncBlendEnabled();
SyncBlendFuncs();
SyncBlendColor();
@@ -135,15 +156,37 @@ void RasterizerOpenGL::Reset() {
SetShader();
- res_cache.FullFlush();
+ res_cache.InvalidateAll();
+}
+
+/**
+ * This is a helper function to resolve an issue with opposite quaternions being interpolated by
+ * OpenGL. See below for a detailed description of this issue (yuriks):
+ *
+ * For any rotation, there are two quaternions Q, and -Q, that represent the same rotation. If you
+ * interpolate two quaternions that are opposite, instead of going from one rotation to another
+ * using the shortest path, you'll go around the longest path. You can test if two quaternions are
+ * opposite by checking if Dot(Q1, W2) < 0. In that case, you can flip either of them, therefore
+ * making Dot(-Q1, W2) positive.
+ *
+ * NOTE: This solution corrects this issue per-vertex before passing the quaternions to OpenGL. This
+ * should be correct for nearly all cases, however a more correct implementation (but less trivial
+ * and perhaps unnecessary) would be to handle this per-fragment, by interpolating the quaternions
+ * manually using two Lerps, and doing this correction before each Lerp.
+ */
+static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) {
+ Math::Vec4f a{ qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32() };
+ Math::Vec4f b{ qb.x.ToFloat32(), qb.y.ToFloat32(), qb.z.ToFloat32(), qb.w.ToFloat32() };
+
+ return (Math::Dot(a, b) < 0.f);
}
void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0,
const Pica::Shader::OutputVertex& v1,
const Pica::Shader::OutputVertex& v2) {
- vertex_batch.emplace_back(v0);
- vertex_batch.emplace_back(v1);
- vertex_batch.emplace_back(v2);
+ vertex_batch.emplace_back(v0, false);
+ vertex_batch.emplace_back(v1, AreQuaternionsOpposite(v0.quat, v1.quat));
+ vertex_batch.emplace_back(v2, AreQuaternionsOpposite(v0.quat, v2.quat));
}
void RasterizerOpenGL::DrawTriangles() {
@@ -155,6 +198,13 @@ void RasterizerOpenGL::DrawTriangles() {
state.draw.shader_dirty = false;
}
+ for (unsigned index = 0; index < lighting_lut.size(); index++) {
+ if (uniform_block_data.lut_dirty[index]) {
+ SyncLightingLUT(index);
+ uniform_block_data.lut_dirty[index] = false;
+ }
+ }
+
if (uniform_block_data.dirty) {
glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW);
uniform_block_data.dirty = false;
@@ -168,19 +218,17 @@ void RasterizerOpenGL::DrawTriangles() {
// Flush the resource cache at the current depth and color framebuffer addresses for render-to-texture
const auto& regs = Pica::g_state.regs;
- PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
- u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
- * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
+ u32 cached_fb_color_size = Pica::Regs::BytesPerColorPixel(fb_color_texture.format)
+ * fb_color_texture.width * fb_color_texture.height;
- PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
- u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
- * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
+ u32 cached_fb_depth_size = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format)
+ * fb_depth_texture.width * fb_depth_texture.height;
- res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size, true);
- res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size, true);
+ res_cache.InvalidateInRange(cached_fb_color_addr, cached_fb_color_size, true);
+ res_cache.InvalidateInRange(cached_fb_depth_addr, cached_fb_depth_size, true);
}
-void RasterizerOpenGL::CommitFramebuffer() {
+void RasterizerOpenGL::FlushFramebuffer() {
CommitColorBuffer();
CommitDepthBuffer();
}
@@ -188,15 +236,18 @@ void RasterizerOpenGL::CommitFramebuffer() {
void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
const auto& regs = Pica::g_state.regs;
- if (!Settings::values.use_hw_renderer)
- return;
-
switch(id) {
// Culling
case PICA_REG_INDEX(cull_mode):
SyncCullMode();
break;
+ // Depth modifiers
+ case PICA_REG_INDEX(viewport_depth_range):
+ case PICA_REG_INDEX(viewport_depth_far_plane):
+ SyncDepthModifiers();
+ break;
+
// Blending
case PICA_REG_INDEX(output_merger.alphablend_enable):
SyncBlendEnabled();
@@ -281,54 +332,203 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
case PICA_REG_INDEX(tev_combiner_buffer_color):
SyncCombinerColor();
break;
+
+ // Fragment lighting specular 0 color
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[0].specular_0, 0x140 + 0 * 0x10):
+ SyncLightSpecular0(0);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[1].specular_0, 0x140 + 1 * 0x10):
+ SyncLightSpecular0(1);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[2].specular_0, 0x140 + 2 * 0x10):
+ SyncLightSpecular0(2);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[3].specular_0, 0x140 + 3 * 0x10):
+ SyncLightSpecular0(3);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[4].specular_0, 0x140 + 4 * 0x10):
+ SyncLightSpecular0(4);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[5].specular_0, 0x140 + 5 * 0x10):
+ SyncLightSpecular0(5);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[6].specular_0, 0x140 + 6 * 0x10):
+ SyncLightSpecular0(6);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[7].specular_0, 0x140 + 7 * 0x10):
+ SyncLightSpecular0(7);
+ break;
+
+ // Fragment lighting specular 1 color
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[0].specular_1, 0x141 + 0 * 0x10):
+ SyncLightSpecular1(0);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[1].specular_1, 0x141 + 1 * 0x10):
+ SyncLightSpecular1(1);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[2].specular_1, 0x141 + 2 * 0x10):
+ SyncLightSpecular1(2);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[3].specular_1, 0x141 + 3 * 0x10):
+ SyncLightSpecular1(3);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[4].specular_1, 0x141 + 4 * 0x10):
+ SyncLightSpecular1(4);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[5].specular_1, 0x141 + 5 * 0x10):
+ SyncLightSpecular1(5);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[6].specular_1, 0x141 + 6 * 0x10):
+ SyncLightSpecular1(6);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[7].specular_1, 0x141 + 7 * 0x10):
+ SyncLightSpecular1(7);
+ break;
+
+ // Fragment lighting diffuse color
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[0].diffuse, 0x142 + 0 * 0x10):
+ SyncLightDiffuse(0);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[1].diffuse, 0x142 + 1 * 0x10):
+ SyncLightDiffuse(1);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[2].diffuse, 0x142 + 2 * 0x10):
+ SyncLightDiffuse(2);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[3].diffuse, 0x142 + 3 * 0x10):
+ SyncLightDiffuse(3);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[4].diffuse, 0x142 + 4 * 0x10):
+ SyncLightDiffuse(4);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[5].diffuse, 0x142 + 5 * 0x10):
+ SyncLightDiffuse(5);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[6].diffuse, 0x142 + 6 * 0x10):
+ SyncLightDiffuse(6);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[7].diffuse, 0x142 + 7 * 0x10):
+ SyncLightDiffuse(7);
+ break;
+
+ // Fragment lighting ambient color
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[0].ambient, 0x143 + 0 * 0x10):
+ SyncLightAmbient(0);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[1].ambient, 0x143 + 1 * 0x10):
+ SyncLightAmbient(1);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[2].ambient, 0x143 + 2 * 0x10):
+ SyncLightAmbient(2);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[3].ambient, 0x143 + 3 * 0x10):
+ SyncLightAmbient(3);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[4].ambient, 0x143 + 4 * 0x10):
+ SyncLightAmbient(4);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[5].ambient, 0x143 + 5 * 0x10):
+ SyncLightAmbient(5);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[6].ambient, 0x143 + 6 * 0x10):
+ SyncLightAmbient(6);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[7].ambient, 0x143 + 7 * 0x10):
+ SyncLightAmbient(7);
+ break;
+
+ // Fragment lighting position
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[0].x, 0x144 + 0 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[0].z, 0x145 + 0 * 0x10):
+ SyncLightPosition(0);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[1].x, 0x144 + 1 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[1].z, 0x145 + 1 * 0x10):
+ SyncLightPosition(1);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[2].x, 0x144 + 2 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[2].z, 0x145 + 2 * 0x10):
+ SyncLightPosition(2);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[3].x, 0x144 + 3 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[3].z, 0x145 + 3 * 0x10):
+ SyncLightPosition(3);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[4].x, 0x144 + 4 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[4].z, 0x145 + 4 * 0x10):
+ SyncLightPosition(4);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[5].x, 0x144 + 5 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[5].z, 0x145 + 5 * 0x10):
+ SyncLightPosition(5);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[6].x, 0x144 + 6 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[6].z, 0x145 + 6 * 0x10):
+ SyncLightPosition(6);
+ break;
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[7].x, 0x144 + 7 * 0x10):
+ case PICA_REG_INDEX_WORKAROUND(lighting.light[7].z, 0x145 + 7 * 0x10):
+ SyncLightPosition(7);
+ break;
+
+ // Fragment lighting global ambient color (emission + ambient * ambient)
+ case PICA_REG_INDEX_WORKAROUND(lighting.global_ambient, 0x1c0):
+ SyncGlobalAmbient();
+ break;
+
+ // Fragment lighting lookup tables
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[0], 0x1c8):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[1], 0x1c9):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[2], 0x1ca):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[3], 0x1cb):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[4], 0x1cc):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[5], 0x1cd):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[6], 0x1ce):
+ case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[7], 0x1cf):
+ {
+ auto& lut_config = regs.lighting.lut_config;
+ uniform_block_data.lut_dirty[lut_config.type / 4] = true;
+ break;
+ }
+
}
}
-void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) {
+void RasterizerOpenGL::FlushRegion(PAddr addr, u32 size) {
const auto& regs = Pica::g_state.regs;
- if (!Settings::values.use_hw_renderer)
- return;
+ u32 cached_fb_color_size = Pica::Regs::BytesPerColorPixel(fb_color_texture.format)
+ * fb_color_texture.width * fb_color_texture.height;
- PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
- u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
- * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
-
- PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
- u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
- * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
+ u32 cached_fb_depth_size = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format)
+ * fb_depth_texture.width * fb_depth_texture.height;
// If source memory region overlaps 3DS framebuffers, commit them before the copy happens
- if (MathUtil::IntervalsIntersect(addr, size, cur_fb_color_addr, cur_fb_color_size))
+ if (MathUtil::IntervalsIntersect(addr, size, cached_fb_color_addr, cached_fb_color_size))
CommitColorBuffer();
- if (MathUtil::IntervalsIntersect(addr, size, cur_fb_depth_addr, cur_fb_depth_size))
+ if (MathUtil::IntervalsIntersect(addr, size, cached_fb_depth_addr, cached_fb_depth_size))
CommitDepthBuffer();
}
-void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
+void RasterizerOpenGL::InvalidateRegion(PAddr addr, u32 size) {
const auto& regs = Pica::g_state.regs;
- if (!Settings::values.use_hw_renderer)
- return;
-
- PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
- u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
- * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
+ u32 cached_fb_color_size = Pica::Regs::BytesPerColorPixel(fb_color_texture.format)
+ * fb_color_texture.width * fb_color_texture.height;
- PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
- u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
- * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
+ u32 cached_fb_depth_size = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format)
+ * fb_depth_texture.width * fb_depth_texture.height;
// If modified memory region overlaps 3DS framebuffers, reload their contents into OpenGL
- if (MathUtil::IntervalsIntersect(addr, size, cur_fb_color_addr, cur_fb_color_size))
+ if (MathUtil::IntervalsIntersect(addr, size, cached_fb_color_addr, cached_fb_color_size))
ReloadColorBuffer();
- if (MathUtil::IntervalsIntersect(addr, size, cur_fb_depth_addr, cur_fb_depth_size))
+ if (MathUtil::IntervalsIntersect(addr, size, cached_fb_depth_addr, cached_fb_depth_size))
ReloadDepthBuffer();
// Notify cache of flush in case the region touches a cached resource
- res_cache.NotifyFlush(addr, size);
+ res_cache.InvalidateInRange(addr, size);
}
void RasterizerOpenGL::SamplerInfo::Create() {
@@ -499,27 +699,48 @@ void RasterizerOpenGL::SetShader() {
uniform_tex = glGetUniformLocation(shader->shader.handle, "tex[2]");
if (uniform_tex != -1) { glUniform1i(uniform_tex, 2); }
+ // Set the texture samplers to correspond to different lookup table texture units
+ GLuint uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[0]");
+ if (uniform_lut != -1) { glUniform1i(uniform_lut, 3); }
+ uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[1]");
+ if (uniform_lut != -1) { glUniform1i(uniform_lut, 4); }
+ uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[2]");
+ if (uniform_lut != -1) { glUniform1i(uniform_lut, 5); }
+ uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[3]");
+ if (uniform_lut != -1) { glUniform1i(uniform_lut, 6); }
+ uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[4]");
+ if (uniform_lut != -1) { glUniform1i(uniform_lut, 7); }
+ uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[5]");
+ if (uniform_lut != -1) { glUniform1i(uniform_lut, 8); }
+
current_shader = shader_cache.emplace(config, std::move(shader)).first->second.get();
unsigned int block_index = glGetUniformBlockIndex(current_shader->shader.handle, "shader_data");
glUniformBlockBinding(current_shader->shader.handle, block_index, 0);
- }
- // Update uniforms
- SyncAlphaTest();
- SyncCombinerColor();
- auto& tev_stages = Pica::g_state.regs.GetTevStages();
- for (int index = 0; index < tev_stages.size(); ++index)
- SyncTevConstColor(index, tev_stages[index]);
+ // Update uniforms
+ SyncAlphaTest();
+ SyncCombinerColor();
+ auto& tev_stages = Pica::g_state.regs.GetTevStages();
+ for (int index = 0; index < tev_stages.size(); ++index)
+ SyncTevConstColor(index, tev_stages[index]);
+
+ SyncGlobalAmbient();
+ for (int light_index = 0; light_index < 8; light_index++) {
+ SyncLightDiffuse(light_index);
+ SyncLightAmbient(light_index);
+ SyncLightPosition(light_index);
+ }
+ }
}
void RasterizerOpenGL::SyncFramebuffer() {
const auto& regs = Pica::g_state.regs;
- PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
+ PAddr new_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
Pica::Regs::ColorFormat new_fb_color_format = regs.framebuffer.color_format;
- PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
+ PAddr new_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress();
Pica::Regs::DepthFormat new_fb_depth_format = regs.framebuffer.depth_format;
bool fb_size_changed = fb_color_texture.width != static_cast<GLsizei>(regs.framebuffer.GetWidth()) ||
@@ -531,10 +752,10 @@ void RasterizerOpenGL::SyncFramebuffer() {
bool depth_fb_prop_changed = fb_depth_texture.format != new_fb_depth_format ||
fb_size_changed;
- bool color_fb_modified = last_fb_color_addr != cur_fb_color_addr ||
+ bool color_fb_modified = cached_fb_color_addr != new_fb_color_addr ||
color_fb_prop_changed;
- bool depth_fb_modified = last_fb_depth_addr != cur_fb_depth_addr ||
+ bool depth_fb_modified = cached_fb_depth_addr != new_fb_depth_addr ||
depth_fb_prop_changed;
// Commit if framebuffer modified in any way
@@ -574,13 +795,13 @@ void RasterizerOpenGL::SyncFramebuffer() {
// Load buffer data again if fb modified in any way
if (color_fb_modified) {
- last_fb_color_addr = cur_fb_color_addr;
+ cached_fb_color_addr = new_fb_color_addr;
ReloadColorBuffer();
}
if (depth_fb_modified) {
- last_fb_depth_addr = cur_fb_depth_addr;
+ cached_fb_depth_addr = new_fb_depth_addr;
ReloadDepthBuffer();
}
@@ -596,12 +817,12 @@ void RasterizerOpenGL::SyncCullMode() {
case Pica::Regs::CullMode::KeepClockWise:
state.cull.enabled = true;
- state.cull.mode = GL_BACK;
+ state.cull.front_face = GL_CW;
break;
case Pica::Regs::CullMode::KeepCounterClockWise:
state.cull.enabled = true;
- state.cull.mode = GL_FRONT;
+ state.cull.front_face = GL_CCW;
break;
default:
@@ -611,6 +832,15 @@ void RasterizerOpenGL::SyncCullMode() {
}
}
+void RasterizerOpenGL::SyncDepthModifiers() {
+ float depth_scale = -Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_range).ToFloat32();
+ float depth_offset = Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_far_plane).ToFloat32() / 2.0f;
+
+ // TODO: Implement scale modifier
+ uniform_block_data.data.depth_offset = depth_offset;
+ uniform_block_data.dirty = true;
+}
+
void RasterizerOpenGL::SyncBlendEnabled() {
state.blend.enabled = (Pica::g_state.regs.output_merger.alphablend_enable == 1);
}
@@ -657,8 +887,10 @@ void RasterizerOpenGL::SyncStencilTest() {
void RasterizerOpenGL::SyncDepthTest() {
const auto& regs = Pica::g_state.regs;
- state.depth.test_enabled = (regs.output_merger.depth_test_enable == 1);
- state.depth.test_func = PicaToGL::CompareFunc(regs.output_merger.depth_test_func);
+ state.depth.test_enabled = regs.output_merger.depth_test_enable == 1 ||
+ regs.output_merger.depth_write_enable == 1;
+ state.depth.test_func = regs.output_merger.depth_test_enable == 1 ?
+ PicaToGL::CompareFunc(regs.output_merger.depth_test_func) : GL_ALWAYS;
state.color_mask.red_enabled = regs.output_merger.red_enable;
state.color_mask.green_enabled = regs.output_merger.green_enable;
state.color_mask.blue_enabled = regs.output_merger.blue_enable;
@@ -682,19 +914,87 @@ void RasterizerOpenGL::SyncTevConstColor(int stage_index, const Pica::Regs::TevS
}
}
+void RasterizerOpenGL::SyncGlobalAmbient() {
+ auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.global_ambient);
+ if (color != uniform_block_data.data.lighting_global_ambient) {
+ uniform_block_data.data.lighting_global_ambient = color;
+ uniform_block_data.dirty = true;
+ }
+}
+
+void RasterizerOpenGL::SyncLightingLUT(unsigned lut_index) {
+ std::array<GLvec4, 256> new_data;
+
+ for (unsigned offset = 0; offset < new_data.size(); ++offset) {
+ new_data[offset][0] = Pica::g_state.lighting.luts[(lut_index * 4) + 0][offset].ToFloat();
+ new_data[offset][1] = Pica::g_state.lighting.luts[(lut_index * 4) + 1][offset].ToFloat();
+ new_data[offset][2] = Pica::g_state.lighting.luts[(lut_index * 4) + 2][offset].ToFloat();
+ new_data[offset][3] = Pica::g_state.lighting.luts[(lut_index * 4) + 3][offset].ToFloat();
+ }
+
+ if (new_data != lighting_lut_data[lut_index]) {
+ lighting_lut_data[lut_index] = new_data;
+ glActiveTexture(GL_TEXTURE3 + lut_index);
+ glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, lighting_lut_data[lut_index].data());
+ }
+}
+
+void RasterizerOpenGL::SyncLightSpecular0(int light_index) {
+ auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].specular_0);
+ if (color != uniform_block_data.data.light_src[light_index].specular_0) {
+ uniform_block_data.data.light_src[light_index].specular_0 = color;
+ uniform_block_data.dirty = true;
+ }
+}
+
+void RasterizerOpenGL::SyncLightSpecular1(int light_index) {
+ auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].specular_1);
+ if (color != uniform_block_data.data.light_src[light_index].specular_1) {
+ uniform_block_data.data.light_src[light_index].specular_1 = color;
+ uniform_block_data.dirty = true;
+ }
+}
+
+void RasterizerOpenGL::SyncLightDiffuse(int light_index) {
+ auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
+ if (color != uniform_block_data.data.light_src[light_index].diffuse) {
+ uniform_block_data.data.light_src[light_index].diffuse = color;
+ uniform_block_data.dirty = true;
+ }
+}
+
+void RasterizerOpenGL::SyncLightAmbient(int light_index) {
+ auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].ambient);
+ if (color != uniform_block_data.data.light_src[light_index].ambient) {
+ uniform_block_data.data.light_src[light_index].ambient = color;
+ uniform_block_data.dirty = true;
+ }
+}
+
+void RasterizerOpenGL::SyncLightPosition(int light_index) {
+ GLvec3 position = {
+ Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].x).ToFloat32(),
+ Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].y).ToFloat32(),
+ Pica::float16::FromRaw(Pica::g_state.regs.lighting.light[light_index].z).ToFloat32() };
+
+ if (position != uniform_block_data.data.light_src[light_index].position) {
+ uniform_block_data.data.light_src[light_index].position = position;
+ uniform_block_data.dirty = true;
+ }
+}
+
void RasterizerOpenGL::SyncDrawState() {
const auto& regs = Pica::g_state.regs;
// Sync the viewport
- GLsizei viewport_width = (GLsizei)Pica::float24::FromRawFloat24(regs.viewport_size_x).ToFloat32() * 2;
- GLsizei viewport_height = (GLsizei)Pica::float24::FromRawFloat24(regs.viewport_size_y).ToFloat32() * 2;
+ GLsizei viewport_width = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_x).ToFloat32() * 2;
+ GLsizei viewport_height = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_y).ToFloat32() * 2;
// OpenGL uses different y coordinates, so negate corner offset and flip origin
// TODO: Ensure viewport_corner.x should not be negated or origin flipped
// TODO: Use floating-point viewports for accuracy if supported
- glViewport((GLsizei)static_cast<float>(regs.viewport_corner.x),
- -(GLsizei)static_cast<float>(regs.viewport_corner.y)
- + regs.framebuffer.GetHeight() - viewport_height,
+ glViewport((GLsizei)regs.viewport_corner.x,
+ (GLsizei)regs.viewport_corner.y,
viewport_width, viewport_height);
// Sync bound texture(s), upload if not cached
@@ -717,7 +1017,7 @@ void RasterizerOpenGL::SyncDrawState() {
MICROPROFILE_DEFINE(OpenGL_FramebufferReload, "OpenGL", "FB Reload", MP_RGB(70, 70, 200));
void RasterizerOpenGL::ReloadColorBuffer() {
- u8* color_buffer = Memory::GetPhysicalPointer(Pica::g_state.regs.framebuffer.GetColorBufferPhysicalAddress());
+ u8* color_buffer = Memory::GetPhysicalPointer(cached_fb_color_addr);
if (color_buffer == nullptr)
return;
@@ -733,7 +1033,7 @@ void RasterizerOpenGL::ReloadColorBuffer() {
for (int x = 0; x < fb_color_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel;
- u32 gl_pixel_index = (x + y * fb_color_texture.width) * bytes_per_pixel;
+ u32 gl_pixel_index = (x + (fb_color_texture.height - 1 - y) * fb_color_texture.width) * bytes_per_pixel;
u8* pixel = color_buffer + dst_offset;
memcpy(&temp_fb_color_buffer[gl_pixel_index], pixel, bytes_per_pixel);
@@ -752,13 +1052,11 @@ void RasterizerOpenGL::ReloadColorBuffer() {
}
void RasterizerOpenGL::ReloadDepthBuffer() {
- PAddr depth_buffer_addr = Pica::g_state.regs.framebuffer.GetDepthBufferPhysicalAddress();
-
- if (depth_buffer_addr == 0)
+ if (cached_fb_depth_addr == 0)
return;
// TODO: Appears to work, but double-check endianness of depth values and order of depth-stencil
- u8* depth_buffer = Memory::GetPhysicalPointer(depth_buffer_addr);
+ u8* depth_buffer = Memory::GetPhysicalPointer(cached_fb_depth_addr);
if (depth_buffer == nullptr)
return;
@@ -779,7 +1077,7 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
for (int x = 0; x < fb_depth_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
- u32 gl_pixel_index = (x + y * fb_depth_texture.width);
+ u32 gl_pixel_index = (x + (fb_depth_texture.height - 1 - y) * fb_depth_texture.width);
u8* pixel = depth_buffer + dst_offset;
u32 depth_stencil = *(u32*)pixel;
@@ -791,7 +1089,7 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
for (int x = 0; x < fb_depth_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
- u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp;
+ u32 gl_pixel_index = (x + (fb_depth_texture.height - 1 - y) * fb_depth_texture.width) * gl_bpp;
u8* pixel = depth_buffer + dst_offset;
memcpy(&temp_fb_depth_data[gl_pixel_index], pixel, bytes_per_pixel);
@@ -821,8 +1119,8 @@ Common::Profiling::TimingCategory buffer_commit_category("Framebuffer Commit");
MICROPROFILE_DEFINE(OpenGL_FramebufferCommit, "OpenGL", "FB Commit", MP_RGB(70, 70, 200));
void RasterizerOpenGL::CommitColorBuffer() {
- if (last_fb_color_addr != 0) {
- u8* color_buffer = Memory::GetPhysicalPointer(last_fb_color_addr);
+ if (cached_fb_color_addr != 0) {
+ u8* color_buffer = Memory::GetPhysicalPointer(cached_fb_color_addr);
if (color_buffer != nullptr) {
Common::Profiling::ScopeTimer timer(buffer_commit_category);
@@ -846,7 +1144,7 @@ void RasterizerOpenGL::CommitColorBuffer() {
for (int x = 0; x < fb_color_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel;
- u32 gl_pixel_index = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = x * bytes_per_pixel + (fb_color_texture.height - 1 - y) * fb_color_texture.width * bytes_per_pixel;
u8* pixel = color_buffer + dst_offset;
memcpy(pixel, &temp_gl_color_buffer[gl_pixel_index], bytes_per_pixel);
@@ -857,9 +1155,9 @@ void RasterizerOpenGL::CommitColorBuffer() {
}
void RasterizerOpenGL::CommitDepthBuffer() {
- if (last_fb_depth_addr != 0) {
+ if (cached_fb_depth_addr != 0) {
// TODO: Output seems correct visually, but doesn't quite match sw renderer output. One of them is wrong.
- u8* depth_buffer = Memory::GetPhysicalPointer(last_fb_depth_addr);
+ u8* depth_buffer = Memory::GetPhysicalPointer(cached_fb_depth_addr);
if (depth_buffer != nullptr) {
Common::Profiling::ScopeTimer timer(buffer_commit_category);
@@ -888,7 +1186,7 @@ void RasterizerOpenGL::CommitDepthBuffer() {
for (int x = 0; x < fb_depth_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
- u32 gl_pixel_index = (x + y * fb_depth_texture.width);
+ u32 gl_pixel_index = (x + (fb_depth_texture.height - 1 - y) * fb_depth_texture.width);
u8* pixel = depth_buffer + dst_offset;
u32 depth_stencil = ((u32*)temp_gl_depth_data)[gl_pixel_index];
@@ -900,7 +1198,7 @@ void RasterizerOpenGL::CommitDepthBuffer() {
for (int x = 0; x < fb_depth_texture.width; ++x) {
const u32 coarse_y = y & ~7;
u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel;
- u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp;
+ u32 gl_pixel_index = (x + (fb_depth_texture.height - 1 - y) * fb_depth_texture.width) * gl_bpp;
u8* pixel = depth_buffer + dst_offset;
memcpy(pixel, &temp_gl_depth_data[gl_pixel_index], bytes_per_pixel);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 5ba898189..fc85aa3ff 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -14,9 +14,11 @@
#include "common/hash.h"
#include "video_core/pica.h"
-#include "video_core/hwrasterizer_base.h"
+#include "video_core/pica_state.h"
+#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_state.h"
+#include "video_core/renderer_opengl/pica_to_gl.h"
#include "video_core/shader/shader_interpreter.h"
/**
@@ -71,6 +73,59 @@ struct PicaShaderConfig {
regs.tev_combiner_buffer_input.update_mask_rgb.Value() |
regs.tev_combiner_buffer_input.update_mask_a.Value() << 4;
+ // Fragment lighting
+
+ res.lighting.enable = !regs.lighting.disable;
+ res.lighting.src_num = regs.lighting.num_lights + 1;
+
+ for (unsigned light_index = 0; light_index < res.lighting.src_num; ++light_index) {
+ unsigned num = regs.lighting.light_enable.GetNum(light_index);
+ const auto& light = regs.lighting.light[num];
+ res.lighting.light[light_index].num = num;
+ res.lighting.light[light_index].directional = light.directional != 0;
+ res.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0;
+ res.lighting.light[light_index].dist_atten_enable = !regs.lighting.IsDistAttenDisabled(num);
+ res.lighting.light[light_index].dist_atten_bias = Pica::float20::FromRaw(light.dist_atten_bias).ToFloat32();
+ res.lighting.light[light_index].dist_atten_scale = Pica::float20::FromRaw(light.dist_atten_scale).ToFloat32();
+ }
+
+ res.lighting.lut_d0.enable = regs.lighting.disable_lut_d0 == 0;
+ res.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.disable_d0 == 0;
+ res.lighting.lut_d0.type = regs.lighting.lut_input.d0.Value();
+ res.lighting.lut_d0.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0);
+
+ res.lighting.lut_d1.enable = regs.lighting.disable_lut_d1 == 0;
+ res.lighting.lut_d1.abs_input = regs.lighting.abs_lut_input.disable_d1 == 0;
+ res.lighting.lut_d1.type = regs.lighting.lut_input.d1.Value();
+ res.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1);
+
+ res.lighting.lut_fr.enable = regs.lighting.disable_lut_fr == 0;
+ res.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.disable_fr == 0;
+ res.lighting.lut_fr.type = regs.lighting.lut_input.fr.Value();
+ res.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr);
+
+ res.lighting.lut_rr.enable = regs.lighting.disable_lut_rr == 0;
+ res.lighting.lut_rr.abs_input = regs.lighting.abs_lut_input.disable_rr == 0;
+ res.lighting.lut_rr.type = regs.lighting.lut_input.rr.Value();
+ res.lighting.lut_rr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr);
+
+ res.lighting.lut_rg.enable = regs.lighting.disable_lut_rg == 0;
+ res.lighting.lut_rg.abs_input = regs.lighting.abs_lut_input.disable_rg == 0;
+ res.lighting.lut_rg.type = regs.lighting.lut_input.rg.Value();
+ res.lighting.lut_rg.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg);
+
+ res.lighting.lut_rb.enable = regs.lighting.disable_lut_rb == 0;
+ res.lighting.lut_rb.abs_input = regs.lighting.abs_lut_input.disable_rb == 0;
+ res.lighting.lut_rb.type = regs.lighting.lut_input.rb.Value();
+ res.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb);
+
+ res.lighting.config = regs.lighting.config;
+ res.lighting.fresnel_selector = regs.lighting.fresnel_selector;
+ res.lighting.bump_mode = regs.lighting.bump_mode;
+ res.lighting.bump_selector = regs.lighting.bump_selector;
+ res.lighting.bump_renorm = regs.lighting.disable_bump_renorm == 0;
+ res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0;
+
return res;
}
@@ -86,9 +141,37 @@ struct PicaShaderConfig {
return std::memcmp(this, &o, sizeof(PicaShaderConfig)) == 0;
};
- Pica::Regs::CompareFunc alpha_test_func;
+ Pica::Regs::CompareFunc alpha_test_func = Pica::Regs::CompareFunc::Never;
std::array<Pica::Regs::TevStageConfig, 6> tev_stages = {};
- u8 combiner_buffer_input;
+ u8 combiner_buffer_input = 0;
+
+ struct {
+ struct {
+ unsigned num = 0;
+ bool directional = false;
+ bool two_sided_diffuse = false;
+ bool dist_atten_enable = false;
+ GLfloat dist_atten_scale = 0.0f;
+ GLfloat dist_atten_bias = 0.0f;
+ } light[8];
+
+ bool enable = false;
+ unsigned src_num = 0;
+ Pica::Regs::LightingBumpMode bump_mode = Pica::Regs::LightingBumpMode::None;
+ unsigned bump_selector = 0;
+ bool bump_renorm = false;
+ bool clamp_highlights = false;
+
+ Pica::Regs::LightingConfig config = Pica::Regs::LightingConfig::Config0;
+ Pica::Regs::LightingFresnelSelector fresnel_selector = Pica::Regs::LightingFresnelSelector::None;
+
+ struct {
+ bool enable = false;
+ bool abs_input = false;
+ Pica::Regs::LightingLutInput type = Pica::Regs::LightingLutInput::NH;
+ float scale = 1.0f;
+ } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb;
+ } lighting;
};
namespace std {
@@ -102,37 +185,22 @@ struct hash<PicaShaderConfig> {
} // namespace std
-class RasterizerOpenGL : public HWRasterizer {
+class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
RasterizerOpenGL();
~RasterizerOpenGL() override;
- /// Initialize API-specific GPU objects
void InitObjects() override;
-
- /// Reset the rasterizer, such as flushing all caches and updating all state
void Reset() override;
-
- /// Queues the primitive formed by the given vertices for rendering
void AddTriangle(const Pica::Shader::OutputVertex& v0,
const Pica::Shader::OutputVertex& v1,
const Pica::Shader::OutputVertex& v2) override;
-
- /// Draw the current batch of triangles
void DrawTriangles() override;
-
- /// Commit the rasterizer's framebuffer contents immediately to the current 3DS memory framebuffer
- void CommitFramebuffer() override;
-
- /// Notify rasterizer that the specified PICA register has been changed
+ void FlushFramebuffer() override;
void NotifyPicaRegisterChanged(u32 id) override;
-
- /// Notify rasterizer that the specified 3DS memory region will be read from after this notification
- void NotifyPreRead(PAddr addr, u32 size) override;
-
- /// Notify rasterizer that a 3DS memory region has been changed
- void NotifyFlush(PAddr addr, u32 size) override;
+ void FlushRegion(PAddr addr, u32 size) override;
+ void InvalidateRegion(PAddr addr, u32 size) override;
/// OpenGL shader generated for a given Pica register state
struct PicaShader {
@@ -182,7 +250,7 @@ private:
/// Structure that the hardware rendered vertices are composed of
struct HardwareVertex {
- HardwareVertex(const Pica::Shader::OutputVertex& v) {
+ HardwareVertex(const Pica::Shader::OutputVertex& v, bool flip_quaternion) {
position[0] = v.pos.x.ToFloat32();
position[1] = v.pos.y.ToFloat32();
position[2] = v.pos.z.ToFloat32();
@@ -197,6 +265,19 @@ private:
tex_coord1[1] = v.tc1.y.ToFloat32();
tex_coord2[0] = v.tc2.x.ToFloat32();
tex_coord2[1] = v.tc2.y.ToFloat32();
+ normquat[0] = v.quat.x.ToFloat32();
+ normquat[1] = v.quat.y.ToFloat32();
+ normquat[2] = v.quat.z.ToFloat32();
+ normquat[3] = v.quat.w.ToFloat32();
+ view[0] = v.view.x.ToFloat32();
+ view[1] = v.view.y.ToFloat32();
+ view[2] = v.view.z.ToFloat32();
+
+ if (flip_quaternion) {
+ for (float& x : normquat) {
+ x = -x;
+ }
+ }
}
GLfloat position[4];
@@ -204,19 +285,31 @@ private:
GLfloat tex_coord0[2];
GLfloat tex_coord1[2];
GLfloat tex_coord2[2];
+ GLfloat normquat[4];
+ GLfloat view[3];
+ };
+
+ struct LightSrc {
+ alignas(16) GLvec3 specular_0;
+ alignas(16) GLvec3 specular_1;
+ alignas(16) GLvec3 diffuse;
+ alignas(16) GLvec3 ambient;
+ alignas(16) GLvec3 position;
};
/// Uniform structure for the Uniform Buffer Object, all members must be 16-byte aligned
struct UniformData {
// A vec4 color for each of the six tev stages
- std::array<GLfloat, 4> const_color[6];
- std::array<GLfloat, 4> tev_combiner_buffer_color;
+ GLvec4 const_color[6];
+ GLvec4 tev_combiner_buffer_color;
GLint alphatest_ref;
- INSERT_PADDING_BYTES(12);
+ GLfloat depth_offset;
+ alignas(16) GLvec3 lighting_global_ambient;
+ LightSrc light_src[8];
};
- static_assert(sizeof(UniformData) == 0x80, "The size of the UniformData structure has changed, update the structure in the shader");
- static_assert(sizeof(UniformData) < 16000, "UniformData structure must be less than 16kb as per the OpenGL spec");
+ static_assert(sizeof(UniformData) == 0x310, "The size of the UniformData structure has changed, update the structure in the shader");
+ static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec");
/// Reconfigure the OpenGL color texture to use the given format and dimensions
void ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height);
@@ -233,6 +326,9 @@ private:
/// Syncs the cull mode to match the PICA register
void SyncCullMode();
+ /// Syncs the depth scale and offset to match the PICA registers
+ void SyncDepthModifiers();
+
/// Syncs the blend enabled status to match the PICA register
void SyncBlendEnabled();
@@ -260,6 +356,27 @@ private:
/// Syncs the TEV combiner color buffer to match the PICA register
void SyncCombinerColor();
+ /// Syncs the lighting global ambient color to match the PICA register
+ void SyncGlobalAmbient();
+
+ /// Syncs the lighting lookup tables
+ void SyncLightingLUT(unsigned index);
+
+ /// Syncs the specified light's diffuse color to match the PICA register
+ void SyncLightDiffuse(int light_index);
+
+ /// Syncs the specified light's ambient color to match the PICA register
+ void SyncLightAmbient(int light_index);
+
+ /// Syncs the specified light's position to match the PICA register
+ void SyncLightPosition(int light_index);
+
+ /// Syncs the specified light's specular 0 color to match the PICA register
+ void SyncLightSpecular0(int light_index);
+
+ /// Syncs the specified light's specular 1 color to match the PICA register
+ void SyncLightSpecular1(int light_index);
+
/// Syncs the remaining OpenGL drawing state to match the current PICA state
void SyncDrawState();
@@ -289,8 +406,8 @@ private:
OpenGLState state;
- PAddr last_fb_color_addr;
- PAddr last_fb_depth_addr;
+ PAddr cached_fb_color_addr;
+ PAddr cached_fb_depth_addr;
// Hardware rasterizer
std::array<SamplerInfo, 3> texture_samplers;
@@ -302,6 +419,7 @@ private:
struct {
UniformData data;
+ bool lut_dirty[6];
bool dirty;
} uniform_block_data;
@@ -309,4 +427,7 @@ private:
OGLBuffer vertex_buffer;
OGLBuffer uniform_buffer;
OGLFramebuffer framebuffer;
+
+ std::array<OGLTexture, 6> lighting_lut;
+ std::array<std::array<GLvec4, 256>, 6> lighting_lut_data;
};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 10d4ab0b6..a9ad46fe0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -15,7 +15,7 @@
#include "video_core/renderer_opengl/pica_to_gl.h"
RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
- FullFlush();
+ InvalidateAll();
}
MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
@@ -58,8 +58,7 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
}
}
-void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size, bool ignore_hash) {
- // Flush any texture that falls in the flushed region
+void RasterizerCacheOpenGL::InvalidateInRange(PAddr addr, u32 size, bool ignore_hash) {
// TODO: Optimize by also inserting upper bound (addr + size) of each texture into the same map and also narrow using lower_bound
auto cache_upper_bound = texture_cache.upper_bound(addr + size);
@@ -77,6 +76,6 @@ void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size, bool ignore_hash)
}
}
-void RasterizerCacheOpenGL::FullFlush() {
+void RasterizerCacheOpenGL::InvalidateAll() {
texture_cache.clear();
}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 98a48ffbe..b69651427 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -23,11 +23,11 @@ public:
LoadAndBindTexture(state, texture_unit, Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format));
}
- /// Flush any cached resource that touches the flushed region
- void NotifyFlush(PAddr addr, u32 size, bool ignore_hash = false);
+ /// Invalidate any cached resource intersecting the specified region.
+ void InvalidateInRange(PAddr addr, u32 size, bool ignore_hash = false);
- /// Flush all cached OpenGL resources tracked by this cache manager
- void FullFlush();
+ /// Invalidate all cached OpenGL resources tracked by this cache manager
+ void InvalidateAll();
private:
struct CachedTexture {
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 498c506e7..ee4b54ab9 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -32,12 +32,10 @@ static void AppendSource(std::string& out, TevStageConfig::Source source,
out += "primary_color";
break;
case Source::PrimaryFragmentColor:
- // HACK: Until we implement fragment lighting, use primary_color
- out += "primary_color";
+ out += "primary_fragment_color";
break;
case Source::SecondaryFragmentColor:
- // HACK: Until we implement fragment lighting, use zero
- out += "vec4(0.0)";
+ out += "secondary_fragment_color";
break;
case Source::Texture0:
out += "texture(tex[0], texcoord[0])";
@@ -320,25 +318,229 @@ static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsi
out += "next_combiner_buffer.a = last_tex_env_out.a;\n";
}
+/// Writes the code to emulate fragment lighting
+static void WriteLighting(std::string& out, const PicaShaderConfig& config) {
+ // Define lighting globals
+ out += "vec4 diffuse_sum = vec4(0.0, 0.0, 0.0, 1.0);\n"
+ "vec4 specular_sum = vec4(0.0, 0.0, 0.0, 1.0);\n"
+ "vec3 light_vector = vec3(0.0);\n"
+ "vec3 refl_value = vec3(0.0);\n";
+
+ // Compute fragment normals
+ if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::NormalMap) {
+ // Bump mapping is enabled using a normal map, read perturbation vector from the selected texture
+ std::string bump_selector = std::to_string(config.lighting.bump_selector);
+ out += "vec3 surface_normal = 2.0 * texture(tex[" + bump_selector + "], texcoord[" + bump_selector + "]).rgb - 1.0;\n";
+
+ // Recompute Z-component of perturbation if 'renorm' is enabled, this provides a higher precision result
+ if (config.lighting.bump_renorm) {
+ std::string val = "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))";
+ out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n";
+ }
+ } else if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::TangentMap) {
+ // Bump mapping is enabled using a tangent map
+ LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)");
+ UNIMPLEMENTED();
+ } else {
+ // No bump mapping - surface local normal is just a unit normal
+ out += "vec3 surface_normal = vec3(0.0, 0.0, 1.0);\n";
+ }
+
+ // Rotate the surface-local normal by the interpolated normal quaternion to convert it to eyespace
+ out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n";
+
+ // Gets the index into the specified lookup table for specular lighting
+ auto GetLutIndex = [config](unsigned light_num, Regs::LightingLutInput input, bool abs) {
+ const std::string half_angle = "normalize(normalize(view) + light_vector)";
+ std::string index;
+ switch (input) {
+ case Regs::LightingLutInput::NH:
+ index = "dot(normal, " + half_angle + ")";
+ break;
+
+ case Regs::LightingLutInput::VH:
+ index = std::string("dot(normalize(view), " + half_angle + ")");
+ break;
+
+ case Regs::LightingLutInput::NV:
+ index = std::string("dot(normal, normalize(view))");
+ break;
+
+ case Regs::LightingLutInput::LN:
+ index = std::string("dot(light_vector, normal)");
+ break;
+
+ default:
+ LOG_CRITICAL(HW_GPU, "Unknown lighting LUT input %d\n", (int)input);
+ UNIMPLEMENTED();
+ break;
+ }
+
+ if (abs) {
+ // LUT index is in the range of (0.0, 1.0)
+ index = config.lighting.light[light_num].two_sided_diffuse ? "abs(" + index + ")" : "max(" + index + ", 0.f)";
+ return "(FLOAT_255 * clamp(" + index + ", 0.0, 1.0))";
+ } else {
+ // LUT index is in the range of (-1.0, 1.0)
+ index = "clamp(" + index + ", -1.0, 1.0)";
+ return "(FLOAT_255 * ((" + index + " < 0) ? " + index + " + 2.0 : " + index + ") / 2.0)";
+ }
+
+ return std::string();
+ };
+
+ // Gets the lighting lookup table value given the specified sampler and index
+ auto GetLutValue = [](Regs::LightingSampler sampler, std::string lut_index) {
+ return std::string("texture(lut[" + std::to_string((unsigned)sampler / 4) + "], " +
+ lut_index + ")[" + std::to_string((unsigned)sampler & 3) + "]");
+ };
+
+ // Write the code to emulate each enabled light
+ for (unsigned light_index = 0; light_index < config.lighting.src_num; ++light_index) {
+ const auto& light_config = config.lighting.light[light_index];
+ std::string light_src = "light_src[" + std::to_string(light_config.num) + "]";
+
+ // Compute light vector (directional or positional)
+ if (light_config.directional)
+ out += "light_vector = normalize(" + light_src + ".position);\n";
+ else
+ out += "light_vector = normalize(" + light_src + ".position + view);\n";
+
+ // Compute dot product of light_vector and normal, adjust if lighting is one-sided or two-sided
+ std::string dot_product = light_config.two_sided_diffuse ? "abs(dot(light_vector, normal))" : "max(dot(light_vector, normal), 0.0)";
+
+ // If enabled, compute distance attenuation value
+ std::string dist_atten = "1.0";
+ if (light_config.dist_atten_enable) {
+ std::string scale = std::to_string(light_config.dist_atten_scale);
+ std::string bias = std::to_string(light_config.dist_atten_bias);
+ std::string index = "(" + scale + " * length(-view - " + light_src + ".position) + " + bias + ")";
+ index = "((clamp(" + index + ", 0.0, FLOAT_255)))";
+ const unsigned lut_num = ((unsigned)Regs::LightingSampler::DistanceAttenuation + light_config.num);
+ dist_atten = GetLutValue((Regs::LightingSampler)lut_num, index);
+ }
+
+ // If enabled, clamp specular component if lighting result is negative
+ std::string clamp_highlights = config.lighting.clamp_highlights ? "(dot(light_vector, normal) <= 0.0 ? 0.0 : 1.0)" : "1.0";
+
+ // Specular 0 component
+ std::string d0_lut_value = "1.0";
+ if (config.lighting.lut_d0.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::Distribution0)) {
+ // Lookup specular "distribution 0" LUT value
+ std::string index = GetLutIndex(light_config.num, config.lighting.lut_d0.type, config.lighting.lut_d0.abs_input);
+ d0_lut_value = "(" + std::to_string(config.lighting.lut_d0.scale) + " * " + GetLutValue(Regs::LightingSampler::Distribution0, index) + ")";
+ }
+ std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)";
+
+ // If enabled, lookup ReflectRed value, otherwise, 1.0 is used
+ if (config.lighting.lut_rr.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::ReflectRed)) {
+ std::string index = GetLutIndex(light_config.num, config.lighting.lut_rr.type, config.lighting.lut_rr.abs_input);
+ std::string value = "(" + std::to_string(config.lighting.lut_rr.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectRed, index) + ")";
+ out += "refl_value.r = " + value + ";\n";
+ } else {
+ out += "refl_value.r = 1.0;\n";
+ }
+
+ // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used
+ if (config.lighting.lut_rg.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::ReflectGreen)) {
+ std::string index = GetLutIndex(light_config.num, config.lighting.lut_rg.type, config.lighting.lut_rg.abs_input);
+ std::string value = "(" + std::to_string(config.lighting.lut_rg.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectGreen, index) + ")";
+ out += "refl_value.g = " + value + ";\n";
+ } else {
+ out += "refl_value.g = refl_value.r;\n";
+ }
+
+ // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used
+ if (config.lighting.lut_rb.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::ReflectBlue)) {
+ std::string index = GetLutIndex(light_config.num, config.lighting.lut_rb.type, config.lighting.lut_rb.abs_input);
+ std::string value = "(" + std::to_string(config.lighting.lut_rb.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectBlue, index) + ")";
+ out += "refl_value.b = " + value + ";\n";
+ } else {
+ out += "refl_value.b = refl_value.r;\n";
+ }
+
+ // Specular 1 component
+ std::string d1_lut_value = "1.0";
+ if (config.lighting.lut_d1.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::Distribution1)) {
+ // Lookup specular "distribution 1" LUT value
+ std::string index = GetLutIndex(light_config.num, config.lighting.lut_d1.type, config.lighting.lut_d1.abs_input);
+ d1_lut_value = "(" + std::to_string(config.lighting.lut_d1.scale) + " * " + GetLutValue(Regs::LightingSampler::Distribution1, index) + ")";
+ }
+ std::string specular_1 = "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)";
+
+ // Fresnel
+ if (config.lighting.lut_fr.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::Fresnel)) {
+ // Lookup fresnel LUT value
+ std::string index = GetLutIndex(light_config.num, config.lighting.lut_fr.type, config.lighting.lut_fr.abs_input);
+ std::string value = "(" + std::to_string(config.lighting.lut_fr.scale) + " * " + GetLutValue(Regs::LightingSampler::Fresnel, index) + ")";
+
+ // Enabled for difffuse lighting alpha component
+ if (config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::PrimaryAlpha ||
+ config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both)
+ out += "diffuse_sum.a *= " + value + ";\n";
+
+ // Enabled for the specular lighting alpha component
+ if (config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::SecondaryAlpha ||
+ config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both)
+ out += "specular_sum.a *= " + value + ";\n";
+ }
+
+ // Compute primary fragment color (diffuse lighting) function
+ out += "diffuse_sum.rgb += ((" + light_src + ".diffuse * " + dot_product + ") + " + light_src + ".ambient) * " + dist_atten + ";\n";
+
+ // Compute secondary fragment color (specular lighting) function
+ out += "specular_sum.rgb += (" + specular_0 + " + " + specular_1 + ") * " + clamp_highlights + " * " + dist_atten + ";\n";
+ }
+
+ // Sum final lighting result
+ out += "diffuse_sum.rgb += lighting_global_ambient;\n";
+ out += "primary_fragment_color = clamp(diffuse_sum, vec4(0.0), vec4(1.0));\n";
+ out += "secondary_fragment_color = clamp(specular_sum, vec4(0.0), vec4(1.0));\n";
+}
+
std::string GenerateFragmentShader(const PicaShaderConfig& config) {
std::string out = R"(
#version 330 core
#define NUM_TEV_STAGES 6
+#define NUM_LIGHTS 8
+#define LIGHTING_LUT_SIZE 256
+#define FLOAT_255 (255.0 / 256.0)
in vec4 primary_color;
in vec2 texcoord[3];
+in vec4 normquat;
+in vec3 view;
out vec4 color;
+struct LightSrc {
+ vec3 specular_0;
+ vec3 specular_1;
+ vec3 diffuse;
+ vec3 ambient;
+ vec3 position;
+};
+
layout (std140) uniform shader_data {
vec4 const_color[NUM_TEV_STAGES];
vec4 tev_combiner_buffer_color;
int alphatest_ref;
+ float depth_offset;
+ vec3 lighting_global_ambient;
+ LightSrc light_src[NUM_LIGHTS];
};
uniform sampler2D tex[3];
+uniform sampler1D lut[6];
+
+// Rotate the vector v by the quaternion q
+vec3 quaternion_rotate(vec4 q, vec3 v) {
+ return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
+}
void main() {
+vec4 primary_fragment_color = vec4(0.0);
+vec4 secondary_fragment_color = vec4(0.0);
)";
// Do not do any sort of processing if it's obvious we're not going to pass the alpha test
@@ -347,6 +549,9 @@ void main() {
return out;
}
+ if (config.lighting.enable)
+ WriteLighting(out, config);
+
out += "vec4 combiner_buffer = vec4(0.0);\n";
out += "vec4 next_combiner_buffer = tev_combiner_buffer_color;\n";
out += "vec4 last_tex_env_out = vec4(0.0);\n";
@@ -360,29 +565,37 @@ void main() {
out += ") discard;\n";
}
- out += "color = last_tex_env_out;\n}";
+ out += "color = last_tex_env_out;\n";
+ out += "gl_FragDepth = gl_FragCoord.z + depth_offset;\n}";
return out;
}
std::string GenerateVertexShader() {
std::string out = "#version 330 core\n";
+
out += "layout(location = " + std::to_string((int)ATTRIBUTE_POSITION) + ") in vec4 vert_position;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_COLOR) + ") in vec4 vert_color;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD0) + ") in vec2 vert_texcoord0;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD1) + ") in vec2 vert_texcoord1;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD2) + ") in vec2 vert_texcoord2;\n";
+ out += "layout(location = " + std::to_string((int)ATTRIBUTE_NORMQUAT) + ") in vec4 vert_normquat;\n";
+ out += "layout(location = " + std::to_string((int)ATTRIBUTE_VIEW) + ") in vec3 vert_view;\n";
out += R"(
out vec4 primary_color;
out vec2 texcoord[3];
+out vec4 normquat;
+out vec3 view;
void main() {
primary_color = vert_color;
texcoord[0] = vert_texcoord0;
texcoord[1] = vert_texcoord1;
texcoord[2] = vert_texcoord2;
- gl_Position = vec4(vert_position.x, -vert_position.y, -vert_position.z, vert_position.w);
+ normquat = vert_normquat;
+ view = vert_view;
+ gl_Position = vec4(vert_position.x, vert_position.y, -vert_position.z, vert_position.w);
}
)";
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h
index 046aae14f..097242f6f 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.h
+++ b/src/video_core/renderer_opengl/gl_shader_util.h
@@ -14,6 +14,8 @@ enum Attributes {
ATTRIBUTE_TEXCOORD0,
ATTRIBUTE_TEXCOORD1,
ATTRIBUTE_TEXCOORD2,
+ ATTRIBUTE_NORMQUAT,
+ ATTRIBUTE_VIEW,
};
/**
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index c44497fc3..08e4d0b54 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -11,6 +11,7 @@ OpenGLState::OpenGLState() {
// These all match default OpenGL values
cull.enabled = false;
cull.mode = GL_BACK;
+ cull.front_face = GL_CCW;
depth.test_enabled = false;
depth.test_func = GL_LESS;
@@ -47,6 +48,10 @@ OpenGLState::OpenGLState() {
texture_unit.sampler = 0;
}
+ for (auto& lut : lighting_lut) {
+ lut.texture_1d = 0;
+ }
+
draw.framebuffer = 0;
draw.vertex_array = 0;
draw.vertex_buffer = 0;
@@ -67,6 +72,10 @@ void OpenGLState::Apply() {
glCullFace(cull.mode);
}
+ if (cull.front_face != cur_state.cull.front_face) {
+ glFrontFace(cull.front_face);
+ }
+
// Depth test
if (depth.test_enabled != cur_state.depth.test_enabled) {
if (depth.test_enabled) {
@@ -165,6 +174,14 @@ void OpenGLState::Apply() {
}
}
+ // Lighting LUTs
+ for (unsigned i = 0; i < ARRAY_SIZE(lighting_lut); ++i) {
+ if (lighting_lut[i].texture_1d != cur_state.lighting_lut[i].texture_1d) {
+ glActiveTexture(GL_TEXTURE3 + i);
+ glBindTexture(GL_TEXTURE_1D, lighting_lut[i].texture_1d);
+ }
+ }
+
// Framebuffer
if (draw.framebuffer != cur_state.draw.framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, draw.framebuffer);
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 84b3d49bc..e848058d7 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -11,6 +11,7 @@ public:
struct {
bool enabled; // GL_CULL_FACE
GLenum mode; // GL_CULL_FACE_MODE
+ GLenum front_face; // GL_FRONT_FACE
} cull;
struct {
@@ -61,6 +62,10 @@ public:
} texture_units[3];
struct {
+ GLuint texture_1d; // GL_TEXTURE_BINDING_1D
+ } lighting_lut[6];
+
+ struct {
GLuint framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING
GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING
GLuint vertex_buffer; // GL_ARRAY_BUFFER_BINDING
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h
index 04c1d1a34..3d6c4e9e5 100644
--- a/src/video_core/renderer_opengl/pica_to_gl.h
+++ b/src/video_core/renderer_opengl/pica_to_gl.h
@@ -10,6 +10,9 @@
#include "video_core/pica.h"
+using GLvec3 = std::array<GLfloat, 3>;
+using GLvec4 = std::array<GLfloat, 4>;
+
namespace PicaToGL {
inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) {
@@ -175,7 +178,7 @@ inline GLenum StencilOp(Pica::Regs::StencilAction action) {
return stencil_op_table[(unsigned)action];
}
-inline std::array<GLfloat, 4> ColorRGBA8(const u32 color) {
+inline GLvec4 ColorRGBA8(const u32 color) {
return { { (color >> 0 & 0xFF) / 255.0f,
(color >> 8 & 0xFF) / 255.0f,
(color >> 16 & 0xFF) / 255.0f,
@@ -183,4 +186,11 @@ inline std::array<GLfloat, 4> ColorRGBA8(const u32 color) {
} };
}
+inline std::array<GLfloat, 3> LightColor(const Pica::Regs::LightColor& color) {
+ return { { color.r / 255.0f,
+ color.g / 255.0f,
+ color.b / 255.0f
+ } };
+}
+
} // namespace
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 1420229cc..11c4d0daf 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -81,8 +81,8 @@ struct ScreenRectVertex {
* The projection part of the matrix is trivial, hence these operations are represented
* by a 3x2 matrix.
*/
-static std::array<GLfloat, 3*2> MakeOrthographicMatrix(const float width, const float height) {
- std::array<GLfloat, 3*2> matrix;
+static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, const float height) {
+ std::array<GLfloat, 3 * 2> matrix;
matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
@@ -93,7 +93,6 @@ static std::array<GLfloat, 3*2> MakeOrthographicMatrix(const float width, const
/// RendererOpenGL constructor
RendererOpenGL::RendererOpenGL() {
- hw_rasterizer.reset(new RasterizerOpenGL());
resolution_width = std::max(VideoCore::kScreenTopWidth, VideoCore::kScreenBottomWidth);
resolution_height = VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight;
}
@@ -157,15 +156,7 @@ void RendererOpenGL::SwapBuffers() {
profiler.BeginFrame();
- bool hw_renderer_enabled = VideoCore::g_hw_renderer_enabled;
- if (Settings::values.use_hw_renderer != hw_renderer_enabled) {
- // TODO: Save new setting value to config file for next startup
- Settings::values.use_hw_renderer = hw_renderer_enabled;
-
- if (Settings::values.use_hw_renderer) {
- hw_rasterizer->Reset();
- }
- }
+ RefreshRasterizerSetting();
if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
Pica::g_debug_context->recorder->FrameFinished();
@@ -286,8 +277,6 @@ void RendererOpenGL::InitOpenGLObjects() {
state.texture_units[0].texture_2d = 0;
state.Apply();
-
- hw_rasterizer->InitObjects();
}
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
@@ -405,8 +394,58 @@ void RendererOpenGL::SetWindow(EmuWindow* window) {
render_window = window;
}
+static const char* GetSource(GLenum source) {
+#define RET(s) case GL_DEBUG_SOURCE_##s: return #s
+ switch (source) {
+ RET(API);
+ RET(WINDOW_SYSTEM);
+ RET(SHADER_COMPILER);
+ RET(THIRD_PARTY);
+ RET(APPLICATION);
+ RET(OTHER);
+ default:
+ UNREACHABLE();
+ }
+#undef RET
+}
+
+static const char* GetType(GLenum type) {
+#define RET(t) case GL_DEBUG_TYPE_##t: return #t
+ switch (type) {
+ RET(ERROR);
+ RET(DEPRECATED_BEHAVIOR);
+ RET(UNDEFINED_BEHAVIOR);
+ RET(PORTABILITY);
+ RET(PERFORMANCE);
+ RET(OTHER);
+ RET(MARKER);
+ default:
+ UNREACHABLE();
+ }
+#undef RET
+}
+
+static void DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
+ const GLchar* message, const void* user_param) {
+ Log::Level level;
+ switch (severity) {
+ case GL_DEBUG_SEVERITY_HIGH:
+ level = Log::Level::Error;
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ level = Log::Level::Warning;
+ break;
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ case GL_DEBUG_SEVERITY_LOW:
+ level = Log::Level::Debug;
+ break;
+ }
+ LOG_GENERIC(Log::Class::Render_OpenGL, level, "%s %s %d: %s",
+ GetSource(source), GetType(type), id, message);
+}
+
/// Initialize the renderer
-void RendererOpenGL::Init() {
+bool RendererOpenGL::Init() {
render_window->MakeCurrent();
// TODO: Make frontends initialize this, so they can use gladLoadGLLoader with their own loaders
@@ -415,10 +454,23 @@ void RendererOpenGL::Init() {
exit(-1);
}
+ if (GLAD_GL_KHR_debug) {
+ glEnable(GL_DEBUG_OUTPUT);
+ glDebugMessageCallback(DebugHandler, nullptr);
+ }
+
LOG_INFO(Render_OpenGL, "GL_VERSION: %s", glGetString(GL_VERSION));
LOG_INFO(Render_OpenGL, "GL_VENDOR: %s", glGetString(GL_VENDOR));
LOG_INFO(Render_OpenGL, "GL_RENDERER: %s", glGetString(GL_RENDERER));
+ if (!GLAD_GL_VERSION_3_3) {
+ return false;
+ }
+
InitOpenGLObjects();
+
+ RefreshRasterizerSetting();
+
+ return true;
}
/// Shutdown the renderer
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index b42df7654..fe4d142a5 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -31,7 +31,7 @@ public:
void SetWindow(EmuWindow* window) override;
/// Initialize the renderer
- void Init() override;
+ bool Init() override;
/// Shutdown the renderer
void ShutDown() override;
diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp
index 59f54236b..5e8930476 100644
--- a/src/video_core/shader/shader.cpp
+++ b/src/video_core/shader/shader.cpp
@@ -14,6 +14,7 @@
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/video_core.h"
#include "shader.h"
@@ -134,16 +135,18 @@ OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attr
std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f));
}
- LOG_TRACE(Render_Software, "Output vertex: pos (%.2f, %.2f, %.2f, %.2f), quat (%.2f, %.2f, %.2f, %.2f), col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f)",
+ LOG_TRACE(Render_Software, "Output vertex: pos(%.2f, %.2f, %.2f, %.2f), quat(%.2f, %.2f, %.2f, %.2f), "
+ "col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f), view(%.2f, %.2f, %.2f)",
ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(),
ret.quat.x.ToFloat32(), ret.quat.y.ToFloat32(), ret.quat.z.ToFloat32(), ret.quat.w.ToFloat32(),
ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(),
- ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32());
+ ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32(),
+ ret.view.x.ToFloat32(), ret.view.y.ToFloat32(), ret.view.z.ToFloat32());
return ret;
}
-DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes, const Regs::ShaderConfig& config, const State::ShaderSetup& setup) {
+DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes, const Regs::ShaderConfig& config, const ShaderSetup& setup) {
UnitState<true> state;
state.program_counter = config.main_offset;
diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h
index 1c6fa592c..7af8f1fa1 100644
--- a/src/video_core/shader/shader.h
+++ b/src/video_core/shader/shader.h
@@ -37,17 +37,19 @@ struct OutputVertex {
Math::Vec4<float24> color;
Math::Vec2<float24> tc0;
Math::Vec2<float24> tc1;
- float24 pad[6];
+ INSERT_PADDING_WORDS(2);
+ Math::Vec3<float24> view;
+ INSERT_PADDING_WORDS(1);
Math::Vec2<float24> tc2;
// Padding for optimal alignment
- float24 pad2[4];
+ INSERT_PADDING_WORDS(4);
// Attributes used to store intermediate results
// position after perspective divide
Math::Vec3<float24> screenpos;
- float24 pad3;
+ INSERT_PADDING_WORDS(1);
// Linear interpolation
// factor: 0=this, 1=vtx
@@ -75,6 +77,22 @@ struct OutputVertex {
static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD");
static_assert(sizeof(OutputVertex) == 32 * sizeof(float), "OutputVertex has invalid size");
+/// Vertex shader memory
+struct ShaderSetup {
+ struct {
+ // The float uniforms are accessed by the shader JIT using SSE instructions, and are
+ // therefore required to be 16-byte aligned.
+ alignas(16) Math::Vec4<float24> f[96];
+
+ std::array<bool, 16> b;
+ std::array<Math::Vec4<u8>, 4> i;
+ } uniforms;
+
+ Math::Vec4<float24> default_attributes[16];
+
+ std::array<u32, 1024> program_code;
+ std::array<u32, 1024> swizzle_data;
+};
// Helper structure used to keep track of data useful for inspection of shader emulation
template<bool full_debugging>
@@ -258,9 +276,9 @@ struct UnitState {
struct Registers {
// The registers are accessed by the shader JIT using SSE instructions, and are therefore
// required to be 16-byte aligned.
- Math::Vec4<float24> MEMORY_ALIGNED16(input[16]);
- Math::Vec4<float24> MEMORY_ALIGNED16(output[16]);
- Math::Vec4<float24> MEMORY_ALIGNED16(temporary[16]);
+ alignas(16) Math::Vec4<float24> input[16];
+ alignas(16) Math::Vec4<float24> output[16];
+ alignas(16) Math::Vec4<float24> temporary[16];
} registers;
static_assert(std::is_pod<Registers>::value, "Structure is not POD");
@@ -345,7 +363,7 @@ OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attr
* @param setup Setup object for the shader pipeline
* @return Debug information for this shader with regards to the given vertex
*/
-DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes, const Regs::ShaderConfig& config, const State::ShaderSetup& setup);
+DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes, const Regs::ShaderConfig& config, const ShaderSetup& setup);
} // namespace Shader
diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp
index 7b0c20b74..79fcc56b9 100644
--- a/src/video_core/shader/shader_interpreter.cpp
+++ b/src/video_core/shader/shader_interpreter.cpp
@@ -7,6 +7,7 @@
#include <nihstro/shader_bytecode.h>
#include "video_core/pica.h"
+#include "video_core/pica_state.h"
#include "video_core/shader/shader.h"
#include "video_core/shader/shader_interpreter.h"
@@ -515,7 +516,8 @@ void RunInterpreter(UnitState<Debug>& state) {
case OpCode::Id::JMPU:
Record<DebugDataRecord::COND_BOOL_IN>(state.debug, iteration, uniforms.b[instr.flow_control.bool_uniform_id]);
- if (uniforms.b[instr.flow_control.bool_uniform_id]) {
+
+ if (uniforms.b[instr.flow_control.bool_uniform_id] == !(instr.flow_control.num_instructions & 1)) {
state.program_counter = instr.flow_control.dest_offset - 1;
}
break;
diff --git a/src/video_core/shader/shader_jit_x64.cpp b/src/video_core/shader/shader_jit_x64.cpp
index 00415e402..5083d7e54 100644
--- a/src/video_core/shader/shader_jit_x64.cpp
+++ b/src/video_core/shader/shader_jit_x64.cpp
@@ -11,6 +11,8 @@
#include "shader.h"
#include "shader_jit_x64.h"
+#include "video_core/pica_state.h"
+
namespace Pica {
namespace Shader {
@@ -653,7 +655,7 @@ void JitCompiler::Compile_IF(Instruction instr) {
FixupBranch b = J_CC(CC_Z, true);
// Compile the code that corresponds to the condition evaluating as true
- Compile_Block(instr.flow_control.dest_offset - 1);
+ Compile_Block(instr.flow_control.dest_offset);
// If there isn't an "ELSE" condition, we are done here
if (instr.flow_control.num_instructions == 0) {
@@ -667,7 +669,7 @@ void JitCompiler::Compile_IF(Instruction instr) {
// This code corresponds to the "ELSE" condition
// Comple the code that corresponds to the condition evaluating as false
- Compile_Block(instr.flow_control.dest_offset + instr.flow_control.num_instructions - 1);
+ Compile_Block(instr.flow_control.dest_offset + instr.flow_control.num_instructions);
SetJumpTarget(b2);
}
@@ -691,7 +693,7 @@ void JitCompiler::Compile_LOOP(Instruction instr) {
auto loop_start = GetCodePtr();
- Compile_Block(instr.flow_control.dest_offset);
+ Compile_Block(instr.flow_control.dest_offset + 1);
ADD(32, R(LOOPCOUNT_REG), R(LOOPINC)); // Increment LOOPCOUNT_REG by Z-component
SUB(32, R(LOOPCOUNT), Imm8(1)); // Increment loop count by 1
@@ -710,19 +712,21 @@ void JitCompiler::Compile_JMP(Instruction instr) {
else
UNREACHABLE();
- FixupBranch b = J_CC(CC_NZ, true);
+ bool inverted_condition = (instr.opcode.Value() == OpCode::Id::JMPU) &&
+ (instr.flow_control.num_instructions & 1);
+ FixupBranch b = J_CC(inverted_condition ? CC_Z : CC_NZ, true);
Compile_Block(instr.flow_control.dest_offset);
SetJumpTarget(b);
}
-void JitCompiler::Compile_Block(unsigned stop) {
+void JitCompiler::Compile_Block(unsigned end) {
// Save current offset pointer
unsigned* prev_offset_ptr = offset_ptr;
unsigned offset = *prev_offset_ptr;
- while (offset <= stop)
+ while (offset < end)
Compile_NextInstr(&offset);
// Restore current offset pointer
diff --git a/src/video_core/shader/shader_jit_x64.h b/src/video_core/shader/shader_jit_x64.h
index 3afbceccf..5ad2d9606 100644
--- a/src/video_core/shader/shader_jit_x64.h
+++ b/src/video_core/shader/shader_jit_x64.h
@@ -61,7 +61,7 @@ public:
void Compile_MAD(Instruction instr);
private:
- void Compile_Block(unsigned stop);
+ void Compile_Block(unsigned end);
void Compile_NextInstr(unsigned* offset);
void Compile_SwizzleSrc(Instruction instr, unsigned src_num, SourceRegister src_reg, Gen::X64Reg dest);
diff --git a/src/video_core/swrasterizer.cpp b/src/video_core/swrasterizer.cpp
new file mode 100644
index 000000000..03df15b01
--- /dev/null
+++ b/src/video_core/swrasterizer.cpp
@@ -0,0 +1,16 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "video_core/clipper.h"
+#include "video_core/swrasterizer.h"
+
+namespace VideoCore {
+
+void SWRasterizer::AddTriangle(const Pica::Shader::OutputVertex& v0,
+ const Pica::Shader::OutputVertex& v1,
+ const Pica::Shader::OutputVertex& v2) {
+ Pica::Clipper::ProcessTriangle(v0, v1, v2);
+}
+
+}
diff --git a/src/video_core/swrasterizer.h b/src/video_core/swrasterizer.h
new file mode 100644
index 000000000..9a9a76d7a
--- /dev/null
+++ b/src/video_core/swrasterizer.h
@@ -0,0 +1,26 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+#include "video_core/rasterizer_interface.h"
+
+namespace VideoCore {
+
+class SWRasterizer : public RasterizerInterface {
+ void InitObjects() override {}
+ void Reset() override {}
+ void AddTriangle(const Pica::Shader::OutputVertex& v0,
+ const Pica::Shader::OutputVertex& v1,
+ const Pica::Shader::OutputVertex& v2) override;
+ void DrawTriangles() override {}
+ void FlushFramebuffer() override {}
+ void NotifyPicaRegisterChanged(u32 id) override {}
+ void FlushRegion(PAddr addr, u32 size) override {}
+ void InvalidateRegion(PAddr addr, u32 size) override {}
+};
+
+}
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index eaddda668..ee5e50df1 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -2,7 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <memory>
+
#include "common/emu_window.h"
+#include "common/make_unique.h"
#include "common/logging/log.h"
#include "core/core.h"
@@ -18,29 +21,33 @@
namespace VideoCore {
-EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window
-RendererBase* g_renderer = nullptr; ///< Renderer plugin
+EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window
+std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
std::atomic<bool> g_hw_renderer_enabled;
std::atomic<bool> g_shader_jit_enabled;
/// Initialize the video core
-void Init(EmuWindow* emu_window) {
+bool Init(EmuWindow* emu_window) {
Pica::Init();
g_emu_window = emu_window;
- g_renderer = new RendererOpenGL();
+ g_renderer = Common::make_unique<RendererOpenGL>();
g_renderer->SetWindow(g_emu_window);
- g_renderer->Init();
-
- LOG_DEBUG(Render, "initialized OK");
+ if (g_renderer->Init()) {
+ LOG_DEBUG(Render, "initialized OK");
+ } else {
+ LOG_ERROR(Render, "initialization failed !");
+ return false;
+ }
+ return true;
}
/// Shutdown the video core
void Shutdown() {
Pica::Shutdown();
- delete g_renderer;
+ g_renderer.reset();
LOG_DEBUG(Render, "shutdown OK");
}
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h
index 2867bf03e..bca67fb8c 100644
--- a/src/video_core/video_core.h
+++ b/src/video_core/video_core.h
@@ -5,6 +5,7 @@
#pragma once
#include <atomic>
+#include <memory>
class EmuWindow;
class RendererBase;
@@ -29,8 +30,8 @@ static const int kScreenBottomHeight = 240; ///< 3DS bottom screen height
// Video core renderer
// ---------------------
-extern RendererBase* g_renderer; ///< Renderer plugin
-extern EmuWindow* g_emu_window; ///< Emu window
+extern std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
+extern EmuWindow* g_emu_window; ///< Emu window
// TODO: Wrap these in a user settings struct along with any other graphics settings (often set from qt ui)
extern std::atomic<bool> g_hw_renderer_enabled;
@@ -40,7 +41,7 @@ extern std::atomic<bool> g_shader_jit_enabled;
void Start();
/// Initialize the video core
-void Init(EmuWindow* emu_window);
+bool Init(EmuWindow* emu_window);
/// Shutdown the video core
void Shutdown();