aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-x.travis-build.sh10
-rwxr-xr-x.travis-deps.sh1
-rw-r--r--.travis-upload.sh6
-rw-r--r--.travis.yml2
-rw-r--r--CMakeLists.txt6
-rw-r--r--CONTRIBUTING.md6
-rw-r--r--Doxyfile126
-rw-r--r--README.md2
-rw-r--r--appveyor.yml12
-rw-r--r--dist/citra.ico (renamed from src/assets/citra.ico)bin509287 -> 509287 bytes
-rw-r--r--dist/doc-icon.png (renamed from doc-icon.png)bin8791 -> 8791 bytes
-rw-r--r--externals/glfw-3.0.4.bin/include/GLFW/glfw3native.h180
-rw-r--r--externals/glfw-3.0.4.bin/lib-mingw-i686/glfw3.dllbin172569 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-mingw-i686/libglfw3.abin83006 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-mingw-x86_64/glfw3.dllbin199843 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-mingw-x86_64/libglfw3.abin89300 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.dllbin43520 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.libbin123024 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3dll.libbin17748 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.dllbin48640 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.libbin180886 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3dll.libbin17418 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.dllbin43520 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.libbin123566 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3dll.libbin17748 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.dllbin48640 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.libbin180408 -> 0 bytes
-rw-r--r--externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3dll.libbin17418 -> 0 bytes
-rw-r--r--externals/glfw-3.1.1.bin/COPYING.txt (renamed from externals/glfw-3.0.4.bin/COPYING.txt)0
-rw-r--r--externals/glfw-3.1.1.bin/include/GLFW/glfw3.h (renamed from externals/glfw-3.0.4.bin/include/GLFW/glfw3.h)2014
-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.dllbin0 -> 196839 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3dll.a (renamed from externals/glfw-3.0.4.bin/lib-mingw-i686/glfw3dll.a)bin48318 -> 54834 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-i686/libglfw3.abin0 -> 89732 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3.dllbin0 -> 235754 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3dll.a (renamed from externals/glfw-3.0.4.bin/lib-mingw-x86_64/glfw3dll.a)bin47144 -> 53500 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-mingw-x86_64/libglfw3.abin0 -> 97354 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.dllbin0 -> 47104 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.libbin0 -> 150616 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3dll.libbin0 -> 19984 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.dllbin0 -> 53248 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.libbin0 -> 196774 bytes
-rw-r--r--externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3dll.libbin0 -> 19602 bytes
-rw-r--r--src/citra/citra.rc18
-rw-r--r--src/citra/config.cpp1
-rw-r--r--src/citra/resource.hbin898 -> 431 bytes
-rw-r--r--src/citra_qt/CMakeLists.txt14
-rw-r--r--src/citra_qt/bootmanager.cpp2
-rw-r--r--src/citra_qt/bootmanager.h2
-rw-r--r--src/citra_qt/citra-qt.rcbin566 -> 275 bytes
-rw-r--r--src/citra_qt/config.cpp2
-rw-r--r--src/citra_qt/debugger/callstack.cpp2
-rw-r--r--src/citra_qt/debugger/callstack.ui3
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.cpp4
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp3
-rw-r--r--src/citra_qt/main.cpp2
-rw-r--r--src/citra_qt/main.ui17
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/color.h (renamed from src/video_core/color.h)3
-rw-r--r--src/common/emu_window.cpp2
-rw-r--r--src/common/file_util.cpp2
-rw-r--r--src/common/logging/backend.cpp1
-rw-r--r--src/common/logging/log.h5
-rw-r--r--src/common/math_util.h2
-rw-r--r--src/common/swap.h2
-rw-r--r--src/common/vector_math.h (renamed from src/video_core/math.h)2
-rw-r--r--src/core/CMakeLists.txt83
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp2
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp39
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp102
-rw-r--r--src/core/arm/interpreter/arminit.cpp1
-rw-r--r--src/core/arm/interpreter/armsupp.cpp2
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/armdefs.h34
-rw-r--r--src/core/arm/skyeye_common/armemu.h47
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h1
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp18
-rw-r--r--src/core/core_timing.cpp2
-rw-r--r--src/core/core_timing.h2
-rw-r--r--src/core/file_sys/archive_extsavedata.cpp13
-rw-r--r--src/core/file_sys/archive_extsavedata.h4
-rw-r--r--src/core/file_sys/archive_savedata.cpp2
-rw-r--r--src/core/hle/function_wrappers.h17
-rw-r--r--src/core/hle/kernel/event.cpp3
-rw-r--r--src/core/hle/kernel/kernel.cpp22
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/mutex.cpp9
-rw-r--r--src/core/hle/kernel/resource_limit.h8
-rw-r--r--src/core/hle/kernel/semaphore.cpp10
-rw-r--r--src/core/hle/kernel/thread.cpp84
-rw-r--r--src/core/hle/kernel/thread.h14
-rw-r--r--src/core/hle/kernel/timer.cpp2
-rw-r--r--src/core/hle/kernel/vm_manager.cpp245
-rw-r--r--src/core/hle/kernel/vm_manager.h200
-rw-r--r--src/core/hle/service/am/am.cpp55
-rw-r--r--src/core/hle/service/am/am.h47
-rw-r--r--src/core/hle/service/am/am_app.cpp20
-rw-r--r--src/core/hle/service/am/am_app.h22
-rw-r--r--src/core/hle/service/am/am_net.cpp (renamed from src/core/hle/service/am_net.cpp)17
-rw-r--r--src/core/hle/service/am/am_net.h22
-rw-r--r--src/core/hle/service/am/am_sys.cpp22
-rw-r--r--src/core/hle/service/am/am_sys.h22
-rw-r--r--src/core/hle/service/am/am_u.cpp22
-rw-r--r--src/core/hle/service/am/am_u.h22
-rw-r--r--src/core/hle/service/am_app.cpp23
-rw-r--r--src/core/hle/service/am_app.h23
-rw-r--r--src/core/hle/service/am_net.h23
-rw-r--r--src/core/hle/service/am_sys.cpp62
-rw-r--r--src/core/hle/service/am_sys.h23
-rw-r--r--src/core/hle/service/apt/apt.cpp4
-rw-r--r--src/core/hle/service/apt/apt.h8
-rw-r--r--src/core/hle/service/boss/boss.cpp29
-rw-r--r--src/core/hle/service/boss/boss.h20
-rw-r--r--src/core/hle/service/boss/boss_p.cpp20
-rw-r--r--src/core/hle/service/boss/boss_p.h22
-rw-r--r--src/core/hle/service/boss/boss_u.cpp21
-rw-r--r--src/core/hle/service/boss/boss_u.h22
-rw-r--r--src/core/hle/service/boss_p.cpp23
-rw-r--r--src/core/hle/service/boss_p.h23
-rw-r--r--src/core/hle/service/boss_u.cpp24
-rw-r--r--src/core/hle/service/boss_u.h23
-rw-r--r--src/core/hle/service/cam/cam.cpp35
-rw-r--r--src/core/hle/service/cam/cam.h20
-rw-r--r--src/core/hle/service/cam/cam_c.cpp20
-rw-r--r--src/core/hle/service/cam/cam_c.h22
-rw-r--r--src/core/hle/service/cam/cam_q.cpp20
-rw-r--r--src/core/hle/service/cam/cam_q.h22
-rw-r--r--src/core/hle/service/cam/cam_s.cpp20
-rw-r--r--src/core/hle/service/cam/cam_s.h22
-rw-r--r--src/core/hle/service/cam/cam_u.cpp20
-rw-r--r--src/core/hle/service/cam/cam_u.h22
-rw-r--r--src/core/hle/service/cam_u.cpp23
-rw-r--r--src/core/hle/service/cam_u.h23
-rw-r--r--src/core/hle/service/cecd/cecd.cpp31
-rw-r--r--src/core/hle/service/cecd/cecd.h20
-rw-r--r--src/core/hle/service/cecd/cecd_s.cpp20
-rw-r--r--src/core/hle/service/cecd/cecd_s.h (renamed from src/core/hle/service/cecd_s.h)13
-rw-r--r--src/core/hle/service/cecd/cecd_u.cpp20
-rw-r--r--src/core/hle/service/cecd/cecd_u.h (renamed from src/core/hle/service/cecd_u.h)13
-rw-r--r--src/core/hle/service/cecd_s.cpp23
-rw-r--r--src/core/hle/service/cecd_u.cpp23
-rw-r--r--src/core/hle/service/cfg/cfg.cpp4
-rw-r--r--src/core/hle/service/frd/frd.cpp29
-rw-r--r--src/core/hle/service/frd/frd.h20
-rw-r--r--src/core/hle/service/frd/frd_a.cpp20
-rw-r--r--src/core/hle/service/frd/frd_a.h (renamed from src/core/hle/service/frd_a.h)13
-rw-r--r--src/core/hle/service/frd/frd_u.cpp (renamed from src/core/hle/service/frd_u.cpp)17
-rw-r--r--src/core/hle/service/frd/frd_u.h (renamed from src/core/hle/service/frd_u.h)13
-rw-r--r--src/core/hle/service/frd_a.cpp23
-rw-r--r--src/core/hle/service/fs/archive.cpp29
-rw-r--r--src/core/hle/service/fs/archive.h4
-rw-r--r--src/core/hle/service/fs/fs_user.cpp20
-rw-r--r--src/core/hle/service/gsp_gpu.cpp68
-rw-r--r--src/core/hle/service/hid/hid.cpp6
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp2
-rw-r--r--src/core/hle/service/hid/hid_user.h2
-rw-r--r--src/core/hle/service/news/news.cpp31
-rw-r--r--src/core/hle/service/news/news.h20
-rw-r--r--src/core/hle/service/news/news_s.cpp21
-rw-r--r--src/core/hle/service/news/news_s.h (renamed from src/core/hle/service/news_s.h)13
-rw-r--r--src/core/hle/service/news/news_u.cpp21
-rw-r--r--src/core/hle/service/news/news_u.h (renamed from src/core/hle/service/news_u.h)13
-rw-r--r--src/core/hle/service/news_s.cpp24
-rw-r--r--src/core/hle/service/news_u.cpp24
-rw-r--r--src/core/hle/service/nim/nim.cpp42
-rw-r--r--src/core/hle/service/nim/nim.h30
-rw-r--r--src/core/hle/service/nim/nim_aoc.cpp (renamed from src/core/hle/service/nim_aoc.cpp)16
-rw-r--r--src/core/hle/service/nim/nim_aoc.h22
-rw-r--r--src/core/hle/service/nim/nim_s.cpp22
-rw-r--r--src/core/hle/service/nim/nim_s.h22
-rw-r--r--src/core/hle/service/nim/nim_u.cpp27
-rw-r--r--src/core/hle/service/nim/nim_u.h22
-rw-r--r--src/core/hle/service/nim_aoc.h23
-rw-r--r--src/core/hle/service/nim_u.cpp48
-rw-r--r--src/core/hle/service/nim_u.h23
-rw-r--r--src/core/hle/service/ptm/ptm.h6
-rw-r--r--src/core/hle/service/ptm/ptm_play.cpp2
-rw-r--r--src/core/hle/service/service.cpp60
-rw-r--r--src/core/hle/service/soc_u.cpp30
-rw-r--r--src/core/hle/svc.cpp32
-rw-r--r--src/core/hw/gpu.cpp17
-rw-r--r--src/core/hw/hw.cpp2
-rw-r--r--src/core/hw/lcd.cpp2
-rw-r--r--src/core/hw/lcd.h2
-rw-r--r--src/core/loader/3dsx.cpp2
-rw-r--r--src/core/mem_map.cpp55
-rw-r--r--src/core/mem_map.h8
-rw-r--r--src/core/memory.cpp12
-rw-r--r--src/core/memory.h2
-rw-r--r--src/core/memory_setup.h7
-rw-r--r--src/core/settings.h1
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/command_processor.cpp78
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp6
-rw-r--r--src/video_core/debug_utils/debug_utils.h3
-rw-r--r--src/video_core/pica.h93
-rw-r--r--src/video_core/rasterizer.cpp80
-rw-r--r--src/video_core/renderer_opengl/generated/gl_3_2_core.c16
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp169
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shaders.h24
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp49
-rw-r--r--src/video_core/renderer_opengl/gl_state.h11
-rw-r--r--src/video_core/renderer_opengl/pica_to_gl.h31
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp10
-rw-r--r--src/video_core/vertex_shader.cpp33
210 files changed, 4512 insertions, 1964 deletions
diff --git a/.travis-build.sh b/.travis-build.sh
index 21582c68..422e1322 100755
--- a/.travis-build.sh
+++ b/.travis-build.sh
@@ -3,14 +3,20 @@
set -e
set -x
+if grep -r '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .travis* dist/*.desktop \
+ dist/*.svg dist/*.xml; then
+ echo Trailing whitespace found, aborting
+ exit 1
+fi
+
#if OS is linux or is not set
if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
mkdir build && cd build
- cmake -DUSE_QT5=OFF ..
+ cmake -DUSE_QT5=OFF ..
make -j4
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
export Qt5_DIR=$(brew --prefix)/opt/qt5
mkdir build && cd build
cmake .. -GXcode
- xcodebuild -configuration Release
+ xcodebuild -configuration Release | xcpretty -c && exit ${PIPESTATUS[0]}
fi
diff --git a/.travis-deps.sh b/.travis-deps.sh
index f8074fb9..b9561bb6 100755
--- a/.travis-deps.sh
+++ b/.travis-deps.sh
@@ -26,4 +26,5 @@ if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew tap homebrew/versions
brew install qt5 glfw3 pkgconfig
+ gem install xcpretty
fi
diff --git a/.travis-upload.sh b/.travis-upload.sh
index 4b9446a9..0904b646 100644
--- a/.travis-upload.sh
+++ b/.travis-upload.sh
@@ -6,7 +6,7 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then
REV_NAME="citra-${GITDATE}-${GITREV}-linux-amd64"
UPLOAD_DIR="/citra/nightly/linux-amd64"
mkdir "$REV_NAME"
-
+
sudo apt-get -qq install lftp
cp build/src/citra/citra "$REV_NAME"
cp build/src/citra_qt/citra-qt "$REV_NAME"
@@ -14,7 +14,7 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then
REV_NAME="citra-${GITDATE}-${GITREV}-osx-amd64"
UPLOAD_DIR="/citra/nightly/osx-amd64"
mkdir "$REV_NAME"
-
+
brew install lftp
cp build/src/citra/Release/citra "$REV_NAME"
cp -r build/src/citra_qt/Release/citra-qt.app "$REV_NAME"
@@ -22,7 +22,7 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then
# move qt libs into app bundle for deployment
$(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/citra-qt.app"
fi
-
+
ARCHIVE_NAME="${REV_NAME}.tar.xz"
tar -cJvf "$ARCHIVE_NAME" "$REV_NAME"
lftp -c "open -u citra-builds,$BUILD_PASSWORD sftp://builds.citra-emu.org; put -O '$UPLOAD_DIR' '$ARCHIVE_NAME'"
diff --git a/.travis.yml b/.travis.yml
index b878cc16..5c882a57 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ language: cpp
env:
global:
- - secure: "AXHFIafTmbGDsHD3mUVj5a4I397DQjti/WoqAJGUp2PglxTcc04BwxZ9Z+xLuf5N2Hs5r9ojAJLT8OGxJCLBDXzneQTNSqXbFuYSLbqrEAiIRlA9eRIotWCg+wYcO+5e8MKX+cHVKwiIWasUB21AtCdq6msh6Y3pUshZp212VPg="
+ - secure: "AXHFIafTmbGDsHD3mUVj5a4I397DQjti/WoqAJGUp2PglxTcc04BwxZ9Z+xLuf5N2Hs5r9ojAJLT8OGxJCLBDXzneQTNSqXbFuYSLbqrEAiIRlA9eRIotWCg+wYcO+5e8MKX+cHVKwiIWasUB21AtCdq6msh6Y3pUshZp212VPg="
before_install:
- sh .travis-deps.sh
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d958dfc3..6805ebed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,7 +45,7 @@ else()
set(CMAKE_CXX_FLAGS_RELEASE "${optimization_flags} /MP /MD" CACHE STRING "" FORCE)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE)
-
+
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG" CACHE STRING "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG" CACHE STRING "" FORCE)
endif()
@@ -114,7 +114,7 @@ if (ENABLE_GLFW)
set(TMP_TOOLSET "mingw-${TMP_ARCH}")
endif()
- set(GLFW_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/externals/glfw-3.0.4.bin")
+ set(GLFW_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/externals/glfw-3.1.1.bin")
set(GLFW_INCLUDE_DIRS "${GLFW_PREFIX}/include" CACHE PATH "Path to GLFW3 headers")
set(GLFW_LIBRARY_DIRS "${GLFW_PREFIX}/lib-${TMP_TOOLSET}" CACHE PATH "Path to GLFW3 libraries")
@@ -137,7 +137,7 @@ IF (APPLE)
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++")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
ELSEIF(MINGW)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c8c8e388..906a4bc7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -10,16 +10,16 @@ Citra is a brand new project, so we have a great opportunity to keep things clea
### Naming Rules
* Functions
- * CamelCase, "_" may also be used for clarity (e.g. ARM_InitCore)
+ * PascalCase, "_" may also be used for clarity (e.g. ARM_InitCore)
* Variables
* lower_case_underscored
* Prefix "g_" if global
* Classes
- * CamelCase, "_" may also be used for clarity (e.g. OGL_VideoInterface)
+ * PascalCase, "_" may also be used for clarity (e.g. OGL_VideoInterface)
* Files/Folders
* lower_case_underscored
* Namespaces
- * CamelCase, "_" may also be used for clarity (e.g. ARM_InitCore)
+ * PascalCase, "_" may also be used for clarity (e.g. ARM_InitCore)
### Indentation/Whitespace Style
Follow the indentation/whitespace style shown below. Do not use tabs, use 4-spaces instead.
diff --git a/Doxyfile b/Doxyfile
index 5c2e0924..6ddf2cf2 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Citra
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER =
+PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -51,7 +51,7 @@ PROJECT_BRIEF = "Nintendo 3DS emulator/debugger"
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
# to the output directory.
-PROJECT_LOGO = doc-icon.png
+PROJECT_LOGO = dist/doc-icon.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
@@ -162,7 +162,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-STRIP_FROM_PATH =
+STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -171,7 +171,7 @@ STRIP_FROM_PATH =
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@@ -238,13 +238,13 @@ TAB_SIZE = 4
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
-ALIASES =
+ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
-TCL_SUBST =
+TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
@@ -291,7 +291,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
-EXTENSION_MAPPING =
+EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
@@ -627,7 +627,7 @@ GENERATE_DEPRECATEDLIST= YES
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
@@ -669,7 +669,7 @@ SHOW_NAMESPACES = YES
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
-FILE_VERSION_FILTER =
+FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
@@ -682,7 +682,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
-LAYOUT_FILE =
+LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
@@ -692,7 +692,7 @@ LAYOUT_FILE =
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
-CITE_BIB_FILES =
+CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
@@ -751,7 +751,7 @@ WARN_FORMAT = "$file:$line: $text"
# messages should be written. If left blank the output is written to standard
# error (stderr).
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
@@ -807,7 +807,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE =
+EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -823,7 +823,7 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -834,13 +834,13 @@ EXCLUDE_PATTERNS =
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
-EXAMPLE_PATH =
+EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -860,7 +860,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
-IMAGE_PATH =
+IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -877,7 +877,7 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
-INPUT_FILTER =
+INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
@@ -886,7 +886,7 @@ INPUT_FILTER =
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
-FILTER_PATTERNS =
+FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER ) will also be used to filter the input files that are used for
@@ -901,14 +901,14 @@ FILTER_SOURCE_FILES = NO
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
-FILTER_SOURCE_PATTERNS =
+FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
-USE_MDFILE_AS_MAINPAGE =
+USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
@@ -1013,7 +1013,7 @@ CLANG_ASSISTED_PARSING = NO
# specified with INPUT and INCLUDE_PATH.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-CLANG_OPTIONS =
+CLANG_OPTIONS =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
@@ -1039,7 +1039,7 @@ COLS_IN_ALPHA_INDEX = 5
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-IGNORE_PREFIX =
+IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
@@ -1083,7 +1083,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_HEADER =
+HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1093,7 +1093,7 @@ HTML_HEADER =
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FOOTER =
+HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1105,7 +1105,7 @@ HTML_FOOTER =
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_STYLESHEET =
+HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
@@ -1118,7 +1118,7 @@ HTML_STYLESHEET =
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@@ -1128,7 +1128,7 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_FILES =
+HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the stylesheet and background images according to
@@ -1256,7 +1256,7 @@ GENERATE_HTMLHELP = NO
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_FILE =
+CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
@@ -1264,7 +1264,7 @@ CHM_FILE =
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-HHC_LOCATION =
+HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated (
# YES) or that it should be included in the master .chm file ( NO).
@@ -1277,7 +1277,7 @@ GENERATE_CHI = NO
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_INDEX_ENCODING =
+CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated (
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
@@ -1308,7 +1308,7 @@ GENERATE_QHP = NO
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QCH_FILE =
+QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
@@ -1333,7 +1333,7 @@ QHP_VIRTUAL_FOLDER = doc
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
@@ -1341,21 +1341,21 @@ QHP_CUST_FILTER_NAME =
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_ATTRS =
+QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_SECT_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHG_LOCATION =
+QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
@@ -1488,7 +1488,7 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_EXTENSIONS =
+MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
@@ -1496,7 +1496,7 @@ MATHJAX_EXTENSIONS =
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_CODEFILE =
+MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
@@ -1556,7 +1556,7 @@ EXTERNAL_SEARCH = NO
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
-SEARCHENGINE_URL =
+SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
@@ -1572,7 +1572,7 @@ SEARCHDATA_FILE = searchdata.xml
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTERNAL_SEARCH_ID =
+EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
@@ -1582,7 +1582,7 @@ EXTERNAL_SEARCH_ID =
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTRA_SEARCH_MAPPINGS =
+EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
@@ -1643,7 +1643,7 @@ PAPER_TYPE = a4
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-EXTRA_PACKAGES =
+EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
@@ -1659,7 +1659,7 @@ EXTRA_PACKAGES =
# HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_HEADER =
+LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
@@ -1670,7 +1670,7 @@ LATEX_HEADER =
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_FOOTER =
+LATEX_FOOTER =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
@@ -1678,7 +1678,7 @@ LATEX_FOOTER =
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_EXTRA_FILES =
+LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
@@ -1778,14 +1778,14 @@ RTF_HYPERLINKS = NO
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_STYLESHEET_FILE =
+RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Configuration options related to the man page output
@@ -1820,7 +1820,7 @@ MAN_EXTENSION = .3
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
-MAN_SUBDIR =
+MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
@@ -1933,7 +1933,7 @@ PERLMOD_PRETTY = YES
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
@@ -1974,7 +1974,7 @@ SEARCH_INCLUDES = YES
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
-INCLUDE_PATH =
+INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -1982,7 +1982,7 @@ INCLUDE_PATH =
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
@@ -1992,7 +1992,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-PREDEFINED =
+PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@@ -2001,7 +2001,7 @@ PREDEFINED =
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
@@ -2030,13 +2030,13 @@ SKIP_FUNCTION_MACROS = YES
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
-TAGFILES =
+TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
# class index. If set to NO only the inherited external classes will be listed.
@@ -2084,14 +2084,14 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
-MSCGEN_PATH =
+MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
-DIA_PATH =
+DIA_PATH =
# If set to YES, the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
@@ -2140,7 +2140,7 @@ DOT_FONTSIZE = 10
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTPATH =
+DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
@@ -2278,26 +2278,26 @@ INTERACTIVE_SVG = NO
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH =
+DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
-DOTFILE_DIRS =
+DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
-MSCFILE_DIRS =
+MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
-DIAFILE_DIRS =
+DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
@@ -2306,7 +2306,7 @@ DIAFILE_DIRS =
# will not generate output for the diagram.
# This tag requires that the tag HAVE_DOT is set to YES.
-PLANTUML_JAR_PATH =
+PLANTUML_JAR_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
diff --git a/README.md b/README.md
index f420beb0..71d19784 100644
--- a/README.md
+++ b/README.md
@@ -28,5 +28,5 @@ If you like, you can [donate by PayPal](https://www.paypal.com/cgi-bin/webscr?cm
* Infrastructure setup
* Eventually 3D displays to get proper 3D output working
* ... etc ...
-
+
We also more than gladly accept used 3DS consoles, preferrably ones with firmware 4.5 or lower! If you would like to give yours away, don't hesitate to join our IRC channel #citra on [Freenode](http://webchat.freenode.net/?channels=citra) and talk to neobrain or bunnei. Mind you, IRC is slow-paced, so it might be a while until people reply. If you're in a hurry you can just leave contact details in the channel or via private message and we'll get back to you.
diff --git a/appveyor.yml b/appveyor.yml
index f2b65672..aef2d6f7 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -33,18 +33,22 @@ after_build:
$GITREV = $(git show -s --format='%h')
# Where are these spaces coming from? Regardless, let's remove them
$BUILD_NAME = "citra-${GITDATE}-${GITREV}-windows-amd64.7z" -replace " ",""
+ $BUILD_NAME_NOQT = "citra-noqt-${GITDATE}-${GITREV}-windows-amd64.7z" -replace " ",""
# Zip up the build folder
7z a $BUILD_NAME .\build\bin\release\*
-
+ # Do a second archive with only the binaries
+ 7z a $BUILD_NAME_NOQT .\build\bin\release\*.exe
+
# Download winscp
- Invoke-WebRequest "http://hivelocity.dl.sourceforge.net/project/winscp/WinSCP/5.7/winscp570.zip" -OutFile "winscp570.zip"
- 7z e -y winscp570.zip
-
+ Invoke-WebRequest "http://iweb.dl.sourceforge.net/project/winscp/WinSCP/5.7.3/winscp573.zip" -OutFile "winscp573.zip"
+ 7z e -y winscp573.zip
+
# Upload to server
.\WinSCP.com /command `
"option batch abort" `
"option confirm off" `
"open sftp://citra-builds:${env:BUILD_PASSWORD}@builds.citra-emu.org -hostkey=*" `
"put $BUILD_NAME /citra/nightly/windows-amd64/" `
+ "put $BUILD_NAME_NOQT /citra/nightly/windows-noqt-amd64/" `
"exit"
}
diff --git a/src/assets/citra.ico b/dist/citra.ico
index 4fef651e..4fef651e 100644
--- a/src/assets/citra.ico
+++ b/dist/citra.ico
Binary files differ
diff --git a/doc-icon.png b/dist/doc-icon.png
index 420b1546..420b1546 100644
--- a/doc-icon.png
+++ b/dist/doc-icon.png
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/include/GLFW/glfw3native.h b/externals/glfw-3.0.4.bin/include/GLFW/glfw3native.h
deleted file mode 100644
index d570f587..00000000
--- a/externals/glfw-3.0.4.bin/include/GLFW/glfw3native.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*************************************************************************
- * GLFW 3.0 - 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 API, you assert that you know what you're doing and
- * how to fix problems caused by using it. If you don't, you shouldn't be
- * using it.**
- *
- * Before the inclusion of @ref glfw3native.h, you must define exactly one
- * window API macro and exactly one context 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)
- #include <windows.h>
-#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
- #if defined(__OBJC__)
- #import <Cocoa/Cocoa.h>
- #else
- typedef void* id;
- #endif
-#elif defined(GLFW_EXPOSE_NATIVE_X11)
- #include <X11/Xlib.h>
-#else
- #error "No window API specified"
-#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 specified"
-#endif
-
-
-/*************************************************************************
- * Functions
- *************************************************************************/
-
-#if defined(GLFW_EXPOSE_NATIVE_WIN32)
-/*! @brief Returns the `HWND` of the specified window.
- * @return The `HWND` of the specified window.
- * @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.
- * @ingroup native
- */
-GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
-#endif
-
-#if defined(GLFW_EXPOSE_NATIVE_COCOA)
-/*! @brief Returns the `NSWindow` of the specified window.
- * @return The `NSWindow` of the specified window.
- * @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.
- * @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.
- * @ingroup native
- */
-GLFWAPI Display* glfwGetX11Display(void);
-/*! @brief Returns the `Window` of the specified window.
- * @return The `Window` of the specified window.
- * @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.
- * @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.
- * @ingroup native
- */
-GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
-/*! @brief Returns the `EGLContext` of the specified window.
- * @return The `EGLContext` of the specified window.
- * @ingroup native
- */
-GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
-/*! @brief Returns the `EGLSurface` of the specified window.
- * @return The `EGLSurface` of the specified window.
- * @ingroup native
- */
-GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _glfw3_native_h_ */
-
diff --git a/externals/glfw-3.0.4.bin/lib-mingw-i686/glfw3.dll b/externals/glfw-3.0.4.bin/lib-mingw-i686/glfw3.dll
deleted file mode 100644
index 5941d1a0..00000000
--- a/externals/glfw-3.0.4.bin/lib-mingw-i686/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-mingw-i686/libglfw3.a b/externals/glfw-3.0.4.bin/lib-mingw-i686/libglfw3.a
deleted file mode 100644
index 7138ee9b..00000000
--- a/externals/glfw-3.0.4.bin/lib-mingw-i686/libglfw3.a
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-mingw-x86_64/glfw3.dll b/externals/glfw-3.0.4.bin/lib-mingw-x86_64/glfw3.dll
deleted file mode 100644
index 49cf94a8..00000000
--- a/externals/glfw-3.0.4.bin/lib-mingw-x86_64/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-mingw-x86_64/libglfw3.a b/externals/glfw-3.0.4.bin/lib-mingw-x86_64/libglfw3.a
deleted file mode 100644
index d1ca9a42..00000000
--- a/externals/glfw-3.0.4.bin/lib-mingw-x86_64/libglfw3.a
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.dll b/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.dll
deleted file mode 100644
index d66c5dd8..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.lib b/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.lib
deleted file mode 100644
index 2f972ab1..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3dll.lib b/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3dll.lib
deleted file mode 100644
index 365cdbaf..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v110-Win32/glfw3dll.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.dll b/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.dll
deleted file mode 100644
index 44e6d49e..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.lib b/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.lib
deleted file mode 100644
index 77757999..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3dll.lib b/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3dll.lib
deleted file mode 100644
index 20b54840..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v110-x64/glfw3dll.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.dll b/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.dll
deleted file mode 100644
index e15fc43b..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.lib b/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.lib
deleted file mode 100644
index 071a0ab8..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3dll.lib b/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3dll.lib
deleted file mode 100644
index d0c5ff5e..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v120-Win32/glfw3dll.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.dll b/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.dll
deleted file mode 100644
index 9da042a6..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.dll
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.lib b/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.lib
deleted file mode 100644
index e2b495ff..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3dll.lib b/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3dll.lib
deleted file mode 100644
index 3d6e8641..00000000
--- a/externals/glfw-3.0.4.bin/lib-msvc_v120-x64/glfw3dll.lib
+++ /dev/null
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/COPYING.txt b/externals/glfw-3.1.1.bin/COPYING.txt
index b30c7015..b30c7015 100644
--- a/externals/glfw-3.0.4.bin/COPYING.txt
+++ b/externals/glfw-3.1.1.bin/COPYING.txt
diff --git a/externals/glfw-3.0.4.bin/include/GLFW/glfw3.h b/externals/glfw-3.1.1.bin/include/GLFW/glfw3.h
index 0f97738c..009fa755 100644
--- a/externals/glfw-3.0.4.bin/include/GLFW/glfw3.h
+++ b/externals/glfw-3.1.1.bin/include/GLFW/glfw3.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * GLFW 3.0 - www.glfw.org
+ * GLFW 3.1 - www.glfw.org
* A library for OpenGL, window and input
*------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard
@@ -38,23 +38,27 @@ extern "C" {
* Doxygen documentation
*************************************************************************/
-/*! @defgroup clipboard Clipboard support
- */
/*! @defgroup context Context handling
+ *
+ * This is the reference documentation for context related functions. For more
+ * information, see the @ref context.
*/
-/*! @defgroup error Error handling
- */
-/*! @defgroup init Initialization and version information
+/*! @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 time Time input
- */
/*! @defgroup window Window handling
*
* This is the reference documentation for window related functions and types,
@@ -64,28 +68,17 @@ extern "C" {
/*************************************************************************
- * Global definitions
+ * Compiler- and platform-specific preprocessor work
*************************************************************************/
-/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
-
-/* Please report any problems that you find with your compiler, which may
- * be solved in this section! There are several compilers that I have not
- * been able to test this file with yet.
- *
- * First: If we are we on Windows, we want a single define for it (_WIN32)
- * (Note: For Cygwin the compiler flag -mwin32 should be used, but to
- * make sure that things run smoothly for Cygwin users, we add __CYGWIN__
- * to the list of "valid Win32 identifiers", which removes the need for
- * -mwin32)
+/* If we are we on Windows, we want a single define for it.
*/
-#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__))
+#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
#define _WIN32
#endif /* _WIN32 */
-/* In order for extension support to be portable, we need to define an
- * OpenGL function call method. We use the keyword APIENTRY, which is
- * defined for Win32. (Note: Windows also needs this for <GL/gl.h>)
+/* 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
@@ -95,44 +88,23 @@ extern "C" {
#endif
#endif /* APIENTRY */
-/* The following three defines are here solely to make some Windows-based
- * <GL/gl.h> files happy. Theoretically we could include <windows.h>, but
- * it has the major drawback of severely polluting our namespace.
+/* Some Windows OpenGL headers need this.
*/
-
-/* Under Windows, we need WINGDIAPI defined */
#if !defined(WINGDIAPI) && defined(_WIN32)
- #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)
- /* Microsoft Visual C++, Borland C++ Builder and Pelles C */
- #define WINGDIAPI __declspec(dllimport)
- #elif defined(__LCC__)
- /* LCC-Win32 */
- #define WINGDIAPI __stdcall
- #else
- /* Others (e.g. MinGW, Cygwin) */
- #define WINGDIAPI extern
- #endif
+ #define WINGDIAPI __declspec(dllimport)
#define GLFW_WINGDIAPI_DEFINED
#endif /* WINGDIAPI */
-/* Some <GL/glu.h> files also need CALLBACK defined */
+/* Some Windows GLU headers need this.
+ */
#if !defined(CALLBACK) && defined(_WIN32)
- #if defined(_MSC_VER)
- /* Microsoft Visual C++ */
- #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
- #define CALLBACK __stdcall
- #else
- #define CALLBACK
- #endif
- #else
- /* Other Windows compilers */
- #define CALLBACK __stdcall
- #endif
+ #define CALLBACK __stdcall
#define GLFW_CALLBACK_DEFINED
#endif /* CALLBACK */
-/* Most GL/glu.h variants on Windows need wchar_t
- * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */
+/* 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
@@ -140,67 +112,79 @@ extern "C" {
/* Include the chosen client API headers.
*/
#if defined(__APPLE_CC__)
- #if defined(GLFW_INCLUDE_GLCOREARB)
- #include <OpenGL/gl3.h>
- #elif !defined(GLFW_INCLUDE_NONE)
- #define GL_GLEXT_LEGACY
- #include <OpenGL/gl.h>
+ #if defined(GLFW_INCLUDE_GLCOREARB)
+ #include <OpenGL/gl3.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <OpenGL/gl3ext.h>
#endif
- #if defined(GLFW_INCLUDE_GLU)
- #include <OpenGL/glu.h>
+ #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>
- #elif defined(GLFW_INCLUDE_ES2)
- #include <GLES2/gl2.h>
- #elif defined(GLFW_INCLUDE_ES3)
- #include <GLES3/gl3.h>
- #elif !defined(GLFW_INCLUDE_NONE)
- #include <GL/gl.h>
+ #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
- #if defined(GLFW_INCLUDE_GLU)
- #include <GL/glu.h>
+ #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 is defined by users of GLFW when compiling programs that will link
- * to 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.
+ /* 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 must not have both GLFW_DLL and _GLFW_BUILD_DLL defined"
+ #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 a Win32 DLL */
+ /* We are building GLFW as a Win32 DLL */
#define GLFWAPI __declspec(dllexport)
-
#elif defined(_WIN32) && defined(GLFW_DLL)
-
- /* We are calling a Win32 DLL */
- #if defined(__LCC__)
- #define GLFWAPI extern
- #else
- #define GLFWAPI __declspec(dllimport)
- #endif
-
+ /* 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 either building/calling a static lib or we are non-win32 */
+ /* We are building or calling GLFW as a static library */
#define GLFWAPI
-
#endif
-/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
-
/*************************************************************************
* GLFW API tokens
@@ -220,27 +204,36 @@ extern "C" {
* backward-compatible.
* @ingroup init
*/
-#define GLFW_VERSION_MINOR 0
+#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 4
+#define GLFW_VERSION_REVISION 1
/*! @} */
/*! @name Key and button actions
* @{ */
-/*! @brief The key or button was released.
+/*! @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 button was pressed.
+/*! @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
@@ -248,20 +241,22 @@ extern "C" {
/*! @defgroup keys Keyboard keys
*
- * 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.)
+ * 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
* @{
@@ -398,6 +393,9 @@ extern "C" {
/*! @} */
/*! @defgroup mods Modifier key flags
+ *
+ * See [key input](@ref input_key) for how these are used.
+ *
* @ingroup input
* @{ */
@@ -417,6 +415,9 @@ extern "C" {
/*! @} */
/*! @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
@@ -434,6 +435,9 @@ extern "C" {
/*! @} */
/*! @defgroup joysticks Joysticks
+ *
+ * See [joystick input](@ref joystick) for how these are used.
+ *
* @ingroup input
* @{ */
#define GLFW_JOYSTICK_1 0
@@ -456,36 +460,131 @@ extern "C" {
/*! @} */
/*! @defgroup errors Error codes
- * @ingroup error
+ *
+ * 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 enum parameters for the function was given an invalid
- * enum.
+/*! @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 parameters for the function was given an invalid value.
+/*! @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 client API version is not available.
+/*! @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 clipboard did not contain data in the requested format.
+/*! @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
/*! @} */
@@ -495,6 +594,8 @@ extern "C" {
#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
@@ -511,6 +612,7 @@ extern "C" {
#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
@@ -520,6 +622,7 @@ extern "C" {
#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
@@ -540,9 +643,54 @@ extern "C" {
#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
@@ -573,6 +721,14 @@ typedef struct GLFWmonitor GLFWmonitor;
*/
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.
@@ -582,7 +738,7 @@ typedef struct GLFWwindow GLFWwindow;
*
* @sa glfwSetErrorCallback
*
- * @ingroup error
+ * @ingroup init
*/
typedef void (* GLFWerrorfun)(int,const char*);
@@ -590,7 +746,7 @@ typedef void (* GLFWerrorfun)(int,const char*);
*
* This is the function signature for window position callback functions.
*
- * @param[in] window The window that the user moved.
+ * @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
@@ -606,7 +762,7 @@ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);
*
* This is the function signature for window size callback functions.
*
- * @param[in] window The window that the user resized.
+ * @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.
*
@@ -644,9 +800,9 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
*
* This is the function signature for window focus callback functions.
*
- * @param[in] window The window that was focused or defocused.
- * @param[in] focused `GL_TRUE` if the window was focused, or `GL_FALSE` if
- * it was defocused.
+ * @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
*
@@ -750,7 +906,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
* @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 @ref GLFW_PRESS, @ref GLFW_RELEASE or @ref GLFW_REPEAT.
+ * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
* @param[in] mods Bit field describing which [modifier keys](@ref mods) were
* held down.
*
@@ -773,6 +929,38 @@ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);
*/
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.
@@ -838,6 +1026,21 @@ typedef struct GLFWgammaramp
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
@@ -846,53 +1049,70 @@ typedef struct GLFWgammaramp
/*! @brief Initializes the GLFW library.
*
* This function initializes the GLFW library. Before most GLFW functions can
- * be used, GLFW must be initialized, and before a program terminates GLFW
+ * 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 program exits.
+ * succeeds, you should call @ref glfwTerminate before the application exits.
*
* Additional calls to this function after successful initialization but before
- * termination will succeed but will do nothing.
+ * termination will return `GL_TRUE` immediately.
*
- * @return `GL_TRUE` if successful, or `GL_FALSE` if an error occurred.
+ * @return `GL_TRUE` if successful, or `GL_FALSE` if an
+ * [error](@ref error_handling) occurred.
*
- * @par New in GLFW 3
- * This function no longer registers @ref glfwTerminate with `atexit`.
+ * @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).
*
- * @note This function may only be called from the main thread.
+ * @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.
*
- * @note **OS X:** This function will change the current directory of the
- * application to the `Contents/Resources` subdirectory of the application's
- * bundle, if present.
+ * @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, frees any allocated resources
- * and sets the library to an uninitialized state. Once this is called, you
- * must again call @ref glfwInit successfully before you will be able to use
- * most GLFW functions.
+ * 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 program exits. If initialization fails, there is no need to call
- * this function, as it is called by @ref glfwInit before it returns failure.
+ * 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.
*
- * @note This function may only be called from the main thread.
- *
* @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);
@@ -903,46 +1123,55 @@ GLFWAPI void glfwTerminate(void);
* 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.
*
- * @remarks This function may be called from any thread.
+ * @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 a static string generated at compile-time according to
- * which configuration macros were defined. This is intended for use when
- * submitting bug reports, to allow developers to see which code paths are
- * enabled in a binary.
- *
- * The format of the string is as follows:
- * - The version of GLFW
- * - The name of the window system API
- * - The name of the context creation API
- * - Any additional options or APIs
+ * 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.
*
- * For example, when compiling GLFW 3.0 with MinGW using the Win32 and WGL
- * back ends, the version string may look something like this:
+ * __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.
*
- * 3.0.0 Win32 WGL MinGW
+ * This function always succeeds.
*
* @return The GLFW version string.
*
* @remarks This function may be called before @ref glfwInit.
*
- * @remarks This function may be called from any thread.
+ * @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);
@@ -952,23 +1181,31 @@ GLFWAPI const char* glfwGetVersionString(void);
* 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 or an
- * error occurred.
+ * @return The previously set callback, or `NULL` if no callback was set.
*
* @remarks This function may be called before @ref glfwInit.
*
- * @note The error callback is called by the thread where the error was
- * generated. If you are using GLFW from multiple threads, your error callback
- * needs to be written accordingly.
+ * @par Thread Safety
+ * This function may only be called from the main thread.
+ *
+ * @sa @ref error_handling
*
- * @note Because the description string provided to the callback 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 that, you need
- * to make your own copy of it before returning.
+ * @since Added in GLFW 3.0.
*
- * @ingroup error
+ * @ingroup init
*/
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);
@@ -977,19 +1214,25 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);
* This function returns an array of handles for all currently connected
* monitors.
*
- * @param[out] count Where to store the size of the returned array. This is
- * set to zero if an error occurred.
- * @return An array of monitor handles, or `NULL` if an error occurred.
+ * @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.
*
- * @note The returned array is allocated and freed by GLFW. You should not
- * free it yourself.
+ * @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.
*
- * @note The returned array is valid only until the monitor configuration
- * changes. See @ref glfwSetMonitorCallback to receive notifications of
- * configuration changes.
+ * @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);
@@ -999,10 +1242,17 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);
* 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 occurred.
+ * @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);
@@ -1012,10 +1262,20 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);
* 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);
@@ -1025,31 +1285,55 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
* 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] width Where to store the width, in mm, of the monitor's display
- * area, or `NULL`.
- * @param[out] height Where to store the height, in mm, of the monitor's
- * display area, or `NULL`.
+ * @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`.
*
- * @note Some operating systems do not provide accurate information, either
- * because the monitor's EDID data is incorrect, or because the driver does not
- * report it accurately.
+ * @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* width, int* height);
+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.
+ * 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
- * occurred.
+ * @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
*
- * @note The returned string is allocated and freed by GLFW. You should not
- * free it yourself.
+ * @since Added in GLFW 3.0.
*
* @ingroup monitor
*/
@@ -1063,12 +1347,19 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
*
* @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.
+ * @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
+ * @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);
@@ -1083,16 +1374,25 @@ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun);
* @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 occurred.
+ * @return An array of video modes, or `NULL` if an
+ * [error](@ref error_handling) occurred.
*
- * @note The returned array is allocated and freed by GLFW. You should not
- * free it yourself.
+ * @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.
*
- * @note The returned array is valid only until this function is called again
- * for the specified monitor.
+ * @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);
@@ -1100,17 +1400,26 @@ 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 are using a full screen window, the return value will therefore depend
- * on whether it is focused.
+ * 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 occurred.
+ * @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.
*
- * @note The returned struct is allocated and freed by GLFW. You should not
- * free it yourself.
+ * @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);
@@ -1118,24 +1427,43 @@ 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.
+ * 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 Retrieves the current gamma ramp for the specified monitor.
+/*! @brief Returns the current gamma ramp for the specified monitor.
*
- * This function retrieves the current gamma ramp of 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 occurred.
+ * @return The current gamma ramp, or `NULL` if an
+ * [error](@ref error_handling) occurred.
*
- * @note The value arrays of the returned ramp are allocated and freed by GLFW.
- * You should not free them yourself.
+ * @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
*/
@@ -1143,12 +1471,27 @@ 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.
+ * 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.
*
- * @note Gamma ramp sizes other than 256 are not supported by all hardware.
+ * @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
*/
@@ -1159,10 +1502,14 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);
* This function resets all window hints to their
* [default values](@ref window_hints_values).
*
- * @note This function may only be called from the main thread.
+ * @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);
@@ -1172,51 +1519,69 @@ GLFWAPI void glfwDefaultWindowHints(void);
* 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 with @ref glfwTerminate.
+ * terminated.
*
* @param[in] target The [window hint](@ref window_hints) to set.
* @param[in] hint The new value of the window hint.
*
- * @par New in GLFW 3
- * Hints are no longer reset to their default values on window creation. To
- * set default hint values, use @ref glfwDefaultWindowHints.
- *
- * @note This function may only be called from the main thread.
+ * @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 context. Most of the
- * options controlling how the window and its context should be created are
- * specified through @ref glfwWindowHint.
+ * 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 using @ref
- * glfwMakeContextCurrent.
+ * 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.
*
- * Note that the created window and context may differ from what you requested,
- * as not all parameters and hints are
+ * 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 retrieve the actual
- * attributes of the created window and context, use queries like @ref
+ * 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 to use. 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 retrieve monitors, see
- * @ref monitor_monitors.
+ * 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.
*
- * To create the window at a specific position, make it initially invisible
- * using the `GLFW_VISIBLE` window hint, set its position and then show it.
+ * 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.
*
- * If a full screen window is active, the screensaver is prohibited from
- * starting.
+ * 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.
@@ -1227,32 +1592,54 @@ GLFWAPI void glfwWindowHint(int target, int hint);
* 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 occurred.
+ * @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
+ * @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
+ * @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 **OS X:** The GLFW window has no icon, as it is not a document
+ * @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.
- * Also, the first time a window is opened the menu bar is populated with
- * common commands like Hide, Quit and About. The (minimal) about dialog uses
- * information from the application's bundle. For more information on bundles,
- * see the Bundle Programming Guide provided by Apple.
+ * 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 **X11:** There is no mechanism for setting the window icon yet.
+ * @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 The swap interval is not set during window creation, but is left at
- * the default value for that platform. For more information, see @ref
- * glfwSwapInterval.
+ * @remarks __X11:__ There is no mechanism for setting the window icon yet.
*
- * @note This function may only be called from the main thread.
+ * @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);
@@ -1262,19 +1649,25 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, G
* This function destroys the specified window and its context. On calling
* this function, no further callbacks will be called for that window.
*
- * @param[in] window The window to destroy.
+ * If the context of the specified window is current on the main thread, it is
+ * detached before being destroyed.
*
- * @note This function may only be called from the main thread.
+ * @param[in] window The window to destroy.
*
- * @note This function may not be called from a callback.
+ * @note The context of the specified window must not be current on any other
+ * thread when this function is called.
*
- * @note If the window's context is current on the main thread, it is
- * detached before being destroyed.
+ * @par Reentrancy
+ * This function may not be called from a callback.
*
- * @warning The window's context must not be current on any other thread.
+ * @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);
@@ -1286,7 +1679,12 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* window);
* @param[in] window The window to query.
* @return The value of the close flag.
*
- * @remarks This function may be called from secondary threads.
+ * @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
*/
@@ -1301,7 +1699,12 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* window);
* @param[in] window The window whose flag to change.
* @param[in] value The new value.
*
- * @remarks This function may be called from secondary threads.
+ * @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
*/
@@ -1315,7 +1718,15 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
* @param[in] window The window whose title to change.
* @param[in] title The UTF-8 encoded window title.
*
- * @note This function may only be called from the main thread.
+ * @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
*/
@@ -1326,14 +1737,23 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
* 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);
@@ -1341,26 +1761,29 @@ 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 window.
+ * corner of the client area of the specified windowed mode window. If the
+ * window is a full screen window, this function does nothing.
*
- * If the specified 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.
*
- * If you wish to set an initial window position you should create a hidden
- * window (using @ref glfwWindowHint and `GLFW_VISIBLE`), set its position and
- * then show it.
+ * 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.
*
- * @note It is very rarely a good idea to move an already visible window, as it
- * will confuse and annoy the user.
+ * @par Thread Safety
+ * This function may only be called from the main thread.
*
- * @note This function may only be called from the main thread.
+ * @sa @ref window_pos
+ * @sa glfwGetWindowPos
*
- * @note The window manager may put limits on what positions are allowed.
+ * @since Added in GLFW 1.0.
*
- * @sa glfwGetWindowPos
+ * @par
+ * __GLFW 3:__ Added window handle parameter.
*
* @ingroup window
*/
@@ -1370,7 +1793,10 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
*
* 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 in pixels, see @ref glfwGetFramebufferSize.
+ * 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
@@ -1378,8 +1804,17 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
* @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);
@@ -1394,16 +1829,24 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
* 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.
*
- * @note This function may only be called from the main thread.
- *
- * @note The window manager may put limits on what window sizes are allowed.
+ * @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);
@@ -1414,80 +1857,149 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height);
* 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 it is a full screen window, the original monitor resolution is
- * restored until the window is restored. If the window is already iconified,
- * this function does nothing.
+ * 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.
*
- * @note This function may only be called from the main thread.
+ * @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 it is a full screen window, the resolution chosen
- * for the window is restored on the selected monitor. If the window is
- * already restored, this function does nothing.
+ * 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.
*
- * @note This function may only be called from the main thread.
+ * @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
+ * 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.
*
- * @note This function may only be called from the main thread.
+ * @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
+ * 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.
*
- * @note This function may only be called from the main thread.
+ * @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);
@@ -1498,7 +2010,15 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
* in full screen on.
*
* @param[in] window The window to query.
- * @return The monitor, or `NULL` if the window is in windowed mode.
+ * @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
*/
@@ -1506,13 +2026,22 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
/*! @brief Returns an attribute of the specified window.
*
- * This function returns an attribute of the specified window. There are many
- * attributes, some related to the window and others to its context.
+ * 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 occurred.
+ * @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
*/
@@ -1527,8 +2056,14 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* @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);
@@ -1540,8 +2075,14 @@ GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer);
*
* @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);
@@ -1555,8 +2096,15 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* 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 an
- * error occurred.
+ * @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
*/
@@ -1571,8 +2119,18 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow
* @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.
+ * @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
*/
@@ -1592,15 +2150,22 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
* @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.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
*
- * @par New in GLFW 3
- * The close callback no longer returns a value.
- *
- * @remarks **OS X:** Selecting Quit from the application menu will
+ * @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);
@@ -1618,12 +2183,18 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi
* @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.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
*
- * @note 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.
+ * @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
*/
@@ -1632,18 +2203,25 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GL
/*! @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 focus.
+ * called when the window gains or loses input focus.
*
- * After the focus callback is called for a window that lost 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.
+ * 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 an
- * error occurred.
+ * @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
*/
@@ -1657,8 +2235,15 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
* @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.
+ * @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
*/
@@ -1672,8 +2257,15 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GL
* @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.
+ * @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
*/
@@ -1681,114 +2273,164 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window
/*! @brief Processes all pending events.
*
- * This function processes only those events that have already been received
- * and then returns immediately. Processing events will cause the window and
- * input callbacks associated with those events to be called.
- *
- * This function is not required for joystick input to work.
+ * 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.
*
- * @par New in GLFW 3
- * This function is no longer called by @ref glfwSwapBuffers. You need to call
- * it or @ref glfwWaitEvents yourself.
+ * 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.
*
- * @remarks 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 GLFWwindowrefreshfun) to redraw the contents
- * of your window when necessary during the operation.
+ * 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.
*
- * @note This function may only be called from the main thread.
+ * Event processing is not required for joystick input to work.
*
- * @note This function may not be called from a callback.
+ * @par Reentrancy
+ * This function may not be called from a callback.
*
- * @note On some platforms, certain callbacks may be called outside of a call
- * to one of the event processing functions.
+ * @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 pending and processes them.
+/*! @brief Waits until events are queued and processes them.
*
- * This function puts the calling thread to sleep until at least one event has
- * been received. Once one or more events have been received, it behaves as if
- * @ref glfwPollEvents was called, i.e. the events are processed and the
- * function then returns immediately. Processing events will cause the window
- * and input callbacks associated with those events to be called.
+ * 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.
*
- * This function is not required for joystick input to work.
+ * 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.
*
- * @remarks 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 GLFWwindowrefreshfun) to redraw the contents
- * of your window when necessary during the operation.
+ * On some platforms, certain callbacks may be called outside of a call to one
+ * of the event processing functions.
*
- * @note This function may only be called from the main thread.
+ * 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.
*
- * @note This function may not be called from a callback.
+ * Event processing is not required for joystick input to work.
*
- * @note On some platforms, certain callbacks may be called outside of a call
- * to one of the event processing functions.
+ * @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.
- * @param[in] window The window whose input mode to set.
- * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
+ *
+ * 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`.
- * @param[in] value The new value of the specified input mode.
*
- * If `mode` is `GLFW_CURSOR`, the value must be one of the supported input
+ * 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. This is
- * useful if you wish to render your own cursor or have no visible cursor at
- * all.
+ * 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 `mode` is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to
+ * 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 @ref
- * 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 `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 @ref 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.
+ * 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);
@@ -1798,22 +2440,34 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
*
* 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 state `GLFW_REPEAT` is only reported to
+ * `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 this function after a key has been
- * pressed, even if the key has already been released.
+ * `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).
+ * @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`.
*
- * @note `GLFW_KEY_UNKNOWN` is not a valid key for this function.
+ * @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
*/
@@ -1823,26 +2477,37 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
* window.
*
* This function returns the last state reported for the specified mouse button
- * to the specified window.
+ * 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
- * returns `GLFW_PRESS` the first time you call this function after a mouse
- * button has been pressed, even if the mouse button has already been released.
+ * `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 last reported cursor position, relative to the client
- * area of the window.
+/*! @brief Retrieves the position of the cursor relative to the client area of
+ * the window.
*
- * This function returns the last reported position of the cursor, in screen
- * coordinates, relative to the upper-left corner of the client area of the
- * specified 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
@@ -1852,14 +2517,23 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
* `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);
@@ -1869,11 +2543,16 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
*
* 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 be focused. If the window does not have focus when
- * this function is called, it fails silently.
+ * window. The window must have input focus. If the window does not have
+ * input focus when this function is called, it fails silently.
*
- * 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
+ * __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.
@@ -1882,15 +2561,138 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
* @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 specific window, which is called
+ * 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
@@ -1898,16 +2700,16 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
* layout. If you want to input text, use the
* [character callback](@ref glfwSetCharCallback) instead.
*
- * When a window loses 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 window has lost
- * focus, i.e. `GLFW_FOCUSED` will be false and the focus callback will have
- * already been called.
+ * 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 retrieved with @ref glfwGetKey.
+ * 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.
@@ -1915,8 +2717,18 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
* @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 an
- * error occurred.
+ * @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
*/
@@ -1924,11 +2736,56 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
/*! @brief Sets the Unicode character callback.
*
- * This function sets the character callback of the specific window, which is
+ * 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 text input. If you want to know
- * whether a specific key was pressed or released, use the
+ * 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.
@@ -1937,26 +2794,43 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
* @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 GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);
+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 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 window has lost focus, i.e. `GLFW_FOCUSED` will be false and the
- * focus callback will have already been called.
+ * 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 an
- * error occurred.
+ * @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
*/
@@ -1972,8 +2846,15 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmo
* @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.
+ * @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
*/
@@ -1988,8 +2869,15 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursor
* @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.
+ * @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
*/
@@ -2007,20 +2895,61 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcu
* @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 an
- * error occurred.
+ * @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 to query.
+ * @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);
@@ -2028,17 +2957,24 @@ 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 to query.
- * @param[out] count Where to store the size of the returned array. This is
- * set to zero if an error occurred.
+ * @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.
*
- * @note The returned array is allocated and freed by GLFW. You should not
- * free it yourself.
+ * @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.
*
- * @note The returned array is valid only until the next call to @ref
- * glfwGetJoystickAxes for that joystick.
+ * @sa @ref joystick_axis
+ *
+ * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`.
*
* @ingroup input
*/
@@ -2047,17 +2983,27 @@ 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 to query.
- * @param[out] count Where to store the size of the returned array. This is
- * set to zero if an error occurred.
+ * @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.
*
- * @note The returned array is allocated and freed by GLFW. You should not
- * free it yourself.
+ * @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
*
- * @note The returned array is valid only until the next call to @ref
- * glfwGetJoystickButtons for that joystick.
+ * @since Added in GLFW 2.2.
+ *
+ * @par
+ * __GLFW 3:__ Changed to return a dynamic array.
*
* @ingroup input
*/
@@ -2066,16 +3012,24 @@ 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 to query.
+ * @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.
*
- * @note The returned string is allocated and freed by GLFW. You should not
- * free it yourself.
+ * @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.
*
- * @note The returned string is valid only until the next call to @ref
- * glfwGetJoystickName for that joystick.
+ * @sa @ref joystick_name
+ *
+ * @since Added in GLFW 3.0.
*
* @ingroup input
*/
@@ -2084,40 +3038,50 @@ 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. The string is copied before returning, so you don't have to retain
- * it afterwards.
+ * string.
*
* @param[in] window The window that will own the clipboard contents.
* @param[in] string A UTF-8 encoded string.
*
- * @note This function may only be called from the main thread.
+ * @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
*
- * @ingroup clipboard
+ * @since Added in GLFW 3.0.
+ *
+ * @ingroup input
*/
GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
-/*! @brief Retrieves the contents of the clipboard as a 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 occurred.
+ * if an [error](@ref error_handling) occurred.
*
- * @note This function may only be called from the main thread.
+ * @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.
*
- * @note The returned string is allocated and freed by GLFW. You should not
- * free it yourself.
- *
- * @note The returned string is valid only until the next call to @ref
- * glfwGetClipboardString or @ref glfwSetClipboardString.
+ * @par Thread Safety
+ * This function may only be called from the main thread.
*
+ * @sa @ref clipboard
* @sa glfwSetClipboardString
*
- * @ingroup clipboard
+ * @since Added in GLFW 3.0.
+ *
+ * @ingroup input
*/
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
@@ -2127,63 +3091,91 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
* been set using @ref glfwSetTime, the timer measures time elapsed since GLFW
* was initialized.
*
- * @return The current value, in seconds, or zero if an error occurred.
+ * 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.
*
- * @remarks This function may be called from secondary threads.
+ * @sa @ref time
*
- * @note 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.
+ * @since Added in GLFW 1.0.
*
- * @ingroup time
+ * @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.
+ * 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.
*
- * @note 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.
+ * @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 time
+ * @ingroup input
*/
GLFWAPI void glfwSetTime(double time);
/*! @brief Makes the context of the specified window current for the calling
* thread.
*
- * This function makes the 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.
+ * 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.
*
- * @remarks This function may be called from secondary threads.
+ * @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 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.
*
- * @remarks This function may be called from secondary threads.
+ * @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);
@@ -2196,24 +3188,28 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
*
* @param[in] window The window whose buffers to swap.
*
- * @remarks This function may be called from secondary threads.
- *
- * @par New in GLFW 3
- * This function no longer calls @ref glfwPollEvents. You need to call it or
- * @ref glfwWaitEvents yourself.
+ * @par Thread Safety
+ * This function may be called from any thread.
*
+ * @sa @ref buffer_swap
* @sa glfwSwapInterval
*
- * @ingroup context
+ * @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 before swapping the buffers of a window and
- * returning from @ref glfwSwapBuffers. This is sometimes called 'vertical
- * synchronization', 'vertical retrace synchronization' or 'vsync'.
+ * 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,
@@ -2222,22 +3218,29 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
* 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 may be called from secondary threads.
- *
- * @note This function is not called during window creation, leaving the swap
- * interval set to whatever is the default on that platform. This is done
+ * @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.
*
- * @note Some GPU drivers do not honor the requested swap interval, either
- * because of user settings that override the request or due to bugs in the
- * driver.
+ * @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);
@@ -2245,19 +3248,28 @@ GLFWAPI void glfwSwapInterval(int interval);
/*! @brief Returns whether the specified extension is available.
*
* This function returns whether the specified
- * [OpenGL or context creation API extension](@ref context_glext) is supported
- * by the current context. For example, on Windows both the OpenGL and WGL
- * extension strings are checked.
+ * [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.
*
- * @remarks This function may be called from secondary threads.
+ * @par Thread Safety
+ * This function may be called from any thread.
*
- * @note As this functions searches one or more extension strings on each call,
- * it is recommended that you cache its results if it's 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.
+ * @sa @ref context_glext
+ * @sa glfwGetProcAddress
+ *
+ * @since Added in GLFW 1.0.
*
* @ingroup context
*/
@@ -2267,18 +3279,34 @@ GLFWAPI int glfwExtensionSupported(const char* extension);
* context.
*
* This function returns the address of the specified
- * [client API or extension function](@ref context_glext), if it is supported
+ * [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.
+ * 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.
*
- * @remarks This function may be called from secondary threads.
+ * @sa @ref context_glext
+ * @sa glfwExtensionSupported
*
- * @note The addresses of these functions are not guaranteed to be the same for
- * all contexts, especially if they use different client APIs or even different
- * context creation hints.
+ * @since Added in GLFW 1.0.
*
* @ingroup context
*/
diff --git a/externals/glfw-3.1.1.bin/include/GLFW/glfw3native.h b/externals/glfw-3.1.1.bin/include/GLFW/glfw3native.h
new file mode 100644
index 00000000..b3ce7482
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/include/GLFW/glfw3native.h
@@ -0,0 +1,356 @@
+/*************************************************************************
+ * 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
new file mode 100644
index 00000000..84c2e1bc
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3.dll
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-mingw-i686/glfw3dll.a b/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3dll.a
index 415d8563..dc593d06 100644
--- a/externals/glfw-3.0.4.bin/lib-mingw-i686/glfw3dll.a
+++ b/externals/glfw-3.1.1.bin/lib-mingw-i686/glfw3dll.a
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
new file mode 100644
index 00000000..59eae086
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-mingw-i686/libglfw3.a
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
new file mode 100644
index 00000000..437918ed
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3.dll
Binary files differ
diff --git a/externals/glfw-3.0.4.bin/lib-mingw-x86_64/glfw3dll.a b/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3dll.a
index d71c6537..be08358a 100644
--- a/externals/glfw-3.0.4.bin/lib-mingw-x86_64/glfw3dll.a
+++ b/externals/glfw-3.1.1.bin/lib-mingw-x86_64/glfw3dll.a
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
new file mode 100644
index 00000000..e9e7be93
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-mingw-x86_64/libglfw3.a
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
new file mode 100644
index 00000000..f15748d7
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.dll
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
new file mode 100644
index 00000000..6a5a85a1
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3.lib
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
new file mode 100644
index 00000000..248a5cad
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-msvc_v120-Win32/glfw3dll.lib
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
new file mode 100644
index 00000000..cba172f6
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.dll
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
new file mode 100644
index 00000000..efdd6433
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3.lib
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
new file mode 100644
index 00000000..49ed2bb6
--- /dev/null
+++ b/externals/glfw-3.1.1.bin/lib-msvc_v120-x64/glfw3dll.lib
Binary files differ
diff --git a/src/citra/citra.rc b/src/citra/citra.rc
index 0165e93d..b0edb2e6 100644
--- a/src/citra/citra.rc
+++ b/src/citra/citra.rc
@@ -1,9 +1,9 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-GLFW_ICON ICON "..\\assets\\citra.ico"
-
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+GLFW_ICON ICON "..\\..\\dist\\citra.ico"
+
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 846479fd..1378567c 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -66,7 +66,6 @@ void Config::ReadValues() {
Settings::values.pad_cright_key = glfw_config->GetInteger("Controls", "pad_cright", GLFW_KEY_L);
// Core
- Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 30);
Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0);
// Renderer
diff --git a/src/citra/resource.h b/src/citra/resource.h
index 0d42c8a8..12789642 100644
--- a/src/citra/resource.h
+++ b/src/citra/resource.h
Binary files differ
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index efccdbec..c2d1ad24 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -89,15 +89,15 @@ if (Qt5_FOUND AND MSVC)
)
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
set(PLATFORMS ${DLL_DEST}platforms/)
-
+
# 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})
-
+ 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
+ # 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"
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 72b55e94..3db09c65 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -57,7 +57,7 @@ void EmuThread::run() {
Core::SingleStep();
emit DebugModeEntered();
yieldCurrentThread();
-
+
was_active = false;
} else {
std::unique_lock<std::mutex> lock(running_mutex);
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index 16809eaa..47512431 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -80,7 +80,7 @@ signals:
* @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
*/
void DebugModeEntered();
-
+
/**
* Emitted right before the CPU continues execution
*
diff --git a/src/citra_qt/citra-qt.rc b/src/citra_qt/citra-qt.rc
index dd6f834f..3c723985 100644
--- a/src/citra_qt/citra-qt.rc
+++ b/src/citra_qt/citra-qt.rc
Binary files differ
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 460f4ec0..2a9af1f3 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -49,7 +49,6 @@ void Config::ReadValues() {
qt_config->endGroup();
qt_config->beginGroup("Core");
- Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 30).toInt();
Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt();
qt_config->endGroup();
@@ -102,7 +101,6 @@ void Config::SaveValues() {
qt_config->endGroup();
qt_config->beginGroup("Core");
- qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate);
qt_config->setValue("frame_skip", Settings::values.frame_skip);
qt_config->endGroup();
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
index 94e20471..6799ce84 100644
--- a/src/citra_qt/debugger/callstack.cpp
+++ b/src/citra_qt/debugger/callstack.cpp
@@ -39,7 +39,7 @@ void CallstackWidget::OnDebugModeEntered()
{
ret_addr = Memory::Read32(addr);
call_addr = ret_addr - 4; //get call address???
-
+
if (Memory::GetPointer(call_addr) == nullptr)
break;
diff --git a/src/citra_qt/debugger/callstack.ui b/src/citra_qt/debugger/callstack.ui
index b0e31120..248ea3dd 100644
--- a/src/citra_qt/debugger/callstack.ui
+++ b/src/citra_qt/debugger/callstack.ui
@@ -17,6 +17,9 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeView" name="treeView">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp
index 804c735a..cabf5fe0 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.cpp
+++ b/src/citra_qt/debugger/graphics_cmdlists.cpp
@@ -11,10 +11,10 @@
#include <QSpinBox>
#include <QComboBox>
-#include "video_core/pica.h"
-#include "video_core/math.h"
+#include "common/vector_math.h"
#include "video_core/debug_utils/debug_utils.h"
+#include "video_core/pica.h"
#include "graphics_cmdlists.h"
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index e0734459..6bbe7572 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -9,10 +9,11 @@
#include <QPushButton>
#include <QSpinBox>
+#include "common/color.h"
+
#include "core/hw/gpu.h"
#include "core/memory.h"
-#include "video_core/color.h"
#include "video_core/pica.h"
#include "video_core/utils.h"
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index f6010459..8041816a 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -127,7 +127,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer);
SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked());
-
+
ui.action_Single_Window_Mode->setChecked(settings.value("singleWindowMode", true).toBool());
ToggleWindowMode();
diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui
index 0942c28c..9a809ee6 100644
--- a/src/citra_qt/main.ui
+++ b/src/citra_qt/main.ui
@@ -24,7 +24,20 @@
<bool>true</bool>
</property>
<widget class="QWidget" name="centralwidget">
- <layout class="QHBoxLayout" name="horizontalLayout"/>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ </layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
@@ -92,7 +105,7 @@
</action>
<action name="action_Start">
<property name="enabled">
- <bool>false</bool>
+ <bool>false</bool>
</property>
<property name="text">
<string>&amp;Start</string>
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index dbaaac77..e78f4f14 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -24,6 +24,7 @@ set(HEADERS
bit_field.h
break_points.h
chunk_file.h
+ color.h
common_funcs.h
common_paths.h
common_types.h
@@ -54,6 +55,7 @@ set(HEADERS
thread_queue_list.h
thunk.h
timer.h
+ vector_math.h
)
create_directory_groups(${SRCS} ${HEADERS})
diff --git a/src/video_core/color.h b/src/common/color.h
index 4d2026eb..422fdc8a 100644
--- a/src/video_core/color.h
+++ b/src/common/color.h
@@ -6,8 +6,7 @@
#include "common/common_types.h"
#include "common/swap.h"
-
-#include "video_core/math.h"
+#include "common/vector_math.h"
namespace Color {
diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp
index f5b6c730..43facb85 100644
--- a/src/common/emu_window.cpp
+++ b/src/common/emu_window.cpp
@@ -32,7 +32,7 @@ std::tuple<unsigned,unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsig
new_x = std::max(new_x, framebuffer_layout.bottom_screen.left);
new_x = std::min(new_x, framebuffer_layout.bottom_screen.right-1);
-
+
new_y = std::max(new_y, framebuffer_layout.bottom_screen.top);
new_y = std::min(new_y, framebuffer_layout.bottom_screen.bottom-1);
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 7cdd1484..24648ea3 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -16,7 +16,7 @@
#include <io.h>
#include <direct.h> // getcwd
#include <tchar.h>
-
+
// 64 bit offsets for windows
#define fseeko _fseeki64
#define ftello _ftelli64
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 6ca8cb78..d85e5837 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -37,6 +37,7 @@ namespace Log {
SUB(Service, APT) \
SUB(Service, GSP) \
SUB(Service, AC) \
+ SUB(Service, AM) \
SUB(Service, PTM) \
SUB(Service, LDR) \
SUB(Service, NIM) \
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index d720d7fe..5b3a731e 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -57,13 +57,14 @@ enum class Class : ClassType {
Service_APT, ///< The APT (Applets) service
Service_GSP, ///< The GSP (GPU control) service
Service_AC, ///< The AC (WiFi status) service
+ Service_AM, ///< The AM (Application manager) service
Service_PTM, ///< The PTM (Power status & misc.) service
Service_LDR, ///< The LDR (3ds dll loader) service
Service_NIM, ///< The NIM (Network interface manager) service
- Service_NWM, ///< The NWM (Network manager) service
+ Service_NWM, ///< The NWM (Network wlan manager) service
Service_CFG, ///< The CFG (Configuration) service
Service_DSP, ///< The DSP (DSP control) service
- Service_HID, ///< The HID (User input) service
+ Service_HID, ///< The HID (Human interface device) service
Service_SOC, ///< The SOC (Socket) service
Service_Y2R, ///< The Y2R (YUV to RGB conversion) service
HW, ///< Low-level hardware emulation
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 4b091074..d44b06e7 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -12,7 +12,7 @@ namespace MathUtil
{
inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1, unsigned length1) {
- return (std::max(start0, start1) <= std::min(start0 + length0, start1 + length1));
+ return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1));
}
template<typename T>
diff --git a/src/common/swap.h b/src/common/swap.h
index 7e37655b..588cebc7 100644
--- a/src/common/swap.h
+++ b/src/common/swap.h
@@ -135,7 +135,7 @@ template <>
inline void swap<8>(u8* data) {
*reinterpret_cast<u64*>(data) = swap64(data);
}
-
+
} // Namespace Common
diff --git a/src/video_core/math.h b/src/common/vector_math.h
index f9a82265..4928c9bf 100644
--- a/src/video_core/math.h
+++ b/src/common/vector_math.h
@@ -461,7 +461,7 @@ public:
// e.g. Vec2 uv() { return Vec2(x,y); }
// _DEFINE_SWIZZLER2 defines a single such function
- // DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r)
+ // DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r)
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and permutations (xy<->yx)
#define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); }
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 5caaee47..057b8ca0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -36,20 +36,29 @@ set(SRCS
hle/kernel/shared_memory.cpp
hle/kernel/thread.cpp
hle/kernel/timer.cpp
+ hle/kernel/vm_manager.cpp
hle/service/ac_u.cpp
hle/service/act_u.cpp
- hle/service/am_app.cpp
- hle/service/am_net.cpp
- hle/service/am_sys.cpp
+ hle/service/am/am.cpp
+ hle/service/am/am_app.cpp
+ hle/service/am/am_net.cpp
+ hle/service/am/am_sys.cpp
+ hle/service/am/am_u.cpp
hle/service/apt/apt.cpp
hle/service/apt/apt_a.cpp
hle/service/apt/apt_s.cpp
hle/service/apt/apt_u.cpp
- hle/service/boss_p.cpp
- hle/service/boss_u.cpp
- hle/service/cam_u.cpp
- hle/service/cecd_s.cpp
- hle/service/cecd_u.cpp
+ hle/service/boss/boss.cpp
+ hle/service/boss/boss_p.cpp
+ hle/service/boss/boss_u.cpp
+ hle/service/cam/cam.cpp
+ hle/service/cam/cam_c.cpp
+ hle/service/cam/cam_q.cpp
+ hle/service/cam/cam_s.cpp
+ hle/service/cam/cam_u.cpp
+ hle/service/cecd/cecd.cpp
+ hle/service/cecd/cecd_s.cpp
+ hle/service/cecd/cecd_u.cpp
hle/service/cfg/cfg.cpp
hle/service/cfg/cfg_i.cpp
hle/service/cfg/cfg_s.cpp
@@ -57,8 +66,9 @@ set(SRCS
hle/service/csnd_snd.cpp
hle/service/dsp_dsp.cpp
hle/service/err_f.cpp
- hle/service/frd_a.cpp
- hle/service/frd_u.cpp
+ hle/service/frd/frd.cpp
+ hle/service/frd/frd_a.cpp
+ hle/service/frd/frd_u.cpp
hle/service/fs/archive.cpp
hle/service/fs/fs_user.cpp
hle/service/gsp_gpu.cpp
@@ -74,10 +84,13 @@ set(SRCS
hle/service/ldr_ro.cpp
hle/service/mic_u.cpp
hle/service/ndm_u.cpp
- hle/service/news_s.cpp
- hle/service/news_u.cpp
- hle/service/nim_aoc.cpp
- hle/service/nim_u.cpp
+ hle/service/news/news.cpp
+ hle/service/news/news_s.cpp
+ hle/service/news/news_u.cpp
+ hle/service/nim/nim.cpp
+ hle/service/nim/nim_aoc.cpp
+ hle/service/nim/nim_s.cpp
+ hle/service/nim/nim_u.cpp
hle/service/ns_s.cpp
hle/service/nwm_uds.cpp
hle/service/pm_app.cpp
@@ -116,7 +129,6 @@ set(HEADERS
arm/dyncom/arm_dyncom_thumb.h
arm/skyeye_common/arm_regformat.h
arm/skyeye_common/armdefs.h
- arm/skyeye_common/armemu.h
arm/skyeye_common/armmmu.h
arm/skyeye_common/vfp/asm_vfp.h
arm/skyeye_common/vfp/vfp.h
@@ -148,21 +160,30 @@ set(HEADERS
hle/kernel/shared_memory.h
hle/kernel/thread.h
hle/kernel/timer.h
+ hle/kernel/vm_manager.h
hle/result.h
hle/service/ac_u.h
hle/service/act_u.h
- hle/service/am_app.h
- hle/service/am_net.h
- hle/service/am_sys.h
+ hle/service/am/am.h
+ hle/service/am/am_app.h
+ hle/service/am/am_net.h
+ hle/service/am/am_sys.h
+ hle/service/am/am_u.h
hle/service/apt/apt.h
hle/service/apt/apt_a.h
hle/service/apt/apt_s.h
hle/service/apt/apt_u.h
- hle/service/boss_p.h
- hle/service/boss_u.h
- hle/service/cam_u.h
- hle/service/cecd_s.h
- hle/service/cecd_u.h
+ hle/service/boss/boss.h
+ hle/service/boss/boss_p.h
+ hle/service/boss/boss_u.h
+ hle/service/cam/cam.h
+ hle/service/cam/cam_c.h
+ hle/service/cam/cam_q.h
+ hle/service/cam/cam_s.h
+ hle/service/cam/cam_u.h
+ hle/service/cecd/cecd.h
+ hle/service/cecd/cecd_s.h
+ hle/service/cecd/cecd_u.h
hle/service/cfg/cfg.h
hle/service/cfg/cfg_i.h
hle/service/cfg/cfg_s.h
@@ -170,8 +191,9 @@ set(HEADERS
hle/service/csnd_snd.h
hle/service/dsp_dsp.h
hle/service/err_f.h
- hle/service/frd_a.h
- hle/service/frd_u.h
+ hle/service/frd/frd.h
+ hle/service/frd/frd_a.h
+ hle/service/frd/frd_u.h
hle/service/fs/archive.h
hle/service/fs/fs_user.h
hle/service/gsp_gpu.h
@@ -187,10 +209,13 @@ set(HEADERS
hle/service/ldr_ro.h
hle/service/mic_u.h
hle/service/ndm_u.h
- hle/service/news_s.h
- hle/service/news_u.h
- hle/service/nim_aoc.h
- hle/service/nim_u.h
+ hle/service/news/news.h
+ hle/service/news/news_s.h
+ hle/service/news/news_u.h
+ hle/service/nim/nim.h
+ hle/service/nim/nim_aoc.h
+ hle/service/nim/nim_s.h
+ hle/service/nim/nim_u.h
hle/service/ns_s.h
hle/service/nwm_uds.h
hle/service/pm_app.h
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index 913dc145..f6d44d85 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -813,7 +813,7 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) {
// SWI
return OP_SWI;
}
-
+
uint8_t bit4 = (insn >> 4) & 0x1;
uint8_t cpnum = (insn >> 8) & 0xf;
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 0072ae53..529c4ac7 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -6,7 +6,7 @@
#include "common/make_unique.h"
-#include "core/arm/skyeye_common/armemu.h"
+#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
#include "core/arm/dyncom/arm_dyncom.h"
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index e4b5486e..b00eb49a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -134,7 +134,7 @@ static unsigned int DPO(Immediate)(ARMul_State* cpu, unsigned int sht_oper) {
unsigned int immed_8 = BITS(sht_oper, 0, 7);
unsigned int rotate_imm = BITS(sht_oper, 8, 11);
unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);
- if (rotate_imm == 0)
+ if (rotate_imm == 0)
cpu->shifter_carry_out = cpu->CFlag;
else
cpu->shifter_carry_out = BIT(shifter_operand, 31);
@@ -521,7 +521,7 @@ static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned
addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8;
else
addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8;
-
+
virt_addr = addr;
}
@@ -550,7 +550,7 @@ static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsig
if (U_BIT)
addr = rn + offset_8;
- else
+ else
addr = rn - offset_8;
virt_addr = addr;
@@ -1306,8 +1306,8 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index)
inst_cream->Rd = BITS(inst, 12, 15);
inst_cream->shifter_operand = BITS(inst, 0, 11);
inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
+
+ if (inst_cream->Rd == 15)
inst_base->br = INDIRECT_BRANCH;
return inst_base;
@@ -1350,7 +1350,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(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)
+ if (inst_cream->Rd == 15)
inst_base->br = INDIRECT_BRANCH;
return inst_base;
}
@@ -3269,7 +3269,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index)
#define VFP_INTERPRETER_STRUCT
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_INTERPRETER_STRUCT
-
+
#define VFP_INTERPRETER_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_INTERPRETER_TRANS
@@ -3478,9 +3478,9 @@ const transop_fp_t arm_instruction_trans[] = {
INTERPRETER_TRANSLATE(bbl),
// All the thumb instructions should be placed the end of table
- INTERPRETER_TRANSLATE(b_2_thumb),
- INTERPRETER_TRANSLATE(b_cond_thumb),
- INTERPRETER_TRANSLATE(bl_1_thumb),
+ INTERPRETER_TRANSLATE(b_2_thumb),
+ INTERPRETER_TRANSLATE(b_cond_thumb),
+ INTERPRETER_TRANSLATE(bl_1_thumb),
INTERPRETER_TRANSLATE(bl_2_thumb),
INTERPRETER_TRANSLATE(blx_1_thumb)
};
@@ -3564,17 +3564,13 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
unsigned int inst, inst_size = 4;
int idx;
int ret = NON_BRANCH;
- int thumb = 0;
int size = 0; // instruction size of basic block
bb_start = top;
- if (cpu->TFlag)
- thumb = THUMB;
-
u32 phys_addr = addr;
u32 pc_start = cpu->Reg[15];
- while(ret == NON_BRANCH) {
+ while (ret == NON_BRANCH) {
inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
size++;
@@ -3890,7 +3886,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
#define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE)
#define PC (cpu->Reg[15])
- #define CHECK_EXT_INT if (!cpu->NirqSig && !(cpu->Cpsr & 0x80)) goto END;
// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
// to a clunky switch statement.
@@ -4343,7 +4338,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
if (BIT(inst, 13)) {
- if (cpu->Mode == USER32MODE)
+ if (cpu->Mode == USER32MODE)
cpu->Reg[13] = ReadMemory32(cpu, addr);
else
cpu->Reg_usr[0] = ReadMemory32(cpu, addr);
@@ -4351,7 +4346,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
addr += 4;
}
if (BIT(inst, 14)) {
- if (cpu->Mode == USER32MODE)
+ if (cpu->Mode == USER32MODE)
cpu->Reg[14] = ReadMemory32(cpu, addr);
else
cpu->Reg_usr[1] = ReadMemory32(cpu, addr);
@@ -5153,7 +5148,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
REV16_INST:
REVSH_INST:
{
-
+
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
rev_inst* const inst_cream = (rev_inst*)inst_base->component;
@@ -5726,7 +5721,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (do_swap)
rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
-
+
const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
s64 result;
@@ -6588,7 +6583,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
u32 lo_val = 0;
u32 hi_val = 0;
-
+
// UHADD16
if (op2 == 0x00) {
lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
@@ -6777,7 +6772,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u16 lo_val = 0;
u16 hi_val = 0;
-
+
// UQADD16
if (op2 == 0x00) {
lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index 08b5c0b7..3e79c44c 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -184,38 +184,27 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
case 9: // LDR Rd,[PC,#imm8]
*ainstr = 0xE59F0000 // base
| ((tinstr & 0x0700) << (12 - 8)) // Rd
- |((tinstr & 0x00FF) << (2 - 0)); // off8
+ |((tinstr & 0x00FF) << (2 - 0)); // off8
break;
case 10:
case 11:
- // TODO: Format 7 and Format 8 perform the same ARM encoding, so the following could be
- // merged into a single subset, saving on the following boolean:
-
- if ((tinstr & (1 << 9)) == 0) {
- static const ARMword subset[4] = {
- 0xE7800000, // STR Rd,[Rb,Ro]
- 0xE7C00000, // STRB Rd,[Rb,Ro]
- 0xE7900000, // LDR Rd,[Rb,Ro]
- 0xE7D00000 // LDRB Rd,[Rb,Ro]
- };
-
- *ainstr = subset[(tinstr & 0x0C00) >> 10] // base
- |((tinstr & 0x0007) << (12 - 0)) // Rd
- |((tinstr & 0x0038) << (16 - 3)) // Rb
- |((tinstr & 0x01C0) >> 6); // Ro
-
- } else {
- static const ARMword subset[4] = {
+ {
+ static const ARMword subset[8] = {
+ 0xE7800000, // STR Rd,[Rb,Ro]
0xE18000B0, // STRH Rd,[Rb,Ro]
+ 0xE7C00000, // STRB Rd,[Rb,Ro]
0xE19000D0, // LDRSB Rd,[Rb,Ro]
+ 0xE7900000, // LDR Rd,[Rb,Ro]
0xE19000B0, // LDRH Rd,[Rb,Ro]
+ 0xE7D00000, // LDRB Rd,[Rb,Ro]
0xE19000F0 // LDRSH Rd,[Rb,Ro]
};
- *ainstr = subset[(tinstr & 0x0C00) >> 10] // base
- |((tinstr & 0x0007) << (12 - 0)) // Rd
- |((tinstr & 0x0038) << (16 - 3)) // Rb
- |((tinstr & 0x01C0) >> 6); // Ro
+
+ *ainstr = subset[(tinstr & 0xE00) >> 9] // base
+ |((tinstr & 0x0007) << (12 - 0)) // Rd
+ |((tinstr & 0x0038) << (16 - 3)) // Rb
+ |((tinstr & 0x01C0) >> 6); // Ro
}
break;
@@ -285,9 +274,46 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
? 0xE24DDF00 // SUB
: 0xE28DDF00) // ADD
|(tinstr & 0x007F); // off7
- } else if ((tinstr & 0x0F00) == 0x0e00)
- *ainstr = 0xEF000000 | 0x180000; // base | BKPT mask
- else {
+ } else if ((tinstr & 0x0F00) == 0x0e00) {
+ // BKPT
+ *ainstr = 0xEF000000 // base
+ | BITS(tinstr, 0, 3) // imm4 field;
+ | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12
+ } else if ((tinstr & 0x0F00) == 0x0200) {
+ static const ARMword subset[4] = {
+ 0xE6BF0070, // SXTH
+ 0xE6AF0070, // SXTB
+ 0xE6FF0070, // UXTH
+ 0xE6EF0070, // UXTB
+ };
+
+ *ainstr = subset[BITS(tinstr, 6, 7)] // base
+ | (BITS(tinstr, 0, 2) << 12) // Rd
+ | BITS(tinstr, 3, 5); // Rm
+ } else if ((tinstr & 0x0F00) == 0x600) {
+ if (BIT(tinstr, 5) == 0) {
+ // SETEND
+ *ainstr = 0xF1010000 // base
+ | (BIT(tinstr, 3) << 9); // endian specifier
+ } else {
+ // CPS
+ *ainstr = 0xF1080000 // base
+ | (BIT(tinstr, 0) << 6) // fiq bit
+ | (BIT(tinstr, 1) << 7) // irq bit
+ | (BIT(tinstr, 2) << 8) // abort bit
+ | (BIT(tinstr, 4) << 18); // enable bit
+ }
+ } else if ((tinstr & 0x0F00) == 0x0a00) {
+ static const ARMword subset[3] = {
+ 0xE6BF0F30, // REV
+ 0xE6BF0FB0, // REV16
+ 0xE6FF0FB0, // REVSH
+ };
+
+ *ainstr = subset[BITS(tinstr, 6, 7)] // base
+ | (BITS(tinstr, 0, 2) << 12) // Rd
+ | BITS(tinstr, 3, 5); // Rm
+ } else {
static const ARMword subset[4] = {
0xE92D0000, // STMDB sp!,{rlist}
0xE92D4000, // STMDB sp!,{rlist,lr}
@@ -301,11 +327,25 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
case 24: // STMIA
case 25: // LDMIA
- *ainstr = ((tinstr & (1 << 11)) // base
- ? 0xE8B00000 // LDMIA
- : 0xE8A00000) // STMIA
- |((tinstr & 0x0700) << (16 - 8)) // Rb
- |(tinstr & 0x00FF); // mask8
+ if (tinstr & (1 << 11))
+ {
+ unsigned int base = 0xE8900000;
+ unsigned int rn = BITS(tinstr, 8, 10);
+
+ // Writeback
+ if ((tinstr & (1 << rn)) == 0)
+ base |= (1 << 21);
+
+ *ainstr = base // base (LDMIA)
+ | (rn << 16) // Rn
+ | (tinstr & 0x00FF); // Register list
+ }
+ else
+ {
+ *ainstr = 0xE8A00000 // base (STMIA)
+ | (BITS(tinstr, 8, 10) << 16) // Rn
+ | (tinstr & 0x00FF); // Register list
+ }
break;
case 26: // Bcc
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 680a94a3..4f7a48fa 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -17,7 +17,6 @@
#include <cstring>
#include "core/arm/skyeye_common/armdefs.h"
-#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
/***************************************************************************\
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 1b078dc7..83f7f3e2 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -628,7 +628,7 @@ void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 c
cpu->CP15[CP15_DATA_SYNC_BARRIER] = value;
else if (opcode_2 == 5)
cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value;
-
+
}
else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2)
{
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index 6c89774e..a92effbb 100644
--- a/src/core/arm/skyeye_common/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -59,6 +59,8 @@ enum {
VFP_FPSID,
VFP_FPSCR,
VFP_FPEXC,
+ VFP_MVFR0,
+ VFP_MVFR1,
// Not an actual register.
// All VFP system registers should be defined above this.
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 470f9508..d2c90110 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -1,16 +1,16 @@
/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator.
Copyright (C) 1994 Advanced RISC Machines Ltd.
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
@@ -262,6 +262,34 @@ enum ConditionCode {
NV = 15,
};
+// Flags for use with the APSR.
+enum : u32 {
+ NBIT = (1U << 31U),
+ ZBIT = (1 << 30),
+ CBIT = (1 << 29),
+ VBIT = (1 << 28),
+ QBIT = (1 << 27),
+ JBIT = (1 << 24),
+ EBIT = (1 << 9),
+ ABIT = (1 << 8),
+ IBIT = (1 << 7),
+ FBIT = (1 << 6),
+ TBIT = (1 << 5),
+
+ // Masks for groups of bits in the APSR.
+ MODEBITS = 0x1F,
+ INTBITS = 0x1C0,
+};
+
+// Values for Emulate.
+enum {
+ STOP = 0, // Stop
+ CHANGEMODE = 1, // Change mode
+ ONCE = 2, // Execute just one iteration
+ RUN = 3 // Continuous execution
+};
+
+
extern bool AddOverflow(ARMword, ARMword, ARMword);
extern bool SubOverflow(ARMword, ARMword, ARMword);
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
deleted file mode 100644
index 7e096505..00000000
--- a/src/core/arm/skyeye_common/armemu.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* armemu.h -- ARMulator emulation macros: ARM6 Instruction Emulator.
- Copyright (C) 1994 Advanced RISC Machines Ltd.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#pragma once
-
-#include "core/arm/skyeye_common/armdefs.h"
-
-// Flags for use with the APSR.
-enum : u32 {
- NBIT = (1U << 31U),
- ZBIT = (1 << 30),
- CBIT = (1 << 29),
- VBIT = (1 << 28),
- QBIT = (1 << 27),
- JBIT = (1 << 24),
- EBIT = (1 << 9),
- ABIT = (1 << 8),
- IBIT = (1 << 7),
- FBIT = (1 << 6),
- TBIT = (1 << 5),
-
- // Masks for groups of bits in the APSR.
- MODEBITS = 0x1F,
- INTBITS = 0x1C0,
-};
-
-// Values for Emulate.
-enum {
- STOP = 0, // Stop
- CHANGEMODE = 1, // Change mode
- ONCE = 2, // Execute just one interation
- RUN = 3 // Continuous execution
-};
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index b88d4775..571d6c2f 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -33,6 +33,10 @@ unsigned VFPInit(ARMul_State* state)
state->VFP[VFP_FPEXC] = 0;
state->VFP[VFP_FPSCR] = 0;
+ // ARM11 MPCore feature register values.
+ state->VFP[VFP_MVFR0] = 0x11111111;
+ state->VFP[VFP_MVFR1] = 0;
+
return 0;
}
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 727350f1..acefae9b 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -22,7 +22,6 @@
#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
-#define VFP_DEBUG_UNIMPLEMENTED(x) LOG_ERROR(Core_ARM11, "in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
#define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested\n", __FUNCTION__);
#define CHECK_VFP_ENABLED
#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index ccc0212a..2007d6dc 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -18,10 +18,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*
+/*
* The following code is derivative from Linux Android kernel vfp
* floating point support.
- *
+ *
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
*
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 3ed918a9..67fe63aa 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -1068,10 +1068,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBRC_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
- VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
+ vmovbrc_inst* const inst_cream = (vmovbrc_inst*)inst_base->component;
+
+ cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t];
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
INC_PC(sizeof(vmovbrc_inst));
@@ -1139,12 +1141,10 @@ VMRS_INST:
cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSID];
break;
case 6:
- /* MVFR1, VFPv3 only ? */
- LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", inst_cream->Rt);
+ cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR1];
break;
case 7:
- /* MVFR0, VFPv3 only? */
- LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", inst_cream->Rt);
+ cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR0];
break;
case 8:
cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPEXC];
@@ -1195,10 +1195,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMOVBCR_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
- VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
+ vmovbcr_inst* const inst_cream = (vmovbcr_inst*) inst_base->component;
+
+ cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index];
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
INC_PC(sizeof(vmovbcr_inst));
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index f70c84c3..e53c2e60 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -549,7 +549,7 @@ std::string GetScheduledEventsSummary() {
const char* name = event_types[event->type].name;
if (!name)
name = "[unknown]";
- text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time,
+ text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time,
(u32)(event->userdata >> 32), (u32)(event->userdata));
event = event->next;
}
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 01519608..64f5b06d 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -87,7 +87,7 @@ void UnregisterAllEvents();
/// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk,
/// when we implement state saves.
/**
- * Schedules an event to run after the specified number of cycles,
+ * Schedules an event to run after the specified number of cycles,
* with an optional parameter to be passed to the callback handler.
* This must be run ONLY from within the cpu thread.
* @param cycles_into_future The number of cycles after which this event will be fired
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 38d498d0..e50c58a5 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -30,8 +30,8 @@ std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path)
std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) {
if (shared)
return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID.c_str());
-
- return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(),
+
+ return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(),
SYSTEM_ID.c_str(), SDCARD_ID.c_str());
}
@@ -71,7 +71,7 @@ bool ArchiveFactory_ExtSaveData::Initialize() {
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) {
- std::string fullpath = GetExtSaveDataPath(mount_point, path);
+ std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/";
if (!FileUtil::Exists(fullpath)) {
// TODO(Subv): Check error code, this one is probably wrong
return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
@@ -82,8 +82,11 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
}
ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path) {
- std::string fullpath = GetExtSaveDataPath(mount_point, path);
- FileUtil::CreateFullPath(fullpath);
+ // These folders are always created with the ExtSaveData
+ std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/";
+ std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/";
+ FileUtil::CreateFullPath(user_path);
+ FileUtil::CreateFullPath(boss_path);
return RESULT_SUCCESS;
}
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h
index c77c04e4..ef0b27bd 100644
--- a/src/core/file_sys/archive_extsavedata.h
+++ b/src/core/file_sys/archive_extsavedata.h
@@ -35,14 +35,14 @@ public:
private:
/**
* This holds the full directory path for this archive, it is only set after a successful call
- * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>.
+ * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>.
* See GetExtSaveDataPath for the code that extracts this data from an archive path.
*/
std::string mount_point;
};
/**
- * Constructs a path to the concrete ExtData archive in the host filesystem based on the
+ * Constructs a path to the concrete ExtData archive in the host filesystem based on the
* input Path and base mount point.
* @param mount_point The base mount point of the ExtSaveData archives.
* @param path The path that identifies the requested concrete ExtSaveData archive.
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
index 8dff5196..a9230937 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -21,7 +21,7 @@
namespace FileSys {
static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) {
- return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(),
+ return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(),
SYSTEM_ID.c_str(), SDCARD_ID.c_str());
}
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 23c86a72..5949cb47 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -9,11 +9,15 @@
#include "core/arm/arm_interface.h"
#include "core/memory.h"
#include "core/hle/hle.h"
+#include "core/hle/result.h"
namespace HLE {
#define PARAM(n) Core::g_app_core->GetReg(n)
+/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
+static const ResultCode RESULT_INVALID(0xDEADC0DE);
+
/**
* HLE a function return from the current ARM11 userland process
* @param res Result to return
@@ -57,8 +61,11 @@ template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() {
s32 param_1 = 0;
s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
(PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))).raw;
- Core::g_app_core->SetReg(1, (u32)param_1);
- FuncReturn(retval);
+
+ if (retval != RESULT_INVALID.raw) {
+ Core::g_app_core->SetReg(1, (u32)param_1);
+ FuncReturn(retval);
+ }
}
template<ResultCode func(u32, u32, u32, u32, s64)> void Wrap() {
@@ -73,7 +80,11 @@ template<ResultCode func(u32*)> void Wrap(){
}
template<ResultCode func(u32, s64)> void Wrap() {
- FuncReturn(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw);
+ s32 retval = func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw;
+
+ if (retval != RESULT_INVALID.raw) {
+ FuncReturn(retval);
+ }
}
template<ResultCode func(void*, void*, u32)> void Wrap(){
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index e45deb1c..f338f326 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -41,10 +41,7 @@ void Event::Acquire() {
void Event::Signal() {
signaled = true;
-
WakeupAllWaitingThreads();
-
- HLE::Reschedule(__func__);
}
void Event::Clear() {
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 726e4d2f..20e11da1 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -32,27 +32,13 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
waiting_threads.erase(itr);
}
-SharedPtr<Thread> WaitObject::WakeupNextThread() {
- if (waiting_threads.empty())
- return nullptr;
-
- auto next_thread = std::move(waiting_threads.front());
- waiting_threads.erase(waiting_threads.begin());
-
- next_thread->ReleaseWaitObject(this);
-
- return next_thread;
-}
-
void WaitObject::WakeupAllWaitingThreads() {
- auto waiting_threads_copy = waiting_threads;
+ for (auto thread : waiting_threads)
+ thread->ResumeFromWait();
- // We use a copy because ReleaseWaitObject will remove the thread from this object's
- // waiting_threads list
- for (auto thread : waiting_threads_copy)
- thread->ReleaseWaitObject(this);
+ waiting_threads.clear();
- ASSERT_MSG(waiting_threads.empty(), "failed to awaken all waiting threads!");
+ HLE::Reschedule(__func__);
}
HandleTable::HandleTable() {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index a5a0f480..64595f75 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -140,12 +140,6 @@ public:
*/
void RemoveWaitingThread(Thread* thread);
- /**
- * Wake up the next thread waiting on this object
- * @return Pointer to the thread that was resumed, nullptr if no threads are waiting
- */
- SharedPtr<Thread> WakeupNextThread();
-
/// Wake up all threads waiting on this object
void WakeupAllWaitingThreads();
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 6aa73df8..edb97d32 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -23,12 +23,7 @@ static void ResumeWaitingThread(Mutex* mutex) {
// Reset mutex lock thread handle, nothing is waiting
mutex->lock_count = 0;
mutex->holding_thread = nullptr;
-
- // Find the next waiting thread for the mutex...
- auto next_thread = mutex->WakeupNextThread();
- if (next_thread != nullptr) {
- mutex->Acquire(next_thread);
- }
+ mutex->WakeupAllWaitingThreads();
}
void ReleaseThreadMutexes(Thread* thread) {
@@ -94,8 +89,6 @@ void Mutex::Release() {
ResumeWaitingThread(this);
}
}
-
- HLE::Reschedule(__func__);
}
} // namespace
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 201ec0db..1b8249c7 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -81,13 +81,13 @@ public:
s32 max_timers = 0;
s32 max_shared_mems = 0;
s32 max_address_arbiters = 0;
-
+
/// Max CPU time that the processes in this category can utilize
s32 max_cpu_time = 0;
- // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that
- // APPLICATION resource limits should not be affected by the objects created by service modules.
- // Currently we have no way of distinguishing if a Create was called by the running application,
+ // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that
+ // APPLICATION resource limits should not be affected by the objects created by service modules.
+ // Currently we have no way of distinguishing if a Create was called by the running application,
// or by a service module. Approach this once we have separated the service modules into their own processes
/// Current memory that the processes in this category are using
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index dbb4c9b7..4b359ed0 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -42,19 +42,13 @@ void Semaphore::Acquire() {
ResultVal<s32> Semaphore::Release(s32 release_count) {
if (max_count - available_count < release_count)
- return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
+ return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
s32 previous_count = available_count;
available_count += release_count;
- // Notify some of the threads that the semaphore has been released
- // stop once the semaphore is full again or there are no more waiting threads
- while (!ShouldWait() && WakeupNextThread() != nullptr) {
- Acquire();
- }
-
- HLE::Reschedule(__func__);
+ WakeupAllWaitingThreads();
return MakeResult<s32>(previous_count);
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 690d33b5..4729a7fe 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -13,6 +13,7 @@
#include "common/thread_queue_list.h"
#include "core/arm/arm_interface.h"
+#include "core/arm/skyeye_common/armdefs.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/hle.h"
@@ -100,7 +101,7 @@ void Thread::Stop() {
}
status = THREADSTATUS_DEAD;
-
+
WakeupAllWaitingThreads();
// Clean up any dangling references in objects that this thread was waiting for
@@ -169,7 +170,7 @@ static void PriorityBoostStarvedThreads() {
}
}
-/**
+/**
* Switches the CPU's active thread context to that of the specified thread
* @param new_thread The thread to switch to
*/
@@ -193,8 +194,22 @@ static void SwitchContext(Thread* new_thread) {
if (new_thread) {
DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running.");
+ // Cancel any outstanding wakeup events for this thread
+ CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle);
+
current_thread = new_thread;
+ // If the thread was waited by a svcWaitSynch call, step back PC by one instruction to rerun
+ // the SVC when the thread wakes up. This is necessary to ensure that the thread can acquire
+ // the requested wait object(s) before continuing.
+ if (new_thread->waitsynch_waited) {
+ // CPSR flag indicates CPU mode
+ bool thumb_mode = (new_thread->context.cpsr & TBIT) != 0;
+
+ // SVC instruction is 2 bytes for THUMB, 4 bytes for ARM
+ new_thread->context.pc -= thumb_mode ? 2 : 4;
+ }
+
ready_queue.remove(new_thread->current_priority, new_thread);
new_thread->status = THREADSTATUS_RUNNING;
@@ -243,6 +258,7 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa
thread->wait_set_output = wait_set_output;
thread->wait_all = wait_all;
thread->wait_objects = std::move(wait_objects);
+ thread->waitsynch_waited = true;
thread->status = THREADSTATUS_WAIT_SYNCH;
}
@@ -268,6 +284,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
return;
}
+ thread->waitsynch_waited = false;
+
if (thread->status == THREADSTATUS_WAIT_SYNCH) {
thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
ErrorSummary::StatusChanged, ErrorLevel::Info));
@@ -288,63 +306,20 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle);
}
-void Thread::ReleaseWaitObject(WaitObject* wait_object) {
- if (status != THREADSTATUS_WAIT_SYNCH || wait_objects.empty()) {
- LOG_CRITICAL(Kernel, "thread is not waiting on any objects!");
- return;
- }
-
- // Remove this thread from the waiting object's thread list
- wait_object->RemoveWaitingThread(this);
-
- unsigned index = 0;
- bool wait_all_failed = false; // Will be set to true if any object is unavailable
-
- // Iterate through all waiting objects to check availability...
- for (auto itr = wait_objects.begin(); itr != wait_objects.end(); ++itr) {
- if ((*itr)->ShouldWait())
- wait_all_failed = true;
-
- // The output should be the last index of wait_object
- if (*itr == wait_object)
- index = itr - wait_objects.begin();
- }
-
- // If we are waiting on all objects...
- if (wait_all) {
- // Resume the thread only if all are available...
- if (!wait_all_failed) {
- SetWaitSynchronizationResult(RESULT_SUCCESS);
- SetWaitSynchronizationOutput(-1);
-
- ResumeFromWait();
- }
- } else {
- // Otherwise, resume
- SetWaitSynchronizationResult(RESULT_SUCCESS);
-
- if (wait_set_output)
- SetWaitSynchronizationOutput(index);
-
- ResumeFromWait();
- }
-}
-
void Thread::ResumeFromWait() {
- // Cancel any outstanding wakeup events for this thread
- CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
-
switch (status) {
case THREADSTATUS_WAIT_SYNCH:
- // Remove this thread from all other WaitObjects
- for (auto wait_object : wait_objects)
- wait_object->RemoveWaitingThread(this);
- break;
case THREADSTATUS_WAIT_ARB:
case THREADSTATUS_WAIT_SLEEP:
break;
- case THREADSTATUS_RUNNING:
+
case THREADSTATUS_READY:
+ // If the thread is waiting on multiple wait objects, it might be awoken more than once
+ // before actually resuming. We can ignore subsequent wakeups if the thread status has
+ // already been set to THREADSTATUS_READY.
+ return;
+
+ case THREADSTATUS_RUNNING:
DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId());
return;
case THREADSTATUS_DEAD:
@@ -353,7 +328,7 @@ void Thread::ResumeFromWait() {
GetObjectId());
return;
}
-
+
ready_queue.push_back(current_priority, this);
status = THREADSTATUS_READY;
}
@@ -415,6 +390,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom();
thread->owner_process = g_current_process;
thread->tls_index = -1;
+ thread->waitsynch_waited = false;
// Find the next available TLS index, and mark it as used
auto& used_tls_slots = Kernel::g_current_process->used_tls_slots;
@@ -504,7 +480,7 @@ void Reschedule() {
} else if (next) {
LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId());
}
-
+
SwitchContext(next);
}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 38992817..b8160bb2 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -94,12 +94,6 @@ public:
* @return The thread's ID
*/
u32 GetThreadId() const { return thread_id; }
-
- /**
- * Release an acquired wait object
- * @param wait_object WaitObject to release
- */
- void ReleaseWaitObject(WaitObject* wait_object);
/**
* Resumes a thread from waiting
@@ -152,6 +146,8 @@ public:
s32 tls_index; ///< Index of the Thread Local Storage of the thread
+ bool waitsynch_waited; ///< Set to true if the last svcWaitSynch call caused the thread to wait
+
/// Mutexes currently held by this thread, which will be released when it exits.
boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
@@ -163,12 +159,12 @@ public:
std::string name;
+ /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
+ Handle callback_handle;
+
private:
Thread();
~Thread() override;
-
- /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
- Handle callback_handle;
};
/**
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 25d066bf..8aa4110a 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -88,7 +88,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
if (timer->interval_delay != 0) {
// Reschedule the timer with the interval delay
u64 interval_microseconds = timer->interval_delay / 1000;
- CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
+ CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
timer_callback_event_type, timer_handle);
}
}
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
new file mode 100644
index 00000000..b2dd2154
--- /dev/null
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -0,0 +1,245 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+
+#include "core/hle/kernel/vm_manager.h"
+#include "core/memory_setup.h"
+
+namespace Kernel {
+
+bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
+ ASSERT(base + size == next.base);
+ if (permissions != next.permissions ||
+ meminfo_state != next.meminfo_state ||
+ type != next.type) {
+ return false;
+ }
+ if (type == VMAType::AllocatedMemoryBlock &&
+ (backing_block != next.backing_block || offset + size != next.offset)) {
+ return false;
+ }
+ if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) {
+ return false;
+ }
+ if (type == VMAType::MMIO && paddr + size != next.paddr) {
+ return false;
+ }
+ return true;
+}
+
+VMManager::VMManager() {
+ Reset();
+}
+
+void VMManager::Reset() {
+ vma_map.clear();
+
+ // Initialize the map with a single free region covering the entire managed space.
+ VirtualMemoryArea initial_vma;
+ initial_vma.size = MAX_ADDRESS;
+ vma_map.emplace(initial_vma.base, initial_vma);
+
+ UpdatePageTableForVMA(initial_vma);
+}
+
+VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
+ return std::prev(vma_map.upper_bound(target));
+}
+
+ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
+ std::shared_ptr<std::vector<u8>> block, u32 offset, u32 size, MemoryState state) {
+ ASSERT(block != nullptr);
+ ASSERT(offset + size <= block->size());
+
+ // 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;
+ ASSERT(final_vma.size == size);
+
+ final_vma.type = VMAType::AllocatedMemoryBlock;
+ final_vma.permissions = VMAPermission::ReadWrite;
+ final_vma.meminfo_state = state;
+ final_vma.backing_block = block;
+ final_vma.offset = offset;
+ UpdatePageTableForVMA(final_vma);
+
+ return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
+}
+
+ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) {
+ ASSERT(memory != nullptr);
+
+ // 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;
+ ASSERT(final_vma.size == size);
+
+ final_vma.type = VMAType::BackingMemory;
+ final_vma.permissions = VMAPermission::ReadWrite;
+ final_vma.meminfo_state = state;
+ final_vma.backing_memory = memory;
+ UpdatePageTableForVMA(final_vma);
+
+ return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
+}
+
+ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state) {
+ // 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;
+ ASSERT(final_vma.size == size);
+
+ final_vma.type = VMAType::MMIO;
+ final_vma.permissions = VMAPermission::ReadWrite;
+ final_vma.meminfo_state = state;
+ final_vma.paddr = paddr;
+ UpdatePageTableForVMA(final_vma);
+
+ return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
+}
+
+void VMManager::Unmap(VMAHandle vma_handle) {
+ VMAIter iter = StripIterConstness(vma_handle);
+
+ VirtualMemoryArea& vma = iter->second;
+ vma.type = VMAType::Free;
+ vma.permissions = VMAPermission::None;
+ vma.meminfo_state = MemoryState::Free;
+
+ vma.backing_block = nullptr;
+ vma.offset = 0;
+ vma.backing_memory = nullptr;
+ vma.paddr = 0;
+
+ UpdatePageTableForVMA(vma);
+
+ MergeAdjacent(iter);
+}
+
+void VMManager::Reprotect(VMAHandle vma_handle, VMAPermission new_perms) {
+ VMAIter iter = StripIterConstness(vma_handle);
+
+ VirtualMemoryArea& vma = iter->second;
+ vma.permissions = new_perms;
+ UpdatePageTableForVMA(vma);
+
+ MergeAdjacent(iter);
+}
+
+VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) {
+ // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given
+ // non-const access to its container.
+ return vma_map.erase(iter, iter); // Erases an empty range of elements
+}
+
+ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) {
+ ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: %8X", size);
+ ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: %08X", base);
+
+ VMAIter vma_handle = StripIterConstness(FindVMA(base));
+ if (vma_handle == vma_map.end()) {
+ // Target address is outside the range managed by the kernel
+ return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
+ ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E01BF5
+ }
+
+ VirtualMemoryArea& vma = vma_handle->second;
+ if (vma.type != VMAType::Free) {
+ // Region is already allocated
+ return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
+ ErrorSummary::InvalidState, ErrorLevel::Usage); // 0xE0A01BF5
+ }
+
+ u32 start_in_vma = base - vma.base;
+ u32 end_in_vma = start_in_vma + size;
+
+ if (end_in_vma > vma.size) {
+ // Requested allocation doesn't fit inside VMA
+ return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
+ ErrorSummary::InvalidState, ErrorLevel::Usage); // 0xE0A01BF5
+ }
+
+ if (end_in_vma != vma.size) {
+ // Split VMA at the end of the allocated region
+ SplitVMA(vma_handle, end_in_vma);
+ }
+ if (start_in_vma != 0) {
+ // Split VMA at the start of the allocated region
+ vma_handle = SplitVMA(vma_handle, start_in_vma);
+ }
+
+ return MakeResult<VMAIter>(vma_handle);
+}
+
+VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u32 offset_in_vma) {
+ VirtualMemoryArea& old_vma = vma_handle->second;
+ VirtualMemoryArea new_vma = old_vma; // Make a copy of the VMA
+
+ // For now, don't allow no-op VMA splits (trying to split at a boundary) because it's probably
+ // a bug. This restriction might be removed later.
+ ASSERT(offset_in_vma < old_vma.size);
+ ASSERT(offset_in_vma > 0);
+
+ old_vma.size = offset_in_vma;
+ new_vma.base += offset_in_vma;
+ new_vma.size -= offset_in_vma;
+
+ switch (new_vma.type) {
+ case VMAType::Free:
+ break;
+ case VMAType::AllocatedMemoryBlock:
+ new_vma.offset += offset_in_vma;
+ break;
+ case VMAType::BackingMemory:
+ new_vma.backing_memory += offset_in_vma;
+ break;
+ case VMAType::MMIO:
+ new_vma.paddr += offset_in_vma;
+ break;
+ }
+
+ ASSERT(old_vma.CanBeMergedWith(new_vma));
+
+ return vma_map.emplace_hint(std::next(vma_handle), new_vma.base, new_vma);
+}
+
+VMManager::VMAIter VMManager::MergeAdjacent(VMAIter iter) {
+ VMAIter next_vma = std::next(iter);
+ if (next_vma != vma_map.end() && iter->second.CanBeMergedWith(next_vma->second)) {
+ iter->second.size += next_vma->second.size;
+ vma_map.erase(next_vma);
+ }
+
+ if (iter != vma_map.begin()) {
+ VMAIter prev_vma = std::prev(iter);
+ if (prev_vma->second.CanBeMergedWith(iter->second)) {
+ prev_vma->second.size += iter->second.size;
+ vma_map.erase(iter);
+ iter = prev_vma;
+ }
+ }
+
+ return iter;
+}
+
+void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
+ switch (vma.type) {
+ case VMAType::Free:
+ Memory::UnmapRegion(vma.base, vma.size);
+ break;
+ case VMAType::AllocatedMemoryBlock:
+ Memory::MapMemoryRegion(vma.base, vma.size, vma.backing_block->data() + vma.offset);
+ break;
+ case VMAType::BackingMemory:
+ 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);
+ break;
+ }
+}
+
+}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
new file mode 100644
index 00000000..22b72460
--- /dev/null
+++ b/src/core/hle/kernel/vm_manager.h
@@ -0,0 +1,200 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/common_types.h"
+
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+enum class VMAType : u8 {
+ /// VMA represents an unmapped region of the address space.
+ Free,
+ /// VMA is backed by a ref-counted allocate memory block.
+ AllocatedMemoryBlock,
+ /// VMA is backed by a raw, unmanaged pointer.
+ BackingMemory,
+ /// VMA is mapped to MMIO registers at a fixed PAddr.
+ MMIO,
+ // TODO(yuriks): Implement MemoryAlias to support MAP/UNMAP
+};
+
+/// Permissions for mapped memory blocks
+enum class VMAPermission : u8 {
+ None = 0,
+ Read = 1,
+ Write = 2,
+ Execute = 4,
+
+ ReadWrite = Read | Write,
+ ReadExecute = Read | Execute,
+ WriteExecute = Write | Execute,
+ ReadWriteExecute = Read | Write | Execute,
+};
+
+/// Set of values returned in MemoryInfo.state by svcQueryMemory.
+enum class MemoryState : u8 {
+ Free = 0,
+ Reserved = 1,
+ IO = 2,
+ Static = 3,
+ Code = 4,
+ Private = 5,
+ Shared = 6,
+ Continuous = 7,
+ Aliased = 8,
+ Alias = 9,
+ AliasCode = 10,
+ Locked = 11,
+};
+
+/**
+ * Represents a VMA in an address space. A VMA is a contiguous region of virtual addressing space
+ * with homogeneous attributes across its extents. In this particular implementation each VMA is
+ * also backed by a single host memory allocation.
+ */
+struct VirtualMemoryArea {
+ /// Virtual base address of the region.
+ VAddr base = 0;
+ /// Size of the region.
+ u32 size = 0;
+
+ VMAType type = VMAType::Free;
+ VMAPermission permissions = VMAPermission::None;
+ /// Tag returned by svcQueryMemory. Not otherwise used.
+ MemoryState meminfo_state = MemoryState::Free;
+
+ // Settings for type = AllocatedMemoryBlock
+ /// Memory block backing this VMA.
+ std::shared_ptr<std::vector<u8>> backing_block = nullptr;
+ /// Offset into the backing_memory the mapping starts from.
+ u32 offset = 0;
+
+ // Settings for type = BackingMemory
+ /// Pointer backing this VMA. It will not be destroyed or freed when the VMA is removed.
+ u8* backing_memory = nullptr;
+
+ // Settings for type = MMIO
+ /// Physical address of the register area this VMA maps to.
+ PAddr paddr = 0;
+
+ /// Tests if this area can be merged to the right with `next`.
+ bool CanBeMergedWith(const VirtualMemoryArea& next) const;
+};
+
+/**
+ * Manages a process' virtual addressing space. This class maintains a list of allocated and free
+ * regions in the address space, along with their attributes, and allows kernel clients to
+ * manipulate it, adjusting the page table to match.
+ *
+ * This is similar in idea and purpose to the VM manager present in operating system kernels, with
+ * the main difference being that it doesn't have to support swapping or memory mapping of files.
+ * The implementation is also simplified by not having to allocate page frames. See these articles
+ * about the Linux kernel for an explantion of the concept and implementation:
+ * - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/
+ * - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/
+ */
+class VMManager {
+ // TODO(yuriks): Make page tables switchable to support multiple VMManagers
+public:
+ /**
+ * The maximum amount of address space managed by the kernel. Addresses above this are never used.
+ * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000.
+ */
+ static const u32 MAX_ADDRESS = 0x40000000;
+
+ /**
+ * A map covering the entirety of the managed address space, keyed by the `base` field of each
+ * VMA. It must always be modified by splitting or merging VMAs, so that the invariant
+ * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be
+ * merged when possible so that no two similar and adjacent regions exist that have not been
+ * merged.
+ */
+ std::map<VAddr, VirtualMemoryArea> vma_map;
+ using VMAHandle = decltype(vma_map)::const_iterator;
+
+ VMManager();
+
+ /// Clears the address space map, re-initializing with a single free area.
+ void Reset();
+
+ /// Finds the VMA in which the given address is included in, or `vma_map.end()`.
+ VMAHandle FindVMA(VAddr target) const;
+
+ // TODO(yuriks): Should these functions actually return the handle?
+
+ /**
+ * Maps part of a ref-counted block of memory at a given address.
+ *
+ * @param target The guest address to start the mapping at.
+ * @param block The block to be mapped.
+ * @param offset Offset into `block` to map from.
+ * @param size Size of the mapping.
+ * @param state MemoryState tag to attach to the VMA.
+ */
+ ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block,
+ u32 offset, u32 size, MemoryState state);
+
+ /**
+ * Maps an unmanaged host memory pointer at a given address.
+ *
+ * @param target The guest address to start the mapping at.
+ * @param memory The memory to be mapped.
+ * @param size Size of the mapping.
+ * @param state MemoryState tag to attach to the VMA.
+ */
+ ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u32 size, MemoryState state);
+
+ /**
+ * Maps a memory-mapped IO region at a given address.
+ *
+ * @param target The guest address to start the mapping at.
+ * @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.
+ */
+ ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state);
+
+ /// Unmaps the given VMA.
+ void Unmap(VMAHandle vma);
+
+ /// Changes the permissions of the given VMA.
+ void Reprotect(VMAHandle vma, VMAPermission new_perms);
+
+private:
+ using VMAIter = decltype(vma_map)::iterator;
+
+ /// Converts a VMAHandle to a mutable VMAIter.
+ VMAIter StripIterConstness(const VMAHandle& iter);
+
+ /**
+ * Carves a VMA of a specific size at the specified address by splitting Free VMAs while doing
+ * the appropriate error checking.
+ */
+ ResultVal<VMAIter> CarveVMA(VAddr base, u32 size);
+
+ /**
+ * Splits a VMA in two, at the specified offset.
+ * @returns the right side of the split, with the original iterator becoming the left side.
+ */
+ VMAIter SplitVMA(VMAIter vma, u32 offset_in_vma);
+
+ /**
+ * Checks for and merges the specified VMA with adjacent ones if possible.
+ * @returns the merged VMA or the original if no merging was possible.
+ */
+ VMAIter MergeAdjacent(VMAIter vma);
+
+ /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
+ void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
+};
+
+}
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
new file mode 100644
index 00000000..57dc1ece
--- /dev/null
+++ b/src/core/hle/service/am/am.cpp
@@ -0,0 +1,55 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+
+#include "core/hle/service/service.h"
+#include "core/hle/service/am/am_app.h"
+#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 {
+
+void TitleIDListGetTotal(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 media_type = cmd_buff[1] & 0xFF;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = 0;
+
+ LOG_WARNING(Service_AM, "(STUBBED) media_type %u", media_type);
+}
+
+void GetTitleIDList(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 num_titles = cmd_buff[1];
+ u32 media_type = cmd_buff[2] & 0xFF;
+ u32 addr = cmd_buff[4];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = 0;
+
+ LOG_WARNING(Service_AM, "(STUBBED) Requested %u titles from media type %u", num_titles, media_type);
+}
+
+void Init() {
+ using namespace Kernel;
+
+ AddService(new AM_APP_Interface);
+ AddService(new AM_NET_Interface);
+ AddService(new AM_SYS_Interface);
+}
+
+void Shutdown() {
+
+}
+
+} // namespace AM
+
+} // namespace Service
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
new file mode 100644
index 00000000..063b8bd0
--- /dev/null
+++ b/src/core/hle/service/am/am.h
@@ -0,0 +1,47 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace AM {
+
+/**
+ * AM::TitleIDListGetTotal service function
+ * Gets the number of installed titles in the requested media type
+ * Inputs:
+ * 0 : Command header (0x00010040)
+ * 1 : Media type to load the titles from
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ * 2 : The number of titles in the requested media type
+ */
+void TitleIDListGetTotal(Service::Interface* self);
+
+/**
+ * AM::GetTitleIDList service function
+ * Loads information about the desired number of titles from the desired media type into an array
+ * Inputs:
+ * 0 : Command header (0x00020082)
+ * 1 : The maximum number of titles to load
+ * 2 : Media type to load the titles from
+ * 3 : Descriptor of the output buffer pointer
+ * 4 : Address of the output buffer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ * 2 : The number of titles loaded from the requested media type
+ */
+void GetTitleIDList(Service::Interface* self);
+
+/// Initialize AM service
+void Init();
+
+/// Shutdown AM service
+void Shutdown();
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp
new file mode 100644
index 00000000..c6fc81bc
--- /dev/null
+++ b/src/core/hle/service/am/am_app.cpp
@@ -0,0 +1,20 @@
+// Copyright 2014 Citra Emulator Project
+// 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"
+
+namespace Service {
+namespace AM {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+AM_APP_Interface::AM_APP_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/am_app.h b/src/core/hle/service/am/am_app.h
new file mode 100644
index 00000000..fd6017d1
--- /dev/null
+++ b/src/core/hle/service/am/am_app.h
@@ -0,0 +1,22 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace AM {
+
+class AM_APP_Interface : public Service::Interface {
+public:
+ AM_APP_Interface();
+
+ std::string GetPortName() const override {
+ return "am:app";
+ }
+};
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am/am_net.cpp
index ba2a499f..b1af0e9d 100644
--- a/src/core/hle/service/am_net.cpp
+++ b/src/core/hle/service/am/am_net.cpp
@@ -3,12 +3,11 @@
// Refer to the license.txt file included.
#include "core/hle/hle.h"
-#include "core/hle/service/am_net.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/am_net.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace AM_NET
-
-namespace AM_NET {
+namespace Service {
+namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
{0x08010000, nullptr, "OpenTicket"},
@@ -33,11 +32,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x081B00C2, nullptr, "InstallTitlesFinish"},
};
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
+AM_NET_Interface::AM_NET_Interface() {
Register(FunctionTable);
}
-} // namespace
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/am_net.h b/src/core/hle/service/am/am_net.h
new file mode 100644
index 00000000..25d2c3f2
--- /dev/null
+++ b/src/core/hle/service/am/am_net.h
@@ -0,0 +1,22 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace AM {
+
+class AM_NET_Interface : public Service::Interface {
+public:
+ AM_NET_Interface();
+
+ std::string GetPortName() const override {
+ return "am:net";
+ }
+};
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp
new file mode 100644
index 00000000..864fc14d
--- /dev/null
+++ b/src/core/hle/service/am/am_sys.cpp
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// 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"
+
+namespace Service {
+namespace AM {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
+ {0x00020082, GetTitleIDList, "GetTitleIDList"},
+};
+
+AM_SYS_Interface::AM_SYS_Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/am_sys.h b/src/core/hle/service/am/am_sys.h
new file mode 100644
index 00000000..b114f1d3
--- /dev/null
+++ b/src/core/hle/service/am/am_sys.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace AM {
+
+class AM_SYS_Interface : public Service::Interface {
+public:
+ AM_SYS_Interface();
+
+ std::string GetPortName() const override {
+ return "am:sys";
+ }
+};
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp
new file mode 100644
index 00000000..6bf84b36
--- /dev/null
+++ b/src/core/hle/service/am/am_u.cpp
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// 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"
+
+namespace Service {
+namespace AM {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
+ {0x00020082, GetTitleIDList, "GetTitleIDList"},
+};
+
+AM_U_Interface::AM_U_Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/am_u.h b/src/core/hle/service/am/am_u.h
new file mode 100644
index 00000000..3b2454b6
--- /dev/null
+++ b/src/core/hle/service/am/am_u.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace AM {
+
+class AM_U_Interface : public Service::Interface {
+public:
+ AM_U_Interface();
+
+ std::string GetPortName() const override {
+ return "am:u";
+ }
+};
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am_app.cpp b/src/core/hle/service/am_app.cpp
deleted file mode 100644
index 684b753f..00000000
--- a/src/core/hle/service/am_app.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/am_app.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace AM_APP
-
-namespace AM_APP {
-
-// Empty arrays are illegal -- commented out until an entry is added.
-//const Interface::FunctionInfo FunctionTable[] = { };
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- //Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/am_app.h b/src/core/hle/service/am_app.h
deleted file mode 100644
index 50dc2f5a..00000000
--- a/src/core/hle/service/am_app.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace AM_APP
-
-namespace AM_APP {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "am:app";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/am_net.h b/src/core/hle/service/am_net.h
deleted file mode 100644
index 616c33ee..00000000
--- a/src/core/hle/service/am_net.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace AM_NET
-
-namespace AM_NET {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "am:net";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/am_sys.cpp b/src/core/hle/service/am_sys.cpp
deleted file mode 100644
index f9e3fe4b..00000000
--- a/src/core/hle/service/am_sys.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// 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/am_sys.h"
-
-namespace AM_SYS {
-
-/**
- * Gets the number of installed titles in the requested media type
- * Inputs:
- * 0: Command header (0x00010040)
- * 1: Media type to load the titles from
- * Outputs:
- * 1: Result, 0 on success, otherwise error code
- * 2: The number of titles in the requested media type
- */
-static void TitleIDListGetTotal(Service::Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 media_type = cmd_buff[1] & 0xFF;
-
- cmd_buff[1] = RESULT_SUCCESS.raw;
- cmd_buff[2] = 0;
- LOG_WARNING(Service_CFG, "(STUBBED) media_type %u", media_type);
-}
-
-/**
- * Loads information about the desired number of titles from the desired media type into an array
- * Inputs:
- * 0: Command header (0x00020082)
- * 1: The maximum number of titles to load
- * 2: Media type to load the titles from
- * 3: Descriptor of the output buffer pointer
- * 4: Address of the output buffer
- * Outputs:
- * 1: Result, 0 on success, otherwise error code
- * 2: The number of titles loaded from the requested media type
- */
-static void GetTitleIDList(Service::Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 num_titles = cmd_buff[1];
- u32 media_type = cmd_buff[2] & 0xFF;
- u32 addr = cmd_buff[4];
-
- cmd_buff[1] = RESULT_SUCCESS.raw;
- cmd_buff[2] = 0;
- LOG_WARNING(Service_CFG, "(STUBBED) Requested %u titles from media type %u", num_titles, media_type);
-}
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
- {0x00020082, GetTitleIDList, "GetTitleIDList"},
-};
-
-Interface::Interface() {
- Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/am_sys.h b/src/core/hle/service/am_sys.h
deleted file mode 100644
index bb6178a4..00000000
--- a/src/core/hle/service/am_sys.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace AM_SYS
-
-namespace AM_SYS {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "am:sys";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 3fd4cfb0..5d14f393 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -151,7 +151,7 @@ void SendParameter(Service::Interface* self) {
u32 handle = cmd_buff[6];
u32 size = cmd_buff[7];
u32 in_param_buffer_ptr = cmd_buff[8];
-
+
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X,"
@@ -283,7 +283,7 @@ void Init() {
AddService(new APT_A_Interface);
AddService(new APT_S_Interface);
AddService(new APT_U_Interface);
-
+
// Load the shared system font (if available).
// The expected format is a decrypted, uncompressed BCFNT file with the 0x80 byte header
// generated by the APT:U service. The best way to get is by dumping it from RAM. We've provided
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index e7fa3932..a03e1712 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -63,7 +63,7 @@ void Initialize(Service::Interface* self);
* 4 : Handle to shared font memory
*/
void GetSharedFont(Service::Interface* self);
-
+
/**
* APT::NotifyToWait service function
* Inputs:
@@ -88,7 +88,7 @@ void Enable(Service::Interface* self);
* 4 : Home Menu AppId
* 5 : AppID of currently active app
*/
-void GetAppletManInfo(Service::Interface* self);
+void GetAppletManInfo(Service::Interface* self);
/**
* APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet.
@@ -100,14 +100,14 @@ void GetAppletManInfo(Service::Interface* self);
* Outputs:
* 0 : Return header
* 1 : Result of function, 0 on success, otherwise error code
- * 2 : Output, 0 = not registered, 1 = registered.
+ * 2 : Output, 0 = not registered, 1 = registered.
*/
void IsRegistered(Service::Interface* self);
void InquireNotification(Service::Interface* self);
/**
- * APT::SendParameter service function. This sets the parameter data state.
+ * APT::SendParameter service function. This sets the parameter data state.
* Inputs:
* 1 : Source AppID
* 2 : Destination AppID
diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp
new file mode 100644
index 00000000..d38140f1
--- /dev/null
+++ b/src/core/hle/service/boss/boss.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 "core/hle/service/service.h"
+#include "core/hle/service/boss/boss.h"
+#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 {
+
+void Init() {
+ using namespace Kernel;
+
+ AddService(new BOSS_P_Interface);
+ AddService(new BOSS_U_Interface);
+}
+
+void Shutdown() {
+}
+
+} // namespace BOSS
+
+} // namespace Service
diff --git a/src/core/hle/service/boss/boss.h b/src/core/hle/service/boss/boss.h
new file mode 100644
index 00000000..a6942ada
--- /dev/null
+++ b/src/core/hle/service/boss/boss.h
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace BOSS {
+
+/// Initialize BOSS service(s)
+void Init();
+
+/// Shutdown BOSS service(s)
+void Shutdown();
+
+} // namespace BOSS
+} // namespace Service
diff --git a/src/core/hle/service/boss/boss_p.cpp b/src/core/hle/service/boss/boss_p.cpp
new file mode 100644
index 00000000..089f5f18
--- /dev/null
+++ b/src/core/hle/service/boss/boss_p.cpp
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// 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 {
+namespace BOSS {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+// const Interface::FunctionInfo FunctionTable[] = { };
+
+BOSS_P_Interface::BOSS_P_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace BOSS
+} // namespace Service
diff --git a/src/core/hle/service/boss/boss_p.h b/src/core/hle/service/boss/boss_p.h
new file mode 100644
index 00000000..32112c25
--- /dev/null
+++ b/src/core/hle/service/boss/boss_p.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace BOSS {
+
+class BOSS_P_Interface : public Service::Interface {
+public:
+ BOSS_P_Interface();
+
+ std::string GetPortName() const override {
+ return "boss:P";
+ }
+};
+
+} // namespace BOSS
+} // namespace Service
diff --git a/src/core/hle/service/boss/boss_u.cpp b/src/core/hle/service/boss/boss_u.cpp
new file mode 100644
index 00000000..ed978b96
--- /dev/null
+++ b/src/core/hle/service/boss/boss_u.cpp
@@ -0,0 +1,21 @@
+// Copyright 2014 Citra Emulator Project
+// 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 {
+namespace BOSS {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00020100, nullptr, "GetStorageInfo"},
+};
+
+BOSS_U_Interface::BOSS_U_Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace BOSS
+} // namespace Service
diff --git a/src/core/hle/service/boss/boss_u.h b/src/core/hle/service/boss/boss_u.h
new file mode 100644
index 00000000..d047d8cf
--- /dev/null
+++ b/src/core/hle/service/boss/boss_u.h
@@ -0,0 +1,22 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace BOSS {
+
+class BOSS_U_Interface : public Service::Interface {
+public:
+ BOSS_U_Interface();
+
+ std::string GetPortName() const override {
+ return "boss:U";
+ }
+};
+
+} // namespace BOSS
+} // namespace Service
diff --git a/src/core/hle/service/boss_p.cpp b/src/core/hle/service/boss_p.cpp
deleted file mode 100644
index 8280830e..00000000
--- a/src/core/hle/service/boss_p.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/boss_p.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace BOSS_P
-
-namespace BOSS_P {
-
-// Empty arrays are illegal -- commented out until an entry is added.
-// const Interface::FunctionInfo FunctionTable[] = { };
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- //Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/boss_p.h b/src/core/hle/service/boss_p.h
deleted file mode 100644
index 71f1e746..00000000
--- a/src/core/hle/service/boss_p.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace BOSS_P
-
-namespace BOSS_P {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "boss:P";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/boss_u.cpp b/src/core/hle/service/boss_u.cpp
deleted file mode 100644
index 2c322bdf..00000000
--- a/src/core/hle/service/boss_u.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/boss_u.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace BOSS_U
-
-namespace BOSS_U {
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x00020100, nullptr, "GetStorageInfo"},
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/boss_u.h b/src/core/hle/service/boss_u.h
deleted file mode 100644
index 2668f2df..00000000
--- a/src/core/hle/service/boss_u.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace BOSS_U
-
-namespace BOSS_U {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "boss:U";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp
new file mode 100644
index 00000000..4f34b699
--- /dev/null
+++ b/src/core/hle/service/cam/cam.cpp
@@ -0,0 +1,35 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+
+#include "core/hle/service/service.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"
+
+namespace Service {
+namespace CAM {
+
+void Init() {
+ using namespace Kernel;
+
+ AddService(new CAM_C_Interface);
+ AddService(new CAM_Q_Interface);
+ AddService(new CAM_S_Interface);
+ AddService(new CAM_U_Interface);
+}
+
+void Shutdown() {
+}
+
+} // namespace CAM
+
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h
new file mode 100644
index 00000000..edd52484
--- /dev/null
+++ b/src/core/hle/service/cam/cam.h
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace CAM {
+
+/// Initialize CAM service(s)
+void Init();
+
+/// Shutdown CAM service(s)
+void Shutdown();
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_c.cpp b/src/core/hle/service/cam/cam_c.cpp
new file mode 100644
index 00000000..d35adcb9
--- /dev/null
+++ b/src/core/hle/service/cam/cam_c.cpp
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// 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 {
+namespace CAM {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+CAM_C_Interface::CAM_C_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_c.h b/src/core/hle/service/cam/cam_c.h
new file mode 100644
index 00000000..6b296c00
--- /dev/null
+++ b/src/core/hle/service/cam/cam_c.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace CAM {
+
+class CAM_C_Interface : public Service::Interface {
+public:
+ CAM_C_Interface();
+
+ std::string GetPortName() const override {
+ return "cam:c";
+ }
+};
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_q.cpp b/src/core/hle/service/cam/cam_q.cpp
new file mode 100644
index 00000000..c2760a10
--- /dev/null
+++ b/src/core/hle/service/cam/cam_q.cpp
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// 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 {
+namespace CAM {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+CAM_Q_Interface::CAM_Q_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_q.h b/src/core/hle/service/cam/cam_q.h
new file mode 100644
index 00000000..07cc1253
--- /dev/null
+++ b/src/core/hle/service/cam/cam_q.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace CAM {
+
+class CAM_Q_Interface : public Service::Interface {
+public:
+ CAM_Q_Interface();
+
+ std::string GetPortName() const override {
+ return "cam:q";
+ }
+};
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_s.cpp b/src/core/hle/service/cam/cam_s.cpp
new file mode 100644
index 00000000..aefbf7df
--- /dev/null
+++ b/src/core/hle/service/cam/cam_s.cpp
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// 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 {
+namespace CAM {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+CAM_S_Interface::CAM_S_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_s.h b/src/core/hle/service/cam/cam_s.h
new file mode 100644
index 00000000..0a5d6fca
--- /dev/null
+++ b/src/core/hle/service/cam/cam_s.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace CAM {
+
+class CAM_S_Interface : public Service::Interface {
+public:
+ CAM_S_Interface();
+
+ std::string GetPortName() const override {
+ return "cam:s";
+ }
+};
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_u.cpp b/src/core/hle/service/cam/cam_u.cpp
new file mode 100644
index 00000000..1c6aca95
--- /dev/null
+++ b/src/core/hle/service/cam/cam_u.cpp
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// 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"
+
+namespace Service {
+namespace CAM {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+CAM_U_Interface::CAM_U_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam/cam_u.h b/src/core/hle/service/cam/cam_u.h
new file mode 100644
index 00000000..36926403
--- /dev/null
+++ b/src/core/hle/service/cam/cam_u.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace CAM {
+
+class CAM_U_Interface : public Service::Interface {
+public:
+ CAM_U_Interface();
+
+ std::string GetPortName() const override {
+ return "cam:u";
+ }
+};
+
+} // namespace CAM
+} // namespace Service
diff --git a/src/core/hle/service/cam_u.cpp b/src/core/hle/service/cam_u.cpp
deleted file mode 100644
index fcfd8771..00000000
--- a/src/core/hle/service/cam_u.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/cam_u.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace CAM_U
-
-namespace CAM_U {
-
-// Empty arrays are illegal -- commented out until an entry is added.
-//const Interface::FunctionInfo FunctionTable[] = { };
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- //Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/cam_u.h b/src/core/hle/service/cam_u.h
deleted file mode 100644
index 878c20a8..00000000
--- a/src/core/hle/service/cam_u.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace CAM_U
-
-namespace CAM_U {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "cam:u";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp
new file mode 100644
index 00000000..db0e52b7
--- /dev/null
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -0,0 +1,31 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+
+#include "core/hle/service/service.h"
+#include "core/hle/service/cecd/cecd.h"
+#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 {
+
+void Init() {
+ using namespace Kernel;
+
+ AddService(new CECD_S_Interface);
+ AddService(new CECD_U_Interface);
+}
+
+void Shutdown() {
+}
+
+} // namespace CECD
+
+} // namespace Service
diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h
new file mode 100644
index 00000000..32fd2045
--- /dev/null
+++ b/src/core/hle/service/cecd/cecd.h
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace CECD {
+
+/// Initialize CECD service(s)
+void Init();
+
+/// Shutdown CECD service(s)
+void Shutdown();
+
+} // namespace CECD
+} // namespace Service
diff --git a/src/core/hle/service/cecd/cecd_s.cpp b/src/core/hle/service/cecd/cecd_s.cpp
new file mode 100644
index 00000000..72d7e8d4
--- /dev/null
+++ b/src/core/hle/service/cecd/cecd_s.cpp
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// 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 {
+namespace CECD {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+CECD_S_Interface::CECD_S_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace CECD
+} // namespace Service
diff --git a/src/core/hle/service/cecd_s.h b/src/core/hle/service/cecd/cecd_s.h
index d880d039..df5c0184 100644
--- a/src/core/hle/service/cecd_s.h
+++ b/src/core/hle/service/cecd/cecd_s.h
@@ -6,18 +6,17 @@
#include "core/hle/service/service.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace CECD_S
+namespace Service {
+namespace CECD {
-namespace CECD_S {
-
-class Interface : public Service::Interface {
+class CECD_S_Interface : public Interface {
public:
- Interface();
+ CECD_S_Interface();
std::string GetPortName() const override {
return "cecd:s";
}
};
-} // namespace
+} // namespace CECD
+} // namespace Service
diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp
new file mode 100644
index 00000000..0a23bafb
--- /dev/null
+++ b/src/core/hle/service/cecd/cecd_u.cpp
@@ -0,0 +1,20 @@
+// Copyright 2014 Citra Emulator Project
+// 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[] = { };
+
+CECD_U_Interface::CECD_U_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace CECD
+} // namespace Service
diff --git a/src/core/hle/service/cecd_u.h b/src/core/hle/service/cecd/cecd_u.h
index e6756413..394030ff 100644
--- a/src/core/hle/service/cecd_u.h
+++ b/src/core/hle/service/cecd/cecd_u.h
@@ -6,18 +6,17 @@
#include "core/hle/service/service.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace CECD_U
+namespace Service {
+namespace CECD {
-namespace CECD_U {
-
-class Interface : public Service::Interface {
+class CECD_U_Interface : public Interface {
public:
- Interface();
+ CECD_U_Interface();
std::string GetPortName() const override {
return "cecd:u";
}
};
-} // namespace
+} // namespace CECD
+} // namespace Service
diff --git a/src/core/hle/service/cecd_s.cpp b/src/core/hle/service/cecd_s.cpp
deleted file mode 100644
index b298f151..00000000
--- a/src/core/hle/service/cecd_s.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/cecd_s.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace CECD_S
-
-namespace CECD_S {
-
-// Empty arrays are illegal -- commented out until an entry is added.
-//const Interface::FunctionInfo FunctionTable[] = { };
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- //Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/cecd_u.cpp b/src/core/hle/service/cecd_u.cpp
deleted file mode 100644
index 9125364b..00000000
--- a/src/core/hle/service/cecd_u.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/cecd_u.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace CECD_U
-
-namespace CECD_U {
-
-// Empty arrays are illegal -- commented out until an entry is added.
-//const Interface::FunctionInfo FunctionTable[] = { };
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- //Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index d4268288..62ad90fd 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -315,11 +315,11 @@ void Init() {
AddService(new CFG_I_Interface);
AddService(new CFG_S_Interface);
AddService(new CFG_U_Interface);
-
+
// Open the SystemSaveData archive 0x00010017
FileSys::Path archive_path(cfg_system_savedata_id);
auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
-
+
// If the archive didn't exist, create the files inside
if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) {
// Format the archive to create the directories
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
new file mode 100644
index 00000000..2911ab40
--- /dev/null
+++ b/src/core/hle/service/frd/frd.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 "core/hle/service/service.h"
+#include "core/hle/service/frd/frd.h"
+#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 {
+
+void Init() {
+ using namespace Kernel;
+
+ AddService(new FRD_A_Interface);
+ AddService(new FRD_U_Interface);
+}
+
+void Shutdown() {
+}
+
+} // namespace FRD
+
+} // namespace Service
diff --git a/src/core/hle/service/frd/frd.h b/src/core/hle/service/frd/frd.h
new file mode 100644
index 00000000..41f7a2f6
--- /dev/null
+++ b/src/core/hle/service/frd/frd.h
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace FRD {
+
+/// Initialize FRD service(s)
+void Init();
+
+/// Shutdown FRD service(s)
+void Shutdown();
+
+} // namespace FRD
+} // namespace Service
diff --git a/src/core/hle/service/frd/frd_a.cpp b/src/core/hle/service/frd/frd_a.cpp
new file mode 100644
index 00000000..1c438a33
--- /dev/null
+++ b/src/core/hle/service/frd/frd_a.cpp
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// 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 {
+namespace FRD {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+// const Interface::FunctionInfo FunctionTable[] = { };
+
+FRD_A_Interface::FRD_A_Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace FRD
+} // namespace Service
diff --git a/src/core/hle/service/frd_a.h b/src/core/hle/service/frd/frd_a.h
index f068c610..006d1cad 100644
--- a/src/core/hle/service/frd_a.h
+++ b/src/core/hle/service/frd/frd_a.h
@@ -6,18 +6,17 @@
#include "core/hle/service/service.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace FRD_A
+namespace Service {
+namespace FRD {
-namespace FRD_A {
-
-class Interface : public Service::Interface {
+class FRD_A_Interface : public Service::Interface {
public:
- Interface();
+ FRD_A_Interface();
std::string GetPortName() const override {
return "frd:a";
}
};
-} // namespace
+} // namespace FRD
+} // namespace Service
diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp
index 6d2ff1e2..439c7282 100644
--- a/src/core/hle/service/frd_u.cpp
+++ b/src/core/hle/service/frd/frd_u.cpp
@@ -3,12 +3,11 @@
// Refer to the license.txt file included.
#include "core/hle/hle.h"
-#include "core/hle/service/frd_u.h"
+#include "core/hle/service/frd/frd.h"
+#include "core/hle/service/frd/frd_u.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace FRD_U
-
-namespace FRD_U {
+namespace Service {
+namespace FRD {
const Interface::FunctionInfo FunctionTable[] = {
{0x00050000, nullptr, "GetFriendKey"},
@@ -22,11 +21,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00320042, nullptr, "SetClientSdkVersion"}
};
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
+FRD_U_Interface::FRD_U_Interface() {
Register(FunctionTable);
}
-} // namespace
+} // namespace FRD
+} // namespace Service
diff --git a/src/core/hle/service/frd_u.h b/src/core/hle/service/frd/frd_u.h
index ab8897d5..07e43f15 100644
--- a/src/core/hle/service/frd_u.h
+++ b/src/core/hle/service/frd/frd_u.h
@@ -6,18 +6,17 @@
#include "core/hle/service/service.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace FRD_U
+namespace Service {
+namespace FRD {
-namespace FRD_U {
-
-class Interface : public Service::Interface {
+class FRD_U_Interface : public Service::Interface {
public:
- Interface();
+ FRD_U_Interface();
std::string GetPortName() const override {
return "frd:u";
}
};
-} // namespace
+} // namespace FRD
+} // namespace Service
diff --git a/src/core/hle/service/frd_a.cpp b/src/core/hle/service/frd_a.cpp
deleted file mode 100644
index 56997931..00000000
--- a/src/core/hle/service/frd_a.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/frd_a.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace FRD_A
-
-namespace FRD_A {
-
-// Empty arrays are illegal -- commented out until an entry is added.
-// const Interface::FunctionInfo FunctionTable[] = { };
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- //Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 6d4a9c7c..4e275cb1 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -254,7 +254,7 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
- // This should never even happen in the first place with 64-bit handles,
+ // This should never even happen in the first place with 64-bit handles,
while (handle_map.count(next_handle) != 0) {
++next_handle;
}
@@ -406,7 +406,7 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) {
return archive_itr->second->Format(path);
}
-ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low) {
+ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size) {
// Construct the binary path to the archive first
FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
@@ -421,9 +421,25 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low) {
}
std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
- std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
- if (!FileUtil::CreateFullPath(extsavedata_path))
+ std::string game_path = FileSys::GetExtSaveDataPath(base_path, path);
+ // These two folders are always created with the ExtSaveData
+ std::string user_path = game_path + "user/";
+ std::string boss_path = game_path + "boss/";
+ if (!FileUtil::CreateFullPath(user_path))
+ return ResultCode(-1); // TODO(Subv): Find the right error code
+ if (!FileUtil::CreateFullPath(boss_path))
+ return ResultCode(-1); // TODO(Subv): Find the right error code
+
+ u8* smdh_icon = Memory::GetPointer(icon_buffer);
+ if (!smdh_icon)
return ResultCode(-1); // TODO(Subv): Find the right error code
+
+ // Create the icon
+ FileUtil::IOFile icon_file(game_path + "icon", "wb+");
+ if (!icon_file.IsGood())
+ return ResultCode(-1); // TODO(Subv): Find the right error code
+
+ icon_file.WriteBytes(smdh_icon, icon_size);
return RESULT_SUCCESS;
}
@@ -441,6 +457,7 @@ ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
return ResultCode(-1); // TODO(Subv): Find the right error code
}
+ // Delete all directories (/user, /boss) and the icon file.
std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
if (!FileUtil::DeleteDirRecursively(extsavedata_path))
@@ -488,7 +505,7 @@ void ArchiveInit() {
RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC);
else
LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str());
-
+
// Create the SaveData archive
auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData);
@@ -503,7 +520,7 @@ void ArchiveInit() {
if (sharedextsavedata_factory->Initialize())
RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData);
else
- LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",
+ LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",
sharedextsavedata_factory->GetMountPoint().c_str());
// Create the SaveDataCheck archive, basically a small variation of the RomFS archive
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index faab0cb7..357b6b09 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -177,9 +177,11 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = File
* @param media_type The media type of the archive to create (NAND / SDMC)
* @param high The high word of the extdata id to create
* @param low The low word of the extdata id to create
+ * @param icon_buffer VAddr of the SMDH icon for this ExtSaveData
+ * @param icon_size Size of the SMDH icon
* @return ResultCode 0 on success or the corresponding code on error
*/
-ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low);
+ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size);
/**
* Deletes the SharedExtSaveData archive for the specified extdata ID
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index b25c8941..0ad44e55 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -434,7 +434,7 @@ static void IsSdmcWriteable(Service::Interface* self) {
}
/**
- * FS_User::FormatSaveData service function,
+ * FS_User::FormatSaveData service function,
* formats the SaveData specified by the input path.
* Inputs:
* 0 : 0x084C0242
@@ -504,9 +504,9 @@ static void FormatThisUserSaveData(Service::Interface* self) {
* 6 : Unknown
* 7 : Unknown
* 8 : Unknown
- * 9 : Unknown
- * 10: Unknown
- * 11: Unknown
+ * 9 : Size of the SMDH icon
+ * 10: (SMDH Size << 4) | 0x0000000A
+ * 11: Pointer to the SMDH icon for the new ExtSaveData
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
@@ -516,14 +516,16 @@ static void CreateExtSaveData(Service::Interface* self) {
MediaType media_type = static_cast<MediaType>(cmd_buff[1] & 0xFF);
u32 save_low = cmd_buff[2];
u32 save_high = cmd_buff[3];
+ u32 icon_size = cmd_buff[9];
+ VAddr icon_buffer = cmd_buff[11];
LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
"cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
- "cmd_buff[9]=%08X cmd_buff[10]=%08X cmd_buff[11]=%08X", save_high, save_low,
- cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9],
- cmd_buff[10], cmd_buff[11]);
+ "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", save_high, save_low,
+ cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size,
+ cmd_buff[10], icon_buffer);
- cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low).raw;
+ cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size).raw;
}
/**
@@ -544,7 +546,7 @@ static void DeleteExtSaveData(Service::Interface* self) {
u32 save_high = cmd_buff[3];
u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is
- LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X",
+ LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X",
save_low, save_high, cmd_buff[1] & 0xFF, unknown);
cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw;
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index c56475ae..4b0b4229 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -167,7 +167,7 @@ static void WriteHWRegsWithMask(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 reg_addr = cmd_buff[1];
u32 size = cmd_buff[2];
-
+
u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]);
u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]);
@@ -208,21 +208,21 @@ static void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left);
PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right);
if (info.active_fb == 0) {
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 4,
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 4,
&phys_address_left);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 4,
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 4,
&phys_address_right);
} else {
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 4,
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 4,
&phys_address_left);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 4,
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 4,
&phys_address_right);
}
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 4,
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 4,
&info.stride);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 4,
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 4,
&info.format);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4,
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4,
&info.shown_fb);
}
@@ -374,7 +374,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
{
auto& params = command.set_command_list_last;
- WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)),
+ WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)),
Memory::VirtualToPhysicalAddress(params.address) >> 3);
WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), params.size);
@@ -470,7 +470,7 @@ static void SetLcdForceBlack(Service::Interface* self) {
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
-
+
cmd_buff[1] = RESULT_SUCCESS.raw;
}
@@ -496,6 +496,52 @@ static void TriggerCmdReqQueue(Service::Interface* self) {
cmd_buff[1] = 0; // No error
}
+/**
+ * GSP_GPU::ImportDisplayCaptureInfo service function
+ *
+ * Returns information about the current framebuffer state
+ *
+ * Inputs:
+ * 0: Header 0x00180000
+ * Outputs:
+ * 1: Result code
+ * 2: Left framebuffer virtual address for the main screen
+ * 3: Right framebuffer virtual address for the main screen
+ * 4: Main screen framebuffer format
+ * 5: Main screen framebuffer width
+ * 6: Left framebuffer virtual address for the bottom screen
+ * 7: Right framebuffer virtual address for the bottom screen
+ * 8: Bottom screen framebuffer format
+ * 9: Bottom screen framebuffer width
+ */
+static void ImportDisplayCaptureInfo(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ // TODO(Subv): We're always returning the framebuffer structures for thread_id = 0,
+ // because we only support a single running application at a time.
+ // This should always return the framebuffer data that is currently displayed on the screen.
+
+ u32 thread_id = 0;
+
+ FrameBufferUpdate* top_screen = GetFrameBufferInfo(thread_id, 0);
+ FrameBufferUpdate* bottom_screen = GetFrameBufferInfo(thread_id, 1);
+
+ cmd_buff[2] = top_screen->framebuffer_info[top_screen->index].address_left;
+ cmd_buff[3] = top_screen->framebuffer_info[top_screen->index].address_right;
+ cmd_buff[4] = top_screen->framebuffer_info[top_screen->index].format;
+ cmd_buff[5] = top_screen->framebuffer_info[top_screen->index].stride;
+
+ cmd_buff[6] = bottom_screen->framebuffer_info[bottom_screen->index].address_left;
+ cmd_buff[7] = bottom_screen->framebuffer_info[bottom_screen->index].address_right;
+ cmd_buff[8] = bottom_screen->framebuffer_info[bottom_screen->index].format;
+ cmd_buff[9] = bottom_screen->framebuffer_info[bottom_screen->index].stride;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_GSP, "called");
+}
+
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010082, WriteHWRegs, "WriteHWRegs"},
{0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"},
@@ -520,7 +566,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00150002, nullptr, "TryAcquireRight"},
{0x00160042, nullptr, "AcquireRight"},
{0x00170000, nullptr, "ReleaseRight"},
- {0x00180000, nullptr, "ImportDisplayCaptureInfo"},
+ {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"},
{0x00190000, nullptr, "SaveVramSysArea"},
{0x001A0000, nullptr, "RestoreVramSysArea"},
{0x001B0000, nullptr, "ResetGpuCore"},
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 2d2133b2..c7c1bb5a 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -58,7 +58,7 @@ void Update() {
mem->pad.current_state.hex = state.hex;
mem->pad.index = next_pad_index;
- ++next_touch_index %= mem->pad.entries.size();
+ next_touch_index = (next_touch_index + 1) % mem->pad.entries.size();
// Get the previous Pad state
u32 last_entry_index = (mem->pad.index - 1) % mem->pad.entries.size();
@@ -88,7 +88,7 @@ void Update() {
}
mem->touch.index = next_touch_index;
- ++next_touch_index %= mem->touch.entries.size();
+ next_touch_index = (next_touch_index + 1) % mem->touch.entries.size();
// Get the current touch entry
TouchDataEntry* touch_entry = &mem->touch.entries[mem->touch.index];
@@ -106,7 +106,7 @@ void Update() {
mem->touch.index_reset_ticks_previous = mem->touch.index_reset_ticks;
mem->touch.index_reset_ticks = (s64)CoreTiming::GetTicks();
}
-
+
// Signal both handles when there's an update to Pad or touch
event_pad_or_touch_1->Signal();
event_pad_or_touch_2->Signal();
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index 02db12ef..532931ae 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -25,6 +25,6 @@ const Interface::FunctionInfo FunctionTable[] = {
HID_SPVR_Interface::HID_SPVR_Interface() {
Register(FunctionTable);
}
-
+
} // namespace HID
} // namespace Service
diff --git a/src/core/hle/service/hid/hid_user.h b/src/core/hle/service/hid/hid_user.h
index 0eeec2c2..baf7fed7 100644
--- a/src/core/hle/service/hid/hid_user.h
+++ b/src/core/hle/service/hid/hid_user.h
@@ -11,7 +11,7 @@
namespace Service {
namespace HID {
-
+
/**
* HID service interface.
*/
diff --git a/src/core/hle/service/news/news.cpp b/src/core/hle/service/news/news.cpp
new file mode 100644
index 00000000..63cbd385
--- /dev/null
+++ b/src/core/hle/service/news/news.cpp
@@ -0,0 +1,31 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+
+#include "core/hle/service/service.h"
+#include "core/hle/service/news/news.h"
+#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 {
+
+void Init() {
+ using namespace Kernel;
+
+ AddService(new NEWS_S_Interface);
+ AddService(new NEWS_U_Interface);
+}
+
+void Shutdown() {
+}
+
+} // namespace NEWS
+
+} // namespace Service
diff --git a/src/core/hle/service/news/news.h b/src/core/hle/service/news/news.h
new file mode 100644
index 00000000..b31ade25
--- /dev/null
+++ b/src/core/hle/service/news/news.h
@@ -0,0 +1,20 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace NEWS {
+
+/// Initialize NEWS service(s)
+void Init();
+
+/// Shutdown NEWS service(s)
+void Shutdown();
+
+} // namespace NEWS
+} // namespace Service
diff --git a/src/core/hle/service/news/news_s.cpp b/src/core/hle/service/news/news_s.cpp
new file mode 100644
index 00000000..2f8c37d9
--- /dev/null
+++ b/src/core/hle/service/news/news_s.cpp
@@ -0,0 +1,21 @@
+// Copyright 2015 Citra Emulator Project
+// 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"
+
+namespace Service {
+namespace NEWS {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000100C6, nullptr, "AddNotification"},
+};
+
+NEWS_S_Interface::NEWS_S_Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace NEWS
+} // namespace Service
diff --git a/src/core/hle/service/news_s.h b/src/core/hle/service/news/news_s.h
index f8b4636d..f58b969a 100644
--- a/src/core/hle/service/news_s.h
+++ b/src/core/hle/service/news/news_s.h
@@ -6,18 +6,17 @@
#include "core/hle/service/service.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NEWS_S
+namespace Service {
+namespace NEWS {
-namespace NEWS_S {
-
-class Interface : public Service::Interface {
+class NEWS_S_Interface : public Service::Interface {
public:
- Interface();
+ NEWS_S_Interface();
std::string GetPortName() const override {
return "news:s";
}
};
-} // namespace
+} // namespace NEWS
+} // namespace Service
diff --git a/src/core/hle/service/news/news_u.cpp b/src/core/hle/service/news/news_u.cpp
new file mode 100644
index 00000000..81f45a24
--- /dev/null
+++ b/src/core/hle/service/news/news_u.cpp
@@ -0,0 +1,21 @@
+// Copyright 2014 Citra Emulator Project
+// 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 {
+namespace NEWS {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000100C6, nullptr, "AddNotification"},
+};
+
+NEWS_U_Interface::NEWS_U_Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace NEWS
+} // namespace Service
diff --git a/src/core/hle/service/news_u.h b/src/core/hle/service/news/news_u.h
index 0473cd19..2720053d 100644
--- a/src/core/hle/service/news_u.h
+++ b/src/core/hle/service/news/news_u.h
@@ -6,18 +6,17 @@
#include "core/hle/service/service.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NEWS_U
+namespace Service {
+namespace NEWS {
-namespace NEWS_U {
-
-class Interface : public Service::Interface {
+class NEWS_U_Interface : public Service::Interface {
public:
- Interface();
+ NEWS_U_Interface();
std::string GetPortName() const override {
return "news:u";
}
};
-} // namespace
+} // namespace NEWS
+} // namespace Service
diff --git a/src/core/hle/service/news_s.cpp b/src/core/hle/service/news_s.cpp
deleted file mode 100644
index 302d588c..00000000
--- a/src/core/hle/service/news_s.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/news_s.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NEWS_S
-
-namespace NEWS_S {
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x000100C6, nullptr, "AddNotification"},
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/news_u.cpp b/src/core/hle/service/news_u.cpp
deleted file mode 100644
index 7d835aa3..00000000
--- a/src/core/hle/service/news_u.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/hle.h"
-#include "core/hle/service/news_u.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NEWS_U
-
-namespace NEWS_U {
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x000100C8, nullptr, "AddNotification"},
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
new file mode 100644
index 00000000..73b0ee52
--- /dev/null
+++ b/src/core/hle/service/nim/nim.cpp
@@ -0,0 +1,42 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+
+#include "core/hle/service/service.h"
+#include "core/hle/service/nim/nim.h"
+#include "core/hle/service/nim/nim_aoc.h"
+#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 {
+
+void CheckSysUpdateAvailable(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = 0; // No update available
+
+ LOG_WARNING(Service_NWM, "(STUBBED) called");
+}
+
+void Init() {
+ using namespace Kernel;
+
+ AddService(new NIM_AOC_Interface);
+ AddService(new NIM_S_Interface);
+ AddService(new NIM_U_Interface);
+}
+
+void Shutdown() {
+}
+
+} // namespace NIM
+
+} // namespace Service
diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h
new file mode 100644
index 00000000..f7635c74
--- /dev/null
+++ b/src/core/hle/service/nim/nim.h
@@ -0,0 +1,30 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace NIM {
+
+/**
+ * NIM::CheckSysUpdateAvailable service function
+ * Inputs:
+ * 1 : None
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : flag, 0 = no system update available, 1 = system update available.
+ */
+void CheckSysUpdateAvailable(Service::Interface* self);
+
+/// Initialize NIM service(s)
+void Init();
+
+/// Shutdown NIM service(s)
+void Shutdown();
+
+} // namespace NIM
+} // namespace Service
diff --git a/src/core/hle/service/nim_aoc.cpp b/src/core/hle/service/nim/nim_aoc.cpp
index 7a6aea91..e6b1b614 100644
--- a/src/core/hle/service/nim_aoc.cpp
+++ b/src/core/hle/service/nim/nim_aoc.cpp
@@ -3,12 +3,11 @@
// Refer to the license.txt file included.
#include "core/hle/hle.h"
-#include "core/hle/service/nim_aoc.h"
+#include "core/hle/service/nim/nim.h"
+#include "core/hle/service/nim/nim_aoc.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NIM_AOC
-
-namespace NIM_AOC {
+namespace Service {
+namespace NIM {
const Interface::FunctionInfo FunctionTable[] = {
{0x00030042, nullptr, "SetApplicationId"},
@@ -20,11 +19,10 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00240282, nullptr, "CalculateContentsRequiredSize"},
{0x00250000, nullptr, "RefreshServerTime"},
};
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-Interface::Interface() {
+NIM_AOC_Interface::NIM_AOC_Interface() {
Register(FunctionTable);
}
-} // namespace
+} // namespace NIM
+} // namespace Service
diff --git a/src/core/hle/service/nim/nim_aoc.h b/src/core/hle/service/nim/nim_aoc.h
new file mode 100644
index 00000000..aace45b5
--- /dev/null
+++ b/src/core/hle/service/nim/nim_aoc.h
@@ -0,0 +1,22 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace NIM {
+
+class NIM_AOC_Interface : public Service::Interface {
+public:
+ NIM_AOC_Interface();
+
+ std::string GetPortName() const override {
+ return "nim:aoc";
+ }
+};
+
+} // namespace NIM
+} // namespace Service
diff --git a/src/core/hle/service/nim/nim_s.cpp b/src/core/hle/service/nim/nim_s.cpp
new file mode 100644
index 00000000..5d8bc059
--- /dev/null
+++ b/src/core/hle/service/nim/nim_s.cpp
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// 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 {
+namespace NIM {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"},
+};
+
+NIM_S_Interface::NIM_S_Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace NIM
+} // namespace Service
+
diff --git a/src/core/hle/service/nim/nim_s.h b/src/core/hle/service/nim/nim_s.h
new file mode 100644
index 00000000..f4bf73d2
--- /dev/null
+++ b/src/core/hle/service/nim/nim_s.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace NIM {
+
+class NIM_S_Interface : public Service::Interface {
+public:
+ NIM_S_Interface();
+
+ std::string GetPortName() const override {
+ return "nim:s";
+ }
+};
+
+} // namespace NIM
+} // namespace Service
diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp
new file mode 100644
index 00000000..066570a8
--- /dev/null
+++ b/src/core/hle/service/nim/nim_u.cpp
@@ -0,0 +1,27 @@
+// Copyright 2015 Citra Emulator Project
+// 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"
+
+namespace Service {
+namespace NIM {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010000, nullptr, "StartSysUpdate"},
+ {0x00020000, nullptr, "GetUpdateDownloadProgress"},
+ {0x00040000, nullptr, "FinishTitlesInstall"},
+ {0x00050000, nullptr, "CheckForSysUpdateEvent"},
+ {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"},
+ {0x000A0000, nullptr, "GetState"},
+};
+
+NIM_U_Interface::NIM_U_Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace NIM
+} // namespace Service
+
diff --git a/src/core/hle/service/nim/nim_u.h b/src/core/hle/service/nim/nim_u.h
new file mode 100644
index 00000000..bc89dc0f
--- /dev/null
+++ b/src/core/hle/service/nim/nim_u.h
@@ -0,0 +1,22 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included..
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace NIM {
+
+class NIM_U_Interface : public Service::Interface {
+public:
+ NIM_U_Interface();
+
+ std::string GetPortName() const override {
+ return "nim:u";
+ }
+};
+
+} // namespace NIM
+} // namespace Service
diff --git a/src/core/hle/service/nim_aoc.h b/src/core/hle/service/nim_aoc.h
deleted file mode 100644
index aeb71eed..00000000
--- a/src/core/hle/service/nim_aoc.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NIM_AOC
-
-namespace NIM_AOC {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "nim:aoc";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/nim_u.cpp b/src/core/hle/service/nim_u.cpp
deleted file mode 100644
index 5f13bd98..00000000
--- a/src/core/hle/service/nim_u.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// 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/nim_u.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NIM_U
-
-namespace NIM_U {
-
-/**
- * NIM_U::CheckSysUpdateAvailable service function
- * Inputs:
- * 1 : None
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : flag, 0 = no system update available, 1 = system update available.
- */
-static void CheckSysUpdateAvailable(Service::Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
-
- cmd_buff[1] = RESULT_SUCCESS.raw;
- cmd_buff[2] = 0; // No update available
-
- LOG_WARNING(Service_NWM, "(STUBBED) called");
-}
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x00010000, nullptr, "StartSysUpdate"},
- {0x00020000, nullptr, "GetUpdateDownloadProgress"},
- {0x00040000, nullptr, "FinishTitlesInstall"},
- {0x00050000, nullptr, "CheckForSysUpdateEvent"},
- {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"},
- {0x000A0000, nullptr, "GetState"},
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- Register(FunctionTable);
-}
-
-} // namespace
diff --git a/src/core/hle/service/nim_u.h b/src/core/hle/service/nim_u.h
deleted file mode 100644
index 57a1f6ac..00000000
--- a/src/core/hle/service/nim_u.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace NIM_U
-
-namespace NIM_U {
-
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "nim:u";
- }
-};
-
-} // namespace
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index 493e6a11..b690003c 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -20,15 +20,15 @@ enum class ChargeLevels : u32 {
CompletelyFull = 5,
};
-/**
+/**
* Represents the gamecoin file structure in the SharedExtData archive
* More information in 3dbrew (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat)
*/
struct GameCoin {
u32 magic; ///< Magic number: 0x4F00
- u16 total_coins; ///< Total Play Coins
+ u16 total_coins; ///< Total Play Coins
u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below.
- u32 step_count; ///< Total step count at the time a new Play Coin was obtained.
+ u32 step_count; ///< Total step count at the time a new Play Coin was obtained.
u32 last_step_count; ///< Step count for the day the last Play Coin was obtained
u16 year;
u8 month;
diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp
index 48e68a3d..7bb99019 100644
--- a/src/core/hle/service/ptm/ptm_play.cpp
+++ b/src/core/hle/service/ptm/ptm_play.cpp
@@ -18,6 +18,6 @@ const Interface::FunctionInfo FunctionTable[] = {
PTM_Play_Interface::PTM_Play_Interface() {
Register(FunctionTable);
}
-
+
} // namespace PTM
} // namespace Service \ No newline at end of file
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 64185c62..d681cc3d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -8,29 +8,15 @@
#include "core/hle/service/service.h"
#include "core/hle/service/ac_u.h"
#include "core/hle/service/act_u.h"
-#include "core/hle/service/am_app.h"
-#include "core/hle/service/am_net.h"
-#include "core/hle/service/am_sys.h"
-#include "core/hle/service/boss_p.h"
-#include "core/hle/service/boss_u.h"
-#include "core/hle/service/cam_u.h"
-#include "core/hle/service/cecd_u.h"
-#include "core/hle/service/cecd_s.h"
#include "core/hle/service/csnd_snd.h"
#include "core/hle/service/dsp_dsp.h"
#include "core/hle/service/err_f.h"
-#include "core/hle/service/frd_a.h"
-#include "core/hle/service/frd_u.h"
#include "core/hle/service/gsp_gpu.h"
#include "core/hle/service/gsp_lcd.h"
#include "core/hle/service/http_c.h"
#include "core/hle/service/ldr_ro.h"
#include "core/hle/service/mic_u.h"
#include "core/hle/service/ndm_u.h"
-#include "core/hle/service/news_s.h"
-#include "core/hle/service/news_u.h"
-#include "core/hle/service/nim_aoc.h"
-#include "core/hle/service/nim_u.h"
#include "core/hle/service/ns_s.h"
#include "core/hle/service/nwm_uds.h"
#include "core/hle/service/pm_app.h"
@@ -39,11 +25,18 @@
#include "core/hle/service/ssl_c.h"
#include "core/hle/service/y2r_u.h"
+#include "core/hle/service/am/am.h"
#include "core/hle/service/apt/apt.h"
+#include "core/hle/service/boss/boss.h"
+#include "core/hle/service/cam/cam.h"
+#include "core/hle/service/cecd/cecd.h"
+#include "core/hle/service/frd/frd.h"
#include "core/hle/service/fs/archive.h"
#include "core/hle/service/cfg/cfg.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/ir/ir.h"
+#include "core/hle/service/news/news.h"
+#include "core/hle/service/nim/nim.h"
#include "core/hle/service/ptm/ptm.h"
namespace Service {
@@ -52,7 +45,7 @@ std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_por
std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
/**
- * Creates a function string for logging, complete with the name (or header code, depending
+ * Creates a function string for logging, complete with the name (or header code, depending
* on what's passed in) the port name, and all the cmd_buff arguments.
*/
static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) {
@@ -111,36 +104,29 @@ void Init() {
AddNamedPort(new ERR_F::Interface);
Service::FS::ArchiveInit();
- Service::CFG::Init();
+ Service::AM::Init();
Service::APT::Init();
- Service::PTM::Init();
+ Service::BOSS::Init();
+ Service::CAM::Init();
+ Service::CECD::Init();
+ Service::CFG::Init();
+ Service::FRD::Init();
Service::HID::Init();
Service::IR::Init();
+ Service::NEWS::Init();
+ Service::NIM::Init();
+ Service::PTM::Init();
AddService(new AC_U::Interface);
AddService(new ACT_U::Interface);
- AddService(new AM_APP::Interface);
- AddService(new AM_NET::Interface);
- AddService(new AM_SYS::Interface);
- AddService(new BOSS_P::Interface);
- AddService(new BOSS_U::Interface);
- AddService(new CAM_U::Interface);
- AddService(new CECD_S::Interface);
- AddService(new CECD_U::Interface);
AddService(new CSND_SND::Interface);
AddService(new DSP_DSP::Interface);
- AddService(new FRD_A::Interface);
- AddService(new FRD_U::Interface);
AddService(new GSP_GPU::Interface);
AddService(new GSP_LCD::Interface);
AddService(new HTTP_C::Interface);
AddService(new LDR_RO::Interface);
AddService(new MIC_U::Interface);
AddService(new NDM_U::Interface);
- AddService(new NEWS_S::Interface);
- AddService(new NEWS_U::Interface);
- AddService(new NIM_AOC::Interface);
- AddService(new NIM_U::Interface);
AddService(new NS_S::Interface);
AddService(new NWM_UDS::Interface);
AddService(new PM_APP::Interface);
@@ -153,11 +139,19 @@ void Init() {
/// Shutdown ServiceManager
void Shutdown() {
+
+ Service::PTM::Shutdown();
+ Service::NIM::Shutdown();
+ Service::NEWS::Shutdown();
Service::IR::Shutdown();
Service::HID::Shutdown();
- Service::PTM::Shutdown();
- Service::APT::Shutdown();
+ Service::FRD::Shutdown();
Service::CFG::Shutdown();
+ Service::CECD::Shutdown();
+ Service::CAM::Shutdown();
+ Service::BOSS::Shutdown();
+ Service::APT::Shutdown();
+ Service::AM::Shutdown();
Service::FS::ArchiveShutdown();
g_srv_services.clear();
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index 39b8d65f..1e0f5df9 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -139,7 +139,7 @@ static int TranslateError(int error) {
auto found = error_map.find(error);
if (found != error_map.end())
return -found->second;
-
+
return error;
}
@@ -346,7 +346,7 @@ static void Bind(Service::Interface* self) {
sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr);
int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len));
-
+
int result = 0;
if (res != 0)
result = TranslateError(GET_ERRNO);
@@ -360,14 +360,14 @@ static void Fcntl(Service::Interface* self) {
u32 socket_handle = cmd_buffer[1];
u32 ctr_cmd = cmd_buffer[2];
u32 ctr_arg = cmd_buffer[3];
-
+
int result = 0;
u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX)
SCOPE_EXIT({
cmd_buffer[1] = result;
cmd_buffer[2] = posix_ret;
});
-
+
if (ctr_cmd == 3) { // F_GETFL
#if EMU_PLATFORM == PLATFORM_WINDOWS
posix_ret = 0;
@@ -404,11 +404,11 @@ static void Fcntl(Service::Interface* self) {
posix_ret = -1;
return;
}
-
+
flags &= ~O_NONBLOCK;
if (ctr_arg & 4) // O_NONBLOCK
flags |= O_NONBLOCK;
-
+
int ret = ::fcntl(socket_handle, F_SETFL, flags);
if (ret == SOCKET_ERROR_VALUE) {
result = TranslateError(GET_ERRNO);
@@ -439,8 +439,8 @@ static void Listen(Service::Interface* self) {
}
static void Accept(Service::Interface* self) {
- // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
- // preventing graceful shutdown when closing the emulator, this can be fixed by always
+ // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
+ // preventing graceful shutdown when closing the emulator, this can be fixed by always
// performing nonblocking operations and spinlock until the data is available
u32* cmd_buffer = Kernel::GetCommandBuffer();
u32 socket_handle = cmd_buffer[1];
@@ -448,7 +448,7 @@ static void Accept(Service::Interface* self) {
sockaddr addr;
socklen_t addr_len = sizeof(addr);
u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len));
-
+
if ((s32)ret != SOCKET_ERROR_VALUE)
open_sockets[ret] = { ret, true };
@@ -525,8 +525,8 @@ static void SendTo(Service::Interface* self) {
}
static void RecvFrom(Service::Interface* self) {
- // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
- // preventing graceful shutdown when closing the emulator, this can be fixed by always
+ // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
+ // preventing graceful shutdown when closing the emulator, this can be fixed by always
// performing nonblocking operations and spinlock until the data is available
u32* cmd_buffer = Kernel::GetCommandBuffer();
u32 socket_handle = cmd_buffer[1];
@@ -568,7 +568,7 @@ static void Poll(Service::Interface* self) {
pollfd* platform_pollfd = new pollfd[nfds];
for (unsigned current_fds = 0; current_fds < nfds; ++current_fds)
platform_pollfd[current_fds] = CTRPollFD::ToPlatform(input_fds[current_fds]);
-
+
int ret = ::poll(platform_pollfd, nfds, timeout);
// Now update the output pollfd structure
@@ -630,7 +630,7 @@ static void GetPeerName(Service::Interface* self) {
socklen_t len = cmd_buffer[2];
CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2]));
-
+
sockaddr dest_addr;
socklen_t dest_addr_len = sizeof(dest_addr);
int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len);
@@ -651,8 +651,8 @@ static void GetPeerName(Service::Interface* self) {
}
static void Connect(Service::Interface* self) {
- // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
- // preventing graceful shutdown when closing the emulator, this can be fixed by always
+ // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
+ // preventing graceful shutdown when closing the emulator, this can be fixed by always
// performing nonblocking operations and spinlock until the data is available
u32* cmd_buffer = Kernel::GetCommandBuffer();
u32 socket_handle = cmd_buffer[1];
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 347d241f..6cde4fc8 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -40,9 +40,6 @@ const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E
-/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
-const ResultCode RESULT_INVALID(0xDEADC0DE);
-
enum ControlMemoryOperation {
MEMORY_OPERATION_HEAP = 0x00000003,
MEMORY_OPERATION_GSP_HEAP = 0x00010003,
@@ -143,6 +140,10 @@ static ResultCode CloseHandle(Handle handle) {
/// Wait for a handle to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
auto object = Kernel::g_handle_table.GetWaitObject(handle);
+ Kernel::Thread* thread = Kernel::GetCurrentThread();
+
+ thread->waitsynch_waited = false;
+
if (object == nullptr)
return ERR_INVALID_HANDLE;
@@ -154,14 +155,14 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
// Check for next thread to schedule
if (object->ShouldWait()) {
- object->AddWaitingThread(Kernel::GetCurrentThread());
+ object->AddWaitingThread(thread);
Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false);
// Create an event to wake the thread up after the specified nanosecond delay has passed
- Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
+ thread->WakeAfterDelay(nano_seconds);
// NOTE: output of this SVC will be set later depending on how the thread resumes
- return RESULT_INVALID;
+ return HLE::RESULT_INVALID;
}
object->Acquire();
@@ -173,6 +174,9 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) {
bool wait_thread = !wait_all;
int handle_index = 0;
+ Kernel::Thread* thread = Kernel::GetCurrentThread();
+ bool was_waiting = thread->waitsynch_waited;
+ thread->waitsynch_waited = false;
// Check if 'handles' is invalid
if (handles == nullptr)
@@ -190,6 +194,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
// necessary
if (handle_count != 0) {
bool selected = false; // True once an object has been selected
+
+ Kernel::SharedPtr<Kernel::WaitObject> wait_object;
+
for (int i = 0; i < handle_count; ++i) {
auto object = Kernel::g_handle_table.GetWaitObject(handles[i]);
if (object == nullptr)
@@ -204,10 +211,11 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
wait_thread = true;
} else {
// Do not wait on this object, check if this object should be selected...
- if (!wait_all && !selected) {
+ if (!wait_all && (!selected || (wait_object == object && was_waiting))) {
// Do not wait the thread
wait_thread = false;
handle_index = i;
+ wait_object = object;
selected = true;
}
}
@@ -228,7 +236,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
// Actually wait the current thread on each object if we decided to wait...
std::vector<SharedPtr<Kernel::WaitObject>> wait_objects;
wait_objects.reserve(handle_count);
-
+
for (int i = 0; i < handle_count; ++i) {
auto object = Kernel::g_handle_table.GetWaitObject(handles[i]);
object->AddWaitingThread(Kernel::GetCurrentThread());
@@ -241,7 +249,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds);
// NOTE: output of this SVC will be set later depending on how the thread resumes
- return RESULT_INVALID;
+ return HLE::RESULT_INVALID;
}
// Acquire objects if we did not wait...
@@ -261,7 +269,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
// TODO(bunnei): If 'wait_all' is true, this is probably wrong. However, real hardware does
// not seem to set it to any meaningful value.
- *out = wait_all ? 0 : handle_index;
+ *out = handle_count != 0 ? (wait_all ? -1 : handle_index) : 0;
return RESULT_SUCCESS;
}
@@ -475,7 +483,7 @@ static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
return ERR_INVALID_HANDLE;
const SharedPtr<Kernel::Process> process = thread->owner_process;
-
+
ASSERT_MSG(process != nullptr, "Invalid parent process for thread=0x%08X", thread_handle);
*process_id = process->process_id;
@@ -654,6 +662,8 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
using Kernel::MemoryPermission;
SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(size,
(MemoryPermission)my_permission, (MemoryPermission)other_permission);
+ // Map the SharedMemory to the specified address
+ shared_memory->base_address = addr;
CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr);
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index ddc5d647..7471def5 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/color.h"
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
@@ -22,7 +23,6 @@
#include "video_core/command_processor.h"
#include "video_core/utils.h"
#include "video_core/video_core.h"
-#include "video_core/color.h"
namespace GPU {
@@ -30,8 +30,8 @@ Regs g_regs;
/// True if the current frame was skipped
bool g_skip_frame;
-/// 268MHz / gpu_refresh_rate frames per second
-static u64 frame_ticks;
+/// 268MHz CPU clocks / 60Hz frames per second
+const u64 frame_ticks = 268123480ull / 60;
/// Event id for CoreTiming
static int vblank_event;
/// Total number of frames drawn
@@ -140,7 +140,7 @@ inline void Write(u32 addr, const T data) {
// Raw copies do not perform color conversion nor tiled->linear / linear->tiled conversions
// TODO(Subv): Verify if raw copies perform scaling
memcpy(dst_pointer, src_pointer, output_size);
-
+
LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), output format: %x, flags 0x%08X, Raw copy",
output_size,
config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(),
@@ -159,14 +159,14 @@ inline void Write(u32 addr, const T data) {
for (u32 x = 0; x < output_width; ++x) {
Math::Vec4<u8> src_color = { 0, 0, 0, 0 };
- // Calculate the [x,y] position of the input image
+ // Calculate the [x,y] position of the input image
// based on the current output position and the scale
u32 input_x = x * horizontal_scale;
u32 input_y = y * vertical_scale;
if (config.flip_vertically) {
- // Flip the y value of the output data,
- // we do this after calculating the [x,y] position of the input image
+ // Flip the y value of the output data,
+ // we do this after calculating the [x,y] position of the input image
// to account for the scaling options.
y = output_height - y - 1;
}
@@ -302,7 +302,7 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
// - If frameskip == 0 (disabled), always swap buffers
// - If frameskip == 1, swap buffers every other frame (starting from the first frame)
// - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame)
- if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) ||
+ if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) ||
Settings::values.frame_skip == 0) {
VideoCore::g_renderer->SwapBuffers();
}
@@ -357,7 +357,6 @@ void Init() {
framebuffer_sub.color_format = Regs::PixelFormat::RGB8;
framebuffer_sub.active_fb = 0;
- frame_ticks = 268123480 / Settings::values.gpu_refresh_rate;
last_skip_frame = false;
g_skip_frame = false;
frame_count = 0;
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index f4906cc7..c7006a49 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -18,7 +18,7 @@ inline void Read(T &var, const u32 addr) {
GPU::Read(var, addr);
break;
case VADDR_LCD:
- LCD::Write(var, addr);
+ LCD::Read(var, addr);
break;
default:
LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp
index 09134c95..963c8d98 100644
--- a/src/core/hw/lcd.cpp
+++ b/src/core/hw/lcd.cpp
@@ -66,5 +66,5 @@ void Init() {
void Shutdown() {
LOG_DEBUG(HW_LCD, "shutdown OK");
}
-
+
} // namespace
diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h
index fb14c3b2..8631eb20 100644
--- a/src/core/hw/lcd.h
+++ b/src/core/hw/lcd.h
@@ -85,5 +85,5 @@ void Init();
/// Shutdown hardware
void Shutdown();
-
+
} // namespace
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index ad5e929c..14aeebeb 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -234,7 +234,7 @@ ResultStatus AppLoader_THREEDSX::Load() {
Kernel::g_current_process = Kernel::Process::Create(filename, 0);
Kernel::g_current_process->svc_access_mask.set();
Kernel::g_current_process->address_mappings = default_address_mappings;
-
+
// Attach the default resource limit (APPLICATION) to the process
Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp
index 5ecec956..bf814b94 100644
--- a/src/core/mem_map.cpp
+++ b/src/core/mem_map.cpp
@@ -8,6 +8,10 @@
#include "common/logging/log.h"
#include "core/hle/config_mem.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/shared_memory.h"
+#include "core/hle/kernel/vm_manager.h"
+#include "core/hle/result.h"
#include "core/hle/shared_page.h"
#include "core/mem_map.h"
#include "core/memory.h"
@@ -17,31 +21,23 @@
namespace Memory {
-u8* g_exefs_code; ///< ExeFS:/.code is loaded here
-u8* g_heap; ///< Application heap (main memory)
-u8* g_shared_mem; ///< Shared memory
-u8* g_heap_linear; ///< Linear heap
-u8* g_vram; ///< Video memory (VRAM) pointer
-u8* g_dsp_mem; ///< DSP memory
-u8* g_tls_mem; ///< TLS memory
-
namespace {
struct MemoryArea {
- u8** ptr;
u32 base;
u32 size;
+ const char* name;
};
// We don't declare the IO regions in here since its handled by other means.
static MemoryArea memory_areas[] = {
- {&g_exefs_code, PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE},
- {&g_heap, HEAP_VADDR, HEAP_SIZE },
- {&g_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE },
- {&g_heap_linear, LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE },
- {&g_vram, VRAM_VADDR, VRAM_SIZE },
- {&g_dsp_mem, DSP_RAM_VADDR, DSP_RAM_SIZE },
- {&g_tls_mem, TLS_AREA_VADDR, TLS_AREA_SIZE },
+ {PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE, "Process Image"}, // ExeFS:/.code is loaded here
+ {HEAP_VADDR, HEAP_SIZE, "Heap"}, // Application heap (main memory)
+ {SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory
+ {LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE, "Linear Heap"}, // Linear heap (main 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
};
/// Represents a block of memory mapped by ControlMemory/MapMemoryBlock
@@ -135,27 +131,34 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) {
return addr | 0x80000000;
}
+// TODO(yuriks): Move this into Process
+static Kernel::VMManager address_space;
+
void Init() {
+ using namespace Kernel;
+
InitMemoryMap();
for (MemoryArea& area : memory_areas) {
- *area.ptr = new u8[area.size];
- MapMemoryRegion(area.base, area.size, *area.ptr);
+ auto block = std::make_shared<std::vector<u8>>(area.size);
+ address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap();
}
- MapMemoryRegion(CONFIG_MEMORY_VADDR, CONFIG_MEMORY_SIZE, (u8*)&ConfigMem::config_mem);
- MapMemoryRegion(SHARED_PAGE_VADDR, SHARED_PAGE_SIZE, (u8*)&SharedPage::shared_page);
- LOG_DEBUG(HW_Memory, "initialized OK, RAM at %p", g_heap);
+ auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR,
+ (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom();
+ address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
+
+ 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);
+
+ LOG_DEBUG(HW_Memory, "initialized OK");
}
void Shutdown() {
heap_map.clear();
heap_linear_map.clear();
-
- for (MemoryArea& area : memory_areas) {
- delete[] *area.ptr;
- *area.ptr = nullptr;
- }
+ address_space.Reset();
LOG_DEBUG(HW_Memory, "shutdown OK");
}
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 945815cd..ba50914a 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -8,14 +8,6 @@
namespace Memory {
-extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here
-extern u8* g_heap; ///< Application heap (main memory)
-extern u8* g_shared_mem; ///< Shared memory
-extern u8* g_heap_linear; ///< Linear heap (main memory)
-extern u8* g_vram; ///< Video memory (VRAM)
-extern u8* g_dsp_mem; ///< DSP memory
-extern u8* g_tls_mem; ///< TLS memory
-
void Init();
void Shutdown();
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 5d8069ac..28844a91 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -14,12 +14,10 @@
#include "core/hw/hw.h"
#include "core/mem_map.h"
#include "core/memory.h"
+#include "core/memory_setup.h"
namespace Memory {
-const u32 PAGE_MASK = PAGE_SIZE - 1;
-const int PAGE_BITS = 12;
-
enum class PageType {
/// Page is unmapped and should cause an access error.
Unmapped,
@@ -64,7 +62,7 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
while (base != end) {
ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base);
- if (current_page_table->attributes[base] != PageType::Unmapped) {
+ if (current_page_table->attributes[base] != PageType::Unmapped && type != PageType::Unmapped) {
LOG_ERROR(HW_Memory, "overlapping memory ranges at %08X", base * PAGE_SIZE);
}
current_page_table->attributes[base] = type;
@@ -92,6 +90,12 @@ void MapIoRegion(VAddr base, u32 size) {
MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special);
}
+void UnmapRegion(VAddr base, u32 size) {
+ 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::Unmapped);
+}
+
template <typename T>
T Read(const VAddr vaddr) {
const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
diff --git a/src/core/memory.h b/src/core/memory.h
index 2d225801..0b8ff9ec 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -97,7 +97,7 @@ enum : VAddr {
SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
// TODO(yuriks): The size of this area is dynamic, the kernel grows
- // it as more and more threads are created. For now we'll just use a
+ // it as more and more threads are created. For now we'll just use a
// hardcoded value.
/// Area where TLS (Thread-Local Storage) buffers are allocated.
TLS_AREA_VADDR = 0x1FF82000,
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h
index 46263495..361bfc81 100644
--- a/src/core/memory_setup.h
+++ b/src/core/memory_setup.h
@@ -6,8 +6,13 @@
#include "common/common_types.h"
+#include "core/memory.h"
+
namespace Memory {
+const u32 PAGE_MASK = PAGE_SIZE - 1;
+const int PAGE_BITS = 12;
+
void InitMemoryMap();
/**
@@ -26,4 +31,6 @@ void MapMemoryRegion(VAddr base, u32 size, u8* target);
*/
void MapIoRegion(VAddr base, u32 size);
+void UnmapRegion(VAddr base, u32 size);
+
}
diff --git a/src/core/settings.h b/src/core/settings.h
index 54c1023b..5a70d157 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -35,7 +35,6 @@ struct Values {
int pad_cright_key;
// Core
- int gpu_refresh_rate;
int frame_skip;
// Data Storage
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 0258a325..5c7f4ae1 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -29,11 +29,9 @@ set(HEADERS
renderer_opengl/pica_to_gl.h
renderer_opengl/renderer_opengl.h
clipper.h
- color.h
command_processor.h
gpu_debugger.h
hwrasterizer_base.h
- math.h
pica.h
primitive_assembly.h
rasterizer.h
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 100d8c7c..b46fadd9 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -56,7 +56,17 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
// Trigger IRQ
case PICA_REG_INDEX(trigger_irq):
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D);
- return;
+ break;
+
+ case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c):
+ case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d):
+ {
+ unsigned index = id - PICA_REG_INDEX(command_buffer.trigger[0]);
+ u32* head_ptr = (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index));
+ g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr;
+ g_state.cmd_list.length = regs.command_buffer.GetSize(index) / sizeof(u32);
+ break;
+ }
// It seems like these trigger vertex rendering
case PICA_REG_INDEX(trigger_draw):
@@ -136,7 +146,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
input.attr[i][0].ToFloat32(), input.attr[i][1].ToFloat32(),
input.attr[i][2].ToFloat32(), input.attr[i][3].ToFloat32());
}
-
+
// Load per-vertex data from the loader arrays
for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) {
const u8* srcdata = Memory::GetPhysicalPointer(vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i]);
@@ -193,7 +203,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
const Pica::VertexShader::OutputVertex& v2) {
VideoCore::g_renderer->hw_rasterizer->AddTriangle(v0, v1, v2);
};
-
+
primitive_assembler.SubmitVertex(output, AddHWTriangle);
} else {
// Send to triangle clipper
@@ -282,7 +292,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
}
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):
@@ -306,7 +316,7 @@ static inline 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));
@@ -363,38 +373,34 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast<void*>(&id));
}
-static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) {
- const CommandHeader& header = *(const CommandHeader*)(&first_command_word[1]);
-
- u32* read_pointer = (u32*)first_command_word;
-
- const u32 write_mask = ((header.parameter_mask & 0x1) ? (0xFFu << 0) : 0u) |
- ((header.parameter_mask & 0x2) ? (0xFFu << 8) : 0u) |
- ((header.parameter_mask & 0x4) ? (0xFFu << 16) : 0u) |
- ((header.parameter_mask & 0x8) ? (0xFFu << 24) : 0u);
-
- WritePicaReg(header.cmd_id, *read_pointer, write_mask);
- read_pointer += 2;
-
- for (unsigned int i = 1; i < 1+header.extra_data_length; ++i) {
- u32 cmd = header.cmd_id + ((header.group_commands) ? i : 0);
- WritePicaReg(cmd, *read_pointer, write_mask);
- ++read_pointer;
- }
-
- // align read pointer to 8 bytes
- if ((first_command_word - read_pointer) % 2)
- ++read_pointer;
-
- return read_pointer - first_command_word;
-}
-
void ProcessCommandList(const u32* list, u32 size) {
- u32* read_pointer = (u32*)list;
- u32 list_length = size / sizeof(u32);
-
- while (read_pointer < list + list_length) {
- read_pointer += ExecuteCommandBlock(read_pointer);
+ g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = list;
+ g_state.cmd_list.length = size / sizeof(u32);
+
+ while (g_state.cmd_list.current_ptr < g_state.cmd_list.head_ptr + g_state.cmd_list.length) {
+ // Expand a 4-bit mask to 4-byte mask, e.g. 0b0101 -> 0x00FF00FF
+ static const u32 expand_bits_to_bytes[] = {
+ 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+ 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+ 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+ 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
+ };
+
+ // Align read pointer to 8 bytes
+ if ((g_state.cmd_list.head_ptr - g_state.cmd_list.current_ptr) % 2 != 0)
+ ++g_state.cmd_list.current_ptr;
+
+ u32 value = *g_state.cmd_list.current_ptr++;
+ const CommandHeader header = { *g_state.cmd_list.current_ptr++ };
+ const u32 write_mask = expand_bits_to_bytes[header.parameter_mask];
+ u32 cmd = header.cmd_id;
+
+ WritePicaReg(cmd, value, write_mask);
+
+ for (unsigned i = 0; i < header.extra_data_length; ++i) {
+ u32 cmd = header.cmd_id + (header.group_commands ? i + 1 : 0);
+ WritePicaReg(cmd, *g_state.cmd_list.current_ptr++, write_mask);
+ }
}
}
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 7987b922..7b8ab72b 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -17,11 +17,11 @@
#include <nihstro/shader_binary.h>
#include "common/assert.h"
+#include "common/color.h"
#include "common/file_util.h"
#include "common/math_util.h"
+#include "common/vector_math.h"
-#include "video_core/color.h"
-#include "video_core/math.h"
#include "video_core/pica.h"
#include "video_core/utils.h"
#include "video_core/video_core.h"
@@ -319,7 +319,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
// TODO(neobrain): Fix code design to unify vertical block offsets!
source += coarse_y * info.stride;
}
-
+
// TODO: Assert that width/height are multiples of block dimensions
switch (info.format) {
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index f361a538..7926d64e 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -12,7 +12,8 @@
#include <mutex>
#include <vector>
-#include "video_core/math.h"
+#include "common/vector_math.h"
+
#include "video_core/pica.h"
namespace Pica {
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index b67dce1a..9628a758 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -15,8 +15,7 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/logging/log.h"
-
-#include "math.h"
+#include "common/vector_math.h"
namespace Pica {
@@ -162,6 +161,25 @@ struct Regs {
ETC1A4 = 13, // compressed
};
+ enum class LogicOp : u32 {
+ Clear = 0,
+ And = 1,
+ AndReverse = 2,
+ Copy = 3,
+ Set = 4,
+ CopyInverted = 5,
+ NoOp = 6,
+ Invert = 7,
+ Nand = 8,
+ Or = 9,
+ Nor = 10,
+ Xor = 11,
+ Equiv = 12,
+ AndInverted = 13,
+ OrReverse = 14,
+ OrInverted = 15,
+ };
+
static unsigned NibblesPerPixel(TextureFormat format) {
switch (format) {
case TextureFormat::RGBA8:
@@ -221,6 +239,7 @@ struct Regs {
enum class Source : u32 {
PrimaryColor = 0x0,
PrimaryFragmentColor = 0x1,
+ SecondaryFragmentColor = 0x2,
Texture0 = 0x3,
Texture1 = 0x4,
@@ -337,7 +356,7 @@ struct Regs {
return (stage_index < 4) && (update_mask_a & (1 << stage_index));
}
} tev_combiner_buffer_input;
-
+
INSERT_PADDING_WORDS(0xf);
TevStageConfig tev_stage4;
INSERT_PADDING_WORDS(0x3);
@@ -353,9 +372,9 @@ struct Regs {
INSERT_PADDING_WORDS(0x2);
const std::array<Regs::TevStageConfig,6> GetTevStages() const {
- return { tev_stage0, tev_stage1,
- tev_stage2, tev_stage3,
- tev_stage4, tev_stage5 };
+ return {{ tev_stage0, tev_stage1,
+ tev_stage2, tev_stage3,
+ tev_stage4, tev_stage5 }};
};
enum class BlendEquation : u32 {
@@ -413,12 +432,8 @@ struct Regs {
} alpha_blending;
union {
- enum Op {
- Set = 4,
- };
-
- BitField<0, 4, Op> op;
- } logic_op;
+ BitField<0, 4, LogicOp> logic_op;
+ };
union {
BitField< 0, 8, u32> r;
@@ -703,12 +718,38 @@ struct Regs {
struct {
// Index of the current default attribute
u32 index;
-
+
// Writing to these registers sets the "current" default attribute.
u32 set_value[3];
} vs_default_attributes_setup;
-
- INSERT_PADDING_WORDS(0x28);
+
+ INSERT_PADDING_WORDS(0x2);
+
+ struct {
+ // There are two channels that can be used to configure the next command buffer, which
+ // can be then executed by writing to the "trigger" registers. There are two reasons why a
+ // game might use this feature:
+ // 1) With this, an arbitrary number of additional command buffers may be executed in
+ // sequence without requiring any intervention of the CPU after the initial one is
+ // kicked off.
+ // 2) Games can configure these registers to provide a command list subroutine mechanism.
+
+ BitField< 0, 20, u32> size[2]; ///< Size (in bytes / 8) of each channel's command buffer
+ BitField< 0, 28, u32> addr[2]; ///< Physical address / 8 of each channel's command buffer
+ u32 trigger[2]; ///< Triggers execution of the channel's command buffer when written to
+
+ unsigned GetSize(unsigned index) const {
+ ASSERT(index < 2);
+ return 8 * size[index];
+ }
+
+ PAddr GetPhysicalAddress(unsigned index) const {
+ ASSERT(index < 2);
+ return (PAddr)(8 * addr[index]);
+ }
+ } command_buffer;
+
+ INSERT_PADDING_WORDS(0x20);
enum class TriangleTopology : u32 {
List = 0,
@@ -861,6 +902,7 @@ struct Regs {
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(vs_bool_uniforms);
ADD_FIELD(vs_int_uniforms);
@@ -938,6 +980,7 @@ ASSERT_REG_POSITION(num_vertices, 0x228);
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(triangle_topology, 0x25e);
ASSERT_REG_POSITION(vs_bool_uniforms, 0x2b0);
ASSERT_REG_POSITION(vs_int_uniforms, 0x2b1);
@@ -1053,21 +1096,12 @@ private:
float value;
};
-union CommandHeader {
- CommandHeader(u32 h) : hex(h) {}
-
- u32 hex;
-
- BitField< 0, 16, u32> cmd_id;
- BitField<16, 4, u32> parameter_mask;
- BitField<20, 11, u32> extra_data_length;
- BitField<31, 1, u32> group_commands;
-};
-
/// Struct used to describe current Pica state
struct State {
+ /// Pica registers
Regs regs;
+ /// Vertex shader memory
struct {
struct {
Math::Vec4<float24> f[96];
@@ -1080,6 +1114,13 @@ struct State {
std::array<u32, 1024> program_code;
std::array<u32, 1024> swizzle_data;
} vs;
+
+ /// Current Pica command list
+ struct {
+ const u32* head_ptr;
+ const u32* current_ptr;
+ u32 length;
+ } cmd_list;
};
/// Initialize Pica state
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 767ff420..59d156ee 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
+#include "common/color.h"
#include "common/common_types.h"
#include "common/math_util.h"
#include "common/profiler.h"
@@ -13,7 +14,6 @@
#include "debug_utils/debug_utils.h"
#include "math.h"
-#include "color.h"
#include "pica.h"
#include "rasterizer.h"
#include "vertex_shader.h"
@@ -104,7 +104,7 @@ static u32 GetDepth(int x, int y) {
u8* depth_buffer = Memory::GetPhysicalPointer(addr);
y = framebuffer.height - y;
-
+
const u32 coarse_y = y & ~7;
u32 bytes_per_pixel = Regs::BytesPerDepthPixel(framebuffer.depth_format);
u32 stride = framebuffer.width * bytes_per_pixel;
@@ -402,11 +402,16 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
auto GetSource = [&](Source source) -> Math::Vec4<u8> {
switch (source) {
- // TODO: What's the difference between these two?
case Source::PrimaryColor:
+
+ // HACK: Until we implement fragment lighting, use primary_color
case Source::PrimaryFragmentColor:
return primary_color;
+ // HACK: Until we implement fragment lighting, use zero
+ case Source::SecondaryFragmentColor:
+ return {0, 0, 0, 0};
+
case Source::Texture0:
return texture_color[0];
@@ -570,6 +575,13 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
case Operation::Add:
return std::min(255, input[0] + input[1]);
+ case Operation::AddSigned:
+ {
+ // TODO(bunnei): Verify that the color conversion from (float) 0.5f to (byte) 128 is correct
+ auto result = static_cast<int>(input[0]) + static_cast<int>(input[1]) - 128;
+ return static_cast<u8>(MathUtil::Clamp<int>(result, 0, 255));
+ }
+
case Operation::Lerp:
return (input[0] * input[2] + input[1] * (255 - input[2])) / 255;
@@ -808,10 +820,9 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
}
};
- using BlendEquation = Regs::BlendEquation;
static auto EvaluateBlendEquation = [](const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor,
const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor,
- BlendEquation equation) {
+ Regs::BlendEquation equation) {
Math::Vec4<int> result;
auto src_result = (src * srcfactor).Cast<int>();
@@ -866,8 +877,63 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb);
blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a();
} else {
- LOG_CRITICAL(HW_GPU, "logic op: %x", output_merger.logic_op);
- UNIMPLEMENTED();
+ static auto LogicOp = [](u8 src, u8 dest, Regs::LogicOp op) -> u8 {
+ switch (op) {
+ case Regs::LogicOp::Clear:
+ return 0;
+
+ case Regs::LogicOp::And:
+ return src & dest;
+
+ case Regs::LogicOp::AndReverse:
+ return src & ~dest;
+
+ case Regs::LogicOp::Copy:
+ return src;
+
+ case Regs::LogicOp::Set:
+ return 255;
+
+ case Regs::LogicOp::CopyInverted:
+ return ~src;
+
+ case Regs::LogicOp::NoOp:
+ return dest;
+
+ case Regs::LogicOp::Invert:
+ return ~dest;
+
+ case Regs::LogicOp::Nand:
+ return ~(src & dest);
+
+ case Regs::LogicOp::Or:
+ return src | dest;
+
+ case Regs::LogicOp::Nor:
+ return ~(src | dest);
+
+ case Regs::LogicOp::Xor:
+ return src ^ dest;
+
+ case Regs::LogicOp::Equiv:
+ return ~(src ^ dest);
+
+ case Regs::LogicOp::AndInverted:
+ return ~src & dest;
+
+ case Regs::LogicOp::OrReverse:
+ return src | ~dest;
+
+ case Regs::LogicOp::OrInverted:
+ return ~src | dest;
+ }
+ };
+
+ blend_output = Math::MakeVec(
+ LogicOp(combiner_output.r(), dest.r(), output_merger.logic_op),
+ LogicOp(combiner_output.g(), dest.g(), output_merger.logic_op),
+ LogicOp(combiner_output.b(), dest.b(), output_merger.logic_op),
+ LogicOp(combiner_output.a(), dest.a(), output_merger.logic_op));
}
const Math::Vec4<u8> result = {
diff --git a/src/video_core/renderer_opengl/generated/gl_3_2_core.c b/src/video_core/renderer_opengl/generated/gl_3_2_core.c
index ef29972d..95fd29c0 100644
--- a/src/video_core/renderer_opengl/generated/gl_3_2_core.c
+++ b/src/video_core/renderer_opengl/generated/gl_3_2_core.c
@@ -62,9 +62,9 @@ static int TestPointer(const PROC pTest)
ptrdiff_t iTest;
if(!pTest) return 0;
iTest = (ptrdiff_t)pTest;
-
+
if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0;
-
+
return 1;
}
@@ -79,7 +79,7 @@ static PROC WinGetProcAddress(const char *name)
glMod = GetModuleHandleA("OpenGL32.dll");
return (PROC)GetProcAddress(glMod, (LPCSTR)name);
}
-
+
#define IntGetProcAddress(name) WinGetProcAddress(name)
#else
#if defined(__APPLE__)
@@ -1083,7 +1083,7 @@ static ogl_StrToExtMap *FindExtEntry(const char *extensionName)
if(strcmp(extensionName, currLoc->extensionName) == 0)
return currLoc;
}
-
+
return NULL;
}
@@ -1135,15 +1135,15 @@ int ogl_LoadFunctions()
{
int numFailed = 0;
ClearExtensionVars();
-
+
_ptrc_glGetIntegerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint *))IntGetProcAddress("glGetIntegerv");
if(!_ptrc_glGetIntegerv) return ogl_LOAD_FAILED;
_ptrc_glGetStringi = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glGetStringi");
if(!_ptrc_glGetStringi) return ogl_LOAD_FAILED;
-
+
ProcExtsFromExtList();
numFailed = Load_Version_3_2();
-
+
if(numFailed == 0)
return ogl_LOAD_SUCCEEDED;
else
@@ -1177,7 +1177,7 @@ int ogl_IsVersionGEQ(int majorVersion, int minorVersion)
{
if(g_major_version == 0)
GetGLVersion();
-
+
if(majorVersion > g_major_version) return 1;
if(majorVersion < g_major_version) return 0;
if(minorVersion >= g_minor_version) return 1;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 4b7d099a..518f7933 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -2,10 +2,11 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/color.h"
+
#include "core/settings.h"
#include "core/hw/gpu.h"
-#include "video_core/color.h"
#include "video_core/pica.h"
#include "video_core/utils.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
@@ -93,14 +94,27 @@ void RasterizerOpenGL::InitObjects() {
// Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation
fb_color_texture.texture.Create();
ReconfigureColorTexture(fb_color_texture, Pica::Regs::ColorFormat::RGBA8, 1, 1);
+
+ state.texture_units[0].enabled_2d = true;
+ state.texture_units[0].texture_2d = fb_color_texture.texture.handle;
+ state.Apply();
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
fb_depth_texture.texture.Create();
ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1);
+
+ state.texture_units[0].enabled_2d = true;
+ state.texture_units[0].texture_2d = fb_depth_texture.texture.handle;
+ state.Apply();
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -109,14 +123,13 @@ void RasterizerOpenGL::InitObjects() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
// Configure OpenGL framebuffer
framebuffer.Create();
state.draw.framebuffer = framebuffer.handle;
-
- // Unbind texture to allow binding to framebuffer
- state.texture_units[0].enabled_2d = true;
- state.texture_units[0].texture_2d = 0;
state.Apply();
glActiveTexture(GL_TEXTURE0);
@@ -135,6 +148,7 @@ void RasterizerOpenGL::Reset() {
SyncBlendFuncs();
SyncBlendColor();
SyncAlphaTest();
+ SyncLogicOp();
SyncStencilTest();
SyncDepthTest();
@@ -203,7 +217,19 @@ void RasterizerOpenGL::DrawTriangles() {
vertex_batch.clear();
- // TODO: Flush the resource cache at the current depth and color framebuffer addresses for render-to-texture
+ // 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();
+
+ 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();
+
+ res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size);
+ res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size);
}
void RasterizerOpenGL::CommitFramebuffer() {
@@ -249,6 +275,11 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
SyncDepthTest();
break;
+ // Logic op
+ case PICA_REG_INDEX(output_merger.logic_op):
+ SyncLogicOp();
+ break;
+
// TEV stage 0
case PICA_REG_INDEX(tev_stage0.color_source1):
SyncTevSources(0, regs.tev_stage0);
@@ -350,7 +381,7 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
case PICA_REG_INDEX(tev_stage5.color_scale):
SyncTevMultipliers(5, regs.tev_stage5);
break;
-
+
// TEV combiner buffer color
case PICA_REG_INDEX(tev_combiner_buffer_color):
SyncCombinerColor();
@@ -465,6 +496,9 @@ void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs:
glActiveTexture(GL_TEXTURE0);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
texture.gl_format, texture.gl_type, nullptr);
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) {
@@ -484,7 +518,7 @@ void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::
case Pica::Regs::DepthFormat::D24:
internal_format = GL_DEPTH_COMPONENT24;
texture.gl_format = GL_DEPTH_COMPONENT;
- texture.gl_type = GL_UNSIGNED_INT_24_8;
+ texture.gl_type = GL_UNSIGNED_INT;
break;
case Pica::Regs::DepthFormat::D24S8:
@@ -506,6 +540,9 @@ void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::
glActiveTexture(GL_TEXTURE0);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
texture.gl_format, texture.gl_type, nullptr);
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::SyncFramebuffer() {
@@ -633,6 +670,10 @@ void RasterizerOpenGL::SyncAlphaTest() {
glUniform1f(uniform_alphatest_ref, regs.output_merger.alpha_test.ref / 255.0f);
}
+void RasterizerOpenGL::SyncLogicOp() {
+ state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.output_merger.logic_op);
+}
+
void RasterizerOpenGL::SyncStencilTest() {
// TODO: Implement stencil test, mask, and op
}
@@ -641,6 +682,10 @@ 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.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;
+ state.color_mask.alpha_enabled = regs.output_merger.alpha_enable;
state.depth.write_mask = regs.output_merger.depth_write_enable ? GL_TRUE : GL_FALSE;
}
@@ -748,10 +793,10 @@ 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_px_idx = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = (x + y * fb_color_texture.width) * bytes_per_pixel;
u8* pixel = color_buffer + dst_offset;
- memcpy(&temp_fb_color_buffer[gl_px_idx], pixel, bytes_per_pixel);
+ memcpy(&temp_fb_color_buffer[gl_pixel_index], pixel, bytes_per_pixel);
}
}
@@ -762,6 +807,9 @@ void RasterizerOpenGL::ReloadColorBuffer() {
glActiveTexture(GL_TEXTURE0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_color_texture.width, fb_color_texture.height,
fb_color_texture.gl_format, fb_color_texture.gl_type, temp_fb_color_buffer.get());
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::ReloadDepthBuffer() {
@@ -779,29 +827,29 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
std::unique_ptr<u8[]> temp_fb_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]);
- for (int y = 0; y < fb_depth_texture.height; ++y) {
- 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_px_idx = x + y * fb_depth_texture.width;
-
- switch (fb_depth_texture.format) {
- case Pica::Regs::DepthFormat::D16:
- ((u16*)temp_fb_depth_buffer.get())[gl_px_idx] = Color::DecodeD16(depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24:
- ((u32*)temp_fb_depth_buffer.get())[gl_px_idx] = Color::DecodeD24(depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24S8:
- {
- Math::Vec2<u32> depth_stencil = Color::DecodeD24S8(depth_buffer + dst_offset);
- ((u32*)temp_fb_depth_buffer.get())[gl_px_idx] = (depth_stencil.x << 8) | depth_stencil.y;
- break;
+ u8* temp_fb_depth_data = bytes_per_pixel == 3 ? (temp_fb_depth_buffer.get() + 1) : temp_fb_depth_buffer.get();
+
+ if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ 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);
+
+ u8* pixel = depth_buffer + dst_offset;
+ u32 depth_stencil = *(u32*)pixel;
+ ((u32*)temp_fb_depth_data)[gl_pixel_index] = (depth_stencil << 8) | (depth_stencil >> 24);
}
- default:
- LOG_CRITICAL(Render_OpenGL, "Unknown memory framebuffer depth format %x", fb_depth_texture.format);
- UNIMPLEMENTED();
- break;
+ }
+ } else {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ 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;
+
+ u8* pixel = depth_buffer + dst_offset;
+ memcpy(&temp_fb_depth_data[gl_pixel_index], pixel, bytes_per_pixel);
}
}
}
@@ -813,6 +861,9 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
glActiveTexture(GL_TEXTURE0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_depth_texture.width, fb_depth_texture.height,
fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_fb_depth_buffer.get());
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
void RasterizerOpenGL::CommitColorBuffer() {
@@ -831,15 +882,18 @@ void RasterizerOpenGL::CommitColorBuffer() {
glActiveTexture(GL_TEXTURE0);
glGetTexImage(GL_TEXTURE_2D, 0, fb_color_texture.gl_format, fb_color_texture.gl_type, temp_gl_color_buffer.get());
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
// Directly copy pixels. Internal OpenGL color formats are consistent so no conversion is necessary.
for (int y = 0; y < fb_color_texture.height; ++y) {
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_px_idx = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
+ u32 gl_pixel_index = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel;
u8* pixel = color_buffer + dst_offset;
- memcpy(pixel, &temp_gl_color_buffer[gl_px_idx], bytes_per_pixel);
+ memcpy(pixel, &temp_gl_color_buffer[gl_pixel_index], bytes_per_pixel);
}
}
}
@@ -866,29 +920,32 @@ void RasterizerOpenGL::CommitDepthBuffer() {
glActiveTexture(GL_TEXTURE0);
glGetTexImage(GL_TEXTURE_2D, 0, fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_gl_depth_buffer.get());
- for (int y = 0; y < fb_depth_texture.height; ++y) {
- 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_px_idx = x + y * fb_depth_texture.width;
-
- switch (fb_depth_texture.format) {
- case Pica::Regs::DepthFormat::D16:
- Color::EncodeD16(((u16*)temp_gl_depth_buffer.get())[gl_px_idx], depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24:
- Color::EncodeD24(((u32*)temp_gl_depth_buffer.get())[gl_px_idx], depth_buffer + dst_offset);
- break;
- case Pica::Regs::DepthFormat::D24S8:
- {
- u32 depth_stencil = ((u32*)temp_gl_depth_buffer.get())[gl_px_idx];
- Color::EncodeD24S8((depth_stencil >> 8), depth_stencil & 0xFF, depth_buffer + dst_offset);
- break;
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
+ u8* temp_gl_depth_data = bytes_per_pixel == 3 ? (temp_gl_depth_buffer.get() + 1) : temp_gl_depth_buffer.get();
+
+ if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ 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);
+
+ u8* pixel = depth_buffer + dst_offset;
+ u32 depth_stencil = ((u32*)temp_gl_depth_data)[gl_pixel_index];
+ *(u32*)pixel = (depth_stencil >> 8) | (depth_stencil << 24);
}
- default:
- LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer depth format %x", fb_depth_texture.format);
- UNIMPLEMENTED();
- break;
+ }
+ } else {
+ for (int y = 0; y < fb_depth_texture.height; ++y) {
+ 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;
+
+ 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 9896f8d0..d7d422b1 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -125,6 +125,9 @@ private:
/// Syncs the alpha test states to match the PICA register
void SyncAlphaTest();
+ /// Syncs the logic op states to match the PICA register
+ void SyncLogicOp();
+
/// Syncs the stencil test states to match the PICA register
void SyncStencilTest();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 6f88a8b2..2e4110a8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -4,13 +4,13 @@
#include "common/make_unique.h"
#include "common/math_util.h"
+#include "common/vector_math.h"
#include "core/memory.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/pica_to_gl.h"
#include "video_core/debug_utils/debug_utils.h"
-#include "video_core/math.h"
RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
FullFlush();
diff --git a/src/video_core/renderer_opengl/gl_shaders.h b/src/video_core/renderer_opengl/gl_shaders.h
index 8f094123..a8cb2f59 100644
--- a/src/video_core/renderer_opengl/gl_shaders.h
+++ b/src/video_core/renderer_opengl/gl_shaders.h
@@ -69,15 +69,16 @@ const char g_fragment_shader_hw[] = R"(
#define NUM_VTX_ATTR 7
#define NUM_TEV_STAGES 6
-#define SOURCE_PRIMARYCOLOR 0x0
-#define SOURCE_PRIMARYFRAGMENTCOLOR 0x1
-#define SOURCE_TEXTURE0 0x3
-#define SOURCE_TEXTURE1 0x4
-#define SOURCE_TEXTURE2 0x5
-#define SOURCE_TEXTURE3 0x6
-#define SOURCE_PREVIOUSBUFFER 0xd
-#define SOURCE_CONSTANT 0xe
-#define SOURCE_PREVIOUS 0xf
+#define SOURCE_PRIMARYCOLOR 0x0
+#define SOURCE_PRIMARYFRAGMENTCOLOR 0x1
+#define SOURCE_SECONDARYFRAGMENTCOLOR 0x2
+#define SOURCE_TEXTURE0 0x3
+#define SOURCE_TEXTURE1 0x4
+#define SOURCE_TEXTURE2 0x5
+#define SOURCE_TEXTURE3 0x6
+#define SOURCE_PREVIOUSBUFFER 0xd
+#define SOURCE_CONSTANT 0xe
+#define SOURCE_PREVIOUS 0xf
#define COLORMODIFIER_SOURCECOLOR 0x0
#define COLORMODIFIER_ONEMINUSSOURCECOLOR 0x1
@@ -151,8 +152,11 @@ vec4 GetSource(int source) {
if (source == SOURCE_PRIMARYCOLOR) {
return o[2];
} else if (source == SOURCE_PRIMARYFRAGMENTCOLOR) {
- // HACK: Uses color value, but should really use fragment lighting output
+ // HACK: Until we implement fragment lighting, use primary_color
return o[2];
+ } else if (source == SOURCE_SECONDARYFRAGMENTCOLOR) {
+ // HACK: Until we implement fragment lighting, use zero
+ return vec4(0.0, 0.0, 0.0, 0.0);
} else if (source == SOURCE_TEXTURE0) {
return texture(tex[0], o[3].xy);
} else if (source == SOURCE_TEXTURE1) {
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 1afa58c9..3526e16d 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -16,6 +16,11 @@ OpenGLState::OpenGLState() {
depth.test_func = GL_LESS;
depth.write_mask = GL_TRUE;
+ color_mask.red_enabled = GL_TRUE;
+ color_mask.green_enabled = GL_TRUE;
+ color_mask.blue_enabled = GL_TRUE;
+ color_mask.alpha_enabled = GL_TRUE;
+
stencil.test_enabled = false;
stencil.test_func = GL_ALWAYS;
stencil.test_ref = 0;
@@ -32,6 +37,8 @@ OpenGLState::OpenGLState() {
blend.color.blue = 0.0f;
blend.color.alpha = 0.0f;
+ logic_op = GL_COPY;
+
for (auto& texture_unit : texture_units) {
texture_unit.enabled_2d = false;
texture_unit.texture_2d = 0;
@@ -75,6 +82,15 @@ void OpenGLState::Apply() {
glDepthMask(depth.write_mask);
}
+ // Color mask
+ if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
+ color_mask.green_enabled != cur_state.color_mask.green_enabled ||
+ color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
+ color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
+ glColorMask(color_mask.red_enabled, color_mask.green_enabled,
+ color_mask.blue_enabled, color_mask.alpha_enabled);
+ }
+
// Stencil test
if (stencil.test_enabled != cur_state.stencil.test_enabled) {
if (stencil.test_enabled) {
@@ -82,11 +98,11 @@ void OpenGLState::Apply() {
} else {
glDisable(GL_STENCIL_TEST);
}
- }
+ }
if (stencil.test_func != cur_state.stencil.test_func ||
- stencil.test_ref != cur_state.stencil.test_ref ||
- stencil.test_mask != cur_state.stencil.test_mask) {
+ stencil.test_ref != cur_state.stencil.test_ref ||
+ stencil.test_mask != cur_state.stencil.test_mask) {
glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask);
}
@@ -99,23 +115,34 @@ void OpenGLState::Apply() {
if (blend.enabled != cur_state.blend.enabled) {
if (blend.enabled) {
glEnable(GL_BLEND);
+
+ cur_state.logic_op = GL_COPY;
+ glLogicOp(cur_state.logic_op);
+ glDisable(GL_COLOR_LOGIC_OP);
} else {
glDisable(GL_BLEND);
+ glEnable(GL_COLOR_LOGIC_OP);
}
}
if (blend.color.red != cur_state.blend.color.red ||
- blend.color.green != cur_state.blend.color.green ||
- blend.color.blue != cur_state.blend.color.blue ||
- blend.color.alpha != cur_state.blend.color.alpha) {
- glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
+ blend.color.green != cur_state.blend.color.green ||
+ blend.color.blue != cur_state.blend.color.blue ||
+ blend.color.alpha != cur_state.blend.color.alpha) {
+ glBlendColor(blend.color.red, blend.color.green,
+ blend.color.blue, blend.color.alpha);
}
if (blend.src_rgb_func != cur_state.blend.src_rgb_func ||
- blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
- blend.src_a_func != cur_state.blend.src_a_func ||
- blend.dst_a_func != cur_state.blend.dst_a_func) {
- glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func);
+ blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
+ blend.src_a_func != cur_state.blend.src_a_func ||
+ blend.dst_a_func != cur_state.blend.dst_a_func) {
+ glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func,
+ blend.src_a_func, blend.dst_a_func);
+ }
+
+ if (logic_op != cur_state.logic_op) {
+ glLogicOp(logic_op);
}
// Textures
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 281b7cad..26b91636 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -20,6 +20,13 @@ public:
} depth;
struct {
+ GLboolean red_enabled;
+ GLboolean green_enabled;
+ GLboolean blue_enabled;
+ GLboolean alpha_enabled;
+ } color_mask; // GL_COLOR_WRITEMASK
+
+ struct {
bool test_enabled; // GL_STENCIL_TEST
GLenum test_func; // GL_STENCIL_FUNC
GLint test_ref; // GL_STENCIL_REF
@@ -42,6 +49,8 @@ public:
} color; // GL_BLEND_COLOR
} blend;
+ GLenum logic_op; // GL_LOGIC_OP_MODE
+
// 3 texture units - one for each that is used in PICA fragment shader emulation
struct {
bool enabled_2d; // GL_TEXTURE_2D
@@ -61,7 +70,7 @@ public:
static const OpenGLState& GetCurState() {
return cur_state;
}
-
+
/// Apply this state as the current OpenGL state
void Apply();
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h
index f8763e71..e566f9f7 100644
--- a/src/video_core/renderer_opengl/pica_to_gl.h
+++ b/src/video_core/renderer_opengl/pica_to_gl.h
@@ -71,6 +71,37 @@ inline GLenum BlendFunc(Pica::Regs::BlendFactor factor) {
return blend_func_table[(unsigned)factor];
}
+inline GLenum LogicOp(Pica::Regs::LogicOp op) {
+ static const GLenum logic_op_table[] = {
+ GL_CLEAR, // Clear
+ GL_AND, // And
+ GL_AND_REVERSE, // AndReverse
+ GL_COPY, // Copy
+ GL_SET, // Set
+ GL_COPY_INVERTED, // CopyInverted
+ GL_NOOP, // NoOp
+ GL_INVERT, // Invert
+ GL_NAND, // Nand
+ GL_OR, // Or
+ GL_NOR, // Nor
+ GL_XOR, // Xor
+ GL_EQUIV, // Equiv
+ GL_AND_INVERTED, // AndInverted
+ GL_OR_REVERSE, // OrReverse
+ GL_OR_INVERTED, // OrInverted
+ };
+
+ // Range check table for input
+ if ((unsigned)op >= ARRAY_SIZE(logic_op_table)) {
+ LOG_CRITICAL(Render_OpenGL, "Unknown logic op %d", op);
+ UNREACHABLE();
+
+ return GL_COPY;
+ }
+
+ return logic_op_table[(unsigned)op];
+}
+
inline GLenum CompareFunc(Pica::Regs::CompareFunc func) {
static const GLenum compare_func_table[] = {
GL_NEVER, // CompareFunc::Never
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 16cf92e2..3399ca12 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -157,7 +157,7 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
state.texture_units[0].enabled_2d = true;
state.texture_units[0].texture_2d = texture.handle;
state.Apply();
-
+
glActiveTexture(GL_TEXTURE0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride);
@@ -170,6 +170,9 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig&
texture.gl_format, texture.gl_type, framebuffer_data);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
}
/**
@@ -239,6 +242,9 @@ void RendererOpenGL::InitOpenGLObjects() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
+ state.texture_units[0].texture_2d = 0;
+ state.Apply();
+
hw_rasterizer->InitObjects();
}
@@ -370,6 +376,8 @@ void RendererOpenGL::Init() {
}
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));
InitOpenGLObjects();
}
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp
index 7d68998f..87006a83 100644
--- a/src/video_core/vertex_shader.cpp
+++ b/src/video_core/vertex_shader.cpp
@@ -119,17 +119,13 @@ static void ProcessShaderCode(VertexShaderState& state) {
switch (instr.opcode.Value().GetInfo().type) {
case OpCode::Type::Arithmetic:
{
- bool is_inverted = 0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed);
- // TODO: We don't really support this properly: For instance, the address register
- // offset needs to be applied to SRC2 instead, etc.
- // For now, we just abort in this situation.
- ASSERT_MSG(!is_inverted, "Bad condition...");
+ const bool is_inverted = (0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed));
const int address_offset = (instr.common.address_register_index == 0)
? 0 : state.address_registers[instr.common.address_register_index - 1];
- const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + address_offset);
- const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted));
+ const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + (!is_inverted * address_offset));
+ const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted) + ( is_inverted * address_offset));
const bool negate_src1 = ((bool)swizzle.negate_src1 != false);
const bool negate_src2 = ((bool)swizzle.negate_src2 != false);
@@ -208,6 +204,15 @@ static void ProcessShaderCode(VertexShaderState& state) {
}
break;
+ case OpCode::Id::MIN:
+ for (int i = 0; i < 4; ++i) {
+ if (!swizzle.DestComponentEnabled(i))
+ continue;
+
+ dest[i] = std::min(src1[i], src2[i]);
+ }
+ break;
+
case OpCode::Id::DP3:
case OpCode::Id::DP4:
{
@@ -279,6 +284,16 @@ static void ProcessShaderCode(VertexShaderState& state) {
break;
}
+ case OpCode::Id::SLT:
+ case OpCode::Id::SLTI:
+ for (int i = 0; i < 4; ++i) {
+ if (!swizzle.DestComponentEnabled(i))
+ continue;
+
+ dest[i] = (src1[i] < src2[i]) ? float24::FromFloat32(1.0f) : float24::FromFloat32(0.0f);
+ }
+ break;
+
case OpCode::Id::CMP:
for (int i = 0; i < 2; ++i) {
// TODO: Can you restrict to one compare via dest masking?
@@ -330,7 +345,7 @@ static void ProcessShaderCode(VertexShaderState& state) {
case OpCode::Type::MultiplyAdd:
{
- if ((instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MAD) ||
+ if ((instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MAD) ||
(instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI)) {
const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.mad.operand_desc_id];
@@ -547,7 +562,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes) {
const auto& attribute_register_map = regs.vs_input_register_map;
float24 dummy_register;
boost::fill(state.input_register_table, &dummy_register);
-
+
if (num_attributes > 0) state.input_register_table[attribute_register_map.attribute0_register] = &input.attr[0].x;
if (num_attributes > 1) state.input_register_table[attribute_register_map.attribute1_register] = &input.attr[1].x;
if (num_attributes > 2) state.input_register_table[attribute_register_map.attribute2_register] = &input.attr[2].x;