Interface changes: no more KIND ints, all context.name strings now;
Initial version of Event system git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1286 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
+130
-36
@@ -26,6 +26,7 @@
|
|||||||
#include "cdpint.h"
|
#include "cdpint.h"
|
||||||
#include "cdpmod.h"
|
#include "cdpmod.h"
|
||||||
#include "uio.h"
|
#include "uio.h"
|
||||||
|
#include "uqmversion.h"
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include "windl.h"
|
# include "windl.h"
|
||||||
#else
|
#else
|
||||||
@@ -35,21 +36,50 @@
|
|||||||
#define MAX_CDPS 63
|
#define MAX_CDPS 63
|
||||||
#define CDPDIR "cdps"
|
#define CDPDIR "cdps"
|
||||||
|
|
||||||
// internal adl module representation
|
// internal CDP module representation
|
||||||
// cdp_Module will be cast to and from this
|
|
||||||
struct cdp_Module
|
struct cdp_Module
|
||||||
{
|
{
|
||||||
bool used; // used at least once indicator
|
bool builtin; // used at least once indicator
|
||||||
void* hmodule; // loaded module handle
|
bool used; // used at least once indicator
|
||||||
uint32 refcount; // reference count
|
void* hmodule; // loaded module handle
|
||||||
|
uint32 refcount; // reference count
|
||||||
cdp_ModuleInfo* info; // cdp exported info
|
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_MAJOR_VERSION, UQM_MINOR_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;
|
extern uio_DirHandle *cdpDir;
|
||||||
|
|
||||||
static bool cdp_inited = false;
|
static bool cdp_inited = false;
|
||||||
static cdp_Module cdp_modules[MAX_CDPS + 1];
|
|
||||||
static cdp_Error cdp_last_error = CDPERR_NONE;
|
static cdp_Error cdp_last_error = CDPERR_NONE;
|
||||||
static char cdp_path[PATH_MAX] = "";
|
static char cdp_path[PATH_MAX] = "";
|
||||||
|
|
||||||
@@ -64,13 +94,25 @@ cdp_GetError (void)
|
|||||||
bool
|
bool
|
||||||
cdp_Init (void)
|
cdp_Init (void)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
void* hkernel;
|
||||||
|
|
||||||
if (cdp_inited)
|
if (cdp_inited)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cdp_Init(): called when already inited\n");
|
fprintf (stderr, "cdp_Init(): called when already inited\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (cdp_modules, 0, sizeof cdp_modules);
|
// 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);
|
//strcpy (cdp_path, cdpDir->path);
|
||||||
cdp_InitApi ();
|
cdp_InitApi ();
|
||||||
cdp_inited = true;
|
cdp_inited = true;
|
||||||
@@ -94,6 +136,7 @@ cdp_Uninit (void)
|
|||||||
|
|
||||||
cdp_Module*
|
cdp_Module*
|
||||||
cdp_LoadModule (const char* modname)
|
cdp_LoadModule (const char* modname)
|
||||||
|
// special value for modname: NULL - refers to kernel (UQM exe)
|
||||||
{
|
{
|
||||||
void* mod;
|
void* mod;
|
||||||
char modpath[PATH_MAX];
|
char modpath[PATH_MAX];
|
||||||
@@ -104,6 +147,9 @@ cdp_LoadModule (const char* modname)
|
|||||||
cdp_Module* newslot = 0;
|
cdp_Module* newslot = 0;
|
||||||
cdp_Itf* ihost;
|
cdp_Itf* ihost;
|
||||||
|
|
||||||
|
if (modname == NULL)
|
||||||
|
return cdp_modules;
|
||||||
|
|
||||||
if (!cdp_inited)
|
if (!cdp_inited)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cdp_LoadModule(): called when not inited\n");
|
fprintf (stderr, "cdp_LoadModule(): called when not inited\n");
|
||||||
@@ -173,24 +219,33 @@ cdp_LoadModule (const char* modname)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info->module_init ((cdp_Itf_Host*)ihost))
|
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(): "
|
fprintf (stderr, "cdp_LoadModule(): "
|
||||||
"CDP %s failed to init\n",
|
"CDP %s failed to init\n",
|
||||||
modname);
|
modname);
|
||||||
dlclose (mod);
|
dlclose (mod);
|
||||||
|
newslot->hmodule = NULL;
|
||||||
|
newslot->info = NULL;
|
||||||
|
newslot->refcount = 0;
|
||||||
cdp_last_error = CDPERR_INIT_FAILED;
|
cdp_last_error = CDPERR_INIT_FAILED;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newslot)
|
|
||||||
{
|
|
||||||
newslot = cdp;
|
|
||||||
newslot->used = true;
|
|
||||||
}
|
|
||||||
newslot->hmodule = mod;
|
|
||||||
newslot->refcount = 1;
|
|
||||||
newslot->info = info;
|
|
||||||
|
|
||||||
return newslot;
|
return newslot;
|
||||||
}
|
}
|
||||||
@@ -210,7 +265,7 @@ cdp_FreeModule (cdp_Module* module)
|
|||||||
{
|
{
|
||||||
cdp_Module* modslot = cdp_CheckModule (module);
|
cdp_Module* modslot = cdp_CheckModule (module);
|
||||||
|
|
||||||
if (!modslot)
|
if (!modslot || modslot->builtin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
modslot->refcount--;
|
modslot->refcount--;
|
||||||
@@ -227,13 +282,38 @@ cdp_FreeModule (cdp_Module* module)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
cdp_GetModuleName (cdp_Module* module)
|
cdp_GetModuleContext (cdp_Module* module, bool bMetaString)
|
||||||
{
|
{
|
||||||
cdp_Module* modslot = cdp_CheckModule (module);
|
cdp_Module* modslot = cdp_CheckModule (module);
|
||||||
if (!modslot)
|
if (bMetaString)
|
||||||
return "(Error)";
|
{
|
||||||
if (!modslot->info->name)
|
if (!modslot)
|
||||||
return "(Null)";
|
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;
|
return modslot->info->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,24 +327,38 @@ cdp_GetModuleVersion (cdp_Module* module)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
cdp_GetModuleVersionString (cdp_Module* module)
|
cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString)
|
||||||
{
|
{
|
||||||
cdp_Module* modslot = cdp_CheckModule (module);
|
cdp_Module* modslot = cdp_CheckModule (module);
|
||||||
if (!modslot)
|
if (bMetaString)
|
||||||
return "(Error)";
|
{
|
||||||
if (!modslot->info->ver_string)
|
if (!modslot)
|
||||||
return "(Null)";
|
return "(Error)";
|
||||||
|
if (!modslot->info->ver_string)
|
||||||
|
return "(Null)";
|
||||||
|
}
|
||||||
|
else if (!modslot)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return modslot->info->ver_string;
|
return modslot->info->ver_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
cdp_GetModuleComment (cdp_Module* module)
|
cdp_GetModuleComment (cdp_Module* module, bool bMetaString)
|
||||||
{
|
{
|
||||||
cdp_Module* modslot = cdp_CheckModule (module);
|
cdp_Module* modslot = cdp_CheckModule (module);
|
||||||
if (!modslot)
|
if (bMetaString)
|
||||||
return "(Error)";
|
{
|
||||||
if (!modslot->info->comments)
|
if (!modslot)
|
||||||
return "(Null)";
|
return "(Error)";
|
||||||
|
if (!modslot->info->comments)
|
||||||
|
return "(Null)";
|
||||||
|
}
|
||||||
|
else if (!modslot)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return modslot->info->comments;
|
return modslot->info->comments;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,9 +403,9 @@ cdp_LoadAllModules (void)
|
|||||||
{
|
{
|
||||||
nummods++;
|
nummods++;
|
||||||
fprintf (stderr, "\tloaded CDP: %s v%s (%s)\n",
|
fprintf (stderr, "\tloaded CDP: %s v%s (%s)\n",
|
||||||
cdp_GetModuleName (mod),
|
cdp_GetModuleName (mod, true),
|
||||||
cdp_GetModuleVersionString (mod),
|
cdp_GetModuleVersionString (mod, true),
|
||||||
cdp_GetModuleComment (mod));
|
cdp_GetModuleComment (mod, true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -337,7 +431,7 @@ cdp_FreeAllModules (void)
|
|||||||
|
|
||||||
for (cdp = cdp_modules; cdp->used; ++cdp)
|
for (cdp = cdp_modules; cdp->used; ++cdp)
|
||||||
{
|
{
|
||||||
if (cdp->hmodule)
|
if (!cdp->builtin && cdp->hmodule)
|
||||||
cdp_FreeModule (cdp);
|
cdp_FreeModule (cdp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,14 @@ void cdp_Uninit (void);
|
|||||||
cdp_Error cdp_GetError (void);
|
cdp_Error cdp_GetError (void);
|
||||||
cdp_Module* cdp_LoadModule (const char* modname);
|
cdp_Module* cdp_LoadModule (const char* modname);
|
||||||
void cdp_FreeModule (cdp_Module* module);
|
void cdp_FreeModule (cdp_Module* module);
|
||||||
const char* cdp_GetModuleName (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);
|
uint32 cdp_GetModuleVersion (cdp_Module* module);
|
||||||
const char* cdp_GetModuleVersionString (cdp_Module* module);
|
const char* cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString);
|
||||||
const char* cdp_GetModuleComment (cdp_Module* module);
|
const char* cdp_GetModuleComment (cdp_Module* module, bool bMetaString);
|
||||||
|
|
||||||
int cdp_LoadAllModules (void);
|
int cdp_LoadAllModules (void);
|
||||||
void cdp_FreeAllModules (void);
|
void cdp_FreeAllModules (void);
|
||||||
|
|||||||
@@ -28,9 +28,11 @@
|
|||||||
// CDP IO Interface entry points
|
// CDP IO Interface entry points
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uio_Stream* (* fopen) (uio_DirHandle *dir, const char *path, const char *mode);
|
uio_Stream* (* fopen) (uio_DirHandle *dir, const char *path,
|
||||||
|
const char *mode);
|
||||||
int (* fclose) (uio_Stream *stream);
|
int (* fclose) (uio_Stream *stream);
|
||||||
size_t (* fread) (void *buf, size_t size, size_t nmemb, 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,
|
size_t (* fwrite) (const void *buf, size_t size, size_t nmemb,
|
||||||
uio_Stream *stream);
|
uio_Stream *stream);
|
||||||
int (* fseek) (uio_Stream *stream, long offset, int whence);
|
int (* fseek) (uio_Stream *stream, long offset, int whence);
|
||||||
|
|||||||
@@ -25,18 +25,33 @@
|
|||||||
#include "cdpint.h"
|
#include "cdpint.h"
|
||||||
#include "uqmversion.h"
|
#include "uqmversion.h"
|
||||||
|
|
||||||
#define MAX_REG_ITFS 255
|
#define MAX_REG_ITFS 255
|
||||||
|
#define MAX_REG_EVENTS 1023
|
||||||
|
|
||||||
static cdp_Error cdp_api_error = CDPERR_NONE;
|
static cdp_Error cdp_api_error = CDPERR_NONE;
|
||||||
|
|
||||||
static uint32 cdp_Host_GetApiVersion (void);
|
static uint32 cdp_Host_GetApiVersion (void);
|
||||||
static uint32 cdp_Host_GetVersion (void);
|
static uint32 cdp_Host_GetVersion (void);
|
||||||
static cdp_Error cdp_Host_GetApiError (void);
|
static cdp_Error cdp_Host_GetApiError (void);
|
||||||
static cdp_Itf* cdp_Host_GetItf (cdp_ItfKind);
|
static cdp_Itf* cdp_Host_GetItf (const char* name);
|
||||||
static cdp_RegItf* cdp_Host_RegisterItf (cdp_ItfKind,
|
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_ApiVersion ver_from, cdp_ApiVersion ver_to,
|
||||||
cdp_Itf*, cdp_Module*);
|
cdp_Itf*, cdp_Module*);
|
||||||
static void cdp_Host_UnregisterItf (cdp_RegItf*);
|
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
|
// Interfaces
|
||||||
cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 =
|
cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 =
|
||||||
@@ -45,8 +60,22 @@ cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 =
|
|||||||
cdp_Host_GetVersion,
|
cdp_Host_GetVersion,
|
||||||
cdp_Host_GetApiError,
|
cdp_Host_GetApiError,
|
||||||
cdp_Host_GetItf,
|
cdp_Host_GetItf,
|
||||||
|
cdp_Host_GetItfs,
|
||||||
cdp_Host_RegisterItf,
|
cdp_Host_RegisterItf,
|
||||||
cdp_Host_UnregisterItf,
|
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 =
|
cdp_Itf_MemoryVtbl_v1 cdp_memory_itf_v1 =
|
||||||
@@ -84,23 +113,24 @@ cdp_Itf_VideoVtbl_v1 cdp_video_itf_v1 =
|
|||||||
VideoDecoder_Lookup,
|
VideoDecoder_Lookup,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cdp_RegItf
|
// the actual interface registration struct/handle
|
||||||
|
struct cdp_ItfReg
|
||||||
{
|
{
|
||||||
bool builtin;
|
bool builtin;
|
||||||
bool used;
|
bool used;
|
||||||
cdp_ItfKind kind;
|
const char* name;
|
||||||
cdp_ApiVersion ver_from;
|
cdp_ApiVersion ver_from;
|
||||||
cdp_ApiVersion ver_to;
|
cdp_ApiVersion ver_to;
|
||||||
cdp_Itf* itfvtbl;
|
cdp_Itf* itfvtbl;
|
||||||
cdp_Module* module;
|
cdp_Module* module;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CDP_DECLARE_ITF(k,vf,vt,vtbl) \
|
#define CDP_DECLARE_ITF(kind,vf,vt,vtbl) \
|
||||||
{true, true, CDPITF_KIND_##k, \
|
{true, true, CDPITF_KIND_##kind, \
|
||||||
CDPAPI_VERSION_##vf, CDPAPI_VERSION_##vt, vtbl, NULL}
|
CDPAPI_VERSION_##vf, CDPAPI_VERSION_##vt, vtbl, NULL}
|
||||||
|
|
||||||
// Built-in interfaces + space for loadable
|
// Built-in interfaces + space for loadable
|
||||||
cdp_RegItf cdp_itfs[MAX_REG_ITFS + 1] =
|
cdp_ItfReg cdp_itfs[MAX_REG_ITFS + 1] =
|
||||||
{
|
{
|
||||||
CDP_DECLARE_ITF (HOST, 1, 1, &cdp_host_itf_v1),
|
CDP_DECLARE_ITF (HOST, 1, 1, &cdp_host_itf_v1),
|
||||||
CDP_DECLARE_ITF (MEMORY, 1, 1, &cdp_memory_itf_v1),
|
CDP_DECLARE_ITF (MEMORY, 1, 1, &cdp_memory_itf_v1),
|
||||||
@@ -109,7 +139,43 @@ cdp_RegItf cdp_itfs[MAX_REG_ITFS + 1] =
|
|||||||
CDP_DECLARE_ITF (VIDEO, 1, 1, &cdp_video_itf_v1),
|
CDP_DECLARE_ITF (VIDEO, 1, 1, &cdp_video_itf_v1),
|
||||||
// TODO: put newly defined built-in interfaces here
|
// TODO: put newly defined built-in interfaces here
|
||||||
|
|
||||||
{false, false, CDPITF_KIND_INVALID, 0, 0, NULL} // term
|
{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_Error
|
||||||
@@ -123,14 +189,34 @@ cdp_GetApiError (void)
|
|||||||
bool
|
bool
|
||||||
cdp_InitApi (void)
|
cdp_InitApi (void)
|
||||||
{
|
{
|
||||||
// TODO: add whatever init code is necessary
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cdp_UninitApi (void)
|
cdp_UninitApi (void)
|
||||||
{
|
{
|
||||||
cdp_RegItf* itf;
|
cdp_ItfReg* itf;
|
||||||
|
|
||||||
// unregister custom interfaces
|
// unregister custom interfaces
|
||||||
for (itf = cdp_itfs; itf->used; ++itf)
|
for (itf = cdp_itfs; itf->used; ++itf)
|
||||||
@@ -138,31 +224,15 @@ cdp_UninitApi (void)
|
|||||||
if (!itf->builtin)
|
if (!itf->builtin)
|
||||||
{
|
{
|
||||||
itf->used = false;
|
itf->used = false;
|
||||||
itf->kind = CDPITF_KIND_INVALID;
|
if (itf->name)
|
||||||
|
HFree ((void*) itf->name);
|
||||||
|
itf->name = NULL;
|
||||||
itf->itfvtbl = NULL;
|
itf->itfvtbl = NULL;
|
||||||
|
itf->module = 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
|
static uint32
|
||||||
cdp_Host_GetApiVersion (void)
|
cdp_Host_GetApiVersion (void)
|
||||||
{
|
{
|
||||||
@@ -181,32 +251,125 @@ cdp_Host_GetApiError (void)
|
|||||||
return cdp_GetApiError ();
|
return cdp_GetApiError ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static cdp_Itf*
|
static char*
|
||||||
cdp_Host_GetItf (cdp_ItfKind itf_kind)
|
cdp_MakeContextName (const char* ctx, const char* name)
|
||||||
{
|
{
|
||||||
return cdp_GetInterface (itf_kind, CDPAPI_VERSION_1);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cdp_RegItf*
|
/***********************************************************
|
||||||
cdp_Host_RegisterItf (cdp_ItfKind itf_kind, cdp_ApiVersion ver_from,
|
* Interface system *
|
||||||
cdp_ApiVersion ver_to, cdp_Itf* itfvtbl, cdp_Module* module)
|
***********************************************************/
|
||||||
{
|
|
||||||
cdp_RegItf* regitf;
|
|
||||||
cdp_RegItf* newslot = NULL;
|
|
||||||
|
|
||||||
if (!module)
|
cdp_ItfReg*
|
||||||
|
cdp_GetInterfaceReg (const char* name, cdp_ApiVersion api_ver)
|
||||||
|
{
|
||||||
|
cdp_ItfReg* itf;
|
||||||
|
|
||||||
|
for (itf = cdp_itfs; itf->used &&
|
||||||
|
(!itf->name || stricmp(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(): "
|
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||||
"No module info supplied\n");
|
"No owner info supplied\n");
|
||||||
//return NULL;
|
//return NULL;
|
||||||
}
|
}
|
||||||
if (!itf_kind || !itfvtbl)
|
if (!name || !*name || !itfvtbl)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||||
"Null or invalid interface (from %s)\n",
|
"Null or invalid interface (from %s)\n",
|
||||||
cdp_GetModuleName (module));
|
cdp_GetModuleName (owner, true));
|
||||||
return NULL;
|
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)
|
// TODO: review version policy (below)
|
||||||
// enforce version policy and do not allow obsolete interfaces
|
// enforce version policy and do not allow obsolete interfaces
|
||||||
// POLICY: all modules MUST be aware of recent API changes and will not
|
// POLICY: all modules MUST be aware of recent API changes and will not
|
||||||
@@ -217,68 +380,484 @@ cdp_Host_RegisterItf (cdp_ItfKind itf_kind, cdp_ApiVersion ver_from,
|
|||||||
if (ver_to < CDPAPI_VERSION_MIN)
|
if (ver_to < CDPAPI_VERSION_MIN)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||||
"Obsolete interface 0x%08x (from %s)\n",
|
"Obsolete interface %s (from %s)\n",
|
||||||
itf_kind, cdp_GetModuleName (module));
|
name, cdp_GetModuleName (owner, true));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if extension already registered
|
id_name = cdp_MakeContextName (ctx, name);
|
||||||
for (regitf = cdp_itfs; regitf->used &&
|
|
||||||
(regitf->kind != itf_kind ||
|
// check if interface already registered
|
||||||
ver_from < regitf->ver_from || ver_to > regitf->ver_to);
|
for (itfreg = cdp_itfs; itfreg->used &&
|
||||||
++regitf)
|
(!itfreg->name || stricmp(itfreg->name, id_name) != 0 ||
|
||||||
|
ver_from < itfreg->ver_from || ver_to > itfreg->ver_to);
|
||||||
|
++itfreg)
|
||||||
{
|
{
|
||||||
// and pick up an empty slot (where available)
|
// and pick up an empty slot (where available)
|
||||||
if (!newslot && !regitf->kind)
|
if (!newslot && !itfreg->name)
|
||||||
newslot = regitf;
|
newslot = itfreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regitf >= cdp_itfs + MAX_REG_ITFS)
|
if (itfreg >= cdp_itfs + MAX_REG_ITFS)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||||
"Interfaces limit reached\n");
|
"Interfaces limit reached\n");
|
||||||
|
HFree (id_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (regitf->kind)
|
else if (itfreg->name)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||||
"interface 0x%08x already registered for these versions, "
|
"Interface %s already registered for these versions, "
|
||||||
"%s denied\n",
|
"%s denied\n",
|
||||||
itf_kind, cdp_GetModuleName (module));
|
name, cdp_GetModuleName (owner, true));
|
||||||
|
HFree (id_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newslot)
|
if (!newslot)
|
||||||
{
|
{
|
||||||
newslot = regitf;
|
newslot = itfreg;
|
||||||
newslot->used = true;
|
newslot->used = true;
|
||||||
// make next one a term
|
// make next one a term
|
||||||
regitf[1].builtin = false;
|
itfreg[1].builtin = false;
|
||||||
regitf[1].used = false;
|
itfreg[1].used = false;
|
||||||
regitf[1].kind = CDPITF_KIND_INVALID;
|
itfreg[1].name = NULL;
|
||||||
regitf[1].itfvtbl = NULL;
|
itfreg[1].itfvtbl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
newslot->kind = itf_kind;
|
newslot->name = id_name;
|
||||||
newslot->ver_from = ver_from;
|
newslot->ver_from = ver_from;
|
||||||
newslot->ver_to = ver_to;
|
newslot->ver_to = ver_to;
|
||||||
newslot->itfvtbl = itfvtbl;
|
newslot->itfvtbl = itfvtbl;
|
||||||
newslot->module = module;
|
newslot->module = owner;
|
||||||
|
|
||||||
return newslot;
|
return newslot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cdp_Host_UnregisterItf (cdp_RegItf* regitf)
|
cdp_Host_UnregisterItf (cdp_ItfReg* itfreg)
|
||||||
{
|
{
|
||||||
if (regitf < cdp_itfs || regitf >= cdp_itfs + MAX_REG_ITFS ||
|
if (itfreg < cdp_itfs || itfreg >= cdp_itfs + MAX_REG_ITFS ||
|
||||||
!regitf->kind || !regitf->itfvtbl)
|
!itfreg->name || !itfreg->itfvtbl)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cdp_Host_UnregisterItf(): "
|
fprintf (stderr, "cdp_Host_UnregisterItf(): "
|
||||||
"Invalid or expired interface passed\n");
|
"Invalid or expired interface passed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
regitf->kind = CDPITF_KIND_INVALID;
|
if (!itfreg->builtin)
|
||||||
regitf->itfvtbl = NULL;
|
{
|
||||||
|
HFree ((void*) 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 || stricmp(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 || stricmp(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 ((void*) 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,36 +46,76 @@ typedef enum
|
|||||||
CDPERR_INIT_FAILED = 7,
|
CDPERR_INIT_FAILED = 7,
|
||||||
CDPERR_NO_ITF = 8,
|
CDPERR_NO_ITF = 8,
|
||||||
CDPERR_DUPE_ITF = 9,
|
CDPERR_DUPE_ITF = 9,
|
||||||
|
CDPERR_NO_EVENT = 10,
|
||||||
|
CDPERR_DUPE_EVENT = 11,
|
||||||
CDPERR_OTHER = 1000,
|
CDPERR_OTHER = 1000,
|
||||||
|
|
||||||
} cdp_Error;
|
} cdp_Error;
|
||||||
|
|
||||||
typedef struct cdp_Module cdp_Module;
|
typedef struct cdp_Module cdp_Module;
|
||||||
typedef void cdp_Itf;
|
typedef void cdp_Itf;
|
||||||
typedef struct cdp_RegItf cdp_RegItf;
|
typedef struct cdp_ItfReg cdp_ItfReg;
|
||||||
|
|
||||||
typedef enum
|
// 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
|
||||||
{
|
{
|
||||||
CDPITF_KIND_INVALID = 0,
|
// fill in the first 4 members for batch registration
|
||||||
CDPITF_KIND_HOST = 1,
|
// fill in the 1st member for batch lookup
|
||||||
CDPITF_KIND_MEMORY = 2,
|
// terminate an array of these defs with name == NULL
|
||||||
CDPITF_KIND_IO = 3,
|
const char* name; // interface ID
|
||||||
CDPITF_KIND_THREADS = 4,
|
cdp_Itf* itf; // interface pointer
|
||||||
CDPITF_KIND_TIME = 5,
|
cdp_ApiVersion ver_from; // lowest supported version
|
||||||
CDPITF_KIND_INPUT = 6,
|
cdp_ApiVersion ver_to; // highest supported version
|
||||||
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
|
cdp_Module* module; // owner module
|
||||||
# include "cdpitfs.h"
|
// the following member is only set during registration
|
||||||
|
cdp_ItfReg* reg; // registration handle (not set on lookup)
|
||||||
|
|
||||||
} cdp_ItfKind;
|
} 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
|
// Host Interface
|
||||||
// the main itf of the API, it is passed to a loaded module
|
// the main itf of the API, it is passed to a loaded module
|
||||||
@@ -86,11 +126,25 @@ typedef struct
|
|||||||
uint32 (* GetApiVersion) (void);
|
uint32 (* GetApiVersion) (void);
|
||||||
uint32 (* GetVersion) (void);
|
uint32 (* GetVersion) (void);
|
||||||
cdp_Error (* GetApiError) (void);
|
cdp_Error (* GetApiError) (void);
|
||||||
cdp_Itf* (* GetItf) (cdp_ItfKind);
|
cdp_Itf* (* GetItf) (const char* name);
|
||||||
cdp_RegItf* (* RegisterItf) (cdp_ItfKind,
|
bool (* GetItfs) (cdp_ItfDef* defs);
|
||||||
|
cdp_ItfReg* (* RegisterItf) (const char* name,
|
||||||
cdp_ApiVersion ver_from, cdp_ApiVersion ver_to,
|
cdp_ApiVersion ver_from, cdp_ApiVersion ver_to,
|
||||||
cdp_Itf*, cdp_Module*);
|
cdp_Itf*, cdp_Module*);
|
||||||
void (* UnregisterItf) (cdp_RegItf*);
|
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;
|
} cdp_Itf_HostVtbl_v1;
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ extern cdp_Itf_SoundVtbl_v1 cdp_sound_itf_v1;
|
|||||||
bool cdp_InitApi (void);
|
bool cdp_InitApi (void);
|
||||||
void cdp_UninitApi (void);
|
void cdp_UninitApi (void);
|
||||||
cdp_Error cdp_GetApiError (void);
|
cdp_Error cdp_GetApiError (void);
|
||||||
cdp_Itf* cdp_GetInterface (cdp_ItfKind itf_kind, cdp_ApiVersion api_ver);
|
cdp_Itf* cdp_GetInterface (const char* name, cdp_ApiVersion);
|
||||||
|
cdp_ItfReg* cdp_GetInterfaceReg (const char* name, cdp_ApiVersion);
|
||||||
|
|
||||||
#endif /* _CDPISND_H */
|
#endif /* _CDPISND_H */
|
||||||
|
|||||||
@@ -41,27 +41,40 @@ typedef struct
|
|||||||
uint16 host_ver_major; // minimum host version required, purely informational
|
uint16 host_ver_major; // minimum host version required, purely informational
|
||||||
uint16 host_ver_minor;
|
uint16 host_ver_minor;
|
||||||
|
|
||||||
uint32 _32_reserved1[4]; // reserved members: set to all 0s or CDP_MODINFO_RESERVED1
|
// reserved members: set all to 0 or use CDP_MODINFO_RESERVED1
|
||||||
|
uint32 _32_reserved1;
|
||||||
|
uint32 _32_reserved2;
|
||||||
|
uint32 _32_reserved3;
|
||||||
|
uint32 _32_reserved4;
|
||||||
|
|
||||||
// informational, human-only
|
const char* context_name;
|
||||||
const char* name;
|
// cannonical context name (in proper case)
|
||||||
const char* ver_string;
|
// this context will be used with all exposed objects
|
||||||
const char* author;
|
// English preferred; try to keep it below 32 chars
|
||||||
const char* url;
|
// informational, human-only; these fields have no real size
|
||||||
const char* comments;
|
// 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
|
||||||
|
|
||||||
const char* _sz_reserved2[5]; // reserved members, set to all 0s or CDP_MODINFO_RESERVED2
|
// 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
|
// mandatory, CDP entry points
|
||||||
// TODO: decide whether more EPs are necessary and if not move
|
// TODO: decide whether more EPs are necessary and if not move
|
||||||
// EPs above info-string members, abolishing _sz_reserved2
|
// EPs above info-string members, abolishing _sz_reservedX
|
||||||
bool (* module_init) (cdp_Itf_Host* hostitf);
|
bool (* module_init) (cdp_Module* module, cdp_Itf_Host* hostitf);
|
||||||
void (* module_term) ();
|
void (* module_term) ();
|
||||||
|
|
||||||
} cdp_ModuleInfo;
|
} cdp_ModuleInfo;
|
||||||
|
|
||||||
#define CDP_MODINFO_RESERVED1 {0,0,0,0}
|
#define CDP_MODINFO_RESERVED1 0,0,0,0
|
||||||
#define CDP_MODINFO_RESERVED2 {0,0,0,0,0}
|
#define CDP_MODINFO_RESERVED2 0,0,0,0
|
||||||
|
|
||||||
// the following is defined via the last mandatory member
|
// the following is defined via the last mandatory member
|
||||||
#define CDP_MODINFO_MIN_SIZE \
|
#define CDP_MODINFO_MIN_SIZE \
|
||||||
|
|||||||
@@ -36,7 +36,11 @@ dlopen (const char *filename, int flag)
|
|||||||
{
|
{
|
||||||
HMODULE hlib;
|
HMODULE hlib;
|
||||||
|
|
||||||
hlib = LoadLibraryA (filename);
|
if (filename == NULL)
|
||||||
|
hlib = GetModuleHandleA(NULL);
|
||||||
|
else
|
||||||
|
hlib = LoadLibraryA (filename);
|
||||||
|
|
||||||
if (!hlib)
|
if (!hlib)
|
||||||
wdl_last_error = GetLastError ();
|
wdl_last_error = GetLastError ();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user