diff --git a/sc2/src/sc2code/libs/cdp/Makeinfo b/sc2/src/sc2code/libs/cdp/Makeinfo new file mode 100644 index 000000000..9ab9039a2 --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/Makeinfo @@ -0,0 +1 @@ +uqm_CFILES="cdp.c cdpapi.c" diff --git a/sc2/src/sc2code/libs/cdp/cdp.c b/sc2/src/sc2code/libs/cdp/cdp.c new file mode 100644 index 000000000..c08d70a8e --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdp.c @@ -0,0 +1,343 @@ +/* + * 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 +#include +#include "cdp.h" +#include "port.h" +#include "cdpint.h" +#include "cdpmod.h" +#include "uio.h" +#ifdef WIN32 +# include "windl.h" +#else +# include +#endif + +#define MAX_CDPS 63 +#define CDPDIR "cdps" + +// internal adl module representation +// cdp_Module will be cast to and from this +struct cdp_Module +{ + bool used; // used at least once indicator + void* hmodule; // loaded module handle + uint32 refcount; // reference count + cdp_ModuleInfo* info; // cdp exported info + +}; + +extern uio_DirHandle *cdpDir; + +static bool cdp_inited = false; +static cdp_Module cdp_modules[MAX_CDPS + 1]; +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) +{ + if (cdp_inited) + { + fprintf (stderr, "cdp_Init(): called when already inited\n"); + return true; + } + + memset (cdp_modules, 0, sizeof cdp_modules); + //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) +{ + 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 (!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 (!info->module_init ((cdp_Itf_Host*)ihost)) + { + fprintf (stderr, "cdp_LoadModule(): " + "CDP %s failed to init\n", + modname); + dlclose (mod); + cdp_last_error = CDPERR_INIT_FAILED; + return NULL; + } + + if (!newslot) + { + newslot = cdp; + newslot->used = true; + } + newslot->hmodule = mod; + newslot->refcount = 1; + newslot->info = info; + + 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) + 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_GetModuleName (cdp_Module* module) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (!modslot) + return "(Error)"; + if (!modslot->info->name) + 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) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (!modslot) + return "(Error)"; + if (!modslot->info->ver_string) + return "(Null)"; + return modslot->info->ver_string; +} + +const char* +cdp_GetModuleComment (cdp_Module* module) +{ + cdp_Module* modslot = cdp_CheckModule (module); + if (!modslot) + return "(Error)"; + if (!modslot->info->comments) + 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), + cdp_GetModuleVersionString (mod), + cdp_GetModuleComment (mod)); + } + 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->hmodule) + cdp_FreeModule (cdp); + } +} diff --git a/sc2/src/sc2code/libs/cdp/cdp.h b/sc2/src/sc2code/libs/cdp/cdp.h new file mode 100644 index 000000000..39e991f9f --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdp.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 library declarations + */ + +#ifndef _CDP_H +#define _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); +const char* cdp_GetModuleName (cdp_Module* module); +uint32 cdp_GetModuleVersion (cdp_Module* module); +const char* cdp_GetModuleVersionString (cdp_Module* module); +const char* cdp_GetModuleComment (cdp_Module* module); + +int cdp_LoadAllModules (void); +void cdp_FreeAllModules (void); + +#endif /* _CDP_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdp_alli.h b/sc2/src/sc2code/libs/cdp/cdp_alli.h new file mode 100644 index 000000000..38e48b3e2 --- /dev/null +++ b/sc2/src/sc2code/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 _CDPALLI_H +#define _CDPALLI_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 /* _CDPALLI_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdp_iio.h b/sc2/src/sc2code/libs/cdp/cdp_iio.h new file mode 100644 index 000000000..461af7e53 --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdp_iio.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 Unified IO Interface + */ + +#ifndef _CDPIIO_H +#define _CDPIIO_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 /* _CDPIIO_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdp_imem.h b/sc2/src/sc2code/libs/cdp/cdp_imem.h new file mode 100644 index 000000000..f4c894814 --- /dev/null +++ b/sc2/src/sc2code/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 _CDPIMEM_H +#define _CDPIMEM_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 /* _CDPIMEM_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdp_isnd.h b/sc2/src/sc2code/libs/cdp/cdp_isnd.h new file mode 100644 index 000000000..af2b3b0b0 --- /dev/null +++ b/sc2/src/sc2code/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 _CDPISND_H +#define _CDPISND_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 /* _CDPISND_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdp_ivid.h b/sc2/src/sc2code/libs/cdp/cdp_ivid.h new file mode 100644 index 000000000..ed4d3ad9b --- /dev/null +++ b/sc2/src/sc2code/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 _CDPIVID_H +#define _CDPIVID_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 /* _CDPIVID_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdpapi.c b/sc2/src/sc2code/libs/cdp/cdpapi.c new file mode 100644 index 000000000..5b6822119 --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdpapi.c @@ -0,0 +1,284 @@ +/* + * 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 + +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 (cdp_ItfKind); +static cdp_RegItf* cdp_Host_RegisterItf (cdp_ItfKind, + cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, + cdp_Itf*, cdp_Module*); +static void cdp_Host_UnregisterItf (cdp_RegItf*); + +// Interfaces +cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 = +{ + cdp_Host_GetApiVersion, + cdp_Host_GetVersion, + cdp_Host_GetApiError, + cdp_Host_GetItf, + cdp_Host_RegisterItf, + cdp_Host_UnregisterItf, +}; + +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, +}; + +struct cdp_RegItf +{ + bool builtin; + bool used; + cdp_ItfKind kind; + cdp_ApiVersion ver_from; + cdp_ApiVersion ver_to; + cdp_Itf* itfvtbl; + cdp_Module* module; +}; + +#define CDP_DECLARE_ITF(k,vf,vt,vtbl) \ + {true, true, CDPITF_KIND_##k, \ + CDPAPI_VERSION_##vf, CDPAPI_VERSION_##vt, vtbl, NULL} + +// Built-in interfaces + space for loadable +cdp_RegItf 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, CDPITF_KIND_INVALID, 0, 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) +{ + // TODO: add whatever init code is necessary + return true; +} + +void +cdp_UninitApi (void) +{ + cdp_RegItf* itf; + + // unregister custom interfaces + for (itf = cdp_itfs; itf->used; ++itf) + { + if (!itf->builtin) + { + itf->used = false; + itf->kind = CDPITF_KIND_INVALID; + itf->itfvtbl = NULL; + } + } +} + +cdp_Itf* +cdp_GetInterface (cdp_ItfKind itf_kind, cdp_ApiVersion api_ver) +{ + cdp_RegItf* itf; + + for (itf = cdp_itfs; itf->used && + (itf->kind != itf_kind || + api_ver < itf->ver_from || api_ver > itf->ver_to); + itf++) + ; + if (!itf->kind) + { + cdp_api_error = CDPERR_NO_ITF; + return NULL; + } + + return itf->itfvtbl; +} + +static uint32 +cdp_Host_GetApiVersion (void) +{ + return CDPAPI_VERSION; +} + +static uint32 +cdp_Host_GetVersion (void) +{ + return (UQM_MAJOR_VERSION << 16) | UQM_MINOR_VERSION; +} + +static cdp_Error +cdp_Host_GetApiError (void) +{ + return cdp_GetApiError (); +} + +static cdp_Itf* +cdp_Host_GetItf (cdp_ItfKind itf_kind) +{ + return cdp_GetInterface (itf_kind, CDPAPI_VERSION_1); +} + +static cdp_RegItf* +cdp_Host_RegisterItf (cdp_ItfKind itf_kind, cdp_ApiVersion ver_from, + cdp_ApiVersion ver_to, cdp_Itf* itfvtbl, cdp_Module* module) +{ + cdp_RegItf* regitf; + cdp_RegItf* newslot = NULL; + + if (!module) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "No module info supplied\n"); + //return NULL; + } + if (!itf_kind || !itfvtbl) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "Null or invalid interface (from %s)\n", + cdp_GetModuleName (module)); + 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 0x%08x (from %s)\n", + itf_kind, cdp_GetModuleName (module)); + return NULL; + } + + // check if extension already registered + for (regitf = cdp_itfs; regitf->used && + (regitf->kind != itf_kind || + ver_from < regitf->ver_from || ver_to > regitf->ver_to); + ++regitf) + { + // and pick up an empty slot (where available) + if (!newslot && !regitf->kind) + newslot = regitf; + } + + if (regitf >= cdp_itfs + MAX_REG_ITFS) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "Interfaces limit reached\n"); + return NULL; + } + else if (regitf->kind) + { + fprintf (stderr, "cdp_Host_RegisterItf(): " + "interface 0x%08x already registered for these versions, " + "%s denied\n", + itf_kind, cdp_GetModuleName (module)); + return NULL; + } + + if (!newslot) + { + newslot = regitf; + newslot->used = true; + // make next one a term + regitf[1].builtin = false; + regitf[1].used = false; + regitf[1].kind = CDPITF_KIND_INVALID; + regitf[1].itfvtbl = NULL; + } + + newslot->kind = itf_kind; + newslot->ver_from = ver_from; + newslot->ver_to = ver_to; + newslot->itfvtbl = itfvtbl; + newslot->module = module; + + return newslot; +} + +static void +cdp_Host_UnregisterItf (cdp_RegItf* regitf) +{ + if (regitf < cdp_itfs || regitf >= cdp_itfs + MAX_REG_ITFS || + !regitf->kind || !regitf->itfvtbl) + { + fprintf (stderr, "cdp_Host_UnregisterItf(): " + "Invalid or expired interface passed\n"); + return; + } + + regitf->kind = CDPITF_KIND_INVALID; + regitf->itfvtbl = NULL; +} diff --git a/sc2/src/sc2code/libs/cdp/cdpapi.h b/sc2/src/sc2code/libs/cdp/cdpapi.h new file mode 100644 index 000000000..f50c57dec --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdpapi.h @@ -0,0 +1,100 @@ +/* + * 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 _CDPAPI_H +#define _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_OTHER = 1000, + +} cdp_Error; + +typedef struct cdp_Module cdp_Module; +typedef void cdp_Itf; +typedef struct cdp_RegItf cdp_RegItf; + +typedef enum +{ + CDPITF_KIND_INVALID = 0, + CDPITF_KIND_HOST = 1, + CDPITF_KIND_MEMORY = 2, + CDPITF_KIND_IO = 3, + CDPITF_KIND_THREADS = 4, + CDPITF_KIND_TIME = 5, + CDPITF_KIND_INPUT = 6, + CDPITF_KIND_TASK = 7, + CDPITF_KIND_RESOURCE = 8, + CDPITF_KIND_SOUND = 9, + CDPITF_KIND_VIDEO = 10, + CDPITF_KIND_GFX = 11, + CDPITF_KIND_MIXER = 12, + // anything up to 65536 is reserved + // apply for your KIND (range) officially in UQM bugzilla (for now) + + // custom interfaces live here +# include "cdpitfs.h" + +} cdp_ItfKind; + +// 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) (cdp_ItfKind); + cdp_RegItf* (* RegisterItf) (cdp_ItfKind, + cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, + cdp_Itf*, cdp_Module*); + void (* UnregisterItf) (cdp_RegItf*); + +} cdp_Itf_HostVtbl_v1; + +typedef cdp_Itf_HostVtbl_v1 cdp_Itf_HostVtbl; +typedef cdp_Itf_HostVtbl cdp_Itf_Host; + +#endif /* _CDPAPI_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdpint.h b/sc2/src/sc2code/libs/cdp/cdpint.h new file mode 100644 index 000000000..340af6f6c --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdpint.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 common internal definitions + */ + +#ifndef _CDPINT_H +#define _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 (cdp_ItfKind itf_kind, cdp_ApiVersion api_ver); + +#endif /* _CDPISND_H */ diff --git a/sc2/src/sc2code/libs/cdp/cdpitfs.h b/sc2/src/sc2code/libs/cdp/cdpitfs.h new file mode 100644 index 000000000..c6f037444 --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdpitfs.h @@ -0,0 +1,23 @@ +/* TODO: review/comment [inline]/change rules */ + +/* + * CDP Custom Interface KINDs repository + * + * Officially registered interfaces live here. The rules are: + * 1) anything up to 65536 is reserved for internal use + * 2) please (!) apply for your KIND (range) officially in UQM + * bugzilla (for now) + * 3) your choices for KIND names are either your email addy + * or your mod project name, followed by a brief but descriptive + * interface name; please keep is short, the final identifier + * has to be under 64 chars long + * 4) upon application, you get a KIND numerical range for your + * use; please use range sizes that are a multiple of 0x10 + * (self managed for now), but do not take more than 0x40 + * at once + * + * Sample: + * + * CDPITF_KIND_CODEPRO_AT_USA_NET_HANGAR = 0x00010001, + * CDPITF_KIND_CODEPRO_AT_USA_NET_IMAGEEFFECTS = 0x00010002, + */ diff --git a/sc2/src/sc2code/libs/cdp/cdpmod.h b/sc2/src/sc2code/libs/cdp/cdpmod.h new file mode 100644 index 000000000..da4f160e1 --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/cdpmod.h @@ -0,0 +1,77 @@ +/* + * 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 _CDPMOD_H +#define _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 host_ver_major; // minimum host version required, purely informational + uint16 host_ver_minor; + + uint32 _32_reserved1[4]; // reserved members: set to all 0s or CDP_MODINFO_RESERVED1 + + // informational, human-only + const char* name; + const char* ver_string; + const char* author; + const char* url; + const char* comments; + + const char* _sz_reserved2[5]; // reserved members, set to all 0s or CDP_MODINFO_RESERVED2 + + // mandatory, CDP entry points + // TODO: decide whether more EPs are necessary and if not move + // EPs above info-string members, abolishing _sz_reserved2 + bool (* module_init) (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,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 /* _CDPMOD_H */ diff --git a/sc2/src/sc2code/libs/cdp/windl.c b/sc2/src/sc2code/libs/cdp/windl.c new file mode 100644 index 000000000..e2cd6a139 --- /dev/null +++ b/sc2/src/sc2code/libs/cdp/windl.c @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +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; + + 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/sc2/src/sc2code/libs/cdp/windl.h b/sc2/src/sc2code/libs/cdp/windl.h new file mode 100644 index 000000000..c095ca84a --- /dev/null +++ b/sc2/src/sc2code/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 _WINDL_H +#define _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 /* _WINDL_H */ diff --git a/sc2/src/sc2code/libs/cdplib.h b/sc2/src/sc2code/libs/cdplib.h new file mode 100644 index 000000000..51405fea3 --- /dev/null +++ b/sc2/src/sc2code/libs/cdplib.h @@ -0,0 +1,24 @@ +/* + * 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 + * + */ + +#ifndef _CDPLIB_H +#define _CDPLIB_H + +#include "cdp/cdp.h" + +#endif /* _CDPLIB_H */