Mupen64Plus API versions

---------------------------------------------------------------------------------------------------
Goal:

The Mupen64Plus API versioning scheme was invented to give a more friendly and less confusing
experience for users as the various components evolve over time.  There are 6 basic components
to the Mupen64Plus system, which may be independently built and installed:

1. The Front-end UI application
2. The Core emulator library
3. The Video plugin
4. The Audio plugin
5. The Input plugin
6. The RSP plugin

These components interact with each other in several different ways.  The design goal of the
versioning scheme is to gracefully handle all situations in which two components support different
versions of their common API (due to one component being newer than the other).  In particular,
each pair of components sharing a common API must discover whether or not they are compatible with
each other.  They must make this determination early enough in the startup process to inform the
user of an incompatibility and gracefully exit the software if necessary without crashing.  There
are 2 different decisions that pertain to the compatibility determination:

1. Major API version.  The various API version numbers are 32-bit.  The major version number is
   stored in the upper 16 bits, and the minor version number is in the lower 16 bits.  If two
   components have different major API version numbers, then they are definitely incompatible.
2. Minor API version.  If two components with a common API have different minor version numbers,
   then the newer component may decide whether or not it can interact with the older component
   based upon the older component's version number.  The newer component may optionally disable
   new features and still retain backwards compatibility, or it may refuse to operate with the
   older component.  This decision is left to the component author when new features are added.

---------------------------------------------------------------------------------------------------
Basic Design:

In mupen64plus-core/src/plugin/plugin.h, the following macros are defined:

#define RSP_API_MAJOR_VERSION   0x20000
#define GFX_API_MAJOR_VERSION   0x20000
#define AUDIO_API_MAJOR_VERSION 0x20000
#define INPUT_API_MAJOR_VERSION 0x20000

In mupen64plus-core/src/main/version.h, the following macros are defined:

#define FRONTEND_API_VERSION 0x020000
#define CONFIG_API_VERSION   0x020000
#define DEBUG_API_VERSION    0x020000
#define VIDEXT_API_VERSION   0x020000

1. When the front-end application calls the CoreStartup(), it passes it's Core<-->Front-end API
   version to the core.  If the API major version numbers for the core and front-end don't match,
   the core return from this function with a failure code of M64ERR_INCOMPATIBLE.

2. The Console-UI front-end also checks for API compatibility, during the AttachCoreLib() function
   call.  It is not strictly necessary for a front-end application to verify the API compatibility
   with the core, since the core will also check during CoreStartup().  However, by doing so, an
   updated front-end may detect a core library using a newer (but backwards-compatible) API, and
   enable some extra features as a result of the expanded API.

3. At the time each plugin is attached to the core (during CoreAttachPlugin function call), the
   core checks the version number of the plugin API by calling the PluginGetVersion function.  If
   the major version number of the plugin's reported API (APIVersion & 0xffff0000) does not match
   the corresponding version number for that plugin type in the core (defined in plugin.h), then
   the plugin is incompatible and cannot be attached to the core.  Currently the plugins have no
   way to request the major version number required for a particular plugin type in the core
   library.  

4. The emulator core exports several different API groups which may be used by the front-end and
   plugin modules.  Currently, these groups are: Front-end, Config, Debug, and Video Extension.
   A front-end application or any plugin may call the CoreGetAPIVersions() function to retrieve
   the API version numbers for these groups.  Any plugin or front-end which can use any updated
   (not present in the original "2.0" API) functions in one of these groups should call the core's
   CoreGetAPIVersions() function (during PluginStartup for a plugin or at core attach time for a
   front-end) to check the version # of the API supported by the core, and react accordingly.

5. All front-ends and plugins should verify API version compatibility for the Config API.

---------------------------------------------------------------------------------------------------
Handling Future Changes:

1. New feature added to a plugin library
   If the feature is backwards-compatible with older cores, then plugin API minor version will
   be bumped.  Otherwise, major version number will be bumped.  If change is backwards-compatible,
   then newest core can test the plugin's API version and only enable the feature if present.

2. New feature added to Core<-->Front-end API
   Typically this will happen when a new function or a new feature of an existing function is
   added to the core.  If the older front-ends will still be compatible with newer cores, then the
   minor version number of the front-end API will be bumped.  Otherwise the major version number
   will be bumped.  A newer front-end can check the version of the API supported by the core and
   choose whether to retain backwards-compatibility with older cores or refuse to interoperate.

3. New feature added to Core Config API
   If older plugins can still use the Core Config API with the new feature, then Config API minor
   version will be bumped.  Otherwise, major version number will be bumped.  Newer plugins should
   check the Core's Config API version and maintain backwards compatibility with older cores if
   possible.

4. New feature added to Core Debug API
   If older front-ends can still use the Core Debug API with the new feature, then Debug API minor
   version number will be bumped.  Otherwise, major version number will be bumped.  Newer
   front-end applications should check the Core's Debug API version and maintain backwards
   compatibility with older cores if possible.

5. New feature added to Video Extension API
   This is the most complicated interface, because it involves 3 components: the video plugin, the
   core, and the front-end application.  If older video plugins can still use the newer Video
   Extension API with the core, *and* newer front-end applications can work with older cores, then
   the Video Extension API minor version number will be bumped. Otherwise, the major version
   number will be bumped.  Newer video plugins can check the Core's Video Extension API version
   and maintain backwards compatibility with older cores if possible, otherwise they can refuse
   and give a compatibility error.  Front-end applications (such as the default console-ui) which
   do not hook into the Video Extension do not need to check the Core's Video Extension API
   version.  However, front-end applications which do hook into the Video Extension must check the
   API version.  If the Core and Front-end have different API major version numbers, then they are
   incompatible.  Also if the Core has a *newer* minor version than the front-end, then they are
   incompatible.  This is a unique restriction, and it must be checked and verified by the
   front-end; the Core has no way to check this.

---------------------------------------------------------------------------------------------------
Changelog:
 - Version 2.0.0 is the base for all APIs

 - FRONTEND_API_VERSION version 2.0.1:
   - added "m64p_command" type "M64CMD_CORE_STATE_SET", handled by CoreDoCommand()
   - added "m64p_core_param" type "M64CORE_SPEED_LIMITER", handled by "M64CMD_CORE_STATE_QUERY" and "M64CMD_CORE_STATE_SET" commands

 - FRONTEND_API_VERSION version 2.0.2:
   - added "m64p_command" types:
     - M64CMD_GET_SCREEN_WIDTH
     - M64CMD_GET_SCREEN_HEIGHT
     - M64CMD_READ_SCREEN
     - M64CMD_VOLUME_UP
     - M64CMD_VOLUME_DOWN
     - M64CMD_VOLUME_GET_LEVEL
     - M64CMD_VOLUME_SET_LEVEL
     - M64CMD_VOLUME_MUTE
     - M64CMD_RESET
     - M64CMD_ADVANCE_FRAME
   - extend command M64CMD_STATE_SAVE to support saving uncompressed PJ64 savestate files as well as zip compressed

 - FRONTEND_API_VERSION version 2.1.0:
   - removed "m64p_command" types:
     - M64CMD_GET_SCREEN_WIDTH
     - M64CMD_GET_SCREEN_HEIGHT
     - M64CMD_VOLUME_UP
     - M64CMD_VOLUME_DOWN
     - M64CMD_VOLUME_GET_LEVEL
     - M64CMD_VOLUME_SET_LEVEL
     - M64CMD_VOLUME_MUTE
   - added new "m64p_core_param" types:
     - M64CORE_VIDEO_SIZE
     - M64CORE_AUDIO_VOLUME
     - M64CORE_AUDIO_MUTE
     - M64CORE_INPUT_GAMESHARK
     - M64CORE_STATE_LOADCOMPLETE
     - M64CORE_STATE_SAVECOMPLETE

 - FRONTEND_API_VERSION version 2.1.1:
   - Core command M64CMD_CORE_STATE_SET will now accept M64CORE_VIDEO_SIZE parameter
     - will call the video plugin function ResizeVideoOutput()

 - CONFIG_API_VERSION version 2.1.0:
   - add new function "ConfigSaveSection()" to save only a single config section to disk

 - CONFIG_API_VERSION version 2.2.0:
   - add new function "ConfigHasUnsavedChanges()" to determine if a given Section (or all sections)
     of the Mupen64Plus Core configuration file has been modified since it was last saved or loaded.
   - add new function "ConfigRevertChanges()" to revert changes previously made to one section of
     the configuration file, so that it will match with the configuration at the last time that it
     was loaded from or saved to disk.

 - VIDEO_API_VERSION version 2.1.0:
   - video render callback function now takes a boolean (int) parameter, which specifies whether the
     video frame has been re-drawn since the last time the render callback was called. This allows
     us to take screenshots without the On-Screen-Display text

 - VIDEO_API_VERSION version 2.2.0:
   - add (optional) ResizeVideoOutput function in video plugin.  If this function is not present
     in video plugin, then resizing the output video window will not work.

 - VIDEXT_API_VERSION version 3.0.0:
   - add VidExt_ResizeWindow() function in video extension.  This function is called by the video
     plugin to notify the window manager (SDL if no video extension is registered by the front-end)
     that the OpenGL render window size should change.
   - add m64p_video_flags parameter to the VidExt_SetVideoMode() function.  Currently the flags are
     only used to notify the window manager that resizing is supported by the video plugin, and it
     should create a resizable window if possible.  This may be extended in the future to support
     other features.


