libretro-mirrors / libretro-arb

For proposed improvements to libretro API.
8 stars 2 forks source link

Core options #12

Closed Alcaro closed 9 years ago

Alcaro commented 9 years ago

Blocks: #8

Proposed replacement:

#define RETRO_ENVIRONMENT_SET_VARIABLES 40
                                           // const struct retro_variable * --
                                           // Interface to acquire user-defined information from environment
                                           // that cannot feasibly be supported in a multi-system way.
                                           // 
                                           // The first call must be from retro_set_environment or retro_init.
                                           // Additionally, the core may call RETRO_ENVIRONMENT_SET_VARIABLES again during retro_load_game, retro_run, and retro_variable::change_notify, and may have changed some of the entries.
                                           // However, each 'name', 'values' and 'initial' must be the same as for the initial call.
                                           // 
#define RETRO_ENVIRONMENT_GET_VARIABLE 41
                                           // struct retro_variable_query * --
                                           // Asks the frontend what value a variable has.
                                           // 

enum retro_variable_type
{
   RETRO_VARIABLE_TYPE_TERMINATOR, // Tells that the variable list has ended.
   RETRO_VARIABLE_TYPE_SEPARATOR,  // A separator in the list. Use to group them together. All other members are ignored for items of this type.
   RETRO_VARIABLE_TYPE_ENUM,       // Enumeration. 'values' is const char *, with each entry separated by \n. 'initial' is a const unsigned int * containing the index of the default value.
   RETRO_VARIABLE_TYPE_INT,        // Integer. 'values' is const int *; the first entry is the lowest valid value, the second is the highest valid value. 'initial' is also a const int *.
   RETRO_VARIABLE_TYPE_FLOAT,      // Floating point. Same as RETRO_VARIABLE_INT, except with 'float' instead of 'int'. The frontend is responsible for calculating a reasonable step size.
#error TODO: Decide whether FLOAT should be float or double, and if double, whether it should be named FLOAT or DOUBLE.
};

enum retro_variable_change
{
   RETRO_VARIABLE_CHANGE_INSTANT,    // Changes take effect at the next retro_run.
   RETRO_VARIABLE_CHANGE_DELAYED,    // Changes take effect during retro_run, but not instantly; for example, it may be delayed until the next level is loaded.
   RETRO_VARIABLE_CHANGE_RESET,      // Only used during retro_load_game, or possibly retro_reset.
   RETRO_VARIABLE_CHANGE_WRONG_OPTS, // This variable is currently ignored; it is only usable if other options are changed first. If they are, RETRO_ENVIRONMENT_SET_VARIABLES must be called again.
   RETRO_VARIABLE_CHANGE_WRONG_GAME, // This variable is not applicable for this game.
};

struct retro_variable
{
   enum retro_variable_type type;     // Variable type. See above.
   enum retro_variable_change change; // When the implementation will acknowledge changes to this variable. Note that the front is allowed to change variables marked currently unusable.

   const char *name;                  // Variable name, to be used internally. Suitable for saving to configuration files. Example: gb_colorize
   const char *pub_name;              // Variable name, to show the user. Suitable for GUIs. Example: Game Boy colorization
   const char *description;           // Variable description. Suitable as a second line in GUIs. Example: Emulate fake colors on black&white games.
   void *values;                      // Possible values. See enum retro_variable_type for what type it has. Example: Enabled\nDisabled
   void *initial;                     // Default value. Example: 1

   //Called by the frontend every time this variable changes, or NULL to ignore.
   //Can be different for different variables.
   //ID is the index to the array given to RETRO_ENVIRONMENT_SET_VARIABLES.
   //Separators have IDs, but their value must not be set or queried.
   //'value' has the same type as 'default'.
   //Can be called during RETRO_ENVIRONMENT_SET_VARIABLES.
   void (*change_notify)(unsigned int id, void *value);
};

struct retro_variable_query
{
   unsigned int id; // Same ID as in change_notify. Core sets this before calling GET_VARIABLE.
   void *value;     // Same type as initial and change_notify. Front sets this.
};

Any opinions? Suggestions? Face-melting wrath?

Gu1 commented 9 years ago

Why have a RETRO_VARIABLE_TYPE_TERMINATOR instead of just ending the variable list with a NULL pointer ? Why use a string with \n separator for RETRO_VARIABLE_TYPE_ENUM instead of an array of string ? Shouldn't there be a bool type also ? I know this could also be done with the enum type, but a separate bool type would allow the frontend to do i18n on the yes/no choice or even render it with a custom widget (e.g a checkbox). Also, the RETRO_VARIABLE_TYPE_SEPARATOR type feels a bit weird to me...

Alcaro commented 9 years ago

1) Because separators are supposed to use NULL for everything, making them impossible to differentiate from the terminator. I've made sure TYPE_TERMINATOR==0, so you can use while (obj->field). (I seem to have forgotten the dummy==INT_MAX, though.) 2) It's modeled after the original core options, which separate them with |. But yeah, now that I think about it, neither makes sense. 3) Considering I actually pick apart yes/no options in my own front, yes, I should've thought of that. Maybe some options fit better as yes/no and some fit better as enable/disable, but we won't lose too much on forcing them into the same set of strings. 4) A front will work if it doesn't render them; it just feels a bit more organized to group them if they're many. Most cores won't need it, but Snes9X has 13 different options for layer and sound channel toggles, and maybe a few others.