diff --git a/Doxyfile b/Doxyfile index e18f3b6452..78efc9d7c4 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.8.14 +# Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -17,10 +17,10 @@ # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "RetroArch" +PROJECT_NAME = RetroArch # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = +OUTPUT_DIRECTORY = docs # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -187,7 +195,17 @@ SHORT_NAMES = YES # description.) # The default value is: NO. -JAVADOC_AUTOBRIEF = NO +JAVADOC_AUTOBRIEF = YES + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If @@ -209,6 +227,14 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. @@ -238,14 +264,12 @@ TAB_SIZE = 4 # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = +ALIASES = "setby{1}=@par Set by^^The \1." # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For @@ -253,7 +277,7 @@ TCL_SUBST = # members will be omitted, etc. # The default value is: NO. -OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored @@ -275,28 +299,40 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. +# documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. @@ -308,7 +344,7 @@ MARKDOWN_SUPPORT = YES # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 0. +# Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 @@ -398,7 +434,7 @@ INLINE_GROUPED_CLASSES = NO # Man pages) or section (for LaTeX and RTF). # The default value is: NO. -INLINE_SIMPLE_STRUCTS = NO +INLINE_SIMPLE_STRUCTS = YES # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So @@ -424,6 +460,19 @@ TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which efficively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 16 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -442,7 +491,13 @@ EXTRACT_ALL = YES # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = YES +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. @@ -481,6 +536,13 @@ EXTRACT_LOCAL_METHODS = YES EXTRACT_ANON_NSPACES = NO +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation @@ -498,8 +560,8 @@ HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. +# declarations. If set to NO, these declarations will be included in the +# documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO @@ -518,11 +580,18 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. # The default value is: system dependent. CASE_SENSE_NAMES = YES @@ -532,7 +601,7 @@ CASE_SENSE_NAMES = YES # scope will be hidden. # The default value is: NO. -HIDE_SCOPE_NAMES = NO +HIDE_SCOPE_NAMES = YES # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to @@ -571,7 +640,7 @@ INLINE_INFO = YES # name. If set to NO, the members will appear in declaration order. # The default value is: YES. -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member @@ -754,13 +823,17 @@ WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO @@ -791,13 +864,13 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = +INPUT = libretro-common # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 @@ -810,56 +883,17 @@ INPUT_ENCODING = UTF-8 # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.idl \ - *.ddl \ - *.odl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.cs \ - *.d \ - *.php \ - *.php4 \ - *.php5 \ - *.phtml \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.pyw \ - *.f90 \ - *.f95 \ - *.f03 \ - *.f08 \ - *.f \ - *.for \ - *.tcl \ - *.vhd \ - *.vhdl \ - *.ucf \ - *.qsf +FILE_PATTERNS = *.h # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -890,7 +924,11 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = */libretro-common/rthreads/* \ + */libretro-common/formats/* \ + */libretro-common/crt/* \ + */libretro-common/samples/* \ + */libretro-common/include/glsym/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -901,7 +939,9 @@ EXCLUDE_PATTERNS = # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = bool \ + void \ + const # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include @@ -1012,7 +1052,7 @@ INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. +# entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO @@ -1049,7 +1089,7 @@ SOURCE_TOOLTIPS = YES # # To use it do the following: # - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # @@ -1071,6 +1111,44 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to +# YES then doxygen will add the directory of each input to the include path. +# The default value is: YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1082,20 +1160,14 @@ VERBATIM_HEADERS = YES ALPHABETICAL_INDEX = YES -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. -IGNORE_PREFIX = +IGNORE_PREFIX = retro_ \ + RETRO_ #--------------------------------------------------------------------------- # Configuration options related to the HTML output @@ -1227,9 +1299,9 @@ HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that -# are dynamically created via Javascript. If disabled, the navigation index will +# are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have Javascript, +# page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1259,13 +1331,14 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1304,8 +1377,8 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1335,7 +1408,7 @@ CHM_FILE = HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). +# (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1380,7 +1453,8 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1388,7 +1462,8 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1396,28 +1471,30 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = @@ -1468,7 +1545,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. @@ -1494,6 +1571,17 @@ TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML @@ -1514,8 +1602,14 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# https://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1527,7 +1621,7 @@ USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. @@ -1543,7 +1637,7 @@ MATHJAX_FORMAT = HTML-CSS # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ @@ -1557,7 +1651,8 @@ MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1585,7 +1680,7 @@ MATHJAX_CODEFILE = SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a web server instead of a web client using Javascript. There +# implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH # setting. When disabled, doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing @@ -1604,7 +1699,8 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). +# Xapian (see: +# https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1617,8 +1713,9 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). See the section "External Indexing and -# Searching" for details. +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. # This tag requires that the tag SEARCHENGINE is set to YES. SEARCHENGINE_URL = @@ -1669,21 +1766,35 @@ LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. # -# Note that when enabling USE_PDFLATEX this option is only used for generating -# bitmaps for formulas in the HTML output, but not in the Makefile that is -# written to the output directory. -# The default file is: latex. +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). # The default file is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. MAKEINDEX_CMD_NAME = makeindex +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. @@ -1768,9 +1879,11 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES, to get a -# higher quality PDF documentation. +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1818,6 +1931,14 @@ LATEX_BIB_STYLE = plain LATEX_TIMESTAMP = NO +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -1857,9 +1978,9 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's config -# file, i.e. a series of assignments. You only have to provide replacements, -# missing definitions are set to their default value. +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the # default style sheet that doxygen normally uses. @@ -1868,8 +1989,8 @@ RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's config file. A template extensions file can be generated -# using doxygen -e rtf extensionFile. +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = @@ -1955,6 +2076,13 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- @@ -1994,6 +2122,10 @@ DOCBOOK_PROGRAMLISTING = NO GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- @@ -2089,7 +2221,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = DOXYGEN # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2156,12 +2288,6 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of 'which perl'). -# The default file (with absolute path) is: /usr/bin/perl. - -PERL_PATH = /usr/bin/perl - #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- @@ -2173,16 +2299,7 @@ PERL_PATH = /usr/bin/perl # powerful graphs. # The default value is: YES. -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see: -# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = +CLASS_DIAGRAMS = NO # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The @@ -2202,9 +2319,9 @@ HIDE_UNDOC_RELATIONS = YES # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO -# The default value is: NO. +# The default value is: YES. -HAVE_DOT = YES +HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed # to run in parallel. When set to 0 doxygen will base this on the number of @@ -2281,10 +2398,32 @@ UML_LOOK = NO # but if the number exceeds 15, the total amount of fields shown is limited to # 10. # Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. +# This tag requires that the tag UML_LOOK is set to YES. UML_LIMIT_NUM_FIELDS = 10 +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2358,7 +2497,9 @@ DIRECTORY_GRAPH = YES # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). -# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, +# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, +# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, +# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, # png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and # png:gdiplus:gdiplus. # The default value is: png. @@ -2474,9 +2615,11 @@ DOT_MULTI_TARGETS = YES GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc and +# plantuml temporary files. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c index 80fe2c1bee..98b85024d9 100644 --- a/libretro-common/features/features_cpu.c +++ b/libretro-common/features/features_cpu.c @@ -150,13 +150,6 @@ static int ra_clock_gettime(int clk_ik, struct timespec *t) #include -/** - * cpu_features_get_perf_counter: - * - * Gets performance counter. - * - * @return Performance counter. - **/ retro_perf_tick_t cpu_features_get_perf_counter(void) { retro_perf_tick_t time_ticks = 0; @@ -218,13 +211,6 @@ retro_perf_tick_t cpu_features_get_perf_counter(void) return time_ticks; } -/** - * cpu_features_get_time_usec: - * - * Gets time in microseconds. - * - * @return Time in microseconds. - **/ retro_time_t cpu_features_get_time_usec(void) { #if defined(_WIN32) @@ -503,13 +489,6 @@ static void cpulist_read_from(CpuList* list, const char* filename) #endif -/** - * cpu_features_get_core_amount: - * - * Gets the amount of available CPU cores. - * - * @return Amount of CPU cores available. - **/ unsigned cpu_features_get_core_amount(void) { #if defined(_WIN32) && !defined(_XBOX) @@ -609,13 +588,6 @@ unsigned cpu_features_get_core_amount(void) #define VENDOR_INTEL_c 0x6c65746e #define VENDOR_INTEL_d 0x49656e69 -/** - * cpu_features_get: - * - * Gets CPU features.. - * - * @return Bitmask of all CPU features available. - **/ uint64_t cpu_features_get(void) { uint64_t cpu = 0; diff --git a/libretro-common/include/audio/conversion/float_to_s16.h b/libretro-common/include/audio/conversion/float_to_s16.h index 42b9571e4f..e8268fa378 100644 --- a/libretro-common/include/audio/conversion/float_to_s16.h +++ b/libretro-common/include/audio/conversion/float_to_s16.h @@ -31,22 +31,28 @@ RETRO_BEGIN_DECLS #include /** - * convert_float_to_s16: - * @out : output buffer - * @in : input buffer - * @samples : size of samples to be converted + * Converts an array of floating-point audio samples + * to signed integer 16-bit audio samples, + * possibly using SIMD intrinsics. * - * Converts floating point - * to signed integer 16-bit. + * @param out The buffer that will be used to store the converted samples. + * @param in The buffer containing the samples to convert. + * Any number of channels is supported. + * @param samples The length of \c in in samples, \em not bytes or frames. + * \c out must be as large as sizeof(int16_t) * samples. + * @see convert_s16_to_float **/ void convert_float_to_s16(int16_t *out, const float *in, size_t samples); /** - * convert_float_to_s16_init_simd: + * Initializes any prerequisites for + * using SIMD implementations of \c convert_float_to_s16. * - * Sets up function pointers for conversion - * functions based on CPU features. + * If SIMD intrinsics are not available or no initialization is required, + * this function does nothing. + * + * @see convert_float_to_s16 **/ void convert_float_to_s16_init_simd(void); diff --git a/libretro-common/include/audio/conversion/s16_to_float.h b/libretro-common/include/audio/conversion/s16_to_float.h index 188296e076..58d2a516dd 100644 --- a/libretro-common/include/audio/conversion/s16_to_float.h +++ b/libretro-common/include/audio/conversion/s16_to_float.h @@ -30,23 +30,30 @@ RETRO_BEGIN_DECLS /** - * convert_s16_to_float: - * @out : output buffer - * @in : input buffer - * @samples : size of samples to be converted - * @gain : gain applied (.e.g. audio volume) + * Converts an array of signed integer 16-bit audio samples + * to floating-point format, + * possibly using SIMD intrinsics. * - * Converts from signed integer 16-bit - * to floating point. + * @param out The buffer that will be used to store the converted samples. + * @param in The buffer containing the samples to convert. + * Any number of channels is supported. + * @param samples The length of \c in in samples, \em not bytes or frames. + * \c out must be as large as sizeof(float) * samples. + * @param gain The gain (audio volume) to apply to the samples. + * Pass a value of 1.0 to not apply any gain. + * @see convert_float_to_s16 **/ void convert_s16_to_float(float *out, const int16_t *in, size_t samples, float gain); /** - * convert_s16_to_float_init_simd: + * Initializes any prerequisites for + * using SIMD implementations of \c convert_s16_to_float. * - * Sets up function pointers for conversion - * functions based on CPU features. + * If SIMD intrinsics are not available or no initialization is required, + * this function does nothing. + * + * @see convert_s16_to_float **/ void convert_s16_to_float_init_simd(void); diff --git a/libretro-common/include/clamping.h b/libretro-common/include/clamping.h index d836d98990..616dd52f21 100644 --- a/libretro-common/include/clamping.h +++ b/libretro-common/include/clamping.h @@ -27,14 +27,13 @@ #include /** - * clamp_float: - * @val : initial value - * @lower : lower limit that value should be clamped against - * @upper : upper limit that value should be clamped against + * Clamps a floating-point value to the specified range. * - * Clamps a floating point value. + * @param val The value to clamp. + * @param lower The minimum possible value. + * @param upper The maximum possible value. * - * Returns: a clamped value of initial float value @val. + * @returns \c val clamped to between \c lower and \c upper (inclusive). */ static INLINE float clamp_float(float val, float lower, float upper) { @@ -46,12 +45,10 @@ static INLINE float clamp_float(float val, float lower, float upper) } /** - * clamp_8bit: - * @val : initial value + * Clamps an integer to fit in 8 bits. * - * Clamps an unsigned 8-bit value. - * - * Returns: a clamped value of initial unsigned 8-bit value @val. + * @param val The value to clamp. + * @return \c val clamped to between 0 and 255 (inclusive). */ static INLINE uint8_t clamp_8bit(int val) { diff --git a/libretro-common/include/compat/fnmatch.h b/libretro-common/include/compat/fnmatch.h index 9787878448..8bdeb2f6ad 100644 --- a/libretro-common/include/compat/fnmatch.h +++ b/libretro-common/include/compat/fnmatch.h @@ -25,6 +25,11 @@ #define FNM_NOMATCH 1 +/** + * Portable implementation of \c fnmatch(3), + * except \c flags is not implemented. + * @see https://man7.org/linux/man-pages/man3/fnmatch.3.html + */ int rl_fnmatch(const char *pattern, const char *string, int flags); #endif diff --git a/libretro-common/include/compat/getopt.h b/libretro-common/include/compat/getopt.h index 48603f0d22..3647f2e5c1 100644 --- a/libretro-common/include/compat/getopt.h +++ b/libretro-common/include/compat/getopt.h @@ -27,9 +27,17 @@ #include "../../../config.h" #endif -/* Custom implementation of the GNU getopt_long for portability. - * Not designed to be fully compatible, but compatible with - * the features RetroArch uses. */ +/** + * @file getopt.h + * + * Portable reimplementation of a subset of libc's \c getopt_long. + * Not designed to be fully compatible, + * but it's enough for RetroArch's purposes. + * + * If \c getopt_long is available (as determined by \c HAVE_GETOPT_LONG), it will be used instead. + * + * @see https://man7.org/linux/man-pages/man3/getopt.3.html + */ #ifdef HAVE_GETOPT_LONG #include diff --git a/libretro-common/include/compat/ifaddrs.h b/libretro-common/include/compat/ifaddrs.h index 2dc68487e7..43546742be 100644 --- a/libretro-common/include/compat/ifaddrs.h +++ b/libretro-common/include/compat/ifaddrs.h @@ -47,7 +47,20 @@ struct ifaddrs #include +/** + * Portable reimplementation of \c getifaddrs(). + * The original function will be used if it's available. + * + * @see https://man7.org/linux/man-pages/man3/getifaddrs.3.html + */ extern int getifaddrs(struct ifaddrs **ifap); + +/** + * Portable reimplementation of \c freeifaddrs(). + * The original function will be used if it's available. + * + * @see https://man7.org/linux/man-pages/man3/getifaddrs.3.html + */ extern void freeifaddrs(struct ifaddrs *ifa); #endif diff --git a/libretro-common/include/compat/intrinsics.h b/libretro-common/include/compat/intrinsics.h index ac490274e8..bc100f834e 100644 --- a/libretro-common/include/compat/intrinsics.h +++ b/libretro-common/include/compat/intrinsics.h @@ -38,7 +38,13 @@ RETRO_BEGIN_DECLS -/* Count Leading Zero, unsigned 16bit input value */ +/** + * Counts the leading zero bits in a \c uint16_t. + * Uses compiler intrinsics if available, or a standard C implementation if not. + * + * @param val Value to count leading zeroes in. + * @return Number of leading zeroes in \c val. + */ static INLINE unsigned compat_clz_u16(uint16_t val) { #if defined(__GNUC__) @@ -56,7 +62,13 @@ static INLINE unsigned compat_clz_u16(uint16_t val) #endif } -/* Count Trailing Zero */ +/** + * Counts the trailing zero bits in a \c uint16_t. + * Uses compiler intrinsics if available, or a standard C implementation if not. + * + * @param val Value to count trailing zeroes in. + * @return Number of trailing zeroes in \c val. + */ static INLINE int compat_ctz(unsigned x) { #if defined(__GNUC__) && !defined(RARCH_CONSOLE) diff --git a/libretro-common/include/compat/posix_string.h b/libretro-common/include/compat/posix_string.h index 47964b2a0f..6614818772 100644 --- a/libretro-common/include/compat/posix_string.h +++ b/libretro-common/include/compat/posix_string.h @@ -25,31 +25,64 @@ #include +/** + * @file posix_string.h + * + * Portable reimplementations of various string functions + * that are normally provided by libc or POSIX. + */ + #ifdef _MSC_VER #include #endif RETRO_BEGIN_DECLS -#ifdef _WIN32 +#if defined(_WIN32) || defined(DOXYGEN) #undef strtok_r #define strtok_r(str, delim, saveptr) retro_strtok_r__(str, delim, saveptr) +/** + * Portable reimplementation of \c strtok_r(). + * The original function will be used if it's available. + * + * @see https://man7.org/linux/man-pages/man3/strtok.3.html + */ char *strtok_r(char *str, const char *delim, char **saveptr); #endif -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(DOXYGEN) #undef strcasecmp #undef strdup + #define strcasecmp(a, b) retro_strcasecmp__(a, b) #define strdup(orig) retro_strdup__(orig) +/** + * Portable reimplementation of \c strcasecmp(). + * The original function will be used if it's available. + * + * @see https://man7.org/linux/man-pages/man3/strcasecmp.3.html + */ int strcasecmp(const char *a, const char *b); + +/** + * Portable reimplementation of \c strdup(). + * The original function will be used if it's available. + * + * @see https://man7.org/linux/man-pages/man3/strdup.3.html + */ char *strdup(const char *orig); /* isblank is available since MSVC 2013 */ #if _MSC_VER < 1800 #undef isblank #define isblank(c) retro_isblank__(c) +/** + * Portable reimplementation of \c isblank(). + * The original function will be used if it's available. + * + * @see https://en.cppreference.com/w/c/string/byte/isblank + */ int isblank(int c); #endif diff --git a/libretro-common/include/compat/strcasestr.h b/libretro-common/include/compat/strcasestr.h index 227e253e7b..27b229bc20 100644 --- a/libretro-common/include/compat/strcasestr.h +++ b/libretro-common/include/compat/strcasestr.h @@ -39,6 +39,14 @@ RETRO_BEGIN_DECLS * since we prefer to use the actual name. */ #define strcasestr(haystack, needle) strcasestr_retro__(haystack, needle) +/** + * Portable reimplementation of \c strcasestr(3). + * If the original function is available + * (as determined by the presence of \c HAVE_STRCASESTR), + * it will be used instead. + * + * @see https://man7.org/linux/man-pages/man3/strstr.3.html + */ char *strcasestr(const char *haystack, const char *needle); RETRO_END_DECLS diff --git a/libretro-common/include/compat/strl.h b/libretro-common/include/compat/strl.h index 5e7a892fcb..dfa4f10986 100644 --- a/libretro-common/include/compat/strl.h +++ b/libretro-common/include/compat/strl.h @@ -23,6 +23,15 @@ #ifndef __LIBRETRO_SDK_COMPAT_STRL_H #define __LIBRETRO_SDK_COMPAT_STRL_H +/** + * @file strl.h + * + * Portable implementation of \c strlcpy(3) and \c strlcat(3). + * If these functions are available on the target platform, + * then the originals should be imported instead. + * + * @see https://linux.die.net/man/3/strlcpy + */ #include #include @@ -47,11 +56,29 @@ RETRO_BEGIN_DECLS #define strlcat(dst, src, size) strlcat_retro__(dst, src, size) +/** + * @brief Portable implementation of \c strlcpy(3). + * @see https://linux.die.net/man/3/strlcpy + */ size_t strlcpy(char *dest, const char *source, size_t size); + +/** + * @brief Portable implementation of \c strlcat(3). + * @see https://linux.die.net/man/3/strlcpy + */ size_t strlcat(char *dest, const char *source, size_t size); #endif +/** + * A version of \c strndup(3) that guarantees the result will be null-terminated. + * + * @param s The string to duplicate. + * @param n The maximum number of characters to copy from \c s. + * The result will allocate one more byte than this value. + * @return Pointer to the cloned string. + * Must be freed with \c free(). + */ char *strldup(const char *s, size_t n); RETRO_END_DECLS diff --git a/libretro-common/include/dynamic/dylib.h b/libretro-common/include/dynamic/dylib.h index 6a52b95cd8..57bcd8cd95 100644 --- a/libretro-common/include/dynamic/dylib.h +++ b/libretro-common/include/dynamic/dylib.h @@ -39,30 +39,79 @@ RETRO_BEGIN_DECLS +/** + * Opaque handle to a dynamic library. + * @see dylib_load + */ typedef void *dylib_t; + +/** + * Opaque handle to a function exposed by a dynamic library. + * + * Should be cast to a known function pointer type before being used. + * @see dylib_proc + */ typedef void (*function_t)(void); #ifdef NEED_DYNAMIC /** - * dylib_load: - * @path : Path to libretro core library. + * Loads a dynamic library in a platform-independent manner. * - * Platform independent dylib loading. + * @param path Path to the library to load. + * May be either a complete path or a filename without an extension. + * If not a complete path, the operating system will search for a library by this name; + * details will depend on the platform. + * @note The returned library must be freed with \c dylib_close + * before the core or frontend exits. * - * @return Library handle on success, otherwise NULL. + * @return Handle to the loaded library, or \c NULL on failure. + * Upon failure, \c dylib_error may be used + * to retrieve a string describing the error. + * @see dylib_close + * @see dylib_error + * @see dylib_proc **/ dylib_t dylib_load(const char *path); /** - * dylib_close: - * @lib : Library handle. + * Frees the resources associated with a dynamic library. * - * Frees library handle. + * Any function pointers obtained from the library may become invalid, + * depending on whether the operating system manages reference counts to dynamic libraries. + * + * If there was an error closing the library, + * it will be reported by \c dylib_error. + * + * @param lib Handle to the library to close. + * Behavior is undefined if \c NULL. **/ void dylib_close(dylib_t lib); +/** + * Returns a string describing the most recent error that occurred + * within the other \c dylib functions. + * + * @return Pointer to the most recent error string, + * \c or NULL if there was no error. + * @warning The returned string is only valid + * until the next call to a \c dylib function. + * Additionally, the string is managed by the library + * and should not be modified or freed by the caller. + */ char *dylib_error(void); +/** + * Returns a pointer to a function exposed by a dynamic library. + * + * @param lib The library to get a function pointer from. + * @param proc The name of the function to get a pointer to. + * @return Pointer to the requested function, + * or \c NULL if there was an error. + * This must be cast to the correct function pointer type before being used. + * @warning The returned pointer is only valid for the lifetime of \c lib. + * Once \c lib is closed, all function pointers returned from it will be invalidated; + * using them is undefined behavior. + */ function_t dylib_proc(dylib_t lib, const char *proc); #endif diff --git a/libretro-common/include/encodings/base64.h b/libretro-common/include/encodings/base64.h index 13808511e1..859545535b 100644 --- a/libretro-common/include/encodings/base64.h +++ b/libretro-common/include/encodings/base64.h @@ -8,7 +8,29 @@ RETRO_BEGIN_DECLS +/** + * Encodes binary data into a \c NULL-terminated base64 string. + * + * @param binaryData The data to encode. + * Behavior is undefined if \c NULL. + * @param len The length of the data to encode. + * @param flen Pointer to the length of the returned string. + * @return Pointer to the base64-encoded string, or \c NULL on failure. + * The returned string is owned by the caller and must be released with \c free(). + * @see unbase64 + */ char* base64(const void* binaryData, int len, int *flen); + +/** + * Decodes a base64-encoded string into binary data. + * + * @param ascii The base64 string to decode, in ASCII format. + * @param len Length of the string to decode. + * @param flen Pointer to the length of the returned data. + * @return The decoded binary data, or \c NULL on failure. + * The returned buffer is owned by the caller and must be released with \c free(). + * @see base64 + */ unsigned char* unbase64(const char* ascii, int len, int *flen); RETRO_END_DECLS diff --git a/libretro-common/include/encodings/crc32.h b/libretro-common/include/encodings/crc32.h index 5f26cc72f2..8923c97820 100644 --- a/libretro-common/include/encodings/crc32.h +++ b/libretro-common/include/encodings/crc32.h @@ -30,6 +30,14 @@ RETRO_BEGIN_DECLS +/** + * Computes a buffer's CRC32 checksum. + * + * @param crc The initial CRC32 value. + * @param buf The buffer to calculate the CRC32 checksum of. + * @param len The length of the data in \c buf. + * @return The CRC32 checksum of the given buffer. + */ uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len); RETRO_END_DECLS diff --git a/libretro-common/include/features/features_cpu.h b/libretro-common/include/features/features_cpu.h index 130d748125..59796dae13 100644 --- a/libretro-common/include/features/features_cpu.h +++ b/libretro-common/include/features/features_cpu.h @@ -32,42 +32,62 @@ RETRO_BEGIN_DECLS /** - * cpu_features_get_perf_counter: + * Gets the time in ticks since some unspecified epoch. + * The notion of a "tick" varies per platform. * - * Gets performance counter. + * The epoch may change between devices or across reboots. * - * @return Performance counter. - **/ + * Suitable for use as a default implementation of \c retro_perf_callback::get_perf_counter, + * (or as a fallback by the core), + * although a frontend may provide its own implementation. + * + * @return The current time, in ticks. + * @see retro_perf_callback::get_perf_counter + */ retro_perf_tick_t cpu_features_get_perf_counter(void); /** - * cpu_features_get_time_usec: + * Gets the time in microseconds since some unspecified epoch. * - * Gets time in microseconds, from an undefined epoch. - * The epoch may change between computers or across reboots. + * The epoch may change between devices or across reboots. * - * @return Time in microseconds - **/ + * Suitable for use as a default implementation of \c retro_perf_callback::get_time_usec, + * (or as a fallback by the core), + * although a frontend may provide its own implementation. + * + * @return The current time, in microseconds. + * @see retro_perf_callback::get_time_usec + */ retro_time_t cpu_features_get_time_usec(void); /** - * cpu_features_get: + * Returns the available features (mostly SIMD extensions) + * supported by this CPU. * - * Gets CPU features. + * Suitable for use as a default implementation of \c retro_perf_callback::get_time_usec, + * (or as a fallback by the core), + * although a frontend may provide its own implementation. * * @return Bitmask of all CPU features available. - **/ + * @see RETRO_SIMD + * @see retro_perf_callback::get_cpu_features + */ uint64_t cpu_features_get(void); /** - * cpu_features_get_core_amount: - * - * Gets the amount of available CPU cores. - * - * @return Amount of CPU cores available. - **/ + * @return The number of CPU cores available, + * or 1 if the number of cores could not be determined. + */ unsigned cpu_features_get_core_amount(void); +/** + * Returns the name of the CPU model. + * + * @param[out] name Pointer to a buffer to store the name. + * Will be \c NULL-terminated. + * If \c NULL, this value will not be modified. + * @param len The amount of space available in \c name. + */ void cpu_features_get_model_name(char *name, int len); RETRO_END_DECLS diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index d34cbdb622..d9e7658b48 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1,8 +1,15 @@ -/* Copyright (C) 2010-2020 The RetroArch team +/*! + * libretro.h is a simple API that allows for the creation of games and emulators. * - * --------------------------------------------------------------------------------------- + * @file libretro.h + * @version 1 + * @author libretro + * @copyright Copyright (C) 2010-2023 The RetroArch team + * + * @paragraph LICENSE * The following license statement only applies to this libretro API header (libretro.h). - * --------------------------------------------------------------------------------------- + * + * Copyright (C) 2010-2023 The RetroArch team * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -77,78 +84,185 @@ extern "C" { # endif #endif -/* Used for checking API/ABI mismatches that can break libretro - * implementations. - * It is not incremented for compatible changes to the API. +/** + * The major version of the libretro API and ABI. + * Cores may support multiple versions, + * or they may reject cores with unsupported versions. + * It is only incremented for incompatible API/ABI changes; + * this generally implies a function was removed or changed, + * or that a \c struct had fields removed or changed. + * @note A design goal of libretro is to avoid having to increase this value at all costs. + * This is why there are APIs that are "extended" or "V2". */ #define RETRO_API_VERSION 1 -/* - * Libretro's fundamental device abstractions. +/** + * @defgroup RETRO_DEVICE Input Devices + * @brief Libretro's fundamental device abstractions. * - * Libretro's input system consists of some standardized device types, - * such as a joypad (with/without analog), mouse, keyboard, lightgun - * and a pointer. - * - * The functionality of these devices are fixed, and individual cores - * map their own concept of a controller to libretro's abstractions. - * This makes it possible for frontends to map the abstract types to a - * real input device, and not having to worry about binding input - * correctly to arbitrary controller layouts. + * Libretro's input system consists of abstractions over standard device types, + * such as a joypad (with or without analog), mouse, keyboard, light gun, or an abstract pointer. + * Instead of managing input devices themselves, + * cores need only to map their own concept of a controller to libretro's abstractions. + * This makes it possible for frontends to map the abstract types to a real input device + * without having to worry about the correct use of arbitrary (real) controller layouts. + * @{ */ #define RETRO_DEVICE_TYPE_SHIFT 8 #define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) + +/** + * Defines an ID for a subclass of a known device type. + * + * To define a subclass ID, use this macro like so: + * @code{c} + * #define RETRO_DEVICE_SUPER_SCOPE RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_LIGHTGUN, 1) + * #define RETRO_DEVICE_JUSTIFIER RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_LIGHTGUN, 2) + * @endcode + * + * Correct use of this macro allows a frontend to select a suitable physical device + * to map to the emulated device. + * + * @note Cores must use the base ID when polling for input, + * and frontends must only accept the base ID for this purpose. + * Polling for input using subclass IDs is reserved for future definition. + * + * @param base One of the \ref RETRO_DEVICE "base device types". + * @param id A unique ID, with respect to \c base. + * Must be a non-negative integer. + * @return A unique subclass ID. + * @see retro_controller_description + * @see retro_set_controller_port_device + */ #define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) -/* Input disabled. */ +/** + * @defgroup RETRO_DEVICE Input Device Classes + * @{ + */ + +/** + * Indicates no input. + * + * When provided as the \c device argument to \c retro_input_state_t, + * all other arguments are ignored and zero is returned. + * + * @see retro_input_state_t + */ #define RETRO_DEVICE_NONE 0 -/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo - * controller, but with additional L2/R2/L3/R3 buttons, similar to a - * PS1 DualShock. */ +/** + * An abstraction around a game controller, known as a "RetroPad". + * + * The RetroPad is modelled after a SNES controller, + * but with additional L2/R2/L3/R3 buttons + * (similar to a PlayStation controller). + * + * When provided as the \c device argument to \c retro_input_state_t, + * the \c id argument denotes the button (including D-Pad directions) to query. + * The result of said query will be 1 if the button is down, 0 if not. + * + * There is one exception; if \c RETRO_DEVICE_ID_JOYPAD_MASK is queried + * (and the frontend supports this query), + * the result will be a bitmask of all pressed buttons. + * + * @see retro_input_state_t + * @see RETRO_DEVICE_ANALOG + * @see RETRO_DEVICE_ID_JOYPAD + * @see RETRO_DEVICE_ID_JOYPAD_MASK + * @see RETRO_ENVIRONMENT_GET_INPUT_BITMASKS + */ #define RETRO_DEVICE_JOYPAD 1 -/* The mouse is a simple mouse, similar to Super Nintendo's mouse. - * X and Y coordinates are reported relatively to last poll (poll callback). - * It is up to the libretro implementation to keep track of where the mouse - * pointer is supposed to be on the screen. - * The frontend must make sure not to interfere with its own hardware - * mouse pointer. +/** + * An abstraction around a mouse, similar to the SNES Mouse but with more buttons. + * + * When provided as the \c device argument to \c retro_input_state_t, + * the \c id argument denotes the button or axis to query. + * For buttons, the result of said query + * will be 1 if the button is down or 0 if not. + * For mouse wheel axes, the result + * will be 1 if the wheel was rotated in that direction and 0 if not. + * For the mouse pointer axis, the result will be thee mouse's movement + * relative to the last poll. + * The core is responsible for tracking the mouse's position, + * and the frontend is responsible for preventing interference + * by the real hardware pointer (if applicable). + * + * @note This should only be used for cores that emulate mouse input, + * such as for home computers + * or consoles with mouse attachments. + * Cores that emulate light guns should use \c RETRO_DEVICE_LIGHTGUN, + * and cores that emulate touch screens should use \c RETRO_DEVICE_POINTER. + * + * @see RETRO_DEVICE_POINTER + * @see RETRO_DEVICE_LIGHTGUN */ #define RETRO_DEVICE_MOUSE 2 -/* KEYBOARD device lets one poll for raw key pressed. - * It is poll based, so input callback will return with the current - * pressed state. - * For event/text based keyboard input, see - * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. +/** + * An abstraction around a keyboard. + * + * When provided as the \c device argument to \c retro_input_state_t, + * the \c id argument denotes the key to poll. + * + * @note This should only be used for cores that emulate keyboard input, + * such as for home computers + * or consoles with keyboard attachments. + * Cores that emulate gamepads should use \c RETRO_DEVICE_JOYPAD or \c RETRO_DEVICE_ANALOG, + * and leave keyboard compatibility to the frontend. + * + * @see RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK + * @see retro_key */ #define RETRO_DEVICE_KEYBOARD 3 -/* LIGHTGUN device is similar to Guncon-2 for PlayStation 2. - * It reports X/Y coordinates in screen space (similar to the pointer) - * in the range [-0x8000, 0x7fff] in both axes, with zero being center and - * -0x8000 being out of bounds. - * As well as reporting on/off screen state. It features a trigger, - * start/select buttons, auxiliary action buttons and a - * directional pad. A forced off-screen shot can be requested for - * auto-reloading function in some games. +/** + * An abstraction around a light gun, simular to the PlayStation's Guncon. + * + * When provided as the \c device argument to \c retro_input_state_t, + * the \c id argument denotes one of several possible inputs. + * + * The gun's coordinates are reported in screen space (similar to the pointer) + * in the range of [-0x8000, 0x7fff]. + * Zero is the center of the game's screen + * and -0x8000 represents out-of-bounds. + * The trigger and various auxiliary buttons are also reported. + * + * @note A forced off-screen shot can be requested for auto-reloading + * function in some games. + * + * @see RETRO_DEVICE_POINTER */ #define RETRO_DEVICE_LIGHTGUN 4 -/* The ANALOG device is an extension to JOYPAD (RetroPad). - * Similar to DualShock2 it adds two analog sticks and all buttons can - * be analog. This is treated as a separate device type as it returns - * axis values in the full analog range of [-0x7fff, 0x7fff], - * although some devices may return -0x8000. - * Positive X axis is right. Positive Y axis is down. - * Buttons are returned in the range [0, 0x7fff]. - * Only use ANALOG type when polling for analog values. +/** + * An extension of the RetroPad that supports analog input. + * + * The analog RetroPad provides two virtual analog sticks (similar to DualShock controllers) + * and allows any button to be treated as analog (similar to Xbox shoulder triggers). + * + * When provided as the \c device argument to \c retro_input_state_t, + * the \c id argument denotes an analog axis or an analog button. + * + * Analog axes are reported in the range of [-0x8000, 0x7fff], + * with the X axis being positive towards the right + * and the Y axis being positive towards the bottom. + * + * Analog buttons are reported in the range of [0, 0x7fff], + * where 0 is unpressed and 0x7fff is fully pressed. + * + * @note Cores should only use this type if they need analog input. + * Otherwise, \c RETRO_DEVICE_JOYPAD should be used. + * @see RETRO_DEVICE_JOYPAD */ #define RETRO_DEVICE_ANALOG 5 -/* Abstracts the concept of a pointing mechanism, e.g. touch. +/** + * Input Device: Pointer. + * + * Abstracts the concept of a pointing mechanism, e.g. touch. * This allows libretro to query in absolute coordinates where on the * screen a mouse (or something similar) is being placed. * For a touch centric device, coordinates reported are the coordinates @@ -165,45 +279,109 @@ extern "C" { * game image, etc. * * To check if the pointer coordinates are valid (e.g. a touch display - * actually being touched), PRESSED returns 1 or 0. + * actually being touched), \c RETRO_DEVICE_ID_POINTER_PRESSED returns 1 or 0. * - * If using a mouse on a desktop, PRESSED will usually correspond to the - * left mouse button, but this is a frontend decision. - * PRESSED will only return 1 if the pointer is inside the game screen. + * If using a mouse on a desktop, \c RETRO_DEVICE_ID_POINTER_PRESSED will + * usually correspond to the left mouse button, but this is a frontend decision. + * \c RETRO_DEVICE_ID_POINTER_PRESSED will only return 1 if the pointer is + * inside the game screen. * * For multi-touch, the index variable can be used to successively query * more presses. - * If index = 0 returns true for _PRESSED, coordinates can be extracted - * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with + * If index = 0 returns true for \c _PRESSED, coordinates can be extracted + * with \c _X, \c _Y for index = 0. One can then query \c _PRESSED, \c _X, \c _Y with * index = 1, and so on. - * Eventually _PRESSED will return false for an index. No further presses - * are registered at this point. */ + * Eventually \c _PRESSED will return false for an index. No further presses + * are registered at this point. + * + * @see RETRO_DEVICE_MOUSE + * @see RETRO_DEVICE_ID_POINTER_X + * @see RETRO_DEVICE_ID_POINTER_Y + * @see RETRO_DEVICE_ID_POINTER_PRESSED + */ #define RETRO_DEVICE_POINTER 6 -/* Buttons for the RetroPad (JOYPAD). - * The placement of these is equivalent to placements on the - * Super Nintendo controller. - * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. - * Also used as id values for RETRO_DEVICE_INDEX_ANALOG_BUTTON */ +/** @} */ + +/** @defgroup RETRO_DEVICE_ID_JOYPAD RetroPad Input + * @brief Digital buttons for the RetroPad. + * + * Button placement is comparable to that of a SNES controller, + * combined with the shoulder buttons of a PlayStation controller. + * These values can also be used for the \c id field of \c RETRO_DEVICE_INDEX_ANALOG_BUTTON + * to represent analog buttons (usually shoulder triggers). + * @{ + */ + +/** The equivalent of the SNES controller's south face button. */ #define RETRO_DEVICE_ID_JOYPAD_B 0 + +/** The equivalent of the SNES controller's west face button. */ #define RETRO_DEVICE_ID_JOYPAD_Y 1 + +/** The equivalent of the SNES controller's left-center button. */ #define RETRO_DEVICE_ID_JOYPAD_SELECT 2 + +/** The equivalent of the SNES controller's right-center button. */ #define RETRO_DEVICE_ID_JOYPAD_START 3 + +/** Up on the RetroPad's D-pad. */ #define RETRO_DEVICE_ID_JOYPAD_UP 4 + +/** Down on the RetroPad's D-pad. */ #define RETRO_DEVICE_ID_JOYPAD_DOWN 5 + +/** Left on the RetroPad's D-pad. */ #define RETRO_DEVICE_ID_JOYPAD_LEFT 6 + +/** Right on the RetroPad's D-pad. */ #define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 + +/** The equivalent of the SNES controller's east face button. */ #define RETRO_DEVICE_ID_JOYPAD_A 8 + +/** The equivalent of the SNES controller's north face button. */ #define RETRO_DEVICE_ID_JOYPAD_X 9 + +/** The equivalent of the SNES controller's left shoulder button. */ #define RETRO_DEVICE_ID_JOYPAD_L 10 + +/** The equivalent of the SNES controller's right shoulder button. */ #define RETRO_DEVICE_ID_JOYPAD_R 11 + +/** The equivalent of the PlayStation's rear left shoulder button. */ #define RETRO_DEVICE_ID_JOYPAD_L2 12 + +/** The equivalent of the PlayStation's rear right shoulder button. */ #define RETRO_DEVICE_ID_JOYPAD_R2 13 + +/** + * The equivalent of the PlayStation's left analog stick button, + * although the actual button need not be in this position. + */ #define RETRO_DEVICE_ID_JOYPAD_L3 14 + +/** + * The equivalent of the PlayStation's right analog stick button, + * although the actual button need not be in this position. + */ #define RETRO_DEVICE_ID_JOYPAD_R3 15 +/** + * Represents a bitmask that describes the state of all \c RETRO_DEVICE_ID_JOYPAD button constants, + * rather than the state of a single button. + * + * @see RETRO_ENVIRONMENT_GET_INPUT_BITMASKS + * @see RETRO_DEVICE_JOYPAD + */ #define RETRO_DEVICE_ID_JOYPAD_MASK 256 +/** @} */ + +/** @defgroup RETRO_DEVICE_ID_ANALOG Analog RetroPad Input + * @{ + */ + /* Index / Id values for ANALOG device. */ #define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 #define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 @@ -211,6 +389,8 @@ extern "C" { #define RETRO_DEVICE_ID_ANALOG_X 0 #define RETRO_DEVICE_ID_ANALOG_Y 1 +/** @} */ + /* Id values for MOUSE. */ #define RETRO_DEVICE_ID_MOUSE_X 0 #define RETRO_DEVICE_ID_MOUSE_Y 1 @@ -252,11 +432,16 @@ extern "C" { #define RETRO_DEVICE_ID_POINTER_PRESSED 2 #define RETRO_DEVICE_ID_POINTER_COUNT 3 +/** @} */ + /* Returned from retro_get_region(). */ #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 -/* Id values for LANGUAGE */ +/** + * Identifiers for supported languages. + * @see RETRO_ENVIRONMENT_GET_LANGUAGE + */ enum retro_language { RETRO_LANGUAGE_ENGLISH = 0, @@ -294,10 +479,14 @@ enum retro_language RETRO_LANGUAGE_BELARUSIAN = 32, RETRO_LANGUAGE_LAST, - /* Ensure sizeof(enum) == sizeof(int) */ + /** Defined to ensure that sizeof(retro_language) == sizeof(int). Do not use. */ RETRO_LANGUAGE_DUMMY = INT_MAX }; +/** @defgroup RETRO_MEMORY Memory Types + * @{ + */ + /* Passed to retro_get_memory_data/size(). * If the memory type doesn't apply to the * implementation NULL/0 can be returned. @@ -322,6 +511,8 @@ enum retro_language /* Video ram lets a frontend peek into a game systems video RAM (VRAM). */ #define RETRO_MEMORY_VIDEO_RAM 3 +/** @} */ + /* Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. */ enum retro_key { @@ -494,914 +685,1467 @@ enum retro_mod RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ }; -/* If set, this call is not part of the public libretro API yet. It can - * change or be removed at any time. */ +/** + * @defgroup RETRO_ENVIRONMENT Environment Callbacks + * @{ + */ + +/** + * This bit indicates that the associated environment call is experimental, + * and may be changed or removed in the future. + * Frontends should mask out this bit before handling the environment call. + */ #define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 -/* Environment callback to be used internally in frontend. */ + +/** Frontend-internal environment callbacks should include this bit. */ #define RETRO_ENVIRONMENT_PRIVATE 0x20000 /* Environment commands. */ -#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- - * Sets screen rotation of graphics. - * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, - * 270 degrees counter-clockwise respectively. - */ -#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- - * NOTE: As of 2019 this callback is considered deprecated in favor of - * using core options to manage overscan in a more nuanced, core-specific way. - * - * Boolean value whether or not the implementation should use overscan, - * or crop away overscan. - */ -#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- - * Boolean value whether or not frontend supports frame duping, - * passing NULL to video frame callback. - */ +/** + * Requests the frontend to set the screen rotation. + * + * @param[in] data const unsigned*. + * Valid values are 0, 1, 2, and 3. + * These numbers respectively set the screen rotation to 0, 90, 180, and 270 degrees counter-clockwise. + * @returns \c true if the screen rotation was set successfully. + */ +#define RETRO_ENVIRONMENT_SET_ROTATION 1 - /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), - * and reserved to avoid possible ABI clash. - */ +/** + * Queries whether the core should use overscan or not. + * + * @param[out] data bool*. + * Set to \c true if the core should use overscan, + * \c false if it should be cropped away. + * @returns \c true if the environment call is available. + * Does \em not indicate whether overscan should be used. + * @deprecated As of 2019 this callback is considered deprecated in favor of + * using core options to manage overscan in a more nuanced, core-specific way. + */ +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 -#define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- - * Sets a message to be displayed in implementation-specific manner - * for a certain amount of 'frames'. - * Should not be used for trivial messages, which should simply be - * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a - * fallback, stderr). - */ -#define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- - * Requests the frontend to shutdown. - * Should only be used if game has a specific - * way to shutdown the game from a menu item or similar. - */ +/** + * Queries whether the frontend supports frame duping, + * in the form of passing \c NULL to the video frame callback. + * + * @param[out] data bool*. + * Set to \c true if the frontend supports frame duping. + * @returns \c true if the environment call is available. + * @see retro_video_refresh_t + */ +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 + +/* + * Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), + * and reserved to avoid possible ABI clash. + */ + +/** + * @brief Displays a user-facing message for a short time. + * + * Use this callback to convey important status messages, + * such as errors or the result of long-running operations. + * For trivial messages or logging, use \c RETRO_ENVIRONMENT_GET_LOG_INTERFACE or \c stderr. + * + * \code{.c} + * void set_message_example(void) + * { + * struct retro_message msg; + * msg.frames = 60 * 5; // 5 seconds + * msg.msg = "Hello world!"; + * + * environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg); + * } + * \endcode + * + * @deprecated Prefer using \c RETRO_ENVIRONMENT_SET_MESSAGE_EXT for new code, + * as it offers more features. + * Only use this environment call for compatibility with older cores or frontends. + * + * @param[in] data const struct retro_message*. + * Details about the message to show to the user. + * Behavior is undefined if NULL. + * @returns \c true if the environment call is available. + * @see retro_message + * @see RETRO_ENVIRONMENT_GET_LOG_INTERFACE + * @see RETRO_ENVIRONMENT_SET_MESSAGE_EXT + * @see RETRO_ENVIRONMENT_SET_MESSAGE + * @see RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION + * @note The frontend must make its own copy of the message and the underlying string. + */ +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 + +/** + * Requests the frontend to shutdown the core. + * Should only be used if the core can exit on its own, + * such as from a menu item in a game + * or an emulated power-off in an emulator. + * + * @param data Ignored. + * @returns \c true if the environment call is available. + */ +#define RETRO_ENVIRONMENT_SHUTDOWN 7 + +/** + * Gives a hint to the frontend of how demanding this core is on the system. + * For example, reporting a level of 2 means that + * this implementation should run decently on frontends + * of level 2 and above. + * + * It can be used by the frontend to potentially warn + * about too demanding implementations. + * + * The levels are "floating". + * + * This function can be called on a per-game basis, + * as a core may have different demands for different games or settings. + * If called, it should be called in retro_load_game(). + * @param[in] data const unsigned*. +*/ #define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 - /* const unsigned * -- - * Gives a hint to the frontend how demanding this implementation - * is on a system. E.g. reporting a level of 2 means - * this implementation should run decently on all frontends - * of level 2 and up. - * - * It can be used by the frontend to potentially warn - * about too demanding implementations. - * - * The levels are "floating". - * - * This function can be called on a per-game basis, - * as certain games an implementation can play might be - * particularly demanding. - * If called, it should be called in retro_load_game(). - */ + +/** + * Returns the path to the frontend's system directory, + * which can be used to store system-specific configuration + * such as BIOS files or cached data. + * + * @param[out] data const char**. + * Pointer to the \c char* in which the system directory will be saved. + * The string is managed by the frontend and must not be modified or freed by the core. + * May be \c NULL if no system directory is defined, + * in which case the core should find an alternative directory. + * @return \c true if the environment call is available, + * even if the value returned in \c data is NULL. + * @note Historically, some cores would use this folder for save data such as memory cards or SRAM. + * This is now discouraged in favor of \c RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY. + * @see RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY + */ #define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 - /* const char ** -- - * Returns the "system" directory of the frontend. - * This directory can be used to store system specific - * content such as BIOSes, configuration data, etc. - * The returned value can be NULL. - * If so, no such directory is defined, - * and it's up to the implementation to find a suitable directory. - * - * NOTE: Some cores used this folder also for "save" data such as - * memory cards, etc, for lack of a better place to put it. - * This is now discouraged, and if possible, cores should try to - * use the new GET_SAVE_DIRECTORY. - */ + +/** + * Sets the internal pixel format used by the frontend for rendering. + * The default pixel format is \c RETRO_PIXEL_FORMAT_0RGB1555 for compatibility reasons, + * although it's considered deprecated and shouldn't be used by new code. + * + * @param[in] data const enum retro_pixel_format *. + * Pointer to the pixel format to use. + * @returns \c true if the pixel format was set successfully, + * \c false if it's not supported or this callback is unavailable. + * @note This function should be called inside \c retro_load_game() + * or retro_get_system_av_info(). + * @see retro_pixel_format + */ #define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 - /* const enum retro_pixel_format * -- - * Sets the internal pixel format used by the implementation. - * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. - * This pixel format however, is deprecated (see enum retro_pixel_format). - * If the call returns false, the frontend does not support this pixel - * format. - * - * This function should be called inside retro_load_game() or - * retro_get_system_av_info(). - */ + +/** + * Sets an array of input descriptors for the frontend + * to present to the user for configuring the core's controls. + * + * This function can be called at any time, + * preferably early in the core's life cycle. + * Ideally, no later than \c retro_load_game(). + * + * @param[in] data const struct retro_input_descriptor *. + * An array of input descriptors terminated by one whose + * \c retro_input_descriptor::description field is set to \c NULL. + * Behavior is undefined if \c NULL. + * @return \c true if the environment call is recognized. + * @see retro_input_descriptor + */ #define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 - /* const struct retro_input_descriptor * -- - * Sets an array of retro_input_descriptors. - * It is up to the frontend to present this in a usable way. - * The array is terminated by retro_input_descriptor::description - * being set to NULL. - * This function can be called at any time, but it is recommended - * to call it as early as possible. - */ + +/** + * Sets a callback function used to notify the core about keyboard events. + * This should only be used for cores that specifically need keyboard input, + * such as for home computer emulators or games with text entry. + * + * @param[in] data const struct retro_keyboard_callback *. + * Pointer to the callback function. + * Behavior is undefined if NULL. + * @return \c true if the environment call is recognized. + * @see retro_keyboard_callback + * @see retro_key + */ #define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 - /* const struct retro_keyboard_callback * -- - * Sets a callback function used to notify core about keyboard events. - */ + +/** + * Sets an interface that the frontend can use to insert and remove disks + * from the emulated console's disk drive. + * Can be used for optical disks, floppy disks, or any other game storage medium + * that can be swapped at runtime. + * + * This is intended for multi-disk games that expect the player + * to manually swap disks at certain points in the game. + * + * @deprecated Prefer using \c RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE + * over this environment call, as it supports additional features. + * Only use this callback to maintain compatibility + * with older cores or frontends. + * + * @param[in] data const struct retro_disk_control_callback *. + * Pointer to the callback functions to use. + * May be \c NULL, in which case the existing disk callback is deregistered. + * @return \c true if this environment call is available, + * even if \c data is \c NULL. + * @see retro_disk_control_callback + * @see RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE + */ #define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 - /* const struct retro_disk_control_callback * -- - * Sets an interface which frontend can use to eject and insert - * disk images. - * This is used for games which consist of multiple images and - * must be manually swapped out by the user (e.g. PSX). - */ + +/** + * Requests that a frontend enable a particular hardware rendering API. + * + * If successful, the frontend will create a context (and other related resources) + * that the core can use for rendering. + * The framebuffer will be at least as large as + * the maximum dimensions provided in retro_get_system_av_info. + * + * @param[in, out] data struct retro_hw_render_callback *. + * Pointer to the hardware render callback struct. + * Used to define callbacks for the hardware-rendering life cycle, + * as well as to request a particular rendering API. + * @return \c true if the environment call is recognized + * and the requested rendering API is supported. + * \c false if \c data is \c NULL + * or the frontend can't provide the requested rendering API. + * @see retro_hw_render_callback + * @see retro_video_refresh_t + * @see RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER + * @note Should be called in retro_load_game(). + * @note If HW rendering is used, pass only \c RETRO_HW_FRAME_BUFFER_VALID or + * \c NULL to retro_video_refresh_t. + */ #define RETRO_ENVIRONMENT_SET_HW_RENDER 14 - /* struct retro_hw_render_callback * -- - * Sets an interface to let a libretro core render with - * hardware acceleration. - * Should be called in retro_load_game(). - * If successful, libretro cores will be able to render to a - * frontend-provided framebuffer. - * The size of this framebuffer will be at least as large as - * max_width/max_height provided in get_av_info(). - * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or - * NULL to retro_video_refresh_t. - */ + +/** + * Retrieves a core option's value from the frontend. + * \c retro_variable::key should be set to an option key + * that was previously set in \c RETRO_ENVIRONMENT_SET_VARIABLES + * (or a similar environment call). + * + * @param[in,out] data struct retro_variable *. + * Pointer to a single \c retro_variable struct. + * See the documentation for \c retro_variable for details + * on which fields are set by the frontend or core. + * May be \c NULL. + * @returns \c true if the environment call is available, + * even if \c data is \c NULL or the key it specifies is not found. + * @note Passing \c NULL in to \c data can be useful to + * test for support of this environment call without looking up any variables. + * @see retro_variable + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * @see RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE + */ #define RETRO_ENVIRONMENT_GET_VARIABLE 15 - /* struct retro_variable * -- - * Interface to acquire user-defined information from environment - * that cannot feasibly be supported in a multi-system way. - * 'key' should be set to a key which has already been set by - * SET_VARIABLES. - * 'data' will be set to a value or NULL. - */ + +/** + * Notifies the frontend of the core's available options. + * + * The core may check these options later using \c RETRO_ENVIRONMENT_GET_VARIABLE. + * The frontend may also present these options to the user + * in its own configuration UI. + * + * This should be called the first time as early as possible, + * ideally in \c retro_set_environment. + * The core may later call this function again + * to communicate updated options to the frontend, + * but the number of core options must not change. + * + * Here's an example that sets two options. + * + * @code + * void set_variables_example(void) + * { + * struct retro_variable options[] = { + * { "foo_speedhack", "Speed hack; false|true" }, // false by default + * { "foo_displayscale", "Display scale factor; 1|2|3|4" }, // 1 by default + * { NULL, NULL }, + * }; + * + * environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, &options); + * } + * @endcode + * + * The possible values will generally be displayed and stored as-is by the frontend. + * + * @deprecated Prefer using \c RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 for new code, + * as it offers more features such as categories and translation. + * Only use this environment call to maintain compatibility + * with older frontends or cores. + * @note Keep the available options (and their possible values) as low as possible; + * it should be feasible to cycle through them without a keyboard. + * @param[in] data const struct retro_variable *. + * Pointer to an array of \c retro_variable structs that define available core options, + * terminated by a { NULL, NULL } element. + * The frontend must maintain its own copy of this array. + * + * @returns \c true if the environment call is available, + * even if \c data is NULL. + * @see retro_variable + * @see RETRO_ENVIRONMENT_GET_VARIABLE + * @see RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + */ #define RETRO_ENVIRONMENT_SET_VARIABLES 16 - /* const struct retro_variable * -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should be called the first time as early as - * possible (ideally in retro_set_environment). - * Afterward it may be called again for the core to communicate - * updated options to the frontend, but the number of core - * options must not change from the number in the initial call. - * - * 'data' points to an array of retro_variable structs - * terminated by a { NULL, NULL } element. - * retro_variable::key should be namespaced to not collide - * with other implementations' keys. E.g. A core called - * 'foo' should use keys named as 'foo_option'. - * retro_variable::value should contain a human readable - * description of the key as well as a '|' delimited list - * of expected values. - * - * The number of possible options should be very limited, - * i.e. it should be feasible to cycle through options - * without a keyboard. - * - * First entry should be treated as a default. - * - * Example entry: - * { "foo_option", "Speed hack coprocessor X; false|true" } - * - * Text before first ';' is description. This ';' must be - * followed by a space, and followed by a list of possible - * values split up with '|'. - * - * Only strings are operated on. The possible values will - * generally be displayed and stored as-is by the frontend. - */ + +/** + * Queries whether at least one core option was updated by the frontend + * since the last call to \ref RETRO_ENVIRONMENT_GET_VARIABLE. + * This typically means that the user opened the core options menu and made some changes. + * + * Cores usually call this each frame before the core's main emulation logic. + * Specific options can then be queried with \ref RETRO_ENVIRONMENT_GET_VARIABLE. + * + * @param[out] data bool *. + * Set to \c true if at least one core option was updated + * since the last call to \ref RETRO_ENVIRONMENT_GET_VARIABLE. + * Behavior is undefined if this pointer is \c NULL. + * @returns \c true if the environment call is available. + * @see RETRO_ENVIRONMENT_GET_VARIABLE + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + */ #define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 - /* bool * -- - * Result is set to true if some variables are updated by - * frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. - * Variables should be queried with GET_VARIABLE. - */ + +/** + * Notifies the frontend that this core can run without loading any content, + * such as when emulating a console that has built-in software. + * When a core is loaded without content, + * \c retro_load_game receives an argument of NULL. + * This should be called within \c retro_set_environment() only. + * + * @param[in] data const bool *. + * Pointer to a single \c bool that indicates whether this frontend can run without content. + * Can point to a value of \c false but this isn't necessary, + * as contentless support is opt-in. + * The behavior is undefined if \c data is NULL. + * @returns \c true if the environment call is available. + * @see retro_load_game + */ #define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 - /* const bool * -- - * If true, the libretro implementation supports calls to - * retro_load_game() with NULL as argument. - * Used by cores which can run without particular game data. - * This should be called within retro_set_environment() only. - */ + +/** + * Retrieves the absolute path from which this core was loaded. + * Useful when loading assets from paths relative to the core, + * as is sometimes the case when using RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME. + * + * @param[out] data const char **. + * Pointer to a string in which the core's path will be saved. + * The string is managed by the frontend and must not be modified or freed by the core. + * May be \c NULL if the core is statically linked to the frontend + * or if the core's path otherwise cannot be determined. + * Behavior is undefined if \c data is NULL. + * @returns \c true if the environment call is available. + */ #define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 - /* const char ** -- - * Retrieves the absolute path from where this libretro - * implementation was loaded. - * NULL is returned if the libretro was loaded statically - * (i.e. linked statically to frontend), or if the path cannot be - * determined. - * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can - * be loaded without ugly hacks. - */ - /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. - * It was not used by any known core at the time, - * and was removed from the API. */ +/* Environment call 20 was an obsolete version of SET_AUDIO_CALLBACK. + * It was not used by any known core at the time, and was removed from the API. + * The number 20 is reserved to prevent ABI clashes. + */ + +/** + * Sets a callback that notifies the core of how much time has passed + * since the last iteration of retro_run. + * If the frontend is not running the core in real time + * (e.g. it's frame-stepping or running in slow motion), + * then the reference value will be provided to the callback instead. + * + * @param[in] data const struct retro_frame_time_callback *. + * Pointer to a single \c retro_frame_time_callback struct. + * Behavior is undefined if \c data is NULL. + * @returns \c true if the environment call is available. + * @note Frontends may disable this environment call in certain situations. + * It will return \c false in those cases. + * @see retro_frame_time_callback + */ #define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 - /* const struct retro_frame_time_callback * -- - * Lets the core know how much time has passed since last - * invocation of retro_run(). - * The frontend can tamper with the timing to fake fast-forward, - * slow-motion, frame stepping, etc. - * In this case the delta time will use the reference value - * in frame_time_callback.. - */ + +/** + * Registers a set of functions that the frontend can use + * to tell the core it's ready for audio output. + * + * It is intended for games that feature asynchronous audio. + * It should not be used for emulators unless their audio is asynchronous. + * + * + * The callback only notifies about writability; the libretro core still + * has to call the normal audio callbacks + * to write audio. The audio callbacks must be called from within the + * notification callback. + * The amount of audio data to write is up to the core. + * Generally, the audio callback will be called continously in a loop. + * + * A frontend may disable this callback in certain situations. + * The core must be able to render audio with the "normal" interface. + * + * @param[in] data const struct retro_audio_callback *. + * Pointer to a set of functions that the frontend will call to notify the core + * when it's ready to receive audio data. + * May be \c NULL, in which case the frontend will return + * whether this environment callback is available. + * @return \c true if this environment call is available, + * even if \c data is \c NULL. + * @warning The provided callbacks can be invoked from any thread, + * so their implementations \em must be thread-safe. + * @note If a core uses this callback, + * it should also use RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK. + * @see retro_audio_callback + * @see retro_audio_sample_t + * @see retro_audio_sample_batch_t + * @see RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK + */ #define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 - /* const struct retro_audio_callback * -- - * Sets an interface which is used to notify a libretro core about audio - * being available for writing. - * The callback can be called from any thread, so a core using this must - * have a thread safe audio implementation. - * It is intended for games where audio and video are completely - * asynchronous and audio can be generated on the fly. - * This interface is not recommended for use with emulators which have - * highly synchronous audio. - * - * The callback only notifies about writability; the libretro core still - * has to call the normal audio callbacks - * to write audio. The audio callbacks must be called from within the - * notification callback. - * The amount of audio data to write is up to the implementation. - * Generally, the audio callback will be called continously in a loop. - * - * Due to thread safety guarantees and lack of sync between audio and - * video, a frontend can selectively disallow this interface based on - * internal configuration. A core using this interface must also - * implement the "normal" audio interface. - * - * A libretro core using SET_AUDIO_CALLBACK should also make use of - * SET_FRAME_TIME_CALLBACK. - */ + +/** + * Gets an interface that a core can use to access a controller's rumble motors. + * + * The interface supports two independently-controlled motors, + * one strong and one weak. + * + * Should be called from either \c retro_init() or \c retro_load_game(), + * but not from \c retro_set_environment(). + * + * @param[out] data struct retro_rumble_interface *. + * Pointer to the interface struct. + * Behavior is undefined if \c NULL. + * @returns \c true if the environment call is available, + * even if the current device doesn't support vibration. + * @see retro_rumble_interface + * @defgroup GET_RUMBLE_INTERFACE Rumble Interface + */ #define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 - /* struct retro_rumble_interface * -- - * Gets an interface which is used by a libretro core to set - * state of rumble motors in controllers. - * A strong and weak motor is supported, and they can be - * controlled indepedently. - * Should be called from either retro_init() or retro_load_game(). - * Should not be called from retro_set_environment(). - * Returns false if rumble functionality is unavailable. - */ + +/** + * Returns the frontend's supported input device types. + * + * The supported device types are returned as a bitmask, + * with each value of \ref RETRO_DEVICE corresponding to a bit. + * + * Should only be called in \c retro_run(). + * + * @code + * #define REQUIRED_DEVICES ((1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG)) + * void get_input_device_capabilities_example(void) + * { + * uint64_t capabilities; + * environ_cb(RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES, &capabilities); + * if ((capabilities & REQUIRED_DEVICES) == REQUIRED_DEVICES) + * printf("Joypad and analog device types are supported"); + * } + * @endcode + * + * @param[out] data uint64_t *. + * Pointer to a bitmask of supported input device types. + * If the frontend supports a particular \c RETRO_DEVICE_* type, + * then the bit (1 << RETRO_DEVICE_*) will be set. + * + * Each bit represents a \c RETRO_DEVICE constant, + * e.g. bit 1 represents \c RETRO_DEVICE_JOYPAD, + * bit 2 represents \c RETRO_DEVICE_MOUSE, and so on. + * + * Bits that do not correspond to known device types will be set to zero + * and are reserved for future use. + * + * Behavior is undefined if \c NULL. + * @returns \c true if the environment call is available. + * @note If the frontend supports multiple input drivers, + * availability of this environment call (and the reported capabilities) + * may depend on the active driver. + * @see RETRO_DEVICE + */ #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 - /* uint64_t * -- - * Gets a bitmask telling which device type are expected to be - * handled properly in a call to retro_input_state_t. - * Devices which are not handled or recognized always return - * 0 in retro_input_state_t. - * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). - * Should only be called in retro_run(). - */ + +/** + * Returns an interface that the core can use to access and configure available sensors, + * such as an accelerometer or gyroscope. + * + * @param[out] data struct retro_sensor_interface *. + * Pointer to the sensor interface that the frontend will populate. + * Behavior is undefined if is \c NULL. + * @returns \c true if the environment call is available, + * even if the device doesn't have any supported sensors. + * @see retro_sensor_interface + * @see retro_sensor_action + * @see RETRO_SENSOR + * @addtogroup RETRO_SENSOR + */ #define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_sensor_interface * -- - * Gets access to the sensor interface. - * The purpose of this interface is to allow - * setting state related to sensors such as polling rate, - * enabling/disable it entirely, etc. - * Reading sensor state is done via the normal - * input_state_callback API. - */ + +/** + * Gets an interface to the device's video camera. + * + * The frontend delivers new video frames via a user-defined callback + * that runs in the same thread as \c retro_run(). + * Should be called in \c retro_load_game(). + * + * @param[in,out] data struct retro_camera_callback *. + * Pointer to the camera driver interface. + * Some fields in the struct must be filled in by the core, + * others are provided by the frontend. + * Behavior is undefined if \c NULL. + * @returns \c true if this environment call is available, + * even if an actual camera isn't. + * @note This API only supports one video camera at a time. + * If the device provides multiple cameras (e.g. inner/outer cameras on a phone), + * the frontend will choose one to use. + * @see retro_camera_callback + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + */ #define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_camera_callback * -- - * Gets an interface to a video camera driver. - * A libretro core can use this interface to get access to a - * video camera. - * New video frames are delivered in a callback in same - * thread as retro_run(). - * - * GET_CAMERA_INTERFACE should be called in retro_load_game(). - * - * Depending on the camera implementation used, camera frames - * will be delivered as a raw framebuffer, - * or as an OpenGL texture directly. - * - * The core has to tell the frontend here which types of - * buffers can be handled properly. - * An OpenGL texture can only be handled when using a - * libretro GL core (SET_HW_RENDER). - * It is recommended to use a libretro GL core when - * using camera interface. - * - * The camera is not started automatically. The retrieved start/stop - * functions must be used to explicitly - * start and stop the camera driver. - */ + +/** + * Gets an interface that the core can use for cross-platform logging. + * Certain platforms don't have a console or stderr, + * or they have their own preferred logging methods. + * The frontend itself may also display log output. + * + * @attention This should not be used for information that the player must immediately see, + * such as major errors or warnings. + * In most cases, this is best for information that will help you (the developer) + * identify problems when debugging or providing support. + * Unless a core or frontend is intended for advanced users, + * the player might not check (or even know about) their logs. + * + * @param[out] data struct retro_log_callback *. + * Pointer to the callback where the function pointer will be saved. + * Behavior is undefined if \c data is NULL. + * @returns \c true if the environment call is available. + * @see retro_log_callback + * @note Cores can fall back to \c stderr if this interface is not available. + */ #define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 - /* struct retro_log_callback * -- - * Gets an interface for logging. This is useful for - * logging in a cross-platform way - * as certain platforms cannot use stderr for logging. - * It also allows the frontend to - * show logging information in a more suitable way. - * If this interface is not used, libretro cores should - * log to stderr as desired. - */ + +/** + * Returns an interface that the core can use for profiling code + * and to access performance-related information. + * + * This callback supports performance counters, a high-resolution timer, + * and listing available CPU features (mostly SIMD instructions). + * + * @param[out] data struct retro_perf_callback *. + * Pointer to the callback interface. + * Behavior is undefined if \c NULL. + * @returns \c true if the environment call is available. + * @see retro_perf_callback + */ #define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 - /* struct retro_perf_callback * -- - * Gets an interface for performance counters. This is useful - * for performance logging in a cross-platform way and for detecting - * architecture-specific features, such as SIMD support. - */ + +/** + * Returns an interface that the core can use to retrieve the device's location, + * including its current latitude and longitude. + * + * @param[out] data struct retro_location_callback *. + * Pointer to the callback interface. + * Behavior is undefined if \c NULL. + * @return \c true if the environment call is available, + * even if there's no location information available. + * @see retro_location_callback + */ #define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 - /* struct retro_location_callback * -- - * Gets access to the location interface. - * The purpose of this interface is to be able to retrieve - * location-based information from the host device, - * such as current latitude / longitude. - */ -#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ + +/** + * @deprecated An obsolete alias to \c RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY kept for compatibility. + * @see RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY + **/ +#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 + +/** + * Returns the frontend's "core assets" directory, + * which can be used to store assets that the core needs + * such as art assets or level data. + * + * @param[out] data const char **. + * Pointer to a string in which the core assets directory will be saved. + * This string is managed by the frontend and must not be modified or freed by the core. + * May be \c NULL if no core assets directory is defined, + * in which case the core should find an alternative directory. + * Behavior is undefined if \c data is NULL. + * @returns \c true if the environment call is available, + * even if the value returned in \c data is NULL. + */ #define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 - /* const char ** -- - * Returns the "core assets" directory of the frontend. - * This directory can be used to store specific assets that the - * core relies upon, such as art assets, - * input data, etc etc. - * The returned value can be NULL. - * If so, no such directory is defined, - * and it's up to the implementation to find a suitable directory. - */ + +/** + * Returns the frontend's save data directory, if available. + * This directory should be used to store game-specific save data, + * including memory card images. + * + * Although libretro provides an interface for cores to expose SRAM to the frontend, + * not all cores can support it correctly. + * In this case, cores should use this environment callback + * to save their game data to disk manually. + * + * Cores that use this environment callback + * should flush their save data to disk periodically and when unloading. + * + * @param[out] data const char **. + * Pointer to the string in which the save data directory will be saved. + * This string is managed by the frontend and must not be modified or freed by the core. + * May return \c NULL if no save data directory is defined. + * Behavior is undefined if \c data is NULL. + * @returns \c true if the environment call is available, + * even if the value returned in \c data is NULL. + * @note Early libretro cores used \c RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY for save data. + * This is still supported for backwards compatibility, + * but new cores should use this environment call instead. + * \c RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY should be used for game-agnostic data + * such as BIOS files or core-specific configuration. + * @note The returned directory may or may not be the same + * as the one used for \c retro_get_memory_data. + * + * @see retro_get_memory_data + * @see RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY + */ #define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 - /* const char ** -- - * Returns the "save" directory of the frontend, unless there is no - * save directory available. The save directory should be used to - * store SRAM, memory cards, high scores, etc, if the libretro core - * cannot use the regular memory interface (retro_get_memory_data()). - * - * If the frontend cannot designate a save directory, it will return - * NULL to indicate that the core should attempt to operate without a - * save directory set. - * - * NOTE: early libretro cores used the system directory for save - * files. Cores that need to be backwards-compatible can still check - * GET_SYSTEM_DIRECTORY. - */ + +/** + * Sets new video and audio parameters for the core. + * This can only be called from within retro_run. + * + * This environment call may entail a full reinitialization of the frontend's audio/video drivers, + * hence it should \em only be used if the core needs to make drastic changes + * to audio/video parameters. + * + * This environment call should \em not be used when: + *
    + *
  • Changing the emulated system's internal resolution, + * within the limits defined by the existing values of \c max_width and \c max_height. + * Use \c RETRO_ENVIRONMENT_SET_GEOMETRY instead, + * and adjust \c retro_get_system_av_info to account fo + * supported scale factors and screen layouts + * when computing \c max_width and \c max_height. + * Only use this environment call if \c max_width or \c max_height needs to increase. + *
  • Adjusting the screen's aspect ratio, + * e.g. when changing the layout of the screen(s). + * Use \c RETRO_ENVIRONMENT_SET_GEOMETRY or \c RETRO_ENVIRONMENT_SET_ROTATION instead. + *
+ * + * The frontend will reinitialize its audio and video drivers within this callback; + * after that happens, audio and video callbacks will target the newly-initialized driver, + * even within the same \c retro_run call. + * + * This callback makes it possible to support configurable resolutions + * while avoiding the need to compute the "worst case" values of \c max_width and \c max_height. + * + * @param[in] data const struct retro_system_av_info *. + * Pointer to the new video and audio parameters that the frontend should adopt. + * @returns \c true if the environment call is available + * and the new av_info struct was accepted. + * \c false if the environment call is unavailable or \c data is NULL. + * @see retro_system_av_info + * @see RETRO_ENVIRONMENT_SET_GEOMETRY + */ #define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 - /* const struct retro_system_av_info * -- - * Sets a new av_info structure. This can only be called from - * within retro_run(). - * This should *only* be used if the core is completely altering the - * internal resolutions, aspect ratios, timings, sampling rate, etc. - * Calling this can require a full reinitialization of video/audio - * drivers in the frontend, - * - * so it is important to call it very sparingly, and usually only with - * the users explicit consent. - * An eventual driver reinitialize will happen so that video and - * audio callbacks - * happening after this call within the same retro_run() call will - * target the newly initialized driver. - * - * This callback makes it possible to support configurable resolutions - * in games, which can be useful to - * avoid setting the "worst case" in max_width/max_height. - * - * ***HIGHLY RECOMMENDED*** Do not call this callback every time - * resolution changes in an emulator core if it's - * expected to be a temporary change, for the reasons of possible - * driver reinitialization. - * This call is not a free pass for not trying to provide - * correct values in retro_get_system_av_info(). If you need to change - * things like aspect ratio or nominal width/height, - * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant - * of SET_SYSTEM_AV_INFO. - * - * If this returns false, the frontend does not acknowledge a - * changed av_info struct. - */ + +/** + * Provides an interface that a frontend can use + * to get function pointers from the core. + * + * This allows cores to define their own extensions to the libretro API, + * or to expose implementations of a frontend's libretro extensions. + * + * @param[in] data const struct retro_get_proc_address_interface *. + * Pointer to the interface that the frontend can use to get function pointers from the core. + * The frontend must maintain its own copy of this interface. + * @returns \c true if the environment call is available + * and the returned interface was accepted. + * @note The provided interface may be called at any time, + * even before this environment call returns. + * @note Extensions should be prefixed with the name of the frontend or core that defines them. + * For example, a frontend named "foo" that defines a debugging extension + * should expect the core to define functions prefixed with "foo_debug_". + * @warning If a core wants to use this environment call, + * it \em must do so from within \c retro_set_environment(). + * @see retro_get_proc_address_interface + */ #define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 - /* const struct retro_get_proc_address_interface * -- - * Allows a libretro core to announce support for the - * get_proc_address() interface. - * This interface allows for a standard way to extend libretro where - * use of environment calls are too indirect, - * e.g. for cases where the frontend wants to call directly into the core. - * - * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK - * **MUST** be called from within retro_set_environment(). - */ + +/** + * Registers a core's ability to handle "subsystems", + * which are secondary platforms that augment a core's primary emulated hardware. + * + * A core doesn't need to emulate a secondary platform + * in order to use it as a subsystem; + * as long as it can load a secondary file for some practical use, + * then this environment call is most likely suitable. + * + * Possible use cases of a subsystem include: + * + * \li Installing software onto an emulated console's internal storage, + * such as the Nintendo DSi. + * \li Emulating accessories that are used to support another console's games, + * such as the Super Game Boy or the N64 Transfer Pak. + * \li Inserting a secondary ROM into a console + * that features multiple cartridge ports, + * such as the Nintendo DS's Slot-2. + * \li Loading a save data file created and used by another core. + * + * Cores should \em not use subsystems for: + * + * \li Emulators that support multiple "primary" platforms, + * such as a Game Boy/Game Boy Advance core + * or a Sega Genesis/Sega CD/32X core. + * Use \c retro_system_content_info_override, \c retro_system_info, + * and/or runtime detection instead. + * \li Selecting different memory card images. + * Use dynamically-populated core options instead. + * \li Different variants of a single console, + * such the Game Boy vs. the Game Boy Color. + * Use core options or runtime detection instead. + * \li Games that span multiple disks. + * Use \c RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE + * and m3u-formatted playlists instead. + * \li Console system files (BIOS, firmware, etc.). + * Use \c RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY + * and a common naming convention instead. + * + * When the frontend loads a game via a subsystem, + * it must call \c retro_load_game_special() instead of \c retro_load_game(). + * + * @param[in] data const struct retro_subsystem_info *. + * Pointer to an array of subsystem descriptors, + * terminated by a zeroed-out \c retro_subsystem_info struct. + * The frontend should maintain its own copy + * of this array and the strings within it. + * Behavior is undefined if \c NULL. + * @returns \c true if this environment call is available. + * @note This environment call \em must be called from within \c retro_set_environment(), + * as frontends may need the registered information before loading a game. + * @see retro_subsystem_info + * @see retro_load_game_special + */ #define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 - /* const struct retro_subsystem_info * -- - * This environment call introduces the concept of libretro "subsystems". - * A subsystem is a variant of a libretro core which supports - * different kinds of games. - * The purpose of this is to support e.g. emulators which might - * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. - * It can also be used to pick among subsystems in an explicit way - * if the libretro implementation is a multi-system emulator itself. - * - * Loading a game via a subsystem is done with retro_load_game_special(), - * and this environment call allows a libretro core to expose which - * subsystems are supported for use with retro_load_game_special(). - * A core passes an array of retro_game_special_info which is terminated - * with a zeroed out retro_game_special_info struct. - * - * If a core wants to use this functionality, SET_SUBSYSTEM_INFO - * **MUST** be called from within retro_set_environment(). - */ + +/** + * Declares one or more types of controllers supported by this core. + * The frontend may then allow the player to select one of these controllers in its menu. + * + * Many consoles had controllers that came in different versions, + * were extensible with peripherals, + * or could be held in multiple ways; + * this environment call can be used to represent these differences + * and adjust the core's behavior to match. + * + * Possible use cases include: + * + * \li Supporting different classes of a single controller that supported their own sets of games. + * For example, the SNES had two different lightguns (the Super Scope and the Justifier) + * whose games were incompatible with each other. + * \li Representing a platform's alternative controllers. + * For example, several platforms had music/rhythm games that included controllers + * shaped like musical instruments. + * \li Representing variants of a standard controller with additional inputs. + * For example, numerous consoles in the 90's introduced 6-button controllers for fighting games, + * steering wheels for racing games, + * or analog sticks for 3D platformers. + * \li Representing add-ons for consoles or standard controllers. + * For example, the 3DS had a Circle Pad Pro attachment that added a second analog stick. + * \li Selecting different configurations for a single controller. + * For example, the Wii Remote could be held sideways like a traditional game pad + * or in one hand like a wand. + * \li Providing multiple ways to simulate the experience of using a particular controller. + * For example, the Game Boy Advance featured several games + * with motion or light sensors in their cartridges; + * a core could provide controller configurations + * that allow emulating the sensors with either analog axes + * or with their host device's sensors. + * + * Should be called in retro_load_game. + * The frontend must maintain its own copy of the provided array, + * including all strings and subobjects. + * A core may exclude certain controllers for known incompatible games. + * + * When the frontend changes the active device for a particular port, + * it must call \c retro_set_controller_port_device() with that port's index + * and one of the IDs defined in its retro_controller_info::types field. + * + * Input ports are generally associated with different players + * (and the frontend's UI may reflect this with "Player 1" labels), + * but this is not required. + * Some games use multiple controllers for a single player, + * or some cores may use port indexes to represent an emulated console's + * alternative input peripherals. + * + * @param[in] data const struct retro_controller_info *. + * Pointer to an array of controller types defined by this core, + * terminated by a zeroed-out \c retro_controller_info. + * Each element of this array represents a controller port on the emulated device. + * Behavior is undefined if \c NULL. + * @returns \c true if this environment call is available. + * @see retro_controller_info + * @see retro_set_controller_port_device + * @see RETRO_DEVICE_SUBCLASS + */ #define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 - /* const struct retro_controller_info * -- - * This environment call lets a libretro core tell the frontend - * which controller subclasses are recognized in calls to - * retro_set_controller_port_device(). - * - * Some emulators such as Super Nintendo support multiple lightgun - * types which must be specifically selected from. It is therefore - * sometimes necessary for a frontend to be able to tell the core - * about a special kind of input device which is not specifcally - * provided by the Libretro API. - * - * In order for a frontend to understand the workings of those devices, - * they must be defined as a specialized subclass of the generic device - * types already defined in the libretro API. - * - * The core must pass an array of const struct retro_controller_info which - * is terminated with a blanked out struct. Each element of the - * retro_controller_info struct corresponds to the ascending port index - * that is passed to retro_set_controller_port_device() when that function - * is called to indicate to the core that the frontend has changed the - * active device subclass. SEE ALSO: retro_set_controller_port_device() - * - * The ascending input port indexes provided by the core in the struct - * are generally presented by frontends as ascending User # or Player #, - * such as Player 1, Player 2, Player 3, etc. Which device subclasses are - * supported can vary per input port. - * - * The first inner element of each entry in the retro_controller_info array - * is a retro_controller_description struct that specifies the names and - * codes of all device subclasses that are available for the corresponding - * User or Player, beginning with the generic Libretro device that the - * subclasses are derived from. The second inner element of each entry is the - * total number of subclasses that are listed in the retro_controller_description. - * - * NOTE: Even if special device types are set in the libretro core, - * libretro should only poll input based on the base input device types. - */ + +/** + * Notifies the frontend of the address spaces used by the core's emulated hardware, + * and of the memory maps within these spaces. + * This can be used by the frontend to provide cheats, achievements, or debugging capabilities. + * Should only be used by emulators, as it makes little sense for game engines. + * + * @note Cores should also expose these address spaces + * through retro_get_memory_data and \c retro_get_memory_size if applicable; + * this environment call is not intended to replace those two functions, + * as the emulated hardware may feature memory regions outside of its own address space + * that are nevertheless useful for the frontend. + * + * @param[in] data const struct retro_memory_map *. + * Pointer to a single memory-map listing. + * The frontend must maintain its own copy of this object and its contents, + * including strings and nested objects. + * Behavior is undefined if \c NULL. + * @returns \c true if this environment call is available. + * @see retro_memory_map + * @see retro_get_memory_data + * @see retro_memory_descriptor + */ #define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_memory_map * -- - * This environment call lets a libretro core tell the frontend - * about the memory maps this core emulates. - * This can be used to implement, for example, cheats in a core-agnostic way. - * - * Should only be used by emulators; it doesn't make much sense for - * anything else. - * It is recommended to expose all relevant pointers through - * retro_get_memory_* as well. - */ + +/** + * Resizes the viewport without reinitializing the video driver. + * + * Similar to \c RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, + * but any changes that would require video reinitialization will not be performed. + * Can only be called from within \c retro_run(). + * + * This environment call allows a core to revise the size of the viewport at will, + * which can be useful for emulated platforms that support dynamic resolution changes + * or for cores that support multiple screen layouts. + * + * A frontend must guarantee that this environment call completes in + * constant time. + * + * @param[in] data const struct retro_game_geometry *. + * Pointer to the new video parameters that the frontend should adopt. + * \c retro_game_geometry::max_width and \c retro_game_geometry::max_height + * will be ignored. + * Behavior is undefined if \c data is NULL. + * @return \c true if the environment call is available. + * @see RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO + */ #define RETRO_ENVIRONMENT_SET_GEOMETRY 37 - /* const struct retro_game_geometry * -- - * This environment call is similar to SET_SYSTEM_AV_INFO for changing - * video parameters, but provides a guarantee that drivers will not be - * reinitialized. - * This can only be called from within retro_run(). - * - * The purpose of this call is to allow a core to alter nominal - * width/heights as well as aspect ratios on-the-fly, which can be - * useful for some emulators to change in run-time. - * - * max_width/max_height arguments are ignored and cannot be changed - * with this call as this could potentially require a reinitialization or a - * non-constant time operation. - * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. - * - * A frontend must guarantee that this environment call completes in - * constant time. - */ + +/** + * Returns the name of the user, if possible. + * This callback is suitable for cores that offer personalization, + * such as online facilities or user profiles on the emulated system. + * @param[out] data const char **. + * Pointer to the user name string. + * May be \c NULL, in which case the core should use a default name. + * The returned pointer is owned by the frontend and must not be modified or freed by the core. + * Behavior is undefined if \c NULL. + * @returns \c true if the environment call is available, + * even if the frontend couldn't provide a name. + */ #define RETRO_ENVIRONMENT_GET_USERNAME 38 - /* const char ** - * Returns the specified username of the frontend, if specified by the user. - * This username can be used as a nickname for a core that has online facilities - * or any other mode where personalization of the user is desirable. - * The returned value can be NULL. - * If this environ callback is used by a core that requires a valid username, - * a default username should be specified by the core. - */ + +/** + * Returns the frontend's configured language. + * It can be used to localize the core's UI, + * or to customize the emulated firmware if applicable. + * + * @param[out] data retro_language *. + * Pointer to the language identifier. + * Behavior is undefined if \c NULL. + * @returns \c true if the environment call is available. + * @note The returned language may not be the same as the operating system's language. + * Cores should fall back to the operating system's language (or to English) + * if the environment call is unavailable or the returned language is unsupported. + * @see retro_language + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL + */ #define RETRO_ENVIRONMENT_GET_LANGUAGE 39 - /* unsigned * -- - * Returns the specified language of the frontend, if specified by the user. - * It can be used by the core for localization purposes. - */ + +/** + * Returns a frontend-managed framebuffer + * that the core may render directly into + * + * This environment call is provided as an optimization + * for cores that use software rendering + * (i.e. that don't use \refitem RETRO_ENVIRONMENT_SET_HW_RENDER "a graphics hardware API"); + * specifically, the intended use case is to allow a core + * to render directly into frontend-managed video memory, + * avoiding the bandwidth use that copying a whole framebuffer from core to video memory entails. + * + * Must be called every frame if used, + * as this may return a different framebuffer each frame + * (e.g. for swap chains). + * However, a core may render to a different buffer even if this call succeeds. + * + * @param[in,out] data struct retro_framebuffer *. + * Pointer to a frontend's frame buffer and accompanying data. + * Some fields are set by the core, others are set by the frontend. + * Only guaranteed to be valid for the duration of the current \c retro_run call, + * and must not be used afterwards. + * Behavior is undefined if \c NULL. + * @return \c true if the environment call was recognized + * and the framebuffer was successfully returned. + * @see retro_framebuffer + */ #define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_framebuffer * -- - * Returns a preallocated framebuffer which the core can use for rendering - * the frame into when not using SET_HW_RENDER. - * The framebuffer returned from this call must not be used - * after the current call to retro_run() returns. - * - * The goal of this call is to allow zero-copy behavior where a core - * can render directly into video memory, avoiding extra bandwidth cost by copying - * memory from core to video memory. - * - * If this call succeeds and the core renders into it, - * the framebuffer pointer and pitch can be passed to retro_video_refresh_t. - * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used, - * the core must pass the exact - * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER; - * i.e. passing a pointer which is offset from the - * buffer is undefined. The width, height and pitch parameters - * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER. - * - * It is possible for a frontend to return a different pixel format - * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend - * needs to perform conversion. - * - * It is still valid for a core to render to a different buffer - * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds. - * - * A frontend must make sure that the pointer obtained from this function is - * writeable (and readable). - */ + +/** + * Returns an interface for accessing the data of specific rendering APIs. + * Not all hardware rendering APIs support or need this. + * + * The details of these interfaces are specific to each rendering API. + * + * @note \c retro_hw_render_callback::context_reset must be called by the frontend + * before this environment call can be used. + * Additionally, the contents of the returned interface are invalidated + * after \c retro_hw_render_callback::context_destroyed has been called. + * @param[out] data const struct retro_hw_render_interface **. + * The render interface for the currently-enabled hardware rendering API, if any. + * The frontend will store a pointer to the interface at the address provided here. + * The returned interface is owned by the frontend and must not be modified or freed by the core. + * Behavior is undefined if \c NULL. + * @return \c true if this environment call is available, + * the active graphics API has a libretro rendering interface, + * and the frontend is able to return said interface. + * \c false otherwise. + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + * @see retro_hw_render_interface + * @note Since not every libretro-supported hardware rendering API + * has a \c retro_hw_render_interface implementation, + * a result of \c false is not necessarily an error. + */ #define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_interface ** -- - * Returns an API specific rendering interface for accessing API specific data. - * Not all HW rendering APIs support or need this. - * The contents of the returned pointer is specific to the rendering API - * being used. See the various headers like libretro_vulkan.h, etc. - * - * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. - * Similarly, after context_destroyed callback returns, - * the contents of the HW_RENDER_INTERFACE are invalidated. - */ + +/** + * Explicitly notifies the frontend of whether this core supports achievements. + * The core must expose its emulated address space via + * \c retro_get_memory_data or \c RETRO_ENVIRONMENT_GET_MEMORY_MAPS. + * Must be called before the first call to retro_run. + * + * If \ref retro_get_memory_data returns a valid address + * but this environment call is not used, + * the frontend (at its discretion) may or may not opt in the core to its achievements support. + * whether this core is opted in to the frontend's achievement support + * is left to the frontend's discretion. + * @param[in] data const bool *. + * Pointer to a single \c bool that indicates whether this core supports achievements. + * Behavior is undefined if \c data is NULL. + * @returns \c true if the environment call is available. + * @see RETRO_ENVIRONMENT_SET_MEMORY_MAPS + * @see retro_get_memory_data + */ #define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const bool * -- - * If true, the libretro implementation supports achievements - * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS - * or via retro_get_memory_data/retro_get_memory_size. - * - * This must be called before the first call to retro_run. - */ + +/** + * Defines an interface that the frontend can use + * to ask the core for the parameters it needs for a hardware rendering context. + * The exact semantics depend on \ref RETRO_ENVIRONMENT_SET_HW_RENDER "the active rendering API". + * Will be used some time after \c RETRO_ENVIRONMENT_SET_HW_RENDER is called, + * but before \c retro_hw_render_callback::context_reset is called. + * + * @param[in] data const struct retro_hw_render_context_negotiation_interface *. + * Pointer to the context negotiation interface. + * Will be populated by the frontend. + * Behavior is undefined if \c NULL. + * @return \c true if this environment call is supported, + * even if the current graphics API doesn't use + * a context negotiation interface (in which case the argument is ignored). + * @see retro_hw_render_context_negotiation_interface + * @see RETRO_ENVIRONMENT_GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + */ #define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_context_negotiation_interface * -- - * Sets an interface which lets the libretro core negotiate with frontend how a context is created. - * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. - * This interface will be used when the frontend is trying to create a HW rendering context, - * so it will be used after SET_HW_RENDER, but before the context_reset callback. - */ + +/** + * Notifies the frontend of any quirks associated with serialization. + * + * Should be set in either \c retro_init or \c retro_load_game, but not both. + * @param[in, out] data uint64_t *. + * Pointer to the core's serialization quirks. + * The frontend will set the flags of the quirks it supports + * and clear the flags of those it doesn't. + * Behavior is undefined if \c NULL. + * @return \c true if this environment call is supported. + * @see retro_serialize + * @see retro_unserialize + * @see RETRO_SERIALIZATION_QUIRK + */ #define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44 - /* uint64_t * -- - * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't - * recognize or support. Should be set in either retro_init or retro_load_game, but not both. - */ + +/** + * The frontend will try to use a "shared" context when setting up a hardware context. + * Mostly applicable to OpenGL. + * + * In order for this to have any effect, + * the core must call \c RETRO_ENVIRONMENT_SET_HW_RENDER at some point + * if it hasn't already. + * + * @param data Ignored. + * @returns \c true if the environment call is available + * and the frontend supports shared hardware contexts. + */ #define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* N/A (null) * -- - * The frontend will try to use a 'shared' hardware context (mostly applicable - * to OpenGL) when a hardware context is being set up. - * - * Returns true if the frontend supports shared hardware contexts and false - * if the frontend does not support shared hardware contexts. - * - * This will do nothing on its own until SET_HW_RENDER env callbacks are - * being used. - */ + +/** + * Returns an interface that the core can use to access the file system. + * Should be called as early as possible. + * + * @param[in,out] data struct retro_vfs_interface_info *. + * Information about the desired VFS interface, + * as well as the interface itself. + * Behavior is undefined if \c NULL. + * @return \c true if this environment call is available + * and the frontend can provide a VFS interface of the requested version or newer. + * @see retro_vfs_interface_info + * @see file_path + * @see retro_dirent + * @see file_stream + */ #define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_vfs_interface_info * -- - * Gets access to the VFS interface. - * VFS presence needs to be queried prior to load_game or any - * get_system/save/other_directory being called to let front end know - * core supports VFS before it starts handing out paths. - * It is recomended to do so in retro_set_environment - */ + +/** + * Returns an interface that the core can use + * to set the state of any accessible device LEDs. + * + * @param[out] data struct retro_led_interface *. + * Pointer to the LED interface that the frontend will populate. + * May be \c NULL, in which case the frontend will only return + * whether this environment callback is available. + * @returns \c true if the environment call is available, + * even if \c data is \c NULL + * or no LEDs are accessible. + * @see retro_led_interface + */ #define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_led_interface * -- - * Gets an interface which is used by a libretro core to set - * state of LEDs. - */ + +/** + * Returns hints about certain steps that the core may skip for this frame. + * + * A frontend may not need a core to generate audio or video in certain situations; + * this environment call sets a bitmask that indicates + * which steps the core may skip for this frame. + * + * This can be used to increase performance for some frontend features. + * + * @note Emulation accuracy should not be compromised; + * for example, if a core emulates a platform that supports display capture + * (i.e. looking at its own VRAM), then it should perform its rendering as normal + * unless it can prove that the emulated game is not using display capture. + * + * @param[out] data retro_av_enable_flags *. + * Pointer to the bitmask of steps that the frontend will skip. + * Other bits are set to zero and are reserved for future use. + * If \c NULL, the frontend will only return whether this environment callback is available. + * @returns \c true if the environment call is available, + * regardless of the value output to \c data. + * If \c false, the core should assume that the frontend will not skip any steps. + * @see retro_av_enable_flags + */ #define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* int * -- - * Tells the core if the frontend wants audio or video. - * If disabled, the frontend will discard the audio or video, - * so the core may decide to skip generating a frame or generating audio. - * This is mainly used for increasing performance. - * Bit 0 (value 1): Enable Video - * Bit 1 (value 2): Enable Audio - * Bit 2 (value 4): Use Fast Savestates. - * Bit 3 (value 8): Hard Disable Audio - * Other bits are reserved for future use and will default to zero. - * If video is disabled: - * * The frontend wants the core to not generate any video, - * including presenting frames via hardware acceleration. - * * The frontend's video frame callback will do nothing. - * * After running the frame, the video output of the next frame should be - * no different than if video was enabled, and saving and loading state - * should have no issues. - * If audio is disabled: - * * The frontend wants the core to not generate any audio. - * * The frontend's audio callbacks will do nothing. - * * After running the frame, the audio output of the next frame should be - * no different than if audio was enabled, and saving and loading state - * should have no issues. - * Fast Savestates: - * * Guaranteed to be created by the same binary that will load them. - * * Will not be written to or read from the disk. - * * Suggest that the core assumes loading state will succeed. - * * Suggest that the core updates its memory buffers in-place if possible. - * * Suggest that the core skips clearing memory. - * * Suggest that the core skips resetting the system. - * * Suggest that the core may skip validation steps. - * Hard Disable Audio: - * * Used for a secondary core when running ahead. - * * Indicates that the frontend will never need audio from the core. - * * Suggests that the core may stop synthesizing audio, but this should not - * compromise emulation accuracy. - * * Audio output for the next frame does not matter, and the frontend will - * never need an accurate audio state in the future. - * * State will never be saved when using Hard Disable Audio. - */ + +/** + * Gets an interface that the core can use for raw MIDI I/O. + * + * @param[out] data struct retro_midi_interface **. + * Pointer to the MIDI interface. + * May be \c NULL. + * @return \c true if the environment call is available, + * even if \c data is \c NULL. + * @see retro_midi_interface + */ #define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_midi_interface ** -- - * Returns a MIDI interface that can be used for raw data I/O. - */ +/** + * Asks the frontend if it's currently in fast-forward mode. + * @param[out] data bool *. + * Set to \c true if the frontend is currently fast-forwarding its main loop. + * Behavior is undefined if \c data is NULL. + * @returns \c true if this environment call is available, + * regardless of the value returned in \c data. + * + * @see RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE + */ #define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* bool * -- - * Boolean value that indicates whether or not the frontend is in - * fastforwarding mode. - */ +/** + * Returns the refresh rate the frontend is targeting, in Hz. + * The intended use case is for the core to use the result to select an ideal refresh rate. + * + * @param[out] data float *. + * Pointer to the \c float in which the frontend will store its target refresh rate. + * Behavior is undefined if \c data is NULL. + * @return \c true if this environment call is available, + * regardless of the value returned in \c data. +*/ #define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* float * -- - * Float value that lets us know what target refresh rate - * is curently in use by the frontend. - * - * The core can use the returned value to set an ideal - * refresh rate/framerate. - */ +/** + * Returns whether the frontend can return the state of all buttons at once as a bitmask, + * rather than requiring a series of individual calls to \c retro_input_state_t. + * + * If this callback returns \c true, + * you can get the state of all buttons by passing \c RETRO_DEVICE_ID_JOYPAD_MASK + * as the \c id parameter to \c retro_input_state_t. + * Bit #N represents the RETRO_DEVICE_ID_JOYPAD constant of value N, + * e.g. (1 << RETRO_DEVICE_ID_JOYPAD_A) represents the A button. + * + * @param data Ignored. + * @returns \c true if the frontend can report the complete digital joypad state as a bitmask. + * @see retro_input_state_t + * @see RETRO_DEVICE_JOYPAD + * @see RETRO_DEVICE_ID_JOYPAD_MASK + */ #define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* bool * -- - * Boolean value that indicates whether or not the frontend supports - * input bitmasks being returned by retro_input_state_t. The advantage - * of this is that retro_input_state_t has to be only called once to - * grab all button states instead of multiple times. - * - * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id' - * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD). - * It will return a bitmask of all the digital buttons. - */ +/** + * Returns the version of the core options API supported by the frontend. + * + * Over the years, libretro has used several interfaces + * for allowing cores to define customizable options. + * \ref SET_CORE_OPTIONS_V2 "Version 2 of the interface" + * is currently preferred due to its extra features, + * but cores and frontends should strive to support + * versions \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS "1" + * and \ref RETRO_ENVIRONMENT_SET_VARIABLES "0" as well. + * This environment call provides the information that cores need for that purpose. + * + * If this environment call returns \c false, + * then the core should assume version 0 of the core options API. + * + * @param[out] data unsigned *. + * Pointer to the integer that will store the frontend's + * supported core options API version. + * Behavior is undefined if \c NULL. + * @returns \c true if the environment call is available, + * \c false otherwise. + * @see RETRO_ENVIRONMENT_SET_VARIABLES + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + */ #define RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION 52 - /* unsigned * -- - * Unsigned value is the API version number of the core options - * interface supported by the frontend. If callback return false, - * API version is assumed to be 0. - * - * In legacy code, core options are set by passing an array of - * retro_variable structs to RETRO_ENVIRONMENT_SET_VARIABLES. - * This may be still be done regardless of the core options - * interface version. - * - * If version is >= 1 however, core options may instead be set by - * passing an array of retro_core_option_definition structs to - * RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of - * retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. - * This allows the core to additionally set option sublabel information - * and/or provide localisation support. - * - * If version is >= 2, core options may instead be set by passing - * a retro_core_options_v2 struct to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, - * or an array of retro_core_options_v2 structs to - * RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL. This allows the core - * to additionally set optional core option category information - * for frontends with core option category support. - */ +/** + * @copybrief RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * + * @deprecated This environment call has been superseded + * by RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, + * which supports categorizing options into groups. + * This environment call should only be used to maintain compatibility + * with older cores and frontends. + * + * This environment call is intended to replace \c RETRO_ENVIRONMENT_SET_VARIABLES, + * and should only be called if \c RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION + * returns an API version of at least 1. + * + * This should be called the first time as early as possible, + * ideally in \c retro_set_environment (but \c retro_load_game is acceptable). + * It may then be called again later to update + * the core's options and their associated values, + * as long as the number of options doesn't change + * from the number given in the first call. + * + * The core can retrieve option values at any time with \c RETRO_ENVIRONMENT_GET_VARIABLE. + * If a saved value for a core option doesn't match the option definition's values, + * the frontend may treat it as incorrect and revert to the default. + * + * Core options and their values are usually defined in a large static array, + * but they may be generated at runtime based on the loaded game or system state. + * Here are some use cases for that: + * + * @li Selecting a particular file from one of the + * \ref RETRO_ENVIRONMENT_GET_ASSET_DIRECTORY "frontend's" + * \ref RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY "content" + * \ref RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY "directories", + * such as a memory card image or figurine data file. + * @li Excluding options that are not relevant to the current game, + * for cores that define a large number of possible options. + * @li Choosing a default value at runtime for a specific game, + * such as a BIOS file whose region matches that of the loaded content. + * + * @note A guiding principle of libretro's API design is that + * all common interactions (gameplay, menu navigation, etc.) + * should be possible without a keyboard. + * This implies that cores should keep the number of options and values + * as low as possible. + * + * Example entry: + * @code + * { + * "foo_option", + * "Speed hack coprocessor X", + * "Provides increased performance at the expense of reduced accuracy", + * { + * { "false", NULL }, + * { "true", NULL }, + * { "unstable", "Turbo (Unstable)" }, + * { NULL, NULL }, + * }, + * "false" + * } + * @endcode + * + * @param[in] data const struct retro_core_option_definition *. + * Pointer to one or more core option definitions, + * terminated by a \ref retro_core_option_definition whose values are all zero. + * May be \c NULL, in which case the frontend will remove all existing core options. + * The frontend must maintain its own copy of this object, + * including all strings and subobjects. + * @return \c true if this environment call is available. + * + * @see retro_core_option_definition + * @see RETRO_ENVIRONMENT_GET_VARIABLE + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL + */ #define RETRO_ENVIRONMENT_SET_CORE_OPTIONS 53 - /* const struct retro_core_option_definition ** -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION - * returns an API version of >= 1. - * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. - * This should be called the first time as early as - * possible (ideally in retro_set_environment). - * Afterwards it may be called again for the core to communicate - * updated options to the frontend, but the number of core - * options must not change from the number in the initial call. - * - * 'data' points to an array of retro_core_option_definition structs - * terminated by a { NULL, NULL, NULL, {{0}}, NULL } element. - * retro_core_option_definition::key should be namespaced to not collide - * with other implementations' keys. e.g. A core called - * 'foo' should use keys named as 'foo_option'. - * retro_core_option_definition::desc should contain a human readable - * description of the key. - * retro_core_option_definition::info should contain any additional human - * readable information text that a typical user may need to - * understand the functionality of the option. - * retro_core_option_definition::values is an array of retro_core_option_value - * structs terminated by a { NULL, NULL } element. - * > retro_core_option_definition::values[index].value is an expected option - * value. - * > retro_core_option_definition::values[index].label is a human readable - * label used when displaying the value on screen. If NULL, - * the value itself is used. - * retro_core_option_definition::default_value is the default core option - * setting. It must match one of the expected option values in the - * retro_core_option_definition::values array. If it does not, or the - * default value is NULL, the first entry in the - * retro_core_option_definition::values array is treated as the default. - * - * The number of possible option values should be very limited, - * and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX. - * i.e. it should be feasible to cycle through options - * without a keyboard. - * - * Example entry: - * { - * "foo_option", - * "Speed hack coprocessor X", - * "Provides increased performance at the expense of reduced accuracy", - * { - * { "false", NULL }, - * { "true", NULL }, - * { "unstable", "Turbo (Unstable)" }, - * { NULL, NULL }, - * }, - * "false" - * } - * - * Only strings are operated on. The possible values will - * generally be displayed and stored as-is by the frontend. - */ +/** + * A variant of \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS + * that supports internationalization. + * + * @deprecated This environment call has been superseded + * by \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL, + * which supports categorizing options into groups + * (plus translating the groups themselves). + * Only use this environment call to maintain compatibility + * with older cores and frontends. + * + * This should be called instead of \c RETRO_ENVIRONMENT_SET_CORE_OPTIONS + * if the core provides translations for its options. + * General use is largely the same, + * but see \ref retro_core_options_intl for some important details. + * + * @param[in] data const struct retro_core_options_intl *. + * Pointer to a core's option values and their translations. + * @see retro_core_options_intl + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS + */ #define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL 54 - /* const struct retro_core_options_intl * -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION - * returns an API version of >= 1. - * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. - * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS. - * This should be called the first time as early as - * possible (ideally in retro_set_environment). - * Afterwards it may be called again for the core to communicate - * updated options to the frontend, but the number of core - * options must not change from the number in the initial call. - * - * This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS, - * with the addition of localisation support. The description of the - * RETRO_ENVIRONMENT_SET_CORE_OPTIONS callback should be consulted - * for further details. - * - * 'data' points to a retro_core_options_intl struct. - * - * retro_core_options_intl::us is a pointer to an array of - * retro_core_option_definition structs defining the US English - * core options implementation. It must point to a valid array. - * - * retro_core_options_intl::local is a pointer to an array of - * retro_core_option_definition structs defining core options for - * the current frontend language. It may be NULL (in which case - * retro_core_options_intl::us is used by the frontend). Any items - * missing from this array will be read from retro_core_options_intl::us - * instead. - * - * NOTE: Default core option values are always taken from the - * retro_core_options_intl::us array. Any default values in - * retro_core_options_intl::local array will be ignored. - */ +/** + * Notifies the frontend that it should show or hide the named core option. + * + * Some core options aren't relevant in all scenarios, + * such as a submenu for hardware rendering flags + * when the software renderer is configured. + * This environment call asks the frontend to stop (or start) + * showing the named core option to the player. + * This is only a hint, not a requirement; + * the frontend may ignore this environment call. + * By default, all core options are visible. + * + * @note This environment call must \em only affect a core option's visibility, + * not its functionality or availability. + * \ref RETRO_ENVIRONMENT_GET_VARIABLE "Getting an invisible core option" + * must behave normally. + * + * @param[in] data const struct retro_core_option_display *. + * Pointer to a descriptor for the option that the frontend should show or hide. + * May be \c NULL, in which case the frontend will only return + * whether this environment callback is available. + * @return \c true if this environment call is available, + * even if \c data is \c NULL + * or the specified option doesn't exist. + * @see retro_core_option_display + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK + */ #define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY 55 - /* struct retro_core_option_display * -- - * - * Allows an implementation to signal the environment to show - * or hide a variable when displaying core options. This is - * considered a *suggestion*. The frontend is free to ignore - * this callback, and its implementation not considered mandatory. - * - * 'data' points to a retro_core_option_display struct - * - * retro_core_option_display::key is a variable identifier - * which has already been set by SET_VARIABLES/SET_CORE_OPTIONS. - * - * retro_core_option_display::visible is a boolean, specifying - * whether variable should be displayed - * - * Note that all core option variables will be set visible by - * default when calling SET_VARIABLES/SET_CORE_OPTIONS. - */ +/** + * Returns the frontend's preferred hardware rendering API. + * Cores should use this information to decide which API to use with \c RETRO_ENVIRONMENT_SET_HW_RENDER. + * @param[out] data retro_hw_context_type *. + * Pointer to the hardware context type. + * Behavior is undefined if \c data is NULL. + * This value will be set even if the environment call returns false, + * unless the frontend doesn't implement it. + * @returns \c true if the environment call is available + * and the frontend is able to use a hardware rendering API besides the one returned. + * If \c false is returned and the core cannot use the preferred rendering API, + * then it should exit or fall back to software rendering. + * @note The returned value does not indicate which API is currently in use. + * For example, the frontend may return \c RETRO_HW_CONTEXT_OPENGL + * while a Direct3D context from a previous session is active; + * this would signal that the frontend's current preference is for OpenGL, + * possibly because the user changed their frontend's video driver while a game is running. + * @see retro_hw_context_type + * @see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + */ #define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56 - /* unsigned * -- - * - * Allows an implementation to ask frontend preferred hardware - * context to use. Core should use this information to deal - * with what specific context to request with SET_HW_RENDER. - * - * 'data' points to an unsigned variable - */ +/** + * Returns the minimum version of the disk control interface supported by the frontend. + * + * If this environment call returns \c false or \c data is 0 or greater, + * then cores may use disk control callbacks + * with \c RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. + * If the reported version is 1 or greater, + * then cores should use \c RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE instead. + * + * @param[out] data unsigned *. + * Pointer to the unsigned integer that the frontend's supported disk control interface version will be stored in. + * Behavior is undefined if \c NULL. + * @return \c true if this environment call is available. + * @see RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE + */ #define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57 - /* unsigned * -- - * Unsigned value is the API version number of the disk control - * interface supported by the frontend. If callback return false, - * API version is assumed to be 0. - * - * In legacy code, the disk control interface is defined by passing - * a struct of type retro_disk_control_callback to - * RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. - * This may be still be done regardless of the disk control - * interface version. - * - * If version is >= 1 however, the disk control interface may - * instead be defined by passing a struct of type - * retro_disk_control_ext_callback to - * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE. - * This allows the core to provide additional information about - * disk images to the frontend and/or enables extra - * disk control functionality by the frontend. - */ +/** + * @copybrief RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE + * + * This is intended for multi-disk games that expect the player + * to manually swap disks at certain points in the game. + * This version of the disk control interface provides + * more information about disk images. + * Should be called in \c retro_init. + * + * @param[in] data const struct retro_disk_control_ext_callback *. + * Pointer to the callback functions to use. + * May be \c NULL, in which case the existing disk callback is deregistered. + * @return \c true if this environment call is available, + * even if \c data is \c NULL. + * @see retro_disk_control_ext_callback + */ #define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58 - /* const struct retro_disk_control_ext_callback * -- - * Sets an interface which frontend can use to eject and insert - * disk images, and also obtain information about individual - * disk image files registered by the core. - * This is used for games which consist of multiple images and - * must be manually swapped out by the user (e.g. PSX, floppy disk - * based systems). - */ +/** + * Returns the version of the message interface supported by the frontend. + * + * A version of 0 indicates that the frontend + * only supports the legacy \c RETRO_ENVIRONMENT_SET_MESSAGE interface. + * A version of 1 indicates that the frontend + * supports \c RETRO_ENVIRONMENT_SET_MESSAGE_EXT as well. + * If this environment call returns \c false, + * the core should behave as if it had returned 0. + * + * @param[out] data unsigned *. + * Pointer to the result returned by the frontend. + * Behavior is undefined if \c NULL. + * @return \c true if this environment call is available. + * @see RETRO_ENVIRONMENT_SET_MESSAGE_EXT + * @see RETRO_ENVIRONMENT_SET_MESSAGE + */ #define RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION 59 - /* unsigned * -- - * Unsigned value is the API version number of the message - * interface supported by the frontend. If callback returns - * false, API version is assumed to be 0. - * - * In legacy code, messages may be displayed in an - * implementation-specific manner by passing a struct - * of type retro_message to RETRO_ENVIRONMENT_SET_MESSAGE. - * This may be still be done regardless of the message - * interface version. - * - * If version is >= 1 however, messages may instead be - * displayed by passing a struct of type retro_message_ext - * to RETRO_ENVIRONMENT_SET_MESSAGE_EXT. This allows the - * core to specify message logging level, priority and - * destination (OSD, logging interface or both). - */ +/** + * Displays a user-facing message for a short time. + * + * Use this callback to convey important status messages, + * such as errors or the result of long-running operations. + * For trivial messages or logging, use \c RETRO_ENVIRONMENT_GET_LOG_INTERFACE or \c stderr. + * + * This environment call supersedes \c RETRO_ENVIRONMENT_SET_MESSAGE, + * as it provides many more ways to customize + * how a message is presented to the player. + * However, a frontend that supports this environment call + * must still support \c RETRO_ENVIRONMENT_SET_MESSAGE. + * + * @param[in] data const struct retro_message_ext *. + * Pointer to the message to display to the player. + * Behavior is undefined if \c NULL. + * @returns \c true if this environment call is available. + * @see retro_message_ext + * @see RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION + */ #define RETRO_ENVIRONMENT_SET_MESSAGE_EXT 60 - /* const struct retro_message_ext * -- - * Sets a message to be displayed in an implementation-specific - * manner for a certain amount of 'frames'. Additionally allows - * the core to specify message logging level, priority and - * destination (OSD, logging interface or both). - * Should not be used for trivial messages, which should simply be - * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a - * fallback, stderr). - */ +/** + * Returns the number of active input devices currently provided by the frontend. + * + * This may change between frames, + * but will remain constant for the duration of each frame. + * + * If this callback returns \c true, + * a core need not poll any input device + * with an index greater than or equal to the returned value. + * + * If callback returns \c false, + * the number of active input devices is unknown. + * In this case, all input devices should be considered active. + * + * @param[out] data unsigned *. + * Pointer to the result returned by the frontend. + * Behavior is undefined if \c NULL. + * @return \c true if this environment call is available. + */ #define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61 - /* unsigned * -- - * Unsigned value is the number of active input devices - * provided by the frontend. This may change between - * frames, but will remain constant for the duration - * of each frame. - * If callback returns true, a core need not poll any - * input device with an index greater than or equal to - * the number of active devices. - * If callback returns false, the number of active input - * devices is unknown. In this case, all input devices - * should be considered active. - */ +/** + * Registers a callback that the frontend can use to notify the core + * of the audio output buffer's occupancy. + * Can be used by a core to attempt frame-skipping to avoid buffer under-runs + * (i.e. "crackling" sounds). + * + * @param[in] data const struct retro_audio_buffer_status_callback *. + * Pointer to the the buffer status callback, + * or \c NULL to unregister any existing callback. + * @return \c true if this environment call is available, + * even if \c data is \c NULL. + * + * @see retro_audio_buffer_status_callback + */ #define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62 - /* const struct retro_audio_buffer_status_callback * -- - * Lets the core know the occupancy level of the frontend - * audio buffer. Can be used by a core to attempt frame - * skipping in order to avoid buffer under-runs. - * A core may pass NULL to disable buffer status reporting - * in the frontend. - */ +/** + * Requests a minimum frontend audio latency in milliseconds. + * + * This is a hint; the frontend may assign a different audio latency + * to accommodate hardware limits, + * although it should try to honor requests up to 512ms. + * + * This callback has no effect if the requested latency + * is less than the frontend's current audio latency. + * If value is zero or \c data is \c NULL, + * the frontend should set its default audio latency. + * + * May be used by a core to increase audio latency and + * reduce the risk of buffer under-runs (crackling) + * when performing 'intensive' operations. + * + * A core using RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK + * to implement audio-buffer-based frame skipping can get good results + * by setting the audio latency to a high (typically 6x or 8x) + * integer multiple of the expected frame time. + * + * This can only be called from within \c retro_run(). + * + * @warning This environment call may require the frontend to reinitialize its audio system. + * This environment call should be used sparingly. + * If the driver is reinitialized, + * \ref retro_audio_callback_t "all audio callbacks" will be updated + * to target the newly-initialized driver. + * + * @param[in] data const unsigned *. + * Minimum audio latency, in milliseconds. + * @return \c true if this environment call is available, + * even if \c data is \c NULL. + * + * @see RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK + */ #define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63 - /* const unsigned * -- - * Sets minimum frontend audio latency in milliseconds. - * Resultant audio latency may be larger than set value, - * or smaller if a hardware limit is encountered. A frontend - * is expected to honour requests up to 512 ms. - * - * - If value is less than current frontend - * audio latency, callback has no effect - * - If value is zero, default frontend audio - * latency is set - * - * May be used by a core to increase audio latency and - * therefore decrease the probability of buffer under-runs - * (crackling) when performing 'intensive' operations. - * A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK - * to implement audio-buffer-based frame skipping may achieve - * optimal results by setting the audio latency to a 'high' - * (typically 6x or 8x) integer multiple of the expected - * frame time. - * - * WARNING: This can only be called from within retro_run(). - * Calling this can require a full reinitialization of audio - * drivers in the frontend, so it is important to call it very - * sparingly, and usually only with the users explicit consent. - * An eventual driver reinitialize will happen so that audio - * callbacks happening after this call within the same retro_run() - * call will target the newly initialized driver. - */ +/** + * Allows the core to tell the frontend when it should enable fast-forwarding, + * rather than relying solely on the frontend and user interaction. + * + * Possible use cases include: + * + * \li Temporarily disabling a core's fastforward support + * while investigating a related bug. + * \li Disabling fastforward during netplay sessions, + * or when using an emulated console's network features. + * \li Automatically speeding up the game when in a loading screen + * that cannot be shortened with high-level emulation. + * + * @param[in] data const struct retro_fastforwarding_override *. + * Pointer to the parameters that decide when and how + * the frontend is allowed to enable fast-forward mode. + * May be \c NULL, in which case the frontend will return \c true + * without updating the fastforward state, + * which can be used to detect support for this environment call. + * @return \c true if this environment call is available, + * even if \c data is \c NULL. + * + * @see retro_fastforwarding_override + * @see RETRO_ENVIRONMENT_GET_FASTFORWARDING + */ #define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64 - /* const struct retro_fastforwarding_override * -- - * Used by a libretro core to override the current - * fastforwarding mode of the frontend. - * If NULL is passed to this function, the frontend - * will return true if fastforwarding override - * functionality is supported (no change in - * fastforwarding state will occur in this case). - */ #define RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE 65 /* const struct retro_system_content_info_override * -- @@ -1508,251 +2252,136 @@ enum retro_mod * retro_load_game_special() */ +/** + * Defines a set of core options that can be shown and configured by the frontend, + * so that the player may customize their gameplay experience to their liking. + * + * @note This environment call is intended to replace + * \c RETRO_ENVIRONMENT_SET_VARIABLES and \c RETRO_ENVIRONMENT_SET_CORE_OPTIONS, + * and should only be called if \c RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION + * returns an API version of at least 2. + * + * This should be called the first time as early as possible, + * ideally in \c retro_set_environment (but \c retro_load_game is acceptable). + * It may then be called again later to update + * the core's options and their associated values, + * as long as the number of options doesn't change + * from the number given in the first call. + * + * The core can retrieve option values at any time with \c RETRO_ENVIRONMENT_GET_VARIABLE. + * If a saved value for a core option doesn't match the option definition's values, + * the frontend may treat it as incorrect and revert to the default. + * + * Core options and their values are usually defined in a large static array, + * but they may be generated at runtime based on the loaded game or system state. + * Here are some use cases for that: + * + * @li Selecting a particular file from one of the + * \ref RETRO_ENVIRONMENT_GET_ASSET_DIRECTORY "frontend's" + * \ref RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY "content" + * \ref RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY "directories", + * such as a memory card image or figurine data file. + * @li Excluding options that are not relevant to the current game, + * for cores that define a large number of possible options. + * @li Choosing a default value at runtime for a specific game, + * such as a BIOS file whose region matches that of the loaded content. + * + * @note A guiding principle of libretro's API design is that + * all common interactions (gameplay, menu navigation, etc.) + * should be possible without a keyboard. + * This implies that cores should keep the number of options and values + * as low as possible. + * + * @param[in] data const struct retro_core_options_v2 *. + * Pointer to a core's options and their associated categories. + * May be \c NULL, in which case the frontend will remove all existing core options. + * The frontend must maintain its own copy of this object, + * including all strings and subobjects. + * @return \c true if this environment call is available + * and the frontend supports categories. + * Note that this environment call is guaranteed to successfully register + * the provided core options, + * so the return value does not indicate success or failure. + * + * @see retro_core_options_v2 + * @see retro_core_option_v2_category + * @see retro_core_option_v2_definition + * @see RETRO_ENVIRONMENT_GET_VARIABLE + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL + */ #define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 67 - /* const struct retro_core_options_v2 * -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION - * returns an API version of >= 2. - * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. - * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS. - * This should be called the first time as early as - * possible (ideally in retro_set_environment). - * Afterwards it may be called again for the core to communicate - * updated options to the frontend, but the number of core - * options must not change from the number in the initial call. - * If RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION returns an API - * version of >= 2, this callback is guaranteed to succeed - * (i.e. callback return value does not indicate success) - * If callback returns true, frontend has core option category - * support. - * If callback returns false, frontend does not have core option - * category support. - * - * 'data' points to a retro_core_options_v2 struct, containing - * of two pointers: - * - retro_core_options_v2::categories is an array of - * retro_core_option_v2_category structs terminated by a - * { NULL, NULL, NULL } element. If retro_core_options_v2::categories - * is NULL, all core options will have no category and will be shown - * at the top level of the frontend core option interface. If frontend - * does not have core option category support, categories array will - * be ignored. - * - retro_core_options_v2::definitions is an array of - * retro_core_option_v2_definition structs terminated by a - * { NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL } - * element. - * - * >> retro_core_option_v2_category notes: - * - * - retro_core_option_v2_category::key should contain string - * that uniquely identifies the core option category. Valid - * key characters are [a-z, A-Z, 0-9, _, -] - * Namespace collisions with other implementations' category - * keys are permitted. - * - retro_core_option_v2_category::desc should contain a human - * readable description of the category key. - * - retro_core_option_v2_category::info should contain any - * additional human readable information text that a typical - * user may need to understand the nature of the core option - * category. - * - * Example entry: - * { - * "advanced_settings", - * "Advanced", - * "Options affecting low-level emulation performance and accuracy." - * } - * - * >> retro_core_option_v2_definition notes: - * - * - retro_core_option_v2_definition::key should be namespaced to not - * collide with other implementations' keys. e.g. A core called - * 'foo' should use keys named as 'foo_option'. Valid key characters - * are [a-z, A-Z, 0-9, _, -]. - * - retro_core_option_v2_definition::desc should contain a human readable - * description of the key. Will be used when the frontend does not - * have core option category support. Examples: "Aspect Ratio" or - * "Video > Aspect Ratio". - * - retro_core_option_v2_definition::desc_categorized should contain a - * human readable description of the key, which will be used when - * frontend has core option category support. Example: "Aspect Ratio", - * where associated retro_core_option_v2_category::desc is "Video". - * If empty or NULL, the string specified by - * retro_core_option_v2_definition::desc will be used instead. - * retro_core_option_v2_definition::desc_categorized will be ignored - * if retro_core_option_v2_definition::category_key is empty or NULL. - * - retro_core_option_v2_definition::info should contain any additional - * human readable information text that a typical user may need to - * understand the functionality of the option. - * - retro_core_option_v2_definition::info_categorized should contain - * any additional human readable information text that a typical user - * may need to understand the functionality of the option, and will be - * used when frontend has core option category support. This is provided - * to accommodate the case where info text references an option by - * name/desc, and the desc/desc_categorized text for that option differ. - * If empty or NULL, the string specified by - * retro_core_option_v2_definition::info will be used instead. - * retro_core_option_v2_definition::info_categorized will be ignored - * if retro_core_option_v2_definition::category_key is empty or NULL. - * - retro_core_option_v2_definition::category_key should contain a - * category identifier (e.g. "video" or "audio") that will be - * assigned to the core option if frontend has core option category - * support. A categorized option will be shown in a subsection/ - * submenu of the frontend core option interface. If key is empty - * or NULL, or if key does not match one of the - * retro_core_option_v2_category::key values in the associated - * retro_core_option_v2_category array, option will have no category - * and will be shown at the top level of the frontend core option - * interface. - * - retro_core_option_v2_definition::values is an array of - * retro_core_option_value structs terminated by a { NULL, NULL } - * element. - * --> retro_core_option_v2_definition::values[index].value is an - * expected option value. - * --> retro_core_option_v2_definition::values[index].label is a - * human readable label used when displaying the value on screen. - * If NULL, the value itself is used. - * - retro_core_option_v2_definition::default_value is the default - * core option setting. It must match one of the expected option - * values in the retro_core_option_v2_definition::values array. If - * it does not, or the default value is NULL, the first entry in the - * retro_core_option_v2_definition::values array is treated as the - * default. - * - * The number of possible option values should be very limited, - * and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX. - * i.e. it should be feasible to cycle through options - * without a keyboard. - * - * Example entries: - * - * - Uncategorized: - * - * { - * "foo_option", - * "Speed hack coprocessor X", - * NULL, - * "Provides increased performance at the expense of reduced accuracy.", - * NULL, - * NULL, - * { - * { "false", NULL }, - * { "true", NULL }, - * { "unstable", "Turbo (Unstable)" }, - * { NULL, NULL }, - * }, - * "false" - * } - * - * - Categorized: - * - * { - * "foo_option", - * "Advanced > Speed hack coprocessor X", - * "Speed hack coprocessor X", - * "Setting 'Advanced > Speed hack coprocessor X' to 'true' or 'Turbo' provides increased performance at the expense of reduced accuracy", - * "Setting 'Speed hack coprocessor X' to 'true' or 'Turbo' provides increased performance at the expense of reduced accuracy", - * "advanced_settings", - * { - * { "false", NULL }, - * { "true", NULL }, - * { "unstable", "Turbo (Unstable)" }, - * { NULL, NULL }, - * }, - * "false" - * } - * - * Only strings are operated on. The possible values will - * generally be displayed and stored as-is by the frontend. - */ +/** + * A variant of \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * that supports internationalization. + * + * This should be called instead of \c RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * if the core provides translations for its options. + * General use is largely the same, + * but see \ref retro_core_options_v2_intl for some important details. + * + * @param[in] data const struct retro_core_options_v2_intl *. + * Pointer to a core's option values and categories, + * plus a translation for each option and category. + * @see retro_core_options_v2_intl + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + */ #define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL 68 - /* const struct retro_core_options_v2_intl * -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION - * returns an API version of >= 2. - * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. - * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS. - * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. - * This should be called instead of RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2. - * This should be called the first time as early as - * possible (ideally in retro_set_environment). - * Afterwards it may be called again for the core to communicate - * updated options to the frontend, but the number of core - * options must not change from the number in the initial call. - * If RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION returns an API - * version of >= 2, this callback is guaranteed to succeed - * (i.e. callback return value does not indicate success) - * If callback returns true, frontend has core option category - * support. - * If callback returns false, frontend does not have core option - * category support. - * - * This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, - * with the addition of localisation support. The description of the - * RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 callback should be consulted - * for further details. - * - * 'data' points to a retro_core_options_v2_intl struct. - * - * - retro_core_options_v2_intl::us is a pointer to a - * retro_core_options_v2 struct defining the US English - * core options implementation. It must point to a valid struct. - * - * - retro_core_options_v2_intl::local is a pointer to a - * retro_core_options_v2 struct defining core options for - * the current frontend language. It may be NULL (in which case - * retro_core_options_v2_intl::us is used by the frontend). Any items - * missing from this struct will be read from - * retro_core_options_v2_intl::us instead. - * - * NOTE: Default core option values are always taken from the - * retro_core_options_v2_intl::us struct. Any default values in - * the retro_core_options_v2_intl::local struct will be ignored. - */ +/** + * Registers a callback that the frontend can use + * to notify the core that at least one core option + * should be made hidden or visible. + * Allows a frontend to signal that a core must update + * the visibility of any dynamically hidden core options, + * and enables the frontend to detect visibility changes. + * Used by the frontend to update the menu display status + * of core options without requiring a call of retro_run(). + * Must be called in retro_set_environment(). + * + * @param[in] data const struct retro_core_options_update_display_callback *. + * The callback that the frontend should use. + * May be \c NULL, in which case the frontend will unset any existing callback. + * Can be used to query visibility support. + * @return \c true if this environment call is available, + * even if \c data is \c NULL. + * @see retro_core_options_update_display_callback + */ #define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK 69 - /* const struct retro_core_options_update_display_callback * -- - * Allows a frontend to signal that a core must update - * the visibility of any dynamically hidden core options, - * and enables the frontend to detect visibility changes. - * Used by the frontend to update the menu display status - * of core options without requiring a call of retro_run(). - * Must be called in retro_set_environment(). - */ +/** + * Forcibly sets a core option's value. + * + * After changing a core option value with this callback, + * it will be reflected in the frontend + * and \ref RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE will return \c true. + * \ref retro_variable::key must match + * a \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 "previously-set core option", + * and \ref retro_variable::value must match one of its defined values. + * + * Possible use cases include: + * + * @li Allowing the player to set certain core options + * without entering the frontend's option menu, + * using an in-core hotkey. + * @li Adjusting invalid combinations of settings. + * @li Migrating settings from older releases of a core. + * + * @param[in] data const struct retro_variable *. + * Pointer to a single option that the core is changing. + * May be \c NULL, in which case the frontend will return \c true + * to indicate that this environment call is available. + * @return \c true if this environment call is available + * and the option named by \c key was successfully + * set to the given \c value. + * \c false if the \c key or \c value fields are \c NULL, empty, + * or don't match a previously set option. + * + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * @see RETRO_ENVIRONMENT_GET_VARIABLE + * @see RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE + */ #define RETRO_ENVIRONMENT_SET_VARIABLE 70 - /* const struct retro_variable * -- - * Allows an implementation to notify the frontend - * that a core option value has changed. - * - * retro_variable::key and retro_variable::value - * must match strings that have been set previously - * via one of the following: - * - * - RETRO_ENVIRONMENT_SET_VARIABLES - * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS - * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL - * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 - * - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL - * - * After changing a core option value via this - * callback, RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE - * will return true. - * - * If data is NULL, no changes will be registered - * and the callback will return true; an - * implementation may therefore pass NULL in order - * to test whether the callback is supported. - */ #define RETRO_ENVIRONMENT_GET_THROTTLE_STATE (71 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* struct retro_throttle_state * -- @@ -1760,74 +2389,92 @@ enum retro_mod * the frontend is attempting to call retro_run(). */ +/** + * Returns information about how the frontend will use savestates. + * + * @param[out] data retro_savestate_context *. + * Pointer to the current savestate context. + * May be \c NULL, in which case the environment call + * will return \c true to indicate its availability. + * @returns \c true if the environment call is available, + * even if \c data is \c NULL. + * @see retro_savestate_context + */ #define RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT (72 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* int * -- - * Tells the core about the context the frontend is asking for savestate. - * (see enum retro_savestate_context) - */ +/** + * Before calling \c SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE, will query which interface is supported. + * + * Frontend looks at \c retro_hw_render_interface_type and returns the maximum supported + * context negotiation interface version. If the \c retro_hw_render_interface_type is not + * supported or recognized by the frontend, a version of 0 must be returned in + * \c retro_hw_render_interface's \c interface_version and \c true is returned by frontend. + * + * If this environment call returns true with a \c interface_version greater than 0, + * a core can always use a negotiation interface version larger than what the frontend returns, + * but only earlier versions of the interface will be used by the frontend. + * + * A frontend must not reject a negotiation interface version that is larger than what the + * frontend supports. Instead, the frontend will use the older entry points that it recognizes. + * If this is incompatible with a particular core's requirements, it can error out early. + * + * @note Regarding backwards compatibility, this environment call was introduced after Vulkan v1 + * context negotiation. If this environment call is not supported by frontend, i.e. the environment + * call returns \c false , only Vulkan v1 context negotiation is supported (if Vulkan HW rendering + * is supported at all). If a core uses Vulkan negotiation interface with version > 1, negotiation + * may fail unexpectedly. All future updates to the context negotiation interface implies that + * frontend must support this environment call to query support. + * + * @param[out] data struct retro_hw_render_context_negotiation_interface *. + * @return \c true if the environment call is available. + * @see SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE + * @see retro_hw_render_interface_type + * @see retro_hw_render_context_negotiation_interface + */ #define RETRO_ENVIRONMENT_GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT (73 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_hw_render_context_negotiation_interface * -- - * Before calling SET_HW_RNEDER_CONTEXT_NEGOTIATION_INTERFACE, a core can query - * which version of the interface is supported. - * - * Frontend looks at interface_type and returns the maximum supported - * context negotiation interface version. - * If the interface_type is not supported or recognized by the frontend, a version of 0 - * must be returned in interface_version and true is returned by frontend. - * - * If this environment call returns true with interface_version greater than 0, - * a core can always use a negotiation interface version larger than what the frontend returns, but only - * earlier versions of the interface will be used by the frontend. - * A frontend must not reject a negotiation interface version that is larger than - * what the frontend supports. Instead, the frontend will use the older entry points that it recognizes. - * If this is incompatible with a particular core's requirements, it can error out early. - * - * Backwards compatibility note: - * This environment call was introduced after Vulkan v1 context negotiation. - * If this environment call is not supported by frontend - i.e. the environment call returns false - - * only Vulkan v1 context negotiation is supported (if Vulkan HW rendering is supported at all). - * If a core uses Vulkan negotiation interface with version > 1, negotiation may fail unexpectedly. - * All future updates to the context negotiation interface implies that frontend must support - * this environment call to query support. - */ +/** + * Asks the frontend whether JIT compilation can be used. + * Primarily used by iOS and tvOS. + * @param[out] data bool *. + * Set to \c true if the frontend has verified that JIT compilation is possible. + * @return \c true if the environment call is available. + */ #define RETRO_ENVIRONMENT_GET_JIT_CAPABLE 74 - /* bool * -- - * Result is set to true if the frontend has already verified JIT can be - * used, mainly for use iOS/tvOS. On other platforms the result is true. - */ +/** + * Returns an interface that the core can use to receive microphone input. + * + * @param[out] data retro_microphone_interface *. + * Pointer to the microphone interface. + * @return \true if microphone support is available, + * even if no microphones are plugged in. + * \c false if microphone support is disabled unavailable, + * or if \c data is \c NULL. + * @see retro_microphone_interface + */ #define RETRO_ENVIRONMENT_GET_MICROPHONE_INTERFACE (75 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_microphone_interface * -- - * Returns an interface that can be used to receive input from the microphone driver. - * - * Returns true if microphone support is available, - * even if no microphones are plugged in. - * Returns false if mic support is disabled or unavailable. - * - * This callback can be invoked at any time, - * even before the microphone driver is ready. - */ - /* Environment 76 was an obsolete version of RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE. - * It was not used by any known core at the time, and was removed from the API. */ +/* Environment 76 was an obsolete version of RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE. +* It was not used by any known core at the time, and was removed from the API. */ +/** + * Returns the device's current power state as reported by the frontend. + * + * This is useful for emulating the battery level in handheld consoles, + * or for reducing power consumption when on battery power. + * + * @note This environment call describes the power state for the entire device, + * not for individual peripherals like controllers. + * + * @param[out] data . + * Indicates whether the frontend can provide this information, even if the parameter + * is \c NULL. If the frontend does not support this functionality, then the provided + * argument will remain unchanged. + * @return \c true if the environment call is available. + * @see retro_device_power + */ #define RETRO_ENVIRONMENT_GET_DEVICE_POWER (77 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_device_power * -- - * Returns the device's current power state as reported by the frontend. - * This is useful for emulating the battery level in handheld consoles, - * or for reducing power consumption when on battery power. - * - * The return value indicates whether the frontend can provide this information, - * even if the parameter is NULL. - * - * If the frontend does not support this functionality, - * then the provided argument will remain unchanged. - * - * Note that this environment call describes the power state for the entire device, - * not for individual peripherals like controllers. - */ #define RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE 78 /* const struct retro_netpacket_callback * -- @@ -1853,367 +2500,1142 @@ enum retro_mod * input devices does not need to take any action on its own. */ +/** + * Returns the device's current power state as reported by the frontend. + * This is useful for emulating the battery level in handheld consoles, + * or for reducing power consumption when on battery power. + * + * The return value indicates whether the frontend can provide this information, + * even if the parameter is \c NULL. + * + * If the frontend does not support this functionality, + * then the provided argument will remain unchanged. + * @param[out] data retro_device_power *. + * Pointer to the information that the frontend returns about its power state. + * May be \c NULL. + * @return \c true if the environment call is available, + * even if \c data is \c NULL. + * @see retro_device_power + * @note This environment call describes the power state for the entire device, + * not for individual peripherals like controllers. +*/ +#define RETRO_ENVIRONMENT_GET_DEVICE_POWER (77 | RETRO_ENVIRONMENT_EXPERIMENTAL) + +/** + * Returns the "playlist" directory of the frontend. + * + * This directory can be used to store core generated playlists, in case + * this internal functionality is available (e.g. internal core game detection + * engine). + * + * @param[out] data const char **. + * May be \c NULL. If so, no such directory is defined, and it's up to the + * implementation to find a suitable directory. + * @return \c true if the environment call is available. + */ #define RETRO_ENVIRONMENT_GET_PLAYLIST_DIRECTORY 79 - /* const char ** -- - * Returns the "playlist" directory of the frontend. - * This directory can be used to store core generated playlists, - * in case this internal functionality is available (e.g. internal core - * game detection engine). - * - * The returned value can be NULL. - * If so, no such directory is defined, - * and it's up to the implementation to find a suitable directory. - */ -/* VFS functionality */ -/* File paths: - * File paths passed as parameters when using this API shall be well formed UNIX-style, - * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator. - * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead). - * Other than the directory separator, cores shall not make assumptions about path format: - * "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths. +/**@}*/ + +/** + * @defgroup GET_VFS_INTERFACE File System Interface + * @brief File system functionality. + * + * @section File Paths + * File paths passed to all libretro filesystem APIs shall be well formed UNIX-style, + * using "/" (unquoted forward slash) as the directory separator + * regardless of the platform's native separator. + * + * Paths shall also include at least one forward slash + * (e.g. use "./game.bin" instead of "game.bin"). + * + * Other than the directory separator, cores shall not make assumptions about path format. + * The following paths are all valid: + * @li \c C:/path/game.bin + * @li \c http://example.com/game.bin + * @li \c #game/game.bin + * @li \c ./game.bin + * * Cores may replace the basename or remove path components from the end, and/or add new components; - * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end. - * The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much. - * Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable). - * Cores are allowed to try using them, but must remain functional if the front rejects such requests. + * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request from the front end. + * + * The frontend is encouraged to do the best it can when given an ill-formed path, + * but it is allowed to give up. + * + * Frontends are encouraged, but not required, to support native file system paths + * (including replacing the directory separator, if applicable). + * + * Cores are allowed to try using them, but must remain functional if the frontend rejects such requests. + * * Cores are encouraged to use the libretro-common filestream functions for file I/O, - * as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate - * and provide platform-specific fallbacks in cases where front ends do not support VFS. */ + * as they seamlessly integrate with VFS, + * deal with directory separator replacement as appropriate + * and provide platform-specific fallbacks + * in cases where front ends do not provide their own VFS interface. + * + * @see RETRO_ENVIRONMENT_GET_VFS_INTERFACE + * @see retro_vfs_interface_info + * @see file_path + * @see retro_dirent + * @see file_stream + * + * @{ + */ -/* Opaque file handle - * Introduced in VFS API v1 */ +/** + * Opaque file handle. + * @since VFS API v1 + */ struct retro_vfs_file_handle; -/* Opaque directory handle - * Introduced in VFS API v3 */ +/** + * Opaque directory handle. + * @since VFS API v3 + */ struct retro_vfs_dir_handle; -/* File open flags - * Introduced in VFS API v1 */ -#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */ -#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */ -#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/ +/** @defgroup RETRO_VFS_FILE_ACCESS File Access Flags + * File access flags. + * @since VFS API v1 + * @{ + */ + +/** Opens a file for read-only access. */ +#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) + +/** + * Opens a file for write-only access. + * Any existing file at this path will be discarded and overwritten + * unless \c RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING is also specified. + */ +#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) + +/** + * Opens a file for reading and writing. + * Any existing file at this path will be discarded and overwritten + * unless \c RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING is also specified. + */ +#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) + +/** + * Opens a file without discarding its existing contents. + * Only meaningful if \c RETRO_VFS_FILE_ACCESS_WRITE is specified. + */ #define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */ -/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use, - and how they react to unlikely external interference (for example someone else writing to that file, - or the file's server going down), behavior will not change. */ +/** @} */ + +/** @defgroup RETRO_VFS_FILE_ACCESS_HINT File Access Hints + * + * Hints to the frontend for how a file will be accessed. + * The VFS implementation may use these to optimize performance, + * react to external interference (such as concurrent writes), + * or it may ignore them entirely. + * + * Hint flags do not change the behavior of each VFS function + * unless otherwise noted. + * @{ + */ + +/** No particular hints are given. */ #define RETRO_VFS_FILE_ACCESS_HINT_NONE (0) -/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */ + +/** + * Indicates that the file will be accessed frequently. + * + * The frontend should cache it or map it into memory. + */ #define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0) -/* Seek positions */ +/** @} */ + +/** @defgroup RETRO_VFS_SEEK_POSITION File Seek Positions + * File access flags and hints. + * @{ + */ + +/** + * Indicates a seek relative to the start of the file. + */ #define RETRO_VFS_SEEK_POSITION_START 0 + +/** + * Indicates a seek relative to the current stream position. + */ #define RETRO_VFS_SEEK_POSITION_CURRENT 1 + +/** + * Indicates a seek relative to the end of the file. + * @note The offset passed to \c retro_vfs_seek_t should be negative. + */ #define RETRO_VFS_SEEK_POSITION_END 2 -/* stat() result flags - * Introduced in VFS API v3 */ +/** @} */ + +/** @defgroup RETRO_VFS_STAT File Status Flags + * File stat flags. + * @see retro_vfs_stat_t + * @since VFS API v3 + * @{ + */ + +/** Indicates that the given path refers to a valid file. */ #define RETRO_VFS_STAT_IS_VALID (1 << 0) + +/** Indicates that the given path refers to a directory. */ #define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1) + +/** + * Indicates that the given path refers to a character special file, + * such as \c /dev/null. + */ #define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2) -/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle - * Introduced in VFS API v1 */ +/** @} */ + +/** + * Returns the path that was used to open this file. + * + * @param stream The opened file handle to get the path of. + * Behavior is undefined if \c NULL or closed. + * @return The path that was used to open \c stream. + * The string is owned by \c stream and must not be modified. + * @since VFS API v1 + * @see filestream_get_path + */ typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream); -/* Open a file for reading or writing. If path points to a directory, this will - * fail. Returns the opaque file handle, or NULL for error. - * Introduced in VFS API v1 */ +/** + * Open a file for reading or writing. + * + * @param path The path to open. + * @param mode A bitwise combination of \c RETRO_VFS_FILE_ACCESS flags. + * At a minimum, one of \c RETRO_VFS_FILE_ACCESS_READ or \c RETRO_VFS_FILE_ACCESS_WRITE must be specified. + * @param hints A bitwise combination of \c RETRO_VFS_FILE_ACCESS_HINT flags. + * @return A handle to the opened file, + * or \c NULL upon failure. + * Note that this will return \c NULL if \c path names a directory. + * The returned file handle must be closed with \c retro_vfs_close_t. + * @since VFS API v1 + * @see File Paths + * @see RETRO_VFS_FILE_ACCESS + * @see RETRO_VFS_FILE_ACCESS_HINT + * @see retro_vfs_close_t + * @see filestream_open + */ typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints); -/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure. - * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. - * Introduced in VFS API v1 */ +/** + * Close the file and release its resources. + * All files returned by \c retro_vfs_open_t must be closed with this function. + * + * @param stream The file handle to close. + * Behavior is undefined if already closed. + * Upon completion of this function, \c stream is no longer valid + * (even if it returns failure). + * @return 0 on success, -1 on failure or if \c stream is \c NULL. + * @see retro_vfs_open_t + * @see filestream_close + * @since VFS API v1 + */ typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream); -/* Return the size of the file in bytes, or -1 for error. - * Introduced in VFS API v1 */ +/** + * Return the size of the file in bytes. + * + * @param stream The file to query the size of. + * @return Size of the file in bytes, or -1 if there was an error. + * @see filestream_get_size + * @since VFS API v1 + */ typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream); -/* Truncate file to specified size. Returns 0 on success or -1 on error - * Introduced in VFS API v2 */ +/** + * Set the file's length. + * + * @param stream The file whose length will be adjusted. + * @param length The new length of the file, in bytes. + * If shorter than the original length, the extra bytes will be discarded. + * If longer, the file's padding is unspecified (and likely platform-dependent). + * @return 0 on success, + * -1 on failure. + * @see filestream_truncate + * @since VFS API v2 + */ typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length); -/* Get the current read / write position for the file. Returns -1 for error. - * Introduced in VFS API v1 */ +/** + * Gets the given file's current read/write position. + * This position is advanced with each call to \c retro_vfs_read_t or \c retro_vfs_write_t. + * + * @param stream The file to query the position of. + * @return The current stream position in bytes + * or -1 if there was an error. + * @see filestream_tell + * @since VFS API v1 + */ typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream); -/* Set the current read/write position for the file. Returns the new position, -1 for error. - * Introduced in VFS API v1 */ +/** + * Sets the given file handle's current read/write position. + * + * @param stream The file to set the position of. + * @param offset The new position, in bytes. + * @param seek_position The position to seek from. + * @return The new position, + * or -1 if there was an error. + * @since VFS API v1 + * @see File Seek Positions + * @see filestream_seek + */ typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position); -/* Read data from a file. Returns the number of bytes read, or -1 for error. - * Introduced in VFS API v1 */ +/** + * Read data from a file, if it was opened for reading. + * + * @param stream The file to read from. + * @param s The buffer to read into. + * @param len The number of bytes to read. + * The buffer pointed to by \c s must be this large. + * @return The number of bytes read, + * or -1 if there was an error. + * @since VFS API v1 + * @see filestream_read + */ typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len); -/* Write data to a file. Returns the number of bytes written, or -1 for error. - * Introduced in VFS API v1 */ +/** + * Write data to a file, if it was opened for writing. + * + * @param stream The file handle to write to. + * @param s The buffer to write from. + * @param len The number of bytes to write. + * The buffer pointed to by \c s must be this large. + * @return The number of bytes written, + * or -1 if there was an error. + * @since VFS API v1 + * @see filestream_write + */ typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len); -/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure. - * Introduced in VFS API v1 */ +/** + * Flush pending writes to the file, if applicable. + * + * This does not mean that the changes will be immediately persisted to disk; + * that may be scheduled for later, depending on the platform. + * + * @param stream The file handle to flush. + * @return 0 on success, -1 on failure. + * @since VFS API v1 + * @see filestream_flush + */ typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream); -/* Delete the specified file. Returns 0 on success, -1 on failure - * Introduced in VFS API v1 */ +/** + * Deletes the file at the given path. + * + * @param path The path to the file that will be deleted. + * @return 0 on success, -1 on failure. + * @see filestream_delete + * @since VFS API v1 + */ typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path); -/* Rename the specified file. Returns 0 on success, -1 on failure - * Introduced in VFS API v1 */ +/** + * Rename the specified file. + * + * @param old_path Path to an existing file. + * @param new_path The destination path. + * Must not name an existing file. + * @return 0 on success, -1 on failure + * @see filestream_rename + * @since VFS API v1 + */ typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path); -/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid. - * Additionally stores file size in given variable, unless NULL is given. - * Introduced in VFS API v3 */ +/** + * Gets information about the given file. + * + * @param path The path to the file to query. + * @param[out] size The reported size of the file in bytes. + * May be \c NULL, in which case this value is ignored. + * @return A bitmask of \c RETRO_VFS_STAT flags, + * or 0 if \c path doesn't refer to a valid file. + * @see path_stat + * @see path_get_size + * @see RETRO_VFS_STAT + * @since VFS API v3 + */ typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size); -/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists. - * Introduced in VFS API v3 */ +/** + * Creates a directory at the given path. + * + * @param dir The desired location of the new directory. + * @return 0 if the directory was created, + * -2 if the directory already exists, + * or -1 if some other error occurred. + * @see path_mkdir + * @since VFS API v3 + */ typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir); -/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error. - * Support for the include_hidden argument may vary depending on the platform. - * Introduced in VFS API v3 */ +/** + * Opens a handle to a directory so its contents can be inspected. + * + * @param dir The path to the directory to open. + * Must be an existing directory. + * @param include_hidden Whether to include hidden files in the directory listing. + * The exact semantics of this flag will depend on the platform. + * @return A handle to the opened directory, + * or \c NULL if there was an error. + * @see retro_opendir + * @since VFS API v3 + */ typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden); -/* Read the directory entry at the current position, and move the read pointer to the next position. - * Returns true on success, false if already on the last entry. - * Introduced in VFS API v3 */ +/** + * Gets the next dirent ("directory entry") + * within the given directory. + * + * @param[in,out] dirstream The directory to read from. + * Updated to point to the next file, directory, or other path. + * @return \c true when the next dirent was retrieved, + * \c false if there are no more dirents to read. + * @note This API iterates over all files and directories within \c dirstream. + * Remember to check what the type of the current dirent is. + * @note This function does not recurse, + * i.e. it does not return the contents of subdirectories. + * @note This may include "." and ".." on Unix-like platforms. + * @see retro_readdir + * @see retro_vfs_dirent_is_dir_t + * @since VFS API v3 + */ typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream); -/* Get the name of the last entry read. Returns a string on success, or NULL for error. - * The returned string pointer is valid until the next call to readdir or closedir. - * Introduced in VFS API v3 */ +/** + * Gets the filename of the current dirent. + * + * The returned string pointer is valid + * until the next call to \c retro_vfs_readdir_t or \c retro_vfs_closedir_t. + * + * @param dirstream The directory to read from. + * @return The current dirent's name, + * or \c NULL if there was an error. + * @note This function only returns the file's \em name, + * not a complete path to it. + * @see retro_dirent_get_name + * @since VFS API v3 + */ typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream); -/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error). - * Introduced in VFS API v3 */ +/** + * Checks whether the current dirent names a directory. + * + * @param dirstream The directory to read from. + * @return \c true if \c dirstream's current dirent points to a directory, + * \c false if not or if there was an error. + * @see retro_dirent_is_dir + * @since VFS API v3 + */ typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream); -/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure. - * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. - * Introduced in VFS API v3 */ +/** + * Closes the given directory and release its resources. + * + * Must be called on any \c retro_vfs_dir_handle returned by \c retro_vfs_open_t. + * + * @param dirstream The directory to close. + * When this function returns (even failure), + * \c dirstream will no longer be valid and must not be used. + * @return 0 on success, -1 on failure. + * @see retro_closedir + * @since VFS API v3 + */ typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream); +/** + * File system interface exposed by the frontend. + * + * @see dirent_vfs_init + * @see filestream_vfs_init + * @see path_vfs_init + * @see RETRO_ENVIRONMENT_GET_VFS_INTERFACE + */ struct retro_vfs_interface { /* VFS API v1 */ + /** @copydoc retro_vfs_get_path_t */ retro_vfs_get_path_t get_path; + + /** @copydoc retro_vfs_open_t */ retro_vfs_open_t open; + + /** @copydoc retro_vfs_close_t */ retro_vfs_close_t close; + + /** @copydoc retro_vfs_size_t */ retro_vfs_size_t size; + + /** @copydoc retro_vfs_tell_t */ retro_vfs_tell_t tell; + + /** @copydoc retro_vfs_seek_t */ retro_vfs_seek_t seek; + + /** @copydoc retro_vfs_read_t */ retro_vfs_read_t read; + + /** @copydoc retro_vfs_write_t */ retro_vfs_write_t write; + + /** @copydoc retro_vfs_flush_t */ retro_vfs_flush_t flush; + + /** @copydoc retro_vfs_remove_t */ retro_vfs_remove_t remove; + + /** @copydoc retro_vfs_rename_t */ retro_vfs_rename_t rename; /* VFS API v2 */ + + /** @copydoc retro_vfs_truncate_t */ retro_vfs_truncate_t truncate; /* VFS API v3 */ + + /** @copydoc retro_vfs_stat_t */ retro_vfs_stat_t stat; + + /** @copydoc retro_vfs_mkdir_t */ retro_vfs_mkdir_t mkdir; + + /** @copydoc retro_vfs_opendir_t */ retro_vfs_opendir_t opendir; + + /** @copydoc retro_vfs_readdir_t */ retro_vfs_readdir_t readdir; + + /** @copydoc retro_vfs_dirent_get_name_t */ retro_vfs_dirent_get_name_t dirent_get_name; + + /** @copydoc retro_vfs_dirent_is_dir_t */ retro_vfs_dirent_is_dir_t dirent_is_dir; + + /** @copydoc retro_vfs_closedir_t */ retro_vfs_closedir_t closedir; }; +/** + * Represents a request by the core for the frontend's file system interface, + * as well as the interface itself returned by the frontend. + * + * You do not need to use these functions directly; + * you may pass this struct to \c dirent_vfs_init, + * \c filestream_vfs_init, or \c path_vfs_init + * so that you can use the wrappers provided by these modules. + * + * @see dirent_vfs_init + * @see filestream_vfs_init + * @see path_vfs_init + * @see RETRO_ENVIRONMENT_GET_VFS_INTERFACE + */ struct retro_vfs_interface_info { - /* Set by core: should this be higher than the version the front end supports, - * front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call - * Introduced in VFS API v1 */ + /** + * The minimum version of the VFS API that the core requires. + * libretro-common's wrapper API initializers will check this value as well. + * + * Set to the core's desired VFS version when requesting an interface, + * and set by the frontend to indicate its actual API version. + * + * If the core asks for a newer VFS API version than the frontend supports, + * the frontend must return \c false within the \c RETRO_ENVIRONMENT_GET_VFS_INTERFACE call. + * @since VFS API v1 + */ uint32_t required_interface_version; - /* Frontend writes interface pointer here. The frontend also sets the actual - * version, must be at least required_interface_version. - * Introduced in VFS API v1 */ + /** + * Set by the frontend. + * The frontend will set this to the VFS interface it provides. + * + * The interface is owned by the frontend + * and must not be modified or freed by the core. + * @since VFS API v1 */ struct retro_vfs_interface *iface; }; +/** @} */ + +/** @defgroup GET_HW_RENDER_INTERFACE Hardware Rendering Interface + * @{ + */ + +/** + * Describes the hardware rendering API supported by + * a particular subtype of \c retro_hw_render_interface. + * + * Not every rendering API supported by libretro has its own interface, + * or even needs one. + * + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + * @see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE + */ enum retro_hw_render_interface_type { + /** + * Indicates a \c retro_hw_render_interface for Vulkan. + * @see retro_hw_render_interface_vulkan + */ RETRO_HW_RENDER_INTERFACE_VULKAN = 0, + + /** Indicates a \c retro_hw_render_interface for Direct3D 9. */ RETRO_HW_RENDER_INTERFACE_D3D9 = 1, + + /** Indicates a \c retro_hw_render_interface for Direct3D 10. */ RETRO_HW_RENDER_INTERFACE_D3D10 = 2, + + /** + * Indicates a \c retro_hw_render_interface for Direct3D 11. + * @see retro_hw_render_interface_d3d11 + */ RETRO_HW_RENDER_INTERFACE_D3D11 = 3, + + /** + * Indicates a \c retro_hw_render_interface for Direct3D 12. + * @see retro_hw_render_interface_d3d12 + */ RETRO_HW_RENDER_INTERFACE_D3D12 = 4, + + /** + * Indicates a \c retro_hw_render_interface for + * the PlayStation's 2 PSKit API. + * @see retro_hw_render_interface_gskit_ps2 + */ RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5, + + /** @private Defined to ensure sizeof(retro_hw_render_interface_type) == sizeof(int). + * Do not use. */ RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX }; -/* Base struct. All retro_hw_render_interface_* types - * contain at least these fields. */ +/** + * Base render interface type. + * All \c retro_hw_render_interface implementations + * will start with these two fields set to particular values. + * + * @see retro_hw_render_interface_type + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + * @see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE + */ struct retro_hw_render_interface { + /** + * Denotes the particular rendering API that this interface is for. + * Each interface requires this field to be set to a particular value. + * Use it to cast this interface to the appropriate pointer. + */ enum retro_hw_render_interface_type interface_type; + + /** + * The version of this rendering interface. + * @note This is not related to the version of the API itself. + */ unsigned interface_version; }; +/** @} */ + +/** + * @defgroup GET_LED_INTERFACE LED Interface + * @{ + */ + +/** @copydoc retro_led_interface::set_led_state */ typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state); + +/** + * Interface that the core can use to set the state of available LEDs. + * @see RETRO_ENVIRONMENT_GET_LED_INTERFACE + */ struct retro_led_interface { - retro_set_led_state_t set_led_state; + /** + * Sets the state of an LED. + * + * @param led The LED to set the state of. + * @param state The state to set the LED to. + * \c true to enable, \c false to disable. + */ + retro_set_led_state_t set_led_state; }; -/* Retrieves the current state of the MIDI input. - * Returns true if it's enabled, false otherwise. */ +/** @} */ + +/** @defgroup GET_AUDIO_VIDEO_ENABLE Skipped A/V Steps + * @{ + */ + +/** + * Flags that define A/V steps that the core may skip for this frame. + * + * @see RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE + */ +enum retro_av_enable_flags +{ + /** + * If set, the core should render video output with \c retro_video_refresh_t as normal. + * + * Otherwise, the frontend will discard any video data received this frame, + * including frames presented via hardware acceleration. + * \c retro_video_refresh_t will do nothing. + * + * @note After running the frame, the video output of the next frame + * should be no different than if video was enabled, + * and saving and loading state should have no issues. + * This implies that the emulated console's graphics pipeline state + * should not be affected by this flag. + * + * @note If emulating a platform that supports display capture + * (i.e. reading its own VRAM), + * the core may not be able to completely skip rendering, + * as the VRAM is part of the graphics pipeline's state. + */ + RETRO_AV_ENABLE_VIDEO = (1 << 0), + + /** + * If set, the core should render audio output + * with \c retro_audio_sample_t or \c retro_audio_sample_batch_t as normal. + * + * Otherwise, the frontend will discard any audio data received this frame. + * The core should skip audio rendering if possible. + * + * @note After running the frame, the audio output of the next frame + * should be no different than if audio was enabled, + * and saving and loading state should have no issues. + * This implies that the emulated console's audio pipeline state + * should not be affected by this flag. + */ + RETRO_AV_ENABLE_AUDIO = (1 << 1), + + /** + * If set, indicates that any savestates taken this frame + * are guaranteed to be created by the same binary that will load them, + * and will not be written to or read from the disk. + * + * The core may use these guarantees to: + * + * @li Assume that loading state will succeed. + * @li Update its memory buffers in-place if possible. + * @li Skip clearing memory. + * @li Skip resetting the system. + * @li Skip validation steps. + * + * @deprecated Use \c RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT instead, + * except for compatibility purposes. + */ + RETRO_AV_ENABLE_FAST_SAVESTATES = (1 << 2), + + /** + * If set, indicates that the frontend will never need audio from the core. + * Used by a frontend for implementing runahead via a secondary core instance. + * + * The core may stop synthesizing audio if it can do so + * without compromising emulation accuracy. + * + * Audio output for the next frame does not matter, + * and the frontend will never need an accurate audio state in the future. + * + * State will never be saved while this flag is set. + */ + RETRO_AV_ENABLE_HARD_DISABLE_AUDIO = (1 << 3), + + /** + * @private Defined to ensure sizeof(retro_av_enable_flags) == sizeof(int). + * Do not use. + */ + RETRO_AV_ENABLE_DUMMY = INT_MAX +}; + +/** @} */ + +/** + * @defgroup GET_MIDI_INTERFACE MIDI Interface + * @{ + */ + +/** @copydoc retro_midi_interface::input_enabled */ typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void); -/* Retrieves the current state of the MIDI output. - * Returns true if it's enabled, false otherwise */ +/** @copydoc retro_midi_interface::output_enabled */ typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void); -/* Reads next byte from the input stream. - * Returns true if byte is read, false otherwise. */ +/** @copydoc retro_midi_interface::read */ typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte); -/* Writes byte to the output stream. - * 'delta_time' is in microseconds and represent time elapsed since previous write. - * Returns true if byte is written, false otherwise. */ +/** @copydoc retro_midi_interface::write */ typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time); -/* Flushes previously written data. - * Returns true if successful, false otherwise. */ +/** @copydoc retro_midi_interface::flush */ typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void); +/** + * Interface that the core can use for raw MIDI I/O. + */ struct retro_midi_interface { + /** + * Retrieves the current state of MIDI input. + * + * @return \c true if MIDI input is enabled. + */ retro_midi_input_enabled_t input_enabled; + + /** + * Retrieves the current state of MIDI output. + * @return \c true if MIDI output is enabled. + */ retro_midi_output_enabled_t output_enabled; + + /** + * Reads a byte from the MIDI input stream. + * + * @param[out] byte The byte received from the input stream. + * @return \c true if a byte was read, + * \c false if MIDI input is disabled or \c byte is \c NULL. + */ retro_midi_read_t read; + + /** + * Writes a byte to the output stream. + * + * @param byte The byte to write to the output stream. + * @param delta_time Time since the previous write, in microseconds. + * @return \c true if c\ byte was written, false otherwise. + */ retro_midi_write_t write; + + /** + * Flushes previously-written data. + * + * @return \c true if successful. + */ retro_midi_flush_t flush; }; +/** @} */ + +/** @defgroup SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE Render Context Negotiation + * @{ + */ + +/** + * Describes the hardware rendering API used by + * a particular subtype of \c retro_hw_render_context_negotiation_interface. + * + * Not every rendering API supported by libretro has a context negotiation interface, + * or even needs one. + * + * @see RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + * @see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE + */ enum retro_hw_render_context_negotiation_interface_type { + /** + * Denotes a context negotiation interface for Vulkan. + * @see retro_hw_render_context_negotiation_interface_vulkan + */ RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0, + + /** + * @private Defined to ensure sizeof(retro_hw_render_context_negotiation_interface_type) == sizeof(int). + * Do not use. + */ RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX }; -/* Base struct. All retro_hw_render_context_negotiation_interface_* types - * contain at least these fields. */ +/** + * Base context negotiation interface type. + * All \c retro_hw_render_context_negotiation_interface implementations + * will start with these two fields set to particular values. + * + * @see retro_hw_render_interface_type + * @see RETRO_ENVIRONMENT_SET_HW_RENDER + * @see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE + * @see RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE + */ struct retro_hw_render_context_negotiation_interface { + /** + * Denotes the particular rendering API that this interface is for. + * Each interface requires this field to be set to a particular value. + * Use it to cast this interface to the appropriate pointer. + */ enum retro_hw_render_context_negotiation_interface_type interface_type; + + /** + * The version of this negotiation interface. + * @note This is not related to the version of the API itself. + */ unsigned interface_version; }; -/* Serialized state is incomplete in some way. Set if serialization is - * usable in typical end-user cases but should not be relied upon to - * implement frame-sensitive frontend features such as netplay or - * rerecording. */ +/** @} */ + +/** @defgroup RETRO_SERIALIZATION_QUIRK Serialization Quirks + * @{ + */ + +/** + * Indicates that serialized state is incomplete in some way. + * + * Set if serialization is usable for the common case of saving and loading game state, + * but should not be relied upon for frame-sensitive frontend features + * such as netplay or rerecording. + */ #define RETRO_SERIALIZATION_QUIRK_INCOMPLETE (1 << 0) -/* The core must spend some time initializing before serialization is - * supported. retro_serialize() will initially fail; retro_unserialize() - * and retro_serialize_size() may or may not work correctly either. */ + +/** + * Indicates that core must spend some time initializing before serialization can be done. + * + * \c retro_serialize(), \c retro_unserialize(), and \c retro_serialize_size() will initially fail. + */ #define RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE (1 << 1) -/* Serialization size may change within a session. */ + +/** Set by the core to indicate that serialization size may change within a session. */ #define RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE (1 << 2) -/* Set by the frontend to acknowledge that it supports variable-sized - * states. */ + +/** Set by the frontend to acknowledge that it supports variable-sized states. */ #define RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE (1 << 3) -/* Serialized state can only be loaded during the same session. */ + +/** Serialized state can only be loaded during the same session. */ #define RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION (1 << 4) -/* Serialized state cannot be loaded on an architecture with a different - * endianness from the one it was saved on. */ + +/** + * Serialized state cannot be loaded on an architecture + * with a different endianness from the one it was saved on. + */ #define RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT (1 << 5) -/* Serialized state cannot be loaded on a different platform from the one it - * was saved on for reasons other than endianness, such as word size - * dependence */ + +/** + * Serialized state cannot be loaded on a different platform + * from the one it was saved on for reasons other than endianness, + * such as word size dependence. + */ #define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6) -#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ -#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ -#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */ -#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */ -#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */ -#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ +/** @} */ + +/** @defgroup SET_MEMORY_MAPS Memory Descriptors + * @{ + */ + +/** @defgroup RETRO_MEMDESC Memory Descriptor Flags + * Information about how the emulated hardware uses this portion of its address space. + * @{ + */ + +/** + * Indicates that this memory area won't be modified + * once \c retro_load_game has returned. + */ +#define RETRO_MEMDESC_CONST (1 << 0) + +/** + * Indicates a memory area with big-endian byte ordering, + * as opposed to the default of little-endian. + */ +#define RETRO_MEMDESC_BIGENDIAN (1 << 1) + +/** + * Indicates a memory area that is used for the emulated system's main RAM. + */ +#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2) + +/** + * Indicates a memory area that is used for the emulated system's save RAM, + * usually found on a game cartridge as battery-backed RAM or flash memory. + */ +#define RETRO_MEMDESC_SAVE_RAM (1 << 3) + +/** + * Indicates a memory area that is used for the emulated system's video RAM, + * usually found on a console's GPU (or local equivalent). + */ +#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) + +/** + * Indicates a memory area that requires all accesses + * to be aligned to 2 bytes or their own size + * (whichever is smaller). + */ +#define RETRO_MEMDESC_ALIGN_2 (1 << 16) + +/** + * Indicates a memory area that requires all accesses + * to be aligned to 4 bytes or their own size + * (whichever is smaller). + */ #define RETRO_MEMDESC_ALIGN_4 (2 << 16) + +/** + * Indicates a memory area that requires all accesses + * to be aligned to 8 bytes or their own size + * (whichever is smaller). + */ #define RETRO_MEMDESC_ALIGN_8 (3 << 16) -#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ + +/** + * Indicates a memory area that requires all accesses + * to be at least 2 bytes long. + */ +#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) + +/** + * Indicates a memory area that requires all accesses + * to be at least 4 bytes long. + */ #define RETRO_MEMDESC_MINSIZE_4 (2 << 24) + +/** + * Indicates a memory area that requires all accesses + * to be at least 8 bytes long. + */ #define RETRO_MEMDESC_MINSIZE_8 (3 << 24) + +/** @} */ + +/** + * A mapping from a region of the emulated console's address space + * to the host's address space. + * + * Can be used to map an address in the console's address space + * to the host's address space, like so: + * + * @code + * void* emu_to_host(void* addr, struct retro_memory_descriptor* descriptor) + * { + * return descriptor->ptr + (addr & ~descriptor->disconnect) - descriptor->start; + * } + * @endcode + * + * @see RETRO_ENVIRONMENT_SET_MEMORY_MAPS + */ struct retro_memory_descriptor { + /** + * A bitwise \c OR of one or more \ref RETRO_MEMDESC "flags" + * that describe how the emulated system uses this descriptor's address range. + * + * @note If \c ptr is \c NULL, + * then no flags should be set. + * @see RETRO_MEMDESC + */ uint64_t flags; - /* Pointer to the start of the relevant ROM or RAM chip. - * It's strongly recommended to use 'offset' if possible, rather than - * doing math on the pointer. + /** + * Pointer to the start of this memory region's buffer + * within the \em host's address space. + * The address listed here must be valid for the duration of the session; + * it must not be freed or modified by the frontend + * and it must not be moved by the core. * - * If the same byte is mapped my multiple descriptors, their descriptors - * must have the same pointer. - * If 'start' does not point to the first byte in the pointer, put the - * difference in 'offset' instead. + * May be \c NULL to indicate a lack of accessible memory + * at the emulated address given in \c start. * - * May be NULL if there's nothing usable here (e.g. hardware registers and - * open bus). No flags should be set if the pointer is NULL. - * It's recommended to minimize the number of descriptors if possible, - * but not mandatory. */ + * @note Overlapping descriptors that include the same byte + * must have the same \c ptr value. + */ void *ptr; + + /** + * The offset of this memory region, + * relative to the address given by \c ptr. + * + * @note It is recommended to use this field for address calculations + * instead of performing arithmetic on \c ptr. + */ size_t offset; - /* This is the location in the emulated address space - * where the mapping starts. */ + /** + * The starting address of this memory region + * within the emulated hardware's address space. + * + * @note Not represented as a pointer + * because it's unlikely to be valid on the host device. + */ size_t start; - /* Which bits must be same as in 'start' for this mapping to apply. - * The first memory descriptor to claim a certain byte is the one - * that applies. - * A bit which is set in 'start' must also be set in this. - * Can be zero, in which case each byte is assumed mapped exactly once. - * In this case, 'len' must be a power of two. */ + /** + * A bitmask that specifies which bits of an address must match + * the bits of the \ref start address. + * + * Combines with \c disconnect to map an address to a memory block. + * + * If multiple memory descriptors can claim a particular byte, + * the first one defined in the \ref retro_memory_descriptor array applies. + * A bit which is set in \c start must also be set in this. + * + * Can be zero, in which case \c start and \c len represent + * the complete mapping for this region of memory + * (i.e. each byte is mapped exactly once). + * In this case, \c len must be a power of two. + */ size_t select; - /* If this is nonzero, the set bits are assumed not connected to the - * memory chip's address pins. */ + /** + * A bitmask of bits that are \em not used for addressing. + * + * Any set bits are assumed to be disconnected from + * the emulated memory chip's address pins, + * and are therefore ignored when memory-mapping. + */ size_t disconnect; - /* This one tells the size of the current memory area. - * If, after start+disconnect are applied, the address is higher than - * this, the highest bit of the address is cleared. + /** + * The length of this memory region, in bytes. + * + * If applying \ref start and \ref disconnect to an address + * results in a value higher than this, + * the highest bit of the address is cleared. * * If the address is still too high, the next highest bit is cleared. - * Can be zero, in which case it's assumed to be infinite (as limited - * by 'select' and 'disconnect'). */ + * Can be zero, in which case it's assumed to be + * bounded only by \ref select and \ref disconnect. + */ size_t len; - /* To go from emulated address to physical address, the following - * order applies: - * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ - - /* The address space name must consist of only a-zA-Z0-9_-, - * should be as short as feasible (maximum length is 8 plus the NUL), - * and may not be any other address space plus one or more 0-9A-F - * at the end. - * However, multiple memory descriptors for the same address space is - * allowed, and the address space name can be empty. NULL is treated - * as empty. + /** + * A short name for this address space. * - * Address space names are case sensitive, but avoid lowercase if possible. - * The same pointer may exist in multiple address spaces. + * Names must meet the following requirements: * - * Examples: - * blank+blank - valid (multiple things may be mapped in the same namespace) - * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) - * 'A'+'B' - valid (neither is a prefix of each other) - * 'S'+blank - valid ('S' is not in 0-9A-F) - * 'a'+blank - valid ('a' is not in 0-9A-F) - * 'a'+'A' - valid (neither is a prefix of each other) - * 'AR'+blank - valid ('R' is not in 0-9A-F) - * 'ARB'+blank - valid (the B can't be part of the address either, because - * there is no namespace 'AR') - * blank+'B' - not valid, because it's ambigous which address space B1234 - * would refer to. - * The length can't be used for that purpose; the frontend may want - * to append arbitrary data to an address, without a separator. */ + * \li Characters must be in the set [a-zA-Z0-9_-]. + * \li No more than 8 characters, plus a \c NULL terminator. + * \li Names are case-sensitive, but lowercase characters are discouraged. + * \li A name must not be the same as another name plus a character in the set \c [A-F0-9] + * (i.e. if an address space named "RAM" exists, + * then the names "RAM0", "RAM1", ..., "RAMF" are forbidden). + * This is to allow addresses to be named by each descriptor unambiguously, + * even if the areas overlap. + * \li May be \c NULL or empty (both are considered equivalent). + * + * Here are some examples of pairs of address space names: + * + * \li \em blank + \em blank: valid (multiple things may be mapped in the same namespace) + * \li \c Sp + \c Sp: valid (multiple things may be mapped in the same namespace) + * \li \c SRAM + \c VRAM: valid (neither is a prefix of the other) + * \li \c V + \em blank: valid (\c V is not in \c [A-F0-9]) + * \li \c a + \em blank: valid but discouraged (\c a is not in \c [A-F0-9]) + * \li \c a + \c A: valid but discouraged (neither is a prefix of the other) + * \li \c AR + \em blank: valid (\c R is not in \c [A-F0-9]) + * \li \c ARB + \em blank: valid (there's no \c AR namespace, + * so the \c B doesn't cause ambiguity). + * \li \em blank + \c B: invalid, because it's ambiguous which address space \c B1234 would refer to. + * + * The length of the address space's name can't be used to disambugiate, + * as extra information may be appended to it without a separator. + */ const char *addrspace; /* TODO: When finalizing this one, add a description field, which should be @@ -2248,535 +3670,1325 @@ struct retro_memory_descriptor * them up. */ }; -/* The frontend may use the largest value of 'start'+'select' in a - * certain namespace to infer the size of the address space. +/** + * A list of regions within the emulated console's address space. * - * If the address space is larger than that, a mapping with .ptr=NULL - * should be at the end of the array, with .select set to all ones for - * as long as the address space is big. + * The frontend may use the largest value of + * \ref retro_memory_descriptor::start + \ref retro_memory_descriptor::select + * in a certain namespace to infer the overall size of the address space. + * If the address space is larger than that, + * the last mapping in \ref descriptors should have \ref retro_memory_descriptor::ptr set to \c NULL + * and \ref retro_memory_descriptor::select should have all bits used in the address space set to 1. * - * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): - * SNES WRAM: - * .start=0x7E0000, .len=0x20000 - * (Note that this must be mapped before the ROM in most cases; some of the - * ROM mappers - * try to claim $7E0000, or at least $7E8000.) - * SNES SPC700 RAM: - * .addrspace="S", .len=0x10000 - * SNES WRAM mirrors: - * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 - * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 - * SNES WRAM mirrors, alternate equivalent descriptor: - * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF - * (Various similar constructions can be created by combining parts of - * the above two.) - * SNES LoROM (512KB, mirrored a couple of times): - * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 - * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 - * SNES HiROM (4MB): - * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 - * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 - * SNES ExHiROM (8MB): - * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 - * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 - * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 - * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 - * Clarify the size of the address space: - * .ptr=NULL, .select=0xFFFFFF - * .len can be implied by .select in many of them, but was included for clarity. + * Here's an example set of descriptors for the SNES. + * + * @code{.c} + * struct retro_memory_map snes_descriptors = retro_memory_map + * { + * .descriptors = (struct retro_memory_descriptor[]) + * { + * // WRAM; must usually be mapped before the ROM, + * // as some SNES ROM mappers try to claim 0x7E0000 + * { .addrspace="WRAM", .start=0x7E0000, .len=0x20000 }, + * + * // SPC700 RAM + * { .addrspace="SPC700", .len=0x10000 }, + * + * // WRAM mirrors + * { .addrspace="WRAM", .start=0x000000, .select=0xC0E000, .len=0x2000 }, + * { .addrspace="WRAM", .start=0x800000, .select=0xC0E000, .len=0x2000 }, + * + * // WRAM mirror, alternate equivalent descriptor + * // (Various similar constructions can be created by combining parts of the above two.) + * { .addrspace="WRAM", .select=0x40E000, .disconnect=~0x1FFF }, + * + * // LoROM (512KB, mirrored a couple of times) + * { .addrspace="LoROM", .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024, .flags=RETRO_MEMDESC_CONST }, + * { .addrspace="LoROM", .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024, .flags=RETRO_MEMDESC_CONST }, + * + * // HiROM (4MB) + * { .addrspace="HiROM", .start=0x400000, .select=0x400000, .len=4*1024*1024, .flags=RETRO_MEMDESC_CONST }, + * { .addrspace="HiROM", .start=0x008000, .select=0x408000, .len=4*1024*1024, .offset=0x8000, .flags=RETRO_MEMDESC_CONST }, + * + * // ExHiROM (8MB) + * { .addrspace="ExHiROM", .start=0xC00000, .select=0xC00000, .len=4*1024*1024, .offset=0, .flags=RETRO_MEMDESC_CONST }, + * { .addrspace="ExHiROM", .start=0x400000, .select=0xC00000, .len=4*1024*1024, .offset=4*1024*1024, .flags=RETRO_MEMDESC_CONST }, + * { .addrspace="ExHiROM", .start=0x808000, .select=0xC08000, .len=4*1024*1024, .offset=0x8000, .flags=RETRO_MEMDESC_CONST }, + * { .addrspace="ExHiROM", .start=0x008000, .select=0xC08000, .len=4*1024*1024, .offset=4*1024*1024+0x8000, .flags=RETRO_MEMDESC_CONST }, + * + * // Clarifying the full size of the address space + * { .select=0xFFFFFF, .ptr=NULL }, + * }, + * .num_descriptors = 14, + * }; + * @endcode + * + * @see RETRO_ENVIRONMENT_SET_MEMORY_MAPS */ - struct retro_memory_map { + /** + * Pointer to an array of memory descriptors, + * each of which describes part of the emulated console's address space. + */ const struct retro_memory_descriptor *descriptors; + + /** The number of descriptors in \c descriptors. */ unsigned num_descriptors; }; +/** @} */ + +/** @defgroup SET_CONTROLLER_INFO Controller Info + * @{ + */ + +/** + * Details about a controller (or controller configuration) + * supported by one of a core's emulated input ports. + * + * @see RETRO_ENVIRONMENT_SET_CONTROLLER_INFO + */ struct retro_controller_description { - /* Human-readable description of the controller. Even if using a generic - * input device type, this can be set to the particular device type the - * core uses. */ + /** + * A human-readable label for the controller or configuration + * represented by this device type. + * Most likely the device's original brand name. + */ const char *desc; - /* Device type passed to retro_set_controller_port_device(). If the device - * type is a sub-class of a generic input device type, use the - * RETRO_DEVICE_SUBCLASS macro to create an ID. + /** + * A unique identifier that will be passed to \c retro_set_controller_port_device()'s \c device parameter. + * May be the ID of one of \ref RETRO_DEVICE "the generic controller types", + * or a subclass ID defined with \c RETRO_DEVICE_SUBCLASS. * - * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ + * @see RETRO_DEVICE_SUBCLASS + */ unsigned id; }; +/** + * Lists the types of controllers supported by + * one of core's emulated input ports. + * + * @see RETRO_ENVIRONMENT_SET_CONTROLLER_INFO + */ struct retro_controller_info { + + /** + * A pointer to an array of device types supported by this controller port. + * + * @note Ports that support the same devices + * may share the same underlying array. + */ const struct retro_controller_description *types; + + /** The number of elements in \c types. */ unsigned num_types; }; +/** @} */ + +/** @defgroup SET_SUBSYSTEM_INFO Subsystems + * @{ + */ + +/** + * Information about a type of memory associated with a subsystem. + * Usually used for SRAM (save RAM). + * + * @see RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO + * @see retro_get_memory_data + * @see retro_get_memory_size + */ struct retro_subsystem_memory_info { - /* The extension associated with a memory type, e.g. "psram". */ + /** + * The file extension the frontend should use + * to save this memory region to disk, e.g. "srm" or "sav". + */ const char *extension; - /* The memory type for retro_get_memory(). This should be at - * least 0x100 to avoid conflict with standardized - * libretro memory types. */ + /** + * A constant that identifies this type of memory. + * Should be at least 0x100 (256) to avoid conflict + * with the standard libretro memory types, + * unless a subsystem uses the main platform's memory region. + * @see RETRO_MEMORY + */ unsigned type; }; +/** + * Information about a type of ROM that a subsystem may use. + * Subsystems may use one or more ROMs at once, + * possibly of different types. + * + * @see RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO + * @see retro_subsystem_info + */ struct retro_subsystem_rom_info { - /* Describes what the content is (SGB BIOS, GB ROM, etc). */ + /** + * Human-readable description of what the content represents, + * e.g. "Game Boy ROM". + */ const char *desc; - /* Same definition as retro_get_system_info(). */ + /** @copydoc retro_system_info::valid_extensions */ const char *valid_extensions; - /* Same definition as retro_get_system_info(). */ + /** @copydoc retro_system_info::need_fullpath */ bool need_fullpath; - /* Same definition as retro_get_system_info(). */ + /** @copydoc retro_system_info::block_extract */ bool block_extract; - /* This is set if the content is required to load a game. - * If this is set to false, a zeroed-out retro_game_info can be passed. */ + /** + * Indicates whether this particular subsystem ROM is required. + * If \c true and the user doesn't provide a ROM, + * the frontend should not load the core. + * If \c false and the user doesn't provide a ROM, + * the frontend should pass a zeroed-out \c retro_game_info + * to the corresponding entry in \c retro_load_game_special(). + */ bool required; - /* Content can have multiple associated persistent - * memory types (retro_get_memory()). */ + /** + * Pointer to an array of memory descriptors that this subsystem ROM type uses. + * Useful for secondary cartridges that have their own save data. + * May be \c NULL, in which case this subsystem ROM's memory is not persisted by the frontend + * and \c num_memory should be zero. + */ const struct retro_subsystem_memory_info *memory; + + /** The number of elements in the array pointed to by \c memory. */ unsigned num_memory; }; +/** + * Information about a secondary platform that a core supports. + * @see RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO + */ struct retro_subsystem_info { - /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */ + /** + * A human-readable description of the subsystem type, + * usually the brand name of the original platform + * (e.g. "Super Game Boy"). + */ const char *desc; - /* A computer friendly short string identifier for the subsystem type. - * This name must be [a-z]. - * E.g. if desc is "Super GameBoy", this can be "sgb". - * This identifier can be used for command-line interfaces, etc. + /** + * A short machine-friendly identifier for the subsystem, + * usually an abbreviation of the platform name. + * For example, a Super Game Boy subsystem for a SNES core + * might use an identifier of "sgb". + * This identifier can be used for command-line interfaces, + * configuration, or other purposes. + * Must use lower-case alphabetical characters only (i.e. from a-z). */ const char *ident; - /* Infos for each content file. The first entry is assumed to be the - * "most significant" content for frontend purposes. + /** + * The list of ROM types that this subsystem may use. + * + * The first entry is considered to be the "most significant" content, + * for the purposes of the frontend's categorization. * E.g. with Super GameBoy, the first content should be the GameBoy ROM, * as it is the most "significant" content to a user. - * If a frontend creates new file paths based on the content used - * (e.g. savestates), it should use the path for the first ROM to do so. */ + * + * If a frontend creates new files based on the content used (e.g. for savestates), + * it should derive the filenames from the name of the first ROM in this list. + * + * @note \c roms can have a single element, + * but this is usually a sign that the core should broaden its + * primary system info instead. + * + * @see \c retro_system_info + */ const struct retro_subsystem_rom_info *roms; - /* Number of content files associated with a subsystem. */ + /** The length of the array given in \c roms. */ unsigned num_roms; - /* The type passed to retro_load_game_special(). */ + /** A unique identifier passed to retro_load_game_special(). */ unsigned id; }; +/** @} */ + +/** @defgroup SET_PROC_ADDRESS_CALLBACK Core Function Pointers + * @{ */ + +/** + * The function pointer type that \c retro_get_proc_address_t returns. + * + * Despite the signature shown here, the original function may include any parameters and return type + * that respects the calling convention and C ABI. + * + * The frontend is expected to cast the function pointer to the correct type. + */ typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); -/* libretro API extension functions: - * (None here so far). - * +/** * Get a symbol from a libretro core. - * Cores should only return symbols which are actual - * extensions to the libretro API. * - * Frontends should not use this to obtain symbols to standard - * libretro entry points (static linking or dlsym). + * Cores should only return symbols that serve as libretro extensions. + * Frontends should not use this to obtain symbols to standard libretro entry points; + * instead, they should link to the core statically or use \c dlsym (or local equivalent). * - * The symbol name must be equal to the function name, - * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". + * The symbol name must be equal to the function name. + * e.g. if void retro_foo(void); exists, the symbol in the compiled library must be called \c retro_foo. * The returned function pointer must be cast to the corresponding type. + * + * @param \c sym The name of the symbol to look up. + * @return Pointer to the exposed function with the name given in \c sym, + * or \c NULL if one couldn't be found. + * @note The frontend is expected to know the returned pointer's type in advance + * so that it can be cast correctly. + * @note The core doesn't need to expose every possible function through this interface. + * It's enough to only expose the ones that it expects the frontend to use. + * @note The functions exposed through this interface + * don't need to be publicly exposed in the compiled library + * (e.g. via \c __declspec(dllexport)). + * @see RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK */ typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym); +/** + * An interface that the frontend can use to get function pointers from the core. + * + * @note The returned function pointer will be invalidated once the core is unloaded. + * How and when that happens is up to the frontend. + * + * @see retro_get_proc_address_t + * @see RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK + */ struct retro_get_proc_address_interface { + /** Set by the core. */ retro_get_proc_address_t get_proc_address; }; +/** @} */ + +/** @defgroup GET_LOG_INTERFACE Logging + * @{ + */ + +/** + * The severity of a given message. + * The frontend may log messages differently depending on the level. + * It may also ignore log messages of a certain level. + * @see retro_log_callback + */ enum retro_log_level { + /** The logged message is most likely not interesting to the user. */ RETRO_LOG_DEBUG = 0, + + /** Information about the core operating normally. */ RETRO_LOG_INFO, + + /** Indicates a potential problem, possibly one that the core can recover from. */ RETRO_LOG_WARN, + + /** Indicates a degraded experience, if not failure. */ RETRO_LOG_ERROR, + /** Defined to ensure that sizeof(enum retro_log_level) == sizeof(int). Do not use. */ RETRO_LOG_DUMMY = INT_MAX }; -/* Logging function. Takes log level argument as well. */ +/** + * Logs a message to the frontend. + * + * @param level The log level of the message. + * @param fmt The format string to log. + * Same format as \c printf. + * Behavior is undefined if this is \c NULL. + * @param ... Zero or more arguments used by the format string. + * Behavior is undefined if these don't match the ones expected by \c fmt. + * @see retro_log_level + * @see retro_log_callback + * @see RETRO_ENVIRONMENT_GET_LOG_INTERFACE + * @see printf + */ typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level, const char *fmt, ...); +/** + * Details about how to make log messages. + * + * @see retro_log_printf_t + * @see RETRO_ENVIRONMENT_GET_LOG_INTERFACE + */ struct retro_log_callback { + /** + * Called when logging a message. + * + * @note Set by the frontend. + */ retro_log_printf_t log; }; -/* Performance related functions */ +/** @} */ -/* ID values for SIMD CPU features */ +/** @defgroup GET_PERF_INTERFACE Performance Interface + * @{ + */ + +/** @defgroup RETRO_SIMD CPU Features + * @{ + */ + +/** + * Indicates CPU support for the SSE instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ssetechs=SSE + */ #define RETRO_SIMD_SSE (1 << 0) + +/** + * Indicates CPU support for the SSE2 instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ssetechs=SSE2 + */ #define RETRO_SIMD_SSE2 (1 << 1) + +/** Indicates CPU support for the AltiVec (aka VMX or Velocity Engine) instruction set. */ #define RETRO_SIMD_VMX (1 << 2) + +/** Indicates CPU support for the VMX128 instruction set. Xbox 360 only. */ #define RETRO_SIMD_VMX128 (1 << 3) + +/** + * Indicates CPU support for the AVX instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#avxnewtechs=AVX + */ #define RETRO_SIMD_AVX (1 << 4) + +/** + * Indicates CPU support for the NEON instruction set. + * @see https://developer.arm.com/architectures/instruction-sets/intrinsics/#f:@navigationhierarchiessimdisa=[Neon] + */ #define RETRO_SIMD_NEON (1 << 5) + +/** + * Indicates CPU support for the SSE3 instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ssetechs=SSE3 + */ #define RETRO_SIMD_SSE3 (1 << 6) + +/** + * Indicates CPU support for the SSSE3 instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ssetechs=SSSE3 + */ #define RETRO_SIMD_SSSE3 (1 << 7) + +/** + * Indicates CPU support for the MMX instruction set. + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#techs=MMX + */ #define RETRO_SIMD_MMX (1 << 8) + +/** Indicates CPU support for the MMXEXT instruction set. */ #define RETRO_SIMD_MMXEXT (1 << 9) + +/** + * Indicates CPU support for the SSE4 instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ssetechs=SSE4_1 + */ #define RETRO_SIMD_SSE4 (1 << 10) + +/** + * Indicates CPU support for the SSE4.2 instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ssetechs=SSE4_2 + */ #define RETRO_SIMD_SSE42 (1 << 11) + +/** + * Indicates CPU support for the AVX2 instruction set. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#avxnewtechs=AVX2 + */ #define RETRO_SIMD_AVX2 (1 << 12) + +/** Indicates CPU support for the VFPU instruction set. PS2 and PSP only. + * + * @see https://pspdev.github.io/vfpu-docs + */ #define RETRO_SIMD_VFPU (1 << 13) + +/** + * Indicates CPU support for Gekko SIMD extensions. GameCube only. + */ #define RETRO_SIMD_PS (1 << 14) + +/** + * Indicates CPU support for AES instructions. + * + * @see https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#aestechs=AES&othertechs=AES + */ #define RETRO_SIMD_AES (1 << 15) + +/** + * Indicates CPU support for the VFPv3 instruction set. + */ #define RETRO_SIMD_VFPV3 (1 << 16) + +/** + * Indicates CPU support for the VFPv4 instruction set. + */ #define RETRO_SIMD_VFPV4 (1 << 17) + +/** Indicates CPU support for the POPCNT instruction. */ #define RETRO_SIMD_POPCNT (1 << 18) + +/** Indicates CPU support for the MOVBE instruction. */ #define RETRO_SIMD_MOVBE (1 << 19) + +/** Indicates CPU support for the CMOV instruction. */ #define RETRO_SIMD_CMOV (1 << 20) + +/** Indicates CPU support for the ASIMD instruction set. */ #define RETRO_SIMD_ASIMD (1 << 21) +/** @} */ + +/** + * An abstract unit of ticks. + * + * Usually nanoseconds or CPU cycles, + * but it depends on the platform and the frontend. + */ typedef uint64_t retro_perf_tick_t; + +/** Time in microseconds. */ typedef int64_t retro_time_t; +/** + * A performance counter. + * + * Use this to measure the execution time of a region of code. + * @see retro_perf_callback + */ struct retro_perf_counter { + /** + * A human-readable identifier for the counter. + * + * May be displayed by the frontend. + * Behavior is undefined if this is \c NULL. + */ const char *ident; + + /** + * The time of the most recent call to \c retro_perf_callback::perf_start + * on this performance counter. + * + * @see retro_perf_start_t + */ retro_perf_tick_t start; + + /** + * The total time spent within this performance counter's measured code, + * i.e. between calls to \c retro_perf_callback::perf_start and \c retro_perf_callback::perf_stop. + * + * Updated after each call to \c retro_perf_callback::perf_stop. + * @see retro_perf_stop_t + */ retro_perf_tick_t total; + + /** + * The number of times this performance counter has been started. + * + * Updated after each call to \c retro_perf_callback::perf_start. + * @see retro_perf_start_t + */ retro_perf_tick_t call_cnt; + /** + * \c true if this performance counter has been registered by the frontend. + * Must be initialized to \c false by the core before registering it. + * @see retro_perf_register_t + */ bool registered; }; -/* Returns current time in microseconds. - * Tries to use the most accurate timer available. +/** + * @returns The current system time in microseconds. + * @note Accuracy may vary by platform. + * The frontend should use the most accurate timer possible. + * @see RETRO_ENVIRONMENT_GET_PERF_INTERFACE */ typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void); -/* A simple counter. Usually nanoseconds, but can also be CPU cycles. - * Can be used directly if desired (when creating a more sophisticated - * performance counter system). - * */ +/** + * @returns The number of ticks since some unspecified epoch. + * The exact meaning of a "tick" depends on the platform, + * but it usually refers to nanoseconds or CPU cycles. + * @see RETRO_ENVIRONMENT_GET_PERF_INTERFACE + */ typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); -/* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ +/** + * Returns a bitmask of detected CPU features. + * + * Use this for runtime dispatching of CPU-specific code. + * + * @returns A bitmask of detected CPU features. + * @see RETRO_ENVIRONMENT_GET_PERF_INTERFACE + * @see RETRO_SIMD + */ typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void); -/* Asks frontend to log and/or display the state of performance counters. - * Performance counters can always be poked into manually as well. +/** + * Asks the frontend to log or display the state of performance counters. + * How this is done depends on the frontend. + * Performance counters can be reviewed manually as well. + * + * @see RETRO_ENVIRONMENT_GET_PERF_INTERFACE + * @see retro_perf_counter */ typedef void (RETRO_CALLCONV *retro_perf_log_t)(void); -/* Register a performance counter. - * ident field must be set with a discrete value and other values in - * retro_perf_counter must be 0. - * Registering can be called multiple times. To avoid calling to - * frontend redundantly, you can check registered field first. */ +/** + * Registers a new performance counter. + * + * If \c counter has already been registered beforehand, + * this function does nothing. + * + * @param counter The counter to register. + * \c counter::ident must be set to a unique identifier, + * and all other values in \c counter must be set to zero or \c false. + * Behavior is undefined if \c NULL. + * @post If \c counter is successfully registered, + * then \c counter::registered will be set to \c true. + * Otherwise, it will be set to \c false. + * Registration may fail if the frontend's maximum number of counters (if any) has been reached. + * @note The counter is owned by the core and must not be freed by the frontend. + * The frontend must also clean up any references to a core's performance counters + * before unloading it, otherwise undefined behavior may occur. + * @see retro_perf_start_t + * @see retro_perf_stop_t + */ typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); -/* Starts a registered counter. */ +/** + * Starts a registered performance counter. + * + * Call this just before the code you want to measure. + * + * @param counter The counter to start. + * Behavior is undefined if \c NULL. + * @see retro_perf_stop_t + */ typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter); -/* Stops a registered counter. */ +/** + * Stops a registered performance counter. + * + * Call this just after the code you want to measure. + * + * @param counter The counter to stop. + * Behavior is undefined if \c NULL. + * @see retro_perf_start_t + * @see retro_perf_stop_t + */ typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *counter); -/* For convenience it can be useful to wrap register, start and stop in macros. - * E.g.: - * #ifdef LOG_PERFORMANCE +/** + * An interface that the core can use to get performance information. + * + * Here's a usage example: + * + * @code{.c} + * #ifdef PROFILING + * // Wrapper macros to simplify using performance counters. + * // Optional; tailor these to your project's needs. * #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) * #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) * #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) * #else - * ... Blank macros ... + * // Exclude the performance counters if profiling is disabled. + * #define RETRO_PERFORMANCE_INIT(perf_cb, name) ((void)0) + * #define RETRO_PERFORMANCE_START(perf_cb, name) ((void)0) + * #define RETRO_PERFORMANCE_STOP(perf_cb, name) ((void)0) * #endif * - * These can then be used mid-functions around code snippets. + * // Defined somewhere else in the core. + * extern struct retro_perf_callback perf_cb; * - * extern struct retro_perf_callback perf_cb; * Somewhere in the core. - * - * void do_some_heavy_work(void) + * void retro_run(void) * { - * RETRO_PERFORMANCE_INIT(cb, work_1; - * RETRO_PERFORMANCE_START(cb, work_1); - * heavy_work_1(); - * RETRO_PERFORMANCE_STOP(cb, work_1); + * RETRO_PERFORMANCE_INIT(cb, interesting); + * RETRO_PERFORMANCE_START(cb, interesting); + * interesting_work(); + * RETRO_PERFORMANCE_STOP(cb, interesting); * - * RETRO_PERFORMANCE_INIT(cb, work_2); - * RETRO_PERFORMANCE_START(cb, work_2); - * heavy_work_2(); - * RETRO_PERFORMANCE_STOP(cb, work_2); + * RETRO_PERFORMANCE_INIT(cb, maybe_slow); + * RETRO_PERFORMANCE_START(cb, maybe_slow); + * more_interesting_work(); + * RETRO_PERFORMANCE_STOP(cb, maybe_slow); * } * * void retro_deinit(void) * { - * perf_cb.perf_log(); * Log all perf counters here for example. + * // Asks the frontend to log the results of all performance counters. + * perf_cb.perf_log(); * } + * @endcode + * + * All functions are set by the frontend. + * + * @see RETRO_ENVIRONMENT_GET_PERF_INTERFACE */ - struct retro_perf_callback { + /** @copydoc retro_perf_get_time_usec_t */ retro_perf_get_time_usec_t get_time_usec; + + /** @copydoc retro_perf_get_counter_t */ retro_get_cpu_features_t get_cpu_features; + /** @copydoc retro_perf_get_counter_t */ retro_perf_get_counter_t get_perf_counter; + + /** @copydoc retro_perf_register_t */ retro_perf_register_t perf_register; + + /** @copydoc retro_perf_start_t */ retro_perf_start_t perf_start; + + /** @copydoc retro_perf_stop_t */ retro_perf_stop_t perf_stop; + + /** @copydoc retro_perf_log_t */ retro_perf_log_t perf_log; }; -/* FIXME: Document the sensor API and work out behavior. - * It will be marked as experimental until then. +/** @} */ + +/** + * @defgroup RETRO_SENSOR Sensor Interface + * @{ + */ + +/** + * Defines actions that can be performed on sensors. + * @note Cores should only enable sensors while they're actively being used; + * depending on the frontend and platform, + * enabling these sensors may impact battery life. + * + * @see RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE + * @see retro_sensor_interface + * @see retro_set_sensor_state_t */ enum retro_sensor_action { + /** Enables accelerometer input, if one exists. */ RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, + + /** Disables accelerometer input, if one exists. */ RETRO_SENSOR_ACCELEROMETER_DISABLE, + + /** Enables gyroscope input, if one exists. */ RETRO_SENSOR_GYROSCOPE_ENABLE, + + /** Disables gyroscope input, if one exists. */ RETRO_SENSOR_GYROSCOPE_DISABLE, + + /** Enables ambient light input, if a luminance sensor exists. */ RETRO_SENSOR_ILLUMINANCE_ENABLE, + + /** Disables ambient light input, if a luminance sensor exists. */ RETRO_SENSOR_ILLUMINANCE_DISABLE, + /** @private Defined to ensure sizeof(enum retro_sensor_action) == sizeof(int). Do not use. */ RETRO_SENSOR_DUMMY = INT_MAX }; +/** @defgroup RETRO_SENSOR_ID Sensor Value IDs + * @{ + */ /* Id values for SENSOR types. */ -#define RETRO_SENSOR_ACCELEROMETER_X 0 -#define RETRO_SENSOR_ACCELEROMETER_Y 1 -#define RETRO_SENSOR_ACCELEROMETER_Z 2 -#define RETRO_SENSOR_GYROSCOPE_X 3 -#define RETRO_SENSOR_GYROSCOPE_Y 4 -#define RETRO_SENSOR_GYROSCOPE_Z 5 -#define RETRO_SENSOR_ILLUMINANCE 6 +/** + * Returns the device's acceleration along its local X axis minus the effect of gravity, in m/s^2. + * + * Positive values mean that the device is accelerating to the right. + * assuming the user is looking at it head-on. + */ +#define RETRO_SENSOR_ACCELEROMETER_X 0 + +/** + * Returns the device's acceleration along its local Y axis minus the effect of gravity, in m/s^2. + * + * Positive values mean that the device is accelerating upwards, + * assuming the user is looking at it head-on. + */ +#define RETRO_SENSOR_ACCELEROMETER_Y 1 + +/** + * Returns the the device's acceleration along its local Z axis minus the effect of gravity, in m/s^2. + * + * Positive values indicate forward acceleration towards the user, + * assuming the user is looking at the device head-on. + */ +#define RETRO_SENSOR_ACCELEROMETER_Z 2 + +/** + * Returns the angular velocity of the device around its local X axis, in radians per second. + * + * Positive values indicate counter-clockwise rotation. + * + * @note A radian is about 57 degrees, and a full 360-degree rotation is 2*pi radians. + * @see https://developer.android.com/reference/android/hardware/SensorEvent#sensor.type_gyroscope + * for guidance on using this value to derive a device's orientation. + */ +#define RETRO_SENSOR_GYROSCOPE_X 3 + +/** + * Returns the angular velocity of the device around its local Z axis, in radians per second. + * + * Positive values indicate counter-clockwise rotation. + * + * @note A radian is about 57 degrees, and a full 360-degree rotation is 2*pi radians. + * @see https://developer.android.com/reference/android/hardware/SensorEvent#sensor.type_gyroscope + * for guidance on using this value to derive a device's orientation. + */ +#define RETRO_SENSOR_GYROSCOPE_Y 4 + +/** + * Returns the angular velocity of the device around its local Z axis, in radians per second. + * + * Positive values indicate counter-clockwise rotation. + * + * @note A radian is about 57 degrees, and a full 360-degree rotation is 2*pi radians. + * @see https://developer.android.com/reference/android/hardware/SensorEvent#sensor.type_gyroscope + * for guidance on using this value to derive a device's orientation. + */ +#define RETRO_SENSOR_GYROSCOPE_Z 5 + +/** + * Returns the ambient illuminance (light intensity) of the device's environment, in lux. + * + * @see https://en.wikipedia.org/wiki/Lux for a table of common lux values. + */ +#define RETRO_SENSOR_ILLUMINANCE 6 +/** @} */ + +/** + * Adjusts the state of a sensor. + * + * @param port The device port of the controller that owns the sensor given in \c action. + * @param action The action to perform on the sensor. + * Different devices support different sensors. + * @param rate The rate at which the underlying sensor should be updated, in Hz. + * This should be treated as a hint, + * as some device sensors may not support the requested rate + * (if it's configurable at all). + * @returns \c true if the sensor state was successfully adjusted, \c false otherwise. + * @note If one of the \c RETRO_SENSOR_*_ENABLE actions fails, + * this likely means that the given sensor is not available + * on the provided \c port. + * @see retro_sensor_action + */ typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate); +/** + * Retrieves the current value reported by sensor. + * @param port The device port of the controller that owns the sensor given in \c id. + * @param id The sensor value to query. + * @returns The current sensor value. + * Exact semantics depend on the value given in \c id, + * but will return 0 for invalid arguments. + * + * @see RETRO_SENSOR_ID + */ typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); +/** + * An interface that cores can use to access device sensors. + * + * All function pointers are set by the frontend. + */ struct retro_sensor_interface { + /** @copydoc retro_set_sensor_state_t */ retro_set_sensor_state_t set_sensor_state; + + /** @copydoc retro_sensor_get_input_t */ retro_sensor_get_input_t get_sensor_input; }; +/** @} */ + +/** @defgroup GET_CAMERA_INTERFACE Camera Interface + * @{ + */ + +/** + * Denotes the type of buffer in which the camera will store its input. + * + * Different camera drivers may support different buffer types. + * + * @see RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE + * @see retro_camera_callback + */ enum retro_camera_buffer { + /** + * Indicates that camera frames should be delivered to the core as an OpenGL texture. + * + * Requires that the core is using an OpenGL context via \c RETRO_ENVIRONMENT_SET_HW_RENDER. + * + * @see retro_camera_frame_opengl_texture_t + */ RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, + + /** + * Indicates that camera frames should be delivered to the core as a raw buffer in memory. + * + * @see retro_camera_frame_raw_framebuffer_t + */ RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, + /** + * @private Defined to ensure sizeof(enum retro_camera_buffer) == sizeof(int). + * Do not use. + */ RETRO_CAMERA_BUFFER_DUMMY = INT_MAX }; -/* Starts the camera driver. Can only be called in retro_run(). */ +/** + * Starts an initialized camera. + * The camera is disabled by default, + * and must be enabled with this function before being used. + * + * Set by the frontend. + * + * @returns \c true if the camera was successfully started, \c false otherwise. + * Failure may occur if no actual camera is available, + * or if the frontend doesn't have permission to access it. + * @note Must be called in \c retro_run(). + * @see retro_camera_callback + */ typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); -/* Stops the camera driver. Can only be called in retro_run(). */ +/** + * Stops the running camera. + * + * Set by the frontend. + * + * @note Must be called in \c retro_run(). + * @warning The frontend may close the camera on its own when unloading the core, + * but this behavior is not guaranteed. + * Cores should clean up the camera before exiting. + * @see retro_camera_callback + */ typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); -/* Callback which signals when the camera driver is initialized - * and/or deinitialized. - * retro_camera_start_t can be called in initialized callback. +/** + * Called by the frontend to report the state of the camera driver. + * + * @see retro_camera_callback */ typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); -/* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. - * Width, height and pitch are similar to retro_video_refresh_t. - * First pixel is top-left origin. +/** + * Called by the frontend to report a new camera frame, + * delivered as a raw buffer in memory. + * + * Set by the core. + * + * @param buffer Pointer to the camera's most recent video frame. + * Each pixel is in XRGB8888 format. + * The first pixel represents the top-left corner of the image + * (i.e. the Y axis goes downward). + * @param width The width of the frame given in \c buffer, in pixels. + * @param height The height of the frame given in \c buffer, in pixels. + * @param pitch The width of the frame given in \c buffer, in bytes. + * @warning \c buffer may be invalidated when this function returns, + * so the core should make its own copy of \c buffer if necessary. + * @see RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER */ typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch); -/* A callback for when OpenGL textures are used. +/** + * Called by the frontend to report a new camera frame, + * delivered as an OpenGL texture. * - * texture_id is a texture owned by camera driver. - * Its state or content should be considered immutable, except for things like - * texture filtering and clamping. + * @param texture_id The ID of the OpenGL texture that represents the camera's most recent frame. + * Owned by the frontend, and must not be modified by the core. + * @param texture_target The type of the texture given in \c texture_id. + * Usually either \c GL_TEXTURE_2D or \c GL_TEXTURE_RECTANGLE, + * but other types are allowed. + * @param affine A pointer to a 3x3 column-major affine matrix + * that can be used to transform pixel coordinates to texture coordinates. + * After transformation, the bottom-left corner should have coordinates of (0, 0) + * and the top-right corner should have coordinates of (1, 1) + * (or (width, height) for \c GL_TEXTURE_RECTANGLE). * - * texture_target is the texture target for the GL texture. - * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly - * more depending on extensions. - * - * affine points to a packed 3x3 column-major matrix used to apply an affine - * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) - * After transform, normalized texture coord (0, 0) should be bottom-left - * and (1, 1) should be top-right (or (width, height) for RECTANGLE). - * - * GL-specific typedefs are avoided here to avoid relying on gl.h in - * the API definition. + * @note GL-specific typedefs (e.g. \c GLfloat and \c GLuint) are avoided here + * so that the API doesn't rely on gl.h. + * @warning \c texture_id and \c affine may be invalidated when this function returns, + * so the core should make its own copy of them if necessary. */ typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine); +/** + * An interface that the core can use to access a device's camera. + * + * @see RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE + */ struct retro_camera_callback { - /* Set by libretro core. - * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). + /** + * Requested camera capabilities, + * given as a bitmask of \c retro_camera_buffer values. + * Set by the core. + * + * Here's a usage example: + * @code + * // Requesting support for camera data delivered as both an OpenGL texture and a pixel buffer: + * struct retro_camera_callback callback; + * callback.caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER); + * @endcode */ uint64_t caps; - /* Desired resolution for camera. Is only used as a hint. */ + /** + * The desired width of the camera frame, in pixels. + * This is only a hint; the frontend may provide a different size. + * Set by the core. + * Use zero to let the frontend decide. + */ unsigned width; + + /** + * The desired height of the camera frame, in pixels. + * This is only a hint; the frontend may provide a different size. + * Set by the core. + * Use zero to let the frontend decide. + */ unsigned height; - /* Set by frontend. */ + /** + * @copydoc retro_camera_start_t + * @see retro_camera_callback + */ retro_camera_start_t start; + + /** + * @copydoc retro_camera_stop_t + * @see retro_camera_callback + */ retro_camera_stop_t stop; - /* Set by libretro core if raw framebuffer callbacks will be used. */ + /** + * @copydoc retro_camera_frame_raw_framebuffer_t + * @note If \c NULL, this function will not be called. + */ retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; - /* Set by libretro core if OpenGL texture callbacks will be used. */ + /** + * @copydoc retro_camera_frame_opengl_texture_t + * @note If \c NULL, this function will not be called. + */ retro_camera_frame_opengl_texture_t frame_opengl_texture; - /* Set by libretro core. Called after camera driver is initialized and - * ready to be started. - * Can be NULL, in which this callback is not called. + /** + * Core-defined callback invoked by the frontend right after the camera driver is initialized + * (\em not when calling \c start). + * May be \c NULL, in which case this function is skipped. */ retro_camera_lifetime_status_t initialized; - /* Set by libretro core. Called right before camera driver is - * deinitialized. - * Can be NULL, in which this callback is not called. + /** + * Core-defined callback invoked by the frontend + * right before the video camera driver is deinitialized + * (\em not when calling \c stop). + * May be \c NULL, in which case this function is skipped. */ retro_camera_lifetime_status_t deinitialized; }; -/* Sets the interval of time and/or distance at which to update/poll - * location-based data. - * - * To ensure compatibility with all location-based implementations, - * values for both interval_ms and interval_distance should be provided. - * - * interval_ms is the interval expressed in milliseconds. - * interval_distance is the distance interval expressed in meters. +/** @} */ + +/** @defgroup GET_LOCATION_INTERFACE Location Interface + * @{ */ + +/** @copydoc retro_location_callback::set_interval */ typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_ms, unsigned interval_distance); -/* Start location services. The device will start listening for changes to the - * current location at regular intervals (which are defined with - * retro_location_set_interval_t). */ +/** @copydoc retro_location_callback::start */ typedef bool (RETRO_CALLCONV *retro_location_start_t)(void); -/* Stop location services. The device will stop listening for changes - * to the current location. */ +/** @copydoc retro_location_callback::stop */ typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); -/* Get the position of the current location. Will set parameters to - * 0 if no new location update has happened since the last time. */ +/** @copydoc retro_location_callback::get_position */ typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy, double *vert_accuracy); -/* Callback which signals when the location driver is initialized - * and/or deinitialized. - * retro_location_start_t can be called in initialized callback. - */ +/** Function type that reports the status of the location service. */ typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); +/** + * An interface that the core can use to access a device's location. + * + * @note It is the frontend's responsibility to request the necessary permissions + * from the operating system. + * @see RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE + */ struct retro_location_callback { + /** + * Starts listening the device's location service. + * + * The frontend will report changes to the device's location + * at the interval defined by \c set_interval. + * Set by the frontend. + * + * @return true if location services were successfully started, false otherwise. + * Note that this will return \c false if location services are disabled + * or the frontend doesn't have permission to use them. + * @note The device's location service may or may not have been enabled + * before the core calls this function. + */ retro_location_start_t start; + + /** + * Stop listening to the device's location service. + * + * Set by the frontend. + * + * @note The location service itself may or may not + * be turned off by this function, + * depending on the platform and the frontend. + * @post The core will stop receiving location service updates. + */ retro_location_stop_t stop; + + /** + * Returns the device's current coordinates. + * + * Set by the frontend. + * + * @param[out] lat Pointer to latitude, in degrees. + * Will be set to 0 if no change has occurred since the last call. + * Behavior is undefined if \c NULL. + * @param[out] lon Pointer to longitude, in degrees. + * Will be set to 0 if no change has occurred since the last call. + * Behavior is undefined if \c NULL. + * @param[out] horiz_accuracy Pointer to horizontal accuracy. + * Will be set to 0 if no change has occurred since the last call. + * Behavior is undefined if \c NULL. + * @param[out] vert_accuracy Pointer to vertical accuracy. + * Will be set to 0 if no change has occurred since the last call. + * Behavior is undefined if \c NULL. + */ retro_location_get_position_t get_position; + + /** + * Sets the rate at which the location service should report updates. + * + * This is only a hint; the actual rate may differ. + * Sets the interval of time and/or distance at which to update/poll + * location-based data. + * + * Some platforms may only support one of the two parameters; + * cores should provide both to ensure compatibility. + * + * Set by the frontend. + * + * @param interval_ms The desired period of time between location updates, in milliseconds. + * @param interval_distance The desired distance between location updates, in meters. + */ retro_location_set_interval_t set_interval; + /** Called when the location service is initialized. Set by the core. Optional. */ retro_location_lifetime_status_t initialized; + + /** Called when the location service is deinitialized. Set by the core. Optional. */ retro_location_lifetime_status_t deinitialized; }; +/** @} */ + +/** @addtogroup GET_RUMBLE_INTERFACE + * @{ */ + +/** + * The type of rumble motor in a controller. + * + * Both motors can be controlled independently, + * and the strong motor does not override the weak motor. + * @see RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE + */ enum retro_rumble_effect { RETRO_RUMBLE_STRONG = 0, RETRO_RUMBLE_WEAK = 1, + /** @private Defined to ensure sizeof(enum retro_rumble_effect) == sizeof(int). Do not use. */ RETRO_RUMBLE_DUMMY = INT_MAX }; -/* Sets rumble state for joypad plugged in port 'port'. - * Rumble effects are controlled independently, - * and setting e.g. strong rumble does not override weak rumble. - * Strength has a range of [0, 0xffff]. +/** + * Requests a rumble state change for a controller. + * Set by the frontend. * - * Returns true if rumble state request was honored. - * Calling this before first retro_run() is likely to return false. */ + * @param port The controller port to set the rumble state for. + * @param effect The rumble motor to set the strength of. + * @param strength The desired intensity of the rumble motor, ranging from \c 0 to \c 0xffff (inclusive). + * @return \c true if the requested rumble state was honored. + * If the controller doesn't support rumble, will return \c false. + * @note Calling this before the first \c retro_run() may return \c false. + * @see RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE + */ typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength); +/** + * An interface that the core can use to set the rumble state of a controller. + * @see RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE + */ struct retro_rumble_interface { + /** @copydoc retro_set_rumble_state_t */ retro_set_rumble_state_t set_rumble_state; }; -/* Notifies libretro that audio data should be written. */ +/** @} */ + +/** + * Called by the frontend to request audio samples. + * The core should render audio within this function + * using the callback provided by \c retro_set_audio_sample or \c retro_set_audio_sample_batch. + * + * @warning This function may be called by any thread, + * therefore it must be thread-safe. + * @see RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK + * @see retro_audio_callback + * @see retro_audio_sample_batch_t + * @see retro_audio_sample_t + */ typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); -/* True: Audio driver in frontend is active, and callback is - * expected to be called regularily. - * False: Audio driver in frontend is paused or inactive. - * Audio callback will not be called until set_state has been - * called with true. - * Initial state is false (inactive). +/** + * Called by the frontend to notify the core that it should pause or resume audio rendering. + * The initial state of the audio driver after registering this callback is \c false (inactive). + * + * @param enabled \c true if the frontend's audio driver is active. + * If so, the registered audio callback will be called regularly. + * If not, the audio callback will not be invoked until the next time + * the frontend calls this function with \c true. + * @warning This function may be called by any thread, + * therefore it must be thread-safe. + * @note Even if no audio samples are rendered, + * the core should continue to update its emulated platform's audio engine if necessary. + * @see RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK + * @see retro_audio_callback + * @see retro_audio_callback_t */ typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); +/** + * An interface that the frontend uses to request audio samples from the core. + * @note To unregister a callback, pass a \c retro_audio_callback_t + * with both fields set to NULL. + * @see RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK + */ struct retro_audio_callback { + /** @see retro_audio_callback_t */ retro_audio_callback_t callback; + + /** @see retro_audio_set_state_callback_t */ retro_audio_set_state_callback_t set_state; }; -/* Notifies a libretro core of time spent since last invocation - * of retro_run() in microseconds. - * - * It will be called right before retro_run() every frame. - * The frontend can tamper with timing to support cases like - * fast-forward, slow-motion and framestepping. - * - * In those scenarios the reference frame time value will be used. */ typedef int64_t retro_usec_t; + +/** + * Called right before each iteration of \c retro_run + * if registered via RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK. + * + * @param usec Time since the last call to retro_run, in microseconds. + * If the frontend is manipulating the frame time + * (e.g. via fast-forward or slow motion), + * this value will be the reference value initially provided to the environment call. + * @see RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK + * @see retro_frame_time_callback + */ typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); + +/** + * @see RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK + */ struct retro_frame_time_callback { + /** + * Called to notify the core of the current frame time. + * If NULL, the frontend will clear its registered callback. + */ retro_frame_time_callback_t callback; - /* Represents the time of one frame. It is computed as - * 1000000 / fps, but the implementation will resolve the - * rounding to ensure that framestepping, etc is exact. */ + + /** + * The ideal duration of one frame, in microseconds. + * Compute it as 1000000 / fps. + * The frontend will resolve rounding to ensure that framestepping, etc is exact. + */ retro_usec_t reference; }; -/* Notifies a libretro core of the current occupancy - * level of the frontend audio buffer. +/** @defgroup SET_AUDIO_BUFFER_STATUS_CALLBACK Audio Buffer Occupancy + * @{ + */ + +/** + * Notifies a libretro core of how full the frontend's audio buffer is. + * Set by the core, called by the frontend. + * It will be called right before \c retro_run() every frame. * - * - active: 'true' if audio buffer is currently - * in use. Will be 'false' if audio is - * disabled in the frontend - * - * - occupancy: Given as a value in the range [0,100], - * corresponding to the occupancy percentage - * of the audio buffer - * - * - underrun_likely: 'true' if the frontend expects an - * audio buffer underrun during the - * next frame (indicates that a core - * should attempt frame skipping) - * - * It will be called right before retro_run() every frame. */ + * @param active \c true if the frontend's audio buffer is currently in use, + * \c false if audio is disabled in the frontend. + * @param occupancy A value between 0 and 100 (inclusive), + * corresponding to the frontend's audio buffer occupancy percentage. + * @param underrun_likely \c true if the frontend expects an audio buffer underrun + * during the next frame, which indicates that a core should attempt frame-skipping. + */ typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)( bool active, unsigned occupancy, bool underrun_likely); + +/** + * A callback to register with the frontend to receive audio buffer occupancy information. + */ struct retro_audio_buffer_status_callback { + /** @copydoc retro_audio_buffer_status_callback_t */ retro_audio_buffer_status_callback_t callback; }; +/** @} */ + /* Pass this to retro_video_refresh_t if rendering to hardware. * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. * */ @@ -2832,6 +5044,7 @@ enum retro_hw_context_type /* Direct3D9, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */ RETRO_HW_CONTEXT_D3D9 = 10, + /** Dummy value to ensure sizeof(enum retro_hw_context_type) == sizeof(int). Do not use. */ RETRO_HW_CONTEXT_DUMMY = INT_MAX }; @@ -2945,146 +5158,297 @@ struct retro_keyboard_callback retro_keyboard_event_t callback; }; -/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE & - * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE. - * Should be set for implementations which can swap out multiple disk - * images in runtime. +/** @defgroup SET_DISK_CONTROL_INTERFACE Disk Control * - * If the implementation can do this automatically, it should strive to do so. - * However, there are cases where the user must manually do so. + * Callbacks for inserting and removing disks from the emulated console at runtime. + * Should be provided by cores that support doing so. + * Cores should automate this process if possible, + * but some cases require the player's manual input. * - * Overview: To swap a disk image, eject the disk image with - * set_eject_state(true). - * Set the disk index with set_image_index(index). Insert the disk again - * with set_eject_state(false). + * The steps for swapping disk images are generally as follows: + * + * \li Eject the emulated console's disk drive with \c set_eject_state(true). + * \li Insert the new disk image with \c set_image_index(index). + * \li Close the virtual disk tray with \c set_eject_state(false). + * + * @{ */ -/* If ejected is true, "ejects" the virtual disk tray. - * When ejected, the disk image index can be set. +/** + * Called by the frontend to open or close the emulated console's virtual disk tray. + * + * The frontend may only set the disk image index + * while the emulated tray is opened. + * + * If the emulated console's disk tray is already in the state given by \c ejected, + * then this function should return \c true without doing anything. + * The core should return \c false if it couldn't change the disk tray's state; + * this may happen if the console itself limits when the disk tray can be open or closed + * (e.g. to wait for the disc to stop spinning). + * + * @param ejected \c true if the virtual disk tray should be "ejected", + * \c false if it should be "closed". + * @return \c true if the virtual disk tray's state has been set to the given state, + * false if there was an error. + * @see retro_get_eject_state_t */ typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected); -/* Gets current eject state. The initial state is 'not ejected'. */ +/** + * Gets the current ejected state of the disk drive. + * The initial state is closed, i.e. \c false. + * + * @return \c true if the virtual disk tray is "ejected", + * i.e. it's open and a disk can be inserted. + * @see retro_set_eject_state_t + */ typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); -/* Gets current disk index. First disk is index 0. - * If return value is >= get_num_images(), no disk is currently inserted. +/** + * Gets the index of the current disk image, + * as determined by however the frontend orders disk images + * (such as m3u-formatted playlists or special directories). + * + * @return The index of the current disk image + * (starting with 0 for the first disk), + * or a value greater than or equal to \c get_num_images() if no disk is inserted. + * @see retro_get_num_images_t */ typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); -/* Sets image index. Can only be called when disk is ejected. - * The implementation supports setting "no disk" by using an - * index >= get_num_images(). +/** + * Inserts the disk image at the given index into the emulated console's drive. + * Can only be called while the disk tray is ejected + * (i.e. \c retro_get_eject_state_t returns \c true). + * + * If the emulated disk tray is ejected + * and already contains the disk image named by \c index, + * then this function should do nothing and return \c true. + * + * @param index The index of the disk image to insert, + * starting from 0 for the first disk. + * A value greater than or equal to \c get_num_images() + * represents the frontend removing the disk without inserting a new one. + * @return \c true if the disk image was successfully set. + * \c false if the disk tray isn't ejected or there was another error + * inserting a new disk image. */ typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); -/* Gets total number of images which are available to use. */ +/** + * @return The number of disk images which are available to use. + * These are most likely defined in a playlist file. + */ typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); struct retro_game_info; -/* Replaces the disk image associated with index. +/** + * Replaces the disk image at the given index with a new disk. + * + * Replaces the disk image associated with index. * Arguments to pass in info have same requirements as retro_load_game(). * Virtual disk tray must be ejected when calling this. * - * Replacing a disk image with info = NULL will remove the disk image - * from the internal list. - * As a result, calls to get_image_index() can change. + * Passing \c NULL to this function indicates + * that the frontend has removed this disk image from its internal list. + * As a result, calls to this function can change the number of available disk indexes. * - * E.g. replace_image_index(1, NULL), and previous get_image_index() - * returned 4 before. - * Index 1 will be removed, and the new index is 3. + * For example, calling replace_image_index(1, NULL) + * will remove the disk image at index 1, + * and the disk image at index 2 (if any) + * will be moved to the newly-available index 1. + * + * @param index The index of the disk image to replace. + * @param info Details about the new disk image, + * or \c NULL if the disk image at the given index should be discarded. + * The semantics of each field are the same as in \c retro_load_game. + * @return \c true if the disk image was successfully replaced + * or removed from the playlist, + * \c false if the tray is not ejected + * or if there was an error. */ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, const struct retro_game_info *info); -/* Adds a new valid index (get_num_images()) to the internal disk list. - * This will increment subsequent return values from get_num_images() by 1. +/** + * Adds a new index to the core's internal disk list. + * This will increment the return value from \c get_num_images() by 1. * This image index cannot be used until a disk image has been set - * with replace_image_index. */ + * with \c replace_image_index. + * + * @return \c true if the core has added space for a new disk image + * and is ready to receive one. + */ typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); -/* Sets initial image to insert in drive when calling - * core_load_game(). - * Since we cannot pass the initial index when loading - * content (this would require a major API change), this - * is set by the frontend *before* calling the core's - * retro_load_game()/retro_load_game_special() implementation. - * A core should therefore cache the index/path values and handle - * them inside retro_load_game()/retro_load_game_special(). - * - If 'index' is invalid (index >= get_num_images()), the - * core should ignore the set value and instead use 0 - * - 'path' is used purely for error checking - i.e. when - * content is loaded, the core should verify that the - * disk specified by 'index' has the specified file path. - * This is to guard against auto selecting the wrong image - * if (for example) the user should modify an existing M3U - * playlist. We have to let the core handle this because - * set_initial_image() must be called before loading content, - * i.e. the frontend cannot access image paths in advance - * and thus cannot perform the error check itself. - * If set path and content path do not match, the core should - * ignore the set 'index' value and instead use 0 - * Returns 'false' if index or 'path' are invalid, or core - * does not support this functionality +/** + * Sets the disk image that will be inserted into the emulated disk drive + * before \c retro_load_game is called. + * + * \c retro_load_game does not provide a way to ensure + * that a particular disk image in a playlist is inserted into the console; + * this function makes up for that. + * Frontends should call it immediately before \c retro_load_game, + * and the core should use the arguments + * to validate the disk image in \c retro_load_game. + * + * When content is loaded, the core should verify that the + * disk specified by \c index can be found at \c path. + * This is to guard against auto-selecting the wrong image + * if (for example) the user should modify an existing M3U playlist. + * We have to let the core handle this because + * \c set_initial_image() must be called before loading content, + * i.e. the frontend cannot access image paths in advance + * and thus cannot perform the error check itself. + * If \c index is invalid (i.e. index >= get_num_images()) + * or the disk image doesn't match the value given in \c path, + * the core should ignore the arguments + * and insert the disk at index 0 into the virtual disk tray. + * + * @warning If \c RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE is called within \c retro_load_game, + * then this function may not be executed. + * Set the disk control interface in \c retro_init if possible. + * + * @param index The index of the disk image within the playlist to set. + * @param path The path of the disk image to set as the first. + * The core should not load this path immediately; + * instead, it should use it within \c retro_load_game + * to verify that the correct disk image was loaded. + * @return \c true if the initial disk index was set, + * \c false if the arguments are invalid + * or the core doesn't support this function. */ typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path); -/* Fetches the path of the specified disk image file. - * Returns 'false' if index is invalid (index >= get_num_images()) - * or path is otherwise unavailable. +/** + * Returns the path of the disk image at the given index + * on the host's file system. + * + * @param index The index of the disk image to get the path of. + * @param path A buffer to store the path in. + * @param len The size of \c path, in bytes. + * @return \c true if the disk image's location was successfully + * queried and copied into \c path, + * \c false if the index is invalid + * or the core couldn't locate the disk image. */ typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len); -/* Fetches a core-provided 'label' for the specified disk - * image file. In the simplest case this may be a file name - * (without extension), but for cores with more complex - * content requirements information may be provided to - * facilitate user disk swapping - for example, a core - * running floppy-disk-based content may uniquely label - * save disks, data disks, level disks, etc. with names - * corresponding to in-game disk change prompts (so the - * frontend can provide better user guidance than a 'dumb' - * disk index value). - * Returns 'false' if index is invalid (index >= get_num_images()) - * or label is otherwise unavailable. +/** + * Returns a friendly label for the given disk image. + * + * In the simplest case, this may be the disk image's file name + * with the extension omitted. + * For cores or games with more complex content requirements, + * the label can be used to provide information to help the player + * select a disk image to insert; + * for example, a core may label different kinds of disks + * (save data, level disk, installation disk, bonus content, etc.). + * with names that correspond to in-game prompts, + * so that the frontend can provide better guidance to the player. + * + * @param index The index of the disk image to return a label for. + * @param label A buffer to store the resulting label in. + * @param len The length of \c label, in bytes. + * @return \c true if the disk image at \c index is valid + * and a label was copied into \c label. */ typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len); +/** + * An interface that the frontend can use to exchange disks + * within the emulated console's disk drive. + * + * All function pointers are required. + * + * @deprecated This struct is superseded by \ref retro_disk_control_ext_callback. + * Only use this one to maintain compatibility + * with older cores and frontends. + * + * @see RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE + * @see retro_disk_control_ext_callback + */ struct retro_disk_control_callback { + /** @copydoc retro_set_eject_state_t */ retro_set_eject_state_t set_eject_state; + + /** @copydoc retro_get_eject_state_t */ retro_get_eject_state_t get_eject_state; + /** @copydoc retro_get_image_index_t */ retro_get_image_index_t get_image_index; + + /** @copydoc retro_set_image_index_t */ retro_set_image_index_t set_image_index; + + /** @copydoc retro_get_num_images_t */ retro_get_num_images_t get_num_images; + /** @copydoc retro_replace_image_index_t */ retro_replace_image_index_t replace_image_index; + + /** @copydoc retro_add_image_index_t */ retro_add_image_index_t add_image_index; }; +/** + * @copybrief retro_disk_control_callback + * + * All function pointers are required unless otherwise noted. + * + * @see RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE + */ struct retro_disk_control_ext_callback { + /** @copydoc retro_set_eject_state_t */ retro_set_eject_state_t set_eject_state; + + /** @copydoc retro_get_eject_state_t */ retro_get_eject_state_t get_eject_state; + /** @copydoc retro_get_image_index_t */ retro_get_image_index_t get_image_index; + + /** @copydoc retro_set_image_index_t */ retro_set_image_index_t set_image_index; + + /** @copydoc retro_get_num_images_t */ retro_get_num_images_t get_num_images; + /** @copydoc retro_replace_image_index_t */ retro_replace_image_index_t replace_image_index; + + /** @copydoc retro_add_image_index_t */ retro_add_image_index_t add_image_index; - /* NOTE: Frontend will only attempt to record/restore - * last used disk index if both set_initial_image() - * and get_image_path() are implemented */ - retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */ + /** @copydoc retro_set_initial_image_t + * + * Optional; not called if \c NULL. + * + * @note The frontend will only try to record/restore the last-used disk index + * if both \c set_initial_image and \c get_image_path are implemented. + */ + retro_set_initial_image_t set_initial_image; - retro_get_image_path_t get_image_path; /* Optional - may be NULL */ - retro_get_image_label_t get_image_label; /* Optional - may be NULL */ + /** + * @copydoc retro_get_image_path_t + * + * Optional; not called if \c NULL. + */ + retro_get_image_path_t get_image_path; + + /** + * @copydoc retro_get_image_label_t + * + * Optional; not called if \c NULL. + */ + retro_get_image_label_t get_image_label; }; +/** @} */ + /* Definitions for RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE. * A core can set it if sending and receiving custom network packets * during a multiplayer session is desired. @@ -3197,163 +5561,350 @@ struct retro_netpacket_callback const char* protocol_version; /* Optional - if not NULL will be used instead of core version to decide if communication is compatible */ }; +/** + * The pixel format used for rendering. + * @see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT + */ enum retro_pixel_format { - /* 0RGB1555, native endian. - * 0 bit must be set to 0. - * This pixel format is default for compatibility concerns only. - * If a 15/16-bit pixel format is desired, consider using RGB565. */ + /** + * 0RGB1555, native endian. + * Used as the default if \c RETRO_ENVIRONMENT_SET_PIXEL_FORMAT is not called. + * The most significant bit must be set to 0. + * @deprecated This format remains supported to maintain compatibility. + * New code should use RETRO_PIXEL_FORMAT_RGB565 instead. + * @see RETRO_PIXEL_FORMAT_RGB565 + */ RETRO_PIXEL_FORMAT_0RGB1555 = 0, - /* XRGB8888, native endian. - * X bits are ignored. */ + /** + * XRGB8888, native endian. + * The most significant byte (the X) is ignored. + */ RETRO_PIXEL_FORMAT_XRGB8888 = 1, - /* RGB565, native endian. - * This pixel format is the recommended format to use if a 15/16-bit - * format is desired as it is the pixel format that is typically - * available on a wide range of low-power devices. - * - * It is also natively supported in APIs like OpenGL ES. */ + /** + * RGB565, native endian. + * This format is recommended if 16-bit pixels are desired, + * as it is available on a variety of devices and APIs. + */ RETRO_PIXEL_FORMAT_RGB565 = 2, - /* Ensure sizeof() == sizeof(int). */ + /** Defined to ensure that sizeof(retro_pixel_format) == sizeof(int). Do not use. */ RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX }; +/** @defgroup GET_SAVESTATE_CONTEXT Savestate Context + * @{ + */ + +/** + * Details about how the frontend will use savestates. + * + * @see RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT + * @see retro_serialize + */ enum retro_savestate_context { - /* Standard savestate written to disk. */ + /** + * Standard savestate written to disk. + * May be loaded at any time, + * even in a separate session or on another device. + * + * Should not contain any pointers to code or data. + */ RETRO_SAVESTATE_CONTEXT_NORMAL = 0, - /* Savestate where you are guaranteed that the same instance will load the save state. - * You can store internal pointers to code or data. - * It's still a full serialization and deserialization, and could be loaded or saved at any time. - * It won't be written to disk or sent over the network. + /** + * The savestate is guaranteed to be loaded + * within the same session, address space, and binary. + * Will not be written to disk or sent over the network; + * therefore, internal pointers to code or data are acceptable. + * May still be loaded or saved at any time. + * + * @note This context generally implies the use of runahead or rewinding, + * which may work by taking savestates multiple times per second. + * Savestate code that runs in this context should be fast. */ RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_INSTANCE = 1, - /* Savestate where you are guaranteed that the same emulator binary will load that savestate. - * You can skip anything that would slow down saving or loading state but you can not store internal pointers. - * It won't be written to disk or sent over the network. - * Example: "Second Instance" runahead + /** + * The savestate is guaranteed to be loaded + * in the same session and by the same binary, + * but possibly by a different address space + * (e.g. for "second instance" runahead) + * + * Will not be written to disk or sent over the network, + * but may be loaded in a different address space. + * Therefore, the savestate must not contain pointers. */ RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_BINARY = 2, - /* Savestate used within a rollback netplay feature. - * You should skip anything that would unnecessarily increase bandwidth usage. - * It won't be written to disk but it will be sent over the network. + /** + * The savestate will not be written to disk, + * but no other guarantees are made. + * The savestate will almost certainly be loaded + * by a separate binary, device, and address space. + * + * This context is intended for use with frontends that support rollback netplay. + * Serialized state should omit any data that would unnecessarily increase bandwidth usage. + * Must not contain pointers, and integers must be saved in big-endian format. + * @see retro_endianness.h + * @see network_stream */ RETRO_SAVESTATE_CONTEXT_ROLLBACK_NETPLAY = 3, - /* Ensure sizeof() == sizeof(int). */ + /** + * @private Defined to ensure sizeof(retro_savestate_context) == sizeof(int). + * Do not use. + */ RETRO_SAVESTATE_CONTEXT_UNKNOWN = INT_MAX }; +/** @} */ + +/** @defgroup SET_MESSAGE User-Visible Messages + * + * @{ + */ + +/** + * Defines a message that the frontend will display to the user, + * as determined by RETRO_ENVIRONMENT_SET_MESSAGE. + * + * @deprecated This struct is superseded by \ref retro_message_ext, + * which provides more control over how a message is presented. + * Only use it for compatibility with older cores and frontends. + * + * @see RETRO_ENVIRONMENT_SET_MESSAGE + * @see retro_message_ext + */ struct retro_message { - const char *msg; /* Message to be displayed. */ - unsigned frames; /* Duration in frames of message. */ + /** + * Null-terminated message to be displayed. + * If \c NULL or empty, the message will be ignored. + */ + const char *msg; + + /** Duration to display \c msg in frames. */ + unsigned frames; }; +/** + * The method that the frontend will use to display a message to the player. + * @see retro_message_ext + */ enum retro_message_target { + /** + * Indicates that the frontent should display the given message + * using all other targets defined by \c retro_message_target at once. + */ RETRO_MESSAGE_TARGET_ALL = 0, + + /** + * Indicates that the frontend should display the given message + * using the frontend's on-screen display, if available. + * + * @attention If the frontend allows players to customize or disable notifications, + * then they may not see messages sent to this target. + */ RETRO_MESSAGE_TARGET_OSD, + + /** + * Indicates that the frontend should log the message + * via its usual logging mechanism, if available. + * + * This is not intended to be a substitute for \c RETRO_ENVIRONMENT_SET_LOG_INTERFACE. + * It is intended for the common use case of + * logging a player-facing message. + * + * This target should not be used for messages + * of type \c RETRO_MESSAGE_TYPE_STATUS or \c RETRO_MESSAGE_TYPE_PROGRESS, + * as it may add unnecessary noise to a log file. + * + * @see RETRO_ENVIRONMENT_SET_LOG_INTERFACE + */ RETRO_MESSAGE_TARGET_LOG }; +/** + * A broad category for the type of message that the frontend will display. + * + * Each message type has its own use case, + * therefore the frontend should present each one differently. + * + * @note This is a hint that the frontend may ignore. + * The frontend should fall back to \c RETRO_MESSAGE_TYPE_NOTIFICATION + * for message types that it doesn't support. + */ enum retro_message_type { + /** + * A standard on-screen message. + * + * Suitable for a variety of use cases, + * such as messages about errors + * or other important events. + * + * Frontends that display their own messages + * should display this type of core-generated message the same way. + */ RETRO_MESSAGE_TYPE_NOTIFICATION = 0, + + /** + * An on-screen message that should be visually distinct + * from \c RETRO_MESSAGE_TYPE_NOTIFICATION messages. + * + * The exact meaning of "visually distinct" is left to the frontend, + * but this usually implies that the frontend shows the message + * in a way that it doesn't typically use for its own notices. + */ RETRO_MESSAGE_TYPE_NOTIFICATION_ALT, + + /** + * Indicates a frequently-updated status display, + * rather than a standard notification. + * Status messages are intended to be displayed permanently while a core is running + * in a way that doesn't suggest user action is required. + * + * Here are some possible use cases for status messages: + * + * @li An internal framerate counter. + * @li Debugging information. + * Remember to let the player disable it in the core options. + * @li Core-specific state, such as when a microphone is active. + * + * The status message is displayed for the given duration, + * unless another status message of equal or greater priority is shown. + */ RETRO_MESSAGE_TYPE_STATUS, + + /** + * Denotes a message that reports the progress + * of a long-running asynchronous task, + * such as when a core loads large files from disk or the network. + * + * The frontend should display messages of this type as a progress bar + * (or a progress spinner for indefinite tasks), + * where \c retro_message_ext::msg is the progress bar's title + * and \c retro_message_ext::progress sets the progress bar's length. + * + * This message type shouldn't be used for tasks that are expected to complete quickly. + */ RETRO_MESSAGE_TYPE_PROGRESS }; +/** + * A core-provided message that the frontend will display to the player. + * + * @note The frontend is encouraged store these messages in a queue. + * However, it should not empty the queue of core-submitted messages upon exit; + * if a core exits with an error, it may want to use this API + * to show an error message to the player. + * + * The frontend should maintain its own copy of the submitted message + * and all subobjects, including strings. + * + * @see RETRO_ENVIRONMENT_SET_MESSAGE_EXT + */ struct retro_message_ext { - /* Message string to be displayed/logged */ + /** + * The \c NULL-terminated text of a message to show to the player. + * Must not be \c NULL. + * + * @note The frontend must honor newlines in this string + * when rendering text to \c RETRO_MESSAGE_TARGET_OSD. + */ const char *msg; - /* Duration (in ms) of message when targeting the OSD */ + + /** + * The duration that \c msg will be displayed on-screen, in milliseconds. + * + * Ignored for \c RETRO_MESSAGE_TARGET_LOG. + */ unsigned duration; - /* Message priority when targeting the OSD - * > When multiple concurrent messages are sent to - * the frontend and the frontend does not have the - * capacity to display them all, messages with the - * *highest* priority value should be shown - * > There is no upper limit to a message priority - * value (within the bounds of the unsigned data type) - * > In the reference frontend (RetroArch), the same - * priority values are used for frontend-generated - * notifications, which are typically assigned values - * between 0 and 3 depending upon importance */ + + /** + * The relative importance of this message + * when targeting \c RETRO_MESSAGE_TARGET_OSD. + * Higher values indicate higher priority. + * + * The frontend should use this to prioritize messages + * when it can't show all active messages at once, + * or to remove messages from its queue if it's full. + * + * The relative display order of messages with the same priority + * is left to the frontend's discretion, + * although we suggest breaking ties + * in favor of the most recently-submitted message. + * + * Frontends may handle deprioritized messages at their discretion; + * such messages may have their \c duration altered, + * be hidden without being delayed, + * or even be discarded entirely. + * + * @note In the reference frontend (RetroArch), + * the same priority values are used for frontend-generated notifications, + * which are typically between 0 and 3 depending upon importance. + * + * Ignored for \c RETRO_MESSAGE_TARGET_LOG. + */ unsigned priority; - /* Message logging level (info, warn, error, etc.) */ + + /** + * The severity level of this message. + * + * The frontend may use this to filter or customize messages + * depending on the player's preferences. + * Here are some ideas: + * + * @li Use this to prioritize errors and warnings + * over higher-ranking info and debug messages. + * @li Render warnings or errors with extra visual feedback, + * e.g. with brighter colors or accompanying sound effects. + * + * @see RETRO_ENVIRONMENT_SET_LOG_INTERFACE + */ enum retro_log_level level; - /* Message destination: OSD, logging interface or both */ + + /** + * The intended destination of this message. + * + * @see retro_message_target + */ enum retro_message_target target; - /* Message 'type' when targeting the OSD - * > RETRO_MESSAGE_TYPE_NOTIFICATION: Specifies that a - * message should be handled in identical fashion to - * a standard frontend-generated notification - * > RETRO_MESSAGE_TYPE_NOTIFICATION_ALT: Specifies that - * message is a notification that requires user attention - * or action, but that it should be displayed in a manner - * that differs from standard frontend-generated notifications. - * This would typically correspond to messages that should be - * displayed immediately (independently from any internal - * frontend message queue), and/or which should be visually - * distinguishable from frontend-generated notifications. - * For example, a core may wish to inform the user of - * information related to a disk-change event. It is - * expected that the frontend itself may provide a - * notification in this case; if the core sends a - * message of type RETRO_MESSAGE_TYPE_NOTIFICATION, an - * uncomfortable 'double-notification' may occur. A message - * of RETRO_MESSAGE_TYPE_NOTIFICATION_ALT should therefore - * be presented such that visual conflict with regular - * notifications does not occur - * > RETRO_MESSAGE_TYPE_STATUS: Indicates that message - * is not a standard notification. This typically - * corresponds to 'status' indicators, such as a core's - * internal FPS, which are intended to be displayed - * either permanently while a core is running, or in - * a manner that does not suggest user attention or action - * is required. 'Status' type messages should therefore be - * displayed in a different on-screen location and in a manner - * easily distinguishable from both standard frontend-generated - * notifications and messages of type RETRO_MESSAGE_TYPE_NOTIFICATION_ALT - * > RETRO_MESSAGE_TYPE_PROGRESS: Indicates that message reports - * the progress of an internal core task. For example, in cases - * where a core itself handles the loading of content from a file, - * this may correspond to the percentage of the file that has been - * read. Alternatively, an audio/video playback core may use a - * message of type RETRO_MESSAGE_TYPE_PROGRESS to display the current - * playback position as a percentage of the runtime. 'Progress' type - * messages should therefore be displayed as a literal progress bar, - * where: - * - 'retro_message_ext.msg' is the progress bar title/label - * - 'retro_message_ext.progress' determines the length of - * the progress bar - * NOTE: Message type is a *hint*, and may be ignored - * by the frontend. If a frontend lacks support for - * displaying messages via alternate means than standard - * frontend-generated notifications, it will treat *all* - * messages as having the type RETRO_MESSAGE_TYPE_NOTIFICATION */ + + /** + * The intended semantics of this message. + * + * Ignored for \c RETRO_MESSAGE_TARGET_LOG. + * + * @see retro_message_type + */ enum retro_message_type type; - /* Task progress when targeting the OSD and message is - * of type RETRO_MESSAGE_TYPE_PROGRESS - * > -1: Unmetered/indeterminate - * > 0-100: Current progress percentage - * NOTE: Since message type is a hint, a frontend may ignore - * progress values. Where relevant, a core should therefore - * include progress percentage within the message string, + + /** + * The progress of an asynchronous task. + * + * A value betwen 0 and 100 (inclusive) indicates the task's percentage, + * and a value of -1 indicates a task of unknown completion. + * + * @note Since message type is a hint, a frontend may ignore progress values. + * Where relevant, a core should include progress percentage within the message string, * such that the message intent remains clear when displayed - * as a standard frontend-generated notification */ + * as a standard frontend-generated notification. + * + * Ignored for \c RETRO_MESSAGE_TARGET_LOG and for + * message types other than \c RETRO_MESSAGE_TYPE_PROGRESS. + */ int8_t progress; }; +/** @} */ + /* Describes how the libretro implementation maps a libretro input bind * to its internal input system through a human readable string. * This string can be used to better let a user configure input. */ @@ -3371,21 +5922,32 @@ struct retro_input_descriptor const char *description; }; +/** + * Contains basic information about the core. + * + * @see retro_get_system_info + * @warning All pointers are owned by the core + * and must remain valid throughout its lifetime. + */ struct retro_system_info { - /* All pointers are owned by libretro implementation, and pointers must - * remain valid until it is unloaded. */ + /** + * Descriptive name of the library. + * + * @note Should not contain any version numbers, etc. + */ + const char *library_name; - const char *library_name; /* Descriptive name of library. Should not - * contain any version numbers, etc. */ - const char *library_version; /* Descriptive version of core. */ + /** + * Descriptive version of the core. + */ + const char *library_version; - const char *valid_extensions; /* A string listing probably content - * extensions the core will be able to - * load, separated with pipe. - * I.e. "bin|rom|iso". - * Typically used for a GUI to filter - * out extensions. */ + /** + * A pipe-delimited string list of file extensions that this core can load, e.g. "bin|rom|iso". + * Typically used by a frontend for filtering or core selection. + */ + const char *valid_extensions; /* Libretro cores that need to have direct access to their content * files, including cores which use the path of the content files to @@ -3623,101 +6185,273 @@ struct retro_game_info_ext bool persistent_data; }; +/** + * Parameters describing the size and shape of the video frame. + * @see retro_system_av_info + * @see RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO + * @see RETRO_ENVIRONMENT_SET_GEOMETRY + * @see retro_get_system_av_info + */ struct retro_game_geometry { - unsigned base_width; /* Nominal video width of game. */ - unsigned base_height; /* Nominal video height of game. */ - unsigned max_width; /* Maximum possible width of game. */ + /** + * Nominal video width of game, in pixels. + * This will typically be the emulated platform's native video width + * (or its smallest, if the original hardware supports multiple resolutions). + */ + unsigned base_width; + + /** + * Nominal video height of game, in pixels. + * This will typically be the emulated platform's native video height + * (or its smallest, if the original hardware supports multiple resolutions). + */ + unsigned base_height; + + /** + * Maximum possible width of the game screen, in pixels. + * This will typically be the emulated platform's maximum video width. + * For cores that emulate platforms with multiple screens (such as the Nintendo DS), + * this should assume the core's widest possible screen layout (e.g. side-by-side). + * For cores that support upscaling the resolution, + * this should assume the highest supported scale factor is active. + */ + unsigned max_width; + + /** + * Maximum possible height of the game screen, in pixels. + * This will typically be the emulated platform's maximum video height. + * For cores that emulate platforms with multiple screens (such as the Nintendo DS), + * this should assume the core's tallest possible screen layout (e.g. vertical). + * For cores that support upscaling the resolution, + * this should assume the highest supported scale factor is active. + */ unsigned max_height; /* Maximum possible height of game. */ - float aspect_ratio; /* Nominal aspect ratio of game. If - * aspect_ratio is <= 0.0, an aspect ratio - * of base_width / base_height is assumed. - * A frontend could override this setting, - * if desired. */ + /** + * Nominal aspect ratio of game. + * If zero or less, + * an aspect ratio of base_width / base_height is assumed. + * + * @note A frontend may ignore this setting. + */ + float aspect_ratio; }; +/** + * Parameters describing the timing of the video and audio. + * @see retro_system_av_info + * @see RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO + * @see retro_get_system_av_info + */ struct retro_system_timing { - double fps; /* FPS of video content. */ - double sample_rate; /* Sampling rate of audio. */ + /** Video output refresh rate, in frames per second. */ + double fps; + + /** The audio output sample rate, in Hz. */ + double sample_rate; }; +/** + * Configures how the core's audio and video should be updated. + * @see RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO + * @see retro_get_system_av_info + */ struct retro_system_av_info { + /** Parameters describing the size and shape of the video frame. */ struct retro_game_geometry geometry; + + /** Parameters describing the timing of the video and audio. */ struct retro_system_timing timing; }; +/** @defgroup SET_CORE_OPTIONS Core Options + * @{ + */ + +/** + * Represents \ref RETRO_ENVIRONMENT_GET_VARIABLE "a core option query". + * + * @note In \ref RETRO_ENVIRONMENT_SET_VARIABLES + * (which is a deprecated API), + * this \c struct serves as an option definition. + * + * @see RETRO_ENVIRONMENT_GET_VARIABLE + */ struct retro_variable { - /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. - * If NULL, obtains the complete environment string if more - * complex parsing is necessary. - * The environment string is formatted as key-value pairs - * delimited by semicolons as so: - * "key1=value1;key2=value2;..." + /** + * A unique key identifying this option. + * + * Should be a key for an option that was previously defined + * with \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 or similar. + * + * Should be prefixed with the core's name + * to minimize the risk of collisions with another core's options, + * as frontends are not required to use a namespacing scheme for storing options. + * For example, a core named "foo" might define an option named "foo_option". + * + * @note In \ref RETRO_ENVIRONMENT_SET_VARIABLES + * (which is a deprecated API), + * this field is used to define an option + * named by this key. */ const char *key; - /* Value to be obtained. If key does not exist, it is set to NULL. */ + /** + * Value to be obtained. + * + * Set by the frontend to \c NULL if + * the option named by \ref key does not exist. + * + * @note In \ref RETRO_ENVIRONMENT_SET_VARIABLES + * (which is a deprecated API), + * this field is set by the core to define the possible values + * for an option named by \ref key. + * When used this way, it must be formatted as follows: + * @li The text before the first ';' is the option's human-readable title. + * @li A single space follows the ';'. + * @li The rest of the string is a '|'-delimited list of possible values, + * with the first one being the default. + */ const char *value; }; +/** + * An argument that's used to show or hide a core option in the frontend. + * + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY + */ struct retro_core_option_display { - /* Variable to configure in RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY */ + /** + * The key for a core option that was defined with \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, + * \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL, + * or their legacy equivalents. + */ const char *key; - /* Specifies whether variable should be displayed - * when presenting core options to the user */ + /** + * Whether the option named by \c key + * should be displayed to the player in the frontend's core options menu. + * + * @note This value is a hint, \em not a requirement; + * the frontend is free to ignore this field. + */ bool visible; }; -/* Maximum number of values permitted for a core option - * > Note: We have to set a maximum value due the limitations - * of the C language - i.e. it is not possible to create an - * array of structs each containing a variable sized array, - * so the retro_core_option_definition values array must - * have a fixed size. The size limit of 128 is a balancing - * act - it needs to be large enough to support all 'sane' - * core options, but setting it too large may impact low memory - * platforms. In practise, if a core option has more than - * 128 values then the implementation is likely flawed. - * To quote the above API reference: - * "The number of possible options should be very limited - * i.e. it should be feasible to cycle through options - * without a keyboard." +/** + * The maximum number of choices that can be defined for a given core option. + * + * This limit was chosen as a compromise between + * a core's flexibility and a streamlined user experience. + * + * @note A guiding principle of libretro's API design is that + * all common interactions (gameplay, menu navigation, etc.) + * should be possible without a keyboard. + * + * If you need more than 128 choices for a core option, + * consider simplifying your option structure. + * Here are some ideas: + * + * \li If a core option represents a numeric value, + * consider reducing the option's granularity + * (e.g. define time limits in increments of 5 seconds instead of 1 second). + * Providing a fixed set of values based on experimentation + * is also a good idea. + * \li If a core option represents a dynamically-built list of files, + * consider leaving out files that won't be useful. + * For example, if a core allows the player to choose a specific BIOS file, + * it can omit files of the wrong length or without a valid header. + * + * @see retro_core_option_definition + * @see retro_core_option_v2_definition */ #define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 +/** + * A descriptor for a particular choice within a core option. + * + * @note All option values are represented as strings. + * If you need to represent any other type, + * parse the string in \ref value. + * + * @see retro_core_option_v2_category + */ struct retro_core_option_value { - /* Expected option value */ + /** + * The option value that the frontend will serialize. + * + * Must not be \c NULL or empty. + * No other hard limits are placed on this value's contents, + * but here are some suggestions: + * + * \li If the value represents a number, + * don't include any non-digit characters (units, separators, etc.). + * Instead, include that information in \c label. + * This will simplify parsing. + * \li If the value represents a file path, + * store it as a relative path with respect to one of the common libretro directories + * (e.g. \ref RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY "the system directory" + * or \ref RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY "the save directory"), + * and use forward slashes (\c "/") as directory separators. + * This will simplify cloud storage if supported by the frontend, + * as the same file may be used on multiple devices. + */ const char *value; - /* Human-readable value label. If NULL, value itself - * will be displayed by the frontend */ + /** + * Human-readable name for \c value that the frontend should show to players. + * + * May be \c NULL, in which case the frontend + * should display \c value itself. + * + * Here are some guidelines for writing a good label: + * + * \li Make the option labels obvious + * so that they don't need to be explained in the description. + * \li Keep labels short, and don't use unnecessary words. + * For example, "OpenGL" is a better label than "OpenGL Mode". + * \li If the option represents a number, + * consider adding units, separators, or other punctuation + * into the label itself. + * For example, "5 seconds" is a better label than "5". + * \li If the option represents a number, use intuitive units + * that don't take a lot of digits to express. + * For example, prefer "1 minute" over "60 seconds" or "60,000 milliseconds". + */ const char *label; }; +/** + * @copybrief retro_core_option_v2_definition + * + * @deprecated Use \ref retro_core_option_v2_definition instead, + * as it supports categorizing options into groups. + * Only use this \c struct to support older frontends or cores. + * + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL + */ struct retro_core_option_definition { - /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. */ + /** @copydoc retro_core_option_v2_definition::key */ const char *key; - /* Human-readable core option description (used as menu label) */ + /** @copydoc retro_core_option_v2_definition::desc */ const char *desc; - /* Human-readable core option information (used as menu sublabel) */ + /** @copydoc retro_core_option_v2_definition::info */ const char *info; - /* Array of retro_core_option_value structs, terminated by NULL */ + /** @copydoc retro_core_option_v2_definition::values */ struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX]; - /* Default core option value. Must match one of the values - * in the retro_core_option_value array, otherwise will be - * ignored */ + /** @copydoc retro_core_option_v2_definition::default_value */ const char *default_value; }; @@ -3725,156 +6459,325 @@ struct retro_core_option_definition #undef local #endif +/** + * A variant of \ref retro_core_options that supports internationalization. + * + * @deprecated Use \ref retro_core_options_v2_intl instead, + * as it supports categorizing options into groups. + * Only use this \c struct to support older frontends or cores. + * + * @see retro_core_options + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL + * @see RETRO_ENVIRONMENT_GET_LANGUAGE + * @see retro_language + */ struct retro_core_options_intl { - /* Pointer to an array of retro_core_option_definition structs - * - US English implementation - * - Must point to a valid array */ + /** @copydoc retro_core_options_v2_intl::us */ struct retro_core_option_definition *us; - /* Pointer to an array of retro_core_option_definition structs - * - Implementation for current frontend language - * - May be NULL */ + /** @copydoc retro_core_options_v2_intl::local */ struct retro_core_option_definition *local; }; +/** + * A descriptor for a group of related core options. + * + * Here's an example category: + * + * @code + * { + * "cpu", + * "CPU Emulation", + * "Settings for CPU quirks." + * } + * @endcode + * + * @see retro_core_options_v2 + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL + */ struct retro_core_option_v2_category { - /* Variable uniquely identifying the - * option category. Valid key characters - * are [a-z, A-Z, 0-9, _, -] */ + /** + * A string that uniquely identifies this category within the core's options. + * Any \c retro_core_option_v2_definition whose \c category_key matches this + * is considered to be within this category. + * Different cores may use the same category keys, + * so namespacing them is not necessary. + * Valid characters are [a-zA-Z0-9_-]. + * + * Frontends should use this category to organize core options, + * but may customize this category's presentation in other ways. + * For example, a frontend may use common keys like "audio" or "gfx" + * to select an appropriate icon in its UI. + * + * Required; must not be \c NULL. + */ const char *key; - /* Human-readable category description - * > Used as category menu label when - * frontend has core option category - * support */ + /** + * A brief human-readable name for this category, + * intended for the frontend to display to the player. + * This should be a name that's concise and descriptive, such as "Audio" or "Video". + * + * Required; must not be \c NULL. + */ const char *desc; - /* Human-readable category information - * > Used as category menu sublabel when - * frontend has core option category - * support - * > Optional (may be NULL or an empty - * string) */ + /** + * A human-readable description for this category, + * intended for the frontend to display to the player + * as secondary help text (e.g. a sublabel or a tooltip). + * Optional; may be \c NULL or an empty string. + */ const char *info; }; +/** + * A descriptor for a particular core option and the values it may take. + * + * Supports categorizing options into groups, + * so as not to overwhelm the player. + * + * @see retro_core_option_v2_category + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL + */ struct retro_core_option_v2_definition { - /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. - * Valid key characters are [a-z, A-Z, 0-9, _, -] */ + /** + * A unique identifier for this option that cores may use + * \ref RETRO_ENVIRONMENT_GET_VARIABLE "to query its value from the frontend". + * Must be unique within this core. + * + * Should be unique globally; + * the recommended method for doing so + * is to prefix each option with the core's name. + * For example, an option that controls the resolution for a core named "foo" + * should be named \c "foo_resolution". + * + * Valid key characters are in the set [a-zA-Z0-9_-]. + */ const char *key; - /* Human-readable core option description - * > Used as menu label when frontend does - * not have core option category support - * e.g. "Video > Aspect Ratio" */ + /** + * A human-readable name for this option, + * intended to be displayed by frontends that don't support + * categorizing core options. + * + * Required; must not be \c NULL or empty. + */ const char *desc; - /* Human-readable core option description - * > Used as menu label when frontend has - * core option category support - * e.g. "Aspect Ratio", where associated - * retro_core_option_v2_category::desc - * is "Video" - * > If empty or NULL, the string specified by - * desc will be used as the menu label - * > Will be ignored (and may be set to NULL) - * if category_key is empty or NULL */ + /** + * A human-readable name for this option, + * intended to be displayed by frontends that support + * categorizing core options. + * + * This version may be slightly more concise than \ref desc, + * as it can rely on the structure of the options menu. + * For example, "Interface" is a good \c desc_categorized, + * as it can be displayed as a sublabel for a "Network" category. + * For \c desc, "Network Interface" would be more suitable. + * + * Optional; if this field or \c category_key is empty or \c NULL, + * \c desc will be used instead. + */ const char *desc_categorized; - /* Human-readable core option information - * > Used as menu sublabel */ + /** + * A human-readable description of this option and its effects, + * intended to be displayed by frontends that don't support + * categorizing core options. + * + * @details Intended to be displayed as secondary help text, + * such as a tooltip or a sublabel. + * + * Here are some suggestions for writing a good description: + * + * \li Avoid technical jargon unless this option is meant for advanced users. + * If unavoidable, suggest one of the default options for those unsure. + * \li Don't repeat the option name in the description; + * instead, describe what the option name means. + * \li If an option requires a core restart or game reset to take effect, + * be sure to say so. + * \li Try to make the option labels obvious + * so that they don't need to be explained in the description. + * + * Optional; may be \c NULL. + */ const char *info; - /* Human-readable core option information - * > Used as menu sublabel when frontend - * has core option category support - * (e.g. may be required when info text - * references an option by name/desc, - * and the desc/desc_categorized text - * for that option differ) - * > If empty or NULL, the string specified by - * info will be used as the menu sublabel - * > Will be ignored (and may be set to NULL) - * if category_key is empty or NULL */ + /** + * @brief A human-readable description of this option and its effects, + * intended to be displayed by frontends that support + * categorizing core options. + * + * This version is provided to accommodate descriptions + * that reference other options by name, + * as options may have different user-facing names + * depending on whether the frontend supports categorization. + * + * @copydetails info + * + * If empty or \c NULL, \c info will be used instead. + * Will be ignored if \c category_key is empty or \c NULL. + */ const char *info_categorized; - /* Variable specifying category (e.g. "video", - * "audio") that will be assigned to the option - * if frontend has core option category support. - * > Categorized options will be displayed in a - * subsection/submenu of the frontend core - * option interface - * > Specified string must match one of the - * retro_core_option_v2_category::key values - * in the associated retro_core_option_v2_category - * array; If no match is not found, specified - * string will be considered as NULL - * > If specified string is empty or NULL, option will - * have no category and will be shown at the top - * level of the frontend core option interface */ + /** + * The key of the category that this option belongs to. + * + * Optional; if equal to \ref retro_core_option_v2_category::key "a defined category", + * then this option shall be displayed by the frontend + * next to other options in this same category, + * assuming it supports doing so. + * Option categories are intended to be displayed in a submenu, + * but this isn't a hard requirement. + * + * If \c NULL, empty, or not equal to a defined category, + * then this option is considered uncategorized + * and the frontend shall display it outside of any category + * (most likely at a top-level menu). + * + * @see retro_core_option_v2_category + */ const char *category_key; - /* Array of retro_core_option_value structs, terminated by NULL */ + /** + * One or more possible values for this option, + * up to the limit of \ref RETRO_NUM_CORE_OPTION_VALUES_MAX. + * + * Terminated by a \c { NULL, NULL } element, + * although frontends should work even if all elements are used. + */ struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX]; - /* Default core option value. Must match one of the values - * in the retro_core_option_value array, otherwise will be - * ignored */ + /** + * The default value for this core option. + * Used if it hasn't been set, e.g. for new cores. + * Must equal one of the \ref value members in the \c values array, + * or else this option will be ignored. + */ const char *default_value; }; +/** + * A set of core option descriptors and the categories that group them, + * suitable for enabling a core to be customized. + * + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 + */ struct retro_core_options_v2 { - /* Array of retro_core_option_v2_category structs, - * terminated by NULL - * > If NULL, all entries in definitions array - * will have no category and will be shown at - * the top level of the frontend core option - * interface - * > Will be ignored if frontend does not have - * core option category support */ + /** + * An array of \ref retro_core_option_v2_category "option categories", + * terminated by a zeroed-out category \c struct. + * + * Will be ignored if the frontend doesn't support core option categories. + * + * If \c NULL or ignored, all options will be treated as uncategorized. + * This most likely means that a frontend will display them at a top-level menu + * without any kind of hierarchy or grouping. + */ struct retro_core_option_v2_category *categories; - /* Array of retro_core_option_v2_definition structs, - * terminated by NULL */ + /** + * An array of \ref retro_core_option_v2_definition "core option descriptors", + * terminated by a zeroed-out definition \c struct. + * + * Required; must not be \c NULL. + */ struct retro_core_option_v2_definition *definitions; }; +/** + * A variant of \ref retro_core_options_v2 that supports internationalization. + * + * @see retro_core_options_v2 + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL + * @see RETRO_ENVIRONMENT_GET_LANGUAGE + * @see retro_language + */ struct retro_core_options_v2_intl { - /* Pointer to a retro_core_options_v2 struct - * > US English implementation - * > Must point to a valid struct */ + /** + * Pointer to a core options set + * whose text is written in American English. + * + * This may be passed to \c RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2 as-is + * if not using \c RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL. + * + * Required; must not be \c NULL. + */ struct retro_core_options_v2 *us; - /* Pointer to a retro_core_options_v2 struct - * - Implementation for current frontend language - * - May be NULL */ + /** + * Pointer to a core options set + * whose text is written in one of libretro's \ref retro_language "supported languages", + * most likely the one returned by \ref RETRO_ENVIRONMENT_GET_LANGUAGE. + * + * Structure is the same, but usage is slightly different: + * + * \li All text (except for keys and option values) + * should be written in whichever language + * is returned by \c RETRO_ENVIRONMENT_GET_LANGUAGE. + * \li All fields besides keys and option values may be \c NULL, + * in which case the corresponding string in \c us + * is used instead. + * \li All \ref retro_core_option_v2_definition::default_value "default option values" + * are taken from \c us. + * The defaults in this field are ignored. + * + * May be \c NULL, in which case \c us is used instead. + */ struct retro_core_options_v2 *local; }; -/* Used by the frontend to monitor changes in core option - * visibility. May be called each time any core option - * value is set via the frontend. - * - On each invocation, the core must update the visibility - * of any dynamically hidden options using the - * RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY environment - * callback. - * - On the first invocation, returns 'true' if the visibility - * of any core option has changed since the last call of - * retro_load_game() or retro_load_game_special(). - * - On each subsequent invocation, returns 'true' if the - * visibility of any core option has changed since the last - * time the function was called. */ +/** + * Called by the frontend to determine if any core option's visibility has changed. + * + * Each time a frontend sets a core option, + * it should call this function to see if + * any core option should be made visible or invisible. + * + * May also be called after \ref retro_load_game "loading a game", + * to determine what the initial visibility of each option should be. + * + * Within this function, the core must update the visibility + * of any dynamically-hidden options + * using \ref RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY. + * + * @note All core options are visible by default, + * even during this function's first call. + * + * @return \c true if any core option's visibility was adjusted + * since the last call to this function. + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY + * @see retro_core_option_display + */ typedef bool (RETRO_CALLCONV *retro_core_options_update_display_callback_t)(void); + +/** + * Callback registered by the core for the frontend to use + * when setting the visibility of each core option. + * + * @see RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY + * @see retro_core_option_display + */ struct retro_core_options_update_display_callback { + /** + * @copydoc retro_core_options_update_display_callback_t + * + * Set by the core. + */ retro_core_options_update_display_callback_t callback; }; +/** @} */ + struct retro_game_info { const char *path; /* Path to game, UTF-8 encoded. @@ -3891,114 +6794,264 @@ struct retro_game_info const char *meta; /* String of implementation specific meta-data. */ }; +/** @defgroup GET_CURRENT_SOFTWARE_FRAMEBUFFER Frontend-Owned Framebuffers + * @{ + */ + +/** @defgroup RETRO_MEMORY_ACCESS Framebuffer Memory Access Types + * @{ + */ + +/** Indicates that core will write to the framebuffer returned by the frontend. */ #define RETRO_MEMORY_ACCESS_WRITE (1 << 0) - /* The core will write to the buffer provided by retro_framebuffer::data. */ + +/** Indicates that the core will read from the framebuffer returned by the frontend. */ #define RETRO_MEMORY_ACCESS_READ (1 << 1) - /* The core will read from retro_framebuffer::data. */ + +/** @} */ + +/** @defgroup RETRO_MEMORY_TYPE Framebuffer Memory Types + * @{ + */ + +/** + * Indicates that the returned framebuffer's memory is cached. + * If not set, random access to the buffer may be very slow. + */ #define RETRO_MEMORY_TYPE_CACHED (1 << 0) - /* The memory in data is cached. - * If not cached, random writes and/or reading from the buffer is expected to be very slow. */ + +/** @} */ + +/** + * A frame buffer owned by the frontend that a core may use for rendering. + * + * @see GET_CURRENT_SOFTWARE_FRAMEBUFFER + * @see retro_video_refresh_t + */ struct retro_framebuffer { - void *data; /* The framebuffer which the core can render into. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. - The initial contents of data are unspecified. */ - unsigned width; /* The framebuffer width used by the core. Set by core. */ - unsigned height; /* The framebuffer height used by the core. Set by core. */ - size_t pitch; /* The number of bytes between the beginning of a scanline, - and beginning of the next scanline. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ - enum retro_pixel_format format; /* The pixel format the core must use to render into data. - This format could differ from the format used in - SET_PIXEL_FORMAT. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + /** + * Pointer to the beginning of the framebuffer provided by the frontend. + * The initial contents of this buffer are unspecified, + * as is the means used to map the memory; + * this may be defined in software, + * or it may be GPU memory mapped to RAM. + * + * If the framebuffer is used, + * this pointer must be passed to \c retro_video_refresh_t as-is. + * It is undefined behavior to pass an offset to this pointer. + * + * @warning This pointer is only guaranteed to be valid + * for the duration of the same \c retro_run iteration + * \ref GET_CURRENT_SOFTWARE_FRAMEBUFFER "that requested the framebuffer". + * Reuse of this pointer is undefined. + */ + void *data; - unsigned access_flags; /* How the core will access the memory in the framebuffer. - RETRO_MEMORY_ACCESS_* flags. - Set by core. */ - unsigned memory_flags; /* Flags telling core how the memory has been mapped. - RETRO_MEMORY_TYPE_* flags. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + /** + * The width of the framebuffer given in \c data, in pixels. + * Set by the core. + * + * @warning If the framebuffer is used, + * this value must be passed to \c retro_video_refresh_t as-is. + * It is undefined behavior to try to render \c data with any other width. + */ + unsigned width; + + /** + * The height of the framebuffer given in \c data, in pixels. + * Set by the core. + * + * @warning If the framebuffer is used, + * this value must be passed to \c retro_video_refresh_t as-is. + * It is undefined behavior to try to render \c data with any other height. + */ + unsigned height; + + /** + * The distance between the start of one scanline and the beginning of the next, in bytes. + * In practice this is usually equal to \c width times the pixel size, + * but that's not guaranteed. + * Sometimes called the "stride". + * + * @setby{frontend} + * @warning If the framebuffer is used, + * this value must be passed to \c retro_video_refresh_t as-is. + * It is undefined to try to render \c data with any other pitch. + */ + size_t pitch; + + /** + * The pixel format of the returned framebuffer. + * May be different than the format specified by the core in \c RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, + * e.g. due to conversions. + * Set by the frontend. + * + * @see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT + */ + enum retro_pixel_format format; + + /** + * One or more \ref RETRO_MEMORY_ACCESS "memory access flags" + * that specify how the core will access the memory in \c data. + * + * @setby{core} + */ + unsigned access_flags; + + /** + * Zero or more \ref RETRO_MEMORY_TYPE "memory type flags" + * that describe how the framebuffer's memory has been mapped. + * + * @setby{frontend} + */ + unsigned memory_flags; }; -/* Used by a libretro core to override the current - * fastforwarding mode of the frontend */ +/** @} */ + +/** @defgroup SET_FASTFORWARDING_OVERRIDE Fast-Forward Override + * @{ + */ + +/** + * Parameters that govern when and how the core takes control + * of fast-forwarding mode. + */ struct retro_fastforwarding_override { - /* Specifies the runtime speed multiplier that - * will be applied when 'fastforward' is true. - * For example, a value of 5.0 when running 60 FPS - * content will cap the fast-forward rate at 300 FPS. - * Note that the target multiplier may not be achieved - * if the host hardware has insufficient processing - * power. - * Setting a value of 0.0 (or greater than 0.0 but - * less than 1.0) will result in an uncapped - * fast-forward rate (limited only by hardware - * capacity). - * If the value is negative, it will be ignored - * (i.e. the frontend will use a runtime speed - * multiplier of its own choosing) */ + /** + * The factor by which the core will be sped up + * when \c fastforward is \c true. + * This value is used as follows: + * + * @li A value greater than 1.0 will run the core at + * the specified multiple of normal speed. + * For example, a value of 5.0 + * combined with a normal target rate of 60 FPS + * will result in a target rate of 300 FPS. + * The actual rate may be lower if the host's hardware can't keep up. + * @li A value of 1.0 will run the core at normal speed. + * @li A value between 0.0 (inclusive) and 1.0 (exclusive) + * will run the core as fast as the host system can manage. + * @li A negative value will let the frontend choose a factor. + * @li An infinite value or \c NaN results in undefined behavior. + * + * @attention Setting this value to less than 1.0 will \em not + * slow down the core. + */ float ratio; - /* If true, fastforwarding mode will be enabled. - * If false, fastforwarding mode will be disabled. */ + /** + * If \c true, the frontend should activate fast-forwarding + * until this field is set to \c false or the core is unloaded. + */ bool fastforward; - /* If true, and if supported by the frontend, an - * on-screen notification will be displayed while - * 'fastforward' is true. - * If false, and if supported by the frontend, any - * on-screen fast-forward notifications will be - * suppressed */ + /** + * If \c true, the frontend should display an on-screen notification or icon + * while \c fastforward is \c true (where supported). + * Otherwise, the frontend should not display any such notification. + */ bool notification; - /* If true, the core will have sole control over - * when fastforwarding mode is enabled/disabled; - * the frontend will not be able to change the - * state set by 'fastforward' until either - * 'inhibit_toggle' is set to false, or the core - * is unloaded */ + /** + * If \c true, the core has exclusive control + * over enabling and disabling fast-forwarding + * via the \c fastforward field. + * The frontend will not be able to start or stop fast-forwarding + * until this field is set to \c false or the core is unloaded. + */ bool inhibit_toggle; }; -/* During normal operation. Rate will be equal to the core's internal FPS. */ +/** @} */ + +/** + * During normal operation. + * + * @note Rate will be equal to the core's internal FPS. + */ #define RETRO_THROTTLE_NONE 0 -/* While paused or stepping single frames. Rate will be 0. */ +/** + * While paused or stepping single frames. + * + * @note Rate will be 0. + */ #define RETRO_THROTTLE_FRAME_STEPPING 1 -/* During fast forwarding. - * Rate will be 0 if not specifically limited to a maximum speed. */ +/** + * During fast forwarding. + * + * @note Rate will be 0 if not specifically limited to a maximum speed. + */ #define RETRO_THROTTLE_FAST_FORWARD 2 -/* During slow motion. Rate will be less than the core's internal FPS. */ +/** + * During slow motion. + * + * @note Rate will be less than the core's internal FPS. + */ #define RETRO_THROTTLE_SLOW_MOTION 3 -/* While rewinding recorded save states. Rate can vary depending on the rewind - * speed or be 0 if the frontend is not aiming for a specific rate. */ +/** + * While rewinding recorded save states. + * + * @note Rate can vary depending on the rewind speed or be 0 if the frontend + * is not aiming for a specific rate. + */ #define RETRO_THROTTLE_REWINDING 4 -/* While vsync is active in the video driver and the target refresh rate is - * lower than the core's internal FPS. Rate is the target refresh rate. */ +/** + * While vsync is active in the video driver, and the target refresh rate is lower than the core's internal FPS. + * + * @note Rate is the target refresh rate. + */ #define RETRO_THROTTLE_VSYNC 5 -/* When the frontend does not throttle in any way. Rate will be 0. - * An example could be if no vsync or audio output is active. */ +/** + * When the frontend does not throttle in any way. + * + * @note Rate will be 0. An example could be if no vsync or audio output is active. + */ #define RETRO_THROTTLE_UNBLOCKED 6 +/** + * Details about the actual rate an implementation is calling \c retro_run() at. + * + * @see RETRO_ENVIRONMENT_GET_THROTTLE_STATE + */ struct retro_throttle_state { - /* The current throttling mode. Should be one of the values above. */ + /** + * The current throttling mode. + * + * @note Should be one of the \c RETRO_THROTTLE_* values. + * @see RETRO_THROTTLE_NONE + * @see RETRO_THROTTLE_FRAME_STEPPING + * @see RETRO_THROTTLE_FAST_FORWARD + * @see RETRO_THROTTLE_SLOW_MOTION + * @see RETRO_THROTTLE_REWINDING + * @see RETRO_THROTTLE_VSYNC + * @see RETRO_THROTTLE_UNBLOCKED + */ unsigned mode; - /* How many times per second the frontend aims to call retro_run. - * Depending on the mode, it can be 0 if there is no known fixed rate. + /** + * How many times per second the frontend aims to call retro_run. + * + * @note Depending on the mode, it can be 0 if there is no known fixed rate. * This won't be accurate if the total processing time of the core and - * the frontend is longer than what is available for one frame. */ + * the frontend is longer than what is available for one frame. + */ float rate; }; +/** @defgroup GET_MICROPHONE_INTERFACE Microphone Interface + * @{ + */ + /** * Opaque handle to a microphone that's been opened for use. * The underlying object is accessed or created with \c retro_microphone_interface_t. @@ -4092,7 +7145,7 @@ struct retro_microphone_interface * * This function is not guaranteed to be thread-safe. * - * @param args[in] Parameters used to create the microphone. + * @param[in] args Parameters used to create the microphone. * May be \c NULL, in which case the default value of each parameter will be used. * * @returns Pointer to the newly-opened microphone, @@ -4132,9 +7185,9 @@ struct retro_microphone_interface * * Will not change after the mic was opened. * - * @param microphone[in] Opaque handle to the microphone + * @param[in] microphone Opaque handle to the microphone * whose parameters will be retrieved. - * @param params[out] The parameters object that the + * @param[out] params The parameters object that the * microphone's parameters will be copied to. * * @return \c true if the parameters were retrieved, @@ -4202,6 +7255,12 @@ struct retro_microphone_interface retro_read_mic_t read_mic; }; +/** @} */ + +/** @defgroup GET_DEVICE_POWER Device Power + * @{ + */ + /** * Describes how a device is being powered. * @see RETRO_ENVIRONMENT_GET_DEVICE_POWER @@ -4282,152 +7341,450 @@ struct retro_device_power int8_t percent; }; -/* Callbacks */ +/** @} */ -/* Environment callback. Gives implementations a way of performing - * uncommon tasks. Extensible. */ +/** + * @defgroup Callbacks + * @{ + */ + +/** + * Environment callback to give implementations a way of performing uncommon tasks. + * + * @note Extensible. + * + * @param cmd The command to run. + * @param data A pointer to the data associated with the command. + * + * @return Varies by callback, + * but will always return \c false if the command is not recognized. + * + * @see RETRO_ENVIRONMENT_SET_ROTATION + * @see retro_set_environment() + */ typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); -/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian - * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). +/** + * Render a frame. * - * Width and height specify dimensions of buffer. - * Pitch specifices length in bytes between two lines in buffer. - * - * For performance reasons, it is highly recommended to have a frame + * @note For performance reasons, it is highly recommended to have a frame * that is packed in memory, i.e. pitch == width * byte_per_pixel. * Certain graphic APIs, such as OpenGL ES, do not like textures * that are not packed in memory. + * + * @param data A pointer to the frame buffer data with a pixel format of 15-bit \c 0RGB1555 native endian, unless changed with \c RETRO_ENVIRONMENT_SET_PIXEL_FORMAT. + * @param width The width of the frame buffer, in pixels. + * @param height The height frame buffer, in pixels. + * @param pitch The width of the frame buffer, in bytes. + * + * @see retro_set_video_refresh() + * @see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT + * @see retro_pixel_format */ typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); -/* Renders a single audio frame. Should only be used if implementation - * generates a single sample at a time. - * Format is signed 16-bit native endian. +/** + * Renders a single audio frame. Should only be used if implementation generates a single sample at a time. + * + * @param left The left audio sample represented as a signed 16-bit native endian. + * @param right The right audio sample represented as a signed 16-bit native endian. + * + * @see retro_set_audio_sample() + * @see retro_set_audio_sample_batch() */ typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); -/* Renders multiple audio frames in one go. +/** + * Renders multiple audio frames in one go. * - * One frame is defined as a sample of left and right channels, interleaved. - * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. - * Only one of the audio callbacks must ever be used. + * @note Only one of the audio callbacks must ever be used. + * + * @param data A pointer to the audio sample data pairs to render. + * @param frames The number of frames that are represented in the data. One frame + * is defined as a sample of left and right channels, interleaved. + * For example: int16_t buf[4] = { l, r, l, r }; would be 2 frames. + * + * @return The number of samples that were processed. + * + * @see retro_set_audio_sample_batch() + * @see retro_set_audio_sample() */ typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, size_t frames); -/* Polls input. */ +/** + * Polls input. + * + * @see retro_set_input_poll() + */ typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); -/* Queries for input for player 'port'. device will be masked with - * RETRO_DEVICE_MASK. +/** + * Queries for input for player 'port'. * - * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that - * have been set with retro_set_controller_port_device() - * will still use the higher level RETRO_DEVICE_JOYPAD to request input. + * @param port Which player 'port' to query. + * @param device Which device to query for. Will be masked with \c RETRO_DEVICE_MASK. + * @param index The input index to retrieve. + * The exact semantics depend on the device type given in \c device. + * @param id The ID of which value to query, like \c RETRO_DEVICE_ID_JOYPAD_B. + * @returns Depends on the provided arguments, + * but will return 0 if their values are unsupported + * by the frontend or the backing physical device. + * @note Specialization of devices such as \c RETRO_DEVICE_JOYPAD_MULTITAP that + * have been set with \c retro_set_controller_port_device() will still use the + * higher level \c RETRO_DEVICE_JOYPAD to request input. + * + * @see retro_set_input_state() + * @see RETRO_DEVICE_NONE + * @see RETRO_DEVICE_JOYPAD + * @see RETRO_DEVICE_MOUSE + * @see RETRO_DEVICE_KEYBOARD + * @see RETRO_DEVICE_LIGHTGUN + * @see RETRO_DEVICE_ANALOG + * @see RETRO_DEVICE_POINTER */ typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); -/* Sets callbacks. retro_set_environment() is guaranteed to be called - * before retro_init(). +/** + * Sets the environment callback. * - * The rest of the set_* functions are guaranteed to have been called - * before the first call to retro_run() is made. */ -RETRO_API void retro_set_environment(retro_environment_t); -RETRO_API void retro_set_video_refresh(retro_video_refresh_t); -RETRO_API void retro_set_audio_sample(retro_audio_sample_t); -RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t); -RETRO_API void retro_set_input_poll(retro_input_poll_t); -RETRO_API void retro_set_input_state(retro_input_state_t); + * @param cb The function which is used when making environment calls. + * + * @note Guaranteed to be called before \c retro_init(). + * + * @see RETRO_ENVIRONMENT + */ +RETRO_API void retro_set_environment(retro_environment_t cb); -/* Library global initialization/deinitialization. */ +/** + * Sets the video refresh callback. + * + * @param cb The function which is used when rendering a frame. + * + * @note Guaranteed to have been called before the first call to \c retro_run() is made. + */ +RETRO_API void retro_set_video_refresh(retro_video_refresh_t cb); + +/** + * Sets the audio sample callback. + * + * @param cb The function which is used when rendering a single audio frame. + * + * @note Guaranteed to have been called before the first call to \c retro_run() is made. + */ +RETRO_API void retro_set_audio_sample(retro_audio_sample_t cb); + +/** + * Sets the audio sample batch callback. + * + * @param cb The function which is used when rendering multiple audio frames in one go. + * + * @note Guaranteed to have been called before the first call to \c retro_run() is made. + */ +RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb); + +/** + * Sets the input poll callback. + * + * @param cb The function which is used to poll the active input. + * + * @note Guaranteed to have been called before the first call to \c retro_run() is made. + */ +RETRO_API void retro_set_input_poll(retro_input_poll_t cb); + +/** + * Sets the input state callback. + * + * @param cb The function which is used to query the input state. + * + *@note Guaranteed to have been called before the first call to \c retro_run() is made. + */ +RETRO_API void retro_set_input_state(retro_input_state_t cb); + +/** + * @} + */ + +/** + * Called by the frontend when initializing a libretro core. + * + * @warning There are many possible "gotchas" with global state in dynamic libraries. + * Here are some to keep in mind: + *
    + *
  • Do not assume that the core was loaded by the operating system + * for the first time within this call. + * It may have been statically linked or retained from a previous session. + * Consequently, cores must not rely on global variables being initialized + * to their default values before this function is called; + * this also goes for object constructors in C++. + *
  • Although C++ requires that constructors be called for global variables, + * it does not require that their destructors be called + * if stored within a dynamic library's global scope. + *
  • If the core is statically linked to the frontend, + * global variables may be initialized when the frontend itself is initially executed. + *
+ * @see retro_deinit + */ RETRO_API void retro_init(void); + +/** + * Called by the frontend when deinitializing a libretro core. + * The core must release all of its allocated resources before this function returns. + * + * @warning There are many possible "gotchas" with global state in dynamic libraries. + * Here are some to keep in mind: + *
    + *
  • Do not assume that the operating system will unload the core after this function returns, + * as the core may be linked statically or retained in memory. + * Cores should use this function to clean up all allocated resources + * and reset all global variables to their default states. + *
  • Do not assume that this core won't be loaded again after this function returns. + * It may be kept in memory by the frontend for later use, + * or it may be statically linked. + * Therefore, all global variables should be reset to their default states within this function. + *
  • C++ does not require that destructors be called + * for variables within a dynamic library's global scope. + * Therefore, global objects that own dynamically-managed resources + * (such as \c std::string or std::vector) + * should be kept behind pointers that are explicitly deallocated within this function. + *
+ * @see retro_init + */ RETRO_API void retro_deinit(void); -/* Must return RETRO_API_VERSION. Used to validate ABI compatibility - * when the API is revised. */ +/** + * Retrieves which version of the libretro API is being used. + * + * @note This is used to validate ABI compatibility when the API is revised. + * + * @return Must return \c RETRO_API_VERSION. + * + * @see RETRO_API_VERSION + */ RETRO_API unsigned retro_api_version(void); -/* Gets statically known system info. Pointers provided in *info - * must be statically allocated. - * Can be called at any time, even before retro_init(). */ +/** + * Gets statically known system info. + * + * @note Can be called at any time, even before retro_init(). + * + * @param info A pointer to a \c retro_system_info where the info is to be loaded into. This must be statically allocated. + */ RETRO_API void retro_get_system_info(struct retro_system_info *info); -/* Gets information about system audio/video timings and geometry. - * Can be called only after retro_load_game() has successfully completed. - * NOTE: The implementation of this function might not initialize every - * variable if needed. - * E.g. geom.aspect_ratio might not be initialized if core doesn't - * desire a particular aspect ratio. */ +/** + * Gets information about system audio/video timings and geometry. + * + * @note Can be called only after \c retro_load_game() has successfully completed. + * + * @note The implementation of this function might not initialize every variable + * if needed. For example, \c geom.aspect_ratio might not be initialized if + * the core doesn't desire a particular aspect ratio. + * + * @param info A pointer to a \c retro_system_av_info where the audio/video information should be loaded into. + * + * @see retro_system_av_info + */ RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); -/* Sets device to be used for player 'port'. - * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all +/** + * Sets device to be used for player 'port'. + * + * By default, \c RETRO_DEVICE_JOYPAD is assumed to be plugged into all * available ports. - * Setting a particular device type is not a guarantee that libretro cores + * + * @note Setting a particular device type is not a guarantee that libretro cores * will only poll input based on that particular device type. It is only a * hint to the libretro core when a core cannot automatically detect the * appropriate input device type on its own. It is also relevant when a * core can change its behavior depending on device type. * - * As part of the core's implementation of retro_set_controller_port_device, - * the core should call RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the + * @note As part of the core's implementation of retro_set_controller_port_device, + * the core should call \c RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the * frontend if the descriptions for any controls have changed as a * result of changing the device type. + * + * @param port Which port to set the device for, usually indicates the player number. + * @param device Which device the given port is using. By default, \c RETRO_DEVICE_JOYPAD is assumed for all ports. + * + * @see RETRO_DEVICE_NONE + * @see RETRO_DEVICE_JOYPAD + * @see RETRO_DEVICE_MOUSE + * @see RETRO_DEVICE_KEYBOARD + * @see RETRO_DEVICE_LIGHTGUN + * @see RETRO_DEVICE_ANALOG + * @see RETRO_DEVICE_POINTER + * @see RETRO_ENVIRONMENT_SET_CONTROLLER_INFO */ RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); -/* Resets the current game. */ +/** + * Resets the currently-loaded game. + * Cores should treat this as a soft reset (i.e. an emulated reset button) if possible, + * but hard resets are acceptable. + */ RETRO_API void retro_reset(void); -/* Runs the game for one video frame. - * During retro_run(), input_poll callback must be called at least once. +/** + * Runs the game for one video frame. * - * If a frame is not rendered for reasons where a game "dropped" a frame, - * this still counts as a frame, and retro_run() should explicitly dupe - * a frame if GET_CAN_DUPE returns true. - * In this case, the video callback can take a NULL argument for data. + * During \c retro_run(), the \c retro_input_poll_t callback must be called at least once. + * + * @note If a frame is not rendered for reasons where a game "dropped" a frame, + * this still counts as a frame, and \c retro_run() should explicitly dupe + * a frame if \c RETRO_ENVIRONMENT_GET_CAN_DUPE returns true. In this case, + * the video callback can take a NULL argument for data. + * + * @see retro_input_poll_t */ RETRO_API void retro_run(void); -/* Returns the amount of data the implementation requires to serialize - * internal state (save states). - * Between calls to retro_load_game() and retro_unload_game(), the +/** + * Returns the amount of data the implementation requires to serialize internal state (save states). + * + * @note Between calls to \c retro_load_game() and \c retro_unload_game(), the * returned size is never allowed to be larger than a previous returned * value, to ensure that the frontend can allocate a save state buffer once. + * + * @return The amount of data the implementation requires to serialize the internal state. + * + * @see retro_serialize() */ RETRO_API size_t retro_serialize_size(void); -/* Serializes internal state. If failed, or size is lower than - * retro_serialize_size(), it should return false, true otherwise. */ +/** + * Serializes the internal state. + * + * @param data A pointer to where the serialized data should be saved to. + * @param size The size of the memory. + * + * @return If failed, or size is lower than \c retro_serialize_size(), it + * should return false. On success, it will return true. + * + * @see retro_serialize_size() + * @see retro_unserialize() + */ RETRO_API bool retro_serialize(void *data, size_t size); + +/** + * Unserialize the given state data, and load it into the internal state. + * + * @return Returns true if loading the state was successful, false otherwise. + * + * @see retro_serialize() + */ RETRO_API bool retro_unserialize(const void *data, size_t size); +/** + * Reset all the active cheats to their default disabled state. + * + * @see retro_cheat_set() + */ RETRO_API void retro_cheat_reset(void); + +/** + * Enable or disable a cheat. + * + * @param index The index of the cheat to act upon. + * @param enabled Whether to enable or disable the cheat. + * @param code A string of the code used for the cheat. + * + * @see retro_cheat_reset() + */ RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code); -/* Loads a game. - * Return true to indicate successful loading and false to indicate load failure. +/** + * Loads a game. + * + * @param game A pointer to a \c retro_game_info detailing information about the game to load. + * May be \c NULL if the core is loaded without content. + * + * @return Will return true when the game was loaded successfully, or false otherwise. + * + * @see retro_game_info + * @see RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME */ RETRO_API bool retro_load_game(const struct retro_game_info *game); -/* Loads a "special" kind of game. Should not be used, - * except in extreme cases. */ +/** + * Called when the frontend has loaded one or more "special" content files, + * typically through subsystems. + * + * @note Only necessary for cores that support subsystems. + * Others may return \c false or delegate to retro_load_game. + * + * @param game_type The type of game to load, + * as determined by \c retro_subsystem_info. + * @param info A pointer to an array of \c retro_game_info objects + * providing information about the loaded content. + * @param num_info The number of \c retro_game_info objects passed into the info parameter. + * @return \c true if loading is successful, false otherwise. + * If the core returns \c false, + * the frontend should abort the core + * and return to its main menu (if applicable). + * + * @see RETRO_ENVIRONMENT_GET_GAME_INFO_EXT + * @see RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO + * @see retro_load_game() + * @see retro_subsystem_info + */ RETRO_API bool retro_load_game_special( unsigned game_type, const struct retro_game_info *info, size_t num_info ); -/* Unloads the currently loaded game. Called before retro_deinit(void). */ +/** + * Unloads the currently loaded game. + * + * @note This is called before \c retro_deinit(void). + * + * @see retro_load_game() + * @see retro_deinit() + */ RETRO_API void retro_unload_game(void); -/* Gets region of game. */ +/** + * Gets the region of the actively loaded content as either \c RETRO_REGION_NTSC or \c RETRO_REGION_PAL. + * @note This refers to the region of the content's intended television standard, + * not necessarily the region of the content's origin. + * For emulated consoles that don't use either standard + * (e.g. handhelds or post-HD platforms), + * the core should return \c RETRO_REGION_NTSC. + * @return The region of the actively loaded content. + * + * @see RETRO_REGION_NTSC + * @see RETRO_REGION_PAL + */ RETRO_API unsigned retro_get_region(void); -/* Gets region of memory. */ +/** + * Get a region of memory. + * + * @param id The ID for the memory block that's desired to retrieve. Can be \c RETRO_MEMORY_SAVE_RAM, \c RETRO_MEMORY_RTC, \c RETRO_MEMORY_SYSTEM_RAM, or \c RETRO_MEMORY_VIDEO_RAM. + * + * @return A pointer to the desired region of memory, or NULL when not available. + * + * @see RETRO_MEMORY_SAVE_RAM + * @see RETRO_MEMORY_RTC + * @see RETRO_MEMORY_SYSTEM_RAM + * @see RETRO_MEMORY_VIDEO_RAM + */ RETRO_API void *retro_get_memory_data(unsigned id); + +/** + * Gets the size of the given region of memory. + * + * @param id The ID for the memory block to check the size of. Can be RETRO_MEMORY_SAVE_RAM, RETRO_MEMORY_RTC, RETRO_MEMORY_SYSTEM_RAM, or RETRO_MEMORY_VIDEO_RAM. + * + * @return The size of the region in memory, or 0 when not available. + * + * @see RETRO_MEMORY_SAVE_RAM + * @see RETRO_MEMORY_RTC + * @see RETRO_MEMORY_SYSTEM_RAM + * @see RETRO_MEMORY_VIDEO_RAM + */ RETRO_API size_t retro_get_memory_size(unsigned id); #ifdef __cplusplus diff --git a/libretro-common/include/queues/fifo_queue.h b/libretro-common/include/queues/fifo_queue.h index 7a27b0434e..5be3f3f58d 100644 --- a/libretro-common/include/queues/fifo_queue.h +++ b/libretro-common/include/queues/fifo_queue.h @@ -33,14 +33,39 @@ RETRO_BEGIN_DECLS +/** + * Returns the available data in \c buffer for reading. + * + * @param buffer fifo_buffer_t *. The FIFO queue to check. + * @return The number of bytes available for reading from \c buffer. + */ #define FIFO_READ_AVAIL(buffer) (((buffer)->end + (((buffer)->end < (buffer)->first) ? (buffer)->size : 0)) - (buffer)->first) +/** + * Returns the available space in \c buffer for writing. + * + * @param buffer fifo_buffer_t *. The FIFO queue to check. + * @return The number of bytes that \c buffer can accept. + */ #define FIFO_WRITE_AVAIL(buffer) (((buffer)->size - 1) - (((buffer)->end + (((buffer)->end < (buffer)->first) ? (buffer)->size : 0)) - (buffer)->first)) +/** + * Returns the available data in \c buffer for reading. + * + * @param buffer \c fifo_buffer_t. The FIFO queue to check. + * @return The number of bytes available for reading from \c buffer. + */ #define FIFO_READ_AVAIL_NONPTR(buffer) (((buffer).end + (((buffer).end < (buffer).first) ? (buffer).size : 0)) - (buffer).first) +/** + * Returns the available space in \c buffer for writing. + * + * @param buffer \c fifo_buffer_t. The FIFO queue to check. + * @return The number of bytes that \c buffer can accept. + */ #define FIFO_WRITE_AVAIL_NONPTR(buffer) (((buffer).size - 1) - (((buffer).end + (((buffer).end < (buffer).first) ? (buffer).size : 0)) - (buffer).first)) +/** @copydoc fifo_buffer_t */ struct fifo_buffer { uint8_t *buffer; @@ -49,24 +74,94 @@ struct fifo_buffer size_t end; }; +/** + * A bounded FIFO byte queue implemented as a ring buffer. + * + * Useful for communication between threads, + * although the caller is responsible for synchronization. + */ typedef struct fifo_buffer fifo_buffer_t; +/** + * Creates a new FIFO queue with \c size bytes of memory. + * Must be freed with \c fifo_free. + * + * @param size The size of the FIFO queue, in bytes. + * @return The new queue if successful, \c NULL otherwise. + * @see fifo_initialize + */ fifo_buffer_t *fifo_new(size_t size); +/** + * Initializes an existing FIFO queue with \c size bytes of memory. + * + * Suitable for use with \c fifo_buffer_t instances + * of static or automatic lifetime. + * Must be freed with \c fifo_deinitialize. + * + * @param buf Pointer to the FIFO queue to initialize. + * May be static or automatic. + * @param size The size of the FIFO queue, in bytes. + * @return \c true if \c buf was initialized with the requested memory, + * \c false if \c buf is \c NULL or there was an error. + */ bool fifo_initialize(fifo_buffer_t *buf, size_t size); +/** + * Resets the bounds of \c buffer, + * effectively clearing it. + * + * No memory will actually be freed, + * but the contents of \c buffer will be overwritten + * with the next call to \c fifo_write. + * @param buffer The FIFO queue to clear. + * Behavior is undefined if \c NULL. + */ static INLINE void fifo_clear(fifo_buffer_t *buffer) { buffer->first = 0; buffer->end = 0; } +/** + * Writes \c size bytes to the given queue. + * + * @param buffer The FIFO queue to write to. + * @param in_buf The buffer to read bytes from. + * @param size The length of \c in_buf, in bytes. + */ void fifo_write(fifo_buffer_t *buffer, const void *in_buf, size_t size); +/** + * Reads \c size bytes from the given queue. + * + * @param buffer The FIFO queue to read from. + * @param in_buf The buffer to store the read bytes in. + * @param size The length of \c in_buf, in bytes. + * @post Upon return, \c buffer will have up to \c size more bytes of space available for writing. + */ void fifo_read(fifo_buffer_t *buffer, void *in_buf, size_t size); +/** + * Releases \c buffer and its contents. + * + * @param buffer The FIFO queue to free. + * If \c NULL, this function will do nothing. + * Behavior is undefined if \c buffer was previously freed. + * @see fifo_deinitialize + */ void fifo_free(fifo_buffer_t *buffer); +/** + * Deallocates the contents of \c buffer, + * but not \c buffer itself. + * + * Suitable for use with static or automatic \c fifo_buffer_t instances. + * + * @param buffer The buffer to deinitialize. + * @return \c false if \c buffer is \c NULL, \c true otherwise. + * @see fifo_free + */ bool fifo_deinitialize(fifo_buffer_t *buffer); diff --git a/libretro-common/include/queues/task_queue.h b/libretro-common/include/queues/task_queue.h index 10400370b3..f854dc57e9 100644 --- a/libretro-common/include/queues/task_queue.h +++ b/libretro-common/include/queues/task_queue.h @@ -36,10 +36,12 @@ RETRO_BEGIN_DECLS enum task_type { + /** A regular task. The vast majority of tasks will use this type. */ TASK_TYPE_NONE, - /* Only one blocking task can exist in the queue at a time. - * Attempts to add a new one while another is running is - * ignored. + + /** + * Only one blocking task can exist in the queue at a time. + * Attempts to add a new one while another is running will fail. */ TASK_TYPE_BLOCKING }; @@ -52,21 +54,38 @@ enum task_style }; typedef struct retro_task retro_task_t; + +/** @copydoc retro_task::callback */ typedef void (*retro_task_callback_t)(retro_task_t *task, void *task_data, void *user_data, const char *error); +/** @copydoc retro_task::handler */ typedef void (*retro_task_handler_t)(retro_task_t *task); +/** @copydoc task_finder_data::func */ typedef bool (*retro_task_finder_t)(retro_task_t *task, void *userdata); +/** + * Displays a message output by a task. + */ typedef void (*retro_task_queue_msg_t)(retro_task_t *task, const char *msg, unsigned prio, unsigned duration, bool flush); +/** @copydoc task_retriever_data::func */ typedef bool (*retro_task_retriever_t)(retro_task_t *task, void *data); +/** + * Called by \c task_queue_wait after each task executes + * (i.e. once per pass over the queue). + * @param data Arbitrary data. + * The function should cast this to a known type. + * @return \c true if \c task_queue_wait should continue waiting, + * \c false if it should return early. + * @see task_queue_wait + */ typedef bool (*retro_task_condition_fn_t)(void *data); typedef struct @@ -74,195 +93,652 @@ typedef struct char *source_file; } decompress_task_data_t; +/** + * A unit of work executed by the task system, + * spread across one or more frames. + * + * Some fields are set by the caller, + * others are set by the task system. + */ struct retro_task { - /* when the task should run (0 for as soon as possible) */ + /** + * The time (in microseconds) when the task should start running, + * or 0 if it should start as soon as possible. + * The exact time this task starts will depend on when the queue is next updated. + * Set by the caller. + * @note This is a point in time, not a duration. + * It is not affected by a frontend's time manipulation (pausing, fast-forward, etc.). + * @see cpu_features_get_time_usec + */ retro_time_t when; + /** + * The main body of work for a task. + * Should be as fast as possible, + * as it will be called with each task queue update + * (usually once per frame). + * Must not be \c NULL. + * + * @param task The task that this handler is associated with. + * Can be used to configure or query the task. + * Will never be \c NULL. + * @see task_queue_check + */ retro_task_handler_t handler; - /* always called from the main loop */ + /** + * Called when this task finishes; + * executed during the next task queue update + * after \c finished is set to \c true. + * May be \c NULL, in which case this function is skipped. + * + * @param task The task that is being cleaned up. + * Will never be \c NULL. + * @param task_data \c task's \c task_data field. + * @param user_data \c task's \c user_data field. + * @param error \c task's \c error field. + * @see task_queue_check + * @see retro_task_callback_t + */ retro_task_callback_t callback; - /* task cleanup handler to free allocated resources, will - * be called immediately after running the main callback */ + /** + * Called when this task finishes immediately after \c callback is run. + * Used to clean up any resources or state owned by the task. + * May be \c NULL, in which case this function is skipped. + * + * @param task The task that is being cleaned up. + * Will never be \c NULL. + */ retro_task_handler_t cleanup; - /* created by the handler, destroyed by the user */ + /** + * Pointer to arbitrary data, intended for "returning" an object from the task + * (although it can be used for any purpose). + * If owned by the task, it should be cleaned up within \c cleanup. + * Not modified or freed by the task queue. + */ void *task_data; - /* owned by the user */ + /** + * Pointer to arbitrary data, intended for passing parameters to the task. + * If owned by the task, it should be cleaned up within \c cleanup. + * Not modified or freed by the task queue. + */ void *user_data; - /* created and destroyed by the code related to the handler */ + /** + * Pointer to arbitrary data, intended for state that exists for the task's lifetime. + * If owned by the task, it should be cleaned up within \c cleanup. + * Not modified or freed by the task queue. + */ void *state; - /* created by task handler; destroyed by main loop - * (after calling the callback) */ + /** + * Human-readable details about an error that occurred while running the task. + * Should be created and assigned within \c handler if there was an error. + * Will be cleaned up by the task queue with \c free() upon this task's completion. + * @see task_set_error + */ char *error; + /** + * Called to update a task's \c progress, + * or to update some view layer (e.g. an on-screen display) + * about the task's progress. + * + * Skipped if \c NULL or if \c mute is set. + * + * @param task The task whose progress is being updated or reported. + * @see progress + */ void (*progress_cb)(retro_task_t*); - /* handler can modify but will be - * free()d automatically if non-NULL. */ + /** + * Human-readable description of this task. + * May be \c NULL, + * but if not then it will be disposed of by the task system with \c free() + * upon this task's completion. + * Can be modified or replaced at any time. + * @see strdup + */ char *title; - /* frontend userdata - * (e.g. associate a sticky notification to a task) */ + /** + * Pointer to arbitrary data, intended for use by a frontend + * (for example, to associate a sticky notification with a task). + * + * This should be cleaned up within \c cleanup if necessary. + * Cores may use this for any purpose. + */ void *frontend_userdata; - /* don't touch this. */ + /** + * @private Pointer to the next task in the queue. + * Do not touch this; it is managed by the task system. + */ retro_task_t *next; - /* -1 = unmetered/indeterminate, 0-100 = current progress percentage */ + /** + * Indicates the current progress of the task. + * + * -1 means the task is indefinite or not measured, + * 0-100 is a percentage of the task's completion. + * + * Set by the caller. + * + * @see progress_cb + */ int8_t progress; - /* task identifier */ + /** + * A unique identifier assigned to a task when it's created. + * Set by the task system. + */ uint32_t ident; + /** + * The type of task this is. + * Set by the caller. + */ enum task_type type; enum task_style style; - /* if set to true, frontend will - use an alternative look for the - task progress display */ + /** + * If \c true, the frontend should use some alternative means + * of displaying this task's progress or messages. + * Not used within cores. + */ bool alternative_look; - /* set to true by the handler to signal - * the task has finished executing. */ + /** + * Set to \c true by \c handler to indicate that this task has finished. + * At this point the task queue will call \c callback and \c cleanup, + * then deallocate the task. + */ bool finished; - /* set to true by the task system - * to signal the task *must* end. */ + /** + * Set to true by the task queue to signal that this task \em must end. + * \c handler should check to see if this is set, + * aborting or completing its work as soon as possible afterward. + * \c callback and \c cleanup will still be called as normal. + * + * @see task_queue_reset + */ bool cancelled; - /* if true no OSD messages will be displayed. */ + /** + * If set, the task queue will not call \c progress_cb + * and will not display any messages from this task. + */ bool mute; }; +/** + * Parameters for \c task_queue_find. + * + * @see task_queue_find + */ typedef struct task_finder_data { + /** + * Predicate to call for each task. + * Must not be \c NULL. + * + * @param task The task to query. + * @param userdata \c userdata from this struct. + * @return \c true if this task matches the search criteria, + * at which point \c task_queue_find will stop searching and return \c true. + */ retro_task_finder_t func; + + /** + * Pointer to arbitrary data. + * Passed directly to \c func. + * May be \c NULL. + */ void *userdata; } task_finder_data_t; +/** + * Contains the result of a call to \c task_retriever_data::func. + * Implemented as an intrusive singly-linked list. + */ typedef struct task_retriever_info { + /** + * The next item in the result list, + * or \c NULL if this is the last one. + */ struct task_retriever_info *next; + + /** + * Arbitrary data returned by \c func. + * Can be anything, but should be a simple \c struct + * so that it can be freed by \c task_queue_retriever_info_free. + */ void *data; } task_retriever_info_t; +/** + * Parameters for \c task_queue_retrieve. + * + * @see task_queue_retrieve + */ typedef struct task_retriever_data { + /** + * Contains the result of each call to \c func that returned \c true. + * Should be initialized to \c NULL. + * Will remain \c NULL after \c task_queue_retrieve if no tasks matched. + * Must be freed by \c task_queue_retriever_info_free. + * @see task_queue_retriever_info_free + */ task_retriever_info_t *list; + + /** + * The handler to compare against. + * Only tasks with this handler will be considered for retrieval. + * Must not be \c NULL. + */ retro_task_handler_t handler; + + /** + * The predicate that determines if the given task will be retrieved. + * Must not be \c NULL. + * + * @param task[in] The task to query. + * @param data[out] Arbitrary data that the retriever should return. + * Allocated by the task queue based on \c element_size. + * @return \c true if \c data should be appended to \c list. + */ retro_task_retriever_t func; + + /** + * The size of the output that \c func may write to. + * Must not be zero. + */ size_t element_size; } task_retriever_data_t; +/** + * Returns the next item in the result list. + * Here's a usage example, assuming that \c results is used to store strings: + * + * @code{.c} + * void print_results(task_retriever_info_t *results) + * { + * char* text = NULL; + * task_retriever_info_t *current = results; + * while (text = task_queue_retriever_info_next(¤t)) + * { + * printf("%s\n", text); + * } + * } + * @endcode + * + * @param link Pointer to the first element in the result list. + * Must not be \c NULL. + * @return The next item in the result list. + */ void *task_queue_retriever_info_next(task_retriever_info_t **link); +/** + * Frees the result of a call to \c task_queue_retrieve. + * @param list The result list to free. + * May be \c NULL, in which case this function does nothing. + * The list, its nodes, and its elements will all be freed. + * + * If the list's elements must be cleaned up with anything besides \c free, + * then the caller must do that itself before invoking this function. + */ void task_queue_retriever_info_free(task_retriever_info_t *list); /** - * Signals a task to end without waiting for - * it to complete. */ + * Cancels the provided task. + * The task should finish its work as soon as possible afterward. + * + * @param task The task to cancel. + * @see task_set_cancelled + */ void task_queue_cancel_task(void *task); +/** + * Sets \c task::finished to the given value. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * Behavior is undefined if \c NULL. + * @param finished Whether the task should be considered finished. + * @see retro_task::finished + */ void task_set_finished(retro_task_t *task, bool finished); +/** + * Sets \c task::mute to the given value. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * Behavior is undefined if \c NULL. + * @param mute Whether the task should be considered muted. + * @see retro_task::mute + */ void task_set_mute(retro_task_t *task, bool mute); +/** + * Sets \c task::error to the given value. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * Behavior is undefined if \c NULL. + * @param error The error message to set. + * @see retro_task::error + * @warning This does not free the existing error message. + * The caller must do that itself. + */ void task_set_error(retro_task_t *task, char *error); +/** + * Sets \c task::progress to the given value. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * Behavior is undefined if \c NULL. + * @param progress The progress value to set. + * @see retro_task::progress + */ void task_set_progress(retro_task_t *task, int8_t progress); +/** + * Sets \c task::title to the given value. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * Behavior is undefined if \c NULL. + * @param title The title to set. + * @see retro_task::title + * @see task_free_title + * @warning This does not free the existing title. + * The caller must do that itself. + */ void task_set_title(retro_task_t *task, char *title); +/** + * Sets \c task::data to the given value. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * Behavior is undefined if \c NULL. + * @param data The data to set. + * @see retro_task::data + */ void task_set_data(retro_task_t *task, void *data); +/** + * Sets \c task::cancelled to the given value. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * Behavior is undefined if \c NULL. + * @param cancelled Whether the task should be considered cancelled. + * @see retro_task::cancelled + */ void task_set_cancelled(retro_task_t *task, bool cancelled); +/** + * Frees the \c task's title, if any. + * Thread-safe if the task queue is threaded. + * + * @param task The task to modify. + * @see task_set_title + */ void task_free_title(retro_task_t *task); +/** + * Returns \c task::cancelled. + * Thread-safe if the task queue is threaded. + * + * @param task The task to query. + * Behavior is undefined if \c NULL. + * @return The value of \c task::cancelled. + * @see retro_task::cancelled + */ bool task_get_cancelled(retro_task_t *task); +/** + * Returns \c task::finished. + * Thread-safe if the task queue is threaded. + * + * @param task The task to query. + * Behavior is undefined if \c NULL. + * @return The value of \c task::finished. + * @see retro_task::finished + */ bool task_get_finished(retro_task_t *task); +/** + * Returns \c task::mute. + * Thread-safe if the task queue is threaded. + * + * @param task The task to query. + * Behavior is undefined if \c NULL. + * @return The value of \c task::mute. + * @see retro_task::mute + */ bool task_get_mute(retro_task_t *task); +/** + * Returns \c task::error. + * Thread-safe if the task queue is threaded. + * + * @param task The task to query. + * Behavior is undefined if \c NULL. + * @return The value of \c task::error. + * @see retro_task::error + */ char* task_get_error(retro_task_t *task); +/** + * Returns \c task::progress. + * Thread-safe if the task queue is threaded. + * + * @param task The task to query. + * Behavior is undefined if \c NULL. + * @return The value of \c task::progress. + * @see retro_task::progress + */ int8_t task_get_progress(retro_task_t *task); +/** + * Returns \c task::title. + * Thread-safe if the task queue is threaded. + * + * @param task The task to query. + * Behavior is undefined if \c NULL. + * @return The value of \c task::title. + * @see retro_task::title + */ char* task_get_title(retro_task_t *task); +/** + * Returns \c task::data. + * Thread-safe if the task queue is threaded. + * + * @param task The task to query. + * Behavior is undefined if \c NULL. + * @return The value of \c task::data. + * @see retro_task::data + */ void* task_get_data(retro_task_t *task); +/** + * Returns whether the task queue is running + * on the same thread that called \c task_queue_init. + * + * @return \c true if the caller is running + * on the same thread that called \c task_queue_init. + */ bool task_is_on_main_thread(void); +/** + * Ensures that the task queue is in threaded mode. + * + * Next time \c retro_task_queue_check is called, + * the task queue will be recreated with threading enabled. + * Existing tasks will continue to run on the new thread. + */ void task_queue_set_threaded(void); +/** + * Ensures that the task queue is not in threaded mode. + * + * Next time \c retro_task_queue_check is called, + * the task queue will be recreated with threading disabled. + * Existing tasks will continue to run on whichever thread updates the queue. + * + * @see task_queue_set_threaded + * @see task_queue_is_threaded + */ void task_queue_unset_threaded(void); +/** + * Returns whether the task queue is running in threaded mode. + * + * @return \c true if the task queue is running its tasks on a separate thread. + */ bool task_queue_is_threaded(void); /** - * Calls func for every running task - * until it returns true. - * Returns a task or NULL if not found. + * Calls the function given in \c find_data for each task + * until it returns \c true for one of them, + * or until all tasks have been searched. + * + * @param find_data Parameters for the search. + * Behavior is undefined if \c NULL. + * @return \c true if \c find_data::func returned \c true for any task. + * @see task_finder_data_t */ bool task_queue_find(task_finder_data_t *find_data); /** - * Calls func for every running task when handler - * parameter matches task handler, allowing the - * list parameter to be filled with user-defined - * data. + * Retrieves arbitrary data from every task + * whose handler matches \c data::handler. + * + * @param data[in, out] Parameters for retrieving data from the task queue, + * including the results themselves. + * Behavior is undefined if \c NULL. + * @see task_retriever_data_t */ void task_queue_retrieve(task_retriever_data_t *data); - /* Checks for finished tasks - * Takes the finished tasks, if any, - * and runs their callbacks. - * This must only be called from the main thread. */ + /** + * Runs each task. + * If a task is finished or cancelled, + * its callback and cleanup handler will be called. + * Afterwards, the task will be deallocated. + * If used in a core, generally called in \c retro_run + * and just before \c task_queue_deinit. + * @warning This must only be called from the main thread. + */ void task_queue_check(void); -/* Pushes a task - * The task will start as soon as possible. - * If a second blocking task is attempted, false will be returned - * and the task will be ignored. */ +/** + * Schedules a task to start running. + * If \c task::when is 0, it will start as soon as possible. + * + * Tasks with the same \c task::when value + * will be executed in the order they were scheduled. + * + * @param task The task to schedule. + * @return \c true unless \c task's type is \c TASK_TYPE_BLOCKING + * and there's already a blocking task in the queue. + */ bool task_queue_push(retro_task_t *task); -/* Blocks until all non-scheduled tasks have finished. - * Will return early if cond is not NULL - * and cond(data) returns false. - * This must only be called from the main thread. */ +/** + * Block until all active (i.e. current time > \c task::when) tasks have finished, + * or until the given function returns \c false. + * If a scheduled task's \c when is passed while within this function, + * it will start executing. + * + * Must only be called from the main thread. + * + * @param cond Function to call after all tasks in the queue have executed + * (i.e. once per pass over the task queue). + * May be \c NULL, in which case the task queue will wait unconditionally. + * @param data Pointer to arbitrary data, passed directly into \c cond. + * May be \c NULL. + * @see retro_task_condition_fn_t + * @see task_queue_deinit + * @see task_queue_reset + * @warning Passing \c NULL to \c cond is strongly discouraged. + * If you use tasks that run indefinitely + * (e.g. for the lifetime of the core), + * you will need a way to stop these tasks externally; + * otherwise, you risk the frontend and core freezing. + */ void task_queue_wait(retro_task_condition_fn_t cond, void* data); -/* Sends a signal to terminate all the tasks. +/** + * Marks all tasks in the queue as cancelled. * - * This won't terminate the tasks immediately. - * They will finish as soon as possible. + * The tasks won't immediately be terminated; + * each task may finish its work, + * but must do so as quickly as possible. * - * This must only be called from the main thread. */ + * Must only be called from the main thread. + * + * @see task_queue_wait + * @see task_queue_deinit + * @see task_set_finished + * @see task_get_cancelled + */ void task_queue_reset(void); -/* Deinitializes the task system. - * This deinitializes the task system. - * The tasks that are running at - * the moment will stay on hold */ +/** + * Deinitializes the task system. + * + * Outstanding tasks will not be cleaned up; + * if the intent is to finish the core or frontend's work, + * then all tasks must be finished before calling this function. + * May be safely called multiple times in a row, + * but only from the main thread. + * @see task_queue_wait + * @see task_queue_reset + */ void task_queue_deinit(void); -/* Initializes the task system. - * This initializes the task system - * and chooses an appropriate - * implementation according to the settings. +/** + * Initializes the task system with the provided parameters. + * Must be called before any other task_queue_* function, + * and must only be called from the main thread. * - * This must only be called from the main thread. */ + * @param threaded \c true if tasks should run on a separate thread, + * \c false if they should remain on the calling thread. + * All tasks run in sequence on a single thread. + * If you want to scale a task to multiple threads, + * you must do so within the task itself. + * @param msg_push The task system will call this function to output messages. + * If \c NULL, no messages will be output. + * @note Calling this function while the task system is already initialized + * will reinitialize it with the new parameters, + * but it will not reset the task queue; + * all existing tasks will continue to run + * when the queue is updated. + * @see task_queue_deinit + * @see retro_task_queue_msg_t + */ void task_queue_init(bool threaded, retro_task_queue_msg_t msg_push); -/* Allocates and inits a new retro_task_t */ +/** + * Allocates and initializes a new task. + * Deallocated by the task queue after it finishes executing. + * + * @returns Pointer to a newly allocated task, + * or \c NULL if allocation fails. + */ retro_task_t *task_init(void); RETRO_END_DECLS diff --git a/libretro-common/include/retro_common.h b/libretro-common/include/retro_common.h index a715a28c40..16ac6357df 100644 --- a/libretro-common/include/retro_common.h +++ b/libretro-common/include/retro_common.h @@ -23,12 +23,12 @@ #ifndef _LIBRETRO_COMMON_RETRO_COMMON_H #define _LIBRETRO_COMMON_RETRO_COMMON_H -/* -This file is designed to normalize the libretro-common compiling environment. -It is not to be used in public API headers, as they should be designed as leanly as possible. -Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable, -in a public API, you may need this. -*/ +/*! + * @internal This file is designed to normalize the libretro-common compiling environment. + * It is not to be used in public API headers, as they should be designed as leanly as possible. + * Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable, + * in a public API, you may need this. + */ /* conditional compilation is handled inside here */ #include diff --git a/libretro-common/include/retro_dirent.h b/libretro-common/include/retro_dirent.h index 3b041679b8..d4af7e27d0 100644 --- a/libretro-common/include/retro_dirent.h +++ b/libretro-common/include/retro_dirent.h @@ -28,50 +28,142 @@ #include +/** @defgroup dirent Directory Entries + * @{ + */ + RETRO_BEGIN_DECLS +/** + * The minimum VFS version (as defined in \c retro_vfs_interface_info::required_interface_version) + * required by the \c dirent functions. + * If no acceptable VFS interface is provided, + * all dirent functions will fall back to libretro-common's implementations. + * @see retro_vfs_interface_info + */ #define DIRENT_REQUIRED_VFS_VERSION 3 +/** + * Installs a frontend-provided VFS interface for the dirent functions to use + * instead of libretro-common's built-in implementations. + * + * @param vfs_info The VFS interface returned by the frontend. + * The dirent functions will fall back to libretro-common's implementations + * if \c vfs_info::required_interface_version is too low. + * @see retro_vfs_interface_info + * @see RETRO_ENVIRONMENT_GET_VFS_INTERFACE + */ void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info); +/** + * Opaque handle to a directory entry (aka "dirent"). + * It may name a file, directory, or other filesystem object. + * @see retro_opendir + */ typedef struct RDIR RDIR; /** + * Opens a directory for reading. * - * retro_opendir: - * @name : path to the directory to open. - * - * Opens a directory for reading. Tidy up with retro_closedir. - * - * Returns: RDIR pointer on success, NULL if name is not a - * valid directory, null itself or the empty string. + * @param name Path to a directory to open. + * @return An \c RDIR representing the given directory if successful. + * Returns \c NULL if \c name is \c NULL, the empty string, or does not name a directory. + * @note The returned \c RDIR must be closed with \c retro_closedir. + * @see retro_opendir_include_hidden + * @see retro_closedir */ struct RDIR *retro_opendir(const char *name); +/** + * @copybrief retro_opendir + * + * @param name Path to the directory to open. + * @param include_hidden Whether to include hidden files and directories + * when iterating over this directory with \c retro_readdir. + * Platforms and filesystems have different notions of "hidden" files. + * Setting this to \c false will not prevent this function from opening \c name. + * @return An \c RDIR representing the given directory if successful. + * Returns \c NULL if \c name is \c NULL, the empty string, or does not name a directory. + * @note The returned \c RDIR must be closed with \c retro_closedir. + * @see retro_opendir + * @see retro_closedir + */ struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden); +/** + * Reads the next entry in the given directory. + * + * Here's a usage example that prints the names of all files in the current directory: + * @code + * struct RDIR *rdir = retro_opendir("."); + * if (rdir) + * { + * while (retro_readdir(rdir)) + * { + * const char *name = retro_dirent_get_name(rdir); + * printf("%s\n", name); + * } + * retro_closedir(rdir); + * rdir = NULL; + * } + * @endcode + * + * @param rdir The directory to iterate over. + * Behavior is undefined if \c NULL. + * @return \c true if the next entry was read successfully, + * \c false if there are no more entries to read or if there was an error. + * @note This may include "." and ".." on Unix-like platforms. + * @see retro_dirent_get_name + * @see retro_dirent_is_dir + */ int retro_readdir(struct RDIR *rdir); -/* Deprecated, returns false, left for compatibility */ +/** + * @deprecated Left for compatibility. + * @param rdir Ignored. + * @return \c false. + */ bool retro_dirent_error(struct RDIR *rdir); +/** + * Gets the name of the dirent's current file or directory. + * + * @param rdir The dirent to get the name of. + * Behavior is undefined if \c NULL. + * @return The name of the directory entry (file, directory, etc.) that the dirent points to. + * Will return \c NULL if there was an error, + * \c retro_readdir has not been called on \c rdir, + * or if there are no more entries to read. + * @note This returns only a name, not a full path. + * @warning The returned string is managed by the VFS implementation + * and must not be modified or freed by the caller. + * @warning The returned string is only valid until the next call to \c retro_readdir. + * @see retro_readdir + */ const char *retro_dirent_get_name(struct RDIR *rdir); /** + * Checks if the given \c RDIR's current dirent names a directory. * - * retro_dirent_is_dir: - * @rdir : pointer to the directory entry. - * @unused : deprecated, included for compatibility reasons, pass NULL - * - * Is the directory listing entry a directory? - * - * Returns: true if directory listing entry is - * a directory, false if not. + * @param rdir The directory entry to check. + * Behavior is undefined if \c NULL. + * @param unused Ignored for compatibility reasons. Pass \c NULL. + * @return \c true if \c rdir refers to a directory, otherwise \c false. + * @see retro_readdir */ bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused); +/** + * Closes an opened \c RDIR that was returned by \c retro_opendir. + * + * @param rdir The directory entry to close. + * If \c NULL, this function does nothing. + * @see retro_vfs_closedir_t + */ void retro_closedir(struct RDIR *rdir); RETRO_END_DECLS +/** @} */ + #endif diff --git a/libretro-common/include/retro_endianness.h b/libretro-common/include/retro_endianness.h index 46984638c8..8638b2c396 100644 --- a/libretro-common/include/retro_endianness.h +++ b/libretro-common/include/retro_endianness.h @@ -31,12 +31,22 @@ #define SWAP16 _byteswap_ushort #define SWAP32 _byteswap_ulong #else +/** + * Swaps the byte order of a 16-bit unsigned integer. + * @param x The integer to byteswap. + * @return \c with its two bytes swapped. + */ static INLINE uint16_t SWAP16(uint16_t x) { return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); } +/** + * Swaps the byte order of a 32-bit unsigned integer. + * @param x The integer to byteswap. + * @return \c with its bytes swapped. + */ static INLINE uint32_t SWAP32(uint32_t x) { return ((x & 0x000000ff) << 24) | @@ -61,6 +71,11 @@ static INLINE uint64_t SWAP64(uint64_t val) | ((val & 0xff00000000000000) >> 56); } #else +/** + * Swaps the byte order of a 64-bit unsigned integer. + * @param x The integer to byteswap. + * @return \c with its bytes swapped. + */ static INLINE uint64_t SWAP64(uint64_t val) { return ((val & 0x00000000000000ffULL) << 56) @@ -124,25 +139,20 @@ static INLINE uint64_t SWAP64(uint64_t val) /** - * is_little_endian: + * Checks if the current CPU is little-endian. * - * Checks if the system is little endian or big-endian. - * - * Returns: greater than 0 if little-endian, - * otherwise big-endian. - **/ + * @return \c true on little-endian CPUs, + * \c false on big-endian CPUs. + */ #define is_little_endian() RETRO_IS_LITTLE_ENDIAN /** - * swap_if_big64: - * @val : unsigned 64-bit value + * Byte-swaps an unsigned 64-bit integer on big-endian CPUs. * - * Byteswap unsigned 64-bit value if system is big-endian. - * - * Returns: Byteswapped value in case system is big-endian, - * otherwise returns same value. - **/ - + * @param val The value to byteswap if necessary. + * @return \c val byteswapped on big-endian CPUs, + * \c val unchanged on little-endian CPUs. + */ #if RETRO_IS_BIG_ENDIAN #define swap_if_big64(val) (SWAP64(val)) #elif RETRO_IS_LITTLE_ENDIAN @@ -150,15 +160,12 @@ static INLINE uint64_t SWAP64(uint64_t val) #endif /** - * swap_if_big32: - * @val : unsigned 32-bit value + * Byte-swaps an unsigned 32-bit integer on big-endian CPUs. * - * Byteswap unsigned 32-bit value if system is big-endian. - * - * Returns: Byteswapped value in case system is big-endian, - * otherwise returns same value. - **/ - + * @param val The value to byteswap if necessary. + * @return \c val byteswapped on big-endian CPUs, + * \c val unchanged on little-endian CPUs. + */ #if RETRO_IS_BIG_ENDIAN #define swap_if_big32(val) (SWAP32(val)) #elif RETRO_IS_LITTLE_ENDIAN @@ -166,15 +173,12 @@ static INLINE uint64_t SWAP64(uint64_t val) #endif /** - * swap_if_little64: - * @val : unsigned 64-bit value + * Byte-swaps an unsigned 64-bit integer on little-endian CPUs. * - * Byteswap unsigned 64-bit value if system is little-endian. - * - * Returns: Byteswapped value in case system is little-endian, - * otherwise returns same value. - **/ - + * @param val The value to byteswap if necessary. + * @return \c val byteswapped on little-endian CPUs, + * \c val unchanged on big-endian CPUs. + */ #if RETRO_IS_BIG_ENDIAN #define swap_if_little64(val) (val) #elif RETRO_IS_LITTLE_ENDIAN @@ -182,15 +186,12 @@ static INLINE uint64_t SWAP64(uint64_t val) #endif /** - * swap_if_little32: - * @val : unsigned 32-bit value + * Byte-swaps an unsigned 32-bit integer on little-endian CPUs. * - * Byteswap unsigned 32-bit value if system is little-endian. - * - * Returns: Byteswapped value in case system is little-endian, - * otherwise returns same value. - **/ - + * @param val The value to byteswap if necessary. + * @return \c val byteswapped on little-endian CPUs, + * \c val unchanged on big-endian CPUs. + */ #if RETRO_IS_BIG_ENDIAN #define swap_if_little32(val) (val) #elif RETRO_IS_LITTLE_ENDIAN @@ -198,15 +199,12 @@ static INLINE uint64_t SWAP64(uint64_t val) #endif /** - * swap_if_big16: - * @val : unsigned 16-bit value + * Byte-swaps an unsigned 16-bit integer on big-endian systems. * - * Byteswap unsigned 16-bit value if system is big-endian. - * - * Returns: Byteswapped value in case system is big-endian, - * otherwise returns same value. - **/ - + * @param val The value to byteswap if necessary. + * @return \c val byteswapped on big-endian systems, + * \c val unchanged on little-endian systems. + */ #if RETRO_IS_BIG_ENDIAN #define swap_if_big16(val) (SWAP16(val)) #elif RETRO_IS_LITTLE_ENDIAN @@ -214,15 +212,12 @@ static INLINE uint64_t SWAP64(uint64_t val) #endif /** - * swap_if_little16: - * @val : unsigned 16-bit value + * Byte-swaps an unsigned 16-bit integer on little-endian systems. * - * Byteswap unsigned 16-bit value if system is little-endian. - * - * Returns: Byteswapped value in case system is little-endian, - * otherwise returns same value. - **/ - + * @param val The value to byteswap if necessary. + * @return \c val byteswapped on little-endian systems, + * \c val unchanged on big-endian systems. + */ #if RETRO_IS_BIG_ENDIAN #define swap_if_little16(val) (val) #elif RETRO_IS_LITTLE_ENDIAN @@ -230,167 +225,143 @@ static INLINE uint64_t SWAP64(uint64_t val) #endif /** - * store32be: - * @addr : pointer to unsigned 32-bit buffer - * @data : unsigned 32-bit value to write + * Stores a 32-bit integer in at the given address, in big-endian order. * - * Write data to address. Endian-safe. Byteswaps the data - * first if necessary before storing it. - **/ + * @param addr The address to store the value at. + * Behavior is undefined if \c NULL or not aligned to a 32-bit boundary. + * @param data The value to store in \c addr. + * Will be byteswapped if on a little-endian CPU. + */ static INLINE void store32be(uint32_t *addr, uint32_t data) { *addr = swap_if_little32(data); } /** - * load32be: - * @addr : pointer to unsigned 32-bit buffer + * Loads a 32-bit integer order from the given address, in big-endian order. * - * Load value from address. Endian-safe. - * - * Returns: value from address, byte-swapped if necessary. - **/ + * @param addr The address to load the value from. + * Behavior is undefined if \c NULL or not aligned to a 32-bit boundary. + * @return The value at \c addr, byteswapped if on a little-endian CPU. + */ static INLINE uint32_t load32be(const uint32_t *addr) { return swap_if_little32(*addr); } /** - * retro_cpu_to_le16: - * @val : unsigned 16-bit value + * Converts the given unsigned 16-bit integer to little-endian order if necessary. * - * Convert unsigned 16-bit value from system to little-endian. - * - * Returns: Little-endian representation of val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a big-endian CPU, + * unchanged otherwise. + */ #define retro_cpu_to_le16(val) swap_if_big16(val) /** - * retro_cpu_to_le32: - * @val : unsigned 32-bit value + * Converts the given unsigned 32-bit integer to little-endian order if necessary. * - * Convert unsigned 32-bit value from system to little-endian. - * - * Returns: Little-endian representation of val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a big-endian CPU, + * unchanged otherwise. + */ #define retro_cpu_to_le32(val) swap_if_big32(val) /** - * retro_cpu_to_le64: - * @val : unsigned 64-bit value + * Converts the given unsigned 64-bit integer to little-endian order if necessary. * - * Convert unsigned 64-bit value from system to little-endian. - * - * Returns: Little-endian representation of val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a big-endian CPU, + * unchanged otherwise. + */ #define retro_cpu_to_le64(val) swap_if_big64(val) /** - * retro_le_to_cpu16: - * @val : unsigned 16-bit value + * Converts the given unsigned 16-bit integer to host-native order if necessary. * - * Convert unsigned 16-bit value from little-endian to native. - * - * Returns: Native representation of little-endian val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a big-endian CPU, + * unchanged otherwise. + */ #define retro_le_to_cpu16(val) swap_if_big16(val) /** - * retro_le_to_cpu32: - * @val : unsigned 32-bit value + * Converts the given unsigned 32-bit integer to host-native order if necessary. * - * Convert unsigned 32-bit value from little-endian to native. - * - * Returns: Native representation of little-endian val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a big-endian CPU, + * unchanged otherwise. + */ #define retro_le_to_cpu32(val) swap_if_big32(val) /** - * retro_le_to_cpu16: - * @val : unsigned 64-bit value + * Converts the given unsigned 64-bit integer to host-native order if necessary. * - * Convert unsigned 64-bit value from little-endian to native. - * - * Returns: Native representation of little-endian val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a big-endian CPU, + * unchanged otherwise. + */ #define retro_le_to_cpu64(val) swap_if_big64(val) /** - * retro_cpu_to_be16: - * @val : unsigned 16-bit value + * Converts the given unsigned 16-bit integer to big-endian order if necessary. * - * Convert unsigned 16-bit value from system to big-endian. - * - * Returns: Big-endian representation of val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a little-endian CPU, + * unchanged otherwise. + */ #define retro_cpu_to_be16(val) swap_if_little16(val) /** - * retro_cpu_to_be32: - * @val : unsigned 32-bit value + * Converts the given unsigned 32-bit integer to big-endian order if necessary. * - * Convert unsigned 32-bit value from system to big-endian. - * - * Returns: Big-endian representation of val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a little-endian CPU, + * unchanged otherwise. + */ #define retro_cpu_to_be32(val) swap_if_little32(val) /** - * retro_cpu_to_be64: - * @val : unsigned 64-bit value + * Converts the given unsigned 64-bit integer to big-endian order if necessary. * - * Convert unsigned 64-bit value from system to big-endian. - * - * Returns: Big-endian representation of val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a little-endian CPU, + * unchanged otherwise. + */ #define retro_cpu_to_be64(val) swap_if_little64(val) /** - * retro_be_to_cpu16: - * @val : unsigned 16-bit value + * Converts the given unsigned 16-bit integer from big-endian to host-native order if necessary. * - * Convert unsigned 16-bit value from big-endian to native. - * - * Returns: Native representation of big-endian val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a little-endian CPU, + * unchanged otherwise. + */ #define retro_be_to_cpu16(val) swap_if_little16(val) /** - * retro_be_to_cpu32: - * @val : unsigned 32-bit value + * Converts the given unsigned 32-bit integer from big-endian to host-native order if necessary. * - * Convert unsigned 32-bit value from big-endian to native. - * - * Returns: Native representation of big-endian val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a little-endian CPU, + * unchanged otherwise. + */ #define retro_be_to_cpu32(val) swap_if_little32(val) /** - * retro_be_to_cpu64: - * @val : unsigned 64-bit value + * Converts the given unsigned 64-bit integer from big-endian to host-native order if necessary. * - * Convert unsigned 64-bit value from big-endian to native. - * - * Returns: Native representation of big-endian val. - **/ - + * @param val The value to convert if necessary. + * @return \c val byteswapped if on a little-endian CPU, + * unchanged otherwise. + */ #define retro_be_to_cpu64(val) swap_if_little64(val) #ifdef __GNUC__ -/* This attribute means that the same memory may be referred through - pointers to different size of the object (aliasing). E.g. that u8 * - and u32 * may actually be pointing to the same object. */ +/** + * This attribute indicates that pointers to this type may alias + * to pointers of any other type, similar to \c void* or \c char*. + */ #define MAY_ALIAS __attribute__((__may_alias__)) #else #define MAY_ALIAS @@ -411,8 +382,22 @@ struct retro_unaligned_uint64_s } MAY_ALIAS; #pragma pack(pop) +/** + * A wrapper around a \c uint16_t that allows unaligned access + * where supported by the compiler. + */ typedef struct retro_unaligned_uint16_s retro_unaligned_uint16_t; + +/** + * A wrapper around a \c uint32_t that allows unaligned access + * where supported by the compiler. + */ typedef struct retro_unaligned_uint32_s retro_unaligned_uint32_t; + +/** + * A wrapper around a \c uint64_t that allows unaligned access + * where supported by the compiler. + */ typedef struct retro_unaligned_uint64_s retro_unaligned_uint64_t; /* L-value references to unaligned pointers. */ @@ -421,157 +406,175 @@ typedef struct retro_unaligned_uint64_s retro_unaligned_uint64_t; #define retro_unaligned64(p) (((retro_unaligned_uint64_t *)p)->val) /** - * retro_get_unaligned_16be: - * @addr : pointer to unsigned 16-bit value + * Reads a 16-bit unsigned integer from the given address + * and converts it from big-endian to host-native order (if necessary), + * regardless of the CPU's alignment requirements. * - * Convert unsigned unaligned 16-bit value from big-endian to native. - * - * Returns: Native representation of big-endian val. - **/ - + * @param addr The address of the integer to read. + * Does not need to be divisible by 2 + * the way a \c uint16_t* usually would be. + * @return The first two bytes of \c addr as a 16-bit unsigned integer, + * byteswapped from big-endian to host-native order if necessary. + */ static INLINE uint16_t retro_get_unaligned_16be(void *addr) { return retro_be_to_cpu16(retro_unaligned16(addr)); } /** - * retro_get_unaligned_32be: - * @addr : pointer to unsigned 32-bit value + * Reads a 32-bit unsigned integer from the given address + * and converts it from big-endian to host-native order (if necessary), + * regardless of the CPU's alignment requirements. * - * Convert unsigned unaligned 32-bit value from big-endian to native. - * - * Returns: Native representation of big-endian val. - **/ - + * @param addr The address of the integer to read. + * Does not need to be divisible by 4 + * the way a \c uint32_t* usually would be. + * @return The first four bytes of \c addr as a 32-bit unsigned integer, + * byteswapped from big-endian to host-native order if necessary. + */ static INLINE uint32_t retro_get_unaligned_32be(void *addr) { return retro_be_to_cpu32(retro_unaligned32(addr)); } /** - * retro_get_unaligned_64be: - * @addr : pointer to unsigned 64-bit value + * Reads a 64-bit unsigned integer from the given address + * and converts it from big-endian to host-native order (if necessary), + * regardless of the CPU's alignment requirements. * - * Convert unsigned unaligned 64-bit value from big-endian to native. - * - * Returns: Native representation of big-endian val. - **/ - + * @param addr The address of the integer to read. + * Does not need to be divisible by 8 + * the way a \c uint64_t* usually would be. + * @return The first eight bytes of \c addr as a 64-bit unsigned integer, + * byteswapped from big-endian to host-native order if necessary. + */ static INLINE uint64_t retro_get_unaligned_64be(void *addr) { return retro_be_to_cpu64(retro_unaligned64(addr)); } /** - * retro_get_unaligned_16le: - * @addr : pointer to unsigned 16-bit value + * Reads a 16-bit unsigned integer from the given address + * and converts it from little-endian to host-native order (if necessary), + * regardless of the CPU's alignment requirements. * - * Convert unsigned unaligned 16-bit value from little-endian to native. - * - * Returns: Native representation of little-endian val. - **/ - + * @param addr The address of the integer to read. + * Does not need to be divisible by 2 + * the way a \c uint16_t* usually would be. + * @return The first two bytes of \c addr as a 16-bit unsigned integer, + * byteswapped from little-endian to host-native order if necessary. + */ static INLINE uint16_t retro_get_unaligned_16le(void *addr) { return retro_le_to_cpu16(retro_unaligned16(addr)); } /** - * retro_get_unaligned_32le: - * @addr : pointer to unsigned 32-bit value + * Reads a 32-bit unsigned integer from the given address + * and converts it from little-endian to host-native order (if necessary), + * regardless of the CPU's alignment requirements. * - * Convert unsigned unaligned 32-bit value from little-endian to native. - * - * Returns: Native representation of little-endian val. - **/ - + * @param addr The address of the integer to read. + * Does not need to be divisible by 4 + * the way a \c uint32_t* usually would be. + * @return The first four bytes of \c addr as a 32-bit unsigned integer, + * byteswapped from little-endian to host-native order if necessary. + */ static INLINE uint32_t retro_get_unaligned_32le(void *addr) { return retro_le_to_cpu32(retro_unaligned32(addr)); } /** - * retro_get_unaligned_64le: - * @addr : pointer to unsigned 64-bit value + * Reads a 64-bit unsigned integer from the given address + * and converts it from little-endian to host-native order (if necessary), + * regardless of the CPU's alignment requirements. * - * Convert unsigned unaligned 64-bit value from little-endian to native. - * - * Returns: Native representation of little-endian val. - **/ - + * @param addr The address of the integer to read. + * Does not need to be divisible by 8 + * the way a \c uint64_t* usually would be. + * @return The first eight bytes of \c addr as a 64-bit unsigned integer, + * byteswapped from little-endian to host-native order if necessary. + */ static INLINE uint64_t retro_get_unaligned_64le(void *addr) { return retro_le_to_cpu64(retro_unaligned64(addr)); } /** - * retro_set_unaligned_16le: - * @addr : pointer to unsigned 16-bit value - * @val : value to store + * Writes a 16-bit unsigned integer to the given address + * (converted to little-endian order if necessary), + * regardless of the CPU's alignment requirements. * - * Convert native value to unsigned unaligned 16-bit little-endian value - * - **/ - + * @param addr The address to write the integer to. + * Does not need to be divisible by 2 + * the way a \c uint16_t* usually would be. + * @param v The value to write. + */ static INLINE void retro_set_unaligned_16le(void *addr, uint16_t v) { retro_unaligned16(addr) = retro_cpu_to_le16(v); } /** - * retro_set_unaligned_32le: - * @addr : pointer to unsigned 32-bit value - * @val : value to store + * Writes a 32-bit unsigned integer to the given address + * (converted to little-endian order if necessary), + * regardless of the CPU's alignment requirements. * - * Convert native value to unsigned unaligned 32-bit little-endian value - * - **/ - + * @param addr The address to write the integer to. + * Does not need to be divisible by 4 + * the way a \c uint32_t* usually would be. + * @param v The value to write. + */ static INLINE void retro_set_unaligned_32le(void *addr, uint32_t v) { retro_unaligned32(addr) = retro_cpu_to_le32(v); } /** - * retro_set_unaligned_32le: - * @addr : pointer to unsigned 32-bit value - * @val : value to store + * Writes a 64-bit unsigned integer to the given address + * (converted to little-endian order if necessary), + * regardless of the CPU's alignment requirements. * - * Convert native value to unsigned unaligned 32-bit little-endian value - * - **/ - + * @param addr The address to write the integer to. + * Does not need to be divisible by 8 + * the way a \c uint64_t* usually would be. + * @param v The value to write. + */ static INLINE void retro_set_unaligned_64le(void *addr, uint64_t v) { retro_unaligned64(addr) = retro_cpu_to_le64(v); } /** - * retro_set_unaligned_16be: - * @addr : pointer to unsigned 16-bit value - * @val : value to store + * Writes a 16-bit unsigned integer to the given address + * (converted to big-endian order if necessary), + * regardless of the CPU's alignment requirements. * - * Convert native value to unsigned unaligned 16-bit big-endian value - * - **/ - + * @param addr The address to write the integer to. + * Does not need to be divisible by 2 + * the way a \c uint16_t* usually would be. + * @param v The value to write. + */ static INLINE void retro_set_unaligned_16be(void *addr, uint16_t v) { retro_unaligned16(addr) = retro_cpu_to_be16(v); } /** - * retro_set_unaligned_32be: - * @addr : pointer to unsigned 32-bit value - * @val : value to store + * Writes a 32-bit unsigned integer to the given address + * (converted to big-endian order if necessary), + * regardless of the CPU's alignment requirements. * - * Convert native value to unsigned unaligned 32-bit big-endian value - * - **/ - + * @param addr The address to write the integer to. + * Does not need to be divisible by 4 + * the way a \c uint32_t* usually would be. + * @param v The value to write. + */ static INLINE void retro_set_unaligned_32be(void *addr, uint32_t v) { retro_unaligned32(addr) = retro_cpu_to_be32(v); } /** - * retro_set_unaligned_32be: - * @addr : pointer to unsigned 32-bit value - * @val : value to store + * Writes a 64-bit unsigned integer to the given address + * (converted to big-endian order if necessary), + * regardless of the CPU's alignment requirements. * - * Convert native value to unsigned unaligned 32-bit big-endian value - * - **/ - + * @param addr The address to write the integer to. + * Does not need to be divisible by 8 + * the way a \c uint64_t* usually would be. + * @param v The value to write. + */ static INLINE void retro_set_unaligned_64be(void *addr, uint64_t v) { retro_unaligned64(addr) = retro_cpu_to_be64(v); } diff --git a/libretro-common/include/retro_inline.h b/libretro-common/include/retro_inline.h index b27d6dd6d4..a9e41bc8e6 100644 --- a/libretro-common/include/retro_inline.h +++ b/libretro-common/include/retro_inline.h @@ -25,6 +25,12 @@ #ifndef INLINE +/** + * Cross-platform inline specifier. + * + * Expands to something like \c __inline or \c inline, + * depending on the compiler. + */ #if defined(_WIN32) || defined(__INTEL_COMPILER) #define INLINE __inline #elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h index a42ed176b6..dfa69975c3 100644 --- a/libretro-common/include/retro_miscellaneous.h +++ b/libretro-common/include/retro_miscellaneous.h @@ -53,6 +53,13 @@ #include #endif +/** + * Computes the bitwise OR of two bit arrays. + * + * @param a[in,out] The first bit array, and the location of the result. + * @param b[in] The second bit array. + * @param count The length of each bit array, in 32-bit words. + */ static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count) { uint32_t i; @@ -60,6 +67,14 @@ static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count) a[i] |= b[i]; } +/** + * Clears every bit in \c a that is set in \c b. + * + * @param a[in,out] The bit array to modify. + * @param b[in] The bit array to use for reference. + * @param count The length of each bit array, in 32-bit words + * (\em not bits or bytes). + */ static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count) { uint32_t i; @@ -67,6 +82,15 @@ static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count) a[i] &= ~b[i]; } +/** + * Checks if any bits in \c ptr are set. + * + * @param ptr The bit array to check. + * @param count The length of the buffer pointed to by \c ptr, in 32-bit words + * (\em not bits or bytes). + * @return \c true if any bit in \c ptr is set, + * \c false if all bits are clear (zero). + */ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count) { uint32_t i; @@ -78,6 +102,16 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count) return false; } +/** + * Checks if any bits in \c a are different from those in \c b. + * + * @param a The first bit array to compare. + * @param b The second bit array to compare. + * @param count The length of each bit array, in 32-bit words + * (\em not bits or bytes). + * @return \c true if \c and \c differ by at least one bit, + * \c false if they're both identical. + */ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count) { uint32_t i; @@ -93,46 +127,212 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count) #if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(__PSL1GHT__) || defined(__PS3__) || defined(HAVE_EMSCRIPTEN) #define PATH_MAX_LENGTH 512 #else +/** + * An upper limit for the length of a path (including the filename). + * If a path is longer than this, it may not work properly. + * This value may vary by platform. + */ #define PATH_MAX_LENGTH 4096 #endif #endif #ifndef NAME_MAX_LENGTH +/** + * An upper limit for the length of a file or directory (excluding parent directories). + * If a path has a component longer than this, it may not work properly. + */ #define NAME_MAX_LENGTH 256 #endif #ifndef MAX +/** + * @return \c a or \c b, whichever is larger. + */ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN +/** + * @return \c a or \c b, whichever is smaller. + */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif +/** + * Gets the number of elements in an array whose size is known at compile time. + * @param a An array of fixed length. + * @return The number of elements in \c a. + */ #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +/** @defgroup BITS Bit Arrays + * + * @{ + */ + #define BITS_GET_ELEM(a, i) ((a).data[i]) #define BITS_GET_ELEM_PTR(a, i) ((a)->data[i]) +/** @defgroup BIT_ Arbitrary-length Bit Arrays + * + * @{ + */ + +/** + * Sets a particular bit within a bit array to 1. + * + * @param a A \c uint8_t array, + * treated here as a bit vector. + * @param bit Index of the bit to set, where 0 is the least significant. + */ #define BIT_SET(a, bit) ((a)[(bit) >> 3] |= (1 << ((bit) & 7))) + +/** + * Clears a particular bit within a bit array. + * + * @param a A \c uint8_t array, + * treated here as a bit vector. + * @param bit Index of the bit to clear, where 0 is the least significant. + */ #define BIT_CLEAR(a, bit) ((a)[(bit) >> 3] &= ~(1 << ((bit) & 7))) + +/** + * Gets the value of a particular bit within a bit array. + * + * @param a A \c uint8_t array, + * treated here as a bit vector. + * @param bit Index of the bit to get, where 0 is the least significant. + * @return The value of the bit at the specified index. + */ #define BIT_GET(a, bit) (((a)[(bit) >> 3] >> ((bit) & 7)) & 1) +/** @} */ + +/** @defgroup BIT16 16-bit Bit Arrays + * + * @{ + */ + +/** + * Sets a particular bit within a 16-bit integer to 1. + * @param a An unsigned 16-bit integer, + * treated as a bit array. + * @param bit Index of the bit to set, where 0 is the least significant and 15 is the most. + */ #define BIT16_SET(a, bit) ((a) |= (1 << ((bit) & 15))) + +/** + * Clears a particular bit within a 16-bit integer. + * + * @param a An unsigned 16-bit integer, + * treated as a bit array. + * @param bit Index of the bit to clear, where 0 is the least significant and 15 is the most. + */ #define BIT16_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 15))) + +/** + * Gets the value of a particular bit within a 16-bit integer. + * + * @param a An unsigned 16-bit integer, + * treated as a bit array. + * @param bit Index of the bit to get, where 0 is the least significant and 15 is the most. + * @return The value of the bit at the specified index. + */ #define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1) + +/** + * Clears all bits in a 16-bit bitmask. + */ #define BIT16_CLEAR_ALL(a) ((a) = 0) +/** @} */ + +/** @defgroup BIT32 32-bit Bit Arrays + * + * @{ + */ + +/** + * Sets a particular bit within a 32-bit integer to 1. + * + * @param a An unsigned 32-bit integer, + * treated as a bit array. + * @param bit Index of the bit to set, where 0 is the least significant and 31 is the most. + */ #define BIT32_SET(a, bit) ((a) |= (UINT32_C(1) << ((bit) & 31))) + +/** + * Clears a particular bit within a 32-bit integer. + * + * @param a An unsigned 32-bit integer, + * treated as a bit array. + * @param bit Index of the bit to clear, where 0 is the least significant and 31 is the most. + */ #define BIT32_CLEAR(a, bit) ((a) &= ~(UINT32_C(1) << ((bit) & 31))) + +/** + * Gets the value of a particular bit within a 32-bit integer. + * + * @param a An unsigned 32-bit integer, + * treated as a bit array. + * @param bit Index of the bit to get, where 0 is the least significant and 31 is the most. + * @return The value of the bit at the specified index. + */ #define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1) + +/** + * Clears all bits in a 32-bit bitmask. + * + * @param a An unsigned 32-bit integer, + * treated as a bit array. + */ #define BIT32_CLEAR_ALL(a) ((a) = 0) +/** @} */ + +/** + * @defgroup BIT64 64-bit Bit Arrays + * @{ + */ + +/** + * Sets a particular bit within a 64-bit integer to 1. + * + * @param a An unsigned 64-bit integer, + * treated as a bit array. + * @param bit Index of the bit to set, where 0 is the least significant and 63 is the most. + */ #define BIT64_SET(a, bit) ((a) |= (UINT64_C(1) << ((bit) & 63))) + +/** + * Clears a particular bit within a 64-bit integer. + * + * @param a An unsigned 64-bit integer, + * treated as a bit array. + * @param bit Index of the bit to clear, where 0 is the least significant and 63 is the most. + */ #define BIT64_CLEAR(a, bit) ((a) &= ~(UINT64_C(1) << ((bit) & 63))) + +/** + * Gets the value of a particular bit within a 64-bit integer. + * + * @param a An unsigned 64-bit integer, + * treated as a bit array. + * @param bit Index of the bit to get, where 0 is the least significant and 63 is the most. + * @return The value of the bit at the specified index. + */ #define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1) + +/** + * Clears all bits in a 64-bit bitmask. + * + * @param a An unsigned 64-bit integer, + * treated as a bit array. + */ #define BIT64_CLEAR_ALL(a) ((a) = 0) +/** @} */ + #define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (UINT32_C(1) << ((bit) & 31))) #define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(UINT32_C(1) << ((bit) & 31))) #define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1) @@ -143,24 +343,98 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count) #define BIT128_GET_PTR(a, bit) BIT128_GET(*a, bit) #define BIT128_CLEAR_ALL_PTR(a) BIT128_CLEAR_ALL(*a) +/** + * Sets a single bit from a 256-bit \c retro_bits_t to 1. + * + * @param a A 256-bit \c retro_bits_t. + * @param bit Index of the bit to set, + * where 0 is the least significant and 255 is the most. + */ #define BIT256_SET(a, bit) BIT128_SET(a, bit) + +/** + * Clears a single bit from a 256-bit \c retro_bits_t. + * + * @param a A 256-bit \c retro_bits_t. + * @param bit Index of the bit to clear, + * where 0 is the least significant and 255 is the most. + */ #define BIT256_CLEAR(a, bit) BIT128_CLEAR(a, bit) + +/** + * Gets the value of a single bit from a 256-bit \c retro_bits_t. + * + * @param a A 256-bit \c retro_bits_t. + * @param bit Index of the bit to get, + * where 0 is the least significant and 255 is the most. + * @return The value of the bit at the specified index. + */ #define BIT256_GET(a, bit) BIT128_GET(a, bit) + +/** + * Clears all bits in a 256-bit \c retro_bits_t. + * + * @param a A 256-bit \c retro_bits_t. + */ #define BIT256_CLEAR_ALL(a) BIT128_CLEAR_ALL(a) +/** Variant of BIT256_SET() that takes a pointer to a \c retro_bits_t. */ #define BIT256_SET_PTR(a, bit) BIT256_SET(*a, bit) + +/** Variant of BIT256_CLEAR() that takes a pointer to a \c retro_bits_t. */ #define BIT256_CLEAR_PTR(a, bit) BIT256_CLEAR(*a, bit) + +/** Variant of BIT256_GET() that takes a pointer to a \c retro_bits_t. */ #define BIT256_GET_PTR(a, bit) BIT256_GET(*a, bit) + +/** Variant of BIT256_CLEAR_ALL() that takes a pointer to a \c retro_bits_t. */ #define BIT256_CLEAR_ALL_PTR(a) BIT256_CLEAR_ALL(*a) +/** + * Sets a single bit from a 512-bit \c retro_bits_512_t to 1. + * + * @param a A 512-bit \c retro_bits_512_t. + * @param bit Index of the bit to set, + * where 0 is the least significant and 511 is the most. + */ #define BIT512_SET(a, bit) BIT256_SET(a, bit) + +/** + * Clears a single bit from a 512-bit \c retro_bits_512_t. + * + * @param a A 512-bit \c retro_bits_512_t. + * @param bit Index of the bit to clear, + * where 0 is the least significant and 511 is the most. + */ #define BIT512_CLEAR(a, bit) BIT256_CLEAR(a, bit) + +/** + * Gets the value of a single bit from a 512-bit \c retro_bits_512_t. + * + * @param a A 512-bit \c retro_bits_512_t. + * @param bit Index of the bit to get, + * where 0 is the least significant and 511 is the most. + * @return The value of the bit at the specified index. + */ #define BIT512_GET(a, bit) BIT256_GET(a, bit) + +/** + * Clears all bits in a 512-bit \c retro_bits_512_t. + * + * @param a A 512-bit \c retro_bits_512_t. + */ #define BIT512_CLEAR_ALL(a) BIT256_CLEAR_ALL(a) +/** Variant of BIT512_SET() that takes a pointer to a \c retro_bits_512_t. */ #define BIT512_SET_PTR(a, bit) BIT512_SET(*a, bit) + +/** Variant of BIT512_CLEAR() that takes a pointer to a \c retro_bits_512_t. */ #define BIT512_CLEAR_PTR(a, bit) BIT512_CLEAR(*a, bit) + +/** Variant of BIT512_GET() that takes a pointer to a \c retro_bits_512_t. */ #define BIT512_GET_PTR(a, bit) BIT512_GET(*a, bit) + +/** Variant of BIT512_CLEAR_ALL() that takes a pointer to a \c retro_bits_512_t. */ #define BIT512_CLEAR_ALL_PTR(a) BIT512_CLEAR_ALL(*a) #define BITS_COPY16_PTR(a,bits) \ @@ -183,18 +457,23 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count) } /* Helper macros and struct to keep track of many booleans. */ -/* This struct has 256 bits. */ + +/** A 256-bit boolean array. */ typedef struct { + /** @private 256 bits. Not intended for direct use. */ uint32_t data[8]; } retro_bits_t; -/* This struct has 512 bits. */ +/** A 512-bit boolean array. */ typedef struct { + /** @private 512 bits. Not intended for direct use. */ uint32_t data[16]; } retro_bits_512_t; +/** @} */ + #ifdef _WIN32 # ifdef _WIN64 # define PRI_SIZET PRIu64 diff --git a/libretro-common/include/retro_timers.h b/libretro-common/include/retro_timers.h index 00e059e290..96041255a3 100644 --- a/libretro-common/include/retro_timers.h +++ b/libretro-common/include/retro_timers.h @@ -80,10 +80,9 @@ static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp) #endif /** - * retro_sleep: - * @msec : amount in milliseconds to sleep + * Briefly suspends the running thread. * - * Sleeps for a specified amount of milliseconds (@msec). + * @param msec The time to sleep for, in milliseconds. **/ #if defined(VITA) #define retro_sleep(msec) (sceKernelDelayThread(1000 * (msec))) diff --git a/libretro-common/include/rthreads/rthreads.h b/libretro-common/include/rthreads/rthreads.h index e4460a1742..7e30c85cd3 100644 --- a/libretro-common/include/rthreads/rthreads.h +++ b/libretro-common/include/rthreads/rthreads.h @@ -32,235 +32,274 @@ RETRO_BEGIN_DECLS +/** Platform-agnostic handle to a thread. */ typedef struct sthread sthread_t; + +/** Platform-agnostic handle to a mutex. */ typedef struct slock slock_t; + +/** Platform-agnostic handle to a condition variable. */ typedef struct scond scond_t; #ifdef HAVE_THREAD_STORAGE +/** Platform-agnostic handle to thread-local storage. */ typedef unsigned sthread_tls_t; #endif /** - * sthread_create: - * @start_routine : thread entry callback function - * @userdata : pointer to userdata that will be made - * available in thread entry callback function + * Creates a new thread and starts running it. * - * Create a new thread. - * - * Returns: pointer to new thread if successful, otherwise NULL. + * @param thread_func Function to run in the new thread. + * Called with the value given in \c userdata as an argument. + * @param userdata Pointer to anything (even \c NULL), passed directly to \c thread_func. + * Must be cleaned up by the caller or the thread. + * @return Pointer to the new thread, + * or \c NULL if there was an error. + * @warn Make sure that the thread can respond to cancellation requests, + * especially if used in a core. + * If a core-created thread isn't terminated by the time the core is unloaded, + * it may leak into the frontend and cause undefined behavior + * (especially if another session with the core is started). */ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata); /** - * sthread_create_with_priority: - * @start_routine : thread entry callback function - * @userdata : pointer to userdata that will be made - * available in thread entry callback function - * @thread_priority : thread priority hint value from [1-100] + * Creates a new thread with a specific priority hint and starts running it. * - * Create a new thread. It is possible for the caller to give a hint - * for the thread's priority from [1-100]. Any passed in @thread_priority - * values that are outside of this range will cause sthread_create() to - * create a new thread using the operating system's default thread - * priority. - * - * Returns: pointer to new thread if successful, otherwise NULL. + * @param thread_func Function to run in the new thread. + * Called with the value given in \c userdata as an argument. + * @param userdata Pointer to anything (even \c NULL), passed directly to \c thread_func. + * Must be cleaned up by the caller or the thread. + * @param thread_priority Priority hint for the new thread. + * Threads with a higher number are more likely to be scheduled first. + * Should be between 1 and 100, inclusive; + * if not, the operating system will assign a default priority. + * May be ignored. + * @return Pointer to the new thread, + * or \c NULL if there was an error. */ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userdata, int thread_priority); /** - * sthread_detach: - * @thread : pointer to thread object + * Detaches the given thread. * - * Detach a thread. When a detached thread terminates, its - * resource sare automatically released back to the system - * without the need for another thread to join with the - * terminated thread. + * When a detached thread terminates, + * its resources are automatically released back to the operating system + * without needing another thread to join with it. * - * Returns: 0 on success, otherwise it returns a non-zero error number. + * @param thread Thread to detach. + * @return 0 on success, a non-zero error code on failure. + * @warn Once a thread is detached, it cannot be joined. + * @see sthread_join */ int sthread_detach(sthread_t *thread); /** - * sthread_join: - * @thread : pointer to thread object + * Waits for the given thread to terminate. * - * Join with a terminated thread. Waits for the thread specified by - * @thread to terminate. If that thread has already terminated, then - * it will return immediately. The thread specified by @thread must - * be joinable. - * - * Returns: 0 on success, otherwise it returns a non-zero error number. + * @param thread The thread to wait for. + * Must be joinable. + * Returns immediately if it's already terminated + * or if it's \c NULL. */ void sthread_join(sthread_t *thread); /** - * sthread_isself: - * @thread : pointer to thread object + * Returns whether the given thread is the same as the calling thread. * - * Returns: true (1) if calling thread is the specified thread + * @param thread Thread to check. + * @return \c true if \c thread is the same as the calling thread, + * \c false if not or if it's \c NULL. + * @note libretro does not have a notion of a "main" thread, + * since the core may not be running on the same thread + * that called \c main (or local equivalent). + * @see sthread_get_thread_id */ bool sthread_isself(sthread_t *thread); /** - * slock_new: + * Creates a new mutex (a.k.a. lock) that can be used to synchronize shared data. * - * Create and initialize a new mutex. Must be manually - * freed. + * Must be manually freed with \c slock_free. * - * Returns: pointer to a new mutex if successful, otherwise NULL. - **/ + * @return Pointer to the new mutex, + * or \c NULL if there was an error. + */ slock_t *slock_new(void); /** - * slock_free: - * @lock : pointer to mutex object - * * Frees a mutex. - **/ + * + * Behavior is undefined if \c lock was previously freed. + * + * @param lock Pointer to the mutex to free. + * May be \c NULL, in which this function does nothing. + */ void slock_free(slock_t *lock); /** - * slock_lock: - * @lock : pointer to mutex object + * Locks a mutex, preventing other threads from claiming it until it's unlocked. * - * Locks a mutex. If a mutex is already locked by - * another thread, the calling thread shall block until - * the mutex becomes available. -**/ + * If the mutex is already locked by another thread, + * the calling thread will block until the mutex is unlocked. + * + * @param lock Pointer to the mutex to lock. + * If \c NULL, will return without further action. + * @see slock_try_lock + */ void slock_lock(slock_t *lock); /** - * slock_try_lock: - * @lock : pointer to mutex object + * Tries to lock a mutex if it's not already locked by another thread. * - * Attempts to lock a mutex. If a mutex is already locked by - * another thread, return false. If the lock is acquired, return true. -**/ + * If the mutex is already in use by another thread, + * returns immediately without waiting for it. + * + * @param lock The mutex to try to lock. + * @return \c true if the mutex was successfully locked, + * \c false if it was already locked by another thread or if \c lock is \c NULL. + * @see slock_lock + */ bool slock_try_lock(slock_t *lock); /** - * slock_unlock: - * @lock : pointer to mutex object + * Unlocks a mutex, allowing other threads to claim it. * - * Unlocks a mutex. - **/ + * @post The mutex is unlocked, + * and another thread may lock it. + * @param lock The mutex to unlock. + * If \c NULL, this function is a no-op. + */ void slock_unlock(slock_t *lock); /** - * scond_new: + * Creates and initializes a condition variable. * - * Creates and initializes a condition variable. Must - * be manually freed. + * Must be manually freed with \c scond_free. * - * Returns: pointer to new condition variable on success, - * otherwise NULL. - **/ + * @return Pointer to the new condition variable, + * or \c NULL if there was an error. + */ scond_t *scond_new(void); /** - * scond_free: - * @cond : pointer to condition variable object - * * Frees a condition variable. -**/ + * + * @param cond Pointer to the condition variable to free. + * If \c NULL, this function is a no-op. + * Behavior is undefined if \c cond was previously freed. + */ void scond_free(scond_t *cond); /** - * scond_wait: - * @cond : pointer to condition variable object - * @lock : pointer to mutex object + * Blocks until the given condition variable is signaled or broadcast. * - * Block on a condition variable (i.e. wait on a condition). - **/ + * @param cond Condition variable to wait on. + * This function blocks until another thread + * calls \c scond_signal or \c scond_broadcast with this condition variable. + * @param lock Mutex to lock while waiting. + * + * @see scond_signal + * @see scond_broadcast + * @see scond_wait_timeout + */ void scond_wait(scond_t *cond, slock_t *lock); /** - * scond_wait_timeout: - * @cond : pointer to condition variable object - * @lock : pointer to mutex object - * @timeout_us : timeout (in microseconds) + * Blocks until the given condition variable is signaled or broadcast, + * or until the specified time has passed. * - * Try to block on a condition variable (i.e. wait on a condition) until - * @timeout_us elapses. + * @param cond Condition variable to wait on. + * This function blocks until another thread + * calls \c scond_signal or \c scond_broadcast with this condition variable. + * @param lock Mutex to lock while waiting. + * @param timeout_us Time to wait for a signal, in microseconds. * - * Returns: false (0) if timeout elapses before condition variable is - * signaled or broadcast, otherwise true (1). - **/ + * @return \c false if \c timeout_us elapses + * before \c cond is signaled or broadcast, otherwise \c true. + */ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us); /** - * scond_broadcast: - * @cond : pointer to condition variable object + * Unblocks all threads waiting on the specified condition variable. * - * Broadcast a condition. Unblocks all threads currently blocked - * on the specified condition variable @cond. - **/ + * @param cond Condition variable to broadcast. + * @return 0 on success, non-zero on failure. + */ int scond_broadcast(scond_t *cond); /** - * scond_signal: - * @cond : pointer to condition variable object + * Unblocks at least one thread waiting on the specified condition variable. * - * Signal a condition. Unblocks at least one of the threads currently blocked - * on the specified condition variable @cond. - **/ + * @param cond Condition variable to signal. + */ void scond_signal(scond_t *cond); #ifdef HAVE_THREAD_STORAGE /** - * @brief Creates a thread local storage key + * Creates a thread-local storage key. * - * This function shall create thread-specific data key visible to all threads in - * the process. The same key can be used by multiple threads to store - * thread-local data. + * Thread-local storage keys have a single value associated with them + * that is unique to the thread that uses them. * - * When the key is created NULL shall be associated with it in all active - * threads. Whenever a new thread is spawned the all defined keys will be - * associated with NULL on that thread. + * New thread-local storage keys have a value of \c NULL for all threads, + * and new threads initialize all existing thread-local storage to \c NULL. * - * @param tls - * @return whether the operation suceeded or not + * @param tls[in,out] Pointer to the thread local storage key that will be initialized. + * Must be cleaned up with \c sthread_tls_delete. + * Behavior is undefined if \c NULL. + * @return \c true if the operation succeeded, \c false otherwise. + * @see sthread_tls_delete */ bool sthread_tls_create(sthread_tls_t *tls); /** - * @brief Deletes a thread local storage - * @param tls - * @return whether the operation suceeded or not + * Deletes a thread local storage key. + * + * The value must be cleaned up separately \em before calling this function, + * if necessary. + * + * @param tls The thread local storage key to delete. + * Behavior is undefined if \c NULL. + * @return \c true if the operation succeeded, \c false otherwise. */ bool sthread_tls_delete(sthread_tls_t *tls); /** - * @brief Retrieves thread specific data associated with a key + * Gets the calling thread's local data for the given key. * - * There is no way to tell whether this function failed. - * - * @param tls - * @return + * @param tls The thread-local storage key to get the data for. + * @return The calling thread's local data associated with \c tls, + * which should previously have been set with \c sthread_tls_set. + * Will be \c NULL if this thread has not set a value or if there was an error. */ void *sthread_tls_get(sthread_tls_t *tls); /** - * @brief Binds thread specific data to a key - * @param tls - * @return Whether the operation suceeded or not + * Sets the calling thread's local data for the given key. + * + * @param tls The thread-local storage key to set the data for. + * @param data Pointer to the data that will be associated with \c tls. + * May be \c NULL. + * @return \c true if \c data was successfully assigned to \c tls, + * \c false if there was an error. */ bool sthread_tls_set(sthread_tls_t *tls, const void *data); #endif -/* - * @brief Get thread ID of specified thread - * @param thread - * @return The ID of the specified thread +/** + * Gets a thread's unique ID. + * + * @param thread The thread to get the ID of. + * @return The provided thread's ID, + * or 0 if it's \c NULL. */ uintptr_t sthread_get_thread_id(sthread_t *thread); -/* - * @brief Get thread ID of the current thread - * @param - * @return The ID of the current thread +/** + * Get the calling thread's unique ID. + * @return The calling thread's ID. + * @see sthread_get_thread_id */ uintptr_t sthread_get_current_thread_id(void); diff --git a/libretro-common/include/streams/file_stream.h b/libretro-common/include/streams/file_stream.h index 079221e1e0..c76968acc4 100644 --- a/libretro-common/include/streams/file_stream.h +++ b/libretro-common/include/streams/file_stream.h @@ -38,105 +38,377 @@ #include #include +/** @defgroup file_stream File Streams + * + * All functions in this header will use the VFS interface set in \ref filestream_vfs_init if possible, + * or else they will fall back to built-in equivalents. + * + * @note These functions are modeled after those in the C standard library + * (and may even use them internally), + * but identical behavior is not guaranteed. + * + * @{ + */ + +/** + * The minimum version of the VFS interface required by the \c filestream functions. + */ #define FILESTREAM_REQUIRED_VFS_VERSION 2 RETRO_BEGIN_DECLS +/** + * Opaque handle to a file stream. + * @warning This is not interchangeable with \c FILE* or \c retro_vfs_file_handle. + */ typedef struct RFILE RFILE; #define FILESTREAM_REQUIRED_VFS_VERSION 2 +/** + * Initializes the \c filestream functions to use the VFS interface provided by the frontend. + * Optional; if not called, all \c filestream functions + * will use libretro-common's built-in implementations. + * + * @param vfs_info The VFS interface returned by the frontend. + * If \c vfs_info::iface (but \em not \c vfs_info itself) is \c NULL, + * then libretro-common's built-in VFS implementation will be used. + */ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info); +/** + * Returns the size of the given file, in bytes. + * + * @param stream The open file to query. + * @return The size of \c stream in bytes, + * or -1 if there was an error. + * @see retro_vfs_size_t + */ int64_t filestream_get_size(RFILE *stream); +/** + * Sets the size of the given file, + * truncating or extending it as necessary. + * + * @param stream The file to resize. + * @param length The new size of \c stream, in bytes. + * @return 0 if the resize was successful, + * or -1 if there was an error. + * @see retro_vfs_truncate_t + */ int64_t filestream_truncate(RFILE *stream, int64_t length); /** - * filestream_open: - * @path : path to file - * @mode : file mode to use when opening (read/write) - * @bufsize : optional buffer size (-1 or 0 to use default) + * Opens a file for reading or writing. * - * Opens a file for reading or writing, depending on the requested mode. - * @return A pointer to an RFILE if opened successfully, otherwise NULL. - **/ + * @param path Path to the file to open. + * Should be in the format described in \ref GET_VFS_INTERFACE. + * @param mode The mode to open the file in. + * Should be one or more of the flags in \refitem RETRO_VFS_FILE_ACCESS OR'd together, + * and \c RETRO_VFS_FILE_ACCESS_READ or \c RETRO_VFS_FILE_ACCESS_WRITE + * (or both) must be included. + * @param hints Optional hints to pass to the frontend. + * + * @return The opened file, or \c NULL if there was an error. + * Must be cleaned up with \c filestream_close when no longer needed. + * @see retro_vfs_open_t + */ RFILE* filestream_open(const char *path, unsigned mode, unsigned hints); +/** + * Sets the current position of the file stream. + * Use this to read specific sections of a file. + * + * @param stream The file to set the stream position of. + * @param offset The new stream position, in bytes. + * @param seek_position The position to seek from. + * Should be one of the values in \refitem RETRO_VFS_SEEK_POSITION. + * @return The new stream position in bytes relative to the beginning, + * or -1 if there was an error. + * @see RETRO_VFS_SEEK_POSITION + * @see retro_vfs_seek_t + */ int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position); +/** + * Reads data from the given file into a buffer. + * If the read is successful, + * the file's stream position will advance by the number of bytes read. + * + * @param stream The file to read from. + * @param data The buffer in which to store the read data. + * @param len The size of \c data, in bytes. + * @return The number of bytes read, + * or -1 if there was an error. + * May be less than \c len, but never more. + * @see retro_vfs_read_t + */ int64_t filestream_read(RFILE *stream, void *data, int64_t len); +/** + * Writes data from a buffer to the given file. + * If the write is successful, + * the file's stream position will advance by the number of bytes written. + * + * @param stream The file to write to. + * @param data The buffer containing the data to write. + * @param len The size of \c data, in bytes. + * @return The number of bytes written, + * or -1 if there was an error. + * May be less than \c len, but never more. + * @see retro_vfs_write_t + */ int64_t filestream_write(RFILE *stream, const void *data, int64_t len); +/** + * Returns the current position of the given file in bytes. + * + * @param stream The file to return the stream position for. + * @return The current stream position in bytes relative to the beginning, + * or -1 if there was an error. + * @see retro_vfs_tell_t + */ int64_t filestream_tell(RFILE *stream); +/** + * Rewinds the given file to the beginning. + * Equivalent to filestream_seek(stream, 0, RETRO_VFS_SEEK_POSITION_START). + + * @param stream The file to rewind. + * May be \c NULL, in which case this function does nothing. + */ void filestream_rewind(RFILE *stream); +/** + * Closes the given file. + * + * @param stream The file to close. + * This should have been created with \c filestream_open. + * Behavior is undefined if \c NULL. + * @return 0 if the file was closed successfully, + * or -1 if there was an error. + * @post \c stream is no longer valid and should not be used, + * even if this function fails. + * @see retro_vfs_close_t + */ int filestream_close(RFILE *stream); /** - * filestream_read_file: - * @path : path to file. - * @buf : buffer to allocate and read the contents of the - * file into. Needs to be freed manually. - * @len : optional output integer containing bytes read. + * Opens a file, reads its contents into a newly-allocated buffer, + * then closes it. * - * Read the contents of a file into @buf. - * - * @return Non-zero on success. + * @param path[in] Path to the file to read. + * Should be in the format described in \ref GET_VFS_INTERFACE. + * @param buf[out] A pointer to the address of the newly-allocated buffer. + * The buffer will contain the entirety of the file at \c path. + * Will be allocated with \c malloc and must be freed with \c free. + * @param len[out] Pointer to the size of the buffer in bytes. + * May be \c NULL, in which case the length is not written. + * Value is unspecified if this function fails. + * @return 1 if the file was read successfully, + * 0 if there was an error. + * @see filestream_write_file */ int64_t filestream_read_file(const char *path, void **buf, int64_t *len); +/** + * Reads a line of text from the given file, + * up to a given length. + * + * Will read to the next newline or until the buffer is full, + * whichever comes first. + * + * @param stream The file to read from. + * @param s The buffer to write the retrieved line to. + * Will contain at most \c len - 1 characters + * plus a null terminator. + * The newline character (if any) will not be included. + * The line delimiter must be Unix-style (\c '\n'). + * Carriage returns (\c '\r') will not be treated specially. + * @param len The length of the buffer \c s, in bytes. + * @return \s if successful, \c NULL if there was an error. + */ char* filestream_gets(RFILE *stream, char *s, size_t len); +/** + * Reads a single character from the given file. + * + * @param stream The file to read from. + * @return The character read, or -1 upon reaching the end of the file. + */ int filestream_getc(RFILE *stream); +/** + * Reads formatted text from the given file, + * with arguments provided as a standard \c va_list. + * + * @param stream The file to read from. + * @param format The string to write, possibly including scanf-compatible format specifiers. + * @param args Argument list with zero or more elements + * whose values will be updated according to the semantics of \c format. + * @return The number of arguments in \c args that were successfully assigned, + * or -1 if there was an error. + * @see https://en.cppreference.com/w/c/io/fscanf + * @see https://en.cppreference.com/w/c/variadic + */ int filestream_vscanf(RFILE *stream, const char* format, va_list *args); +/** + * Reads formatted text from the given file. + * + * @param stream The file to read from. + * @param format The string to write, possibly including scanf-compatible format specifiers. + * @param ... Zero or more arguments that will be updated according to the semantics of \c format. + * @return The number of arguments in \c ... that were successfully assigned, + * or -1 if there was an error. + * @see https://en.cppreference.com/w/c/io/fscanf + */ int filestream_scanf(RFILE *stream, const char* format, ...); +/** + * Determines if there's any more data left to read from this file. + * + * @param stream The file to check the position of. + * @return -1 if this stream has reached the end of the file, + * 0 if not. + */ int filestream_eof(RFILE *stream); /** - * filestream_write_file: - * @path : path to file. - * @data : contents to write to the file. - * @size : size of the contents. + * Writes the entirety of a given buffer to a file at a given path. + * Any file that already exists will be overwritten. * - * Writes data to a file. - * - * @return true on success, otherwise false. - **/ + * @param path Path to the file that will be written to. + * @param data The buffer to write to \c path. + * @param size The size of \c data, in bytes. + * @return \c true if the file was written successfully, + * \c false if there was an error. + */ bool filestream_write_file(const char *path, const void *data, int64_t size); +/** + * Writes a single character to the given file. + * + * @param stream The file to write to. + * @param c The character to write. + * @return The character written, + * or -1 if there was an error. + * Will return -1 if \c stream is \c NULL. + */ int filestream_putc(RFILE *stream, int c); +/** + * Writes formatted text to the given file, + * with arguments provided as a standard \c va_list. + * + * @param stream The file to write to. + * @param format The string to write, possibly including printf-compatible format specifiers. + * @param args A list of arguments to be formatted and inserted in the resulting string. + * @return The number of characters written, + * or -1 if there was an error. + * @see https://en.cppreference.com/w/c/io/vfprintf + * @see https://en.cppreference.com/w/c/variadic + */ int filestream_vprintf(RFILE *stream, const char* format, va_list args); +/** + * Writes formatted text to the given file. + * + * @param stream The file to write to. + * @param format The string to write, possibly including printf-compatible format specifiers. + * @param ... Zero or more arguments to be formatted and inserted into the resulting string. + * @return The number of characters written, + * or -1 if there was an error. + * @see https://en.cppreference.com/w/c/io/printf + */ int filestream_printf(RFILE *stream, const char* format, ...); +/** + * Checks if there was an error in using the given file stream. + * + * @param stream The file stream to check for errors. + * @return \c true if there was an error in using this stream, + * \c false if not or if \c stream is \c NULL. + */ int filestream_error(RFILE *stream); +/** + * Flushes pending writes to the operating system's file layer. + * There is no guarantee that pending writes will be written to disk immediately. + * + * @param stream The file to flush. + * @return 0 if the flush was successful, + * or -1 if there was an error. + * @see retro_vfs_flush_t + */ int filestream_flush(RFILE *stream); +/** + * Deletes the file at the given path. + * If the file is open by any process, + * the behavior is platform-specific. + * + * @note This function might or might not delete directories recursively, + * depending on the platform and the underlying VFS implementation. + * + * @param path The file to delete. + * @return 0 if the file was deleted successfully, + * or -1 if there was an error. + * @see retro_vfs_remove_t + */ int filestream_delete(const char *path); +/** + * Moves a file to a new location, with a new name. + * + * @param old_path Path to the file to rename. + * @param new_path The target name and location of the file. + * @return 0 if the file was renamed successfully, + * or -1 if there was an error. + * @see retro_vfs_rename_t + */ int filestream_rename(const char *old_path, const char *new_path); +/** + * Get the path that was used to open a file. + * + * @param stream The file to get the path of. + * @return The path that was used to open \c stream, + * or \c NULL if there was an error. + * The string is owned by \c stream and must not be modified or freed by the caller. + */ const char* filestream_get_path(RFILE *stream); +/** + * Determines if a file exists at the given path. + * + * @param path The path to check for existence. + * @return \c true if a file exists at \c path, + * \c false if not or if \c path is \c NULL or empty. + */ bool filestream_exists(const char *path); /** - * filestream_getline: + * Reads a line from the given file into a newly-allocated buffer. * - * Returned pointer must be freed by the caller. - **/ + * @param stream The file to read from. + * @return Pointer to the line read from \c stream, + * or \c NULL if there was an error. + * Must be freed with \c free when no longer needed. + */ char* filestream_getline(RFILE *stream); +/** + * Returns the open file handle + * that was originally returned by the VFS interface. + * + * @param stream File handle returned by \c filestream_open. + * @return The file handle returned by the underlying VFS implementation. + */ libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream); RETRO_END_DECLS +/** @} */ + #endif diff --git a/libretro-common/include/streams/file_stream_transforms.h b/libretro-common/include/streams/file_stream_transforms.h index 327e2184cb..60e1388273 100644 --- a/libretro-common/include/streams/file_stream_transforms.h +++ b/libretro-common/include/streams/file_stream_transforms.h @@ -28,10 +28,23 @@ #include #include +/** + * @file file_stream_transforms.h + * + * Contains macros that redirect standard C I/O functions + * to libretro's own file stream API. + * Useful when porting an existing emulator to a core. + * To use these functions without overriding the standard I/O functions, + * define \c SKIP_STDIO_REDEFINES before including this header. + * + * @see https://man7.org/linux/man-pages/man3/stdio.3.html + */ + RETRO_BEGIN_DECLS #ifndef SKIP_STDIO_REDEFINES +/** @see https://en.cppreference.com/w/c/io/FILE */ #define FILE RFILE #undef fopen @@ -66,34 +79,48 @@ RETRO_BEGIN_DECLS #endif +/** @see https://en.cppreference.com/w/c/io/fopen */ RFILE* rfopen(const char *path, const char *mode); +/** @see https://en.cppreference.com/w/c/io/fclose */ int rfclose(RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/ftell */ int64_t rftell(RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/fseek */ int64_t rfseek(RFILE* stream, int64_t offset, int origin); +/** @see https://en.cppreference.com/w/c/io/fread */ int64_t rfread(void* buffer, size_t elem_size, size_t elem_count, RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/fgets */ char *rfgets(char *buffer, int maxCount, RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/fgetc */ int rfgetc(RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/fwrite */ int64_t rfwrite(void const* buffer, size_t elem_size, size_t elem_count, RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/fputc */ int rfputc(int character, RFILE * stream); +/** @see https://en.cppreference.com/w/c/io/fflush */ int64_t rfflush(RFILE * stream); +/** @see https://en.cppreference.com/w/c/io/fprintf */ int rfprintf(RFILE * stream, const char * format, ...); +/** @see https://en.cppreference.com/w/c/io/ferror */ int rferror(RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/feof */ int rfeof(RFILE* stream); +/** @see https://en.cppreference.com/w/c/io/fscanf */ int rfscanf(RFILE * stream, const char * format, ...); RETRO_END_DECLS diff --git a/libretro-common/include/streams/network_stream.h b/libretro-common/include/streams/network_stream.h index 36aa40ba41..e499db716d 100644 --- a/libretro-common/include/streams/network_stream.h +++ b/libretro-common/include/streams/network_stream.h @@ -34,230 +34,359 @@ RETRO_BEGIN_DECLS enum { + /** + * Indicates that \c netstream_seek should seek + * relative to the beginning of the stream. + */ NETSTREAM_SEEK_SET = 0, + + /** + * Indicates that \c netstream_seek should seek + * relative to its current position. + */ NETSTREAM_SEEK_CUR, + + /** + * Indicates that \c netstream_seek should seek + * relative to the end of the stream. + */ NETSTREAM_SEEK_END }; +/** + * A stream that ensures data is read/written in network byte order (big endian). + * + * @note Despite what the name may suggests, + * this object does \em not actually perform any network operations. + * It is intended to be used as input/output for functions that do. + */ typedef struct netstream { + /** The buffer used by the stream for reading or writing. */ void *buf; + + /** The size of \c buf in bytes. */ size_t size; + + /** The number of bytes that have been written to \c buf. */ size_t used; + + /** + * The current position of the stream, in bytes. + * @see netstream_seek + */ size_t pos; } netstream_t; /** - * netstream_open: + * Opens a network-order stream. * - * @stream : Pointer to a network stream object. - * @buf : Pre-allocated buffer. Pass NULL to dynamically allocate a buffer. - * @size : Buffer size. Pass 0 for no pre-allocated/initial buffer. - * @used : Buffer bytes in use. Ignored for non pre-allocated buffers. - * - * Opens a network stream. - * - * Returns: true on success, false otherwise. + * @param stream Pointer to the network-order stream to initialize. + * Behavior is undefined if \c NULL. + * @param buf Pre-allocated buffer. + * May be \c NULL, in which case a new buffer will be created with \c malloc. + * @param size Buffer size in bytes. + * If \c buf is \c NULL, then this will be the size of the newly-allocated buffer. + * If not, then this is the size of the existing buffer. + * If zero, then a buffer will not be allocated. + * @param used The number of bytes in use. + * Ignored for non pre-allocated buffers. + * @return \c true if the stream was opened. + * For new buffers, \c false if allocation failed. + * For existing buffers, \c false if \c size is zero + * or less than \c used. + * @see netstream_close */ bool netstream_open(netstream_t *stream, void *buf, size_t size, size_t used); /** - * netstream_close: - * - * @stream : Pointer to a network stream object. - * @dealloc : Whether to deallocate/free the buffer or not. - * - * Closes a network stream. + * Closes a network-order stream. * + * @param stream Pointer to the network-order stream to close. + * The stream itself is not deallocated, + * but its fields will be reset. + * Behavior is undefined if \c NULL. + * @param dealloc Whether to release the underlying buffer with \c free. + * Set to \c true if the creating \c netstream_open call allocated a buffer, + * or else its memory will be leaked. + * @note \c stream itself is not deallocated. + * This function can be used on static or local variables. + * @see netstream_open */ void netstream_close(netstream_t *stream, bool dealloc); /** - * netstream_reset: + * Resets the stream to the beginning and discards any used bytes. * - * @stream : Pointer to a network stream object. - * - * Resets a network stream to its initial position, - * discarding any used bytes in the process. + * @param stream The network-order stream to reset. + * Behavior is undefined if \c NULL. * + * @note This does not deallocate the underlying buffer, + * nor does it wipe its memory. */ void netstream_reset(netstream_t *stream); /** - * netstream_truncate: + * Resizes the "used" portion of the stream. * - * @stream : Pointer to a network stream object. - * @used : Amount of bytes used. - * - * Truncates the network stream. - * Truncation can either extend or reduce the amount of bytes used. - * - * Returns: true on success, false otherwise. + * @param stream The network-order stream to resize. + * Behavior is undefined if \c NULL. + * @param used The number of bytes in the stream that are considered written. + * @return \c true if the stream's "used" region was resized, + * \c false if it would've been extended past the buffer's capacity. + * @note This function does not reallocate or clear the underlying buffer. + * It only sets the boundaries of the "used" portion of the stream. */ bool netstream_truncate(netstream_t *stream, size_t used); /** - * netstream_data: - * - * @stream : Pointer to a network stream object. - * @data : Pointer to an object to store a reference of the stream's data. - * @len : Pointer to an object to store the amount of bytes in use. - * - * Gets the network stream's data. + * Retrieves the network-order stream's data. * + * @param stream Pointer to the network-order stream. + * Behavior is undefined if \c NULL. + * @param data[out] Pointer to a variable to store the stream's data. + * The data itself is not copied, + * so the pointer will be invalidated + * if the stream is closed or reallocated. + * @param len[out] Set to the length of the stream's data in bytes. */ void netstream_data(netstream_t *stream, void **data, size_t *len); /** - * netstream_eof: + * Checks whether the network-order stream has any more data to read, + * or any more room to write data. * - * @stream : Pointer to a network stream object. - * - * Checks whether the network stream is at EOF or not. - * - * Returns: true if the stream is at EOF, false otherwise. + * @param stream The network-order stream to check. + * @return \c true if the stream is at EOF, \c false otherwise. */ bool netstream_eof(netstream_t *stream); /** - * netstream_tell: + * Gets the network-order stream's current position. * - * @stream : Pointer to a network stream object. - * - * Gets the network stream's current position. - * - * Returns: current value of the position indicator. + * @param stream Pointer to a network-order stream. + * @return The stream's position indicator. */ size_t netstream_tell(netstream_t *stream); /** - * netstream_seek: + * Sets the network-order stream's current position. * - * @stream : Pointer to a network stream object. - * @offset : Position's offset. - * @origin : Position used as reference for the offset. - * - * Sets the network stream's current position. - * - * Returns: true on success, false otherwise. + * @param stream Pointer to a network-order stream. + * @param offset The new position of the stream, in bytes. + * @param origin The position used as reference for the offset. + * Must be one of \c NETSTREAM_SEEK_SET, \c NETSTREAM_SEEK_CUR or \c NETSTREAM_SEEK_END. + * @return \c true on success, \c false on failure. */ bool netstream_seek(netstream_t *stream, long offset, int origin); /** - * netstream_read: + * Reads data from the network-order stream. + * Does not byte-swap any data; + * this is useful for reading strings or unspecified binary data. * - * @stream : Pointer to a network stream object. - * @data : Pointer to a storage for data read from the network stream. - * @len : Amount of bytes to read. Pass 0 to read all remaining bytes. - * - * Reads raw data from the network stream. - * - * Returns: true on success, false otherwise. + * @param stream The network-order stream to read from. + * @param data The buffer that will receive data from the stream. + * @param len The number of bytes to read. + * If 0, will read all remaining bytes. + * @return \c true on success, \c false on failure. */ bool netstream_read(netstream_t *stream, void *data, size_t len); /** - * netstream_read_(type): + * Reads a single byte from the network-order stream. * - * @stream : Pointer to a network stream object. - * @data : Pointer to a storage for data read from the network stream. - * - * Reads data from the network stream. - * Network byte order is always big endian. - * - * Returns: true on success, false otherwise. + * @param stream[in] The network-order stream to read from. + * @param data[out] Pointer to the byte that will receive the read value. + * @return \c true on success, \c false if there was an error. */ bool netstream_read_byte(netstream_t *stream, uint8_t *data); + +/** + * Reads an unsigned 16-bit integer from the network-order stream, + * byte-swapping it from big endian to host-native byte order if necessary. + * + * @param stream[in] The network-order stream to read from. + * @param data[out] Pointer to the value that will receive the read value. + * @return \c true on success, \c false if there was an error. + */ bool netstream_read_word(netstream_t *stream, uint16_t *data); + +/** + * Reads an unsigned 32-bit integer from the network-order stream, + * byte-swapping it from big endian to host-native byte order if necessary. + * + * @param stream[in] The network-order stream to read from. + * @param data[out] Pointer to the value that will receive the read value. + * @return \c true on success, \c false if there was an error. + */ bool netstream_read_dword(netstream_t *stream, uint32_t *data); + +/** + * Reads an unsigned 64-bit integer from the network-order stream, + * byte-swapping it from big endian to host-native byte order if necessary. + * + * @param stream[in] The network-order stream to read from. + * @param data[out] Pointer to the value that will receive the read value. + * @return \c true on success, \c false if there was an error. + */ bool netstream_read_qword(netstream_t *stream, uint64_t *data); #ifdef __STDC_IEC_559__ +/** + * Reads a 32-bit floating-point number from the network-order stream, + * byte-swapping it from big endian to host-native byte order if necessary. + * + * @param stream[in] The network-order stream to read from. + * @param data[out] Pointer to the value that will receive the read value. + * @return \c true on success, \c false if there was an error. + */ bool netstream_read_float(netstream_t *stream, float *data); + +/** + * Reads a 64-bit floating-point number from the network-order stream, + * byte-swapping it from big endian to host-native byte order if necessary. + * + * @param stream[in] The network-order stream to read from. + * @param data[out] Pointer to the value that will receive the read value. + * @return \c true on success, \c false if there was an error. + */ bool netstream_read_double(netstream_t *stream, double *data); #endif /** - * netstream_read_string: + * Reads a null-terminated string from the network-order stream, + * up to the given length. * - * @stream : Pointer to a network stream object. - * @s : Pointer to a string buffer. - * @len : Size of the string buffer. - * - * Reads a string from the network stream. - * - * Returns: Length of the original string on success or - * a negative value on error. + * @param stream Pointer to a network stream object. + * @param s[out] The buffer that will receive the string. + * Will be \c NULL-terminated. + * @param len The length of \c s, in bytes. + * @return The length of the read string in bytes, + * or -1 if there was an error. */ int netstream_read_string(netstream_t *stream, char *s, size_t len); /** - * netstream_read_fixed_string: + * Reads a string of fixed length from a network-order stream. + * Will fail if there isn't enough data to read. * - * @stream : Pointer to a network stream object. - * @s : Pointer to a string buffer. - * @len : Size of the string buffer. + * @param stream Pointer to a network stream object. + * @param s The buffer that will receive the string. + * Will be \c NULL-terminated. + * @param len The length of \c s in bytes, + * including the \c NULL terminator. * - * Reads a fixed-length string from the network stream. - * - * Returns: true on success, false otherwise. + * @return \c true if a string of the exact length was read, + * \c false if there was an error. */ bool netstream_read_fixed_string(netstream_t *stream, char *s, size_t len); /** - * netstream_write: + * Writes arbitrary data to a network-order stream. + * Does not byte-swap any data; + * this is useful for writing strings or unspecified binary data. * - * @stream : Pointer to a network stream object. - * @data : Data to write into the network stream. - * @len : Amount of bytes to write. - * - * Writes raw data into the network stream. - * - * Returns: true on success, false otherwise. + * @param stream Pointer to a network stream object. + * @param data The data to write into the network stream. + * @param len The length of \c data, in bytes. + * @return \c true on success, + * \c false if there was an error. */ bool netstream_write(netstream_t *stream, const void *data, size_t len); /** - * netstream_write_(type): + * Writes a single byte to a network-order stream. * - * @stream : Pointer to a network stream object. - * @data : Data to write into the network stream. - * - * Writes data into the network stream. - * Network byte order is always big endian. - * - * Returns: true on success, false otherwise. + * @param stream Pointer to a network stream object. + * @param data The byte to write to the stream. + * @return \c true on success, + * \c false if there was an error. */ bool netstream_write_byte(netstream_t *stream, uint8_t data); + +/** + * Writes an unsigned 16-bit integer to a network-order stream, + * byte-swapping it from host-native byte order to big-endian if necessary. + * + * @param stream Pointer to a network stream object. + * @param data The value to write to the stream. + * @return \c true on success, + * \c false if there was an error. + */ bool netstream_write_word(netstream_t *stream, uint16_t data); + +/** + * Writes an unsigned 32-bit integer to a network-order stream, + * byte-swapping it from host-native byte order to big-endian if necessary. + * + * @param stream Pointer to a network stream object. + * @param data The value to write to the stream. + * @return \c true on success, + * \c false if there was an error. + */ bool netstream_write_dword(netstream_t *stream, uint32_t data); + +/** + * Writes an unsigned 64-bit integer to a network-order stream, + * byte-swapping it from host-native byte order to big-endian if necessary. + * + * @param stream Pointer to a network stream object. + * @param data The value to write to the stream. + * @return \c true on success, + * \c false if there was an error. + */ bool netstream_write_qword(netstream_t *stream, uint64_t data); #ifdef __STDC_IEC_559__ + +/** + * Writes a 32-bit floating-point number to a network-order stream, + * byte-swapping it from host-native byte order to big-endian if necessary. + * + * @param stream Pointer to a network stream object. + * @param data The value to write to the stream. + * @return \c true on success, + * \c false if there was an error. + */ bool netstream_write_float(netstream_t *stream, float data); + +/** + * Writes a 64-bit floating-point number to a network-order stream, + * byte-swapping it from host-native byte order to big-endian if necessary. + * + * @param stream Pointer to a network stream object. + * @param data The value to write to the stream. + * @return \c true on success, + * \c false if there was an error. + */ bool netstream_write_double(netstream_t *stream, double data); #endif /** - * netstream_write_string: + * Writes a null-terminated string to a network-order stream. + * Does not byte-swap any data. * - * @stream : Pointer to a network stream object. - * @s : Pointer to a string. - * - * Writes a null-terminated string into the network stream. - * - * Returns: true on success, false otherwise. + * @param stream Pointer to a network stream object. + * @param s A \c NULL-terminated string. + * @return \c true on success, + * \c false if there was an error. */ bool netstream_write_string(netstream_t *stream, const char *s); /** - * netstream_write_fixed_string: + * Writes a string of fixed length to a network-order stream, + * \c NULL-terminating it if necessary. * - * @stream : Pointer to a network stream object. - * @s : Pointer to a string. - * @len : Size of the string. - * - * Writes a null-terminated fixed-length string into the network stream. - * - * Returns: true on success, false otherwise. + * @param stream Pointer to a network stream object. + * @param s Pointer to a string. + * Does not need to be \c NULL-terminated, + * but \c NULL values will not stop processing. + * Will be \c NULL + * @param len Length of \c s in bytes, + * including the \c NULL terminator. + * Exactly this many bytes will be written to the stream; + * the last character will be set to \c NULL. + * @return \c true on success, + * \c false if there was an error. */ bool netstream_write_fixed_string(netstream_t *stream, const char *s, size_t len); diff --git a/libretro-common/include/streams/stdin_stream.h b/libretro-common/include/streams/stdin_stream.h index 4dd35460e7..1b66d0c455 100644 --- a/libretro-common/include/streams/stdin_stream.h +++ b/libretro-common/include/streams/stdin_stream.h @@ -32,6 +32,17 @@ RETRO_BEGIN_DECLS +/** + * Reads data from \c stdin if supported by the current platform. + * @param buf[out] The buffer to read data into. + * @param size The length of \c buf in bytes. + * @return The number of bytes that were read, + * or 0 if there was an error + * (including a lack of platform support). + * @note \c stdin is commonly used for text, + * but this function can read binary data as well. + * @see https://man7.org/linux/man-pages/man3/stdout.3.html + */ size_t read_stdin(char *buf, size_t size); RETRO_END_DECLS diff --git a/libretro-common/include/time/rtime.h b/libretro-common/include/time/rtime.h index 7629c1eab3..8012b881c3 100644 --- a/libretro-common/include/time/rtime.h +++ b/libretro-common/include/time/rtime.h @@ -34,13 +34,28 @@ RETRO_BEGIN_DECLS /* TODO/FIXME: Move all generic time handling functions * to this file */ -/* Must be called before using rtime_localtime() */ +/** + * Must be called before using \c rtime_localtime(). + * May be called multiple times without ill effects, + * but must only be called from the main thread. + */ void rtime_init(void); -/* Must be called upon program termination */ +/** + * Must be called upon program or core termination. + * May be called multiple times without ill effects, + * but must only be called from the main thread. + */ void rtime_deinit(void); -/* Thread-safe wrapper for localtime() */ +/** + * Thread-safe wrapper around standard \c localtime(), + * which by itself is not guaranteed to be thread-safe. + * @param timep Pointer to a time_t object to convert. + * @param result Pointer to a tm object to store the result in. + * @return \c result. + * @see https://en.cppreference.com/w/c/chrono/localtime + */ struct tm *rtime_localtime(const time_t *timep, struct tm *result); RETRO_END_DECLS diff --git a/libretro-common/rthreads/rthreads.c b/libretro-common/rthreads/rthreads.c index c0b69f9195..ff11978668 100644 --- a/libretro-common/rthreads/rthreads.c +++ b/libretro-common/rthreads/rthreads.c @@ -150,16 +150,6 @@ static void *thread_wrap(void *data_) return 0; } -/** - * sthread_create: - * @start_routine : thread entry callback function - * @userdata : pointer to userdata that will be made - * available in thread entry callback function - * - * Create a new thread. - * - * Returns: pointer to new thread if successful, otherwise NULL. - */ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) { return sthread_create_with_priority(thread_func, userdata, 0); @@ -170,21 +160,6 @@ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) #define HAVE_THREAD_ATTR #endif -/** - * sthread_create_with_priority: - * @start_routine : thread entry callback function - * @userdata : pointer to userdata that will be made - * available in thread entry callback function - * @thread_priority : thread priority hint value from [1-100] - * - * Create a new thread. It is possible for the caller to give a hint - * for the thread's priority from [1-100]. Any passed in @thread_priority - * values that are outside of this range will cause sthread_create() to - * create a new thread using the operating system's default thread - * priority. - * - * Returns: pointer to new thread if successful, otherwise NULL. - */ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userdata, int thread_priority) { #ifdef HAVE_THREAD_ATTR @@ -231,7 +206,7 @@ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userda pthread_attr_setstacksize(&thread_attr , 0x10000 ); thread_attr_needed = true; #elif defined(__APPLE__) - /* Default stack size on Apple is 512Kb; + /* Default stack size on Apple is 512Kb; * for PS2 disc scanning and other reasons, we'd like 2MB. */ pthread_attr_setstacksize(&thread_attr , 0x200000 ); thread_attr_needed = true; @@ -256,17 +231,6 @@ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userda return NULL; } -/** - * sthread_detach: - * @thread : pointer to thread object - * - * Detach a thread. When a detached thread terminates, its - * resources are automatically released back to the system - * without the need for another thread to join with the - * terminated thread. - * - * Returns: 0 on success, otherwise it returns a non-zero error number. - */ int sthread_detach(sthread_t *thread) { #ifdef USE_WIN32_THREADS @@ -280,17 +244,6 @@ int sthread_detach(sthread_t *thread) #endif } -/** - * sthread_join: - * @thread : pointer to thread object - * - * Join with a terminated thread. Waits for the thread specified by - * @thread to terminate. If that thread has already terminated, then - * it will return immediately. The thread specified by @thread must - * be joinable. - * - * Returns: 0 on success, otherwise it returns a non-zero error number. - */ void sthread_join(sthread_t *thread) { if (!thread) @@ -305,12 +258,6 @@ void sthread_join(sthread_t *thread) } #if !defined(GEKKO) -/** - * sthread_isself: - * @thread : pointer to thread object - * - * Returns: true (1) if calling thread is the specified thread - */ bool sthread_isself(sthread_t *thread) { #ifdef USE_WIN32_THREADS @@ -321,14 +268,6 @@ bool sthread_isself(sthread_t *thread) } #endif -/** - * slock_new: - * - * Create and initialize a new mutex. Must be manually - * freed. - * - * Returns: pointer to a new mutex if successful, otherwise NULL. - **/ slock_t *slock_new(void) { slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); @@ -346,12 +285,6 @@ slock_t *slock_new(void) return lock; } -/** - * slock_free: - * @lock : pointer to mutex object - * - * Frees a mutex. - **/ void slock_free(slock_t *lock) { if (!lock) @@ -365,14 +298,6 @@ void slock_free(slock_t *lock) free(lock); } -/** - * slock_lock: - * @lock : pointer to mutex object - * - * Locks a mutex. If a mutex is already locked by - * another thread, the calling thread shall block until - * the mutex becomes available. -**/ void slock_lock(slock_t *lock) { if (!lock) @@ -384,13 +309,6 @@ void slock_lock(slock_t *lock) #endif } -/** - * slock_try_lock: - * @lock : pointer to mutex object - * - * Attempts to lock a mutex. If a mutex is already locked by - * another thread, return false. If the lock is acquired, return true. -**/ bool slock_try_lock(slock_t *lock) { #ifdef USE_WIN32_THREADS @@ -400,12 +318,6 @@ bool slock_try_lock(slock_t *lock) #endif } -/** - * slock_unlock: - * @lock : pointer to mutex object - * - * Unlocks a mutex. - **/ void slock_unlock(slock_t *lock) { if (!lock) @@ -417,15 +329,6 @@ void slock_unlock(slock_t *lock) #endif } -/** - * scond_new: - * - * Creates and initializes a condition variable. Must - * be manually freed. - * - * Returns: pointer to new condition variable on success, - * otherwise NULL. - **/ scond_t *scond_new(void) { scond_t *cond = (scond_t*)calloc(1, sizeof(*cond)); @@ -480,12 +383,6 @@ error: return NULL; } -/** - * scond_free: - * @cond : pointer to condition variable object - * - * Frees a condition variable. -**/ void scond_free(scond_t *cond) { if (!cond) @@ -707,13 +604,6 @@ static bool _scond_wait_win32(scond_t *cond, slock_t *lock, DWORD dwMilliseconds } #endif -/** - * scond_wait: - * @cond : pointer to condition variable object - * @lock : pointer to mutex object - * - * Block on a condition variable (i.e. wait on a condition). - **/ void scond_wait(scond_t *cond, slock_t *lock) { #ifdef USE_WIN32_THREADS @@ -723,13 +613,6 @@ void scond_wait(scond_t *cond, slock_t *lock) #endif } -/** - * scond_broadcast: - * @cond : pointer to condition variable object - * - * Broadcast a condition. Unblocks all threads currently blocked - * on the specified condition variable @cond. - **/ int scond_broadcast(scond_t *cond) { #ifdef USE_WIN32_THREADS @@ -750,13 +633,6 @@ int scond_broadcast(scond_t *cond) #endif } -/** - * scond_signal: - * @cond : pointer to condition variable object - * - * Signal a condition. Unblocks at least one of the threads currently blocked - * on the specified condition variable @cond. - **/ void scond_signal(scond_t *cond) { #ifdef USE_WIN32_THREADS @@ -796,18 +672,6 @@ void scond_signal(scond_t *cond) #endif } -/** - * scond_wait_timeout: - * @cond : pointer to condition variable object - * @lock : pointer to mutex object - * @timeout_us : timeout (in microseconds) - * - * Try to block on a condition variable (i.e. wait on a condition) until - * @timeout_us elapses. - * - * Returns: false (0) if timeout elapses before condition variable is - * signaled or broadcast, otherwise true (1). - **/ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us) { #ifdef USE_WIN32_THREADS diff --git a/libretro-common/streams/file_stream.c b/libretro-common/streams/file_stream.c index befb31c701..713b5d8c29 100644 --- a/libretro-common/streams/file_stream.c +++ b/libretro-common/streams/file_stream.c @@ -81,7 +81,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info) filestream_rename_cb = NULL; if ( - (vfs_info->required_interface_version < + (vfs_info->required_interface_version < FILESTREAM_REQUIRED_VFS_VERSION) || !vfs_iface) return; @@ -152,15 +152,6 @@ int64_t filestream_truncate(RFILE *stream, int64_t length) return output; } -/** - * filestream_open: - * @path : path to file - * @mode : file mode to use when opening (read/write) - * @hints : - * - * Opens a file for reading or writing, depending on the requested mode. - * @return A pointer to an RFILE if opened successfully, otherwise NULL. - **/ RFILE* filestream_open(const char *path, unsigned mode, unsigned hints) { struct retro_vfs_file_handle *fp = NULL; @@ -269,9 +260,9 @@ int filestream_vscanf(RFILE *stream, const char* format, va_list *args) *subfmtiter++ = *format++; } else if ( - *format == 'j' || - *format == 'z' || - *format == 't' || + *format == 'j' || + *format == 'z' || + *format == 't' || *format == 'L') { *subfmtiter++ = *format++; @@ -470,8 +461,8 @@ int filestream_putc(RFILE *stream, int c) char c_char = (char)c; if (!stream) return EOF; - return filestream_write(stream, &c_char, 1) == 1 - ? (int)(unsigned char)c + return filestream_write(stream, &c_char, 1) == 1 + ? (int)(unsigned char)c : EOF; } @@ -521,17 +512,6 @@ int filestream_close(RFILE *stream) return output; } -/** - * filestream_read_file: - * @path : path to file. - * @buf : buffer to allocate and read the contents of the - * file into. Needs to be freed manually. - * @len : optional output integer containing bytes read. - * - * Read the contents of a file into @buf. - * - * @return Non-zero on success. - */ int64_t filestream_read_file(const char *path, void **buf, int64_t *len) { int64_t ret = 0; @@ -584,16 +564,6 @@ error: return 0; } -/** - * filestream_write_file: - * @path : path to file. - * @data : contents to write to the file. - * @size : size of the contents. - * - * Writes data to a file. - * - * @return true on success, otherwise false. - **/ bool filestream_write_file(const char *path, const void *data, int64_t size) { int64_t ret = 0; @@ -608,11 +578,6 @@ bool filestream_write_file(const char *path, const void *data, int64_t size) return (ret == size); } -/** - * filestream_getline: - * - * Returned pointer must be freed by the caller. - **/ char *filestream_getline(RFILE *stream) { char *newline_tmp = NULL; diff --git a/runloop.c b/runloop.c index a791671e87..135bc6fe7c 100644 --- a/runloop.c +++ b/runloop.c @@ -3110,26 +3110,26 @@ bool runloop_environment_cb(unsigned cmd, void *data) case RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE: { - int result = 0; - video_driver_state_t *video_st = video_state_get_ptr(); - audio_driver_state_t *audio_st = audio_state_get_ptr(); + enum retro_av_enable_flags result = 0; + video_driver_state_t *video_st = video_state_get_ptr(); + audio_driver_state_t *audio_st = audio_state_get_ptr(); if ( !(audio_st->flags & AUDIO_FLAG_SUSPENDED) && (audio_st->flags & AUDIO_FLAG_ACTIVE)) - result |= 2; + result |= RETRO_AV_ENABLE_AUDIO; if ( (video_st->flags & VIDEO_FLAG_ACTIVE) && !(video_st->current_video->frame == video_null.frame)) - result |= 1; + result |= RETRO_AV_ENABLE_VIDEO; #ifdef HAVE_RUNAHEAD if (audio_st->flags & AUDIO_FLAG_HARD_DISABLE) - result |= 8; + result |= RETRO_AV_ENABLE_HARD_DISABLE_AUDIO; #endif #ifdef HAVE_NETWORKING if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_REPLAYING, NULL)) - result &= ~(1|2); + result &= ~(RETRO_AV_ENABLE_VIDEO|RETRO_AV_ENABLE_AUDIO); #endif #if defined(HAVE_RUNAHEAD) || defined(HAVE_NETWORKING) @@ -3137,11 +3137,11 @@ bool runloop_environment_cb(unsigned cmd, void *data) Use RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT instead. */ /* TODO/FIXME: Get rid of this ugly hack. */ if (runloop_st->flags & RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE) - result |= 4; + result |= RETRO_AV_ENABLE_FAST_SAVESTATES; #endif if (data) { - int* result_p = (int*)data; + enum retro_av_enable_flags* result_p = (enum retro_av_enable_flags*)data; *result_p = result; } break;