MDP: Mega Drive Plugins
Interface Specification Version 1.0.0-draft
(c) Copyright 2008-2009 by David Korth.

Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.3 or any later version published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts and
no Back-Cover Texts.  You may obtain a copy of this license at
http://www.gnu.org/copyleft/fdl.html

================================================================

0. WARNING: OUTDATED DOCUMENT!

This document is mostly based on MDP v0.1.0, and has not been updated
for most of the changes in MDP v1.0.0. See the new HTML documentation
for up-to-date MDP v1.0.0 information.

================================================================

1. What is a Mega Drive Plugin?

The Mega Drive Plugin specification, or MDP, defines an interface used
to extend the abilities of Sega Genesis emulators.

================================================================

2. External Plugins

MDP Version 1.0.0 supports external plugins using the operating system's
native shared library interface. On Linux, this uses the Shared Object (.so)
system, and on Windows, this uses the Dynamic-Link Library (.dll) system.

================================================================

3. Version Numbering

All MDP interfaces use a hard version numbering system. That is, the version
number is used to determine compatibility.

mdp.h provides an MDP_VERSION() macro, which creates a version number in
this format: 0xMMNNRRRR

- MM == major version.
- NN == minor version.
- RR == revision number.

So for MDP interface version 1.0.0, you would use MDP_VERSION(1, 0, 0).
As a convenience, the MDP_INTERFACE_VERSION macro provides the version
number of the MDP interface definition as specified in that particular
mdp.h header file.

To determine compatibility, Gens looks at the version number and compares
it to its own MDP version number.

The major version number is the main indicator of compatibility; the major
version number of Gens' MDP interface *must* be equal to the major version
number of the plugin's MDP interface; otherwise, it is assumed that the
plugin is incompatible and it is not loaded.

The minor version number indicates if any new backwards-compatible features
have been added. That is, if a feature has been added that doesn't break
the interface and doesn't require that plugins make use of it, the minor
version number is incremented. Gens will check the minor version number to
see if these specific features should be enabled or not on a plugin-by-plugin
basis.

The revision number is not used at all in checking version compatibility.

Note that some sections have an MDP_VERSION() macro in brackets next to
the section name. This indicates the interfaceVersion of the struct being
described. Differences between versions, if any, will be noted later in
that section.

================================================================

4. Basic Plugin Interface [MDP_VERSION(1, 0, 0)]

Every plugin must export a struct of type mdp_t. This struct contains the
basic information about the plugin. For internal plugins, the mdp_t struct
is referenced in the host program's MDP implementation, so it can have any
name. For external plugins, the mdp_t struct must be exported with the name
"mdp" ("_mdp" on platforms that prefix C symbols with underscores).

Format of the mdp_t struct:

#include "mdp/mdp.h"
#include "mdp/mdp_cpuflags.h"

typedef struct
{
	// Plugin version information.
	const uint32_t interfaceVersion;
	const uint32_t pluginVersion;
	
	// CPU flags.
	const uint32_t cpuFlagsSupported;
	const uint32_t cpuFlagsRequired;
	
	// UUID - each plugin must have a unique ID.
	const unsigned char uuid[16];
	
	// Description.
	mdp_desc_t *desc;
	
	// Functions.
	mdp_func_t *func;
} mdp_t;

Fields:

- interfaceVersion: The MDP interface version.

- pluginVersion: Version number of the specific plugin. This is user-defined
                 and can be anything.

- cpuFlagsSupported: [bitfield] CPU flags that are supported by the plugin.
                     The CPU flag values are defined in mdp_cpuflags.h.

- cpuFlagsRequired: [bitfield] CPU flags that are required by the plugin. If
                    the current CPU does not support any flags specified in
                    this field, the plugin will not be loaded.

- uuid: 16-byte UUID used to uniquely identify the plugin. Use a tool such as
        uuidgen to generate the UUID.

- desc: Pointer to mdp_desc_t with description information about the plugin.

- func: Pointer to a struct containing various plugin functions.

----------------------------------------------------------------

4.1. MDP Description Field

The mdp_t.desc field points to a struct of type mdp_desc_t, which contains
a description of the plugin.

Note: All strings are encoded using UTF-8.

#include "mdp/mdp.h"

typedef struct
{
	const char* name;
	const char* author_mdp;
	const char* author_orig;
	const char* description;
	const char* website;
	const char* license;
	
	// Filler for alignment purposes.
	const void* reserved1;
	const void* reserved2;
	
	// Icon data. (PNG format)
	const unsigned char* icon;
	const unsigned int iconLength;
} mdp_desc_t;

Fields:

- name: Name of the plugin.

- author_mdp: Author of the plugin.

- author_orig: Author of the original code. This is mainly used when porting
               a third-party renderer in an MDP plugin. If the plugin author
               is the same as the code author, this field may be set to NULL.

- description: A short description of the plugin.

- website: The plugin author's website. May be NULL if no website is available.

- license: Plugin license. Example licenses are "GPL-2", "GPL-3", "BSD".
           See mdp.h's MDP_LICENSE_* #defines for more.

- reserved1: Reserved.

- reserved2: Reserved.

- icon: Icon for the plugin. This must be a 32x32 PNG-format icon.
        Alternatively, this field may be set to NULL to indicate no icon.

- iconLength: Length of the data pointed to by the icon field.

----------------------------------------------------------------

4.2. MDP Function Field [MDP_VERSION(1, 0, 0)]

The mdp_t.func field points to a struct of type mdp_func_t, which contains
several pointers to functions within the plugin.

#include "mdp/mdp.h"

typedef void (MDP_FNCALL *mdp_init)(MDP_Host_t *host_srv);
typedef void (MDP_FNCALL *mdp_end)(void);

typedef struct
{
	// Init/Shutdown functions
	mdp_init	init;
	mdp_end		end;
} mdp_func_t;

Fields:

- init: Pointer to a function used to initialize the plugin.
        This function is called at Gens startup. The host_srv parameter
        contains a pointer to MDP Host Services.

- end: Pointer to a function used to shut down the plugin.
       This function is called at Gens shutdown.

----------------------------------------------------------------

4.3. MDP Host Services [MDP_VERSION(1, 0, 0)]

The mdp_func_t.init() function has one parameter, host_srv, which is a pointer
to a struct containing various services offered by the MDP host.

#include "mdp/mdp_host.h"

typedef struct
{
	const uint32_t interfaceVersion;
	
	void* (MDP_FNCALL *ptr_ref)(uint32_t ptrID);
	int   (MDP_FNCALL *ptr_unref)(uint32_t ptrID);
	
	int (MDP_FNCALL *val_set)(uint32_t valID, int val);
	int (MDP_FNCALL *val_get)(uint32_t valID);
	
	int (MDP_FNCALL *renderer_register)(struct mdp_t *plugin, MDP_Render_t *renderer);
	int (MDP_FNCALL *renderer_unregister)(struct mdp_t *plugin, MDP_Render_t *renderer);
	
	int (MDP_FNCALL *menu_item_add)(struct mdp_t *plugin, mdp_menu_handler_fn handler, int menu_id, const char *text);
	int (MDP_FNCALL *menu_item_remove)(struct mdp_t *plugin, int menu_item_id);
	int (MDP_FNCALL *menu_item_set_text)(struct mdp_t *plugin, int menu_item_id, const char *text);
	int (MDP_FNCALL *menu_item_get_text)(struct mdp_t *plugin, int menu_item_id, char *text_buf, int size);
	int (MDP_FNCALL *menu_item_set_checked)(struct mdp_t *plugin, int menu_item_id, int checked);
	int (MDP_FNCALL *menu_item_get_checked)(struct mdp_t *plugin, int menu_item_id);
	
	// Event handler functions.
	int (MDP_FNCALL *event_register)(struct mdp_t *plugin, int event_id, mdp_event_handler_fn handler);
	int (MDP_FNCALL *event_unregister)(struct mdp_t *plugin, int event_id, mdp_event_handler_fn handler);
} MDP_Host_t;

Fields:

- interfaceVersion: MDP interface version supported by the host program.

Pointers: (See section 4.3.1) [DEPRECATED; to be removed before MDP v1.0.0]

- ptr_ref: Function to reference a Gens pointer.

- ptr_unref: Function to unreference a Gens pointer. This function must be
             called for any pointers referenced with refPtr() by the plugin
             when the plugin is shut down.

Values: (See section 4.3.2)
- val_set: Set an MDP value.
- val_get: Get an MDP value.

Renderers: (See section 4.3.3)
- renderer_register: Register a renderer plugin.
- renderer_unregister: Unregister a renderer plugin.

Menu Items: (See section 4.3.4)
- menu_item_add: Add a menu item.
- menu_item_remove: Remove a menu item.
- menu_item_set_text: Set a menu item's text.
- menu_item_get_text: Get a menu item's text.
- menu_item_set_checked: Set a menu item's checked state.
- menu_item_get_checked: Get a menu item's checked state.

Event Handlers: (See section 4.3.5)
- event_register: Register an event handler.
- event_unregister: Unregister an event handler.

----------------------------------------------------------------

4.3.1. Pointer Referencing [MDP_VERSION(1, 0, 0)]

The host service functions ptr_ref and ptr_unref are used to reference and
unreference pointer to various aspects of the emulator. The pointer is
selected by using a value from the MDP_PTR enum.

typedef enum
{
	MDP_PTR_NULL		= 0,
	MDP_PTR_LUT16to32	= 1,
	MDP_PTR_RGB16toYUV	= 2,
	MDP_PTR_ROM_MD		= 3, /* BE */
	MDP_PTR_ROM_32X		= 4, /* LE */
	MDP_PTR_RAM_MD		= 5,
	MDP_PTR_RAM_VDP		= 6,
	MDP_PTR_RAM_Z80		= 7,
	MDP_PTR_RAM_MCD_PRG	= 8, /* unknown */
	MDP_PTR_RAM_MCD_WORD1M	= 9, /* unknown */
	MDP_PTR_RAM_MCD_WORD2M	= 10, /* unknown */
	MDP_PTR_RAM_32X		= 11, /* LE */
} MDP_PTR;

Note: All ROM/RAM data is stored in 16-bit host-endian. That is, you can read
16-bit values from the ROM and RAM buffers normally, but 8-bit reads may
require XOR'ing the address with 1. This is required if reading an 8-bit value
on x86 from MDP_PTR_ROM_MD, but not from MDP_PTR_ROM_32X. (MDP_PTR_ROM_32X is
a byteswapped version of the ROM used for 32X emulation, since the SH2 CPU is
little-endian.)

Items:

- MDP_PTR_NULL: NULL.

- MDP_PTR_LUT16to32: A lookup table for converting 16-bit color to 32-bit color.
  Original Definition: unsigned int LUT16to32[65536];

  To convert a 16-bit color to a 32-bit color, use the 16-bit color value as
  the table offset. The value stored at that offset is the 32-bit color value.

- MDP_PTR_RGB16toYUV: A lookup table for converting 16-bit RGB to YUV valus.
  This is mainly used for hq?x plugins.

- MDP_PTR_ROM_MD: MD ROM. Check MDP_VAL_ROM_SIZE for the loaded ROM size.
- MDP_PTR_ROM_32X: 32X ROM. Check MDP_VAL_ROM_SIZE for the loaded ROM size.
- MDP_PTR_RAM_MD: MD RAM. Size: 64k
- MDP_PTR_RAM_VDP: VDP RAM. Size: 64k
- MDP_PTR_RAM_Z80: Z80 RAM. Size: 8k
- MDP_PTR_RAM_MCD_PRG: SegaCD PRG RAM. Size: 512k
- MDP_PTR_RAM_MCD_WORD1M: Word RAM, 1M mode. Size: 256k (TODO: What's the difference?)
- MDP_PTR_RAM_MCD_WORD2M: Word RAM, 2M mode. Size: 256k (TODO: What's the difference?)
- MDP_PTR_RAM_32X: 32X RAM. Size: 256k

----------------------------------------------------------------

4.3.2. Values [MDP_VERSION(1, 0, 0)]

TODO

----------------------------------------------------------------

4.3.3. MDP Render Plugins [MDP_VERSION(1, 0, 0)]

Render plugins are used to render the original Genesis display to the main
video display. The basic renderers, Normal and Double, merely do a blit or
a 2x scaled blit, respectively. More advanced renderers can apply
interpolation and scanline effects in order to improve the output of the
image on high-resolution monitors.

To register a renderer, a plugin can call the following function in its
initialization function:

host_srv->renderer_register(&mdp, &mdp_render_t);

where mdp is the mdp_t struct and mdp_render_t is the MDP_Render_t struct.

The MDP_Render_t struct contains information about the renderer:

#include "mdp/mdp_render.h"

typedef void (MDP_FNCALL *MDP_Render_Fn)(MDP_Render_Info_t *renderInfo);
typedef struct
{
	const uint32_t interfaceVersion;
	mdp_render_fn blit;
	const int scale;
	const uint32_t flags;
	const char* tag;
} MDP_Render_t;

Fields:

- interfaceVersion: Interface version of the MDPT_RENDER plugin.
                    The MDP_RENDER_INTERFACE_VERSION macro in mdp_render.h
                    defines the current render interface version.

- blit: Pointer to a function of type mdp_render_fn. This function is called
        after every frame to blit the MD image to the output display.

- scale: Scaling factor of the renderer. For the "Normal" renderer, this would
         be set to 1, while for the "Double" renderer, this would be set to 2.

- flags: Renderer flags. [bitfield]

- tag: Renderer tag. This string is what shows up in the "Render" menu.
       (Note: This string is encoded using UTF-8.)

The MDP_Render_t.flags field can be a combination of the following flags:

- MDP_RENDER_FLAG_SRC16DST32: Indicates that the renderer only supports 16-bit
                              color. Gens will convert the output to 32-bit
                              color, if necessary.

The MDP_Render_t.blit function must point to a function of type MDP_Render_fn.
For example, the Normal renderer has this function:

void MDP_FNCALL mdp_render_1x_cpp(MDP_Render_Info_t *renderInfo);

The MDP_Render_Info_t struct contains the current rendering information, as
provided by the emulator.

#include "mdp/mdp_render.h"

typedef struct
{
	void *destScreen;
	void *mdScreen;
	
	int destPitch;
	int srcPitch;
	
	int width;
	int height;
	
	uint32_t bpp;
	uint32_t cpuFlags;
	uint32_t renderFlags;
} MDP_Render_Info_t;

Fields:

- destScreen: Pointer to the destination screen buffer.

- mdScreen: Pointer to the source screen buffer.

- destPitch: Pitch of the destination screen buffer.
             (Number of bytes per row.)

- srcPitch: Pitch of the source screen buffer.
            (Number of bytes per row.)

- width: Width of the image to blit.

- height: Height of the image to blit.

- bpp: Color depth of both destScreen and mdScreen.

- cpuFlags: CPU flags supported by the current CPU.

- renderFlags: Currently unused.

Note that the width of the image might not be the same as the pitch of
the image. This is especially true with regards to the mdScreen buffer
(Gens uses a pitch of 336 pixels) and destScreen on some platforms.

All renderers *must* support 15-bit (RGB555) and 16-bit (RGB565). 15-bit
color is required because some older video cards don't actually support
16-bit color, and use RGB555 mode instead, even if it reports that it's
running in 16-bit color. Regardless of the actual RGB5?5 mode, both of
these color depths use 2 bytes per pixel.

The plugin should also support 32-bit color, but in cases where this is
not possible. the MDP_Render_t.flags field can have the
MDP_RENDER_FLAG_SRC16DST32 flag set.

32-bit color format: 0x00BBGGRR (big-endian notation)

The MDP_Render_Info_t.renderFlags field is currently unused in this version
of the MDP Render interface.

----------------------------------------------------------------

4.3.4. Menu Items [MDP_VERSION(1, 0, 0)]

TODO

----------------------------------------------------------------

4.3.5. Event Handlers [MDP_VERSION(1, 0, 0)]

TODO

================================================================

End of MDP Interface Specification Version 1.0.0-draft.
