summaryrefslogtreecommitdiff
path: root/src/libs/cdp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/cdp')
-rw-r--r--src/libs/cdp/Makeinfo3
-rw-r--r--src/libs/cdp/cdp.c437
-rw-r--r--src/libs/cdp/cdp.h47
-rw-r--r--src/libs/cdp/cdp_alli.h31
-rw-r--r--src/libs/cdp/cdp_iio.h50
-rw-r--r--src/libs/cdp/cdp_imem.h42
-rw-r--r--src/libs/cdp/cdp_isnd.h43
-rw-r--r--src/libs/cdp/cdp_ivid.h43
-rw-r--r--src/libs/cdp/cdpapi.c864
-rw-r--r--src/libs/cdp/cdpapi.h154
-rw-r--r--src/libs/cdp/cdpint.h48
-rw-r--r--src/libs/cdp/cdpmod.h92
-rw-r--r--src/libs/cdp/windl.c76
-rw-r--r--src/libs/cdp/windl.h37
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_ */