Add Doxygen-styled comments to parts of the libretro API (#15641)

* Touch up the documentation for a few environment calls

* Touch up more comments

* Update docs for more environment calls

* Add doc comments for more environment calls

* Change various @returns to indicate that the environment call is available

- Some environment calls might be recognized but ignored (e.g. when fast-forwarding during netplay)

* Note some deprecated symbols

* Touch up the docs for RETRO_ENVIRONMENT_SET_MESSAGE

* Touch up the docs for RETRO_ENVIRONMENT_SET_PIXEL_FORMAT

* Add more doc comments

* (libretro) Add more doxygen documentation for the libretro API

* (libretro) Add doxygen comments for the callbacks

* Document retro_init and retro_deinit

* Add comments for retro_log-related symbols

* Add a comment

* Clean up some camera-related comments

* Clean up frame time-related callbacks

* Correct some information about major callbacks

* Clarify some parameter info

* Fix incorrect info about retro_set_environment

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* (libretro) Add doxygen docs on RETRO_THROTTLE

* Touch up the docs for RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK

* Touch up the docs for some macros

* Touch up the docs for some more environment calls

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Tidy up the doc comments for clamping.h

- It was a low-hanging fruit

* Define some sections for constants

- Doxygen will group all contained symbols on one page

* Fix a duplicate @see

* Polish up the docs for the rumble interface

* Polish up the docs for RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Document INLINE

* Clean up some tags

* Touch up the docs for the sensor interface

* Add docs for RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK

* Update docs for RETRO_ENVIRONMENT_GET_INPUT_BITMASKS and accompanying names

* Update some group definitions

* Spiff up the docs for retro_dirent.h

* Document dylib.h

* Document base64.h

* Document crc32.h

* Touch up the docs for audio conversion functions

* Clean up some Doxygen tags

* Refine the docs for RETRO_ENVIRONMENT_GET_PERF_INTERFACE

* Fix incorrect infor in dylib.h

* Touch up the docs for RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE

* Revise the docs for RETRO_ENVIRONMENT_SET_GEOMETRY

* Revise the docs for RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE

* Revise a function's doc

* Touch up most of the rthreads docs

* Touch up the retro_timers.h docs

* Revise the subsystem docs

* Fix some incorrect @see's

* Touch up the docs for RETRO_ENVIRONMENT_GET_LED_INTERFACE

* Give the RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT docs a makeover

* Slight cleanup to the microphone docs

* Slight cleanup to the device power docs

* Touch up serialization quirk docs

* Give the MIDI docs a haircut

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Freshen up rtime's docs

* Improve the docs and accompanying definitions for RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE

- Revise the text of the documentation
- Introduce an enum that defines the flags (it's still an int, so ABI compatibility will be fine)
- Move the documentation for each bit to its corresponding enum

* Shine the shoes of RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS's docs

* Freshen up the docs for fifo_queue.h

* Document most of task_queue.h

* Put retro_dirent's symbols in a group

* Finish documenting task_queue.h

* Document some compatibility headers

* Document read_stdin

* Document file_stream_transforms.h

* Document the VFS API

- Not the wrappers, just the plain API itself

* (Docs) Add doxygen notes about RETRO_DEVICE_*

* Fix some line breaks

* Revise RETRO_DEVICE docs

* Document strl.h

* Update the features_cpu.h docs

* Rewrite the docs for file_stream.h

* Update the docs for retro_endianness.h

* Update the docs for retro_miscellaneous.h

* Document the RETRO_VFS_SEEK_POSITION constants

* Finish documenting rthreads.h

* Document network_stream.h

* Put the RETRO_MEMORY defines in a defgroup

* Move a doc comment in retro_common.h to file scope

* Revise the docs for RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, and accompanying symbols

* Fix the @param/in/out order in libretro.h's @param declarations

* Tidy up the docs for RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION

* Spiff up the docs for RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER

* Fix some tags

* Polish up RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE's docs

* libretro: Add header doxygen

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Update libretro-common/include/libretro.h

Co-authored-by: Rob Loach <robloach@gmail.com>

* Clean up the docs for RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY

* Clean up the docs for RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE

* Touch up some comment syntax for RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE

* Fix some inaccuracies

* Re-add the license statement for libretro.h

* Touch up the docs for RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2

* Touch up docs for RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY

* Touch up docs for some options-related symbols

* Fix some syntax that was preventing most doc files from being generated

* Express retro_core_option_definition docs in terms of retro_core_option_v2_definition

* Finalize some core option-related docs

* Fix some incorrect info about achievements

* Polish up the docs for RETRO_ENVIRONMENT_SET_MEMORY_MAPS

* Polish up the docs for RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION

* Add a notice for `RETRO_ENVIRONMENT_GET_LOG_INTERFACE`

* Update the disk control interface docs

* Add a sentence to a doc comment

* Update a comment

* Remove an irrelevant @todo

* Touch up the docs for `retro_message_target`

* Touch up the docs for `retro_message_type`

* Touch up the docs for `RETRO_ENVIRONMENT_SET_MESSAGE_EXT`

* Touch up the docs for `RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK`

* Touch up the docs for `RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY`

* Revise a comment

* Revise the docs for `RETRO_ENVIRONMENT_SET_VARIABLE`

* Add a `@see`

* Clean up the `RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE` docs

* Update the Doxyfile

* libretro: Add three more environment callback doxygen docs

* doxygen: Remove @example reference

---------

Co-authored-by: Rob Loach <robloach@gmail.com>
This commit is contained in:
Jesse Talavera 2024-03-09 20:24:01 -05:00 committed by GitHub
parent a417f74476
commit b7ddac2431
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 8039 additions and 3080 deletions

469
Doxyfile
View file

@ -1,4 +1,4 @@
# Doxyfile 1.8.14 # Doxyfile 1.9.1
# This file describes the settings to be used by the documentation system # This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project. # doxygen (www.doxygen.org) for a project.
@ -17,10 +17,10 @@
# Project related configuration options # Project related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file # This tag specifies the encoding used for all characters in the configuration
# that follow. The default is UTF-8 which is also the encoding used for all text # file that follow. The default is UTF-8 which is also the encoding used for all
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # text before the first occurrence of this tag. Doxygen uses libiconv (or the
# built into libc) for the transcoding. See # iconv built into libc) for the transcoding. See
# https://www.gnu.org/software/libiconv/ for the list of possible encodings. # https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8. # 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. # title of most generated pages and in a few other places.
# The default value is: My Project. # 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 # 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 # 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 # entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used. # 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- # 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 # directories (in 2 levels) under the output directory of each output format and
@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English 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 # 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 # descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this. # documentation (similar to Javadoc). Set to NO to disable this.
@ -187,7 +195,17 @@ SHORT_NAMES = YES
# description.) # description.)
# The default value is: NO. # 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 # 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 # 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 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 # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements. # documentation from any documented member that it re-implements.
# The default value is: YES. # 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 # "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 # 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. # 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 = ALIASES = "setby{1}=@par Set by^^The \1."
# 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 =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # 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 # only. Doxygen will then generate output that is more tailored for C. For
@ -253,7 +277,7 @@ TCL_SUBST =
# members will be omitted, etc. # members will be omitted, etc.
# The default value is: NO. # 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 # 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 # Python sources only. Doxygen will then generate output that is more tailored
@ -275,28 +299,40 @@ OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = 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 # 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 # 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 # 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 # 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, # language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# Fortran. In the later case the parser tries to guess whether the code is fixed # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
# or free formatted code, this is the default for Fortran type files), VHDL. For # tries to guess whether the code is fixed or free formatted code, this is the
# instance to make doxygen treat .inc files as Fortran files (default is PHP), # default for Fortran type files). For instance to make doxygen treat .inc files
# and .f files as C (default is Fortran), use: inc=Fortran f=C. # 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: 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 # 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 = EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable # 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 # 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 # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues. # 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 # to that level are automatically included in the table of contents, even if
# they do not have an id attribute. # they do not have an id attribute.
# Note: This feature currently applies only to Markdown headings. # 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. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
TOC_INCLUDE_HEADINGS = 0 TOC_INCLUDE_HEADINGS = 0
@ -398,7 +434,7 @@ INLINE_GROUPED_CLASSES = NO
# Man pages) or section (for LaTeX and RTF). # Man pages) or section (for LaTeX and RTF).
# The default value is: NO. # 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 # 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 # 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 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 # Build related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -442,7 +491,13 @@ EXTRACT_ALL = YES
# be included in the documentation. # be included in the documentation.
# The default value is: NO. # 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 # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation. # scope will be included in the documentation.
@ -481,6 +536,13 @@ EXTRACT_LOCAL_METHODS = YES
EXTRACT_ANON_NSPACES = NO 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 # 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 # undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation # members will be included in the various overviews, but no documentation
@ -498,8 +560,8 @@ HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # 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 # declarations. If set to NO, these declarations will be included in the
# included in the documentation. # documentation.
# The default value is: NO. # The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO HIDE_FRIEND_COMPOUNDS = NO
@ -518,11 +580,18 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # With the correct setting of option CASE_SENSE_NAMES doxygen will better be
# names in lower-case letters. If set to YES, upper-case letters are also # able to match the capabilities of the underlying filesystem. In case the
# allowed. This is useful if you have classes or files whose names only differ # filesystem is case sensitive (i.e. it supports files in the same directory
# in case and if your file system supports case sensitive file names. Windows # whose names only differ in casing), the option must be set to YES to properly
# and Mac users are advised to set this option to NO. # 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. # The default value is: system dependent.
CASE_SENSE_NAMES = YES CASE_SENSE_NAMES = YES
@ -532,7 +601,7 @@ CASE_SENSE_NAMES = YES
# scope will be hidden. # scope will be hidden.
# The default value is: NO. # 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 # 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 # 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. # name. If set to NO, the members will appear in declaration order.
# The default value is: YES. # 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 # 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 # 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 # 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 # are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete # 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. # The default value is: NO.
WARN_NO_PARAMDOC = NO WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # 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. # The default value is: NO.
WARN_AS_ERROR = NO WARN_AS_ERROR = NO
@ -791,13 +864,13 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # 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 # 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 # 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 # 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 # documentation (see:
# possible encodings. # https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# The default value is: UTF-8. # The default value is: UTF-8.
INPUT_ENCODING = 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 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen. # 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, # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. # *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
# *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.c \ FILE_PATTERNS = *.h
*.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
# The RECURSIVE tag can be used to specify whether or not subdirectories should # The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well. # 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 # 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 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 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the # (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 # Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/* # 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 # 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 # that contain example code fragments that are included (see the \include
@ -1012,7 +1052,7 @@ INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented # 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. # The default value is: NO.
REFERENCED_BY_RELATION = NO REFERENCED_BY_RELATION = NO
@ -1049,7 +1089,7 @@ SOURCE_TOOLTIPS = YES
# #
# To use it do the following: # To use it do the following:
# - Install the latest version of global # - 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 # - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal # - Run doxygen as normal
# #
@ -1071,6 +1111,44 @@ USE_HTAGS = NO
VERBATIM_HEADERS = YES 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 # Configuration options related to the alphabetical class index
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -1082,20 +1160,14 @@ VERBATIM_HEADERS = YES
ALPHABETICAL_INDEX = 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 # 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 # 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 # can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers. # while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. # 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 # 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 # 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 # 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 # 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. # like the Qt help browser.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to 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 # 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 # generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: https://developer.apple.com/tools/xcode/), introduced with # environment (see:
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
# Makefile in the HTML output directory. Running make will produce the docset in # create a documentation set, doxygen will generate a Makefile in the HTML
# that directory and running make install will install the docset in # 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 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
# for more information. # genXcode/_index.html for more information.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # 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 # 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 # 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 # 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 # (see:
# Windows. # 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 # 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 # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@ -1335,7 +1408,7 @@ CHM_FILE =
HHC_LOCATION = HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated # 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. # The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES. # 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 # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace # 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. # The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES. # 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 # 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 # 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. # The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES. # 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 # 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 # 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. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # 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 # 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. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS = QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see: # 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. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's # The QHG_LOCATION tag can be used to specify the location (absolute path
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
# generated .qhp file. # run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION = QHG_LOCATION =
@ -1468,7 +1545,7 @@ DISABLE_INDEX = NO
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # 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 # 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. # doxygen will group on one line in the generated HTML documentation.
@ -1494,6 +1571,17 @@ TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO 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 # 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 # 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 # doxygen run you need to manually remove any form_*.png images from the HTML
@ -1514,8 +1602,14 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES 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 # 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 # 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 # 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 # 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 # When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see: # 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 # Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG. # compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS. # 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 # 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. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment. # 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. # This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ 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 # 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 # 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. # example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
@ -1585,7 +1680,7 @@ MATHJAX_CODEFILE =
SEARCHENGINE = YES SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be # 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 # 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 # 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 # 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 # Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (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. # See the section "External Indexing and Searching" for details.
# The default value is: NO. # The default value is: NO.
@ -1617,8 +1713,9 @@ EXTERNAL_SEARCH = NO
# #
# Doxygen ships with an example indexer (doxyindexer) and search engine # Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/). See the section "External Indexing and # Xapian (see:
# Searching" for details. # https://xapian.org/). See the section "External Indexing and Searching" for
# details.
# This tag requires that the tag SEARCHENGINE is set to YES. # This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL = 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 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. # invoked.
# #
# Note that when enabling USE_PDFLATEX this option is only used for generating # Note that when not enabling USE_PDFLATEX the default is latex when enabling
# bitmaps for formulas in the HTML output, but not in the Makefile that is # USE_PDFLATEX the default is pdflatex and when in the later case latex is
# written to the output directory. # chosen this is overwritten by pdflatex. For specific output languages the
# The default file is: latex. # 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. # This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX. # 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. # The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex 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 # 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 # documents. This may be useful for small projects and may help to save some
# trees in general. # trees in general.
@ -1768,9 +1879,11 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate # If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
# the PDF file directly from the LaTeX files. Set this option to YES, to get a # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
# higher quality PDF documentation. # 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. # The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
@ -1818,6 +1931,14 @@ LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO 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 # Configuration options related to the RTF output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -1857,9 +1978,9 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's config # Load stylesheet definitions from file. Syntax is similar to doxygen's
# file, i.e. a series of assignments. You only have to provide replacements, # configuration file, i.e. a series of assignments. You only have to provide
# missing definitions are set to their default value. # replacements, missing definitions are set to their default value.
# #
# See also section "Doxygen usage" for information on how to generate the # See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses. # default style sheet that doxygen normally uses.
@ -1868,8 +1989,8 @@ RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE = RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is # 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 # similar to doxygen's configuration file. A template extensions file can be
# using doxygen -e rtf extensionFile. # generated using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES. # This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE = RTF_EXTENSIONS_FILE =
@ -1955,6 +2076,13 @@ XML_OUTPUT = xml
XML_PROGRAMLISTING = YES 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 # Configuration options related to the DOCBOOK output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -1994,6 +2122,10 @@ DOCBOOK_PROGRAMLISTING = NO
GENERATE_AUTOGEN_DEF = NO GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to Sqlite3 output
#---------------------------------------------------------------------------
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the Perl module 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. # recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # 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 # 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 # 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 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 # Configuration options related to the dot tool
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -2173,16 +2299,7 @@ PERL_PATH = /usr/bin/perl
# powerful graphs. # powerful graphs.
# The default value is: YES. # The default value is: YES.
CLASS_DIAGRAMS = YES CLASS_DIAGRAMS = NO
# 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 =
# You can include diagrams made with dia in doxygen documentation. Doxygen will # 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 # 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 # 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 # Bell Labs. The other options in this section have no effect if this option is
# set to NO # 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 # 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 # 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 # but if the number exceeds 15, the total amount of fields shown is limited to
# 10. # 10.
# Minimum value: 0, maximum value: 100, default value: 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 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 # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their # collaboration graphs will show the relations between templates and their
# instances. # instances.
@ -2358,7 +2497,9 @@ DIRECTORY_GRAPH = YES
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # 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 # to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement). # 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:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus. # png:gdiplus:gdiplus.
# The default value is: png. # The default value is: png.
@ -2474,9 +2615,11 @@ DOT_MULTI_TARGETS = YES
GENERATE_LEGEND = 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. # 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. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES DOT_CLEANUP = YES

View file

@ -150,13 +150,6 @@ static int ra_clock_gettime(int clk_ik, struct timespec *t)
#include <string.h> #include <string.h>
/**
* 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 cpu_features_get_perf_counter(void)
{ {
retro_perf_tick_t time_ticks = 0; retro_perf_tick_t time_ticks = 0;
@ -218,13 +211,6 @@ retro_perf_tick_t cpu_features_get_perf_counter(void)
return time_ticks; 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) retro_time_t cpu_features_get_time_usec(void)
{ {
#if defined(_WIN32) #if defined(_WIN32)
@ -503,13 +489,6 @@ static void cpulist_read_from(CpuList* list, const char* filename)
#endif #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) unsigned cpu_features_get_core_amount(void)
{ {
#if defined(_WIN32) && !defined(_XBOX) #if defined(_WIN32) && !defined(_XBOX)
@ -609,13 +588,6 @@ unsigned cpu_features_get_core_amount(void)
#define VENDOR_INTEL_c 0x6c65746e #define VENDOR_INTEL_c 0x6c65746e
#define VENDOR_INTEL_d 0x49656e69 #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_features_get(void)
{ {
uint64_t cpu = 0; uint64_t cpu = 0;

View file

@ -31,22 +31,28 @@ RETRO_BEGIN_DECLS
#include <stddef.h> #include <stddef.h>
/** /**
* convert_float_to_s16: * Converts an array of floating-point audio samples
* @out : output buffer * to signed integer 16-bit audio samples,
* @in : input buffer * possibly using SIMD intrinsics.
* @samples : size of samples to be converted
* *
* Converts floating point * @param out The buffer that will be used to store the converted samples.
* to signed integer 16-bit. * @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 <tt>sizeof(int16_t) * samples</tt>.
* @see convert_s16_to_float
**/ **/
void convert_float_to_s16(int16_t *out, void convert_float_to_s16(int16_t *out,
const float *in, size_t samples); 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 * If SIMD intrinsics are not available or no initialization is required,
* functions based on CPU features. * this function does nothing.
*
* @see convert_float_to_s16
**/ **/
void convert_float_to_s16_init_simd(void); void convert_float_to_s16_init_simd(void);

View file

@ -30,23 +30,30 @@
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
/** /**
* convert_s16_to_float: * Converts an array of signed integer 16-bit audio samples
* @out : output buffer * to floating-point format,
* @in : input buffer * possibly using SIMD intrinsics.
* @samples : size of samples to be converted
* @gain : gain applied (.e.g. audio volume)
* *
* Converts from signed integer 16-bit * @param out The buffer that will be used to store the converted samples.
* to floating point. * @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 <tt>sizeof(float) * samples</tt>.
* @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, void convert_s16_to_float(float *out,
const int16_t *in, size_t samples, float gain); 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 * If SIMD intrinsics are not available or no initialization is required,
* functions based on CPU features. * this function does nothing.
*
* @see convert_s16_to_float
**/ **/
void convert_s16_to_float_init_simd(void); void convert_s16_to_float_init_simd(void);

View file

@ -27,14 +27,13 @@
#include <retro_inline.h> #include <retro_inline.h>
/** /**
* clamp_float: * Clamps a floating-point value to the specified range.
* @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. * @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) 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: * Clamps an integer to fit in 8 bits.
* @val : initial value
* *
* Clamps an unsigned 8-bit value. * @param val The value to clamp.
* * @return \c val clamped to between 0 and 255 (inclusive).
* Returns: a clamped value of initial unsigned 8-bit value @val.
*/ */
static INLINE uint8_t clamp_8bit(int val) static INLINE uint8_t clamp_8bit(int val)
{ {

View file

@ -25,6 +25,11 @@
#define FNM_NOMATCH 1 #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); int rl_fnmatch(const char *pattern, const char *string, int flags);
#endif #endif

View file

@ -27,9 +27,17 @@
#include "../../../config.h" #include "../../../config.h"
#endif #endif
/* Custom implementation of the GNU getopt_long for portability. /**
* Not designed to be fully compatible, but compatible with * @file getopt.h
* the features RetroArch uses. */ *
* 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 #ifdef HAVE_GETOPT_LONG
#include <getopt.h> #include <getopt.h>

View file

@ -47,7 +47,20 @@ struct ifaddrs
#include <sys/cdefs.h> #include <sys/cdefs.h>
/**
* 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); 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); extern void freeifaddrs(struct ifaddrs *ifa);
#endif #endif

View file

@ -38,7 +38,13 @@
RETRO_BEGIN_DECLS 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) static INLINE unsigned compat_clz_u16(uint16_t val)
{ {
#if defined(__GNUC__) #if defined(__GNUC__)
@ -56,7 +62,13 @@ static INLINE unsigned compat_clz_u16(uint16_t val)
#endif #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) static INLINE int compat_ctz(unsigned x)
{ {
#if defined(__GNUC__) && !defined(RARCH_CONSOLE) #if defined(__GNUC__) && !defined(RARCH_CONSOLE)

View file

@ -25,31 +25,64 @@
#include <retro_common_api.h> #include <retro_common_api.h>
/**
* @file posix_string.h
*
* Portable reimplementations of various string functions
* that are normally provided by libc or POSIX.
*/
#ifdef _MSC_VER #ifdef _MSC_VER
#include <compat/msvc.h> #include <compat/msvc.h>
#endif #endif
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
#ifdef _WIN32 #if defined(_WIN32) || defined(DOXYGEN)
#undef strtok_r #undef strtok_r
#define strtok_r(str, delim, saveptr) retro_strtok_r__(str, delim, saveptr) #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); char *strtok_r(char *str, const char *delim, char **saveptr);
#endif #endif
#ifdef _MSC_VER #if defined(_MSC_VER) || defined(DOXYGEN)
#undef strcasecmp #undef strcasecmp
#undef strdup #undef strdup
#define strcasecmp(a, b) retro_strcasecmp__(a, b) #define strcasecmp(a, b) retro_strcasecmp__(a, b)
#define strdup(orig) retro_strdup__(orig) #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); 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); char *strdup(const char *orig);
/* isblank is available since MSVC 2013 */ /* isblank is available since MSVC 2013 */
#if _MSC_VER < 1800 #if _MSC_VER < 1800
#undef isblank #undef isblank
#define isblank(c) retro_isblank__(c) #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); int isblank(int c);
#endif #endif

View file

@ -39,6 +39,14 @@ RETRO_BEGIN_DECLS
* since we prefer to use the actual name. */ * since we prefer to use the actual name. */
#define strcasestr(haystack, needle) strcasestr_retro__(haystack, needle) #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); char *strcasestr(const char *haystack, const char *needle);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -23,6 +23,15 @@
#ifndef __LIBRETRO_SDK_COMPAT_STRL_H #ifndef __LIBRETRO_SDK_COMPAT_STRL_H
#define __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 <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
@ -47,11 +56,29 @@ RETRO_BEGIN_DECLS
#define strlcat(dst, src, size) strlcat_retro__(dst, src, size) #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); 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); size_t strlcat(char *dest, const char *source, size_t size);
#endif #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); char *strldup(const char *s, size_t n);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -39,30 +39,79 @@
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
/**
* Opaque handle to a dynamic library.
* @see dylib_load
*/
typedef void *dylib_t; 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); typedef void (*function_t)(void);
#ifdef NEED_DYNAMIC #ifdef NEED_DYNAMIC
/** /**
* dylib_load: * Loads a dynamic library in a platform-independent manner.
* @path : Path to libretro core library.
* *
* 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_t dylib_load(const char *path);
/** /**
* dylib_close: * Frees the resources associated with a dynamic library.
* @lib : Library handle.
* *
* 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); 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); 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); function_t dylib_proc(dylib_t lib, const char *proc);
#endif #endif

View file

@ -8,7 +8,29 @@
RETRO_BEGIN_DECLS 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); 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); unsigned char* unbase64(const char* ascii, int len, int *flen);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -30,6 +30,14 @@
RETRO_BEGIN_DECLS 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); uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -32,42 +32,62 @@
RETRO_BEGIN_DECLS 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); 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 devices or across reboots.
* The epoch may change between computers 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); 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. * @return Bitmask of all CPU features available.
**/ * @see RETRO_SIMD
* @see retro_perf_callback::get_cpu_features
*/
uint64_t cpu_features_get(void); uint64_t cpu_features_get(void);
/** /**
* cpu_features_get_core_amount: * @return The number of CPU cores available,
* * or 1 if the number of cores could not be determined.
* Gets the amount of available CPU cores. */
*
* @return Amount of CPU cores available.
**/
unsigned cpu_features_get_core_amount(void); 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); void cpu_features_get_model_name(char *name, int len);
RETRO_END_DECLS RETRO_END_DECLS

File diff suppressed because it is too large Load diff

View file

@ -33,14 +33,39 @@
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
/**
* Returns the available data in \c buffer for reading.
*
* @param buffer <tt>fifo_buffer_t *</tt>. 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) #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 <tt>fifo_buffer_t *</tt>. 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)) #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) #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)) #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 struct fifo_buffer
{ {
uint8_t *buffer; uint8_t *buffer;
@ -49,24 +74,94 @@ struct fifo_buffer
size_t end; 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; 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); 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); 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) static INLINE void fifo_clear(fifo_buffer_t *buffer)
{ {
buffer->first = 0; buffer->first = 0;
buffer->end = 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); 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); 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); 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); bool fifo_deinitialize(fifo_buffer_t *buffer);

View file

@ -36,10 +36,12 @@ RETRO_BEGIN_DECLS
enum task_type enum task_type
{ {
/** A regular task. The vast majority of tasks will use this type. */
TASK_TYPE_NONE, 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 TASK_TYPE_BLOCKING
}; };
@ -52,21 +54,38 @@ enum task_style
}; };
typedef struct retro_task retro_task_t; typedef struct retro_task retro_task_t;
/** @copydoc retro_task::callback */
typedef void (*retro_task_callback_t)(retro_task_t *task, typedef void (*retro_task_callback_t)(retro_task_t *task,
void *task_data, void *task_data,
void *user_data, const char *error); void *user_data, const char *error);
/** @copydoc retro_task::handler */
typedef void (*retro_task_handler_t)(retro_task_t *task); 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, typedef bool (*retro_task_finder_t)(retro_task_t *task,
void *userdata); void *userdata);
/**
* Displays a message output by a task.
*/
typedef void (*retro_task_queue_msg_t)(retro_task_t *task, typedef void (*retro_task_queue_msg_t)(retro_task_t *task,
const char *msg, const char *msg,
unsigned prio, unsigned duration, bool flush); unsigned prio, unsigned duration, bool flush);
/** @copydoc task_retriever_data::func */
typedef bool (*retro_task_retriever_t)(retro_task_t *task, void *data); 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 bool (*retro_task_condition_fn_t)(void *data);
typedef struct typedef struct
@ -74,195 +93,652 @@ typedef struct
char *source_file; char *source_file;
} decompress_task_data_t; } 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 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; 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; 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; 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; 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; 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; 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; 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; 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*); 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; 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; 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; 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; int8_t progress;
/* task identifier */ /**
* A unique identifier assigned to a task when it's created.
* Set by the task system.
*/
uint32_t ident; uint32_t ident;
/**
* The type of task this is.
* Set by the caller.
*/
enum task_type type; enum task_type type;
enum task_style style; enum task_style style;
/* if set to true, frontend will /**
use an alternative look for the * If \c true, the frontend should use some alternative means
task progress display */ * of displaying this task's progress or messages.
* Not used within cores.
*/
bool alternative_look; 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; 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; 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; bool mute;
}; };
/**
* Parameters for \c task_queue_find.
*
* @see task_queue_find
*/
typedef struct task_finder_data 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; retro_task_finder_t func;
/**
* Pointer to arbitrary data.
* Passed directly to \c func.
* May be \c NULL.
*/
void *userdata; void *userdata;
} task_finder_data_t; } 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 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; 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; void *data;
} task_retriever_info_t; } task_retriever_info_t;
/**
* Parameters for \c task_queue_retrieve.
*
* @see task_queue_retrieve
*/
typedef struct task_retriever_data 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; 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; 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; retro_task_retriever_t func;
/**
* The size of the output that \c func may write to.
* Must not be zero.
*/
size_t element_size; size_t element_size;
} task_retriever_data_t; } 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(&current))
* {
* 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); 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); void task_queue_retriever_info_free(task_retriever_info_t *list);
/** /**
* Signals a task to end without waiting for * Cancels the provided task.
* it to complete. */ * 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); bool task_queue_is_threaded(void);
/** /**
* Calls func for every running task * Calls the function given in \c find_data for each task
* until it returns true. * until it returns \c true for one of them,
* Returns a task or NULL if not found. * 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); bool task_queue_find(task_finder_data_t *find_data);
/** /**
* Calls func for every running task when handler * Retrieves arbitrary data from every task
* parameter matches task handler, allowing the * whose handler matches \c data::handler.
* list parameter to be filled with user-defined *
* data. * @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); void task_queue_retrieve(task_retriever_data_t *data);
/* Checks for finished tasks /**
* Takes the finished tasks, if any, * Runs each task.
* and runs their callbacks. * If a task is finished or cancelled,
* This must only be called from the main thread. */ * 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); void task_queue_check(void);
/* Pushes a task /**
* The task will start as soon as possible. * Schedules a task to start running.
* If a second blocking task is attempted, false will be returned * If \c task::when is 0, it will start as soon as possible.
* and the task will be ignored. */ *
* 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); bool task_queue_push(retro_task_t *task);
/* Blocks until all non-scheduled tasks have finished. /**
* Will return early if cond is not NULL * Block until all active (i.e. current time > \c task::when) tasks have finished,
* and cond(data) returns false. * or until the given function returns \c false.
* This must only be called from the main thread. */ * 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); 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. * The tasks won't immediately be terminated;
* They will finish as soon as possible. * 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); void task_queue_reset(void);
/* Deinitializes the task system. /**
* This deinitializes the task system. * Deinitializes the task system.
* The tasks that are running at *
* the moment will stay on hold */ * 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); void task_queue_deinit(void);
/* Initializes the task system. /**
* This initializes the task system * Initializes the task system with the provided parameters.
* and chooses an appropriate * Must be called before any other task_queue_* function,
* implementation according to the settings. * 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); 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_task_t *task_init(void);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -23,12 +23,12 @@
#ifndef _LIBRETRO_COMMON_RETRO_COMMON_H #ifndef _LIBRETRO_COMMON_RETRO_COMMON_H
#define _LIBRETRO_COMMON_RETRO_COMMON_H #define _LIBRETRO_COMMON_RETRO_COMMON_H
/* /*!
This file is designed to normalize the libretro-common compiling environment. * @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. * 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, * 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. * in a public API, you may need this.
*/ */
/* conditional compilation is handled inside here */ /* conditional compilation is handled inside here */
#include <compat/msvc.h> #include <compat/msvc.h>

View file

@ -28,50 +28,142 @@
#include <boolean.h> #include <boolean.h>
/** @defgroup dirent Directory Entries
* @{
*/
RETRO_BEGIN_DECLS 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 #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); 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; typedef struct RDIR RDIR;
/** /**
* Opens a directory for reading.
* *
* retro_opendir: * @param name Path to a directory to open.
* @name : path to the 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.
* Opens a directory for reading. Tidy up with retro_closedir. * @note The returned \c RDIR must be closed with \c retro_closedir.
* * @see retro_opendir_include_hidden
* Returns: RDIR pointer on success, NULL if name is not a * @see retro_closedir
* valid directory, null itself or the empty string.
*/ */
struct RDIR *retro_opendir(const char *name); 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); 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); 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); 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); 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: * @param rdir The directory entry to check.
* @rdir : pointer to the directory entry. * Behavior is undefined if \c NULL.
* @unused : deprecated, included for compatibility reasons, pass NULL * @param unused Ignored for compatibility reasons. Pass \c NULL.
* * @return \c true if \c rdir refers to a directory, otherwise \c false.
* Is the directory listing entry a directory? * @see retro_readdir
*
* Returns: true if directory listing entry is
* a directory, false if not.
*/ */
bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused); 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); void retro_closedir(struct RDIR *rdir);
RETRO_END_DECLS RETRO_END_DECLS
/** @} */
#endif #endif

View file

@ -31,12 +31,22 @@
#define SWAP16 _byteswap_ushort #define SWAP16 _byteswap_ushort
#define SWAP32 _byteswap_ulong #define SWAP32 _byteswap_ulong
#else #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) static INLINE uint16_t SWAP16(uint16_t x)
{ {
return ((x & 0x00ff) << 8) | return ((x & 0x00ff) << 8) |
((x & 0xff00) >> 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) static INLINE uint32_t SWAP32(uint32_t x)
{ {
return ((x & 0x000000ff) << 24) | return ((x & 0x000000ff) << 24) |
@ -61,6 +71,11 @@ static INLINE uint64_t SWAP64(uint64_t val)
| ((val & 0xff00000000000000) >> 56); | ((val & 0xff00000000000000) >> 56);
} }
#else #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) static INLINE uint64_t SWAP64(uint64_t val)
{ {
return ((val & 0x00000000000000ffULL) << 56) 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. * @return \c true on little-endian CPUs,
* * \c false on big-endian CPUs.
* Returns: greater than 0 if little-endian, */
* otherwise big-endian.
**/
#define is_little_endian() RETRO_IS_LITTLE_ENDIAN #define is_little_endian() RETRO_IS_LITTLE_ENDIAN
/** /**
* swap_if_big64: * Byte-swaps an unsigned 64-bit integer on big-endian CPUs.
* @val : unsigned 64-bit value
* *
* Byteswap unsigned 64-bit value if system is big-endian. * @param val The value to byteswap if necessary.
* * @return \c val byteswapped on big-endian CPUs,
* Returns: Byteswapped value in case system is big-endian, * \c val unchanged on little-endian CPUs.
* otherwise returns same value. */
**/
#if RETRO_IS_BIG_ENDIAN #if RETRO_IS_BIG_ENDIAN
#define swap_if_big64(val) (SWAP64(val)) #define swap_if_big64(val) (SWAP64(val))
#elif RETRO_IS_LITTLE_ENDIAN #elif RETRO_IS_LITTLE_ENDIAN
@ -150,15 +160,12 @@ static INLINE uint64_t SWAP64(uint64_t val)
#endif #endif
/** /**
* swap_if_big32: * Byte-swaps an unsigned 32-bit integer on big-endian CPUs.
* @val : unsigned 32-bit value
* *
* Byteswap unsigned 32-bit value if system is big-endian. * @param val The value to byteswap if necessary.
* * @return \c val byteswapped on big-endian CPUs,
* Returns: Byteswapped value in case system is big-endian, * \c val unchanged on little-endian CPUs.
* otherwise returns same value. */
**/
#if RETRO_IS_BIG_ENDIAN #if RETRO_IS_BIG_ENDIAN
#define swap_if_big32(val) (SWAP32(val)) #define swap_if_big32(val) (SWAP32(val))
#elif RETRO_IS_LITTLE_ENDIAN #elif RETRO_IS_LITTLE_ENDIAN
@ -166,15 +173,12 @@ static INLINE uint64_t SWAP64(uint64_t val)
#endif #endif
/** /**
* swap_if_little64: * Byte-swaps an unsigned 64-bit integer on little-endian CPUs.
* @val : unsigned 64-bit value
* *
* Byteswap unsigned 64-bit value if system is little-endian. * @param val The value to byteswap if necessary.
* * @return \c val byteswapped on little-endian CPUs,
* Returns: Byteswapped value in case system is little-endian, * \c val unchanged on big-endian CPUs.
* otherwise returns same value. */
**/
#if RETRO_IS_BIG_ENDIAN #if RETRO_IS_BIG_ENDIAN
#define swap_if_little64(val) (val) #define swap_if_little64(val) (val)
#elif RETRO_IS_LITTLE_ENDIAN #elif RETRO_IS_LITTLE_ENDIAN
@ -182,15 +186,12 @@ static INLINE uint64_t SWAP64(uint64_t val)
#endif #endif
/** /**
* swap_if_little32: * Byte-swaps an unsigned 32-bit integer on little-endian CPUs.
* @val : unsigned 32-bit value
* *
* Byteswap unsigned 32-bit value if system is little-endian. * @param val The value to byteswap if necessary.
* * @return \c val byteswapped on little-endian CPUs,
* Returns: Byteswapped value in case system is little-endian, * \c val unchanged on big-endian CPUs.
* otherwise returns same value. */
**/
#if RETRO_IS_BIG_ENDIAN #if RETRO_IS_BIG_ENDIAN
#define swap_if_little32(val) (val) #define swap_if_little32(val) (val)
#elif RETRO_IS_LITTLE_ENDIAN #elif RETRO_IS_LITTLE_ENDIAN
@ -198,15 +199,12 @@ static INLINE uint64_t SWAP64(uint64_t val)
#endif #endif
/** /**
* swap_if_big16: * Byte-swaps an unsigned 16-bit integer on big-endian systems.
* @val : unsigned 16-bit value
* *
* Byteswap unsigned 16-bit value if system is big-endian. * @param val The value to byteswap if necessary.
* * @return \c val byteswapped on big-endian systems,
* Returns: Byteswapped value in case system is big-endian, * \c val unchanged on little-endian systems.
* otherwise returns same value. */
**/
#if RETRO_IS_BIG_ENDIAN #if RETRO_IS_BIG_ENDIAN
#define swap_if_big16(val) (SWAP16(val)) #define swap_if_big16(val) (SWAP16(val))
#elif RETRO_IS_LITTLE_ENDIAN #elif RETRO_IS_LITTLE_ENDIAN
@ -214,15 +212,12 @@ static INLINE uint64_t SWAP64(uint64_t val)
#endif #endif
/** /**
* swap_if_little16: * Byte-swaps an unsigned 16-bit integer on little-endian systems.
* @val : unsigned 16-bit value
* *
* Byteswap unsigned 16-bit value if system is little-endian. * @param val The value to byteswap if necessary.
* * @return \c val byteswapped on little-endian systems,
* Returns: Byteswapped value in case system is little-endian, * \c val unchanged on big-endian systems.
* otherwise returns same value. */
**/
#if RETRO_IS_BIG_ENDIAN #if RETRO_IS_BIG_ENDIAN
#define swap_if_little16(val) (val) #define swap_if_little16(val) (val)
#elif RETRO_IS_LITTLE_ENDIAN #elif RETRO_IS_LITTLE_ENDIAN
@ -230,167 +225,143 @@ static INLINE uint64_t SWAP64(uint64_t val)
#endif #endif
/** /**
* store32be: * Stores a 32-bit integer in at the given address, in big-endian order.
* @addr : pointer to unsigned 32-bit buffer
* @data : unsigned 32-bit value to write
* *
* Write data to address. Endian-safe. Byteswaps the data * @param addr The address to store the value at.
* first if necessary before storing it. * 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) static INLINE void store32be(uint32_t *addr, uint32_t data)
{ {
*addr = swap_if_little32(data); *addr = swap_if_little32(data);
} }
/** /**
* load32be: * Loads a 32-bit integer order from the given address, in big-endian order.
* @addr : pointer to unsigned 32-bit buffer
* *
* Load value from address. Endian-safe. * @param addr The address to load the value from.
* * Behavior is undefined if \c NULL or not aligned to a 32-bit boundary.
* Returns: value from address, byte-swapped if necessary. * @return The value at \c addr, byteswapped if on a little-endian CPU.
**/ */
static INLINE uint32_t load32be(const uint32_t *addr) static INLINE uint32_t load32be(const uint32_t *addr)
{ {
return swap_if_little32(*addr); return swap_if_little32(*addr);
} }
/** /**
* retro_cpu_to_le16: * Converts the given unsigned 16-bit integer to little-endian order if necessary.
* @val : unsigned 16-bit value
* *
* Convert unsigned 16-bit value from system to little-endian. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a big-endian CPU,
* Returns: Little-endian representation of val. * unchanged otherwise.
**/ */
#define retro_cpu_to_le16(val) swap_if_big16(val) #define retro_cpu_to_le16(val) swap_if_big16(val)
/** /**
* retro_cpu_to_le32: * Converts the given unsigned 32-bit integer to little-endian order if necessary.
* @val : unsigned 32-bit value
* *
* Convert unsigned 32-bit value from system to little-endian. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a big-endian CPU,
* Returns: Little-endian representation of val. * unchanged otherwise.
**/ */
#define retro_cpu_to_le32(val) swap_if_big32(val) #define retro_cpu_to_le32(val) swap_if_big32(val)
/** /**
* retro_cpu_to_le64: * Converts the given unsigned 64-bit integer to little-endian order if necessary.
* @val : unsigned 64-bit value
* *
* Convert unsigned 64-bit value from system to little-endian. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a big-endian CPU,
* Returns: Little-endian representation of val. * unchanged otherwise.
**/ */
#define retro_cpu_to_le64(val) swap_if_big64(val) #define retro_cpu_to_le64(val) swap_if_big64(val)
/** /**
* retro_le_to_cpu16: * Converts the given unsigned 16-bit integer to host-native order if necessary.
* @val : unsigned 16-bit value
* *
* Convert unsigned 16-bit value from little-endian to native. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a big-endian CPU,
* Returns: Native representation of little-endian val. * unchanged otherwise.
**/ */
#define retro_le_to_cpu16(val) swap_if_big16(val) #define retro_le_to_cpu16(val) swap_if_big16(val)
/** /**
* retro_le_to_cpu32: * Converts the given unsigned 32-bit integer to host-native order if necessary.
* @val : unsigned 32-bit value
* *
* Convert unsigned 32-bit value from little-endian to native. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a big-endian CPU,
* Returns: Native representation of little-endian val. * unchanged otherwise.
**/ */
#define retro_le_to_cpu32(val) swap_if_big32(val) #define retro_le_to_cpu32(val) swap_if_big32(val)
/** /**
* retro_le_to_cpu16: * Converts the given unsigned 64-bit integer to host-native order if necessary.
* @val : unsigned 64-bit value
* *
* Convert unsigned 64-bit value from little-endian to native. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a big-endian CPU,
* Returns: Native representation of little-endian val. * unchanged otherwise.
**/ */
#define retro_le_to_cpu64(val) swap_if_big64(val) #define retro_le_to_cpu64(val) swap_if_big64(val)
/** /**
* retro_cpu_to_be16: * Converts the given unsigned 16-bit integer to big-endian order if necessary.
* @val : unsigned 16-bit value
* *
* Convert unsigned 16-bit value from system to big-endian. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a little-endian CPU,
* Returns: Big-endian representation of val. * unchanged otherwise.
**/ */
#define retro_cpu_to_be16(val) swap_if_little16(val) #define retro_cpu_to_be16(val) swap_if_little16(val)
/** /**
* retro_cpu_to_be32: * Converts the given unsigned 32-bit integer to big-endian order if necessary.
* @val : unsigned 32-bit value
* *
* Convert unsigned 32-bit value from system to big-endian. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a little-endian CPU,
* Returns: Big-endian representation of val. * unchanged otherwise.
**/ */
#define retro_cpu_to_be32(val) swap_if_little32(val) #define retro_cpu_to_be32(val) swap_if_little32(val)
/** /**
* retro_cpu_to_be64: * Converts the given unsigned 64-bit integer to big-endian order if necessary.
* @val : unsigned 64-bit value
* *
* Convert unsigned 64-bit value from system to big-endian. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a little-endian CPU,
* Returns: Big-endian representation of val. * unchanged otherwise.
**/ */
#define retro_cpu_to_be64(val) swap_if_little64(val) #define retro_cpu_to_be64(val) swap_if_little64(val)
/** /**
* retro_be_to_cpu16: * Converts the given unsigned 16-bit integer from big-endian to host-native order if necessary.
* @val : unsigned 16-bit value
* *
* Convert unsigned 16-bit value from big-endian to native. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a little-endian CPU,
* Returns: Native representation of big-endian val. * unchanged otherwise.
**/ */
#define retro_be_to_cpu16(val) swap_if_little16(val) #define retro_be_to_cpu16(val) swap_if_little16(val)
/** /**
* retro_be_to_cpu32: * Converts the given unsigned 32-bit integer from big-endian to host-native order if necessary.
* @val : unsigned 32-bit value
* *
* Convert unsigned 32-bit value from big-endian to native. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a little-endian CPU,
* Returns: Native representation of big-endian val. * unchanged otherwise.
**/ */
#define retro_be_to_cpu32(val) swap_if_little32(val) #define retro_be_to_cpu32(val) swap_if_little32(val)
/** /**
* retro_be_to_cpu64: * Converts the given unsigned 64-bit integer from big-endian to host-native order if necessary.
* @val : unsigned 64-bit value
* *
* Convert unsigned 64-bit value from big-endian to native. * @param val The value to convert if necessary.
* * @return \c val byteswapped if on a little-endian CPU,
* Returns: Native representation of big-endian val. * unchanged otherwise.
**/ */
#define retro_be_to_cpu64(val) swap_if_little64(val) #define retro_be_to_cpu64(val) swap_if_little64(val)
#ifdef __GNUC__ #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 * * This attribute indicates that pointers to this type may alias
and u32 * may actually be pointing to the same object. */ * to pointers of any other type, similar to \c void* or \c char*.
*/
#define MAY_ALIAS __attribute__((__may_alias__)) #define MAY_ALIAS __attribute__((__may_alias__))
#else #else
#define MAY_ALIAS #define MAY_ALIAS
@ -411,8 +382,22 @@ struct retro_unaligned_uint64_s
} MAY_ALIAS; } MAY_ALIAS;
#pragma pack(pop) #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; 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; 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; typedef struct retro_unaligned_uint64_s retro_unaligned_uint64_t;
/* L-value references to unaligned pointers. */ /* 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) #define retro_unaligned64(p) (((retro_unaligned_uint64_t *)p)->val)
/** /**
* retro_get_unaligned_16be: * Reads a 16-bit unsigned integer from the given address
* @addr : pointer to unsigned 16-bit value * 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. * @param addr The address of the integer to read.
* * Does not need to be divisible by 2
* Returns: Native representation of big-endian val. * 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) { static INLINE uint16_t retro_get_unaligned_16be(void *addr) {
return retro_be_to_cpu16(retro_unaligned16(addr)); return retro_be_to_cpu16(retro_unaligned16(addr));
} }
/** /**
* retro_get_unaligned_32be: * Reads a 32-bit unsigned integer from the given address
* @addr : pointer to unsigned 32-bit value * 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. * @param addr The address of the integer to read.
* * Does not need to be divisible by 4
* Returns: Native representation of big-endian val. * 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) { static INLINE uint32_t retro_get_unaligned_32be(void *addr) {
return retro_be_to_cpu32(retro_unaligned32(addr)); return retro_be_to_cpu32(retro_unaligned32(addr));
} }
/** /**
* retro_get_unaligned_64be: * Reads a 64-bit unsigned integer from the given address
* @addr : pointer to unsigned 64-bit value * 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. * @param addr The address of the integer to read.
* * Does not need to be divisible by 8
* Returns: Native representation of big-endian val. * 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) { static INLINE uint64_t retro_get_unaligned_64be(void *addr) {
return retro_be_to_cpu64(retro_unaligned64(addr)); return retro_be_to_cpu64(retro_unaligned64(addr));
} }
/** /**
* retro_get_unaligned_16le: * Reads a 16-bit unsigned integer from the given address
* @addr : pointer to unsigned 16-bit value * 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. * @param addr The address of the integer to read.
* * Does not need to be divisible by 2
* Returns: Native representation of little-endian val. * 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) { static INLINE uint16_t retro_get_unaligned_16le(void *addr) {
return retro_le_to_cpu16(retro_unaligned16(addr)); return retro_le_to_cpu16(retro_unaligned16(addr));
} }
/** /**
* retro_get_unaligned_32le: * Reads a 32-bit unsigned integer from the given address
* @addr : pointer to unsigned 32-bit value * 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. * @param addr The address of the integer to read.
* * Does not need to be divisible by 4
* Returns: Native representation of little-endian val. * 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) { static INLINE uint32_t retro_get_unaligned_32le(void *addr) {
return retro_le_to_cpu32(retro_unaligned32(addr)); return retro_le_to_cpu32(retro_unaligned32(addr));
} }
/** /**
* retro_get_unaligned_64le: * Reads a 64-bit unsigned integer from the given address
* @addr : pointer to unsigned 64-bit value * 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. * @param addr The address of the integer to read.
* * Does not need to be divisible by 8
* Returns: Native representation of little-endian val. * 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) { static INLINE uint64_t retro_get_unaligned_64le(void *addr) {
return retro_le_to_cpu64(retro_unaligned64(addr)); return retro_le_to_cpu64(retro_unaligned64(addr));
} }
/** /**
* retro_set_unaligned_16le: * Writes a 16-bit unsigned integer to the given address
* @addr : pointer to unsigned 16-bit value * (converted to little-endian order if necessary),
* @val : value to store * 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) { static INLINE void retro_set_unaligned_16le(void *addr, uint16_t v) {
retro_unaligned16(addr) = retro_cpu_to_le16(v); retro_unaligned16(addr) = retro_cpu_to_le16(v);
} }
/** /**
* retro_set_unaligned_32le: * Writes a 32-bit unsigned integer to the given address
* @addr : pointer to unsigned 32-bit value * (converted to little-endian order if necessary),
* @val : value to store * 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) { static INLINE void retro_set_unaligned_32le(void *addr, uint32_t v) {
retro_unaligned32(addr) = retro_cpu_to_le32(v); retro_unaligned32(addr) = retro_cpu_to_le32(v);
} }
/** /**
* retro_set_unaligned_32le: * Writes a 64-bit unsigned integer to the given address
* @addr : pointer to unsigned 32-bit value * (converted to little-endian order if necessary),
* @val : value to store * 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) { static INLINE void retro_set_unaligned_64le(void *addr, uint64_t v) {
retro_unaligned64(addr) = retro_cpu_to_le64(v); retro_unaligned64(addr) = retro_cpu_to_le64(v);
} }
/** /**
* retro_set_unaligned_16be: * Writes a 16-bit unsigned integer to the given address
* @addr : pointer to unsigned 16-bit value * (converted to big-endian order if necessary),
* @val : value to store * 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) { static INLINE void retro_set_unaligned_16be(void *addr, uint16_t v) {
retro_unaligned16(addr) = retro_cpu_to_be16(v); retro_unaligned16(addr) = retro_cpu_to_be16(v);
} }
/** /**
* retro_set_unaligned_32be: * Writes a 32-bit unsigned integer to the given address
* @addr : pointer to unsigned 32-bit value * (converted to big-endian order if necessary),
* @val : value to store * 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) { static INLINE void retro_set_unaligned_32be(void *addr, uint32_t v) {
retro_unaligned32(addr) = retro_cpu_to_be32(v); retro_unaligned32(addr) = retro_cpu_to_be32(v);
} }
/** /**
* retro_set_unaligned_32be: * Writes a 64-bit unsigned integer to the given address
* @addr : pointer to unsigned 32-bit value * (converted to big-endian order if necessary),
* @val : value to store * 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) { static INLINE void retro_set_unaligned_64be(void *addr, uint64_t v) {
retro_unaligned64(addr) = retro_cpu_to_be64(v); retro_unaligned64(addr) = retro_cpu_to_be64(v);
} }

View file

@ -25,6 +25,12 @@
#ifndef INLINE #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) #if defined(_WIN32) || defined(__INTEL_COMPILER)
#define INLINE __inline #define INLINE __inline
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L #elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L

View file

@ -53,6 +53,13 @@
#include <sys/param.h> #include <sys/param.h>
#endif #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) static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count)
{ {
uint32_t i; 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]; 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) static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count)
{ {
uint32_t i; 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]; 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) static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
{ {
uint32_t i; uint32_t i;
@ -78,6 +102,16 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
return false; 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) static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count)
{ {
uint32_t i; 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) #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 #define PATH_MAX_LENGTH 512
#else #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 #define PATH_MAX_LENGTH 4096
#endif #endif
#endif #endif
#ifndef NAME_MAX_LENGTH #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 #define NAME_MAX_LENGTH 256
#endif #endif
#ifndef MAX #ifndef MAX
/**
* @return \c a or \c b, whichever is larger.
*/
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif #endif
#ifndef MIN #ifndef MIN
/**
* @return \c a or \c b, whichever is smaller.
*/
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif #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])) #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(a, i) ((a).data[i])
#define BITS_GET_ELEM_PTR(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))) #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))) #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) #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))) #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))) #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) #define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
/**
* Clears all bits in a 16-bit bitmask.
*/
#define BIT16_CLEAR_ALL(a) ((a) = 0) #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))) #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))) #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) #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) #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))) #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))) #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) #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 BIT64_CLEAR_ALL(a) ((a) = 0)
/** @} */
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (UINT32_C(1) << ((bit) & 31))) #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_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(UINT32_C(1) << ((bit) & 31)))
#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1) #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_GET_PTR(a, bit) BIT128_GET(*a, bit)
#define BIT128_CLEAR_ALL_PTR(a) BIT128_CLEAR_ALL(*a) #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) #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) #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) #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) #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) #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) #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) #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) #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) #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) #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) #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) #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) #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) #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) #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 BIT512_CLEAR_ALL_PTR(a) BIT512_CLEAR_ALL(*a)
#define BITS_COPY16_PTR(a,bits) \ #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. */ /* Helper macros and struct to keep track of many booleans. */
/* This struct has 256 bits. */
/** A 256-bit boolean array. */
typedef struct typedef struct
{ {
/** @private 256 bits. Not intended for direct use. */
uint32_t data[8]; uint32_t data[8];
} retro_bits_t; } retro_bits_t;
/* This struct has 512 bits. */ /** A 512-bit boolean array. */
typedef struct typedef struct
{ {
/** @private 512 bits. Not intended for direct use. */
uint32_t data[16]; uint32_t data[16];
} retro_bits_512_t; } retro_bits_512_t;
/** @} */
#ifdef _WIN32 #ifdef _WIN32
# ifdef _WIN64 # ifdef _WIN64
# define PRI_SIZET PRIu64 # define PRI_SIZET PRIu64

View file

@ -80,10 +80,9 @@ static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp)
#endif #endif
/** /**
* retro_sleep: * Briefly suspends the running thread.
* @msec : amount in milliseconds to sleep
* *
* Sleeps for a specified amount of milliseconds (@msec). * @param msec The time to sleep for, in milliseconds.
**/ **/
#if defined(VITA) #if defined(VITA)
#define retro_sleep(msec) (sceKernelDelayThread(1000 * (msec))) #define retro_sleep(msec) (sceKernelDelayThread(1000 * (msec)))

View file

@ -32,235 +32,274 @@
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
/** Platform-agnostic handle to a thread. */
typedef struct sthread sthread_t; typedef struct sthread sthread_t;
/** Platform-agnostic handle to a mutex. */
typedef struct slock slock_t; typedef struct slock slock_t;
/** Platform-agnostic handle to a condition variable. */
typedef struct scond scond_t; typedef struct scond scond_t;
#ifdef HAVE_THREAD_STORAGE #ifdef HAVE_THREAD_STORAGE
/** Platform-agnostic handle to thread-local storage. */
typedef unsigned sthread_tls_t; typedef unsigned sthread_tls_t;
#endif #endif
/** /**
* sthread_create: * Creates a new thread and starts running it.
* @start_routine : thread entry callback function
* @userdata : pointer to userdata that will be made
* available in thread entry callback function
* *
* Create a new thread. * @param thread_func Function to run in the new thread.
* * Called with the value given in \c userdata as an argument.
* Returns: pointer to new thread if successful, otherwise NULL. * @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_t *sthread_create(void (*thread_func)(void*), void *userdata);
/** /**
* sthread_create_with_priority: * Creates a new thread with a specific priority hint and starts running it.
* @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 * @param thread_func Function to run in the new thread.
* for the thread's priority from [1-100]. Any passed in @thread_priority * Called with the value given in \c userdata as an argument.
* values that are outside of this range will cause sthread_create() to * @param userdata Pointer to anything (even \c NULL), passed directly to \c thread_func.
* create a new thread using the operating system's default thread * Must be cleaned up by the caller or the thread.
* priority. * @param thread_priority Priority hint for the new thread.
* * Threads with a higher number are more likely to be scheduled first.
* Returns: pointer to new thread if successful, otherwise NULL. * 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_t *sthread_create_with_priority(void (*thread_func)(void*), void *userdata, int thread_priority);
/** /**
* sthread_detach: * Detaches the given thread.
* @thread : pointer to thread object
* *
* Detach a thread. When a detached thread terminates, its * When a detached thread terminates,
* resource sare automatically released back to the system * its resources are automatically released back to the operating system
* without the need for another thread to join with the * without needing another thread to join with it.
* terminated thread.
* *
* 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); int sthread_detach(sthread_t *thread);
/** /**
* sthread_join: * Waits for the given thread to terminate.
* @thread : pointer to thread object
* *
* Join with a terminated thread. Waits for the thread specified by * @param thread The thread to wait for.
* @thread to terminate. If that thread has already terminated, then * Must be joinable.
* it will return immediately. The thread specified by @thread must * Returns immediately if it's already terminated
* be joinable. * or if it's \c NULL.
*
* Returns: 0 on success, otherwise it returns a non-zero error number.
*/ */
void sthread_join(sthread_t *thread); void sthread_join(sthread_t *thread);
/** /**
* sthread_isself: * Returns whether the given thread is the same as the calling thread.
* @thread : pointer to thread object
* *
* 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); 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 * Must be manually freed with \c slock_free.
* freed.
* *
* 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_t *slock_new(void);
/** /**
* slock_free:
* @lock : pointer to mutex object
*
* Frees a mutex. * 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); void slock_free(slock_t *lock);
/** /**
* slock_lock: * Locks a mutex, preventing other threads from claiming it until it's unlocked.
* @lock : pointer to mutex object
* *
* Locks a mutex. If a mutex is already locked by * If the mutex is already locked by another thread,
* another thread, the calling thread shall block until * the calling thread will block until the mutex is unlocked.
* the mutex becomes available. *
**/ * @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); void slock_lock(slock_t *lock);
/** /**
* slock_try_lock: * Tries to lock a mutex if it's not already locked by another thread.
* @lock : pointer to mutex object
* *
* Attempts to lock a mutex. If a mutex is already locked by * If the mutex is already in use by another thread,
* another thread, return false. If the lock is acquired, return true. * 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); bool slock_try_lock(slock_t *lock);
/** /**
* slock_unlock: * Unlocks a mutex, allowing other threads to claim it.
* @lock : pointer to mutex object
* *
* 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); void slock_unlock(slock_t *lock);
/** /**
* scond_new: * Creates and initializes a condition variable.
* *
* Creates and initializes a condition variable. Must * Must be manually freed with \c scond_free.
* be manually freed.
* *
* Returns: pointer to new condition variable on success, * @return Pointer to the new condition variable,
* otherwise NULL. * or \c NULL if there was an error.
**/ */
scond_t *scond_new(void); scond_t *scond_new(void);
/** /**
* scond_free:
* @cond : pointer to condition variable object
*
* Frees a condition variable. * 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); void scond_free(scond_t *cond);
/** /**
* scond_wait: * Blocks until the given condition variable is signaled or broadcast.
* @cond : pointer to condition variable object
* @lock : pointer to mutex object
* *
* 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); void scond_wait(scond_t *cond, slock_t *lock);
/** /**
* scond_wait_timeout: * Blocks until the given condition variable is signaled or broadcast,
* @cond : pointer to condition variable object * or until the specified time has passed.
* @lock : pointer to mutex object
* @timeout_us : timeout (in microseconds)
* *
* Try to block on a condition variable (i.e. wait on a condition) until * @param cond Condition variable to wait on.
* @timeout_us elapses. * 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 * @return \c false if \c timeout_us elapses
* signaled or broadcast, otherwise true (1). * before \c cond is signaled or broadcast, otherwise \c true.
**/ */
bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us); bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us);
/** /**
* scond_broadcast: * Unblocks all threads waiting on the specified condition variable.
* @cond : pointer to condition variable object
* *
* Broadcast a condition. Unblocks all threads currently blocked * @param cond Condition variable to broadcast.
* on the specified condition variable @cond. * @return 0 on success, non-zero on failure.
**/ */
int scond_broadcast(scond_t *cond); int scond_broadcast(scond_t *cond);
/** /**
* scond_signal: * Unblocks at least one thread waiting on the specified condition variable.
* @cond : pointer to condition variable object
* *
* Signal a condition. Unblocks at least one of the threads currently blocked * @param cond Condition variable to signal.
* on the specified condition variable @cond. */
**/
void scond_signal(scond_t *cond); void scond_signal(scond_t *cond);
#ifdef HAVE_THREAD_STORAGE #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 * Thread-local storage keys have a single value associated with them
* the process. The same key can be used by multiple threads to store * that is unique to the thread that uses them.
* thread-local data.
* *
* When the key is created NULL shall be associated with it in all active * New thread-local storage keys have a value of \c NULL for all threads,
* threads. Whenever a new thread is spawned the all defined keys will be * and new threads initialize all existing thread-local storage to \c NULL.
* associated with NULL on that thread.
* *
* @param tls * @param tls[in,out] Pointer to the thread local storage key that will be initialized.
* @return whether the operation suceeded or not * 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); bool sthread_tls_create(sthread_tls_t *tls);
/** /**
* @brief Deletes a thread local storage * Deletes a thread local storage key.
* @param tls *
* @return whether the operation suceeded or not * 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); 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 The thread-local storage key to get the data for.
* * @return The calling thread's local data associated with \c tls,
* @param tls * which should previously have been set with \c sthread_tls_set.
* @return * 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); void *sthread_tls_get(sthread_tls_t *tls);
/** /**
* @brief Binds thread specific data to a key * Sets the calling thread's local data for the given key.
* @param tls *
* @return Whether the operation suceeded or not * @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); bool sthread_tls_set(sthread_tls_t *tls, const void *data);
#endif #endif
/* /**
* @brief Get thread ID of specified thread * Gets a thread's unique ID.
* @param thread *
* @return The ID of the specified thread * @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); uintptr_t sthread_get_thread_id(sthread_t *thread);
/* /**
* @brief Get thread ID of the current thread * Get the calling thread's unique ID.
* @param * @return The calling thread's ID.
* @return The ID of the current thread * @see sthread_get_thread_id
*/ */
uintptr_t sthread_get_current_thread_id(void); uintptr_t sthread_get_current_thread_id(void);

View file

@ -38,105 +38,377 @@
#include <stdarg.h> #include <stdarg.h>
#include <vfs/vfs_implementation.h> #include <vfs/vfs_implementation.h>
/** @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 #define FILESTREAM_REQUIRED_VFS_VERSION 2
RETRO_BEGIN_DECLS 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; typedef struct RFILE RFILE;
#define FILESTREAM_REQUIRED_VFS_VERSION 2 #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); 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); 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); int64_t filestream_truncate(RFILE *stream, int64_t length);
/** /**
* filestream_open: * Opens a file for reading or writing.
* @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, depending on the requested mode. * @param path Path to the file to open.
* @return A pointer to an RFILE if opened successfully, otherwise NULL. * 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); 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); 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); 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); 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); int64_t filestream_tell(RFILE *stream);
/**
* Rewinds the given file to the beginning.
* Equivalent to <tt>filestream_seek(stream, 0, RETRO_VFS_SEEK_POSITION_START)</tt>.
* @param stream The file to rewind.
* May be \c NULL, in which case this function does nothing.
*/
void filestream_rewind(RFILE *stream); 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); int filestream_close(RFILE *stream);
/** /**
* filestream_read_file: * Opens a file, reads its contents into a newly-allocated buffer,
* @path : path to file. * then closes it.
* @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. * @param path[in] Path to the file to read.
* * Should be in the format described in \ref GET_VFS_INTERFACE.
* @return Non-zero on success. * @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); 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); 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); 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); 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, ...); 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); int filestream_eof(RFILE *stream);
/** /**
* filestream_write_file: * Writes the entirety of a given buffer to a file at a given path.
* @path : path to file. * Any file that already exists will be overwritten.
* @data : contents to write to the file.
* @size : size of the contents.
* *
* Writes data to a file. * @param path Path to the file that will be written to.
* * @param data The buffer to write to \c path.
* @return true on success, otherwise false. * @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); 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); 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); 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, ...); 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); 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); 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); 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); 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); 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); 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); 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); libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);
RETRO_END_DECLS RETRO_END_DECLS
/** @} */
#endif #endif

View file

@ -28,10 +28,23 @@
#include <retro_common_api.h> #include <retro_common_api.h>
#include <streams/file_stream.h> #include <streams/file_stream.h>
/**
* @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 RETRO_BEGIN_DECLS
#ifndef SKIP_STDIO_REDEFINES #ifndef SKIP_STDIO_REDEFINES
/** @see https://en.cppreference.com/w/c/io/FILE */
#define FILE RFILE #define FILE RFILE
#undef fopen #undef fopen
@ -66,34 +79,48 @@ RETRO_BEGIN_DECLS
#endif #endif
/** @see https://en.cppreference.com/w/c/io/fopen */
RFILE* rfopen(const char *path, const char *mode); RFILE* rfopen(const char *path, const char *mode);
/** @see https://en.cppreference.com/w/c/io/fclose */
int rfclose(RFILE* stream); int rfclose(RFILE* stream);
/** @see https://en.cppreference.com/w/c/io/ftell */
int64_t rftell(RFILE* stream); int64_t rftell(RFILE* stream);
/** @see https://en.cppreference.com/w/c/io/fseek */
int64_t rfseek(RFILE* stream, int64_t offset, int origin); int64_t rfseek(RFILE* stream, int64_t offset, int origin);
/** @see https://en.cppreference.com/w/c/io/fread */
int64_t rfread(void* buffer, int64_t rfread(void* buffer,
size_t elem_size, size_t elem_count, RFILE* stream); 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); char *rfgets(char *buffer, int maxCount, RFILE* stream);
/** @see https://en.cppreference.com/w/c/io/fgetc */
int rfgetc(RFILE* stream); int rfgetc(RFILE* stream);
/** @see https://en.cppreference.com/w/c/io/fwrite */
int64_t rfwrite(void const* buffer, int64_t rfwrite(void const* buffer,
size_t elem_size, size_t elem_count, RFILE* stream); 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); int rfputc(int character, RFILE * stream);
/** @see https://en.cppreference.com/w/c/io/fflush */
int64_t rfflush(RFILE * stream); int64_t rfflush(RFILE * stream);
/** @see https://en.cppreference.com/w/c/io/fprintf */
int rfprintf(RFILE * stream, const char * format, ...); int rfprintf(RFILE * stream, const char * format, ...);
/** @see https://en.cppreference.com/w/c/io/ferror */
int rferror(RFILE* stream); int rferror(RFILE* stream);
/** @see https://en.cppreference.com/w/c/io/feof */
int rfeof(RFILE* stream); int rfeof(RFILE* stream);
/** @see https://en.cppreference.com/w/c/io/fscanf */
int rfscanf(RFILE * stream, const char * format, ...); int rfscanf(RFILE * stream, const char * format, ...);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -34,230 +34,359 @@ RETRO_BEGIN_DECLS
enum enum
{ {
/**
* Indicates that \c netstream_seek should seek
* relative to the beginning of the stream.
*/
NETSTREAM_SEEK_SET = 0, NETSTREAM_SEEK_SET = 0,
/**
* Indicates that \c netstream_seek should seek
* relative to its current position.
*/
NETSTREAM_SEEK_CUR, NETSTREAM_SEEK_CUR,
/**
* Indicates that \c netstream_seek should seek
* relative to the end of the stream.
*/
NETSTREAM_SEEK_END 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 typedef struct netstream
{ {
/** The buffer used by the stream for reading or writing. */
void *buf; void *buf;
/** The size of \c buf in bytes. */
size_t size; size_t size;
/** The number of bytes that have been written to \c buf. */
size_t used; size_t used;
/**
* The current position of the stream, in bytes.
* @see netstream_seek
*/
size_t pos; size_t pos;
} netstream_t; } netstream_t;
/** /**
* netstream_open: * Opens a network-order stream.
* *
* @stream : Pointer to a network stream object. * @param stream Pointer to the network-order stream to initialize.
* @buf : Pre-allocated buffer. Pass NULL to dynamically allocate a buffer. * Behavior is undefined if \c NULL.
* @size : Buffer size. Pass 0 for no pre-allocated/initial buffer. * @param buf Pre-allocated buffer.
* @used : Buffer bytes in use. Ignored for non pre-allocated buffers. * May be \c NULL, in which case a new buffer will be created with \c malloc.
* * @param size Buffer size in bytes.
* Opens a network stream. * 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.
* Returns: true on success, false otherwise. * 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); bool netstream_open(netstream_t *stream, void *buf, size_t size, size_t used);
/** /**
* netstream_close: * Closes a network-order stream.
*
* @stream : Pointer to a network stream object.
* @dealloc : Whether to deallocate/free the buffer or not.
*
* Closes a network 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); 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. * @param stream The network-order stream to reset.
* * Behavior is undefined if \c NULL.
* Resets a network stream to its initial position,
* discarding any used bytes in the process.
* *
* @note This does not deallocate the underlying buffer,
* nor does it wipe its memory.
*/ */
void netstream_reset(netstream_t *stream); void netstream_reset(netstream_t *stream);
/** /**
* netstream_truncate: * Resizes the "used" portion of the stream.
* *
* @stream : Pointer to a network stream object. * @param stream The network-order stream to resize.
* @used : Amount of bytes used. * Behavior is undefined if \c NULL.
* * @param used The number of bytes in the stream that are considered written.
* Truncates the network stream. * @return \c true if the stream's "used" region was resized,
* Truncation can either extend or reduce the amount of bytes used. * \c false if it would've been extended past the buffer's capacity.
* * @note This function does not reallocate or clear the underlying buffer.
* Returns: true on success, false otherwise. * It only sets the boundaries of the "used" portion of the stream.
*/ */
bool netstream_truncate(netstream_t *stream, size_t used); bool netstream_truncate(netstream_t *stream, size_t used);
/** /**
* netstream_data: * Retrieves the network-order stream's 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.
* *
* @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); 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. * @param stream The network-order stream to check.
* * @return \c true if the stream is at EOF, \c false otherwise.
* Checks whether the network stream is at EOF or not.
*
* Returns: true if the stream is at EOF, false otherwise.
*/ */
bool netstream_eof(netstream_t *stream); bool netstream_eof(netstream_t *stream);
/** /**
* netstream_tell: * Gets the network-order stream's current position.
* *
* @stream : Pointer to a network stream object. * @param stream Pointer to a network-order stream.
* * @return The stream's position indicator.
* Gets the network stream's current position.
*
* Returns: current value of the position indicator.
*/ */
size_t netstream_tell(netstream_t *stream); size_t netstream_tell(netstream_t *stream);
/** /**
* netstream_seek: * Sets the network-order stream's current position.
* *
* @stream : Pointer to a network stream object. * @param stream Pointer to a network-order stream.
* @offset : Position's offset. * @param offset The new position of the stream, in bytes.
* @origin : Position used as reference for the offset. * @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.
* Sets the network stream's current position. * @return \c true on success, \c false on failure.
*
* Returns: true on success, false otherwise.
*/ */
bool netstream_seek(netstream_t *stream, long offset, int origin); 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. * @param stream The network-order stream to read from.
* @data : Pointer to a storage for data read from the network stream. * @param data The buffer that will receive data from the stream.
* @len : Amount of bytes to read. Pass 0 to read all remaining bytes. * @param len The number of bytes to read.
* * If 0, will read all remaining bytes.
* Reads raw data from the network stream. * @return \c true on success, \c false on failure.
*
* Returns: true on success, false otherwise.
*/ */
bool netstream_read(netstream_t *stream, void *data, size_t len); 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. * @param stream[in] The network-order stream to read from.
* @data : Pointer to a storage for data read from the network stream. * @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.
* Reads data from the network stream.
* Network byte order is always big endian.
*
* Returns: true on success, false otherwise.
*/ */
bool netstream_read_byte(netstream_t *stream, uint8_t *data); 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); 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); 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); bool netstream_read_qword(netstream_t *stream, uint64_t *data);
#ifdef __STDC_IEC_559__ #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); 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); bool netstream_read_double(netstream_t *stream, double *data);
#endif #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. * @param stream Pointer to a network stream object.
* @s : Pointer to a string buffer. * @param s[out] The buffer that will receive the string.
* @len : Size of the string buffer. * Will be \c NULL-terminated.
* * @param len The length of \c s, in bytes.
* Reads a string from the network stream. * @return The length of the read string in bytes,
* * or -1 if there was an error.
* Returns: Length of the original string on success or
* a negative value on error.
*/ */
int netstream_read_string(netstream_t *stream, char *s, size_t len); 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. * @param stream Pointer to a network stream object.
* @s : Pointer to a string buffer. * @param s The buffer that will receive the string.
* @len : Size of the string buffer. * 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. * @return \c true if a string of the exact length was read,
* * \c false if there was an error.
* Returns: true on success, false otherwise.
*/ */
bool netstream_read_fixed_string(netstream_t *stream, char *s, size_t len); 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. * @param stream Pointer to a network stream object.
* @data : Data to write into the network stream. * @param data The data to write into the network stream.
* @len : Amount of bytes to write. * @param len The length of \c data, in bytes.
* * @return \c true on success,
* Writes raw data into the network stream. * \c false if there was an error.
*
* Returns: true on success, false otherwise.
*/ */
bool netstream_write(netstream_t *stream, const void *data, size_t len); 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. * @param stream Pointer to a network stream object.
* @data : Data to write into the network stream. * @param data The byte to write to the stream.
* * @return \c true on success,
* Writes data into the network stream. * \c false if there was an error.
* Network byte order is always big endian.
*
* Returns: true on success, false otherwise.
*/ */
bool netstream_write_byte(netstream_t *stream, uint8_t data); 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); 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); 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); bool netstream_write_qword(netstream_t *stream, uint64_t data);
#ifdef __STDC_IEC_559__ #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); 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); bool netstream_write_double(netstream_t *stream, double data);
#endif #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. * @param stream Pointer to a network stream object.
* @s : Pointer to a string. * @param s A \c NULL-terminated string.
* * @return \c true on success,
* Writes a null-terminated string into the network stream. * \c false if there was an error.
*
* Returns: true on success, false otherwise.
*/ */
bool netstream_write_string(netstream_t *stream, const char *s); 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. * @param stream Pointer to a network stream object.
* @s : Pointer to a string. * @param s Pointer to a string.
* @len : Size of the string. * Does not need to be \c NULL-terminated,
* * but \c NULL values will not stop processing.
* Writes a null-terminated fixed-length string into the network stream. * Will be \c NULL
* * @param len Length of \c s in bytes,
* Returns: true on success, false otherwise. * 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, bool netstream_write_fixed_string(netstream_t *stream, const char *s,
size_t len); size_t len);

View file

@ -32,6 +32,17 @@
RETRO_BEGIN_DECLS 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); size_t read_stdin(char *buf, size_t size);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -34,13 +34,28 @@ RETRO_BEGIN_DECLS
/* TODO/FIXME: Move all generic time handling functions /* TODO/FIXME: Move all generic time handling functions
* to this file */ * 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); 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); 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); struct tm *rtime_localtime(const time_t *timep, struct tm *result);
RETRO_END_DECLS RETRO_END_DECLS

View file

@ -150,16 +150,6 @@ static void *thread_wrap(void *data_)
return 0; 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) sthread_t *sthread_create(void (*thread_func)(void*), void *userdata)
{ {
return sthread_create_with_priority(thread_func, userdata, 0); 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 #define HAVE_THREAD_ATTR
#endif #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) sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userdata, int thread_priority)
{ {
#ifdef HAVE_THREAD_ATTR #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 ); pthread_attr_setstacksize(&thread_attr , 0x10000 );
thread_attr_needed = true; thread_attr_needed = true;
#elif defined(__APPLE__) #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. */ * for PS2 disc scanning and other reasons, we'd like 2MB. */
pthread_attr_setstacksize(&thread_attr , 0x200000 ); pthread_attr_setstacksize(&thread_attr , 0x200000 );
thread_attr_needed = true; thread_attr_needed = true;
@ -256,17 +231,6 @@ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userda
return NULL; 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) int sthread_detach(sthread_t *thread)
{ {
#ifdef USE_WIN32_THREADS #ifdef USE_WIN32_THREADS
@ -280,17 +244,6 @@ int sthread_detach(sthread_t *thread)
#endif #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) void sthread_join(sthread_t *thread)
{ {
if (!thread) if (!thread)
@ -305,12 +258,6 @@ void sthread_join(sthread_t *thread)
} }
#if !defined(GEKKO) #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) bool sthread_isself(sthread_t *thread)
{ {
#ifdef USE_WIN32_THREADS #ifdef USE_WIN32_THREADS
@ -321,14 +268,6 @@ bool sthread_isself(sthread_t *thread)
} }
#endif #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 *slock_new(void)
{ {
slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); slock_t *lock = (slock_t*)calloc(1, sizeof(*lock));
@ -346,12 +285,6 @@ slock_t *slock_new(void)
return lock; return lock;
} }
/**
* slock_free:
* @lock : pointer to mutex object
*
* Frees a mutex.
**/
void slock_free(slock_t *lock) void slock_free(slock_t *lock)
{ {
if (!lock) if (!lock)
@ -365,14 +298,6 @@ void slock_free(slock_t *lock)
free(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) void slock_lock(slock_t *lock)
{ {
if (!lock) if (!lock)
@ -384,13 +309,6 @@ void slock_lock(slock_t *lock)
#endif #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) bool slock_try_lock(slock_t *lock)
{ {
#ifdef USE_WIN32_THREADS #ifdef USE_WIN32_THREADS
@ -400,12 +318,6 @@ bool slock_try_lock(slock_t *lock)
#endif #endif
} }
/**
* slock_unlock:
* @lock : pointer to mutex object
*
* Unlocks a mutex.
**/
void slock_unlock(slock_t *lock) void slock_unlock(slock_t *lock)
{ {
if (!lock) if (!lock)
@ -417,15 +329,6 @@ void slock_unlock(slock_t *lock)
#endif #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 *scond_new(void)
{ {
scond_t *cond = (scond_t*)calloc(1, sizeof(*cond)); scond_t *cond = (scond_t*)calloc(1, sizeof(*cond));
@ -480,12 +383,6 @@ error:
return NULL; return NULL;
} }
/**
* scond_free:
* @cond : pointer to condition variable object
*
* Frees a condition variable.
**/
void scond_free(scond_t *cond) void scond_free(scond_t *cond)
{ {
if (!cond) if (!cond)
@ -707,13 +604,6 @@ static bool _scond_wait_win32(scond_t *cond, slock_t *lock, DWORD dwMilliseconds
} }
#endif #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) void scond_wait(scond_t *cond, slock_t *lock)
{ {
#ifdef USE_WIN32_THREADS #ifdef USE_WIN32_THREADS
@ -723,13 +613,6 @@ void scond_wait(scond_t *cond, slock_t *lock)
#endif #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) int scond_broadcast(scond_t *cond)
{ {
#ifdef USE_WIN32_THREADS #ifdef USE_WIN32_THREADS
@ -750,13 +633,6 @@ int scond_broadcast(scond_t *cond)
#endif #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) void scond_signal(scond_t *cond)
{ {
#ifdef USE_WIN32_THREADS #ifdef USE_WIN32_THREADS
@ -796,18 +672,6 @@ void scond_signal(scond_t *cond)
#endif #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) bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us)
{ {
#ifdef USE_WIN32_THREADS #ifdef USE_WIN32_THREADS

View file

@ -81,7 +81,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
filestream_rename_cb = NULL; filestream_rename_cb = NULL;
if ( if (
(vfs_info->required_interface_version < (vfs_info->required_interface_version <
FILESTREAM_REQUIRED_VFS_VERSION) FILESTREAM_REQUIRED_VFS_VERSION)
|| !vfs_iface) || !vfs_iface)
return; return;
@ -152,15 +152,6 @@ int64_t filestream_truncate(RFILE *stream, int64_t length)
return output; 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) RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
{ {
struct retro_vfs_file_handle *fp = NULL; struct retro_vfs_file_handle *fp = NULL;
@ -269,9 +260,9 @@ int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
*subfmtiter++ = *format++; *subfmtiter++ = *format++;
} }
else if ( else if (
*format == 'j' || *format == 'j' ||
*format == 'z' || *format == 'z' ||
*format == 't' || *format == 't' ||
*format == 'L') *format == 'L')
{ {
*subfmtiter++ = *format++; *subfmtiter++ = *format++;
@ -470,8 +461,8 @@ int filestream_putc(RFILE *stream, int c)
char c_char = (char)c; char c_char = (char)c;
if (!stream) if (!stream)
return EOF; return EOF;
return filestream_write(stream, &c_char, 1) == 1 return filestream_write(stream, &c_char, 1) == 1
? (int)(unsigned char)c ? (int)(unsigned char)c
: EOF; : EOF;
} }
@ -521,17 +512,6 @@ int filestream_close(RFILE *stream)
return output; 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 filestream_read_file(const char *path, void **buf, int64_t *len)
{ {
int64_t ret = 0; int64_t ret = 0;
@ -584,16 +564,6 @@ error:
return 0; 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) bool filestream_write_file(const char *path, const void *data, int64_t size)
{ {
int64_t ret = 0; int64_t ret = 0;
@ -608,11 +578,6 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
return (ret == size); return (ret == size);
} }
/**
* filestream_getline:
*
* Returned pointer must be freed by the caller.
**/
char *filestream_getline(RFILE *stream) char *filestream_getline(RFILE *stream)
{ {
char *newline_tmp = NULL; char *newline_tmp = NULL;

View file

@ -3110,26 +3110,26 @@ bool runloop_environment_cb(unsigned cmd, void *data)
case RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE: case RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE:
{ {
int result = 0; enum retro_av_enable_flags result = 0;
video_driver_state_t *video_st = video_state_get_ptr(); video_driver_state_t *video_st = video_state_get_ptr();
audio_driver_state_t *audio_st = audio_state_get_ptr(); audio_driver_state_t *audio_st = audio_state_get_ptr();
if ( !(audio_st->flags & AUDIO_FLAG_SUSPENDED) if ( !(audio_st->flags & AUDIO_FLAG_SUSPENDED)
&& (audio_st->flags & AUDIO_FLAG_ACTIVE)) && (audio_st->flags & AUDIO_FLAG_ACTIVE))
result |= 2; result |= RETRO_AV_ENABLE_AUDIO;
if ( (video_st->flags & VIDEO_FLAG_ACTIVE) if ( (video_st->flags & VIDEO_FLAG_ACTIVE)
&& !(video_st->current_video->frame == video_null.frame)) && !(video_st->current_video->frame == video_null.frame))
result |= 1; result |= RETRO_AV_ENABLE_VIDEO;
#ifdef HAVE_RUNAHEAD #ifdef HAVE_RUNAHEAD
if (audio_st->flags & AUDIO_FLAG_HARD_DISABLE) if (audio_st->flags & AUDIO_FLAG_HARD_DISABLE)
result |= 8; result |= RETRO_AV_ENABLE_HARD_DISABLE_AUDIO;
#endif #endif
#ifdef HAVE_NETWORKING #ifdef HAVE_NETWORKING
if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_REPLAYING, NULL)) if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_REPLAYING, NULL))
result &= ~(1|2); result &= ~(RETRO_AV_ENABLE_VIDEO|RETRO_AV_ENABLE_AUDIO);
#endif #endif
#if defined(HAVE_RUNAHEAD) || defined(HAVE_NETWORKING) #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. */ Use RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT instead. */
/* TODO/FIXME: Get rid of this ugly hack. */ /* TODO/FIXME: Get rid of this ugly hack. */
if (runloop_st->flags & RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE) if (runloop_st->flags & RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE)
result |= 4; result |= RETRO_AV_ENABLE_FAST_SAVESTATES;
#endif #endif
if (data) if (data)
{ {
int* result_p = (int*)data; enum retro_av_enable_flags* result_p = (enum retro_av_enable_flags*)data;
*result_p = result; *result_p = result;
} }
break; break;