diff options
76 files changed, 986 insertions, 324 deletions
diff --git a/.travis-build.sh b/.travis-build.sh index 21582c689..14dfd64d8 100755 --- a/.travis-build.sh +++ b/.travis-build.sh | |||
| @@ -3,10 +3,16 @@ | |||
| 3 | set -e | 3 | set -e |
| 4 | set -x | 4 | set -x |
| 5 | 5 | ||
| 6 | if grep -r '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .travis* dist/*.desktop \ | ||
| 7 | dist/*.svg dist/*.xml; then | ||
| 8 | echo Trailing whitespace found, aborting | ||
| 9 | exit 1 | ||
| 10 | fi | ||
| 11 | |||
| 6 | #if OS is linux or is not set | 12 | #if OS is linux or is not set |
| 7 | if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then | 13 | if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then |
| 8 | mkdir build && cd build | 14 | mkdir build && cd build |
| 9 | cmake -DUSE_QT5=OFF .. | 15 | cmake -DUSE_QT5=OFF .. |
| 10 | make -j4 | 16 | make -j4 |
| 11 | elif [ "$TRAVIS_OS_NAME" = "osx" ]; then | 17 | elif [ "$TRAVIS_OS_NAME" = "osx" ]; then |
| 12 | export Qt5_DIR=$(brew --prefix)/opt/qt5 | 18 | export Qt5_DIR=$(brew --prefix)/opt/qt5 |
diff --git a/.travis-upload.sh b/.travis-upload.sh index 4b9446a96..0904b646a 100644 --- a/.travis-upload.sh +++ b/.travis-upload.sh | |||
| @@ -6,7 +6,7 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then | |||
| 6 | REV_NAME="citra-${GITDATE}-${GITREV}-linux-amd64" | 6 | REV_NAME="citra-${GITDATE}-${GITREV}-linux-amd64" |
| 7 | UPLOAD_DIR="/citra/nightly/linux-amd64" | 7 | UPLOAD_DIR="/citra/nightly/linux-amd64" |
| 8 | mkdir "$REV_NAME" | 8 | mkdir "$REV_NAME" |
| 9 | 9 | ||
| 10 | sudo apt-get -qq install lftp | 10 | sudo apt-get -qq install lftp |
| 11 | cp build/src/citra/citra "$REV_NAME" | 11 | cp build/src/citra/citra "$REV_NAME" |
| 12 | cp build/src/citra_qt/citra-qt "$REV_NAME" | 12 | cp build/src/citra_qt/citra-qt "$REV_NAME" |
| @@ -14,7 +14,7 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then | |||
| 14 | REV_NAME="citra-${GITDATE}-${GITREV}-osx-amd64" | 14 | REV_NAME="citra-${GITDATE}-${GITREV}-osx-amd64" |
| 15 | UPLOAD_DIR="/citra/nightly/osx-amd64" | 15 | UPLOAD_DIR="/citra/nightly/osx-amd64" |
| 16 | mkdir "$REV_NAME" | 16 | mkdir "$REV_NAME" |
| 17 | 17 | ||
| 18 | brew install lftp | 18 | brew install lftp |
| 19 | cp build/src/citra/Release/citra "$REV_NAME" | 19 | cp build/src/citra/Release/citra "$REV_NAME" |
| 20 | cp -r build/src/citra_qt/Release/citra-qt.app "$REV_NAME" | 20 | cp -r build/src/citra_qt/Release/citra-qt.app "$REV_NAME" |
| @@ -22,7 +22,7 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then | |||
| 22 | # move qt libs into app bundle for deployment | 22 | # move qt libs into app bundle for deployment |
| 23 | $(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/citra-qt.app" | 23 | $(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/citra-qt.app" |
| 24 | fi | 24 | fi |
| 25 | 25 | ||
| 26 | ARCHIVE_NAME="${REV_NAME}.tar.xz" | 26 | ARCHIVE_NAME="${REV_NAME}.tar.xz" |
| 27 | tar -cJvf "$ARCHIVE_NAME" "$REV_NAME" | 27 | tar -cJvf "$ARCHIVE_NAME" "$REV_NAME" |
| 28 | lftp -c "open -u citra-builds,$BUILD_PASSWORD sftp://builds.citra-emu.org; put -O '$UPLOAD_DIR' '$ARCHIVE_NAME'" | 28 | 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 b878cc160..5c882a574 100644 --- a/.travis.yml +++ b/.travis.yml | |||
| @@ -6,7 +6,7 @@ language: cpp | |||
| 6 | 6 | ||
| 7 | env: | 7 | env: |
| 8 | global: | 8 | global: |
| 9 | - secure: "AXHFIafTmbGDsHD3mUVj5a4I397DQjti/WoqAJGUp2PglxTcc04BwxZ9Z+xLuf5N2Hs5r9ojAJLT8OGxJCLBDXzneQTNSqXbFuYSLbqrEAiIRlA9eRIotWCg+wYcO+5e8MKX+cHVKwiIWasUB21AtCdq6msh6Y3pUshZp212VPg=" | 9 | - secure: "AXHFIafTmbGDsHD3mUVj5a4I397DQjti/WoqAJGUp2PglxTcc04BwxZ9Z+xLuf5N2Hs5r9ojAJLT8OGxJCLBDXzneQTNSqXbFuYSLbqrEAiIRlA9eRIotWCg+wYcO+5e8MKX+cHVKwiIWasUB21AtCdq6msh6Y3pUshZp212VPg=" |
| 10 | 10 | ||
| 11 | before_install: | 11 | before_install: |
| 12 | - sh .travis-deps.sh | 12 | - sh .travis-deps.sh |
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fb311b11..75f519a1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -38,7 +38,7 @@ else() | |||
| 38 | set(CMAKE_CXX_FLAGS_RELEASE "${optimization_flags} /MP /MD" CACHE STRING "" FORCE) | 38 | set(CMAKE_CXX_FLAGS_RELEASE "${optimization_flags} /MP /MD" CACHE STRING "" FORCE) |
| 39 | set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE) | 39 | set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE) |
| 40 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE) | 40 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE) |
| 41 | 41 | ||
| 42 | set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG" CACHE STRING "" FORCE) | 42 | set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG" CACHE STRING "" FORCE) |
| 43 | set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG" CACHE STRING "" FORCE) | 43 | set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG" CACHE STRING "" FORCE) |
| 44 | endif() | 44 | endif() |
| @@ -130,7 +130,7 @@ IF (APPLE) | |||
| 130 | FIND_LIBRARY(IOKIT_LIBRARY IOKit) # GLFW dependency | 130 | FIND_LIBRARY(IOKIT_LIBRARY IOKit) # GLFW dependency |
| 131 | FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo) # GLFW dependency | 131 | FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo) # GLFW dependency |
| 132 | set(PLATFORM_LIBRARIES iconv ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY}) | 132 | set(PLATFORM_LIBRARIES iconv ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY}) |
| 133 | 133 | ||
| 134 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") | 134 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") |
| 135 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++") | 135 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++") |
| 136 | ELSEIF(MINGW) | 136 | ELSEIF(MINGW) |
| @@ -38,7 +38,7 @@ PROJECT_NAME = Citra | |||
| 38 | # could be handy for archiving the generated documentation or if some version | 38 | # could be handy for archiving the generated documentation or if some version |
| 39 | # control system is used. | 39 | # control system is used. |
| 40 | 40 | ||
| 41 | PROJECT_NUMBER = | 41 | PROJECT_NUMBER = |
| 42 | 42 | ||
| 43 | # Using the PROJECT_BRIEF tag one can provide an optional one line description | 43 | # Using the PROJECT_BRIEF tag one can provide an optional one line description |
| 44 | # for a project that appears at the top of each page and should give viewer a | 44 | # for a project that appears at the top of each page and should give viewer a |
| @@ -162,7 +162,7 @@ FULL_PATH_NAMES = YES | |||
| 162 | # will be relative from the directory where doxygen is started. | 162 | # will be relative from the directory where doxygen is started. |
| 163 | # This tag requires that the tag FULL_PATH_NAMES is set to YES. | 163 | # This tag requires that the tag FULL_PATH_NAMES is set to YES. |
| 164 | 164 | ||
| 165 | STRIP_FROM_PATH = | 165 | STRIP_FROM_PATH = |
| 166 | 166 | ||
| 167 | # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the | 167 | # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the |
| 168 | # path mentioned in the documentation of a class, which tells the reader which | 168 | # path mentioned in the documentation of a class, which tells the reader which |
| @@ -171,7 +171,7 @@ STRIP_FROM_PATH = | |||
| 171 | # specify the list of include paths that are normally passed to the compiler | 171 | # specify the list of include paths that are normally passed to the compiler |
| 172 | # using the -I flag. | 172 | # using the -I flag. |
| 173 | 173 | ||
| 174 | STRIP_FROM_INC_PATH = | 174 | STRIP_FROM_INC_PATH = |
| 175 | 175 | ||
| 176 | # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but | 176 | # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but |
| 177 | # less readable) file names. This can be useful is your file systems doesn't | 177 | # less readable) file names. This can be useful is your file systems doesn't |
| @@ -238,13 +238,13 @@ TAB_SIZE = 4 | |||
| 238 | # "Side Effects:". You can put \n's in the value part of an alias to insert | 238 | # "Side Effects:". You can put \n's in the value part of an alias to insert |
| 239 | # newlines. | 239 | # newlines. |
| 240 | 240 | ||
| 241 | ALIASES = | 241 | ALIASES = |
| 242 | 242 | ||
| 243 | # This tag can be used to specify a number of word-keyword mappings (TCL only). | 243 | # This tag can be used to specify a number of word-keyword mappings (TCL only). |
| 244 | # A mapping has the form "name=value". For example adding "class=itcl::class" | 244 | # A mapping has the form "name=value". For example adding "class=itcl::class" |
| 245 | # will allow you to use the command class in the itcl::class meaning. | 245 | # will allow you to use the command class in the itcl::class meaning. |
| 246 | 246 | ||
| 247 | TCL_SUBST = | 247 | TCL_SUBST = |
| 248 | 248 | ||
| 249 | # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources | 249 | # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources |
| 250 | # only. Doxygen will then generate output that is more tailored for C. For | 250 | # only. Doxygen will then generate output that is more tailored for C. For |
| @@ -291,7 +291,7 @@ OPTIMIZE_OUTPUT_VHDL = NO | |||
| 291 | # Note that for custom extensions you also need to set FILE_PATTERNS otherwise | 291 | # Note that for custom extensions you also need to set FILE_PATTERNS otherwise |
| 292 | # the files are not read by doxygen. | 292 | # the files are not read by doxygen. |
| 293 | 293 | ||
| 294 | EXTENSION_MAPPING = | 294 | EXTENSION_MAPPING = |
| 295 | 295 | ||
| 296 | # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments | 296 | # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments |
| 297 | # according to the Markdown format, which allows for more readable | 297 | # according to the Markdown format, which allows for more readable |
| @@ -627,7 +627,7 @@ GENERATE_DEPRECATEDLIST= YES | |||
| 627 | # sections, marked by \if <section_label> ... \endif and \cond <section_label> | 627 | # sections, marked by \if <section_label> ... \endif and \cond <section_label> |
| 628 | # ... \endcond blocks. | 628 | # ... \endcond blocks. |
| 629 | 629 | ||
| 630 | ENABLED_SECTIONS = | 630 | ENABLED_SECTIONS = |
| 631 | 631 | ||
| 632 | # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the | 632 | # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the |
| 633 | # initial value of a variable or macro / define can have for it to appear in the | 633 | # initial value of a variable or macro / define can have for it to appear in the |
| @@ -669,7 +669,7 @@ SHOW_NAMESPACES = YES | |||
| 669 | # by doxygen. Whatever the program writes to standard output is used as the file | 669 | # by doxygen. Whatever the program writes to standard output is used as the file |
| 670 | # version. For an example see the documentation. | 670 | # version. For an example see the documentation. |
| 671 | 671 | ||
| 672 | FILE_VERSION_FILTER = | 672 | FILE_VERSION_FILTER = |
| 673 | 673 | ||
| 674 | # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed | 674 | # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed |
| 675 | # by doxygen. The layout file controls the global structure of the generated | 675 | # by doxygen. The layout file controls the global structure of the generated |
| @@ -682,7 +682,7 @@ FILE_VERSION_FILTER = | |||
| 682 | # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE | 682 | # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE |
| 683 | # tag is left empty. | 683 | # tag is left empty. |
| 684 | 684 | ||
| 685 | LAYOUT_FILE = | 685 | LAYOUT_FILE = |
| 686 | 686 | ||
| 687 | # The CITE_BIB_FILES tag can be used to specify one or more bib files containing | 687 | # The CITE_BIB_FILES tag can be used to specify one or more bib files containing |
| 688 | # the reference definitions. This must be a list of .bib files. The .bib | 688 | # the reference definitions. This must be a list of .bib files. The .bib |
| @@ -692,7 +692,7 @@ LAYOUT_FILE = | |||
| 692 | # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the | 692 | # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the |
| 693 | # search path. See also \cite for info how to create references. | 693 | # search path. See also \cite for info how to create references. |
| 694 | 694 | ||
| 695 | CITE_BIB_FILES = | 695 | CITE_BIB_FILES = |
| 696 | 696 | ||
| 697 | #--------------------------------------------------------------------------- | 697 | #--------------------------------------------------------------------------- |
| 698 | # Configuration options related to warning and progress messages | 698 | # Configuration options related to warning and progress messages |
| @@ -751,7 +751,7 @@ WARN_FORMAT = "$file:$line: $text" | |||
| 751 | # messages should be written. If left blank the output is written to standard | 751 | # messages should be written. If left blank the output is written to standard |
| 752 | # error (stderr). | 752 | # error (stderr). |
| 753 | 753 | ||
| 754 | WARN_LOGFILE = | 754 | WARN_LOGFILE = |
| 755 | 755 | ||
| 756 | #--------------------------------------------------------------------------- | 756 | #--------------------------------------------------------------------------- |
| 757 | # Configuration options related to the input files | 757 | # Configuration options related to the input files |
| @@ -807,7 +807,7 @@ RECURSIVE = YES | |||
| 807 | # Note that relative paths are relative to the directory from which doxygen is | 807 | # Note that relative paths are relative to the directory from which doxygen is |
| 808 | # run. | 808 | # run. |
| 809 | 809 | ||
| 810 | EXCLUDE = | 810 | EXCLUDE = |
| 811 | 811 | ||
| 812 | # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or | 812 | # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or |
| 813 | # directories that are symbolic links (a Unix file system feature) are excluded | 813 | # directories that are symbolic links (a Unix file system feature) are excluded |
| @@ -823,7 +823,7 @@ EXCLUDE_SYMLINKS = NO | |||
| 823 | # Note that the wildcards are matched against the file with absolute path, so to | 823 | # Note that the wildcards are matched against the file with absolute path, so to |
| 824 | # exclude all test directories for example use the pattern */test/* | 824 | # exclude all test directories for example use the pattern */test/* |
| 825 | 825 | ||
| 826 | EXCLUDE_PATTERNS = | 826 | EXCLUDE_PATTERNS = |
| 827 | 827 | ||
| 828 | # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names | 828 | # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names |
| 829 | # (namespaces, classes, functions, etc.) that should be excluded from the | 829 | # (namespaces, classes, functions, etc.) that should be excluded from the |
| @@ -834,13 +834,13 @@ EXCLUDE_PATTERNS = | |||
| 834 | # Note that the wildcards are matched against the file with absolute path, so to | 834 | # Note that the wildcards are matched against the file with absolute path, so to |
| 835 | # exclude all test directories use the pattern */test/* | 835 | # exclude all test directories use the pattern */test/* |
| 836 | 836 | ||
| 837 | EXCLUDE_SYMBOLS = | 837 | EXCLUDE_SYMBOLS = |
| 838 | 838 | ||
| 839 | # The EXAMPLE_PATH tag can be used to specify one or more files or directories | 839 | # The EXAMPLE_PATH tag can be used to specify one or more files or directories |
| 840 | # that contain example code fragments that are included (see the \include | 840 | # that contain example code fragments that are included (see the \include |
| 841 | # command). | 841 | # command). |
| 842 | 842 | ||
| 843 | EXAMPLE_PATH = | 843 | EXAMPLE_PATH = |
| 844 | 844 | ||
| 845 | # If the value of the EXAMPLE_PATH tag contains directories, you can use the | 845 | # If the value of the EXAMPLE_PATH tag contains directories, you can use the |
| 846 | # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and | 846 | # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and |
| @@ -860,7 +860,7 @@ EXAMPLE_RECURSIVE = NO | |||
| 860 | # that contain images that are to be included in the documentation (see the | 860 | # that contain images that are to be included in the documentation (see the |
| 861 | # \image command). | 861 | # \image command). |
| 862 | 862 | ||
| 863 | IMAGE_PATH = | 863 | IMAGE_PATH = |
| 864 | 864 | ||
| 865 | # The INPUT_FILTER tag can be used to specify a program that doxygen should | 865 | # The INPUT_FILTER tag can be used to specify a program that doxygen should |
| 866 | # invoke to filter for each input file. Doxygen will invoke the filter program | 866 | # invoke to filter for each input file. Doxygen will invoke the filter program |
| @@ -877,7 +877,7 @@ IMAGE_PATH = | |||
| 877 | # code is scanned, but not when the output code is generated. If lines are added | 877 | # code is scanned, but not when the output code is generated. If lines are added |
| 878 | # or removed, the anchors will not be placed correctly. | 878 | # or removed, the anchors will not be placed correctly. |
| 879 | 879 | ||
| 880 | INPUT_FILTER = | 880 | INPUT_FILTER = |
| 881 | 881 | ||
| 882 | # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern | 882 | # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern |
| 883 | # basis. Doxygen will compare the file name with each pattern and apply the | 883 | # basis. Doxygen will compare the file name with each pattern and apply the |
| @@ -886,7 +886,7 @@ INPUT_FILTER = | |||
| 886 | # filters are used. If the FILTER_PATTERNS tag is empty or if none of the | 886 | # filters are used. If the FILTER_PATTERNS tag is empty or if none of the |
| 887 | # patterns match the file name, INPUT_FILTER is applied. | 887 | # patterns match the file name, INPUT_FILTER is applied. |
| 888 | 888 | ||
| 889 | FILTER_PATTERNS = | 889 | FILTER_PATTERNS = |
| 890 | 890 | ||
| 891 | # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using | 891 | # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using |
| 892 | # INPUT_FILTER ) will also be used to filter the input files that are used for | 892 | # INPUT_FILTER ) will also be used to filter the input files that are used for |
| @@ -901,14 +901,14 @@ FILTER_SOURCE_FILES = NO | |||
| 901 | # *.ext= (so without naming a filter). | 901 | # *.ext= (so without naming a filter). |
| 902 | # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. | 902 | # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. |
| 903 | 903 | ||
| 904 | FILTER_SOURCE_PATTERNS = | 904 | FILTER_SOURCE_PATTERNS = |
| 905 | 905 | ||
| 906 | # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that | 906 | # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that |
| 907 | # is part of the input, its contents will be placed on the main page | 907 | # is part of the input, its contents will be placed on the main page |
| 908 | # (index.html). This can be useful if you have a project on for instance GitHub | 908 | # (index.html). This can be useful if you have a project on for instance GitHub |
| 909 | # and want to reuse the introduction page also for the doxygen output. | 909 | # and want to reuse the introduction page also for the doxygen output. |
| 910 | 910 | ||
| 911 | USE_MDFILE_AS_MAINPAGE = | 911 | USE_MDFILE_AS_MAINPAGE = |
| 912 | 912 | ||
| 913 | #--------------------------------------------------------------------------- | 913 | #--------------------------------------------------------------------------- |
| 914 | # Configuration options related to source browsing | 914 | # Configuration options related to source browsing |
| @@ -1013,7 +1013,7 @@ CLANG_ASSISTED_PARSING = NO | |||
| 1013 | # specified with INPUT and INCLUDE_PATH. | 1013 | # specified with INPUT and INCLUDE_PATH. |
| 1014 | # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. | 1014 | # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. |
| 1015 | 1015 | ||
| 1016 | CLANG_OPTIONS = | 1016 | CLANG_OPTIONS = |
| 1017 | 1017 | ||
| 1018 | #--------------------------------------------------------------------------- | 1018 | #--------------------------------------------------------------------------- |
| 1019 | # Configuration options related to the alphabetical class index | 1019 | # Configuration options related to the alphabetical class index |
| @@ -1039,7 +1039,7 @@ COLS_IN_ALPHA_INDEX = 5 | |||
| 1039 | # while generating the index headers. | 1039 | # while generating the index headers. |
| 1040 | # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. | 1040 | # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. |
| 1041 | 1041 | ||
| 1042 | IGNORE_PREFIX = | 1042 | IGNORE_PREFIX = |
| 1043 | 1043 | ||
| 1044 | #--------------------------------------------------------------------------- | 1044 | #--------------------------------------------------------------------------- |
| 1045 | # Configuration options related to the HTML output | 1045 | # Configuration options related to the HTML output |
| @@ -1083,7 +1083,7 @@ HTML_FILE_EXTENSION = .html | |||
| 1083 | # of the possible markers and block names see the documentation. | 1083 | # of the possible markers and block names see the documentation. |
| 1084 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1084 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1085 | 1085 | ||
| 1086 | HTML_HEADER = | 1086 | HTML_HEADER = |
| 1087 | 1087 | ||
| 1088 | # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each | 1088 | # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each |
| 1089 | # generated HTML page. If the tag is left blank doxygen will generate a standard | 1089 | # generated HTML page. If the tag is left blank doxygen will generate a standard |
| @@ -1093,7 +1093,7 @@ HTML_HEADER = | |||
| 1093 | # that doxygen normally uses. | 1093 | # that doxygen normally uses. |
| 1094 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1094 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1095 | 1095 | ||
| 1096 | HTML_FOOTER = | 1096 | HTML_FOOTER = |
| 1097 | 1097 | ||
| 1098 | # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style | 1098 | # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style |
| 1099 | # sheet that is used by each HTML page. It can be used to fine-tune the look of | 1099 | # sheet that is used by each HTML page. It can be used to fine-tune the look of |
| @@ -1105,7 +1105,7 @@ HTML_FOOTER = | |||
| 1105 | # obsolete. | 1105 | # obsolete. |
| 1106 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1106 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1107 | 1107 | ||
| 1108 | HTML_STYLESHEET = | 1108 | HTML_STYLESHEET = |
| 1109 | 1109 | ||
| 1110 | # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined | 1110 | # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined |
| 1111 | # cascading style sheets that are included after the standard style sheets | 1111 | # cascading style sheets that are included after the standard style sheets |
| @@ -1118,7 +1118,7 @@ HTML_STYLESHEET = | |||
| 1118 | # list). For an example see the documentation. | 1118 | # list). For an example see the documentation. |
| 1119 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1119 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1120 | 1120 | ||
| 1121 | HTML_EXTRA_STYLESHEET = | 1121 | HTML_EXTRA_STYLESHEET = |
| 1122 | 1122 | ||
| 1123 | # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or | 1123 | # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or |
| 1124 | # other source files which should be copied to the HTML output directory. Note | 1124 | # other source files which should be copied to the HTML output directory. Note |
| @@ -1128,7 +1128,7 @@ HTML_EXTRA_STYLESHEET = | |||
| 1128 | # files will be copied as-is; there are no commands or markers available. | 1128 | # files will be copied as-is; there are no commands or markers available. |
| 1129 | # This tag requires that the tag GENERATE_HTML is set to YES. | 1129 | # This tag requires that the tag GENERATE_HTML is set to YES. |
| 1130 | 1130 | ||
| 1131 | HTML_EXTRA_FILES = | 1131 | HTML_EXTRA_FILES = |
| 1132 | 1132 | ||
| 1133 | # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen | 1133 | # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen |
| 1134 | # will adjust the colors in the stylesheet and background images according to | 1134 | # will adjust the colors in the stylesheet and background images according to |
| @@ -1256,7 +1256,7 @@ GENERATE_HTMLHELP = NO | |||
| 1256 | # written to the html output directory. | 1256 | # written to the html output directory. |
| 1257 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | 1257 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. |
| 1258 | 1258 | ||
| 1259 | CHM_FILE = | 1259 | CHM_FILE = |
| 1260 | 1260 | ||
| 1261 | # The HHC_LOCATION tag can be used to specify the location (absolute path | 1261 | # The HHC_LOCATION tag can be used to specify the location (absolute path |
| 1262 | # including file name) of the HTML help compiler ( hhc.exe). If non-empty | 1262 | # including file name) of the HTML help compiler ( hhc.exe). If non-empty |
| @@ -1264,7 +1264,7 @@ CHM_FILE = | |||
| 1264 | # The file has to be specified with full path. | 1264 | # The file has to be specified with full path. |
| 1265 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | 1265 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. |
| 1266 | 1266 | ||
| 1267 | HHC_LOCATION = | 1267 | HHC_LOCATION = |
| 1268 | 1268 | ||
| 1269 | # The GENERATE_CHI flag controls if a separate .chi index file is generated ( | 1269 | # The GENERATE_CHI flag controls if a separate .chi index file is generated ( |
| 1270 | # YES) or that it should be included in the master .chm file ( NO). | 1270 | # YES) or that it should be included in the master .chm file ( NO). |
| @@ -1277,7 +1277,7 @@ GENERATE_CHI = NO | |||
| 1277 | # and project file content. | 1277 | # and project file content. |
| 1278 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. | 1278 | # This tag requires that the tag GENERATE_HTMLHELP is set to YES. |
| 1279 | 1279 | ||
| 1280 | CHM_INDEX_ENCODING = | 1280 | CHM_INDEX_ENCODING = |
| 1281 | 1281 | ||
| 1282 | # The BINARY_TOC flag controls whether a binary table of contents is generated ( | 1282 | # The BINARY_TOC flag controls whether a binary table of contents is generated ( |
| 1283 | # YES) or a normal table of contents ( NO) in the .chm file. Furthermore it | 1283 | # YES) or a normal table of contents ( NO) in the .chm file. Furthermore it |
| @@ -1308,7 +1308,7 @@ GENERATE_QHP = NO | |||
| 1308 | # the HTML output folder. | 1308 | # the HTML output folder. |
| 1309 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1309 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1310 | 1310 | ||
| 1311 | QCH_FILE = | 1311 | QCH_FILE = |
| 1312 | 1312 | ||
| 1313 | # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help | 1313 | # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help |
| 1314 | # Project output. For more information please see Qt Help Project / Namespace | 1314 | # Project output. For more information please see Qt Help Project / Namespace |
| @@ -1333,7 +1333,7 @@ QHP_VIRTUAL_FOLDER = doc | |||
| 1333 | # filters). | 1333 | # filters). |
| 1334 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1334 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1335 | 1335 | ||
| 1336 | QHP_CUST_FILTER_NAME = | 1336 | QHP_CUST_FILTER_NAME = |
| 1337 | 1337 | ||
| 1338 | # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the | 1338 | # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the |
| 1339 | # custom filter to add. For more information please see Qt Help Project / Custom | 1339 | # custom filter to add. For more information please see Qt Help Project / Custom |
| @@ -1341,21 +1341,21 @@ QHP_CUST_FILTER_NAME = | |||
| 1341 | # filters). | 1341 | # filters). |
| 1342 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1342 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1343 | 1343 | ||
| 1344 | QHP_CUST_FILTER_ATTRS = | 1344 | QHP_CUST_FILTER_ATTRS = |
| 1345 | 1345 | ||
| 1346 | # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this | 1346 | # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this |
| 1347 | # project's filter section matches. Qt Help Project / Filter Attributes (see: | 1347 | # project's filter section matches. Qt Help Project / Filter Attributes (see: |
| 1348 | # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). | 1348 | # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). |
| 1349 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1349 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1350 | 1350 | ||
| 1351 | QHP_SECT_FILTER_ATTRS = | 1351 | QHP_SECT_FILTER_ATTRS = |
| 1352 | 1352 | ||
| 1353 | # The QHG_LOCATION tag can be used to specify the location of Qt's | 1353 | # The QHG_LOCATION tag can be used to specify the location of Qt's |
| 1354 | # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the | 1354 | # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the |
| 1355 | # generated .qhp file. | 1355 | # generated .qhp file. |
| 1356 | # This tag requires that the tag GENERATE_QHP is set to YES. | 1356 | # This tag requires that the tag GENERATE_QHP is set to YES. |
| 1357 | 1357 | ||
| 1358 | QHG_LOCATION = | 1358 | QHG_LOCATION = |
| 1359 | 1359 | ||
| 1360 | # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be | 1360 | # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be |
| 1361 | # generated, together with the HTML files, they form an Eclipse help plugin. To | 1361 | # 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 | |||
| 1488 | # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols | 1488 | # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols |
| 1489 | # This tag requires that the tag USE_MATHJAX is set to YES. | 1489 | # This tag requires that the tag USE_MATHJAX is set to YES. |
| 1490 | 1490 | ||
| 1491 | MATHJAX_EXTENSIONS = | 1491 | MATHJAX_EXTENSIONS = |
| 1492 | 1492 | ||
| 1493 | # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces | 1493 | # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces |
| 1494 | # of code that will be used on startup of the MathJax code. See the MathJax site | 1494 | # of code that will be used on startup of the MathJax code. See the MathJax site |
| @@ -1496,7 +1496,7 @@ MATHJAX_EXTENSIONS = | |||
| 1496 | # example see the documentation. | 1496 | # example see the documentation. |
| 1497 | # This tag requires that the tag USE_MATHJAX is set to YES. | 1497 | # This tag requires that the tag USE_MATHJAX is set to YES. |
| 1498 | 1498 | ||
| 1499 | MATHJAX_CODEFILE = | 1499 | MATHJAX_CODEFILE = |
| 1500 | 1500 | ||
| 1501 | # When the SEARCHENGINE tag is enabled doxygen will generate a search box for | 1501 | # When the SEARCHENGINE tag is enabled doxygen will generate a search box for |
| 1502 | # the HTML output. The underlying search engine uses javascript and DHTML and | 1502 | # the HTML output. The underlying search engine uses javascript and DHTML and |
| @@ -1556,7 +1556,7 @@ EXTERNAL_SEARCH = NO | |||
| 1556 | # Searching" for details. | 1556 | # Searching" for details. |
| 1557 | # This tag requires that the tag SEARCHENGINE is set to YES. | 1557 | # This tag requires that the tag SEARCHENGINE is set to YES. |
| 1558 | 1558 | ||
| 1559 | SEARCHENGINE_URL = | 1559 | SEARCHENGINE_URL = |
| 1560 | 1560 | ||
| 1561 | # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed | 1561 | # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed |
| 1562 | # search data is written to a file for indexing by an external tool. With the | 1562 | # search data is written to a file for indexing by an external tool. With the |
| @@ -1572,7 +1572,7 @@ SEARCHDATA_FILE = searchdata.xml | |||
| 1572 | # projects and redirect the results back to the right project. | 1572 | # projects and redirect the results back to the right project. |
| 1573 | # This tag requires that the tag SEARCHENGINE is set to YES. | 1573 | # This tag requires that the tag SEARCHENGINE is set to YES. |
| 1574 | 1574 | ||
| 1575 | EXTERNAL_SEARCH_ID = | 1575 | EXTERNAL_SEARCH_ID = |
| 1576 | 1576 | ||
| 1577 | # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen | 1577 | # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen |
| 1578 | # projects other than the one defined by this configuration file, but that are | 1578 | # projects other than the one defined by this configuration file, but that are |
| @@ -1582,7 +1582,7 @@ EXTERNAL_SEARCH_ID = | |||
| 1582 | # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... | 1582 | # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... |
| 1583 | # This tag requires that the tag SEARCHENGINE is set to YES. | 1583 | # This tag requires that the tag SEARCHENGINE is set to YES. |
| 1584 | 1584 | ||
| 1585 | EXTRA_SEARCH_MAPPINGS = | 1585 | EXTRA_SEARCH_MAPPINGS = |
| 1586 | 1586 | ||
| 1587 | #--------------------------------------------------------------------------- | 1587 | #--------------------------------------------------------------------------- |
| 1588 | # Configuration options related to the LaTeX output | 1588 | # Configuration options related to the LaTeX output |
| @@ -1643,7 +1643,7 @@ PAPER_TYPE = a4 | |||
| 1643 | # If left blank no extra packages will be included. | 1643 | # If left blank no extra packages will be included. |
| 1644 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 1644 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1645 | 1645 | ||
| 1646 | EXTRA_PACKAGES = | 1646 | EXTRA_PACKAGES = |
| 1647 | 1647 | ||
| 1648 | # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the | 1648 | # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the |
| 1649 | # generated LaTeX document. The header should contain everything until the first | 1649 | # generated LaTeX document. The header should contain everything until the first |
| @@ -1659,7 +1659,7 @@ EXTRA_PACKAGES = | |||
| 1659 | # HTML_HEADER. | 1659 | # HTML_HEADER. |
| 1660 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 1660 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1661 | 1661 | ||
| 1662 | LATEX_HEADER = | 1662 | LATEX_HEADER = |
| 1663 | 1663 | ||
| 1664 | # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the | 1664 | # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the |
| 1665 | # generated LaTeX document. The footer should contain everything after the last | 1665 | # generated LaTeX document. The footer should contain everything after the last |
| @@ -1670,7 +1670,7 @@ LATEX_HEADER = | |||
| 1670 | # Note: Only use a user-defined footer if you know what you are doing! | 1670 | # Note: Only use a user-defined footer if you know what you are doing! |
| 1671 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 1671 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1672 | 1672 | ||
| 1673 | LATEX_FOOTER = | 1673 | LATEX_FOOTER = |
| 1674 | 1674 | ||
| 1675 | # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or | 1675 | # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or |
| 1676 | # other source files which should be copied to the LATEX_OUTPUT output | 1676 | # other source files which should be copied to the LATEX_OUTPUT output |
| @@ -1678,7 +1678,7 @@ LATEX_FOOTER = | |||
| 1678 | # markers available. | 1678 | # markers available. |
| 1679 | # This tag requires that the tag GENERATE_LATEX is set to YES. | 1679 | # This tag requires that the tag GENERATE_LATEX is set to YES. |
| 1680 | 1680 | ||
| 1681 | LATEX_EXTRA_FILES = | 1681 | LATEX_EXTRA_FILES = |
| 1682 | 1682 | ||
| 1683 | # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is | 1683 | # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is |
| 1684 | # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will | 1684 | # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will |
| @@ -1778,14 +1778,14 @@ RTF_HYPERLINKS = NO | |||
| 1778 | # default style sheet that doxygen normally uses. | 1778 | # default style sheet that doxygen normally uses. |
| 1779 | # This tag requires that the tag GENERATE_RTF is set to YES. | 1779 | # This tag requires that the tag GENERATE_RTF is set to YES. |
| 1780 | 1780 | ||
| 1781 | RTF_STYLESHEET_FILE = | 1781 | RTF_STYLESHEET_FILE = |
| 1782 | 1782 | ||
| 1783 | # Set optional variables used in the generation of an RTF document. Syntax is | 1783 | # Set optional variables used in the generation of an RTF document. Syntax is |
| 1784 | # similar to doxygen's config file. A template extensions file can be generated | 1784 | # similar to doxygen's config file. A template extensions file can be generated |
| 1785 | # using doxygen -e rtf extensionFile. | 1785 | # using doxygen -e rtf extensionFile. |
| 1786 | # This tag requires that the tag GENERATE_RTF is set to YES. | 1786 | # This tag requires that the tag GENERATE_RTF is set to YES. |
| 1787 | 1787 | ||
| 1788 | RTF_EXTENSIONS_FILE = | 1788 | RTF_EXTENSIONS_FILE = |
| 1789 | 1789 | ||
| 1790 | #--------------------------------------------------------------------------- | 1790 | #--------------------------------------------------------------------------- |
| 1791 | # Configuration options related to the man page output | 1791 | # Configuration options related to the man page output |
| @@ -1820,7 +1820,7 @@ MAN_EXTENSION = .3 | |||
| 1820 | # MAN_EXTENSION with the initial . removed. | 1820 | # MAN_EXTENSION with the initial . removed. |
| 1821 | # This tag requires that the tag GENERATE_MAN is set to YES. | 1821 | # This tag requires that the tag GENERATE_MAN is set to YES. |
| 1822 | 1822 | ||
| 1823 | MAN_SUBDIR = | 1823 | MAN_SUBDIR = |
| 1824 | 1824 | ||
| 1825 | # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it | 1825 | # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it |
| 1826 | # will generate one additional man file for each entity documented in the real | 1826 | # will generate one additional man file for each entity documented in the real |
| @@ -1933,7 +1933,7 @@ PERLMOD_PRETTY = YES | |||
| 1933 | # overwrite each other's variables. | 1933 | # overwrite each other's variables. |
| 1934 | # This tag requires that the tag GENERATE_PERLMOD is set to YES. | 1934 | # This tag requires that the tag GENERATE_PERLMOD is set to YES. |
| 1935 | 1935 | ||
| 1936 | PERLMOD_MAKEVAR_PREFIX = | 1936 | PERLMOD_MAKEVAR_PREFIX = |
| 1937 | 1937 | ||
| 1938 | #--------------------------------------------------------------------------- | 1938 | #--------------------------------------------------------------------------- |
| 1939 | # Configuration options related to the preprocessor | 1939 | # Configuration options related to the preprocessor |
| @@ -1974,7 +1974,7 @@ SEARCH_INCLUDES = YES | |||
| 1974 | # preprocessor. | 1974 | # preprocessor. |
| 1975 | # This tag requires that the tag SEARCH_INCLUDES is set to YES. | 1975 | # This tag requires that the tag SEARCH_INCLUDES is set to YES. |
| 1976 | 1976 | ||
| 1977 | INCLUDE_PATH = | 1977 | INCLUDE_PATH = |
| 1978 | 1978 | ||
| 1979 | # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard | 1979 | # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard |
| 1980 | # patterns (like *.h and *.hpp) to filter out the header-files in the | 1980 | # patterns (like *.h and *.hpp) to filter out the header-files in the |
| @@ -1982,7 +1982,7 @@ INCLUDE_PATH = | |||
| 1982 | # used. | 1982 | # used. |
| 1983 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | 1983 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. |
| 1984 | 1984 | ||
| 1985 | INCLUDE_FILE_PATTERNS = | 1985 | INCLUDE_FILE_PATTERNS = |
| 1986 | 1986 | ||
| 1987 | # The PREDEFINED tag can be used to specify one or more macro names that are | 1987 | # The PREDEFINED tag can be used to specify one or more macro names that are |
| 1988 | # defined before the preprocessor is started (similar to the -D option of e.g. | 1988 | # defined before the preprocessor is started (similar to the -D option of e.g. |
| @@ -1992,7 +1992,7 @@ INCLUDE_FILE_PATTERNS = | |||
| 1992 | # recursively expanded use the := operator instead of the = operator. | 1992 | # recursively expanded use the := operator instead of the = operator. |
| 1993 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | 1993 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. |
| 1994 | 1994 | ||
| 1995 | PREDEFINED = | 1995 | PREDEFINED = |
| 1996 | 1996 | ||
| 1997 | # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this | 1997 | # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this |
| 1998 | # tag can be used to specify a list of macro names that should be expanded. The | 1998 | # tag can be used to specify a list of macro names that should be expanded. The |
| @@ -2001,7 +2001,7 @@ PREDEFINED = | |||
| 2001 | # definition found in the source code. | 2001 | # definition found in the source code. |
| 2002 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. | 2002 | # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. |
| 2003 | 2003 | ||
| 2004 | EXPAND_AS_DEFINED = | 2004 | EXPAND_AS_DEFINED = |
| 2005 | 2005 | ||
| 2006 | # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will | 2006 | # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will |
| 2007 | # remove all references to function-like macros that are alone on a line, have | 2007 | # remove all references to function-like macros that are alone on a line, have |
| @@ -2030,13 +2030,13 @@ SKIP_FUNCTION_MACROS = YES | |||
| 2030 | # the path). If a tag file is not located in the directory in which doxygen is | 2030 | # the path). If a tag file is not located in the directory in which doxygen is |
| 2031 | # run, you must also specify the path to the tagfile here. | 2031 | # run, you must also specify the path to the tagfile here. |
| 2032 | 2032 | ||
| 2033 | TAGFILES = | 2033 | TAGFILES = |
| 2034 | 2034 | ||
| 2035 | # When a file name is specified after GENERATE_TAGFILE, doxygen will create a | 2035 | # When a file name is specified after GENERATE_TAGFILE, doxygen will create a |
| 2036 | # tag file that is based on the input files it reads. See section "Linking to | 2036 | # tag file that is based on the input files it reads. See section "Linking to |
| 2037 | # external documentation" for more information about the usage of tag files. | 2037 | # external documentation" for more information about the usage of tag files. |
| 2038 | 2038 | ||
| 2039 | GENERATE_TAGFILE = | 2039 | GENERATE_TAGFILE = |
| 2040 | 2040 | ||
| 2041 | # If the ALLEXTERNALS tag is set to YES all external class will be listed in the | 2041 | # If the ALLEXTERNALS tag is set to YES all external class will be listed in the |
| 2042 | # class index. If set to NO only the inherited external classes will be listed. | 2042 | # class index. If set to NO only the inherited external classes will be listed. |
| @@ -2084,14 +2084,14 @@ CLASS_DIAGRAMS = YES | |||
| 2084 | # the mscgen tool resides. If left empty the tool is assumed to be found in the | 2084 | # the mscgen tool resides. If left empty the tool is assumed to be found in the |
| 2085 | # default search path. | 2085 | # default search path. |
| 2086 | 2086 | ||
| 2087 | MSCGEN_PATH = | 2087 | MSCGEN_PATH = |
| 2088 | 2088 | ||
| 2089 | # You can include diagrams made with dia in doxygen documentation. Doxygen will | 2089 | # You can include diagrams made with dia in doxygen documentation. Doxygen will |
| 2090 | # then run dia to produce the diagram and insert it in the documentation. The | 2090 | # then run dia to produce the diagram and insert it in the documentation. The |
| 2091 | # DIA_PATH tag allows you to specify the directory where the dia binary resides. | 2091 | # DIA_PATH tag allows you to specify the directory where the dia binary resides. |
| 2092 | # If left empty dia is assumed to be found in the default search path. | 2092 | # If left empty dia is assumed to be found in the default search path. |
| 2093 | 2093 | ||
| 2094 | DIA_PATH = | 2094 | DIA_PATH = |
| 2095 | 2095 | ||
| 2096 | # If set to YES, the inheritance and collaboration graphs will hide inheritance | 2096 | # If set to YES, the inheritance and collaboration graphs will hide inheritance |
| 2097 | # and usage relations if the target is undocumented or is not a class. | 2097 | # and usage relations if the target is undocumented or is not a class. |
| @@ -2140,7 +2140,7 @@ DOT_FONTSIZE = 10 | |||
| 2140 | # the path where dot can find it using this tag. | 2140 | # the path where dot can find it using this tag. |
| 2141 | # This tag requires that the tag HAVE_DOT is set to YES. | 2141 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2142 | 2142 | ||
| 2143 | DOT_FONTPATH = | 2143 | DOT_FONTPATH = |
| 2144 | 2144 | ||
| 2145 | # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for | 2145 | # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for |
| 2146 | # each documented class showing the direct and indirect inheritance relations. | 2146 | # each documented class showing the direct and indirect inheritance relations. |
| @@ -2278,26 +2278,26 @@ INTERACTIVE_SVG = NO | |||
| 2278 | # found. If left blank, it is assumed the dot tool can be found in the path. | 2278 | # found. If left blank, it is assumed the dot tool can be found in the path. |
| 2279 | # This tag requires that the tag HAVE_DOT is set to YES. | 2279 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2280 | 2280 | ||
| 2281 | DOT_PATH = | 2281 | DOT_PATH = |
| 2282 | 2282 | ||
| 2283 | # The DOTFILE_DIRS tag can be used to specify one or more directories that | 2283 | # The DOTFILE_DIRS tag can be used to specify one or more directories that |
| 2284 | # contain dot files that are included in the documentation (see the \dotfile | 2284 | # contain dot files that are included in the documentation (see the \dotfile |
| 2285 | # command). | 2285 | # command). |
| 2286 | # This tag requires that the tag HAVE_DOT is set to YES. | 2286 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2287 | 2287 | ||
| 2288 | DOTFILE_DIRS = | 2288 | DOTFILE_DIRS = |
| 2289 | 2289 | ||
| 2290 | # The MSCFILE_DIRS tag can be used to specify one or more directories that | 2290 | # The MSCFILE_DIRS tag can be used to specify one or more directories that |
| 2291 | # contain msc files that are included in the documentation (see the \mscfile | 2291 | # contain msc files that are included in the documentation (see the \mscfile |
| 2292 | # command). | 2292 | # command). |
| 2293 | 2293 | ||
| 2294 | MSCFILE_DIRS = | 2294 | MSCFILE_DIRS = |
| 2295 | 2295 | ||
| 2296 | # The DIAFILE_DIRS tag can be used to specify one or more directories that | 2296 | # The DIAFILE_DIRS tag can be used to specify one or more directories that |
| 2297 | # contain dia files that are included in the documentation (see the \diafile | 2297 | # contain dia files that are included in the documentation (see the \diafile |
| 2298 | # command). | 2298 | # command). |
| 2299 | 2299 | ||
| 2300 | DIAFILE_DIRS = | 2300 | DIAFILE_DIRS = |
| 2301 | 2301 | ||
| 2302 | # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the | 2302 | # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the |
| 2303 | # path where java can find the plantuml.jar file. If left blank, it is assumed | 2303 | # path where java can find the plantuml.jar file. If left blank, it is assumed |
| @@ -2306,7 +2306,7 @@ DIAFILE_DIRS = | |||
| 2306 | # will not generate output for the diagram. | 2306 | # will not generate output for the diagram. |
| 2307 | # This tag requires that the tag HAVE_DOT is set to YES. | 2307 | # This tag requires that the tag HAVE_DOT is set to YES. |
| 2308 | 2308 | ||
| 2309 | PLANTUML_JAR_PATH = | 2309 | PLANTUML_JAR_PATH = |
| 2310 | 2310 | ||
| 2311 | # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes | 2311 | # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes |
| 2312 | # that will be shown in the graph. If the number of nodes in a graph becomes | 2312 | # that will be shown in the graph. If the number of nodes in a graph becomes |
| @@ -28,5 +28,5 @@ If you like, you can [donate by PayPal](https://www.paypal.com/cgi-bin/webscr?cm | |||
| 28 | * Infrastructure setup | 28 | * Infrastructure setup |
| 29 | * Eventually 3D displays to get proper 3D output working | 29 | * Eventually 3D displays to get proper 3D output working |
| 30 | * ... etc ... | 30 | * ... etc ... |
| 31 | 31 | ||
| 32 | 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. | 32 | 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 f2b656729..46362d1b4 100644 --- a/appveyor.yml +++ b/appveyor.yml | |||
| @@ -35,11 +35,11 @@ after_build: | |||
| 35 | $BUILD_NAME = "citra-${GITDATE}-${GITREV}-windows-amd64.7z" -replace " ","" | 35 | $BUILD_NAME = "citra-${GITDATE}-${GITREV}-windows-amd64.7z" -replace " ","" |
| 36 | # Zip up the build folder | 36 | # Zip up the build folder |
| 37 | 7z a $BUILD_NAME .\build\bin\release\* | 37 | 7z a $BUILD_NAME .\build\bin\release\* |
| 38 | 38 | ||
| 39 | # Download winscp | 39 | # Download winscp |
| 40 | Invoke-WebRequest "http://hivelocity.dl.sourceforge.net/project/winscp/WinSCP/5.7/winscp570.zip" -OutFile "winscp570.zip" | 40 | Invoke-WebRequest "http://hivelocity.dl.sourceforge.net/project/winscp/WinSCP/5.7/winscp570.zip" -OutFile "winscp570.zip" |
| 41 | 7z e -y winscp570.zip | 41 | 7z e -y winscp570.zip |
| 42 | 42 | ||
| 43 | # Upload to server | 43 | # Upload to server |
| 44 | .\WinSCP.com /command ` | 44 | .\WinSCP.com /command ` |
| 45 | "option batch abort" ` | 45 | "option batch abort" ` |
diff --git a/src/citra/resource.h b/src/citra/resource.h index 0d42c8a8a..127896424 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 efccdbec6..c05779380 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt | |||
| @@ -89,15 +89,15 @@ if (Qt5_FOUND AND MSVC) | |||
| 89 | ) | 89 | ) |
| 90 | set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") | 90 | set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") |
| 91 | set(PLATFORMS ${DLL_DEST}platforms/) | 91 | set(PLATFORMS ${DLL_DEST}platforms/) |
| 92 | 92 | ||
| 93 | # windows commandline expects the / to be \ so switch them | 93 | # windows commandline expects the / to be \ so switch them |
| 94 | string(REPLACE "/" "\\" Qt5_DLL_DIR ${Qt5_DLL_DIR}) | 94 | string(REPLACE "/" "\\" Qt5_DLL_DIR ${Qt5_DLL_DIR}) |
| 95 | string(REPLACE "/" "\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR}) | 95 | string(REPLACE "/" "\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR}) |
| 96 | string(REPLACE "/" "\\" DLL_DEST ${DLL_DEST}) | 96 | string(REPLACE "/" "\\" DLL_DEST ${DLL_DEST}) |
| 97 | string(REPLACE "/" "\\" PLATFORMS ${PLATFORMS}) | 97 | string(REPLACE "/" "\\" PLATFORMS ${PLATFORMS}) |
| 98 | 98 | ||
| 99 | # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output | 99 | # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output |
| 100 | # cmake adds an extra check for command success which doesn't work too well with robocopy | 100 | # cmake adds an extra check for command success which doesn't work too well with robocopy |
| 101 | # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" | 101 | # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" |
| 102 | add_custom_command(TARGET citra-qt POST_BUILD | 102 | add_custom_command(TARGET citra-qt POST_BUILD |
| 103 | COMMAND robocopy ${Qt5_DLL_DIR} ${DLL_DEST} ${Qt5_DLLS} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" | 103 | 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 72b55e94d..3db09c65b 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp | |||
| @@ -57,7 +57,7 @@ void EmuThread::run() { | |||
| 57 | Core::SingleStep(); | 57 | Core::SingleStep(); |
| 58 | emit DebugModeEntered(); | 58 | emit DebugModeEntered(); |
| 59 | yieldCurrentThread(); | 59 | yieldCurrentThread(); |
| 60 | 60 | ||
| 61 | was_active = false; | 61 | was_active = false; |
| 62 | } else { | 62 | } else { |
| 63 | std::unique_lock<std::mutex> lock(running_mutex); | 63 | std::unique_lock<std::mutex> lock(running_mutex); |
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h index 16809eaae..475124319 100644 --- a/src/citra_qt/bootmanager.h +++ b/src/citra_qt/bootmanager.h | |||
| @@ -80,7 +80,7 @@ signals: | |||
| 80 | * @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) | 80 | * @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) |
| 81 | */ | 81 | */ |
| 82 | void DebugModeEntered(); | 82 | void DebugModeEntered(); |
| 83 | 83 | ||
| 84 | /** | 84 | /** |
| 85 | * Emitted right before the CPU continues execution | 85 | * Emitted right before the CPU continues execution |
| 86 | * | 86 | * |
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 94e204717..6799ce844 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp | |||
| @@ -39,7 +39,7 @@ void CallstackWidget::OnDebugModeEntered() | |||
| 39 | { | 39 | { |
| 40 | ret_addr = Memory::Read32(addr); | 40 | ret_addr = Memory::Read32(addr); |
| 41 | call_addr = ret_addr - 4; //get call address??? | 41 | call_addr = ret_addr - 4; //get call address??? |
| 42 | 42 | ||
| 43 | if (Memory::GetPointer(call_addr) == nullptr) | 43 | if (Memory::GetPointer(call_addr) == nullptr) |
| 44 | break; | 44 | break; |
| 45 | 45 | ||
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index f6010459a..8041816a0 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp | |||
| @@ -127,7 +127,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) | |||
| 127 | 127 | ||
| 128 | ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer); | 128 | ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer); |
| 129 | SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked()); | 129 | SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked()); |
| 130 | 130 | ||
| 131 | ui.action_Single_Window_Mode->setChecked(settings.value("singleWindowMode", true).toBool()); | 131 | ui.action_Single_Window_Mode->setChecked(settings.value("singleWindowMode", true).toBool()); |
| 132 | ToggleWindowMode(); | 132 | ToggleWindowMode(); |
| 133 | 133 | ||
diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index 0942c28c8..9a809ee6c 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui | |||
| @@ -24,7 +24,20 @@ | |||
| 24 | <bool>true</bool> | 24 | <bool>true</bool> |
| 25 | </property> | 25 | </property> |
| 26 | <widget class="QWidget" name="centralwidget"> | 26 | <widget class="QWidget" name="centralwidget"> |
| 27 | <layout class="QHBoxLayout" name="horizontalLayout"/> | 27 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 28 | <property name="leftMargin"> | ||
| 29 | <number>0</number> | ||
| 30 | </property> | ||
| 31 | <property name="topMargin"> | ||
| 32 | <number>0</number> | ||
| 33 | </property> | ||
| 34 | <property name="rightMargin"> | ||
| 35 | <number>0</number> | ||
| 36 | </property> | ||
| 37 | <property name="bottomMargin"> | ||
| 38 | <number>0</number> | ||
| 39 | </property> | ||
| 40 | </layout> | ||
| 28 | </widget> | 41 | </widget> |
| 29 | <widget class="QMenuBar" name="menubar"> | 42 | <widget class="QMenuBar" name="menubar"> |
| 30 | <property name="geometry"> | 43 | <property name="geometry"> |
| @@ -92,7 +105,7 @@ | |||
| 92 | </action> | 105 | </action> |
| 93 | <action name="action_Start"> | 106 | <action name="action_Start"> |
| 94 | <property name="enabled"> | 107 | <property name="enabled"> |
| 95 | <bool>false</bool> | 108 | <bool>false</bool> |
| 96 | </property> | 109 | </property> |
| 97 | <property name="text"> | 110 | <property name="text"> |
| 98 | <string>&Start</string> | 111 | <string>&Start</string> |
diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index f5b6c7301..43facb85c 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 | |||
| 32 | 32 | ||
| 33 | new_x = std::max(new_x, framebuffer_layout.bottom_screen.left); | 33 | new_x = std::max(new_x, framebuffer_layout.bottom_screen.left); |
| 34 | new_x = std::min(new_x, framebuffer_layout.bottom_screen.right-1); | 34 | new_x = std::min(new_x, framebuffer_layout.bottom_screen.right-1); |
| 35 | 35 | ||
| 36 | new_y = std::max(new_y, framebuffer_layout.bottom_screen.top); | 36 | new_y = std::max(new_y, framebuffer_layout.bottom_screen.top); |
| 37 | new_y = std::min(new_y, framebuffer_layout.bottom_screen.bottom-1); | 37 | new_y = std::min(new_y, framebuffer_layout.bottom_screen.bottom-1); |
| 38 | 38 | ||
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 7cdd1484f..24648ea33 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <io.h> | 16 | #include <io.h> |
| 17 | #include <direct.h> // getcwd | 17 | #include <direct.h> // getcwd |
| 18 | #include <tchar.h> | 18 | #include <tchar.h> |
| 19 | 19 | ||
| 20 | // 64 bit offsets for windows | 20 | // 64 bit offsets for windows |
| 21 | #define fseeko _fseeki64 | 21 | #define fseeko _fseeki64 |
| 22 | #define ftello _ftelli64 | 22 | #define ftello _ftelli64 |
diff --git a/src/common/swap.h b/src/common/swap.h index 7e37655bf..588cebc70 100644 --- a/src/common/swap.h +++ b/src/common/swap.h | |||
| @@ -135,7 +135,7 @@ template <> | |||
| 135 | inline void swap<8>(u8* data) { | 135 | inline void swap<8>(u8* data) { |
| 136 | *reinterpret_cast<u64*>(data) = swap64(data); | 136 | *reinterpret_cast<u64*>(data) = swap64(data); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | } // Namespace Common | 139 | } // Namespace Common |
| 140 | 140 | ||
| 141 | 141 | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 42b4be938..bbc285168 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -36,6 +36,7 @@ set(SRCS | |||
| 36 | hle/kernel/shared_memory.cpp | 36 | hle/kernel/shared_memory.cpp |
| 37 | hle/kernel/thread.cpp | 37 | hle/kernel/thread.cpp |
| 38 | hle/kernel/timer.cpp | 38 | hle/kernel/timer.cpp |
| 39 | hle/kernel/vm_manager.cpp | ||
| 39 | hle/service/ac_u.cpp | 40 | hle/service/ac_u.cpp |
| 40 | hle/service/act_u.cpp | 41 | hle/service/act_u.cpp |
| 41 | hle/service/am_app.cpp | 42 | hle/service/am_app.cpp |
| @@ -147,6 +148,7 @@ set(HEADERS | |||
| 147 | hle/kernel/shared_memory.h | 148 | hle/kernel/shared_memory.h |
| 148 | hle/kernel/thread.h | 149 | hle/kernel/thread.h |
| 149 | hle/kernel/timer.h | 150 | hle/kernel/timer.h |
| 151 | hle/kernel/vm_manager.h | ||
| 150 | hle/result.h | 152 | hle/result.h |
| 151 | hle/service/ac_u.h | 153 | hle/service/ac_u.h |
| 152 | hle/service/act_u.h | 154 | hle/service/act_u.h |
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 913dc1454..f6d44d85a 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) { | |||
| 813 | // SWI | 813 | // SWI |
| 814 | return OP_SWI; | 814 | return OP_SWI; |
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | uint8_t bit4 = (insn >> 4) & 0x1; | 817 | uint8_t bit4 = (insn >> 4) & 0x1; |
| 818 | uint8_t cpnum = (insn >> 8) & 0xf; | 818 | uint8_t cpnum = (insn >> 8) & 0xf; |
| 819 | 819 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index b5d1b43cd..b00eb49a9 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) { | |||
| 134 | unsigned int immed_8 = BITS(sht_oper, 0, 7); | 134 | unsigned int immed_8 = BITS(sht_oper, 0, 7); |
| 135 | unsigned int rotate_imm = BITS(sht_oper, 8, 11); | 135 | unsigned int rotate_imm = BITS(sht_oper, 8, 11); |
| 136 | unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2); | 136 | unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2); |
| 137 | if (rotate_imm == 0) | 137 | if (rotate_imm == 0) |
| 138 | cpu->shifter_carry_out = cpu->CFlag; | 138 | cpu->shifter_carry_out = cpu->CFlag; |
| 139 | else | 139 | else |
| 140 | cpu->shifter_carry_out = BIT(shifter_operand, 31); | 140 | cpu->shifter_carry_out = BIT(shifter_operand, 31); |
| @@ -521,7 +521,7 @@ static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned | |||
| 521 | addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8; | 521 | addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8; |
| 522 | else | 522 | else |
| 523 | addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8; | 523 | addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8; |
| 524 | 524 | ||
| 525 | virt_addr = addr; | 525 | virt_addr = addr; |
| 526 | } | 526 | } |
| 527 | 527 | ||
| @@ -550,7 +550,7 @@ static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsig | |||
| 550 | 550 | ||
| 551 | if (U_BIT) | 551 | if (U_BIT) |
| 552 | addr = rn + offset_8; | 552 | addr = rn + offset_8; |
| 553 | else | 553 | else |
| 554 | addr = rn - offset_8; | 554 | addr = rn - offset_8; |
| 555 | 555 | ||
| 556 | virt_addr = addr; | 556 | virt_addr = addr; |
| @@ -1306,8 +1306,8 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) | |||
| 1306 | inst_cream->Rd = BITS(inst, 12, 15); | 1306 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1307 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 1307 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 1308 | inst_cream->shtop_func = get_shtop(inst); | 1308 | inst_cream->shtop_func = get_shtop(inst); |
| 1309 | 1309 | ||
| 1310 | if (inst_cream->Rd == 15) | 1310 | if (inst_cream->Rd == 15) |
| 1311 | inst_base->br = INDIRECT_BRANCH; | 1311 | inst_base->br = INDIRECT_BRANCH; |
| 1312 | 1312 | ||
| 1313 | return inst_base; | 1313 | return inst_base; |
| @@ -1350,7 +1350,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) | |||
| 1350 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 1350 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 1351 | inst_cream->shtop_func = get_shtop(inst); | 1351 | inst_cream->shtop_func = get_shtop(inst); |
| 1352 | 1352 | ||
| 1353 | if (inst_cream->Rd == 15) | 1353 | if (inst_cream->Rd == 15) |
| 1354 | inst_base->br = INDIRECT_BRANCH; | 1354 | inst_base->br = INDIRECT_BRANCH; |
| 1355 | return inst_base; | 1355 | return inst_base; |
| 1356 | } | 1356 | } |
| @@ -3269,7 +3269,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) | |||
| 3269 | #define VFP_INTERPRETER_STRUCT | 3269 | #define VFP_INTERPRETER_STRUCT |
| 3270 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | 3270 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |
| 3271 | #undef VFP_INTERPRETER_STRUCT | 3271 | #undef VFP_INTERPRETER_STRUCT |
| 3272 | 3272 | ||
| 3273 | #define VFP_INTERPRETER_TRANS | 3273 | #define VFP_INTERPRETER_TRANS |
| 3274 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | 3274 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |
| 3275 | #undef VFP_INTERPRETER_TRANS | 3275 | #undef VFP_INTERPRETER_TRANS |
| @@ -3478,9 +3478,9 @@ const transop_fp_t arm_instruction_trans[] = { | |||
| 3478 | INTERPRETER_TRANSLATE(bbl), | 3478 | INTERPRETER_TRANSLATE(bbl), |
| 3479 | 3479 | ||
| 3480 | // All the thumb instructions should be placed the end of table | 3480 | // All the thumb instructions should be placed the end of table |
| 3481 | INTERPRETER_TRANSLATE(b_2_thumb), | 3481 | INTERPRETER_TRANSLATE(b_2_thumb), |
| 3482 | INTERPRETER_TRANSLATE(b_cond_thumb), | 3482 | INTERPRETER_TRANSLATE(b_cond_thumb), |
| 3483 | INTERPRETER_TRANSLATE(bl_1_thumb), | 3483 | INTERPRETER_TRANSLATE(bl_1_thumb), |
| 3484 | INTERPRETER_TRANSLATE(bl_2_thumb), | 3484 | INTERPRETER_TRANSLATE(bl_2_thumb), |
| 3485 | INTERPRETER_TRANSLATE(blx_1_thumb) | 3485 | INTERPRETER_TRANSLATE(blx_1_thumb) |
| 3486 | }; | 3486 | }; |
| @@ -4338,7 +4338,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4338 | } | 4338 | } |
| 4339 | } | 4339 | } |
| 4340 | if (BIT(inst, 13)) { | 4340 | if (BIT(inst, 13)) { |
| 4341 | if (cpu->Mode == USER32MODE) | 4341 | if (cpu->Mode == USER32MODE) |
| 4342 | cpu->Reg[13] = ReadMemory32(cpu, addr); | 4342 | cpu->Reg[13] = ReadMemory32(cpu, addr); |
| 4343 | else | 4343 | else |
| 4344 | cpu->Reg_usr[0] = ReadMemory32(cpu, addr); | 4344 | cpu->Reg_usr[0] = ReadMemory32(cpu, addr); |
| @@ -4346,7 +4346,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4346 | addr += 4; | 4346 | addr += 4; |
| 4347 | } | 4347 | } |
| 4348 | if (BIT(inst, 14)) { | 4348 | if (BIT(inst, 14)) { |
| 4349 | if (cpu->Mode == USER32MODE) | 4349 | if (cpu->Mode == USER32MODE) |
| 4350 | cpu->Reg[14] = ReadMemory32(cpu, addr); | 4350 | cpu->Reg[14] = ReadMemory32(cpu, addr); |
| 4351 | else | 4351 | else |
| 4352 | cpu->Reg_usr[1] = ReadMemory32(cpu, addr); | 4352 | cpu->Reg_usr[1] = ReadMemory32(cpu, addr); |
| @@ -5148,7 +5148,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5148 | REV16_INST: | 5148 | REV16_INST: |
| 5149 | REVSH_INST: | 5149 | REVSH_INST: |
| 5150 | { | 5150 | { |
| 5151 | 5151 | ||
| 5152 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 5152 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 5153 | rev_inst* const inst_cream = (rev_inst*)inst_base->component; | 5153 | rev_inst* const inst_cream = (rev_inst*)inst_base->component; |
| 5154 | 5154 | ||
| @@ -5721,7 +5721,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5721 | 5721 | ||
| 5722 | if (do_swap) | 5722 | if (do_swap) |
| 5723 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); | 5723 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); |
| 5724 | 5724 | ||
| 5725 | const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); | 5725 | const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); |
| 5726 | const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); | 5726 | const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); |
| 5727 | s64 result; | 5727 | s64 result; |
| @@ -6583,7 +6583,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6583 | { | 6583 | { |
| 6584 | u32 lo_val = 0; | 6584 | u32 lo_val = 0; |
| 6585 | u32 hi_val = 0; | 6585 | u32 hi_val = 0; |
| 6586 | 6586 | ||
| 6587 | // UHADD16 | 6587 | // UHADD16 |
| 6588 | if (op2 == 0x00) { | 6588 | if (op2 == 0x00) { |
| 6589 | lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); | 6589 | lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); |
| @@ -6772,7 +6772,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 6772 | 6772 | ||
| 6773 | u16 lo_val = 0; | 6773 | u16 lo_val = 0; |
| 6774 | u16 hi_val = 0; | 6774 | u16 hi_val = 0; |
| 6775 | 6775 | ||
| 6776 | // UQADD16 | 6776 | // UQADD16 |
| 6777 | if (op2 == 0x00) { | 6777 | if (op2 == 0x00) { |
| 6778 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); | 6778 | 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 cdaf21450..2fc8170be 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp +++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp | |||
| @@ -184,7 +184,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 184 | case 9: // LDR Rd,[PC,#imm8] | 184 | case 9: // LDR Rd,[PC,#imm8] |
| 185 | *ainstr = 0xE59F0000 // base | 185 | *ainstr = 0xE59F0000 // base |
| 186 | | ((tinstr & 0x0700) << (12 - 8)) // Rd | 186 | | ((tinstr & 0x0700) << (12 - 8)) // Rd |
| 187 | |((tinstr & 0x00FF) << (2 - 0)); // off8 | 187 | |((tinstr & 0x00FF) << (2 - 0)); // off8 |
| 188 | break; | 188 | break; |
| 189 | 189 | ||
| 190 | case 10: | 190 | case 10: |
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 1b078dc71..83f7f3e2c 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 | |||
| 628 | cpu->CP15[CP15_DATA_SYNC_BARRIER] = value; | 628 | cpu->CP15[CP15_DATA_SYNC_BARRIER] = value; |
| 629 | else if (opcode_2 == 5) | 629 | else if (opcode_2 == 5) |
| 630 | cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value; | 630 | cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value; |
| 631 | 631 | ||
| 632 | } | 632 | } |
| 633 | else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) | 633 | else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) |
| 634 | { | 634 | { |
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 08ece69b6..d2c901100 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h | |||
| @@ -1,16 +1,16 @@ | |||
| 1 | /* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. | 1 | /* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. |
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. |
| 3 | 3 | ||
| 4 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
| 5 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
| 6 | the Free Software Foundation; either version 2 of the License, or | 6 | the Free Software Foundation; either version 2 of the License, or |
| 7 | (at your option) any later version. | 7 | (at your option) any later version. |
| 8 | 8 | ||
| 9 | This program is distributed in the hope that it will be useful, | 9 | This program is distributed in the hope that it will be useful, |
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | GNU General Public License for more details. | 12 | GNU General Public License for more details. |
| 13 | 13 | ||
| 14 | You should have received a copy of the GNU General Public License | 14 | You should have received a copy of the GNU General Public License |
| 15 | along with this program; if not, write to the Free Software | 15 | along with this program; if not, write to the Free Software |
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h index ccc0212ab..2007d6dc4 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 @@ | |||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| 22 | * The following code is derivative from Linux Android kernel vfp | 22 | * The following code is derivative from Linux Android kernel vfp |
| 23 | * floating point support. | 23 | * floating point support. |
| 24 | * | 24 | * |
| 25 | * Copyright (C) 2004 ARM Limited. | 25 | * Copyright (C) 2004 ARM Limited. |
| 26 | * Written by Deep Blue Solutions Limited. | 26 | * Written by Deep Blue Solutions Limited. |
| 27 | * | 27 | * |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index f70c84c3d..e53c2e606 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -549,7 +549,7 @@ std::string GetScheduledEventsSummary() { | |||
| 549 | const char* name = event_types[event->type].name; | 549 | const char* name = event_types[event->type].name; |
| 550 | if (!name) | 550 | if (!name) |
| 551 | name = "[unknown]"; | 551 | name = "[unknown]"; |
| 552 | text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time, | 552 | text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time, |
| 553 | (u32)(event->userdata >> 32), (u32)(event->userdata)); | 553 | (u32)(event->userdata >> 32), (u32)(event->userdata)); |
| 554 | event = event->next; | 554 | event = event->next; |
| 555 | } | 555 | } |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 01519608d..64f5b06d9 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -87,7 +87,7 @@ void UnregisterAllEvents(); | |||
| 87 | /// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, | 87 | /// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, |
| 88 | /// when we implement state saves. | 88 | /// when we implement state saves. |
| 89 | /** | 89 | /** |
| 90 | * Schedules an event to run after the specified number of cycles, | 90 | * Schedules an event to run after the specified number of cycles, |
| 91 | * with an optional parameter to be passed to the callback handler. | 91 | * with an optional parameter to be passed to the callback handler. |
| 92 | * This must be run ONLY from within the cpu thread. | 92 | * This must be run ONLY from within the cpu thread. |
| 93 | * @param cycles_into_future The number of cycles after which this event will be fired | 93 | * @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 38d498d0e..975aafb35 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) | |||
| 30 | std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { | 30 | std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { |
| 31 | if (shared) | 31 | if (shared) |
| 32 | return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID.c_str()); | 32 | return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID.c_str()); |
| 33 | 33 | ||
| 34 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), | 34 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), |
| 35 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); | 35 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); |
| 36 | } | 36 | } |
| 37 | 37 | ||
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h index c77c04e44..ef0b27bde 100644 --- a/src/core/file_sys/archive_extsavedata.h +++ b/src/core/file_sys/archive_extsavedata.h | |||
| @@ -35,14 +35,14 @@ public: | |||
| 35 | private: | 35 | private: |
| 36 | /** | 36 | /** |
| 37 | * This holds the full directory path for this archive, it is only set after a successful call | 37 | * This holds the full directory path for this archive, it is only set after a successful call |
| 38 | * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>. | 38 | * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>. |
| 39 | * See GetExtSaveDataPath for the code that extracts this data from an archive path. | 39 | * See GetExtSaveDataPath for the code that extracts this data from an archive path. |
| 40 | */ | 40 | */ |
| 41 | std::string mount_point; | 41 | std::string mount_point; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | /** | 44 | /** |
| 45 | * Constructs a path to the concrete ExtData archive in the host filesystem based on the | 45 | * Constructs a path to the concrete ExtData archive in the host filesystem based on the |
| 46 | * input Path and base mount point. | 46 | * input Path and base mount point. |
| 47 | * @param mount_point The base mount point of the ExtSaveData archives. | 47 | * @param mount_point The base mount point of the ExtSaveData archives. |
| 48 | * @param path The path that identifies the requested concrete ExtSaveData archive. | 48 | * @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 8dff51966..a92309377 100644 --- a/src/core/file_sys/archive_savedata.cpp +++ b/src/core/file_sys/archive_savedata.cpp | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | namespace FileSys { | 21 | namespace FileSys { |
| 22 | 22 | ||
| 23 | static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { | 23 | static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { |
| 24 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), | 24 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), |
| 25 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); | 25 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); |
| 26 | } | 26 | } |
| 27 | 27 | ||
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h index 201ec0db9..1b8249c74 100644 --- a/src/core/hle/kernel/resource_limit.h +++ b/src/core/hle/kernel/resource_limit.h | |||
| @@ -81,13 +81,13 @@ public: | |||
| 81 | s32 max_timers = 0; | 81 | s32 max_timers = 0; |
| 82 | s32 max_shared_mems = 0; | 82 | s32 max_shared_mems = 0; |
| 83 | s32 max_address_arbiters = 0; | 83 | s32 max_address_arbiters = 0; |
| 84 | 84 | ||
| 85 | /// Max CPU time that the processes in this category can utilize | 85 | /// Max CPU time that the processes in this category can utilize |
| 86 | s32 max_cpu_time = 0; | 86 | s32 max_cpu_time = 0; |
| 87 | 87 | ||
| 88 | // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that | 88 | // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that |
| 89 | // APPLICATION resource limits should not be affected by the objects created by service modules. | 89 | // APPLICATION resource limits should not be affected by the objects created by service modules. |
| 90 | // Currently we have no way of distinguishing if a Create was called by the running application, | 90 | // Currently we have no way of distinguishing if a Create was called by the running application, |
| 91 | // or by a service module. Approach this once we have separated the service modules into their own processes | 91 | // or by a service module. Approach this once we have separated the service modules into their own processes |
| 92 | 92 | ||
| 93 | /// Current memory that the processes in this category are using | 93 | /// 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 dbb4c9b7f..96d61ed3a 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp | |||
| @@ -42,7 +42,7 @@ void Semaphore::Acquire() { | |||
| 42 | 42 | ||
| 43 | ResultVal<s32> Semaphore::Release(s32 release_count) { | 43 | ResultVal<s32> Semaphore::Release(s32 release_count) { |
| 44 | if (max_count - available_count < release_count) | 44 | if (max_count - available_count < release_count) |
| 45 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, | 45 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, |
| 46 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 46 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| 47 | 47 | ||
| 48 | s32 previous_count = available_count; | 48 | s32 previous_count = available_count; |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 690d33b55..22c795ad4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -100,7 +100,7 @@ void Thread::Stop() { | |||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | status = THREADSTATUS_DEAD; | 102 | status = THREADSTATUS_DEAD; |
| 103 | 103 | ||
| 104 | WakeupAllWaitingThreads(); | 104 | WakeupAllWaitingThreads(); |
| 105 | 105 | ||
| 106 | // Clean up any dangling references in objects that this thread was waiting for | 106 | // Clean up any dangling references in objects that this thread was waiting for |
| @@ -169,7 +169,7 @@ static void PriorityBoostStarvedThreads() { | |||
| 169 | } | 169 | } |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | /** | 172 | /** |
| 173 | * Switches the CPU's active thread context to that of the specified thread | 173 | * Switches the CPU's active thread context to that of the specified thread |
| 174 | * @param new_thread The thread to switch to | 174 | * @param new_thread The thread to switch to |
| 175 | */ | 175 | */ |
| @@ -353,7 +353,7 @@ void Thread::ResumeFromWait() { | |||
| 353 | GetObjectId()); | 353 | GetObjectId()); |
| 354 | return; | 354 | return; |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | ready_queue.push_back(current_priority, this); | 357 | ready_queue.push_back(current_priority, this); |
| 358 | status = THREADSTATUS_READY; | 358 | status = THREADSTATUS_READY; |
| 359 | } | 359 | } |
| @@ -504,7 +504,7 @@ void Reschedule() { | |||
| 504 | } else if (next) { | 504 | } else if (next) { |
| 505 | LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); | 505 | LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | SwitchContext(next); | 508 | SwitchContext(next); |
| 509 | } | 509 | } |
| 510 | 510 | ||
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 389928178..2c65419c3 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -94,7 +94,7 @@ public: | |||
| 94 | * @return The thread's ID | 94 | * @return The thread's ID |
| 95 | */ | 95 | */ |
| 96 | u32 GetThreadId() const { return thread_id; } | 96 | u32 GetThreadId() const { return thread_id; } |
| 97 | 97 | ||
| 98 | /** | 98 | /** |
| 99 | * Release an acquired wait object | 99 | * Release an acquired wait object |
| 100 | * @param wait_object WaitObject to release | 100 | * @param wait_object WaitObject to release |
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 25d066bf1..8aa4110a6 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) { | |||
| 88 | if (timer->interval_delay != 0) { | 88 | if (timer->interval_delay != 0) { |
| 89 | // Reschedule the timer with the interval delay | 89 | // Reschedule the timer with the interval delay |
| 90 | u64 interval_microseconds = timer->interval_delay / 1000; | 90 | u64 interval_microseconds = timer->interval_delay / 1000; |
| 91 | CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, | 91 | CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, |
| 92 | timer_callback_event_type, timer_handle); | 92 | timer_callback_event_type, timer_handle); |
| 93 | } | 93 | } |
| 94 | } | 94 | } |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp new file mode 100644 index 000000000..b2dd21542 --- /dev/null +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -0,0 +1,245 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | |||
| 7 | #include "core/hle/kernel/vm_manager.h" | ||
| 8 | #include "core/memory_setup.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { | ||
| 13 | ASSERT(base + size == next.base); | ||
| 14 | if (permissions != next.permissions || | ||
| 15 | meminfo_state != next.meminfo_state || | ||
| 16 | type != next.type) { | ||
| 17 | return false; | ||
| 18 | } | ||
| 19 | if (type == VMAType::AllocatedMemoryBlock && | ||
| 20 | (backing_block != next.backing_block || offset + size != next.offset)) { | ||
| 21 | return false; | ||
| 22 | } | ||
| 23 | if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { | ||
| 24 | return false; | ||
| 25 | } | ||
| 26 | if (type == VMAType::MMIO && paddr + size != next.paddr) { | ||
| 27 | return false; | ||
| 28 | } | ||
| 29 | return true; | ||
| 30 | } | ||
| 31 | |||
| 32 | VMManager::VMManager() { | ||
| 33 | Reset(); | ||
| 34 | } | ||
| 35 | |||
| 36 | void VMManager::Reset() { | ||
| 37 | vma_map.clear(); | ||
| 38 | |||
| 39 | // Initialize the map with a single free region covering the entire managed space. | ||
| 40 | VirtualMemoryArea initial_vma; | ||
| 41 | initial_vma.size = MAX_ADDRESS; | ||
| 42 | vma_map.emplace(initial_vma.base, initial_vma); | ||
| 43 | |||
| 44 | UpdatePageTableForVMA(initial_vma); | ||
| 45 | } | ||
| 46 | |||
| 47 | VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { | ||
| 48 | return std::prev(vma_map.upper_bound(target)); | ||
| 49 | } | ||
| 50 | |||
| 51 | ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | ||
| 52 | std::shared_ptr<std::vector<u8>> block, u32 offset, u32 size, MemoryState state) { | ||
| 53 | ASSERT(block != nullptr); | ||
| 54 | ASSERT(offset + size <= block->size()); | ||
| 55 | |||
| 56 | // This is the appropriately sized VMA that will turn into our allocation. | ||
| 57 | CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); | ||
| 58 | VirtualMemoryArea& final_vma = vma_handle->second; | ||
| 59 | ASSERT(final_vma.size == size); | ||
| 60 | |||
| 61 | final_vma.type = VMAType::AllocatedMemoryBlock; | ||
| 62 | final_vma.permissions = VMAPermission::ReadWrite; | ||
| 63 | final_vma.meminfo_state = state; | ||
| 64 | final_vma.backing_block = block; | ||
| 65 | final_vma.offset = offset; | ||
| 66 | UpdatePageTableForVMA(final_vma); | ||
| 67 | |||
| 68 | return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); | ||
| 69 | } | ||
| 70 | |||
| 71 | ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { | ||
| 72 | ASSERT(memory != nullptr); | ||
| 73 | |||
| 74 | // This is the appropriately sized VMA that will turn into our allocation. | ||
| 75 | CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); | ||
| 76 | VirtualMemoryArea& final_vma = vma_handle->second; | ||
| 77 | ASSERT(final_vma.size == size); | ||
| 78 | |||
| 79 | final_vma.type = VMAType::BackingMemory; | ||
| 80 | final_vma.permissions = VMAPermission::ReadWrite; | ||
| 81 | final_vma.meminfo_state = state; | ||
| 82 | final_vma.backing_memory = memory; | ||
| 83 | UpdatePageTableForVMA(final_vma); | ||
| 84 | |||
| 85 | return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); | ||
| 86 | } | ||
| 87 | |||
| 88 | ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state) { | ||
| 89 | // This is the appropriately sized VMA that will turn into our allocation. | ||
| 90 | CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); | ||
| 91 | VirtualMemoryArea& final_vma = vma_handle->second; | ||
| 92 | ASSERT(final_vma.size == size); | ||
| 93 | |||
| 94 | final_vma.type = VMAType::MMIO; | ||
| 95 | final_vma.permissions = VMAPermission::ReadWrite; | ||
| 96 | final_vma.meminfo_state = state; | ||
| 97 | final_vma.paddr = paddr; | ||
| 98 | UpdatePageTableForVMA(final_vma); | ||
| 99 | |||
| 100 | return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); | ||
| 101 | } | ||
| 102 | |||
| 103 | void VMManager::Unmap(VMAHandle vma_handle) { | ||
| 104 | VMAIter iter = StripIterConstness(vma_handle); | ||
| 105 | |||
| 106 | VirtualMemoryArea& vma = iter->second; | ||
| 107 | vma.type = VMAType::Free; | ||
| 108 | vma.permissions = VMAPermission::None; | ||
| 109 | vma.meminfo_state = MemoryState::Free; | ||
| 110 | |||
| 111 | vma.backing_block = nullptr; | ||
| 112 | vma.offset = 0; | ||
| 113 | vma.backing_memory = nullptr; | ||
| 114 | vma.paddr = 0; | ||
| 115 | |||
| 116 | UpdatePageTableForVMA(vma); | ||
| 117 | |||
| 118 | MergeAdjacent(iter); | ||
| 119 | } | ||
| 120 | |||
| 121 | void VMManager::Reprotect(VMAHandle vma_handle, VMAPermission new_perms) { | ||
| 122 | VMAIter iter = StripIterConstness(vma_handle); | ||
| 123 | |||
| 124 | VirtualMemoryArea& vma = iter->second; | ||
| 125 | vma.permissions = new_perms; | ||
| 126 | UpdatePageTableForVMA(vma); | ||
| 127 | |||
| 128 | MergeAdjacent(iter); | ||
| 129 | } | ||
| 130 | |||
| 131 | VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { | ||
| 132 | // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given | ||
| 133 | // non-const access to its container. | ||
| 134 | return vma_map.erase(iter, iter); // Erases an empty range of elements | ||
| 135 | } | ||
| 136 | |||
| 137 | ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) { | ||
| 138 | ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: %8X", size); | ||
| 139 | ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: %08X", base); | ||
| 140 | |||
| 141 | VMAIter vma_handle = StripIterConstness(FindVMA(base)); | ||
| 142 | if (vma_handle == vma_map.end()) { | ||
| 143 | // Target address is outside the range managed by the kernel | ||
| 144 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, | ||
| 145 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E01BF5 | ||
| 146 | } | ||
| 147 | |||
| 148 | VirtualMemoryArea& vma = vma_handle->second; | ||
| 149 | if (vma.type != VMAType::Free) { | ||
| 150 | // Region is already allocated | ||
| 151 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, | ||
| 152 | ErrorSummary::InvalidState, ErrorLevel::Usage); // 0xE0A01BF5 | ||
| 153 | } | ||
| 154 | |||
| 155 | u32 start_in_vma = base - vma.base; | ||
| 156 | u32 end_in_vma = start_in_vma + size; | ||
| 157 | |||
| 158 | if (end_in_vma > vma.size) { | ||
| 159 | // Requested allocation doesn't fit inside VMA | ||
| 160 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, | ||
| 161 | ErrorSummary::InvalidState, ErrorLevel::Usage); // 0xE0A01BF5 | ||
| 162 | } | ||
| 163 | |||
| 164 | if (end_in_vma != vma.size) { | ||
| 165 | // Split VMA at the end of the allocated region | ||
| 166 | SplitVMA(vma_handle, end_in_vma); | ||
| 167 | } | ||
| 168 | if (start_in_vma != 0) { | ||
| 169 | // Split VMA at the start of the allocated region | ||
| 170 | vma_handle = SplitVMA(vma_handle, start_in_vma); | ||
| 171 | } | ||
| 172 | |||
| 173 | return MakeResult<VMAIter>(vma_handle); | ||
| 174 | } | ||
| 175 | |||
| 176 | VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u32 offset_in_vma) { | ||
| 177 | VirtualMemoryArea& old_vma = vma_handle->second; | ||
| 178 | VirtualMemoryArea new_vma = old_vma; // Make a copy of the VMA | ||
| 179 | |||
| 180 | // For now, don't allow no-op VMA splits (trying to split at a boundary) because it's probably | ||
| 181 | // a bug. This restriction might be removed later. | ||
| 182 | ASSERT(offset_in_vma < old_vma.size); | ||
| 183 | ASSERT(offset_in_vma > 0); | ||
| 184 | |||
| 185 | old_vma.size = offset_in_vma; | ||
| 186 | new_vma.base += offset_in_vma; | ||
| 187 | new_vma.size -= offset_in_vma; | ||
| 188 | |||
| 189 | switch (new_vma.type) { | ||
| 190 | case VMAType::Free: | ||
| 191 | break; | ||
| 192 | case VMAType::AllocatedMemoryBlock: | ||
| 193 | new_vma.offset += offset_in_vma; | ||
| 194 | break; | ||
| 195 | case VMAType::BackingMemory: | ||
| 196 | new_vma.backing_memory += offset_in_vma; | ||
| 197 | break; | ||
| 198 | case VMAType::MMIO: | ||
| 199 | new_vma.paddr += offset_in_vma; | ||
| 200 | break; | ||
| 201 | } | ||
| 202 | |||
| 203 | ASSERT(old_vma.CanBeMergedWith(new_vma)); | ||
| 204 | |||
| 205 | return vma_map.emplace_hint(std::next(vma_handle), new_vma.base, new_vma); | ||
| 206 | } | ||
| 207 | |||
| 208 | VMManager::VMAIter VMManager::MergeAdjacent(VMAIter iter) { | ||
| 209 | VMAIter next_vma = std::next(iter); | ||
| 210 | if (next_vma != vma_map.end() && iter->second.CanBeMergedWith(next_vma->second)) { | ||
| 211 | iter->second.size += next_vma->second.size; | ||
| 212 | vma_map.erase(next_vma); | ||
| 213 | } | ||
| 214 | |||
| 215 | if (iter != vma_map.begin()) { | ||
| 216 | VMAIter prev_vma = std::prev(iter); | ||
| 217 | if (prev_vma->second.CanBeMergedWith(iter->second)) { | ||
| 218 | prev_vma->second.size += iter->second.size; | ||
| 219 | vma_map.erase(iter); | ||
| 220 | iter = prev_vma; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | return iter; | ||
| 225 | } | ||
| 226 | |||
| 227 | void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | ||
| 228 | switch (vma.type) { | ||
| 229 | case VMAType::Free: | ||
| 230 | Memory::UnmapRegion(vma.base, vma.size); | ||
| 231 | break; | ||
| 232 | case VMAType::AllocatedMemoryBlock: | ||
| 233 | Memory::MapMemoryRegion(vma.base, vma.size, vma.backing_block->data() + vma.offset); | ||
| 234 | break; | ||
| 235 | case VMAType::BackingMemory: | ||
| 236 | Memory::MapMemoryRegion(vma.base, vma.size, vma.backing_memory); | ||
| 237 | break; | ||
| 238 | case VMAType::MMIO: | ||
| 239 | // TODO(yuriks): Add support for MMIO handlers. | ||
| 240 | Memory::MapIoRegion(vma.base, vma.size); | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | } | ||
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h new file mode 100644 index 000000000..22b724603 --- /dev/null +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -0,0 +1,200 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <map> | ||
| 8 | #include <memory> | ||
| 9 | #include <string> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "common/common_types.h" | ||
| 13 | |||
| 14 | #include "core/hle/result.h" | ||
| 15 | |||
| 16 | namespace Kernel { | ||
| 17 | |||
| 18 | enum class VMAType : u8 { | ||
| 19 | /// VMA represents an unmapped region of the address space. | ||
| 20 | Free, | ||
| 21 | /// VMA is backed by a ref-counted allocate memory block. | ||
| 22 | AllocatedMemoryBlock, | ||
| 23 | /// VMA is backed by a raw, unmanaged pointer. | ||
| 24 | BackingMemory, | ||
| 25 | /// VMA is mapped to MMIO registers at a fixed PAddr. | ||
| 26 | MMIO, | ||
| 27 | // TODO(yuriks): Implement MemoryAlias to support MAP/UNMAP | ||
| 28 | }; | ||
| 29 | |||
| 30 | /// Permissions for mapped memory blocks | ||
| 31 | enum class VMAPermission : u8 { | ||
| 32 | None = 0, | ||
| 33 | Read = 1, | ||
| 34 | Write = 2, | ||
| 35 | Execute = 4, | ||
| 36 | |||
| 37 | ReadWrite = Read | Write, | ||
| 38 | ReadExecute = Read | Execute, | ||
| 39 | WriteExecute = Write | Execute, | ||
| 40 | ReadWriteExecute = Read | Write | Execute, | ||
| 41 | }; | ||
| 42 | |||
| 43 | /// Set of values returned in MemoryInfo.state by svcQueryMemory. | ||
| 44 | enum class MemoryState : u8 { | ||
| 45 | Free = 0, | ||
| 46 | Reserved = 1, | ||
| 47 | IO = 2, | ||
| 48 | Static = 3, | ||
| 49 | Code = 4, | ||
| 50 | Private = 5, | ||
| 51 | Shared = 6, | ||
| 52 | Continuous = 7, | ||
| 53 | Aliased = 8, | ||
| 54 | Alias = 9, | ||
| 55 | AliasCode = 10, | ||
| 56 | Locked = 11, | ||
| 57 | }; | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Represents a VMA in an address space. A VMA is a contiguous region of virtual addressing space | ||
| 61 | * with homogeneous attributes across its extents. In this particular implementation each VMA is | ||
| 62 | * also backed by a single host memory allocation. | ||
| 63 | */ | ||
| 64 | struct VirtualMemoryArea { | ||
| 65 | /// Virtual base address of the region. | ||
| 66 | VAddr base = 0; | ||
| 67 | /// Size of the region. | ||
| 68 | u32 size = 0; | ||
| 69 | |||
| 70 | VMAType type = VMAType::Free; | ||
| 71 | VMAPermission permissions = VMAPermission::None; | ||
| 72 | /// Tag returned by svcQueryMemory. Not otherwise used. | ||
| 73 | MemoryState meminfo_state = MemoryState::Free; | ||
| 74 | |||
| 75 | // Settings for type = AllocatedMemoryBlock | ||
| 76 | /// Memory block backing this VMA. | ||
| 77 | std::shared_ptr<std::vector<u8>> backing_block = nullptr; | ||
| 78 | /// Offset into the backing_memory the mapping starts from. | ||
| 79 | u32 offset = 0; | ||
| 80 | |||
| 81 | // Settings for type = BackingMemory | ||
| 82 | /// Pointer backing this VMA. It will not be destroyed or freed when the VMA is removed. | ||
| 83 | u8* backing_memory = nullptr; | ||
| 84 | |||
| 85 | // Settings for type = MMIO | ||
| 86 | /// Physical address of the register area this VMA maps to. | ||
| 87 | PAddr paddr = 0; | ||
| 88 | |||
| 89 | /// Tests if this area can be merged to the right with `next`. | ||
| 90 | bool CanBeMergedWith(const VirtualMemoryArea& next) const; | ||
| 91 | }; | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Manages a process' virtual addressing space. This class maintains a list of allocated and free | ||
| 95 | * regions in the address space, along with their attributes, and allows kernel clients to | ||
| 96 | * manipulate it, adjusting the page table to match. | ||
| 97 | * | ||
| 98 | * This is similar in idea and purpose to the VM manager present in operating system kernels, with | ||
| 99 | * the main difference being that it doesn't have to support swapping or memory mapping of files. | ||
| 100 | * The implementation is also simplified by not having to allocate page frames. See these articles | ||
| 101 | * about the Linux kernel for an explantion of the concept and implementation: | ||
| 102 | * - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/ | ||
| 103 | * - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/ | ||
| 104 | */ | ||
| 105 | class VMManager { | ||
| 106 | // TODO(yuriks): Make page tables switchable to support multiple VMManagers | ||
| 107 | public: | ||
| 108 | /** | ||
| 109 | * The maximum amount of address space managed by the kernel. Addresses above this are never used. | ||
| 110 | * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. | ||
| 111 | */ | ||
| 112 | static const u32 MAX_ADDRESS = 0x40000000; | ||
| 113 | |||
| 114 | /** | ||
| 115 | * A map covering the entirety of the managed address space, keyed by the `base` field of each | ||
| 116 | * VMA. It must always be modified by splitting or merging VMAs, so that the invariant | ||
| 117 | * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be | ||
| 118 | * merged when possible so that no two similar and adjacent regions exist that have not been | ||
| 119 | * merged. | ||
| 120 | */ | ||
| 121 | std::map<VAddr, VirtualMemoryArea> vma_map; | ||
| 122 | using VMAHandle = decltype(vma_map)::const_iterator; | ||
| 123 | |||
| 124 | VMManager(); | ||
| 125 | |||
| 126 | /// Clears the address space map, re-initializing with a single free area. | ||
| 127 | void Reset(); | ||
| 128 | |||
| 129 | /// Finds the VMA in which the given address is included in, or `vma_map.end()`. | ||
| 130 | VMAHandle FindVMA(VAddr target) const; | ||
| 131 | |||
| 132 | // TODO(yuriks): Should these functions actually return the handle? | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Maps part of a ref-counted block of memory at a given address. | ||
| 136 | * | ||
| 137 | * @param target The guest address to start the mapping at. | ||
| 138 | * @param block The block to be mapped. | ||
| 139 | * @param offset Offset into `block` to map from. | ||
| 140 | * @param size Size of the mapping. | ||
| 141 | * @param state MemoryState tag to attach to the VMA. | ||
| 142 | */ | ||
| 143 | ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, | ||
| 144 | u32 offset, u32 size, MemoryState state); | ||
| 145 | |||
| 146 | /** | ||
| 147 | * Maps an unmanaged host memory pointer at a given address. | ||
| 148 | * | ||
| 149 | * @param target The guest address to start the mapping at. | ||
| 150 | * @param memory The memory to be mapped. | ||
| 151 | * @param size Size of the mapping. | ||
| 152 | * @param state MemoryState tag to attach to the VMA. | ||
| 153 | */ | ||
| 154 | ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u32 size, MemoryState state); | ||
| 155 | |||
| 156 | /** | ||
| 157 | * Maps a memory-mapped IO region at a given address. | ||
| 158 | * | ||
| 159 | * @param target The guest address to start the mapping at. | ||
| 160 | * @param paddr The physical address where the registers are present. | ||
| 161 | * @param size Size of the mapping. | ||
| 162 | * @param state MemoryState tag to attach to the VMA. | ||
| 163 | */ | ||
| 164 | ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state); | ||
| 165 | |||
| 166 | /// Unmaps the given VMA. | ||
| 167 | void Unmap(VMAHandle vma); | ||
| 168 | |||
| 169 | /// Changes the permissions of the given VMA. | ||
| 170 | void Reprotect(VMAHandle vma, VMAPermission new_perms); | ||
| 171 | |||
| 172 | private: | ||
| 173 | using VMAIter = decltype(vma_map)::iterator; | ||
| 174 | |||
| 175 | /// Converts a VMAHandle to a mutable VMAIter. | ||
| 176 | VMAIter StripIterConstness(const VMAHandle& iter); | ||
| 177 | |||
| 178 | /** | ||
| 179 | * Carves a VMA of a specific size at the specified address by splitting Free VMAs while doing | ||
| 180 | * the appropriate error checking. | ||
| 181 | */ | ||
| 182 | ResultVal<VMAIter> CarveVMA(VAddr base, u32 size); | ||
| 183 | |||
| 184 | /** | ||
| 185 | * Splits a VMA in two, at the specified offset. | ||
| 186 | * @returns the right side of the split, with the original iterator becoming the left side. | ||
| 187 | */ | ||
| 188 | VMAIter SplitVMA(VMAIter vma, u32 offset_in_vma); | ||
| 189 | |||
| 190 | /** | ||
| 191 | * Checks for and merges the specified VMA with adjacent ones if possible. | ||
| 192 | * @returns the merged VMA or the original if no merging was possible. | ||
| 193 | */ | ||
| 194 | VMAIter MergeAdjacent(VMAIter vma); | ||
| 195 | |||
| 196 | /// Updates the pages corresponding to this VMA so they match the VMA's attributes. | ||
| 197 | void UpdatePageTableForVMA(const VirtualMemoryArea& vma); | ||
| 198 | }; | ||
| 199 | |||
| 200 | } | ||
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 3fd4cfb08..5d14f393d 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) { | |||
| 151 | u32 handle = cmd_buff[6]; | 151 | u32 handle = cmd_buff[6]; |
| 152 | u32 size = cmd_buff[7]; | 152 | u32 size = cmd_buff[7]; |
| 153 | u32 in_param_buffer_ptr = cmd_buff[8]; | 153 | u32 in_param_buffer_ptr = cmd_buff[8]; |
| 154 | 154 | ||
| 155 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 155 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 156 | 156 | ||
| 157 | LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," | 157 | 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() { | |||
| 283 | AddService(new APT_A_Interface); | 283 | AddService(new APT_A_Interface); |
| 284 | AddService(new APT_S_Interface); | 284 | AddService(new APT_S_Interface); |
| 285 | AddService(new APT_U_Interface); | 285 | AddService(new APT_U_Interface); |
| 286 | 286 | ||
| 287 | // Load the shared system font (if available). | 287 | // Load the shared system font (if available). |
| 288 | // The expected format is a decrypted, uncompressed BCFNT file with the 0x80 byte header | 288 | // The expected format is a decrypted, uncompressed BCFNT file with the 0x80 byte header |
| 289 | // generated by the APT:U service. The best way to get is by dumping it from RAM. We've provided | 289 | // 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 e7fa39325..a03e1712a 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); | |||
| 63 | * 4 : Handle to shared font memory | 63 | * 4 : Handle to shared font memory |
| 64 | */ | 64 | */ |
| 65 | void GetSharedFont(Service::Interface* self); | 65 | void GetSharedFont(Service::Interface* self); |
| 66 | 66 | ||
| 67 | /** | 67 | /** |
| 68 | * APT::NotifyToWait service function | 68 | * APT::NotifyToWait service function |
| 69 | * Inputs: | 69 | * Inputs: |
| @@ -88,7 +88,7 @@ void Enable(Service::Interface* self); | |||
| 88 | * 4 : Home Menu AppId | 88 | * 4 : Home Menu AppId |
| 89 | * 5 : AppID of currently active app | 89 | * 5 : AppID of currently active app |
| 90 | */ | 90 | */ |
| 91 | void GetAppletManInfo(Service::Interface* self); | 91 | void GetAppletManInfo(Service::Interface* self); |
| 92 | 92 | ||
| 93 | /** | 93 | /** |
| 94 | * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. | 94 | * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. |
| @@ -100,14 +100,14 @@ void GetAppletManInfo(Service::Interface* self); | |||
| 100 | * Outputs: | 100 | * Outputs: |
| 101 | * 0 : Return header | 101 | * 0 : Return header |
| 102 | * 1 : Result of function, 0 on success, otherwise error code | 102 | * 1 : Result of function, 0 on success, otherwise error code |
| 103 | * 2 : Output, 0 = not registered, 1 = registered. | 103 | * 2 : Output, 0 = not registered, 1 = registered. |
| 104 | */ | 104 | */ |
| 105 | void IsRegistered(Service::Interface* self); | 105 | void IsRegistered(Service::Interface* self); |
| 106 | 106 | ||
| 107 | void InquireNotification(Service::Interface* self); | 107 | void InquireNotification(Service::Interface* self); |
| 108 | 108 | ||
| 109 | /** | 109 | /** |
| 110 | * APT::SendParameter service function. This sets the parameter data state. | 110 | * APT::SendParameter service function. This sets the parameter data state. |
| 111 | * Inputs: | 111 | * Inputs: |
| 112 | * 1 : Source AppID | 112 | * 1 : Source AppID |
| 113 | * 2 : Destination AppID | 113 | * 2 : Destination AppID |
diff --git a/src/core/hle/service/boss_p.h b/src/core/hle/service/boss_p.h index 71f1e7464..6fb51d57d 100644 --- a/src/core/hle/service/boss_p.h +++ b/src/core/hle/service/boss_p.h | |||
| @@ -14,7 +14,7 @@ namespace BOSS_P { | |||
| 14 | class Interface : public Service::Interface { | 14 | class Interface : public Service::Interface { |
| 15 | public: | 15 | public: |
| 16 | Interface(); | 16 | Interface(); |
| 17 | 17 | ||
| 18 | std::string GetPortName() const override { | 18 | std::string GetPortName() const override { |
| 19 | return "boss:P"; | 19 | return "boss:P"; |
| 20 | } | 20 | } |
diff --git a/src/core/hle/service/boss_u.h b/src/core/hle/service/boss_u.h index 2668f2dfd..89e77fe47 100644 --- a/src/core/hle/service/boss_u.h +++ b/src/core/hle/service/boss_u.h | |||
| @@ -14,7 +14,7 @@ namespace BOSS_U { | |||
| 14 | class Interface : public Service::Interface { | 14 | class Interface : public Service::Interface { |
| 15 | public: | 15 | public: |
| 16 | Interface(); | 16 | Interface(); |
| 17 | 17 | ||
| 18 | std::string GetPortName() const override { | 18 | std::string GetPortName() const override { |
| 19 | return "boss:U"; | 19 | return "boss:U"; |
| 20 | } | 20 | } |
diff --git a/src/core/hle/service/cam_u.cpp b/src/core/hle/service/cam_u.cpp index fcfd87715..ecda0dbdf 100644 --- a/src/core/hle/service/cam_u.cpp +++ b/src/core/hle/service/cam_u.cpp | |||
| @@ -19,5 +19,5 @@ namespace CAM_U { | |||
| 19 | Interface::Interface() { | 19 | Interface::Interface() { |
| 20 | //Register(FunctionTable); | 20 | //Register(FunctionTable); |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | } // namespace | 23 | } // namespace |
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index d42682883..62ad90fdc 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp | |||
| @@ -315,11 +315,11 @@ void Init() { | |||
| 315 | AddService(new CFG_I_Interface); | 315 | AddService(new CFG_I_Interface); |
| 316 | AddService(new CFG_S_Interface); | 316 | AddService(new CFG_S_Interface); |
| 317 | AddService(new CFG_U_Interface); | 317 | AddService(new CFG_U_Interface); |
| 318 | 318 | ||
| 319 | // Open the SystemSaveData archive 0x00010017 | 319 | // Open the SystemSaveData archive 0x00010017 |
| 320 | FileSys::Path archive_path(cfg_system_savedata_id); | 320 | FileSys::Path archive_path(cfg_system_savedata_id); |
| 321 | auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | 321 | auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); |
| 322 | 322 | ||
| 323 | // If the archive didn't exist, create the files inside | 323 | // If the archive didn't exist, create the files inside |
| 324 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { | 324 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { |
| 325 | // Format the archive to create the directories | 325 | // Format the archive to create the directories |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 6d4a9c7c9..7cab68024 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 | |||
| 254 | 254 | ||
| 255 | CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); | 255 | CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); |
| 256 | 256 | ||
| 257 | // This should never even happen in the first place with 64-bit handles, | 257 | // This should never even happen in the first place with 64-bit handles, |
| 258 | while (handle_map.count(next_handle) != 0) { | 258 | while (handle_map.count(next_handle) != 0) { |
| 259 | ++next_handle; | 259 | ++next_handle; |
| 260 | } | 260 | } |
| @@ -488,7 +488,7 @@ void ArchiveInit() { | |||
| 488 | RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); | 488 | RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); |
| 489 | else | 489 | else |
| 490 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | 490 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); |
| 491 | 491 | ||
| 492 | // Create the SaveData archive | 492 | // Create the SaveData archive |
| 493 | auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); | 493 | auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); |
| 494 | RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); | 494 | RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); |
| @@ -503,7 +503,7 @@ void ArchiveInit() { | |||
| 503 | if (sharedextsavedata_factory->Initialize()) | 503 | if (sharedextsavedata_factory->Initialize()) |
| 504 | RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); | 504 | RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); |
| 505 | else | 505 | else |
| 506 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", | 506 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", |
| 507 | sharedextsavedata_factory->GetMountPoint().c_str()); | 507 | sharedextsavedata_factory->GetMountPoint().c_str()); |
| 508 | 508 | ||
| 509 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive | 509 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive |
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index b25c8941d..32db773bb 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) { | |||
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | /** | 436 | /** |
| 437 | * FS_User::FormatSaveData service function, | 437 | * FS_User::FormatSaveData service function, |
| 438 | * formats the SaveData specified by the input path. | 438 | * formats the SaveData specified by the input path. |
| 439 | * Inputs: | 439 | * Inputs: |
| 440 | * 0 : 0x084C0242 | 440 | * 0 : 0x084C0242 |
| @@ -520,7 +520,7 @@ static void CreateExtSaveData(Service::Interface* self) { | |||
| 520 | LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " | 520 | LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " |
| 521 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " | 521 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " |
| 522 | "cmd_buff[9]=%08X cmd_buff[10]=%08X cmd_buff[11]=%08X", save_high, save_low, | 522 | "cmd_buff[9]=%08X cmd_buff[10]=%08X cmd_buff[11]=%08X", save_high, save_low, |
| 523 | cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9], | 523 | cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9], |
| 524 | cmd_buff[10], cmd_buff[11]); | 524 | cmd_buff[10], cmd_buff[11]); |
| 525 | 525 | ||
| 526 | cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low).raw; | 526 | cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low).raw; |
| @@ -544,7 +544,7 @@ static void DeleteExtSaveData(Service::Interface* self) { | |||
| 544 | u32 save_high = cmd_buff[3]; | 544 | u32 save_high = cmd_buff[3]; |
| 545 | u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is | 545 | u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is |
| 546 | 546 | ||
| 547 | LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X", | 547 | LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X", |
| 548 | save_low, save_high, cmd_buff[1] & 0xFF, unknown); | 548 | save_low, save_high, cmd_buff[1] & 0xFF, unknown); |
| 549 | 549 | ||
| 550 | cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw; | 550 | 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 4af168bfc..4b0b4229d 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) { | |||
| 167 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 167 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 168 | u32 reg_addr = cmd_buff[1]; | 168 | u32 reg_addr = cmd_buff[1]; |
| 169 | u32 size = cmd_buff[2]; | 169 | u32 size = cmd_buff[2]; |
| 170 | 170 | ||
| 171 | u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); | 171 | u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); |
| 172 | u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); | 172 | u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); |
| 173 | 173 | ||
| @@ -208,21 +208,21 @@ static void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
| 208 | PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); | 208 | PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); |
| 209 | PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); | 209 | PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); |
| 210 | if (info.active_fb == 0) { | 210 | if (info.active_fb == 0) { |
| 211 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 4, | 211 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 4, |
| 212 | &phys_address_left); | 212 | &phys_address_left); |
| 213 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 4, | 213 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 4, |
| 214 | &phys_address_right); | 214 | &phys_address_right); |
| 215 | } else { | 215 | } else { |
| 216 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 4, | 216 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 4, |
| 217 | &phys_address_left); | 217 | &phys_address_left); |
| 218 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 4, | 218 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 4, |
| 219 | &phys_address_right); | 219 | &phys_address_right); |
| 220 | } | 220 | } |
| 221 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 4, | 221 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 4, |
| 222 | &info.stride); | 222 | &info.stride); |
| 223 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 4, | 223 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 4, |
| 224 | &info.format); | 224 | &info.format); |
| 225 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4, | 225 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4, |
| 226 | &info.shown_fb); | 226 | &info.shown_fb); |
| 227 | } | 227 | } |
| 228 | 228 | ||
| @@ -374,7 +374,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 374 | { | 374 | { |
| 375 | auto& params = command.set_command_list_last; | 375 | auto& params = command.set_command_list_last; |
| 376 | 376 | ||
| 377 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)), | 377 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)), |
| 378 | Memory::VirtualToPhysicalAddress(params.address) >> 3); | 378 | Memory::VirtualToPhysicalAddress(params.address) >> 3); |
| 379 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), params.size); | 379 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), params.size); |
| 380 | 380 | ||
| @@ -470,7 +470,7 @@ static void SetLcdForceBlack(Service::Interface* self) { | |||
| 470 | 470 | ||
| 471 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD | 471 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD |
| 472 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD | 472 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD |
| 473 | 473 | ||
| 474 | cmd_buff[1] = RESULT_SUCCESS.raw; | 474 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 475 | } | 475 | } |
| 476 | 476 | ||
| @@ -516,8 +516,8 @@ static void TriggerCmdReqQueue(Service::Interface* self) { | |||
| 516 | */ | 516 | */ |
| 517 | static void ImportDisplayCaptureInfo(Service::Interface* self) { | 517 | static void ImportDisplayCaptureInfo(Service::Interface* self) { |
| 518 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 518 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 519 | 519 | ||
| 520 | // TODO(Subv): We're always returning the framebuffer structures for thread_id = 0, | 520 | // TODO(Subv): We're always returning the framebuffer structures for thread_id = 0, |
| 521 | // because we only support a single running application at a time. | 521 | // because we only support a single running application at a time. |
| 522 | // This should always return the framebuffer data that is currently displayed on the screen. | 522 | // This should always return the framebuffer data that is currently displayed on the screen. |
| 523 | 523 | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index feac53816..c7c1bb5ab 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -106,7 +106,7 @@ void Update() { | |||
| 106 | mem->touch.index_reset_ticks_previous = mem->touch.index_reset_ticks; | 106 | mem->touch.index_reset_ticks_previous = mem->touch.index_reset_ticks; |
| 107 | mem->touch.index_reset_ticks = (s64)CoreTiming::GetTicks(); | 107 | mem->touch.index_reset_ticks = (s64)CoreTiming::GetTicks(); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | // Signal both handles when there's an update to Pad or touch | 110 | // Signal both handles when there's an update to Pad or touch |
| 111 | event_pad_or_touch_1->Signal(); | 111 | event_pad_or_touch_1->Signal(); |
| 112 | event_pad_or_touch_2->Signal(); | 112 | 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 02db12efd..532931ae0 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[] = { | |||
| 25 | HID_SPVR_Interface::HID_SPVR_Interface() { | 25 | HID_SPVR_Interface::HID_SPVR_Interface() { |
| 26 | Register(FunctionTable); | 26 | Register(FunctionTable); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | } // namespace HID | 29 | } // namespace HID |
| 30 | } // namespace Service | 30 | } // namespace Service |
diff --git a/src/core/hle/service/hid/hid_user.h b/src/core/hle/service/hid/hid_user.h index 0eeec2c25..baf7fed79 100644 --- a/src/core/hle/service/hid/hid_user.h +++ b/src/core/hle/service/hid/hid_user.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | namespace Service { | 12 | namespace Service { |
| 13 | namespace HID { | 13 | namespace HID { |
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * HID service interface. | 16 | * HID service interface. |
| 17 | */ | 17 | */ |
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index 493e6a11f..b690003cb 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 { | |||
| 20 | CompletelyFull = 5, | 20 | CompletelyFull = 5, |
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | /** | 23 | /** |
| 24 | * Represents the gamecoin file structure in the SharedExtData archive | 24 | * Represents the gamecoin file structure in the SharedExtData archive |
| 25 | * More information in 3dbrew (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) | 25 | * More information in 3dbrew (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) |
| 26 | */ | 26 | */ |
| 27 | struct GameCoin { | 27 | struct GameCoin { |
| 28 | u32 magic; ///< Magic number: 0x4F00 | 28 | u32 magic; ///< Magic number: 0x4F00 |
| 29 | u16 total_coins; ///< Total Play Coins | 29 | u16 total_coins; ///< Total Play Coins |
| 30 | u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. | 30 | u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. |
| 31 | u32 step_count; ///< Total step count at the time a new Play Coin was obtained. | 31 | u32 step_count; ///< Total step count at the time a new Play Coin was obtained. |
| 32 | u32 last_step_count; ///< Step count for the day the last Play Coin was obtained | 32 | u32 last_step_count; ///< Step count for the day the last Play Coin was obtained |
| 33 | u16 year; | 33 | u16 year; |
| 34 | u8 month; | 34 | u8 month; |
diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp index 48e68a3d8..7bb990193 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[] = { | |||
| 18 | PTM_Play_Interface::PTM_Play_Interface() { | 18 | PTM_Play_Interface::PTM_Play_Interface() { |
| 19 | Register(FunctionTable); | 19 | Register(FunctionTable); |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | } // namespace PTM | 22 | } // namespace PTM |
| 23 | } // namespace Service \ No newline at end of file | 23 | } // 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 64185c62e..dc667500c 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -52,7 +52,7 @@ std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_por | |||
| 52 | std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; | 52 | std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; |
| 53 | 53 | ||
| 54 | /** | 54 | /** |
| 55 | * Creates a function string for logging, complete with the name (or header code, depending | 55 | * Creates a function string for logging, complete with the name (or header code, depending |
| 56 | * on what's passed in) the port name, and all the cmd_buff arguments. | 56 | * on what's passed in) the port name, and all the cmd_buff arguments. |
| 57 | */ | 57 | */ |
| 58 | static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) { | 58 | static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) { |
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index 39b8d65fd..1e0f5df9b 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) { | |||
| 139 | auto found = error_map.find(error); | 139 | auto found = error_map.find(error); |
| 140 | if (found != error_map.end()) | 140 | if (found != error_map.end()) |
| 141 | return -found->second; | 141 | return -found->second; |
| 142 | 142 | ||
| 143 | return error; | 143 | return error; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| @@ -346,7 +346,7 @@ static void Bind(Service::Interface* self) { | |||
| 346 | sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr); | 346 | sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr); |
| 347 | 347 | ||
| 348 | int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len)); | 348 | int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len)); |
| 349 | 349 | ||
| 350 | int result = 0; | 350 | int result = 0; |
| 351 | if (res != 0) | 351 | if (res != 0) |
| 352 | result = TranslateError(GET_ERRNO); | 352 | result = TranslateError(GET_ERRNO); |
| @@ -360,14 +360,14 @@ static void Fcntl(Service::Interface* self) { | |||
| 360 | u32 socket_handle = cmd_buffer[1]; | 360 | u32 socket_handle = cmd_buffer[1]; |
| 361 | u32 ctr_cmd = cmd_buffer[2]; | 361 | u32 ctr_cmd = cmd_buffer[2]; |
| 362 | u32 ctr_arg = cmd_buffer[3]; | 362 | u32 ctr_arg = cmd_buffer[3]; |
| 363 | 363 | ||
| 364 | int result = 0; | 364 | int result = 0; |
| 365 | u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX) | 365 | u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX) |
| 366 | SCOPE_EXIT({ | 366 | SCOPE_EXIT({ |
| 367 | cmd_buffer[1] = result; | 367 | cmd_buffer[1] = result; |
| 368 | cmd_buffer[2] = posix_ret; | 368 | cmd_buffer[2] = posix_ret; |
| 369 | }); | 369 | }); |
| 370 | 370 | ||
| 371 | if (ctr_cmd == 3) { // F_GETFL | 371 | if (ctr_cmd == 3) { // F_GETFL |
| 372 | #if EMU_PLATFORM == PLATFORM_WINDOWS | 372 | #if EMU_PLATFORM == PLATFORM_WINDOWS |
| 373 | posix_ret = 0; | 373 | posix_ret = 0; |
| @@ -404,11 +404,11 @@ static void Fcntl(Service::Interface* self) { | |||
| 404 | posix_ret = -1; | 404 | posix_ret = -1; |
| 405 | return; | 405 | return; |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | flags &= ~O_NONBLOCK; | 408 | flags &= ~O_NONBLOCK; |
| 409 | if (ctr_arg & 4) // O_NONBLOCK | 409 | if (ctr_arg & 4) // O_NONBLOCK |
| 410 | flags |= O_NONBLOCK; | 410 | flags |= O_NONBLOCK; |
| 411 | 411 | ||
| 412 | int ret = ::fcntl(socket_handle, F_SETFL, flags); | 412 | int ret = ::fcntl(socket_handle, F_SETFL, flags); |
| 413 | if (ret == SOCKET_ERROR_VALUE) { | 413 | if (ret == SOCKET_ERROR_VALUE) { |
| 414 | result = TranslateError(GET_ERRNO); | 414 | result = TranslateError(GET_ERRNO); |
| @@ -439,8 +439,8 @@ static void Listen(Service::Interface* self) { | |||
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | static void Accept(Service::Interface* self) { | 441 | static void Accept(Service::Interface* self) { |
| 442 | // TODO(Subv): Calling this function on a blocking socket will block the emu thread, | 442 | // TODO(Subv): Calling this function on a blocking socket will block the emu thread, |
| 443 | // preventing graceful shutdown when closing the emulator, this can be fixed by always | 443 | // preventing graceful shutdown when closing the emulator, this can be fixed by always |
| 444 | // performing nonblocking operations and spinlock until the data is available | 444 | // performing nonblocking operations and spinlock until the data is available |
| 445 | u32* cmd_buffer = Kernel::GetCommandBuffer(); | 445 | u32* cmd_buffer = Kernel::GetCommandBuffer(); |
| 446 | u32 socket_handle = cmd_buffer[1]; | 446 | u32 socket_handle = cmd_buffer[1]; |
| @@ -448,7 +448,7 @@ static void Accept(Service::Interface* self) { | |||
| 448 | sockaddr addr; | 448 | sockaddr addr; |
| 449 | socklen_t addr_len = sizeof(addr); | 449 | socklen_t addr_len = sizeof(addr); |
| 450 | u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); | 450 | u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); |
| 451 | 451 | ||
| 452 | if ((s32)ret != SOCKET_ERROR_VALUE) | 452 | if ((s32)ret != SOCKET_ERROR_VALUE) |
| 453 | open_sockets[ret] = { ret, true }; | 453 | open_sockets[ret] = { ret, true }; |
| 454 | 454 | ||
| @@ -525,8 +525,8 @@ static void SendTo(Service::Interface* self) { | |||
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | static void RecvFrom(Service::Interface* self) { | 527 | static void RecvFrom(Service::Interface* self) { |
| 528 | // TODO(Subv): Calling this function on a blocking socket will block the emu thread, | 528 | // TODO(Subv): Calling this function on a blocking socket will block the emu thread, |
| 529 | // preventing graceful shutdown when closing the emulator, this can be fixed by always | 529 | // preventing graceful shutdown when closing the emulator, this can be fixed by always |
| 530 | // performing nonblocking operations and spinlock until the data is available | 530 | // performing nonblocking operations and spinlock until the data is available |
| 531 | u32* cmd_buffer = Kernel::GetCommandBuffer(); | 531 | u32* cmd_buffer = Kernel::GetCommandBuffer(); |
| 532 | u32 socket_handle = cmd_buffer[1]; | 532 | u32 socket_handle = cmd_buffer[1]; |
| @@ -568,7 +568,7 @@ static void Poll(Service::Interface* self) { | |||
| 568 | pollfd* platform_pollfd = new pollfd[nfds]; | 568 | pollfd* platform_pollfd = new pollfd[nfds]; |
| 569 | for (unsigned current_fds = 0; current_fds < nfds; ++current_fds) | 569 | for (unsigned current_fds = 0; current_fds < nfds; ++current_fds) |
| 570 | platform_pollfd[current_fds] = CTRPollFD::ToPlatform(input_fds[current_fds]); | 570 | platform_pollfd[current_fds] = CTRPollFD::ToPlatform(input_fds[current_fds]); |
| 571 | 571 | ||
| 572 | int ret = ::poll(platform_pollfd, nfds, timeout); | 572 | int ret = ::poll(platform_pollfd, nfds, timeout); |
| 573 | 573 | ||
| 574 | // Now update the output pollfd structure | 574 | // Now update the output pollfd structure |
| @@ -630,7 +630,7 @@ static void GetPeerName(Service::Interface* self) { | |||
| 630 | socklen_t len = cmd_buffer[2]; | 630 | socklen_t len = cmd_buffer[2]; |
| 631 | 631 | ||
| 632 | CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | 632 | CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); |
| 633 | 633 | ||
| 634 | sockaddr dest_addr; | 634 | sockaddr dest_addr; |
| 635 | socklen_t dest_addr_len = sizeof(dest_addr); | 635 | socklen_t dest_addr_len = sizeof(dest_addr); |
| 636 | int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); | 636 | int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); |
| @@ -651,8 +651,8 @@ static void GetPeerName(Service::Interface* self) { | |||
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | static void Connect(Service::Interface* self) { | 653 | static void Connect(Service::Interface* self) { |
| 654 | // TODO(Subv): Calling this function on a blocking socket will block the emu thread, | 654 | // TODO(Subv): Calling this function on a blocking socket will block the emu thread, |
| 655 | // preventing graceful shutdown when closing the emulator, this can be fixed by always | 655 | // preventing graceful shutdown when closing the emulator, this can be fixed by always |
| 656 | // performing nonblocking operations and spinlock until the data is available | 656 | // performing nonblocking operations and spinlock until the data is available |
| 657 | u32* cmd_buffer = Kernel::GetCommandBuffer(); | 657 | u32* cmd_buffer = Kernel::GetCommandBuffer(); |
| 658 | u32 socket_handle = cmd_buffer[1]; | 658 | u32 socket_handle = cmd_buffer[1]; |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index ca3ff3328..d1555c753 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -228,7 +228,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 228 | // Actually wait the current thread on each object if we decided to wait... | 228 | // Actually wait the current thread on each object if we decided to wait... |
| 229 | std::vector<SharedPtr<Kernel::WaitObject>> wait_objects; | 229 | std::vector<SharedPtr<Kernel::WaitObject>> wait_objects; |
| 230 | wait_objects.reserve(handle_count); | 230 | wait_objects.reserve(handle_count); |
| 231 | 231 | ||
| 232 | for (int i = 0; i < handle_count; ++i) { | 232 | for (int i = 0; i < handle_count; ++i) { |
| 233 | auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); | 233 | auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); |
| 234 | object->AddWaitingThread(Kernel::GetCurrentThread()); | 234 | object->AddWaitingThread(Kernel::GetCurrentThread()); |
| @@ -475,7 +475,7 @@ static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { | |||
| 475 | return ERR_INVALID_HANDLE; | 475 | return ERR_INVALID_HANDLE; |
| 476 | 476 | ||
| 477 | const SharedPtr<Kernel::Process> process = thread->owner_process; | 477 | const SharedPtr<Kernel::Process> process = thread->owner_process; |
| 478 | 478 | ||
| 479 | ASSERT_MSG(process != nullptr, "Invalid parent process for thread=0x%08X", thread_handle); | 479 | ASSERT_MSG(process != nullptr, "Invalid parent process for thread=0x%08X", thread_handle); |
| 480 | 480 | ||
| 481 | *process_id = process->process_id; | 481 | *process_id = process->process_id; |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 99cfdaafc..789d3dda4 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -140,7 +140,7 @@ inline void Write(u32 addr, const T data) { | |||
| 140 | // Raw copies do not perform color conversion nor tiled->linear / linear->tiled conversions | 140 | // Raw copies do not perform color conversion nor tiled->linear / linear->tiled conversions |
| 141 | // TODO(Subv): Verify if raw copies perform scaling | 141 | // TODO(Subv): Verify if raw copies perform scaling |
| 142 | memcpy(dst_pointer, src_pointer, output_size); | 142 | memcpy(dst_pointer, src_pointer, output_size); |
| 143 | 143 | ||
| 144 | 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", | 144 | 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", |
| 145 | output_size, | 145 | output_size, |
| 146 | config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(), | 146 | config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(), |
| @@ -159,14 +159,14 @@ inline void Write(u32 addr, const T data) { | |||
| 159 | for (u32 x = 0; x < output_width; ++x) { | 159 | for (u32 x = 0; x < output_width; ++x) { |
| 160 | Math::Vec4<u8> src_color = { 0, 0, 0, 0 }; | 160 | Math::Vec4<u8> src_color = { 0, 0, 0, 0 }; |
| 161 | 161 | ||
| 162 | // Calculate the [x,y] position of the input image | 162 | // Calculate the [x,y] position of the input image |
| 163 | // based on the current output position and the scale | 163 | // based on the current output position and the scale |
| 164 | u32 input_x = x * horizontal_scale; | 164 | u32 input_x = x * horizontal_scale; |
| 165 | u32 input_y = y * vertical_scale; | 165 | u32 input_y = y * vertical_scale; |
| 166 | 166 | ||
| 167 | if (config.flip_vertically) { | 167 | if (config.flip_vertically) { |
| 168 | // Flip the y value of the output data, | 168 | // Flip the y value of the output data, |
| 169 | // we do this after calculating the [x,y] position of the input image | 169 | // we do this after calculating the [x,y] position of the input image |
| 170 | // to account for the scaling options. | 170 | // to account for the scaling options. |
| 171 | y = output_height - y - 1; | 171 | y = output_height - y - 1; |
| 172 | } | 172 | } |
| @@ -302,7 +302,7 @@ static void VBlankCallback(u64 userdata, int cycles_late) { | |||
| 302 | // - If frameskip == 0 (disabled), always swap buffers | 302 | // - If frameskip == 0 (disabled), always swap buffers |
| 303 | // - If frameskip == 1, swap buffers every other frame (starting from the first frame) | 303 | // - If frameskip == 1, swap buffers every other frame (starting from the first frame) |
| 304 | // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) | 304 | // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) |
| 305 | if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) || | 305 | if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) || |
| 306 | Settings::values.frame_skip == 0) { | 306 | Settings::values.frame_skip == 0) { |
| 307 | VideoCore::g_renderer->SwapBuffers(); | 307 | VideoCore::g_renderer->SwapBuffers(); |
| 308 | } | 308 | } |
diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp index 09134c95b..963c8d981 100644 --- a/src/core/hw/lcd.cpp +++ b/src/core/hw/lcd.cpp | |||
| @@ -66,5 +66,5 @@ void Init() { | |||
| 66 | void Shutdown() { | 66 | void Shutdown() { |
| 67 | LOG_DEBUG(HW_LCD, "shutdown OK"); | 67 | LOG_DEBUG(HW_LCD, "shutdown OK"); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | } // namespace | 70 | } // namespace |
diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h index fb14c3b21..8631eb201 100644 --- a/src/core/hw/lcd.h +++ b/src/core/hw/lcd.h | |||
| @@ -85,5 +85,5 @@ void Init(); | |||
| 85 | 85 | ||
| 86 | /// Shutdown hardware | 86 | /// Shutdown hardware |
| 87 | void Shutdown(); | 87 | void Shutdown(); |
| 88 | 88 | ||
| 89 | } // namespace | 89 | } // namespace |
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index ad5e929ce..14aeebebb 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp | |||
| @@ -234,7 +234,7 @@ ResultStatus AppLoader_THREEDSX::Load() { | |||
| 234 | Kernel::g_current_process = Kernel::Process::Create(filename, 0); | 234 | Kernel::g_current_process = Kernel::Process::Create(filename, 0); |
| 235 | Kernel::g_current_process->svc_access_mask.set(); | 235 | Kernel::g_current_process->svc_access_mask.set(); |
| 236 | Kernel::g_current_process->address_mappings = default_address_mappings; | 236 | Kernel::g_current_process->address_mappings = default_address_mappings; |
| 237 | 237 | ||
| 238 | // Attach the default resource limit (APPLICATION) to the process | 238 | // Attach the default resource limit (APPLICATION) to the process |
| 239 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 239 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 240 | 240 | ||
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp index 5ecec9566..bf814b945 100644 --- a/src/core/mem_map.cpp +++ b/src/core/mem_map.cpp | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | 9 | ||
| 10 | #include "core/hle/config_mem.h" | 10 | #include "core/hle/config_mem.h" |
| 11 | #include "core/hle/kernel/kernel.h" | ||
| 12 | #include "core/hle/kernel/shared_memory.h" | ||
| 13 | #include "core/hle/kernel/vm_manager.h" | ||
| 14 | #include "core/hle/result.h" | ||
| 11 | #include "core/hle/shared_page.h" | 15 | #include "core/hle/shared_page.h" |
| 12 | #include "core/mem_map.h" | 16 | #include "core/mem_map.h" |
| 13 | #include "core/memory.h" | 17 | #include "core/memory.h" |
| @@ -17,31 +21,23 @@ | |||
| 17 | 21 | ||
| 18 | namespace Memory { | 22 | namespace Memory { |
| 19 | 23 | ||
| 20 | u8* g_exefs_code; ///< ExeFS:/.code is loaded here | ||
| 21 | u8* g_heap; ///< Application heap (main memory) | ||
| 22 | u8* g_shared_mem; ///< Shared memory | ||
| 23 | u8* g_heap_linear; ///< Linear heap | ||
| 24 | u8* g_vram; ///< Video memory (VRAM) pointer | ||
| 25 | u8* g_dsp_mem; ///< DSP memory | ||
| 26 | u8* g_tls_mem; ///< TLS memory | ||
| 27 | |||
| 28 | namespace { | 24 | namespace { |
| 29 | 25 | ||
| 30 | struct MemoryArea { | 26 | struct MemoryArea { |
| 31 | u8** ptr; | ||
| 32 | u32 base; | 27 | u32 base; |
| 33 | u32 size; | 28 | u32 size; |
| 29 | const char* name; | ||
| 34 | }; | 30 | }; |
| 35 | 31 | ||
| 36 | // We don't declare the IO regions in here since its handled by other means. | 32 | // We don't declare the IO regions in here since its handled by other means. |
| 37 | static MemoryArea memory_areas[] = { | 33 | static MemoryArea memory_areas[] = { |
| 38 | {&g_exefs_code, PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE}, | 34 | {PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE, "Process Image"}, // ExeFS:/.code is loaded here |
| 39 | {&g_heap, HEAP_VADDR, HEAP_SIZE }, | 35 | {HEAP_VADDR, HEAP_SIZE, "Heap"}, // Application heap (main memory) |
| 40 | {&g_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE }, | 36 | {SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory |
| 41 | {&g_heap_linear, LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE }, | 37 | {LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE, "Linear Heap"}, // Linear heap (main memory) |
| 42 | {&g_vram, VRAM_VADDR, VRAM_SIZE }, | 38 | {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) |
| 43 | {&g_dsp_mem, DSP_RAM_VADDR, DSP_RAM_SIZE }, | 39 | {DSP_RAM_VADDR, DSP_RAM_SIZE, "DSP RAM"}, // DSP memory |
| 44 | {&g_tls_mem, TLS_AREA_VADDR, TLS_AREA_SIZE }, | 40 | {TLS_AREA_VADDR, TLS_AREA_SIZE, "TLS Area"}, // TLS memory |
| 45 | }; | 41 | }; |
| 46 | 42 | ||
| 47 | /// Represents a block of memory mapped by ControlMemory/MapMemoryBlock | 43 | /// Represents a block of memory mapped by ControlMemory/MapMemoryBlock |
| @@ -135,27 +131,34 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) { | |||
| 135 | return addr | 0x80000000; | 131 | return addr | 0x80000000; |
| 136 | } | 132 | } |
| 137 | 133 | ||
| 134 | // TODO(yuriks): Move this into Process | ||
| 135 | static Kernel::VMManager address_space; | ||
| 136 | |||
| 138 | void Init() { | 137 | void Init() { |
| 138 | using namespace Kernel; | ||
| 139 | |||
| 139 | InitMemoryMap(); | 140 | InitMemoryMap(); |
| 140 | 141 | ||
| 141 | for (MemoryArea& area : memory_areas) { | 142 | for (MemoryArea& area : memory_areas) { |
| 142 | *area.ptr = new u8[area.size]; | 143 | auto block = std::make_shared<std::vector<u8>>(area.size); |
| 143 | MapMemoryRegion(area.base, area.size, *area.ptr); | 144 | address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap(); |
| 144 | } | 145 | } |
| 145 | MapMemoryRegion(CONFIG_MEMORY_VADDR, CONFIG_MEMORY_SIZE, (u8*)&ConfigMem::config_mem); | ||
| 146 | MapMemoryRegion(SHARED_PAGE_VADDR, SHARED_PAGE_SIZE, (u8*)&SharedPage::shared_page); | ||
| 147 | 146 | ||
| 148 | LOG_DEBUG(HW_Memory, "initialized OK, RAM at %p", g_heap); | 147 | auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR, |
| 148 | (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom(); | ||
| 149 | address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); | ||
| 150 | |||
| 151 | auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, | ||
| 152 | (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); | ||
| 153 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); | ||
| 154 | |||
| 155 | LOG_DEBUG(HW_Memory, "initialized OK"); | ||
| 149 | } | 156 | } |
| 150 | 157 | ||
| 151 | void Shutdown() { | 158 | void Shutdown() { |
| 152 | heap_map.clear(); | 159 | heap_map.clear(); |
| 153 | heap_linear_map.clear(); | 160 | heap_linear_map.clear(); |
| 154 | 161 | address_space.Reset(); | |
| 155 | for (MemoryArea& area : memory_areas) { | ||
| 156 | delete[] *area.ptr; | ||
| 157 | *area.ptr = nullptr; | ||
| 158 | } | ||
| 159 | 162 | ||
| 160 | LOG_DEBUG(HW_Memory, "shutdown OK"); | 163 | LOG_DEBUG(HW_Memory, "shutdown OK"); |
| 161 | } | 164 | } |
diff --git a/src/core/mem_map.h b/src/core/mem_map.h index 945815cd6..ba50914a8 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h | |||
| @@ -8,14 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | namespace Memory { | 9 | namespace Memory { |
| 10 | 10 | ||
| 11 | extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here | ||
| 12 | extern u8* g_heap; ///< Application heap (main memory) | ||
| 13 | extern u8* g_shared_mem; ///< Shared memory | ||
| 14 | extern u8* g_heap_linear; ///< Linear heap (main memory) | ||
| 15 | extern u8* g_vram; ///< Video memory (VRAM) | ||
| 16 | extern u8* g_dsp_mem; ///< DSP memory | ||
| 17 | extern u8* g_tls_mem; ///< TLS memory | ||
| 18 | |||
| 19 | void Init(); | 11 | void Init(); |
| 20 | void Shutdown(); | 12 | void Shutdown(); |
| 21 | 13 | ||
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 5d8069acd..28844a915 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -14,12 +14,10 @@ | |||
| 14 | #include "core/hw/hw.h" | 14 | #include "core/hw/hw.h" |
| 15 | #include "core/mem_map.h" | 15 | #include "core/mem_map.h" |
| 16 | #include "core/memory.h" | 16 | #include "core/memory.h" |
| 17 | #include "core/memory_setup.h" | ||
| 17 | 18 | ||
| 18 | namespace Memory { | 19 | namespace Memory { |
| 19 | 20 | ||
| 20 | const u32 PAGE_MASK = PAGE_SIZE - 1; | ||
| 21 | const int PAGE_BITS = 12; | ||
| 22 | |||
| 23 | enum class PageType { | 21 | enum class PageType { |
| 24 | /// Page is unmapped and should cause an access error. | 22 | /// Page is unmapped and should cause an access error. |
| 25 | Unmapped, | 23 | Unmapped, |
| @@ -64,7 +62,7 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) { | |||
| 64 | while (base != end) { | 62 | while (base != end) { |
| 65 | ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); | 63 | ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); |
| 66 | 64 | ||
| 67 | if (current_page_table->attributes[base] != PageType::Unmapped) { | 65 | if (current_page_table->attributes[base] != PageType::Unmapped && type != PageType::Unmapped) { |
| 68 | LOG_ERROR(HW_Memory, "overlapping memory ranges at %08X", base * PAGE_SIZE); | 66 | LOG_ERROR(HW_Memory, "overlapping memory ranges at %08X", base * PAGE_SIZE); |
| 69 | } | 67 | } |
| 70 | current_page_table->attributes[base] = type; | 68 | current_page_table->attributes[base] = type; |
| @@ -92,6 +90,12 @@ void MapIoRegion(VAddr base, u32 size) { | |||
| 92 | MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special); | 90 | MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special); |
| 93 | } | 91 | } |
| 94 | 92 | ||
| 93 | void UnmapRegion(VAddr base, u32 size) { | ||
| 94 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size); | ||
| 95 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base); | ||
| 96 | MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Unmapped); | ||
| 97 | } | ||
| 98 | |||
| 95 | template <typename T> | 99 | template <typename T> |
| 96 | T Read(const VAddr vaddr) { | 100 | T Read(const VAddr vaddr) { |
| 97 | const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | 101 | const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; |
diff --git a/src/core/memory.h b/src/core/memory.h index 2d225801b..0b8ff9ec4 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -97,7 +97,7 @@ enum : VAddr { | |||
| 97 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, | 97 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, |
| 98 | 98 | ||
| 99 | // TODO(yuriks): The size of this area is dynamic, the kernel grows | 99 | // TODO(yuriks): The size of this area is dynamic, the kernel grows |
| 100 | // it as more and more threads are created. For now we'll just use a | 100 | // it as more and more threads are created. For now we'll just use a |
| 101 | // hardcoded value. | 101 | // hardcoded value. |
| 102 | /// Area where TLS (Thread-Local Storage) buffers are allocated. | 102 | /// Area where TLS (Thread-Local Storage) buffers are allocated. |
| 103 | TLS_AREA_VADDR = 0x1FF82000, | 103 | TLS_AREA_VADDR = 0x1FF82000, |
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h index 46263495f..361bfc816 100644 --- a/src/core/memory_setup.h +++ b/src/core/memory_setup.h | |||
| @@ -6,8 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/memory.h" | ||
| 10 | |||
| 9 | namespace Memory { | 11 | namespace Memory { |
| 10 | 12 | ||
| 13 | const u32 PAGE_MASK = PAGE_SIZE - 1; | ||
| 14 | const int PAGE_BITS = 12; | ||
| 15 | |||
| 11 | void InitMemoryMap(); | 16 | void InitMemoryMap(); |
| 12 | 17 | ||
| 13 | /** | 18 | /** |
| @@ -26,4 +31,6 @@ void MapMemoryRegion(VAddr base, u32 size, u8* target); | |||
| 26 | */ | 31 | */ |
| 27 | void MapIoRegion(VAddr base, u32 size); | 32 | void MapIoRegion(VAddr base, u32 size); |
| 28 | 33 | ||
| 34 | void UnmapRegion(VAddr base, u32 size); | ||
| 35 | |||
| 29 | } | 36 | } |
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 100d8c7c1..b46fadd9f 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) { | |||
| 56 | // Trigger IRQ | 56 | // Trigger IRQ |
| 57 | case PICA_REG_INDEX(trigger_irq): | 57 | case PICA_REG_INDEX(trigger_irq): |
| 58 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); | 58 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); |
| 59 | return; | 59 | break; |
| 60 | |||
| 61 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[0], 0x23c): | ||
| 62 | case PICA_REG_INDEX_WORKAROUND(command_buffer.trigger[1], 0x23d): | ||
| 63 | { | ||
| 64 | unsigned index = id - PICA_REG_INDEX(command_buffer.trigger[0]); | ||
| 65 | u32* head_ptr = (u32*)Memory::GetPhysicalPointer(regs.command_buffer.GetPhysicalAddress(index)); | ||
| 66 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; | ||
| 67 | g_state.cmd_list.length = regs.command_buffer.GetSize(index) / sizeof(u32); | ||
| 68 | break; | ||
| 69 | } | ||
| 60 | 70 | ||
| 61 | // It seems like these trigger vertex rendering | 71 | // It seems like these trigger vertex rendering |
| 62 | case PICA_REG_INDEX(trigger_draw): | 72 | case PICA_REG_INDEX(trigger_draw): |
| @@ -136,7 +146,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 136 | input.attr[i][0].ToFloat32(), input.attr[i][1].ToFloat32(), | 146 | input.attr[i][0].ToFloat32(), input.attr[i][1].ToFloat32(), |
| 137 | input.attr[i][2].ToFloat32(), input.attr[i][3].ToFloat32()); | 147 | input.attr[i][2].ToFloat32(), input.attr[i][3].ToFloat32()); |
| 138 | } | 148 | } |
| 139 | 149 | ||
| 140 | // Load per-vertex data from the loader arrays | 150 | // Load per-vertex data from the loader arrays |
| 141 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { | 151 | for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { |
| 142 | const u8* srcdata = Memory::GetPhysicalPointer(vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i]); | 152 | 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) { | |||
| 193 | const Pica::VertexShader::OutputVertex& v2) { | 203 | const Pica::VertexShader::OutputVertex& v2) { |
| 194 | VideoCore::g_renderer->hw_rasterizer->AddTriangle(v0, v1, v2); | 204 | VideoCore::g_renderer->hw_rasterizer->AddTriangle(v0, v1, v2); |
| 195 | }; | 205 | }; |
| 196 | 206 | ||
| 197 | primitive_assembler.SubmitVertex(output, AddHWTriangle); | 207 | primitive_assembler.SubmitVertex(output, AddHWTriangle); |
| 198 | } else { | 208 | } else { |
| 199 | // Send to triangle clipper | 209 | // Send to triangle clipper |
| @@ -282,7 +292,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||
| 282 | } | 292 | } |
| 283 | break; | 293 | break; |
| 284 | } | 294 | } |
| 285 | 295 | ||
| 286 | // Load default vertex input attributes | 296 | // Load default vertex input attributes |
| 287 | case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[0], 0x233): | 297 | case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[0], 0x233): |
| 288 | case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[1], 0x234): | 298 | 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) { | |||
| 306 | } | 316 | } |
| 307 | 317 | ||
| 308 | Math::Vec4<float24>& attribute = g_state.vs.default_attributes[setup.index]; | 318 | Math::Vec4<float24>& attribute = g_state.vs.default_attributes[setup.index]; |
| 309 | 319 | ||
| 310 | // NOTE: The destination component order indeed is "backwards" | 320 | // NOTE: The destination component order indeed is "backwards" |
| 311 | attribute.w = float24::FromRawFloat24(default_attr_write_buffer[0] >> 8); | 321 | attribute.w = float24::FromRawFloat24(default_attr_write_buffer[0] >> 8); |
| 312 | attribute.z = float24::FromRawFloat24(((default_attr_write_buffer[0] & 0xFF) << 16) | ((default_attr_write_buffer[1] >> 16) & 0xFFFF)); | 322 | 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) { | |||
| 363 | g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast<void*>(&id)); | 373 | g_debug_context->OnEvent(DebugContext::Event::CommandProcessed, reinterpret_cast<void*>(&id)); |
| 364 | } | 374 | } |
| 365 | 375 | ||
| 366 | static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) { | ||
| 367 | const CommandHeader& header = *(const CommandHeader*)(&first_command_word[1]); | ||
| 368 | |||
| 369 | u32* read_pointer = (u32*)first_command_word; | ||
| 370 | |||
| 371 | const u32 write_mask = ((header.parameter_mask & 0x1) ? (0xFFu << 0) : 0u) | | ||
| 372 | ((header.parameter_mask & 0x2) ? (0xFFu << 8) : 0u) | | ||
| 373 | ((header.parameter_mask & 0x4) ? (0xFFu << 16) : 0u) | | ||
| 374 | ((header.parameter_mask & 0x8) ? (0xFFu << 24) : 0u); | ||
| 375 | |||
| 376 | WritePicaReg(header.cmd_id, *read_pointer, write_mask); | ||
| 377 | read_pointer += 2; | ||
| 378 | |||
| 379 | for (unsigned int i = 1; i < 1+header.extra_data_length; ++i) { | ||
| 380 | u32 cmd = header.cmd_id + ((header.group_commands) ? i : 0); | ||
| 381 | WritePicaReg(cmd, *read_pointer, write_mask); | ||
| 382 | ++read_pointer; | ||
| 383 | } | ||
| 384 | |||
| 385 | // align read pointer to 8 bytes | ||
| 386 | if ((first_command_word - read_pointer) % 2) | ||
| 387 | ++read_pointer; | ||
| 388 | |||
| 389 | return read_pointer - first_command_word; | ||
| 390 | } | ||
| 391 | |||
| 392 | void ProcessCommandList(const u32* list, u32 size) { | 376 | void ProcessCommandList(const u32* list, u32 size) { |
| 393 | u32* read_pointer = (u32*)list; | 377 | g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = list; |
| 394 | u32 list_length = size / sizeof(u32); | 378 | g_state.cmd_list.length = size / sizeof(u32); |
| 395 | 379 | ||
| 396 | while (read_pointer < list + list_length) { | 380 | while (g_state.cmd_list.current_ptr < g_state.cmd_list.head_ptr + g_state.cmd_list.length) { |
| 397 | read_pointer += ExecuteCommandBlock(read_pointer); | 381 | // Expand a 4-bit mask to 4-byte mask, e.g. 0b0101 -> 0x00FF00FF |
| 382 | static const u32 expand_bits_to_bytes[] = { | ||
| 383 | 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, | ||
| 384 | 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, | ||
| 385 | 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, | ||
| 386 | 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff | ||
| 387 | }; | ||
| 388 | |||
| 389 | // Align read pointer to 8 bytes | ||
| 390 | if ((g_state.cmd_list.head_ptr - g_state.cmd_list.current_ptr) % 2 != 0) | ||
| 391 | ++g_state.cmd_list.current_ptr; | ||
| 392 | |||
| 393 | u32 value = *g_state.cmd_list.current_ptr++; | ||
| 394 | const CommandHeader header = { *g_state.cmd_list.current_ptr++ }; | ||
| 395 | const u32 write_mask = expand_bits_to_bytes[header.parameter_mask]; | ||
| 396 | u32 cmd = header.cmd_id; | ||
| 397 | |||
| 398 | WritePicaReg(cmd, value, write_mask); | ||
| 399 | |||
| 400 | for (unsigned i = 0; i < header.extra_data_length; ++i) { | ||
| 401 | u32 cmd = header.cmd_id + (header.group_commands ? i + 1 : 0); | ||
| 402 | WritePicaReg(cmd, *g_state.cmd_list.current_ptr++, write_mask); | ||
| 403 | } | ||
| 398 | } | 404 | } |
| 399 | } | 405 | } |
| 400 | 406 | ||
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 7987b922c..b92cd1a7e 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp | |||
| @@ -319,7 +319,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture | |||
| 319 | // TODO(neobrain): Fix code design to unify vertical block offsets! | 319 | // TODO(neobrain): Fix code design to unify vertical block offsets! |
| 320 | source += coarse_y * info.stride; | 320 | source += coarse_y * info.stride; |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | // TODO: Assert that width/height are multiples of block dimensions | 323 | // TODO: Assert that width/height are multiples of block dimensions |
| 324 | 324 | ||
| 325 | switch (info.format) { | 325 | switch (info.format) { |
diff --git a/src/video_core/math.h b/src/video_core/math.h index f9a822658..4928c9bf2 100644 --- a/src/video_core/math.h +++ b/src/video_core/math.h | |||
| @@ -461,7 +461,7 @@ public: | |||
| 461 | // e.g. Vec2 uv() { return Vec2(x,y); } | 461 | // e.g. Vec2 uv() { return Vec2(x,y); } |
| 462 | 462 | ||
| 463 | // _DEFINE_SWIZZLER2 defines a single such function | 463 | // _DEFINE_SWIZZLER2 defines a single such function |
| 464 | // DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r) | 464 | // DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r) |
| 465 | // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and permutations (xy<->yx) | 465 | // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and permutations (xy<->yx) |
| 466 | #define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); } | 466 | #define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); } |
| 467 | #define DEFINE_SWIZZLER2_COMP1(a, a2) \ | 467 | #define DEFINE_SWIZZLER2_COMP1(a, a2) \ |
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index b67dce1a9..8ad47a928 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 17 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 18 | 18 | ||
| 19 | #include "math.h" | 19 | #include "math.h" |
| 20 | 20 | ||
| 21 | namespace Pica { | 21 | namespace Pica { |
| 22 | 22 | ||
| @@ -162,6 +162,25 @@ struct Regs { | |||
| 162 | ETC1A4 = 13, // compressed | 162 | ETC1A4 = 13, // compressed |
| 163 | }; | 163 | }; |
| 164 | 164 | ||
| 165 | enum class LogicOp : u32 { | ||
| 166 | Clear = 0, | ||
| 167 | And = 1, | ||
| 168 | AndReverse = 2, | ||
| 169 | Copy = 3, | ||
| 170 | Set = 4, | ||
| 171 | CopyInverted = 5, | ||
| 172 | NoOp = 6, | ||
| 173 | Invert = 7, | ||
| 174 | Nand = 8, | ||
| 175 | Or = 9, | ||
| 176 | Nor = 10, | ||
| 177 | Xor = 11, | ||
| 178 | Equiv = 12, | ||
| 179 | AndInverted = 13, | ||
| 180 | OrReverse = 14, | ||
| 181 | OrInverted = 15, | ||
| 182 | }; | ||
| 183 | |||
| 165 | static unsigned NibblesPerPixel(TextureFormat format) { | 184 | static unsigned NibblesPerPixel(TextureFormat format) { |
| 166 | switch (format) { | 185 | switch (format) { |
| 167 | case TextureFormat::RGBA8: | 186 | case TextureFormat::RGBA8: |
| @@ -221,6 +240,7 @@ struct Regs { | |||
| 221 | enum class Source : u32 { | 240 | enum class Source : u32 { |
| 222 | PrimaryColor = 0x0, | 241 | PrimaryColor = 0x0, |
| 223 | PrimaryFragmentColor = 0x1, | 242 | PrimaryFragmentColor = 0x1, |
| 243 | SecondaryFragmentColor = 0x2, | ||
| 224 | 244 | ||
| 225 | Texture0 = 0x3, | 245 | Texture0 = 0x3, |
| 226 | Texture1 = 0x4, | 246 | Texture1 = 0x4, |
| @@ -337,7 +357,7 @@ struct Regs { | |||
| 337 | return (stage_index < 4) && (update_mask_a & (1 << stage_index)); | 357 | return (stage_index < 4) && (update_mask_a & (1 << stage_index)); |
| 338 | } | 358 | } |
| 339 | } tev_combiner_buffer_input; | 359 | } tev_combiner_buffer_input; |
| 340 | 360 | ||
| 341 | INSERT_PADDING_WORDS(0xf); | 361 | INSERT_PADDING_WORDS(0xf); |
| 342 | TevStageConfig tev_stage4; | 362 | TevStageConfig tev_stage4; |
| 343 | INSERT_PADDING_WORDS(0x3); | 363 | INSERT_PADDING_WORDS(0x3); |
| @@ -413,12 +433,8 @@ struct Regs { | |||
| 413 | } alpha_blending; | 433 | } alpha_blending; |
| 414 | 434 | ||
| 415 | union { | 435 | union { |
| 416 | enum Op { | 436 | BitField<0, 4, LogicOp> logic_op; |
| 417 | Set = 4, | 437 | }; |
| 418 | }; | ||
| 419 | |||
| 420 | BitField<0, 4, Op> op; | ||
| 421 | } logic_op; | ||
| 422 | 438 | ||
| 423 | union { | 439 | union { |
| 424 | BitField< 0, 8, u32> r; | 440 | BitField< 0, 8, u32> r; |
| @@ -703,12 +719,38 @@ struct Regs { | |||
| 703 | struct { | 719 | struct { |
| 704 | // Index of the current default attribute | 720 | // Index of the current default attribute |
| 705 | u32 index; | 721 | u32 index; |
| 706 | 722 | ||
| 707 | // Writing to these registers sets the "current" default attribute. | 723 | // Writing to these registers sets the "current" default attribute. |
| 708 | u32 set_value[3]; | 724 | u32 set_value[3]; |
| 709 | } vs_default_attributes_setup; | 725 | } vs_default_attributes_setup; |
| 710 | 726 | ||
| 711 | INSERT_PADDING_WORDS(0x28); | 727 | INSERT_PADDING_WORDS(0x2); |
| 728 | |||
| 729 | struct { | ||
| 730 | // There are two channels that can be used to configure the next command buffer, which | ||
| 731 | // can be then executed by writing to the "trigger" registers. There are two reasons why a | ||
| 732 | // game might use this feature: | ||
| 733 | // 1) With this, an arbitrary number of additional command buffers may be executed in | ||
| 734 | // sequence without requiring any intervention of the CPU after the initial one is | ||
| 735 | // kicked off. | ||
| 736 | // 2) Games can configure these registers to provide a command list subroutine mechanism. | ||
| 737 | |||
| 738 | BitField< 0, 20, u32> size[2]; ///< Size (in bytes / 8) of each channel's command buffer | ||
| 739 | BitField< 0, 28, u32> addr[2]; ///< Physical address / 8 of each channel's command buffer | ||
| 740 | u32 trigger[2]; ///< Triggers execution of the channel's command buffer when written to | ||
| 741 | |||
| 742 | unsigned GetSize(unsigned index) const { | ||
| 743 | ASSERT(index < 2); | ||
| 744 | return 8 * size[index]; | ||
| 745 | } | ||
| 746 | |||
| 747 | PAddr GetPhysicalAddress(unsigned index) const { | ||
| 748 | ASSERT(index < 2); | ||
| 749 | return (PAddr)(8 * addr[index]); | ||
| 750 | } | ||
| 751 | } command_buffer; | ||
| 752 | |||
| 753 | INSERT_PADDING_WORDS(0x20); | ||
| 712 | 754 | ||
| 713 | enum class TriangleTopology : u32 { | 755 | enum class TriangleTopology : u32 { |
| 714 | List = 0, | 756 | List = 0, |
| @@ -861,6 +903,7 @@ struct Regs { | |||
| 861 | ADD_FIELD(trigger_draw); | 903 | ADD_FIELD(trigger_draw); |
| 862 | ADD_FIELD(trigger_draw_indexed); | 904 | ADD_FIELD(trigger_draw_indexed); |
| 863 | ADD_FIELD(vs_default_attributes_setup); | 905 | ADD_FIELD(vs_default_attributes_setup); |
| 906 | ADD_FIELD(command_buffer); | ||
| 864 | ADD_FIELD(triangle_topology); | 907 | ADD_FIELD(triangle_topology); |
| 865 | ADD_FIELD(vs_bool_uniforms); | 908 | ADD_FIELD(vs_bool_uniforms); |
| 866 | ADD_FIELD(vs_int_uniforms); | 909 | ADD_FIELD(vs_int_uniforms); |
| @@ -938,6 +981,7 @@ ASSERT_REG_POSITION(num_vertices, 0x228); | |||
| 938 | ASSERT_REG_POSITION(trigger_draw, 0x22e); | 981 | ASSERT_REG_POSITION(trigger_draw, 0x22e); |
| 939 | ASSERT_REG_POSITION(trigger_draw_indexed, 0x22f); | 982 | ASSERT_REG_POSITION(trigger_draw_indexed, 0x22f); |
| 940 | ASSERT_REG_POSITION(vs_default_attributes_setup, 0x232); | 983 | ASSERT_REG_POSITION(vs_default_attributes_setup, 0x232); |
| 984 | ASSERT_REG_POSITION(command_buffer, 0x238); | ||
| 941 | ASSERT_REG_POSITION(triangle_topology, 0x25e); | 985 | ASSERT_REG_POSITION(triangle_topology, 0x25e); |
| 942 | ASSERT_REG_POSITION(vs_bool_uniforms, 0x2b0); | 986 | ASSERT_REG_POSITION(vs_bool_uniforms, 0x2b0); |
| 943 | ASSERT_REG_POSITION(vs_int_uniforms, 0x2b1); | 987 | ASSERT_REG_POSITION(vs_int_uniforms, 0x2b1); |
| @@ -1053,21 +1097,12 @@ private: | |||
| 1053 | float value; | 1097 | float value; |
| 1054 | }; | 1098 | }; |
| 1055 | 1099 | ||
| 1056 | union CommandHeader { | ||
| 1057 | CommandHeader(u32 h) : hex(h) {} | ||
| 1058 | |||
| 1059 | u32 hex; | ||
| 1060 | |||
| 1061 | BitField< 0, 16, u32> cmd_id; | ||
| 1062 | BitField<16, 4, u32> parameter_mask; | ||
| 1063 | BitField<20, 11, u32> extra_data_length; | ||
| 1064 | BitField<31, 1, u32> group_commands; | ||
| 1065 | }; | ||
| 1066 | |||
| 1067 | /// Struct used to describe current Pica state | 1100 | /// Struct used to describe current Pica state |
| 1068 | struct State { | 1101 | struct State { |
| 1102 | /// Pica registers | ||
| 1069 | Regs regs; | 1103 | Regs regs; |
| 1070 | 1104 | ||
| 1105 | /// Vertex shader memory | ||
| 1071 | struct { | 1106 | struct { |
| 1072 | struct { | 1107 | struct { |
| 1073 | Math::Vec4<float24> f[96]; | 1108 | Math::Vec4<float24> f[96]; |
| @@ -1080,6 +1115,13 @@ struct State { | |||
| 1080 | std::array<u32, 1024> program_code; | 1115 | std::array<u32, 1024> program_code; |
| 1081 | std::array<u32, 1024> swizzle_data; | 1116 | std::array<u32, 1024> swizzle_data; |
| 1082 | } vs; | 1117 | } vs; |
| 1118 | |||
| 1119 | /// Current Pica command list | ||
| 1120 | struct { | ||
| 1121 | const u32* head_ptr; | ||
| 1122 | const u32* current_ptr; | ||
| 1123 | u32 length; | ||
| 1124 | } cmd_list; | ||
| 1083 | }; | 1125 | }; |
| 1084 | 1126 | ||
| 1085 | /// Initialize Pica state | 1127 | /// Initialize Pica state |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 767ff4205..113b573f8 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -104,7 +104,7 @@ static u32 GetDepth(int x, int y) { | |||
| 104 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); | 104 | u8* depth_buffer = Memory::GetPhysicalPointer(addr); |
| 105 | 105 | ||
| 106 | y = framebuffer.height - y; | 106 | y = framebuffer.height - y; |
| 107 | 107 | ||
| 108 | const u32 coarse_y = y & ~7; | 108 | const u32 coarse_y = y & ~7; |
| 109 | u32 bytes_per_pixel = Regs::BytesPerDepthPixel(framebuffer.depth_format); | 109 | u32 bytes_per_pixel = Regs::BytesPerDepthPixel(framebuffer.depth_format); |
| 110 | u32 stride = framebuffer.width * bytes_per_pixel; | 110 | u32 stride = framebuffer.width * bytes_per_pixel; |
| @@ -402,11 +402,16 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, | |||
| 402 | 402 | ||
| 403 | auto GetSource = [&](Source source) -> Math::Vec4<u8> { | 403 | auto GetSource = [&](Source source) -> Math::Vec4<u8> { |
| 404 | switch (source) { | 404 | switch (source) { |
| 405 | // TODO: What's the difference between these two? | ||
| 406 | case Source::PrimaryColor: | 405 | case Source::PrimaryColor: |
| 406 | |||
| 407 | // HACK: Until we implement fragment lighting, use primary_color | ||
| 407 | case Source::PrimaryFragmentColor: | 408 | case Source::PrimaryFragmentColor: |
| 408 | return primary_color; | 409 | return primary_color; |
| 409 | 410 | ||
| 411 | // HACK: Until we implement fragment lighting, use zero | ||
| 412 | case Source::SecondaryFragmentColor: | ||
| 413 | return {0, 0, 0, 0}; | ||
| 414 | |||
| 410 | case Source::Texture0: | 415 | case Source::Texture0: |
| 411 | return texture_color[0]; | 416 | return texture_color[0]; |
| 412 | 417 | ||
| @@ -570,6 +575,13 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, | |||
| 570 | case Operation::Add: | 575 | case Operation::Add: |
| 571 | return std::min(255, input[0] + input[1]); | 576 | return std::min(255, input[0] + input[1]); |
| 572 | 577 | ||
| 578 | case Operation::AddSigned: | ||
| 579 | { | ||
| 580 | // TODO(bunnei): Verify that the color conversion from (float) 0.5f to (byte) 128 is correct | ||
| 581 | auto result = static_cast<int>(input[0]) + static_cast<int>(input[1]) - 128; | ||
| 582 | return static_cast<u8>(MathUtil::Clamp<int>(result, 0, 255)); | ||
| 583 | } | ||
| 584 | |||
| 573 | case Operation::Lerp: | 585 | case Operation::Lerp: |
| 574 | return (input[0] * input[2] + input[1] * (255 - input[2])) / 255; | 586 | return (input[0] * input[2] + input[1] * (255 - input[2])) / 255; |
| 575 | 587 | ||
| @@ -808,10 +820,9 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, | |||
| 808 | } | 820 | } |
| 809 | }; | 821 | }; |
| 810 | 822 | ||
| 811 | using BlendEquation = Regs::BlendEquation; | ||
| 812 | static auto EvaluateBlendEquation = [](const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor, | 823 | static auto EvaluateBlendEquation = [](const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor, |
| 813 | const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor, | 824 | const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor, |
| 814 | BlendEquation equation) { | 825 | Regs::BlendEquation equation) { |
| 815 | Math::Vec4<int> result; | 826 | Math::Vec4<int> result; |
| 816 | 827 | ||
| 817 | auto src_result = (src * srcfactor).Cast<int>(); | 828 | auto src_result = (src * srcfactor).Cast<int>(); |
| @@ -866,8 +877,63 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0, | |||
| 866 | blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb); | 877 | blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb); |
| 867 | blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a(); | 878 | blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a(); |
| 868 | } else { | 879 | } else { |
| 869 | LOG_CRITICAL(HW_GPU, "logic op: %x", output_merger.logic_op); | 880 | static auto LogicOp = [](u8 src, u8 dest, Regs::LogicOp op) -> u8 { |
| 870 | UNIMPLEMENTED(); | 881 | switch (op) { |
| 882 | case Regs::LogicOp::Clear: | ||
| 883 | return 0; | ||
| 884 | |||
| 885 | case Regs::LogicOp::And: | ||
| 886 | return src & dest; | ||
| 887 | |||
| 888 | case Regs::LogicOp::AndReverse: | ||
| 889 | return src & ~dest; | ||
| 890 | |||
| 891 | case Regs::LogicOp::Copy: | ||
| 892 | return src; | ||
| 893 | |||
| 894 | case Regs::LogicOp::Set: | ||
| 895 | return 255; | ||
| 896 | |||
| 897 | case Regs::LogicOp::CopyInverted: | ||
| 898 | return ~src; | ||
| 899 | |||
| 900 | case Regs::LogicOp::NoOp: | ||
| 901 | return dest; | ||
| 902 | |||
| 903 | case Regs::LogicOp::Invert: | ||
| 904 | return ~dest; | ||
| 905 | |||
| 906 | case Regs::LogicOp::Nand: | ||
| 907 | return ~(src & dest); | ||
| 908 | |||
| 909 | case Regs::LogicOp::Or: | ||
| 910 | return src | dest; | ||
| 911 | |||
| 912 | case Regs::LogicOp::Nor: | ||
| 913 | return ~(src | dest); | ||
| 914 | |||
| 915 | case Regs::LogicOp::Xor: | ||
| 916 | return src ^ dest; | ||
| 917 | |||
| 918 | case Regs::LogicOp::Equiv: | ||
| 919 | return ~(src ^ dest); | ||
| 920 | |||
| 921 | case Regs::LogicOp::AndInverted: | ||
| 922 | return ~src & dest; | ||
| 923 | |||
| 924 | case Regs::LogicOp::OrReverse: | ||
| 925 | return src | ~dest; | ||
| 926 | |||
| 927 | case Regs::LogicOp::OrInverted: | ||
| 928 | return ~src | dest; | ||
| 929 | } | ||
| 930 | }; | ||
| 931 | |||
| 932 | blend_output = Math::MakeVec( | ||
| 933 | LogicOp(combiner_output.r(), dest.r(), output_merger.logic_op), | ||
| 934 | LogicOp(combiner_output.g(), dest.g(), output_merger.logic_op), | ||
| 935 | LogicOp(combiner_output.b(), dest.b(), output_merger.logic_op), | ||
| 936 | LogicOp(combiner_output.a(), dest.a(), output_merger.logic_op)); | ||
| 871 | } | 937 | } |
| 872 | 938 | ||
| 873 | const Math::Vec4<u8> result = { | 939 | 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 ef29972d7..95fd29c0a 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) | |||
| 62 | ptrdiff_t iTest; | 62 | ptrdiff_t iTest; |
| 63 | if(!pTest) return 0; | 63 | if(!pTest) return 0; |
| 64 | iTest = (ptrdiff_t)pTest; | 64 | iTest = (ptrdiff_t)pTest; |
| 65 | 65 | ||
| 66 | if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0; | 66 | if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0; |
| 67 | 67 | ||
| 68 | return 1; | 68 | return 1; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| @@ -79,7 +79,7 @@ static PROC WinGetProcAddress(const char *name) | |||
| 79 | glMod = GetModuleHandleA("OpenGL32.dll"); | 79 | glMod = GetModuleHandleA("OpenGL32.dll"); |
| 80 | return (PROC)GetProcAddress(glMod, (LPCSTR)name); | 80 | return (PROC)GetProcAddress(glMod, (LPCSTR)name); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | #define IntGetProcAddress(name) WinGetProcAddress(name) | 83 | #define IntGetProcAddress(name) WinGetProcAddress(name) |
| 84 | #else | 84 | #else |
| 85 | #if defined(__APPLE__) | 85 | #if defined(__APPLE__) |
| @@ -1083,7 +1083,7 @@ static ogl_StrToExtMap *FindExtEntry(const char *extensionName) | |||
| 1083 | if(strcmp(extensionName, currLoc->extensionName) == 0) | 1083 | if(strcmp(extensionName, currLoc->extensionName) == 0) |
| 1084 | return currLoc; | 1084 | return currLoc; |
| 1085 | } | 1085 | } |
| 1086 | 1086 | ||
| 1087 | return NULL; | 1087 | return NULL; |
| 1088 | } | 1088 | } |
| 1089 | 1089 | ||
| @@ -1135,15 +1135,15 @@ int ogl_LoadFunctions() | |||
| 1135 | { | 1135 | { |
| 1136 | int numFailed = 0; | 1136 | int numFailed = 0; |
| 1137 | ClearExtensionVars(); | 1137 | ClearExtensionVars(); |
| 1138 | 1138 | ||
| 1139 | _ptrc_glGetIntegerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint *))IntGetProcAddress("glGetIntegerv"); | 1139 | _ptrc_glGetIntegerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint *))IntGetProcAddress("glGetIntegerv"); |
| 1140 | if(!_ptrc_glGetIntegerv) return ogl_LOAD_FAILED; | 1140 | if(!_ptrc_glGetIntegerv) return ogl_LOAD_FAILED; |
| 1141 | _ptrc_glGetStringi = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glGetStringi"); | 1141 | _ptrc_glGetStringi = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glGetStringi"); |
| 1142 | if(!_ptrc_glGetStringi) return ogl_LOAD_FAILED; | 1142 | if(!_ptrc_glGetStringi) return ogl_LOAD_FAILED; |
| 1143 | 1143 | ||
| 1144 | ProcExtsFromExtList(); | 1144 | ProcExtsFromExtList(); |
| 1145 | numFailed = Load_Version_3_2(); | 1145 | numFailed = Load_Version_3_2(); |
| 1146 | 1146 | ||
| 1147 | if(numFailed == 0) | 1147 | if(numFailed == 0) |
| 1148 | return ogl_LOAD_SUCCEEDED; | 1148 | return ogl_LOAD_SUCCEEDED; |
| 1149 | else | 1149 | else |
| @@ -1177,7 +1177,7 @@ int ogl_IsVersionGEQ(int majorVersion, int minorVersion) | |||
| 1177 | { | 1177 | { |
| 1178 | if(g_major_version == 0) | 1178 | if(g_major_version == 0) |
| 1179 | GetGLVersion(); | 1179 | GetGLVersion(); |
| 1180 | 1180 | ||
| 1181 | if(majorVersion > g_major_version) return 1; | 1181 | if(majorVersion > g_major_version) return 1; |
| 1182 | if(majorVersion < g_major_version) return 0; | 1182 | if(majorVersion < g_major_version) return 0; |
| 1183 | if(minorVersion >= g_minor_version) return 1; | 1183 | 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 4b7d099a5..b51f8efdf 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -135,6 +135,7 @@ void RasterizerOpenGL::Reset() { | |||
| 135 | SyncBlendFuncs(); | 135 | SyncBlendFuncs(); |
| 136 | SyncBlendColor(); | 136 | SyncBlendColor(); |
| 137 | SyncAlphaTest(); | 137 | SyncAlphaTest(); |
| 138 | SyncLogicOp(); | ||
| 138 | SyncStencilTest(); | 139 | SyncStencilTest(); |
| 139 | SyncDepthTest(); | 140 | SyncDepthTest(); |
| 140 | 141 | ||
| @@ -249,6 +250,11 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | |||
| 249 | SyncDepthTest(); | 250 | SyncDepthTest(); |
| 250 | break; | 251 | break; |
| 251 | 252 | ||
| 253 | // Logic op | ||
| 254 | case PICA_REG_INDEX(output_merger.logic_op): | ||
| 255 | SyncLogicOp(); | ||
| 256 | break; | ||
| 257 | |||
| 252 | // TEV stage 0 | 258 | // TEV stage 0 |
| 253 | case PICA_REG_INDEX(tev_stage0.color_source1): | 259 | case PICA_REG_INDEX(tev_stage0.color_source1): |
| 254 | SyncTevSources(0, regs.tev_stage0); | 260 | SyncTevSources(0, regs.tev_stage0); |
| @@ -350,7 +356,7 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | |||
| 350 | case PICA_REG_INDEX(tev_stage5.color_scale): | 356 | case PICA_REG_INDEX(tev_stage5.color_scale): |
| 351 | SyncTevMultipliers(5, regs.tev_stage5); | 357 | SyncTevMultipliers(5, regs.tev_stage5); |
| 352 | break; | 358 | break; |
| 353 | 359 | ||
| 354 | // TEV combiner buffer color | 360 | // TEV combiner buffer color |
| 355 | case PICA_REG_INDEX(tev_combiner_buffer_color): | 361 | case PICA_REG_INDEX(tev_combiner_buffer_color): |
| 356 | SyncCombinerColor(); | 362 | SyncCombinerColor(); |
| @@ -633,6 +639,10 @@ void RasterizerOpenGL::SyncAlphaTest() { | |||
| 633 | glUniform1f(uniform_alphatest_ref, regs.output_merger.alpha_test.ref / 255.0f); | 639 | glUniform1f(uniform_alphatest_ref, regs.output_merger.alpha_test.ref / 255.0f); |
| 634 | } | 640 | } |
| 635 | 641 | ||
| 642 | void RasterizerOpenGL::SyncLogicOp() { | ||
| 643 | state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.output_merger.logic_op); | ||
| 644 | } | ||
| 645 | |||
| 636 | void RasterizerOpenGL::SyncStencilTest() { | 646 | void RasterizerOpenGL::SyncStencilTest() { |
| 637 | // TODO: Implement stencil test, mask, and op | 647 | // TODO: Implement stencil test, mask, and op |
| 638 | } | 648 | } |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 9896f8d04..d7d422b1f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -125,6 +125,9 @@ private: | |||
| 125 | /// Syncs the alpha test states to match the PICA register | 125 | /// Syncs the alpha test states to match the PICA register |
| 126 | void SyncAlphaTest(); | 126 | void SyncAlphaTest(); |
| 127 | 127 | ||
| 128 | /// Syncs the logic op states to match the PICA register | ||
| 129 | void SyncLogicOp(); | ||
| 130 | |||
| 128 | /// Syncs the stencil test states to match the PICA register | 131 | /// Syncs the stencil test states to match the PICA register |
| 129 | void SyncStencilTest(); | 132 | void SyncStencilTest(); |
| 130 | 133 | ||
diff --git a/src/video_core/renderer_opengl/gl_shaders.h b/src/video_core/renderer_opengl/gl_shaders.h index 8f0941230..a8cb2f595 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"( | |||
| 69 | #define NUM_VTX_ATTR 7 | 69 | #define NUM_VTX_ATTR 7 |
| 70 | #define NUM_TEV_STAGES 6 | 70 | #define NUM_TEV_STAGES 6 |
| 71 | 71 | ||
| 72 | #define SOURCE_PRIMARYCOLOR 0x0 | 72 | #define SOURCE_PRIMARYCOLOR 0x0 |
| 73 | #define SOURCE_PRIMARYFRAGMENTCOLOR 0x1 | 73 | #define SOURCE_PRIMARYFRAGMENTCOLOR 0x1 |
| 74 | #define SOURCE_TEXTURE0 0x3 | 74 | #define SOURCE_SECONDARYFRAGMENTCOLOR 0x2 |
| 75 | #define SOURCE_TEXTURE1 0x4 | 75 | #define SOURCE_TEXTURE0 0x3 |
| 76 | #define SOURCE_TEXTURE2 0x5 | 76 | #define SOURCE_TEXTURE1 0x4 |
| 77 | #define SOURCE_TEXTURE3 0x6 | 77 | #define SOURCE_TEXTURE2 0x5 |
| 78 | #define SOURCE_PREVIOUSBUFFER 0xd | 78 | #define SOURCE_TEXTURE3 0x6 |
| 79 | #define SOURCE_CONSTANT 0xe | 79 | #define SOURCE_PREVIOUSBUFFER 0xd |
| 80 | #define SOURCE_PREVIOUS 0xf | 80 | #define SOURCE_CONSTANT 0xe |
| 81 | #define SOURCE_PREVIOUS 0xf | ||
| 81 | 82 | ||
| 82 | #define COLORMODIFIER_SOURCECOLOR 0x0 | 83 | #define COLORMODIFIER_SOURCECOLOR 0x0 |
| 83 | #define COLORMODIFIER_ONEMINUSSOURCECOLOR 0x1 | 84 | #define COLORMODIFIER_ONEMINUSSOURCECOLOR 0x1 |
| @@ -151,8 +152,11 @@ vec4 GetSource(int source) { | |||
| 151 | if (source == SOURCE_PRIMARYCOLOR) { | 152 | if (source == SOURCE_PRIMARYCOLOR) { |
| 152 | return o[2]; | 153 | return o[2]; |
| 153 | } else if (source == SOURCE_PRIMARYFRAGMENTCOLOR) { | 154 | } else if (source == SOURCE_PRIMARYFRAGMENTCOLOR) { |
| 154 | // HACK: Uses color value, but should really use fragment lighting output | 155 | // HACK: Until we implement fragment lighting, use primary_color |
| 155 | return o[2]; | 156 | return o[2]; |
| 157 | } else if (source == SOURCE_SECONDARYFRAGMENTCOLOR) { | ||
| 158 | // HACK: Until we implement fragment lighting, use zero | ||
| 159 | return vec4(0.0, 0.0, 0.0, 0.0); | ||
| 156 | } else if (source == SOURCE_TEXTURE0) { | 160 | } else if (source == SOURCE_TEXTURE0) { |
| 157 | return texture(tex[0], o[3].xy); | 161 | return texture(tex[0], o[3].xy); |
| 158 | } else if (source == SOURCE_TEXTURE1) { | 162 | } 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 1afa58c99..9c5f38f94 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -32,6 +32,8 @@ OpenGLState::OpenGLState() { | |||
| 32 | blend.color.blue = 0.0f; | 32 | blend.color.blue = 0.0f; |
| 33 | blend.color.alpha = 0.0f; | 33 | blend.color.alpha = 0.0f; |
| 34 | 34 | ||
| 35 | logic_op = GL_COPY; | ||
| 36 | |||
| 35 | for (auto& texture_unit : texture_units) { | 37 | for (auto& texture_unit : texture_units) { |
| 36 | texture_unit.enabled_2d = false; | 38 | texture_unit.enabled_2d = false; |
| 37 | texture_unit.texture_2d = 0; | 39 | texture_unit.texture_2d = 0; |
| @@ -82,7 +84,7 @@ void OpenGLState::Apply() { | |||
| 82 | } else { | 84 | } else { |
| 83 | glDisable(GL_STENCIL_TEST); | 85 | glDisable(GL_STENCIL_TEST); |
| 84 | } | 86 | } |
| 85 | } | 87 | } |
| 86 | 88 | ||
| 87 | if (stencil.test_func != cur_state.stencil.test_func || | 89 | if (stencil.test_func != cur_state.stencil.test_func || |
| 88 | stencil.test_ref != cur_state.stencil.test_ref || | 90 | stencil.test_ref != cur_state.stencil.test_ref || |
| @@ -99,8 +101,13 @@ void OpenGLState::Apply() { | |||
| 99 | if (blend.enabled != cur_state.blend.enabled) { | 101 | if (blend.enabled != cur_state.blend.enabled) { |
| 100 | if (blend.enabled) { | 102 | if (blend.enabled) { |
| 101 | glEnable(GL_BLEND); | 103 | glEnable(GL_BLEND); |
| 104 | |||
| 105 | cur_state.logic_op = GL_COPY; | ||
| 106 | glLogicOp(cur_state.logic_op); | ||
| 107 | glDisable(GL_COLOR_LOGIC_OP); | ||
| 102 | } else { | 108 | } else { |
| 103 | glDisable(GL_BLEND); | 109 | glDisable(GL_BLEND); |
| 110 | glEnable(GL_COLOR_LOGIC_OP); | ||
| 104 | } | 111 | } |
| 105 | } | 112 | } |
| 106 | 113 | ||
| @@ -118,6 +125,10 @@ void OpenGLState::Apply() { | |||
| 118 | glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); | 125 | glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); |
| 119 | } | 126 | } |
| 120 | 127 | ||
| 128 | if (logic_op != cur_state.logic_op) { | ||
| 129 | glLogicOp(logic_op); | ||
| 130 | } | ||
| 131 | |||
| 121 | // Textures | 132 | // Textures |
| 122 | for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) { | 133 | for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) { |
| 123 | if (texture_units[texture_index].enabled_2d != cur_state.texture_units[texture_index].enabled_2d) { | 134 | if (texture_units[texture_index].enabled_2d != cur_state.texture_units[texture_index].enabled_2d) { |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 281b7cad5..6b97721d6 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -42,6 +42,8 @@ public: | |||
| 42 | } color; // GL_BLEND_COLOR | 42 | } color; // GL_BLEND_COLOR |
| 43 | } blend; | 43 | } blend; |
| 44 | 44 | ||
| 45 | GLenum logic_op; // GL_LOGIC_OP_MODE | ||
| 46 | |||
| 45 | // 3 texture units - one for each that is used in PICA fragment shader emulation | 47 | // 3 texture units - one for each that is used in PICA fragment shader emulation |
| 46 | struct { | 48 | struct { |
| 47 | bool enabled_2d; // GL_TEXTURE_2D | 49 | bool enabled_2d; // GL_TEXTURE_2D |
| @@ -61,7 +63,7 @@ public: | |||
| 61 | static const OpenGLState& GetCurState() { | 63 | static const OpenGLState& GetCurState() { |
| 62 | return cur_state; | 64 | return cur_state; |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | /// Apply this state as the current OpenGL state | 67 | /// Apply this state as the current OpenGL state |
| 66 | void Apply(); | 68 | void Apply(); |
| 67 | 69 | ||
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h index f8763e71b..e566f9f7a 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) { | |||
| 71 | return blend_func_table[(unsigned)factor]; | 71 | return blend_func_table[(unsigned)factor]; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | inline GLenum LogicOp(Pica::Regs::LogicOp op) { | ||
| 75 | static const GLenum logic_op_table[] = { | ||
| 76 | GL_CLEAR, // Clear | ||
| 77 | GL_AND, // And | ||
| 78 | GL_AND_REVERSE, // AndReverse | ||
| 79 | GL_COPY, // Copy | ||
| 80 | GL_SET, // Set | ||
| 81 | GL_COPY_INVERTED, // CopyInverted | ||
| 82 | GL_NOOP, // NoOp | ||
| 83 | GL_INVERT, // Invert | ||
| 84 | GL_NAND, // Nand | ||
| 85 | GL_OR, // Or | ||
| 86 | GL_NOR, // Nor | ||
| 87 | GL_XOR, // Xor | ||
| 88 | GL_EQUIV, // Equiv | ||
| 89 | GL_AND_INVERTED, // AndInverted | ||
| 90 | GL_OR_REVERSE, // OrReverse | ||
| 91 | GL_OR_INVERTED, // OrInverted | ||
| 92 | }; | ||
| 93 | |||
| 94 | // Range check table for input | ||
| 95 | if ((unsigned)op >= ARRAY_SIZE(logic_op_table)) { | ||
| 96 | LOG_CRITICAL(Render_OpenGL, "Unknown logic op %d", op); | ||
| 97 | UNREACHABLE(); | ||
| 98 | |||
| 99 | return GL_COPY; | ||
| 100 | } | ||
| 101 | |||
| 102 | return logic_op_table[(unsigned)op]; | ||
| 103 | } | ||
| 104 | |||
| 74 | inline GLenum CompareFunc(Pica::Regs::CompareFunc func) { | 105 | inline GLenum CompareFunc(Pica::Regs::CompareFunc func) { |
| 75 | static const GLenum compare_func_table[] = { | 106 | static const GLenum compare_func_table[] = { |
| 76 | GL_NEVER, // CompareFunc::Never | 107 | 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 16cf92e20..382aeaa05 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& | |||
| 157 | state.texture_units[0].enabled_2d = true; | 157 | state.texture_units[0].enabled_2d = true; |
| 158 | state.texture_units[0].texture_2d = texture.handle; | 158 | state.texture_units[0].texture_2d = texture.handle; |
| 159 | state.Apply(); | 159 | state.Apply(); |
| 160 | 160 | ||
| 161 | glActiveTexture(GL_TEXTURE0); | 161 | glActiveTexture(GL_TEXTURE0); |
| 162 | glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride); | 162 | glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride); |
| 163 | 163 | ||
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp index 7d68998f1..87006a832 100644 --- a/src/video_core/vertex_shader.cpp +++ b/src/video_core/vertex_shader.cpp | |||
| @@ -119,17 +119,13 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 119 | switch (instr.opcode.Value().GetInfo().type) { | 119 | switch (instr.opcode.Value().GetInfo().type) { |
| 120 | case OpCode::Type::Arithmetic: | 120 | case OpCode::Type::Arithmetic: |
| 121 | { | 121 | { |
| 122 | bool is_inverted = 0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed); | 122 | const bool is_inverted = (0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed)); |
| 123 | // TODO: We don't really support this properly: For instance, the address register | ||
| 124 | // offset needs to be applied to SRC2 instead, etc. | ||
| 125 | // For now, we just abort in this situation. | ||
| 126 | ASSERT_MSG(!is_inverted, "Bad condition..."); | ||
| 127 | 123 | ||
| 128 | const int address_offset = (instr.common.address_register_index == 0) | 124 | const int address_offset = (instr.common.address_register_index == 0) |
| 129 | ? 0 : state.address_registers[instr.common.address_register_index - 1]; | 125 | ? 0 : state.address_registers[instr.common.address_register_index - 1]; |
| 130 | 126 | ||
| 131 | const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + address_offset); | 127 | const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + (!is_inverted * address_offset)); |
| 132 | const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted)); | 128 | const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted) + ( is_inverted * address_offset)); |
| 133 | 129 | ||
| 134 | const bool negate_src1 = ((bool)swizzle.negate_src1 != false); | 130 | const bool negate_src1 = ((bool)swizzle.negate_src1 != false); |
| 135 | const bool negate_src2 = ((bool)swizzle.negate_src2 != false); | 131 | const bool negate_src2 = ((bool)swizzle.negate_src2 != false); |
| @@ -208,6 +204,15 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 208 | } | 204 | } |
| 209 | break; | 205 | break; |
| 210 | 206 | ||
| 207 | case OpCode::Id::MIN: | ||
| 208 | for (int i = 0; i < 4; ++i) { | ||
| 209 | if (!swizzle.DestComponentEnabled(i)) | ||
| 210 | continue; | ||
| 211 | |||
| 212 | dest[i] = std::min(src1[i], src2[i]); | ||
| 213 | } | ||
| 214 | break; | ||
| 215 | |||
| 211 | case OpCode::Id::DP3: | 216 | case OpCode::Id::DP3: |
| 212 | case OpCode::Id::DP4: | 217 | case OpCode::Id::DP4: |
| 213 | { | 218 | { |
| @@ -279,6 +284,16 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 279 | break; | 284 | break; |
| 280 | } | 285 | } |
| 281 | 286 | ||
| 287 | case OpCode::Id::SLT: | ||
| 288 | case OpCode::Id::SLTI: | ||
| 289 | for (int i = 0; i < 4; ++i) { | ||
| 290 | if (!swizzle.DestComponentEnabled(i)) | ||
| 291 | continue; | ||
| 292 | |||
| 293 | dest[i] = (src1[i] < src2[i]) ? float24::FromFloat32(1.0f) : float24::FromFloat32(0.0f); | ||
| 294 | } | ||
| 295 | break; | ||
| 296 | |||
| 282 | case OpCode::Id::CMP: | 297 | case OpCode::Id::CMP: |
| 283 | for (int i = 0; i < 2; ++i) { | 298 | for (int i = 0; i < 2; ++i) { |
| 284 | // TODO: Can you restrict to one compare via dest masking? | 299 | // TODO: Can you restrict to one compare via dest masking? |
| @@ -330,7 +345,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 330 | 345 | ||
| 331 | case OpCode::Type::MultiplyAdd: | 346 | case OpCode::Type::MultiplyAdd: |
| 332 | { | 347 | { |
| 333 | if ((instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MAD) || | 348 | if ((instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MAD) || |
| 334 | (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI)) { | 349 | (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI)) { |
| 335 | const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.mad.operand_desc_id]; | 350 | const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.mad.operand_desc_id]; |
| 336 | 351 | ||
| @@ -547,7 +562,7 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes) { | |||
| 547 | const auto& attribute_register_map = regs.vs_input_register_map; | 562 | const auto& attribute_register_map = regs.vs_input_register_map; |
| 548 | float24 dummy_register; | 563 | float24 dummy_register; |
| 549 | boost::fill(state.input_register_table, &dummy_register); | 564 | boost::fill(state.input_register_table, &dummy_register); |
| 550 | 565 | ||
| 551 | if (num_attributes > 0) state.input_register_table[attribute_register_map.attribute0_register] = &input.attr[0].x; | 566 | if (num_attributes > 0) state.input_register_table[attribute_register_map.attribute0_register] = &input.attr[0].x; |
| 552 | if (num_attributes > 1) state.input_register_table[attribute_register_map.attribute1_register] = &input.attr[1].x; | 567 | if (num_attributes > 1) state.input_register_table[attribute_register_map.attribute1_register] = &input.attr[1].x; |
| 553 | if (num_attributes > 2) state.input_register_table[attribute_register_map.attribute2_register] = &input.attr[2].x; | 568 | if (num_attributes > 2) state.input_register_table[attribute_register_map.attribute2_register] = &input.attr[2].x; |