diff options
Diffstat (limited to 'src/libs/cdp')
-rw-r--r-- | src/libs/cdp/Makeinfo | 3 | ||||
-rw-r--r-- | src/libs/cdp/cdp.c | 437 | ||||
-rw-r--r-- | src/libs/cdp/cdp.h | 47 | ||||
-rw-r--r-- | src/libs/cdp/cdp_alli.h | 31 | ||||
-rw-r--r-- | src/libs/cdp/cdp_iio.h | 50 | ||||
-rw-r--r-- | src/libs/cdp/cdp_imem.h | 42 | ||||
-rw-r--r-- | src/libs/cdp/cdp_isnd.h | 43 | ||||
-rw-r--r-- | src/libs/cdp/cdp_ivid.h | 43 | ||||
-rw-r--r-- | src/libs/cdp/cdpapi.c | 864 | ||||
-rw-r--r-- | src/libs/cdp/cdpapi.h | 154 | ||||
-rw-r--r-- | src/libs/cdp/cdpint.h | 48 | ||||
-rw-r--r-- | src/libs/cdp/cdpmod.h | 92 | ||||
-rw-r--r-- | src/libs/cdp/windl.c | 76 | ||||
-rw-r--r-- | src/libs/cdp/windl.h | 37 |
14 files changed, 1967 insertions, 0 deletions
diff --git a/src/libs/cdp/Makeinfo b/src/libs/cdp/Makeinfo new file mode 100644 index 0000000..b2a83b5 --- /dev/null +++ b/src/libs/cdp/Makeinfo @@ -0,0 +1,3 @@ +uqm_CFILES="cdp.c cdpapi.c" +uqm_HFILES="cdp_alli.h cdpapi.h cdp.h cdp_iio.h cdp_imem.h cdpint.h + cdp_isnd.h cdp_ivid.h cdpmod.h windl.h" diff --git a/src/libs/cdp/cdp.c b/src/libs/cdp/cdp.c new file mode 100644 index 0000000..ca9536e --- /dev/null +++ b/src/libs/cdp/cdp.c @@ -0,0 +1,437 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP library definitions + */ + +#include <string.h> +#include <stdio.h> +#include "cdp.h" +#include "port.h" +#include "cdpint.h" +#include "cdpmod.h" +#include "uio.h" +#include "uqmversion.h" +#ifdef WIN32 +# include "windl.h" +#else +# include <dlfcn.h> +#endif + +#define MAX_CDPS 63 +#define CDPDIR "cdps" + +// internal CDP module representation +struct cdp_Module +{ + bool builtin; // used at least once indicator + bool used; // used at least once indicator + void* hmodule; // loaded module handle + uint32 refcount; // reference count + cdp_ModuleInfo* info; // cdp exported info + +}; + +// Kernel module info +// not a real module, and not loadable either +// this just provides information to other modules +cdp_ModuleInfo cdp_kernel_info = +{ + sizeof (cdp_ModuleInfo), + CDPAPI_VERSION, // API version we are using + UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, + UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, + CDP_MODINFO_RESERVED1, + "UQM", // CDP context cannonical name + "UQM Kernel", // CDP mod name +# define S(i) #i + // CDP mod version + S(UQM_MAJOR_VERSION) "." S(UQM_MINOR_VERSION) UQM_EXTRA_VERSION, +# undef S + "UQM Team", // CDP mod author + "http://sc2.sf.net", // CDP mod URL + "Eternal doctrine executor", // CDP mod comment + CDP_MODINFO_RESERVED2, + NULL, NULL // no entrypoints defined/needed +}; + +static cdp_Module cdp_modules[MAX_CDPS + 1] = +{ + {true, true, NULL, 1, &cdp_kernel_info}, + + {false, false, NULL, 0, NULL} // term +}; + +extern uio_DirHandle *cdpDir; + +static bool cdp_inited = false; +static cdp_Error cdp_last_error = CDPERR_NONE; +static char cdp_path[PATH_MAX] = ""; + +cdp_Error +cdp_GetError (void) +{ + cdp_Error ret = cdp_last_error; + cdp_last_error = CDPERR_NONE; + return ret; +} + +bool +cdp_Init (void) +{ + int i; + void* hkernel; + + if (cdp_inited) + { + fprintf (stderr, "cdp_Init(): called when already inited\n"); + return true; + } + + // preprocess built-in modules + hkernel = dlopen (NULL, RTLD_LAZY); + + for (i = 0; cdp_modules[i].builtin; ++i) + cdp_modules[i].hmodule = hkernel; + + // clear the rest + //memset (cdp_modules + i, 0, + // sizeof (cdp_modules) - sizeof (cdp_Module) * i); + + //strcpy (cdp_path, cdpDir->path); + cdp_InitApi (); + cdp_inited = true; + + return true; +} + +void +cdp_Uninit (void) +{ + if (!cdp_inited) + { + fprintf (stderr, "cdp_Uninit(): called when not inited\n"); + return; + } + + cdp_UninitApi (); + cdp_FreeAllModules (); + cdp_inited = false; +} + +cdp_Module* +cdp_LoadModule (const char* modname) + // special value for modname: NULL - refers to kernel (UQM exe) +{ + void* mod; + char modpath[PATH_MAX]; + const char* errstr; + cdp_ModuleInfo* info; + int i; + cdp_Module* cdp; + cdp_Module* newslot = 0; + cdp_Itf* ihost; + + if (modname == NULL) + return cdp_modules; + + if (!cdp_inited) + { + fprintf (stderr, "cdp_LoadModule(): called when not inited\n"); + return 0; + } + + // load dynamic lib + sprintf (modpath, "%s/%s%s", CDPDIR, modname, CDPEXT); + mod = dlopen (modpath, RTLD_NOW); + if (!mod) + { + cdp_last_error = CDPERR_NOT_FOUND; + return NULL; + } + + // look it up in already loaded + for (i = 0, cdp = cdp_modules; cdp->used && cdp->hmodule != mod; + ++cdp, ++i) + { + // and pick up an empty slot (where available) + if (!newslot && !cdp->hmodule) + newslot = cdp; + } + if (i >= MAX_CDPS) + { + fprintf (stderr, "cdp_LoadModule(): " + "CDPs limit reached while loading %s\n", + modname); + dlclose (mod); + cdp_last_error = CDPERR_TOO_MANY; + return NULL; + } + + if (cdp->hmodule) + { // module has already been loaded + cdp->refcount++; + return cdp; + } + + dlerror (); // clear any error + info = dlsym (mod, CDP_INFO_SYM_NAME); + if (!info && (errstr = dlerror ())) + { + dlclose (mod); + cdp_last_error = CDPERR_BAD_MODULE; + return NULL; + } + + if (info->size < CDP_MODINFO_MIN_SIZE || info->api_ver > CDPAPI_VERSION) + { + fprintf (stderr, "cdp_LoadModule(): " + "CDP %s is invalid or newer API version\n", + modname); + dlclose (mod); + cdp_last_error = CDPERR_UNKNOWN_VER; + return NULL; + } + + ihost = cdp_GetInterface (CDPITF_KIND_HOST, info->api_ver); + if (!ihost) + { + fprintf (stderr, "cdp_LoadModule(): " + "CDP %s requested unsupported API version 0x%08x\n", + modname, info->api_ver); + dlclose (mod); + cdp_last_error = CDPERR_UNKNOWN_VER; + return NULL; + } + + if (!newslot) + { + newslot = cdp; + newslot->used = true; + // make next one a term + cdp[1].builtin = false; + cdp[1].used = false; + cdp[1].hmodule = NULL; + cdp[1].refcount = 0; + } + newslot->hmodule = mod; + newslot->refcount = 1; + newslot->info = info; + + if (!info->module_init (newslot, (cdp_Itf_Host*)ihost)) + { + fprintf (stderr, "cdp_LoadModule(): " + "CDP %s failed to init\n", + modname); + dlclose (mod); + newslot->hmodule = NULL; + newslot->info = NULL; + newslot->refcount = 0; + cdp_last_error = CDPERR_INIT_FAILED; + return NULL; + } + + + return newslot; +} + +cdp_Module* +cdp_CheckModule (cdp_Module* module) +{ + if (module < cdp_modules || module >= cdp_modules + MAX_CDPS || + !module->hmodule || !module->info) + return NULL; + else + return module; +} + +void +cdp_FreeModule (cdp_Module* module) +{ + cdp_Module* modslot = cdp_CheckModule (module); + + if (!modslot || modslot->builtin) + return; + + modslot->refcount--; + if (modslot->refcount == 0) + modslot->info->module_term (); + + dlclose (modslot->hmodule); + + if (modslot->refcount == 0) + { + modslot->hmodule = NULL; + modslot->info = NULL; + } +} + +const char* +cdp_GetModuleContext (cdp_Module* module, bool bMetaString) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (bMetaString) + { + if (!modslot) + return "(Error)"; + if (!modslot->info->context_name) + return "(Null)"; + } + else if (!modslot) + { + return NULL; + } + return modslot->info->context_name; +} + +const char* +cdp_GetModuleName (cdp_Module* module, bool bMetaString) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (bMetaString) + { + if (!modslot) + return "(Error)"; + if (!modslot->info->name) + return "(Null)"; + } + else if (!modslot) + { + return NULL; + } + return modslot->info->name; +} + +uint32 +cdp_GetModuleVersion (cdp_Module* module) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (!modslot) + return 0; + return (modslot->info->ver_major << 16) | modslot->info->ver_minor; +} + +const char* +cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (bMetaString) + { + if (!modslot) + return "(Error)"; + if (!modslot->info->ver_string) + return "(Null)"; + } + else if (!modslot) + { + return NULL; + } + return modslot->info->ver_string; +} + +const char* +cdp_GetModuleComment (cdp_Module* module, bool bMetaString) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (bMetaString) + { + if (!modslot) + return "(Error)"; + if (!modslot->info->comments) + return "(Null)"; + } + else if (!modslot) + { + return NULL; + } + return modslot->info->comments; +} + +// load-all and free-all are here temporarily until +// configs are in place +int +cdp_LoadAllModules (void) +{ + uio_DirList *dirList; + int nummods = 0; + int i; + + if (!cdp_inited) + { + fprintf (stderr, "cdp_LoadAllModules(): called when not inited\n"); + return 0; + } + + if (!cdpDir) + return 0; + + fprintf (stderr, "Loading all CDPs...\n"); + + dirList = uio_getDirList (cdpDir, "", CDPEXT, match_MATCH_SUFFIX); + if (!dirList) + return 0; + + for (i = 0; i < dirList->numNames; i++) + { + char modname[PATH_MAX]; + char* pext; + cdp_Module* mod; + + fprintf (stderr, "Loading CDP %s...\n", dirList->names[i]); + strcpy (modname, dirList->names[i]); + pext = strrchr (modname, '.'); + if (pext) // strip extension + *pext = 0; + + mod = cdp_LoadModule (modname); + if (mod) + { + nummods++; + fprintf (stderr, "\tloaded CDP: %s v%s (%s)\n", + cdp_GetModuleName (mod, true), + cdp_GetModuleVersionString (mod, true), + cdp_GetModuleComment (mod, true)); + } + else + { + fprintf (stderr, "\tload failed, error %u\n", + cdp_GetError ()); + } + } + uio_freeDirList (dirList); + + return nummods; +} + +void +cdp_FreeAllModules (void) +{ + cdp_Module* cdp; + + if (!cdp_inited) + { + fprintf (stderr, "cdp_FreeAllModules(): called when not inited\n"); + return; + } + + for (cdp = cdp_modules; cdp->used; ++cdp) + { + if (!cdp->builtin && cdp->hmodule) + cdp_FreeModule (cdp); + } +} diff --git a/src/libs/cdp/cdp.h b/src/libs/cdp/cdp.h new file mode 100644 index 0000000..0390f07 --- /dev/null +++ b/src/libs/cdp/cdp.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP library declarations + */ + +#ifndef LIBS_CDP_CDP_H_ +#define LIBS_CDP_CDP_H_ + +#include "types.h" +#include "cdpapi.h" + +// these will be called by the UQM engine +// and plugins manager +bool cdp_Init (void); +void cdp_Uninit (void); +cdp_Error cdp_GetError (void); +cdp_Module* cdp_LoadModule (const char* modname); +void cdp_FreeModule (cdp_Module* module); +// in the following calls when bMetaString is set +// function will never return a NULL, instead it will +// return a valid string -- error meta-string +const char* cdp_GetModuleContext (cdp_Module* module, bool bMetaString); +const char* cdp_GetModuleName (cdp_Module* module, bool bMetaString); +uint32 cdp_GetModuleVersion (cdp_Module* module); +const char* cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString); +const char* cdp_GetModuleComment (cdp_Module* module, bool bMetaString); + +int cdp_LoadAllModules (void); +void cdp_FreeAllModules (void); + +#endif /* LIBS_CDP_CDP_H_ */ diff --git a/src/libs/cdp/cdp_alli.h b/src/libs/cdp/cdp_alli.h new file mode 100644 index 0000000..31520e5 --- /dev/null +++ b/src/libs/cdp/cdp_alli.h @@ -0,0 +1,31 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP All-interface list (for simplicity) + */ + +#ifndef LIBS_CDP_CDP_ALLI_H_ +#define LIBS_CDP_CDP_ALLI_H_ + +#include "cdp_iio.h" +#include "cdp_imem.h" +#include "cdp_isnd.h" +#include "cdp_ivid.h" +// TODO: add more cdp_iXXX.h here as they are defined + +#endif /* LIBS_CDP_CDP_ALLI_H_ */ diff --git a/src/libs/cdp/cdp_iio.h b/src/libs/cdp/cdp_iio.h new file mode 100644 index 0000000..19e6513 --- /dev/null +++ b/src/libs/cdp/cdp_iio.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP Unified IO Interface + */ + +#ifndef LIBS_CDP_CDP_IIO_H_ +#define LIBS_CDP_CDP_IIO_H_ + +#include "types.h" +#include "libs/uio.h" + +// CDP IO Interface entry points +typedef struct +{ + uio_Stream* (* fopen) (uio_DirHandle *dir, const char *path, + const char *mode); + int (* fclose) (uio_Stream *stream); + size_t (* fread) (void *buf, size_t size, size_t nmemb, + uio_Stream *stream); + size_t (* fwrite) (const void *buf, size_t size, size_t nmemb, + uio_Stream *stream); + int (* fseek) (uio_Stream *stream, long offset, int whence); + long (* ftell) (uio_Stream *stream); + int (* fflush) (uio_Stream *stream); + int (* feof) (uio_Stream *stream); + int (* ferror) (uio_Stream *stream); + +} cdp_Itf_IoVtbl_v1; + +// the following are for the sake of module writers +typedef cdp_Itf_IoVtbl_v1 cdp_Itf_IoVtbl; +typedef cdp_Itf_IoVtbl cdp_Itf_Io; + +#endif /* LIBS_CDP_CDP_IIO_H_ */ diff --git a/src/libs/cdp/cdp_imem.h b/src/libs/cdp/cdp_imem.h new file mode 100644 index 0000000..7d1b59c --- /dev/null +++ b/src/libs/cdp/cdp_imem.h @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP Memory Interface + */ + +#ifndef LIBS_CDP_CDP_IMEM_H_ +#define LIBS_CDP_CDP_IMEM_H_ + +#include "types.h" +#include "libs/memlib.h" + +// CDP Memory Interface entry points +typedef struct +{ + void* (* malloc) (int size); + void (* free) (void *p); + void* (* calloc) (int size); + void* (* realloc) (void *p, int size); + +} cdp_Itf_MemoryVtbl_v1; + +// the following are for the sake of module writers +typedef cdp_Itf_MemoryVtbl_v1 cdp_Itf_MemoryVtbl; +typedef cdp_Itf_MemoryVtbl cdp_Itf_Memory; + +#endif /* LIBS_CDP_CDP_IMEM_H_ */ diff --git a/src/libs/cdp/cdp_isnd.h b/src/libs/cdp/cdp_isnd.h new file mode 100644 index 0000000..ae4aa94 --- /dev/null +++ b/src/libs/cdp/cdp_isnd.h @@ -0,0 +1,43 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP Sound Interface + */ + +#ifndef LIBS_CDP_CDP_ISND_H_ +#define LIBS_CDP_CDP_ISND_H_ + +#include "types.h" +#include "libs/sound/sound.h" +#include "libs/sound/decoders/decoder.h" + +// CDP Sound Interface entry points +typedef struct +{ + TFB_RegSoundDecoder* (* RegisterDecoder) (const char* fileext, + TFB_SoundDecoderFuncs*); + void (* UnregisterDecoder) (TFB_RegSoundDecoder*); + const TFB_SoundDecoderFuncs* (* LookupDecoder) (const char* fileext); + +} cdp_Itf_SoundVtbl_v1; + +// the following are for the sake of module writers +typedef cdp_Itf_SoundVtbl_v1 cdp_Itf_SoundVtbl; +typedef cdp_Itf_SoundVtbl cdp_Itf_Sound; + +#endif /* LIBS_CDP_CDP_ISND_H_ */ diff --git a/src/libs/cdp/cdp_ivid.h b/src/libs/cdp/cdp_ivid.h new file mode 100644 index 0000000..a9fc0b2 --- /dev/null +++ b/src/libs/cdp/cdp_ivid.h @@ -0,0 +1,43 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP Video Interface + */ + +#ifndef LIBS_CDP_CDP_IVID_H_ +#define LIBS_CDP_CDP_IVID_H_ + +#include "types.h" +#include "libs/video/video.h" +#include "libs/video/videodec.h" + +// CDP Video Interface entry points +typedef struct +{ + TFB_RegVideoDecoder* (* RegisterDecoder) (const char* fileext, + TFB_VideoDecoderFuncs*); + void (* UnregisterDecoder) (TFB_RegVideoDecoder*); + const TFB_VideoDecoderFuncs* (* LookupDecoder) (const char* fileext); + +} cdp_Itf_VideoVtbl_v1; + +// the following are for the sake of module writers +typedef cdp_Itf_VideoVtbl_v1 cdp_Itf_VideoVtbl; +typedef cdp_Itf_VideoVtbl cdp_Itf_Video; + +#endif /* LIBS_CDP_CDP_IVID_H_ */ diff --git a/src/libs/cdp/cdpapi.c b/src/libs/cdp/cdpapi.c new file mode 100644 index 0000000..e50e39d --- /dev/null +++ b/src/libs/cdp/cdpapi.c @@ -0,0 +1,864 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP API definitions + * the API is used by both the engine and modules + */ + +#include "cdp.h" +#include "port.h" +#include "cdpint.h" +#include "uqmversion.h" + +#define MAX_REG_ITFS 255 +#define MAX_REG_EVENTS 1023 + +static cdp_Error cdp_api_error = CDPERR_NONE; + +static uint32 cdp_Host_GetApiVersion (void); +static uint32 cdp_Host_GetVersion (void); +static cdp_Error cdp_Host_GetApiError (void); +static cdp_Itf* cdp_Host_GetItf (const char* name); +static bool cdp_Host_GetItfs (cdp_ItfDef* defs); +static cdp_ItfReg* cdp_Host_RegisterItf (const char* name, + cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, + cdp_Itf*, cdp_Module*); +static void cdp_Host_UnregisterItf (cdp_ItfReg*); +static bool cdp_Host_RegisterItfs (cdp_ItfDef* defs, cdp_Module*); +static void cdp_Host_UnregisterItfs (cdp_ItfDef* defs); +static cdp_Event cdp_Host_GetEvent (const char* name); +static bool cdp_Host_GetEvents (cdp_EventDef* defs); +static cdp_EventReg* cdp_Host_RegisterEvent (const char* name, cdp_Module*); +static void cdp_Host_UnregisterEvent (cdp_EventReg*); +static bool cdp_Host_RegisterEvents (cdp_EventDef* defs, cdp_Module*); +static void cdp_Host_UnregisterEvents (cdp_EventDef* defs); +static bool cdp_Host_SubscribeEvent (cdp_Event, cdp_EventProc, cdp_Module*); +static void cdp_Host_UnsubscribeEvent (cdp_Event, cdp_EventProc); +static bool cdp_Host_SubscribeEvents (cdp_EventDef* defs, cdp_Module*); +static void cdp_Host_UnsubscribeEvents (cdp_EventDef* defs); +static cdp_EventResult cdp_Host_FireEvent (cdp_EventReg*, uint32, void*); + +// Interfaces +cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 = +{ + cdp_Host_GetApiVersion, + cdp_Host_GetVersion, + cdp_Host_GetApiError, + cdp_Host_GetItf, + cdp_Host_GetItfs, + cdp_Host_RegisterItf, + cdp_Host_UnregisterItf, + cdp_Host_RegisterItfs, + cdp_Host_UnregisterItfs, + cdp_Host_GetEvent, + cdp_Host_GetEvents, + cdp_Host_RegisterEvent, + cdp_Host_UnregisterEvent, + cdp_Host_RegisterEvents, + cdp_Host_UnregisterEvents, + cdp_Host_SubscribeEvent, + cdp_Host_UnsubscribeEvent, + cdp_Host_SubscribeEvents, + cdp_Host_UnsubscribeEvents, + cdp_Host_FireEvent, +}; + +cdp_Itf_MemoryVtbl_v1 cdp_memory_itf_v1 = +{ + HMalloc, + HFree, + HCalloc, + HRealloc, +}; + +cdp_Itf_IoVtbl_v1 cdp_io_itf_v1 = +{ + uio_fopen, + uio_fclose, + uio_fread, + uio_fwrite, + uio_fseek, + uio_ftell, + uio_fflush, + uio_feof, + uio_ferror, +}; + +cdp_Itf_SoundVtbl_v1 cdp_sound_itf_v1 = +{ + SoundDecoder_Register, + SoundDecoder_Unregister, + SoundDecoder_Lookup, +}; + +cdp_Itf_VideoVtbl_v1 cdp_video_itf_v1 = +{ + VideoDecoder_Register, + VideoDecoder_Unregister, + VideoDecoder_Lookup, +}; + +// the actual interface registration struct/handle +struct cdp_ItfReg +{ + bool builtin; + bool used; + const char* name; + cdp_ApiVersion ver_from; + cdp_ApiVersion ver_to; + cdp_Itf* itfvtbl; + cdp_Module* module; +}; + +#define CDP_DECLARE_ITF(kind,vf,vt,vtbl) \ + {true, true, CDPITF_KIND_##kind, \ + CDPAPI_VERSION_##vf, CDPAPI_VERSION_##vt, vtbl, NULL} + +// Built-in interfaces + space for loadable +cdp_ItfReg cdp_itfs[MAX_REG_ITFS + 1] = +{ + CDP_DECLARE_ITF (HOST, 1, 1, &cdp_host_itf_v1), + CDP_DECLARE_ITF (MEMORY, 1, 1, &cdp_memory_itf_v1), + CDP_DECLARE_ITF (IO, 1, 1, &cdp_io_itf_v1), + CDP_DECLARE_ITF (SOUND, 1, 1, &cdp_sound_itf_v1), + CDP_DECLARE_ITF (VIDEO, 1, 1, &cdp_video_itf_v1), + // TODO: put newly defined built-in interfaces here + + {false, false, "", 0, 0, NULL} // term +}; + +// event bind descriptor +typedef struct +{ + cdp_EventProc proc; + cdp_Module* module; + +} cdp_EventBind; + +#define EVENT_BIND_GROW 16 + +// the actual event registration struct/handle +struct cdp_EventReg +{ + bool builtin; + bool used; + const char* name; + cdp_EventBind* binds; + uint32 bindslots; + cdp_Module* module; +}; + +#define CDP_DECLARE_EVENT(name) \ + {true, true, "UQM." #name, NULL, 0, NULL} + +// Built-in events + space for loadable +// a cdp_Event handle is an index into this array +cdp_EventReg cdp_evts[MAX_REG_EVENTS + 1] = +{ + // sample - no real events defined yet + CDP_DECLARE_EVENT (PlanetSide.TouchDown), + CDP_DECLARE_EVENT (PlanetSide.LiftOff), + // TODO: put newly defined built-in events here + + {false, false, "", NULL, 0, NULL} // term +}; + +cdp_Error +cdp_GetApiError (void) +{ + cdp_Error ret = cdp_api_error; + cdp_api_error = CDPERR_NONE; + return ret; +} + +bool +cdp_InitApi (void) +{ + int i; + cdp_Module* kernel; + + // preprocess built-in itfs + kernel = cdp_LoadModule (NULL); + + for (i = 0; cdp_itfs[i].builtin; ++i) + { + cdp_itfs[i].module = kernel; + } + // clear the rest + //memset (cdp_itfs + i, 0, + // sizeof (cdp_itfs) - sizeof (cdp_ItfReg) * i); + + for (i = 0; cdp_evts[i].builtin; ++i) + { + cdp_evts[i].module = kernel; + cdp_evts[i].bindslots = 0; + cdp_evts[i].binds = NULL; + } + + return true; +} + +void +cdp_UninitApi (void) +{ + cdp_ItfReg* itf; + + // unregister custom interfaces + for (itf = cdp_itfs; itf->used; ++itf) + { + if (!itf->builtin) + { + itf->used = false; + if (itf->name) + HFree (itf->name); + itf->name = NULL; + itf->itfvtbl = NULL; + itf->module = NULL; + } + } +} + +static uint32 +cdp_Host_GetApiVersion (void) +{ + return CDPAPI_VERSION; +} + +static uint32 +cdp_Host_GetVersion (void) +{ + return (UQM_MAJOR_VERSION << 20) | (UQM_MINOR_VERSION << 15) | + UQM_PATCH_VERSION; +} + +static cdp_Error +cdp_Host_GetApiError (void) +{ + return cdp_GetApiError (); +} + +static char* +cdp_MakeContextName (const char* ctx, const char* name) +{ + int namelen; + char* id_name; + + namelen = strlen(ctx) + strlen(name) + 2; + id_name = HMalloc (namelen); + strcpy(id_name, ctx); + strcat(id_name, "."); + strcat(id_name, name); + + return id_name; +} + +/*********************************************************** + * Interface system * + ***********************************************************/ + +cdp_ItfReg* +cdp_GetInterfaceReg (const char* name, cdp_ApiVersion api_ver) +{ + cdp_ItfReg* itf; + + for (itf = cdp_itfs; itf->used && + (!itf->name || strcasecmp(itf->name, name) != 0 || + api_ver < itf->ver_from || api_ver > itf->ver_to); + itf++) + ; + if (!itf->name) + { + cdp_api_error = CDPERR_NO_ITF; + return NULL; + } + + return itf; +} + +cdp_Itf* +cdp_GetInterface (const char* name, cdp_ApiVersion api_ver) +{ + cdp_ItfReg* reg; + + reg = cdp_GetInterfaceReg (name, api_ver); + return reg ? reg->itfvtbl : NULL; +} + +static cdp_Itf* +cdp_Host_GetItf (const char* name) +{ + return cdp_GetInterface (name, CDPAPI_VERSION_1); +} + +static bool +cdp_Host_GetItfs (cdp_ItfDef* defs) +{ + cdp_ItfDef* def; + cdp_ItfReg* reg; + int errors = 0; + + for (def = defs; def->name; ++def) + { + // registration handle is not returned + def->reg = NULL; + + reg = cdp_GetInterfaceReg (def->name, CDPAPI_VERSION_1); + if (reg) + { + def->itf = reg->itfvtbl; + def->name = reg->name; // set to cannonical name + def->ver_from = reg->ver_from; + def->ver_to = reg->ver_to; + def->module = reg->module; + } + else + { + def->itf = NULL; + def->module = NULL; + def->ver_from = 0; + def->ver_to = 0; + ++errors; + } + } + + return !errors; +} + +static cdp_ItfReg* +cdp_Host_RegisterItf (const char* name, cdp_ApiVersion ver_from, + cdp_ApiVersion ver_to, cdp_Itf* itfvtbl, + cdp_Module* owner) +{ + cdp_ItfReg* itfreg; + cdp_ItfReg* newslot = NULL; + char* id_name; + const char* ctx; + + if (!owner) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "No owner info supplied\n"); + //return NULL; + } + if (!name || !*name || !itfvtbl) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "Null or invalid interface (from %s)\n", + cdp_GetModuleName (owner, true)); + return NULL; + } + ctx = cdp_GetModuleContext (owner, false); + if (!ctx) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "Null or invalid context (from %s)\n", + cdp_GetModuleName (owner, true)); + return NULL; + } + + // TODO: review version policy (below) + // enforce version policy and do not allow obsolete interfaces + // POLICY: all modules MUST be aware of recent API changes and will not + // be allowed to expose interfaces that support and/or utilize obsoleted + // API versions + if (ver_from < CDPAPI_VERSION_MIN) + ver_from = CDPAPI_VERSION_MIN; + if (ver_to < CDPAPI_VERSION_MIN) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "Obsolete interface %s (from %s)\n", + name, cdp_GetModuleName (owner, true)); + return NULL; + } + + id_name = cdp_MakeContextName (ctx, name); + + // check if interface already registered + for (itfreg = cdp_itfs; itfreg->used && + (!itfreg->name || strcasecmp(itfreg->name, id_name) != 0 || + ver_from < itfreg->ver_from || ver_to > itfreg->ver_to); + ++itfreg) + { + // and pick up an empty slot (where available) + if (!newslot && !itfreg->name) + newslot = itfreg; + } + + if (itfreg >= cdp_itfs + MAX_REG_ITFS) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "Interfaces limit reached\n"); + HFree (id_name); + return NULL; + } + else if (itfreg->name) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "Interface %s already registered for these versions, " + "%s denied\n", + name, cdp_GetModuleName (owner, true)); + HFree (id_name); + return NULL; + } + + if (!newslot) + { + newslot = itfreg; + newslot->used = true; + // make next one a term + itfreg[1].builtin = false; + itfreg[1].used = false; + itfreg[1].name = NULL; + itfreg[1].itfvtbl = NULL; + } + + newslot->name = id_name; + newslot->ver_from = ver_from; + newslot->ver_to = ver_to; + newslot->itfvtbl = itfvtbl; + newslot->module = owner; + + return newslot; +} + +static void +cdp_Host_UnregisterItf (cdp_ItfReg* itfreg) +{ + if (itfreg < cdp_itfs || itfreg >= cdp_itfs + MAX_REG_ITFS || + !itfreg->name || !itfreg->itfvtbl) + { + fprintf (stderr, "cdp_Host_UnregisterItf(): " + "Invalid or expired interface passed\n"); + return; + } + + if (!itfreg->builtin) + { + HFree (itfreg->name); + } + itfreg->module = NULL; + itfreg->name = NULL; + itfreg->itfvtbl = NULL; +} + +static bool +cdp_Host_RegisterItfs (cdp_ItfDef* defs, cdp_Module* owner) +{ + cdp_ItfDef* def; + int errors = 0; + + for (def = defs; def->name; ++def) + { + def->reg = cdp_Host_RegisterItf (def->name, def->ver_from, + def->ver_to, def->itf, owner); + if (def->reg) + { + def->module = owner; + } + else + { + def->module = NULL; + ++errors; + } + } + + return !errors; +} + +static void +cdp_Host_UnregisterItfs (cdp_ItfDef* defs) +{ + cdp_ItfDef* def; + + for (def = defs; def->name; ++def) + { + if (def->reg) + cdp_Host_UnregisterItf (def->reg); + } +} + +/*********************************************************** + * Event system * + ***********************************************************/ + +cdp_EventReg* +cdp_GetEventReg (const char* name) +{ + cdp_EventReg* evt; + + for (evt = cdp_evts; evt->used && + (!evt->name || strcasecmp(evt->name, name) != 0); + evt++) + ; + if (!evt->name) + { + cdp_api_error = CDPERR_NO_EVENT; + return NULL; + } + + return evt; +} + +// hopefully inlinable +static cdp_Event +cdp_EventFromReg (cdp_EventReg* reg) +{ + return (reg - cdp_evts) / sizeof (cdp_EventReg); +} + +// hopefully inlinable +static cdp_EventReg* +cdp_RegFromEvent (cdp_Event event) +{ + return cdp_evts + event; +} + +cdp_Event +cdp_GetEvent (const char* name) +{ + cdp_EventReg* reg; + + reg = cdp_GetEventReg (name); + return reg ? cdp_EventFromReg (reg) : CDP_EVENT_INVALID; +} + +static cdp_EventBind* +cdp_AllocEventBinds (cdp_EventBind* binds, uint32 ccur, uint32 cnew) +{ + cdp_EventBind* newbinds; + uint32 newsize; + + newsize = cnew * sizeof (cdp_EventBind); + if (binds) + newbinds = HRealloc (binds, newsize); + else + newbinds = HMalloc (newsize); + + if (cnew > ccur) + memset (newbinds + ccur, 0, + (cnew - ccur) * sizeof (cdp_EventBind)); + + return newbinds; +} + +static cdp_Event +cdp_Host_GetEvent (const char* name) +{ + return cdp_GetEvent (name); +} + +static bool +cdp_Host_GetEvents (cdp_EventDef* defs) +{ + cdp_EventDef* def; + cdp_EventReg* reg; + int errors = 0; + + for (def = defs; def->name; ++def) + { + // registration handle is not returned + def->reg = NULL; + + reg = cdp_GetEventReg (def->name); + if (reg) + { + def->event = cdp_EventFromReg(reg); + def->name = reg->name; // set to cannonical name + def->module = reg->module; + } + else + { + def->event = CDP_EVENT_INVALID; + def->module = NULL; + ++errors; + } + } + + return !errors; +} + +static cdp_EventReg* +cdp_Host_RegisterEvent (const char* name, cdp_Module* owner) +{ + cdp_EventReg* evtreg; + cdp_EventReg* newslot = NULL; + char* id_name; + const char* ctx; + + if (!owner) + { + fprintf (stderr, "cdp_Host_RegisterEvent(): " + "No owner info supplied\n"); + //return NULL; + } + if (!name || !*name) + { + fprintf (stderr, "cdp_Host_RegisterEvent(): " + "Null or invalid event (from %s)\n", + cdp_GetModuleName (owner, true)); + return NULL; + } + ctx = cdp_GetModuleContext (owner, false); + if (!ctx) + { + fprintf (stderr, "cdp_Host_RegisterEvent(): " + "Null or invalid context (from %s)\n", + cdp_GetModuleName (owner, true)); + return NULL; + } + + id_name = cdp_MakeContextName (ctx, name); + + // check if event already registered + for (evtreg = cdp_evts; evtreg->used && + (!evtreg->name || strcasecmp(evtreg->name, id_name) != 0); + ++evtreg) + { + // and pick up an empty slot (where available) + if (!newslot && !evtreg->name) + newslot = evtreg; + } + + if (evtreg >= cdp_evts + MAX_REG_EVENTS) + { + fprintf (stderr, "cdp_Host_RegisterEvent(): " + "Event limit reached\n"); + HFree (id_name); + return NULL; + } + else if (evtreg->name) + { + fprintf (stderr, "cdp_Host_RegisterEvent(): " + "Event %s already registered, " + "%s denied\n", + name, cdp_GetModuleName (owner, true)); + HFree (id_name); + return NULL; + } + + if (!newslot) + { + newslot = evtreg; + newslot->used = true; + // make next one a term + evtreg[1].builtin = false; + evtreg[1].used = false; + evtreg[1].name = NULL; + } + + newslot->name = id_name; + newslot->module = owner; + newslot->binds = NULL; + newslot->bindslots = 0; + + return newslot; +} + +static void +cdp_Host_UnregisterEvent (cdp_EventReg* evtreg) +{ + if (evtreg < cdp_evts || evtreg >= cdp_evts + MAX_REG_EVENTS || + !evtreg->name) + { + fprintf (stderr, "cdp_Host_UnregisterEvent(): " + "Invalid or expired event passed\n"); + return; + } + + if (!evtreg->builtin) + { + HFree (evtreg->name); + } + evtreg->module = NULL; + evtreg->name = NULL; + if (evtreg->binds) + HFree (evtreg->binds); + evtreg->binds = NULL; + evtreg->bindslots = 0; +} + +static bool +cdp_Host_RegisterEvents (cdp_EventDef* defs, cdp_Module* owner) +{ + cdp_EventDef* def; + int errors = 0; + + for (def = defs; def->name; ++def) + { + def->reg = cdp_Host_RegisterEvent (def->name, owner); + if (def->reg) + { + def->module = owner; + } + else + { + def->module = NULL; + ++errors; + } + } + + return !errors; +} + +static void +cdp_Host_UnregisterEvents (cdp_EventDef* defs) +{ + cdp_EventDef* def; + + for (def = defs; def->name; ++def) + { + if (def->reg) + cdp_Host_UnregisterEvent (def->reg); + } +} + +static bool +cdp_Host_SubscribeEvent (cdp_Event event, cdp_EventProc proc, cdp_Module* module) +{ + cdp_EventReg* reg = cdp_RegFromEvent (event); + cdp_EventBind* bind = NULL; + uint32 i; + + if (reg < cdp_evts || reg >= cdp_evts + MAX_REG_EVENTS || + !reg->name) + { + fprintf (stderr, "cdp_Host_SubscribeEvent(): " + "Invalid or expired event passed\n"); + return false; + } + + if (reg->binds) + { + // check for duplicate or find a new slot + for (i = 0, bind = reg->binds; i < reg->bindslots && + (!bind->proc || bind->proc != proc); + ++i, ++bind) + ; + if (i >= reg->bindslots) + { // full - add more slots + reg->binds = cdp_AllocEventBinds (reg->binds, + reg->bindslots, reg->bindslots + EVENT_BIND_GROW); + bind = reg->binds + reg->bindslots; + reg->bindslots += EVENT_BIND_GROW; + } + else if (bind->proc == proc) + { // already bound + return true; + } + } + else + { + reg->binds = cdp_AllocEventBinds (NULL, 0, EVENT_BIND_GROW); + reg->bindslots = EVENT_BIND_GROW; + bind = reg->binds; + } + + bind->proc = proc; + bind->module = module; + + return true; +} + +static void +cdp_Host_UnsubscribeEvent (cdp_Event event, cdp_EventProc proc) +{ + cdp_EventReg* reg = cdp_RegFromEvent (event); + cdp_EventBind* bind = NULL; + uint32 i; + + if (reg < cdp_evts || reg >= cdp_evts + MAX_REG_EVENTS || + !reg->name) + { // event either expired or invalid + return; + } + + if (!reg->binds || !reg->bindslots) + return; // hmm, no bindings + + // check for duplicate or find a new slot + for (i = 0, bind = reg->binds; i < reg->bindslots && + bind->proc != proc; + ++i, ++bind) + ; + if (i >= reg->bindslots) + return; // binding not found + + bind->proc = NULL; + bind->module = NULL; +} + +static bool +cdp_Host_SubscribeEvents (cdp_EventDef* defs, cdp_Module* module) +{ + cdp_EventDef* def; + int errors = 0; + + for (def = defs; def->name; ++def) + { + if (def->event != CDP_EVENT_INVALID && def->proc) + if (!cdp_Host_SubscribeEvent (def->event, def->proc, module)) + ++errors; + } + return !errors; +} + +static void +cdp_Host_UnsubscribeEvents (cdp_EventDef* defs) +{ + cdp_EventDef* def; + + for (def = defs; def->name; ++def) + { + if (def->event != CDP_EVENT_INVALID && def->proc) + cdp_Host_UnsubscribeEvent (def->event, def->proc); + } +} + +static cdp_EventResult +cdp_Host_FireEvent (cdp_EventReg* evtreg, uint32 iparam, void* pparam) +{ + bool bHandled = false; + cdp_EventResult ret = 0; + cdp_Event event; + cdp_EventBind* bind; + uint32 i; + + if (evtreg < cdp_evts || evtreg >= cdp_evts + MAX_REG_EVENTS || + !evtreg->name) + { +#ifdef DEBUG + fprintf (stderr, "cdp_Host_FireEvent(): Invalid event\n"); +#endif + return 0; + } + + if (!evtreg->binds) + return 0; // no subscribers + + event = cdp_EventFromReg (evtreg); + + // call event procs in opposite order of binding + for (i = evtreg->bindslots, bind = evtreg->binds + i - 1; + !bHandled && i > 0; + --i, --bind) + { + if (bind->proc) + ret = bind->proc (event, iparam, pparam, &bHandled); + } + return ret; +} diff --git a/src/libs/cdp/cdpapi.h b/src/libs/cdp/cdpapi.h new file mode 100644 index 0000000..e1a0e0b --- /dev/null +++ b/src/libs/cdp/cdpapi.h @@ -0,0 +1,154 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP API declarations + * the API is used by both the engine and modules + */ + +#ifndef LIBS_CDP_CDPAPI_H_ +#define LIBS_CDP_CDPAPI_H_ + +#include "types.h" + +typedef enum +{ + CDPAPI_VERSION_1 = 0x00000001, // version 0.1 + + CDPAPI_VERSION = CDPAPI_VERSION_1, + CDPAPI_VERSION_MIN = CDPAPI_VERSION_1, + +} cdp_ApiVersion; + +typedef enum +{ + CDPERR_NONE = 0, + CDPERR_UKNOWN = 1, + CDPERR_NOT_FOUND = 2, + CDPERR_BAD_MODULE = 3, + CDPERR_OLD_VER = 4, + CDPERR_UNKNOWN_VER = 5, + CDPERR_TOO_MANY = 6, + CDPERR_INIT_FAILED = 7, + CDPERR_NO_ITF = 8, + CDPERR_DUPE_ITF = 9, + CDPERR_NO_EVENT = 10, + CDPERR_DUPE_EVENT = 11, + CDPERR_OTHER = 1000, + +} cdp_Error; + +typedef struct cdp_Module cdp_Module; +typedef void cdp_Itf; +typedef struct cdp_ItfReg cdp_ItfReg; + +// Interface KINDs - for convinience and uniformity +#define CDPITF_KIND_INVALID NULL +#define CDPITF_KIND_HOST "UQM.Host" +#define CDPITF_KIND_MEMORY "UQM.Memory" +#define CDPITF_KIND_IO "UQM.IO" +#define CDPITF_KIND_THREADS "UQM.Threads" +#define CDPITF_KIND_TIME "UQM.Time" +#define CDPITF_KIND_INPUT "UQM.Input" +#define CDPITF_KIND_TASK "UQM.Task" +#define CDPITF_KIND_RESOURCE "UQM.Resource" +#define CDPITF_KIND_SOUND "UQM.Sound" +#define CDPITF_KIND_VIDEO "UQM.Video" +#define CDPITF_KIND_GFX "UQM.Gfx" +#define CDPITF_KIND_MIXER "UQM.Mixer" + +// Interface definition structure +// pass an array of these to Host->GetItfs() for batch lookup +// pass an array of these to Host->RegisterItfs() for batch registration +typedef struct +{ + // fill in the first 4 members for batch registration + // fill in the 1st member for batch lookup + // terminate an array of these defs with name == NULL + const char* name; // interface ID + cdp_Itf* itf; // interface pointer + cdp_ApiVersion ver_from; // lowest supported version + cdp_ApiVersion ver_to; // highest supported version + + cdp_Module* module; // owner module + // the following member is only set during registration + cdp_ItfReg* reg; // registration handle (not set on lookup) + +} cdp_ItfDef; + +typedef unsigned int cdp_Event; +typedef struct cdp_EventReg cdp_EventReg; +typedef intptr_t cdp_EventResult; + +#define CDP_EVENT_INVALID (-1) + // used with cdp_Event + +typedef cdp_EventResult (* cdp_EventProc) + (cdp_Event, uint32, void*, bool* pbHandled); + +// Event definition structure +// pass an array of these to Host->GetItfs() for batch lookup +typedef struct +{ + // fill in the 1st member for batch lookup or registration + // also fill in the 2nd member for batch subscription + // terminate an array of these defs with name == NULL + const char* name; // event ID + cdp_EventProc proc; // event proc, set to NULL for no bind + + cdp_Event event; // subscribable event handle + cdp_Module* module; // owner module + // the following member is only set during registration + cdp_EventReg* reg; // registration handle (not set on lookup) + +} cdp_EventDef; + +// Host Interface +// the main itf of the API, it is passed to a loaded module +// module does everything else through this itf and itfs +// acquired through this itf +typedef struct +{ + uint32 (* GetApiVersion) (void); + uint32 (* GetVersion) (void); + cdp_Error (* GetApiError) (void); + cdp_Itf* (* GetItf) (const char* name); + bool (* GetItfs) (cdp_ItfDef* defs); + cdp_ItfReg* (* RegisterItf) (const char* name, + cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, + cdp_Itf*, cdp_Module*); + void (* UnregisterItf) (cdp_ItfReg*); + bool (* RegisterItfs) (cdp_ItfDef* defs, cdp_Module*); + void (* UnregisterItfs) (cdp_ItfDef* defs); + cdp_Event (* GetEvent) (const char* name); + bool (* GetEvents) (cdp_EventDef* defs); + cdp_EventReg* (* RegisterEvent) (const char* name, cdp_Module*); + void (* UnregisterEvent) (cdp_EventReg*); + bool (* RegisterEvents) (cdp_EventDef* defs, cdp_Module*); + void (* UnregisterEvents) (cdp_EventDef* defs); + bool (* SubscribeEvent) (cdp_Event, cdp_EventProc, cdp_Module*); + void (* UnsubscribeEvent) (cdp_Event, cdp_EventProc); + bool (* SubscribeEvents) (cdp_EventDef* defs, cdp_Module*); + void (* UnsubscribeEvents) (cdp_EventDef* defs); + cdp_EventResult (* FireEvent) (cdp_EventReg*, uint32, void*); + +} cdp_Itf_HostVtbl_v1; + +typedef cdp_Itf_HostVtbl_v1 cdp_Itf_HostVtbl; +typedef cdp_Itf_HostVtbl cdp_Itf_Host; + +#endif /* LIBS_CDP_CDPAPI_H_ */ diff --git a/src/libs/cdp/cdpint.h b/src/libs/cdp/cdpint.h new file mode 100644 index 0000000..fbc3238 --- /dev/null +++ b/src/libs/cdp/cdpint.h @@ -0,0 +1,48 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP common internal definitions + */ + +#ifndef LIBS_CDP_CDPINT_H_ +#define LIBS_CDP_CDPINT_H_ + +#include "cdpapi.h" +#include "cdp_imem.h" +#include "cdp_iio.h" +#include "cdp_isnd.h" +#include "cdp_ivid.h" + +#ifdef WIN32 +# define CDPEXT ".dll" +#else +# define CDPEXT ".so" +#endif + +extern cdp_Itf_HostVtbl_v1 cdp_host_itf_v1; +extern cdp_Itf_MemoryVtbl_v1 cdp_memory_itf_v1; +extern cdp_Itf_IoVtbl_v1 cdp_io_itf_v1; +extern cdp_Itf_SoundVtbl_v1 cdp_sound_itf_v1; + +bool cdp_InitApi (void); +void cdp_UninitApi (void); +cdp_Error cdp_GetApiError (void); +cdp_Itf* cdp_GetInterface (const char* name, cdp_ApiVersion); +cdp_ItfReg* cdp_GetInterfaceReg (const char* name, cdp_ApiVersion); + +#endif /* _CDPISND_H */ diff --git a/src/libs/cdp/cdpmod.h b/src/libs/cdp/cdpmod.h new file mode 100644 index 0000000..a1fdcae --- /dev/null +++ b/src/libs/cdp/cdpmod.h @@ -0,0 +1,92 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP module definitions + * all CDP modules should #include this .h + */ + +#ifndef LIBS_CDP_CDPMOD_H_ +#define LIBS_CDP_CDPMOD_H_ + +#include "types.h" +#include "cdpapi.h" + +#define CDP_INFO_SYM cdpmodinfo +#define CDP_INFO_SYM_NAME "cdpmodinfo" + +// this struct will be exported from the module +// under 'cdpmodinfo' +typedef struct +{ + // mandatory, version control + uint32 size; // size of this structure + cdp_ApiVersion api_ver; // version of cdp API used, set to CDPAPI_VERSION + uint16 ver_major; // module version, somewhat informational + uint16 ver_minor; + uint16 ver_patch; + uint16 host_ver_major; // minimum host version required, purely informational + uint16 host_ver_minor; + uint16 host_ver_patch; + + // reserved members: set all to 0 or use CDP_MODINFO_RESERVED1 + uint32 _32_reserved1; + uint32 _32_reserved2; + uint32 _32_reserved3; + uint32 _32_reserved4; + + const char* context_name; + // cannonical context name (in proper case) + // this context will be used with all exposed objects + // English preferred; try to keep it below 32 chars + // informational, human-only; these fields have no real size + // restriction other than to keep it reasonable + const char* name; // descriptive name + const char* ver_string; // descriptive version + const char* author; // go nuts + const char* url; // go nuts + const char* comments; // go nuts + + // reserved members, set all to 0 or use CDP_MODINFO_RESERVED2 + const char* _sz_reserved1; + const char* _sz_reserved2; + const char* _sz_reserved3; + const char* _sz_reserved4; + + // mandatory, CDP entry points + // TODO: decide whether more EPs are necessary and if not move + // EPs above info-string members, abolishing _sz_reservedX + bool (* module_init) (cdp_Module* module, cdp_Itf_Host* hostitf); + void (* module_term) (); + +} cdp_ModuleInfo; + +#define CDP_MODINFO_RESERVED1 0,0,0,0 +#define CDP_MODINFO_RESERVED2 0,0,0,0 + +// the following is defined via the last mandatory member +#define CDP_MODINFO_MIN_SIZE \ + ( ((uint32) &((cdp_ModuleInfo*)0)->module_term) + \ + sizeof (((cdp_ModuleInfo*)0)->module_term) ) + +#if defined(WIN32) +# define CDPEXPORT __declspec(dllexport) +#else +# define CDPEXPORT +#endif + +#endif /* LIBS_CDP_CDPMOD_H_ */ diff --git a/src/libs/cdp/windl.c b/src/libs/cdp/windl.c new file mode 100644 index 0000000..4bc76f6 --- /dev/null +++ b/src/libs/cdp/windl.c @@ -0,0 +1,76 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP dlopen() & Co. WIN32 implementation + */ + +#include "windl.h" +#include "port.h" +#define WIN32_LEAN_AND_MEAN +//#include <windows.h> +#include <wtypes.h> +#include <winbase.h> +#include <stdio.h> + +static uint32 wdl_last_error = 0; +static char wdl_errstr[128] = ""; + +void* +dlopen (const char *filename, int flag) + // all defined flags are not possible on win32 +{ + HMODULE hlib; + + if (filename == NULL) + hlib = GetModuleHandleA(NULL); + else + hlib = LoadLibraryA (filename); + + if (!hlib) + wdl_last_error = GetLastError (); + + return hlib; +} + +void* +dlsym (void *handle, const char *symbol) +{ + void* ptr = GetProcAddress (handle, symbol); + if (!ptr) + wdl_last_error = GetLastError (); + return ptr; +} + +int +dlclose (void *handle) +{ + return FreeLibrary (handle); +} + +char* +dlerror (void) +{ + if (wdl_last_error) + { + sprintf (wdl_errstr, "Windows error %u", wdl_last_error); + wdl_last_error = 0; + return wdl_errstr; + } + else + return NULL; +} diff --git a/src/libs/cdp/windl.h b/src/libs/cdp/windl.h new file mode 100644 index 0000000..71ca240 --- /dev/null +++ b/src/libs/cdp/windl.h @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * Nota bene: later versions of the GNU General Public License do not apply + * to this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * CDP dlopen() & Co. WIN32 implementation + */ + +#ifndef LIBS_CDP_WINDL_H_ +#define LIBS_CDP_WINDL_H_ + +#include "types.h" + +extern void *dlopen (const char *filename, int flag); +extern void *dlsym (void *handle, const char *symbol); +extern int dlclose (void *handle); +extern char *dlerror (void); + +/* these dlopen() flags are meaningless on win32 */ +#define RTLD_LAZY 1 /* lazy function call binding */ +#define RTLD_NOW 2 /* immediate function call binding */ +#define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other dlopen'ed objs */ + +#endif /* LIBS_CDP_WINDL_H_ */ |