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 "cdpmod.h"
|
||||
#include "uio.h"
|
||||
#include "uqmversion.h"
|
||||
#ifdef WIN32
|
||||
# include "windl.h"
|
||||
#else
|
||||
@@ -35,21 +36,50 @@
|
||||
#define MAX_CDPS 63
|
||||
#define CDPDIR "cdps"
|
||||
|
||||
// internal adl module representation
|
||||
// cdp_Module will be cast to and from this
|
||||
// internal CDP module representation
|
||||
struct cdp_Module
|
||||
{
|
||||
bool used; // used at least once indicator
|
||||
void* hmodule; // loaded module handle
|
||||
uint32 refcount; // reference count
|
||||
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_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;
|
||||
|
||||
static bool cdp_inited = false;
|
||||
static cdp_Module cdp_modules[MAX_CDPS + 1];
|
||||
static cdp_Error cdp_last_error = CDPERR_NONE;
|
||||
static char cdp_path[PATH_MAX] = "";
|
||||
|
||||
@@ -64,13 +94,25 @@ cdp_GetError (void)
|
||||
bool
|
||||
cdp_Init (void)
|
||||
{
|
||||
int i;
|
||||
void* hkernel;
|
||||
|
||||
if (cdp_inited)
|
||||
{
|
||||
fprintf (stderr, "cdp_Init(): called when already inited\n");
|
||||
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);
|
||||
cdp_InitApi ();
|
||||
cdp_inited = true;
|
||||
@@ -94,6 +136,7 @@ cdp_Uninit (void)
|
||||
|
||||
cdp_Module*
|
||||
cdp_LoadModule (const char* modname)
|
||||
// special value for modname: NULL - refers to kernel (UQM exe)
|
||||
{
|
||||
void* mod;
|
||||
char modpath[PATH_MAX];
|
||||
@@ -104,6 +147,9 @@ cdp_LoadModule (const char* modname)
|
||||
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");
|
||||
@@ -173,24 +219,33 @@ cdp_LoadModule (const char* modname)
|
||||
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(): "
|
||||
"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;
|
||||
}
|
||||
|
||||
if (!newslot)
|
||||
{
|
||||
newslot = cdp;
|
||||
newslot->used = true;
|
||||
}
|
||||
newslot->hmodule = mod;
|
||||
newslot->refcount = 1;
|
||||
newslot->info = info;
|
||||
|
||||
return newslot;
|
||||
}
|
||||
@@ -210,7 +265,7 @@ cdp_FreeModule (cdp_Module* module)
|
||||
{
|
||||
cdp_Module* modslot = cdp_CheckModule (module);
|
||||
|
||||
if (!modslot)
|
||||
if (!modslot || modslot->builtin)
|
||||
return;
|
||||
|
||||
modslot->refcount--;
|
||||
@@ -227,13 +282,38 @@ cdp_FreeModule (cdp_Module* module)
|
||||
}
|
||||
|
||||
const char*
|
||||
cdp_GetModuleName (cdp_Module* module)
|
||||
cdp_GetModuleContext (cdp_Module* module, bool bMetaString)
|
||||
{
|
||||
cdp_Module* modslot = cdp_CheckModule (module);
|
||||
if (!modslot)
|
||||
return "(Error)";
|
||||
if (!modslot->info->name)
|
||||
return "(Null)";
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -247,24 +327,38 @@ cdp_GetModuleVersion (cdp_Module* module)
|
||||
}
|
||||
|
||||
const char*
|
||||
cdp_GetModuleVersionString (cdp_Module* module)
|
||||
cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString)
|
||||
{
|
||||
cdp_Module* modslot = cdp_CheckModule (module);
|
||||
if (!modslot)
|
||||
return "(Error)";
|
||||
if (!modslot->info->ver_string)
|
||||
return "(Null)";
|
||||
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)
|
||||
cdp_GetModuleComment (cdp_Module* module, bool bMetaString)
|
||||
{
|
||||
cdp_Module* modslot = cdp_CheckModule (module);
|
||||
if (!modslot)
|
||||
return "(Error)";
|
||||
if (!modslot->info->comments)
|
||||
return "(Null)";
|
||||
if (bMetaString)
|
||||
{
|
||||
if (!modslot)
|
||||
return "(Error)";
|
||||
if (!modslot->info->comments)
|
||||
return "(Null)";
|
||||
}
|
||||
else if (!modslot)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return modslot->info->comments;
|
||||
}
|
||||
|
||||
@@ -309,9 +403,9 @@ cdp_LoadAllModules (void)
|
||||
{
|
||||
nummods++;
|
||||
fprintf (stderr, "\tloaded CDP: %s v%s (%s)\n",
|
||||
cdp_GetModuleName (mod),
|
||||
cdp_GetModuleVersionString (mod),
|
||||
cdp_GetModuleComment (mod));
|
||||
cdp_GetModuleName (mod, true),
|
||||
cdp_GetModuleVersionString (mod, true),
|
||||
cdp_GetModuleComment (mod, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -337,7 +431,7 @@ cdp_FreeAllModules (void)
|
||||
|
||||
for (cdp = cdp_modules; cdp->used; ++cdp)
|
||||
{
|
||||
if (cdp->hmodule)
|
||||
if (!cdp->builtin && cdp->hmodule)
|
||||
cdp_FreeModule (cdp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,14 @@ void cdp_Uninit (void);
|
||||
cdp_Error cdp_GetError (void);
|
||||
cdp_Module* cdp_LoadModule (const char* modname);
|
||||
void cdp_FreeModule (cdp_Module* module);
|
||||
const char* cdp_GetModuleName (cdp_Module* module);
|
||||
// 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);
|
||||
const char* cdp_GetModuleComment (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);
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
// CDP IO Interface entry points
|
||||
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);
|
||||
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,
|
||||
uio_Stream *stream);
|
||||
int (* fseek) (uio_Stream *stream, long offset, int whence);
|
||||
|
||||
@@ -25,18 +25,33 @@
|
||||
#include "cdpint.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 uint32 cdp_Host_GetApiVersion (void);
|
||||
static uint32 cdp_Host_GetVersion (void);
|
||||
static cdp_Error cdp_Host_GetApiError (void);
|
||||
static cdp_Itf* cdp_Host_GetItf (cdp_ItfKind);
|
||||
static cdp_RegItf* cdp_Host_RegisterItf (cdp_ItfKind,
|
||||
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_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
|
||||
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_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 =
|
||||
@@ -84,23 +113,24 @@ cdp_Itf_VideoVtbl_v1 cdp_video_itf_v1 =
|
||||
VideoDecoder_Lookup,
|
||||
};
|
||||
|
||||
struct cdp_RegItf
|
||||
// the actual interface registration struct/handle
|
||||
struct cdp_ItfReg
|
||||
{
|
||||
bool builtin;
|
||||
bool used;
|
||||
cdp_ItfKind kind;
|
||||
const char* name;
|
||||
cdp_ApiVersion ver_from;
|
||||
cdp_ApiVersion ver_to;
|
||||
cdp_Itf* itfvtbl;
|
||||
cdp_Module* module;
|
||||
};
|
||||
|
||||
#define CDP_DECLARE_ITF(k,vf,vt,vtbl) \
|
||||
{true, true, CDPITF_KIND_##k, \
|
||||
#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_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 (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),
|
||||
// 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
|
||||
@@ -123,14 +189,34 @@ cdp_GetApiError (void)
|
||||
bool
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
cdp_UninitApi (void)
|
||||
{
|
||||
cdp_RegItf* itf;
|
||||
cdp_ItfReg* itf;
|
||||
|
||||
// unregister custom interfaces
|
||||
for (itf = cdp_itfs; itf->used; ++itf)
|
||||
@@ -138,31 +224,15 @@ cdp_UninitApi (void)
|
||||
if (!itf->builtin)
|
||||
{
|
||||
itf->used = false;
|
||||
itf->kind = CDPITF_KIND_INVALID;
|
||||
if (itf->name)
|
||||
HFree ((void*) itf->name);
|
||||
itf->name = 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
|
||||
cdp_Host_GetApiVersion (void)
|
||||
{
|
||||
@@ -181,32 +251,125 @@ cdp_Host_GetApiError (void)
|
||||
return cdp_GetApiError ();
|
||||
}
|
||||
|
||||
static cdp_Itf*
|
||||
cdp_Host_GetItf (cdp_ItfKind itf_kind)
|
||||
static char*
|
||||
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,
|
||||
cdp_ApiVersion ver_to, cdp_Itf* itfvtbl, cdp_Module* module)
|
||||
{
|
||||
cdp_RegItf* regitf;
|
||||
cdp_RegItf* newslot = NULL;
|
||||
/***********************************************************
|
||||
* Interface system *
|
||||
***********************************************************/
|
||||
|
||||
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(): "
|
||||
"No module info supplied\n");
|
||||
"No owner info supplied\n");
|
||||
//return NULL;
|
||||
}
|
||||
if (!itf_kind || !itfvtbl)
|
||||
if (!name || !*name || !itfvtbl)
|
||||
{
|
||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||
"Null or invalid interface (from %s)\n",
|
||||
cdp_GetModuleName (module));
|
||||
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
|
||||
@@ -217,68 +380,484 @@ cdp_Host_RegisterItf (cdp_ItfKind itf_kind, cdp_ApiVersion ver_from,
|
||||
if (ver_to < CDPAPI_VERSION_MIN)
|
||||
{
|
||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||
"Obsolete interface 0x%08x (from %s)\n",
|
||||
itf_kind, cdp_GetModuleName (module));
|
||||
"Obsolete interface %s (from %s)\n",
|
||||
name, cdp_GetModuleName (owner, true));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check if extension already registered
|
||||
for (regitf = cdp_itfs; regitf->used &&
|
||||
(regitf->kind != itf_kind ||
|
||||
ver_from < regitf->ver_from || ver_to > regitf->ver_to);
|
||||
++regitf)
|
||||
id_name = cdp_MakeContextName (ctx, name);
|
||||
|
||||
// check if interface already registered
|
||||
for (itfreg = cdp_itfs; itfreg->used &&
|
||||
(!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)
|
||||
if (!newslot && !regitf->kind)
|
||||
newslot = regitf;
|
||||
if (!newslot && !itfreg->name)
|
||||
newslot = itfreg;
|
||||
}
|
||||
|
||||
if (regitf >= cdp_itfs + MAX_REG_ITFS)
|
||||
if (itfreg >= cdp_itfs + MAX_REG_ITFS)
|
||||
{
|
||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||
"Interfaces limit reached\n");
|
||||
HFree (id_name);
|
||||
return NULL;
|
||||
}
|
||||
else if (regitf->kind)
|
||||
else if (itfreg->name)
|
||||
{
|
||||
fprintf (stderr, "cdp_Host_RegisterItf(): "
|
||||
"interface 0x%08x already registered for these versions, "
|
||||
"Interface %s already registered for these versions, "
|
||||
"%s denied\n",
|
||||
itf_kind, cdp_GetModuleName (module));
|
||||
name, cdp_GetModuleName (owner, true));
|
||||
HFree (id_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!newslot)
|
||||
{
|
||||
newslot = regitf;
|
||||
newslot = itfreg;
|
||||
newslot->used = true;
|
||||
// make next one a term
|
||||
regitf[1].builtin = false;
|
||||
regitf[1].used = false;
|
||||
regitf[1].kind = CDPITF_KIND_INVALID;
|
||||
regitf[1].itfvtbl = NULL;
|
||||
itfreg[1].builtin = false;
|
||||
itfreg[1].used = false;
|
||||
itfreg[1].name = NULL;
|
||||
itfreg[1].itfvtbl = NULL;
|
||||
}
|
||||
|
||||
newslot->kind = itf_kind;
|
||||
newslot->name = id_name;
|
||||
newslot->ver_from = ver_from;
|
||||
newslot->ver_to = ver_to;
|
||||
newslot->itfvtbl = itfvtbl;
|
||||
newslot->module = module;
|
||||
newslot->module = owner;
|
||||
|
||||
return newslot;
|
||||
}
|
||||
|
||||
static void
|
||||
cdp_Host_UnregisterItf (cdp_RegItf* regitf)
|
||||
cdp_Host_UnregisterItf (cdp_ItfReg* itfreg)
|
||||
{
|
||||
if (regitf < cdp_itfs || regitf >= cdp_itfs + MAX_REG_ITFS ||
|
||||
!regitf->kind || !regitf->itfvtbl)
|
||||
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;
|
||||
}
|
||||
|
||||
regitf->kind = CDPITF_KIND_INVALID;
|
||||
regitf->itfvtbl = NULL;
|
||||
if (!itfreg->builtin)
|
||||
{
|
||||
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_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_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,
|
||||
CDPITF_KIND_HOST = 1,
|
||||
CDPITF_KIND_MEMORY = 2,
|
||||
CDPITF_KIND_IO = 3,
|
||||
CDPITF_KIND_THREADS = 4,
|
||||
CDPITF_KIND_TIME = 5,
|
||||
CDPITF_KIND_INPUT = 6,
|
||||
CDPITF_KIND_TASK = 7,
|
||||
CDPITF_KIND_RESOURCE = 8,
|
||||
CDPITF_KIND_SOUND = 9,
|
||||
CDPITF_KIND_VIDEO = 10,
|
||||
CDPITF_KIND_GFX = 11,
|
||||
CDPITF_KIND_MIXER = 12,
|
||||
// anything up to 65536 is reserved
|
||||
// apply for your KIND (range) officially in UQM bugzilla (for now)
|
||||
// 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
|
||||
|
||||
// custom interfaces live here
|
||||
# include "cdpitfs.h"
|
||||
cdp_Module* module; // owner module
|
||||
// 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
|
||||
// the main itf of the API, it is passed to a loaded module
|
||||
@@ -86,11 +126,25 @@ typedef struct
|
||||
uint32 (* GetApiVersion) (void);
|
||||
uint32 (* GetVersion) (void);
|
||||
cdp_Error (* GetApiError) (void);
|
||||
cdp_Itf* (* GetItf) (cdp_ItfKind);
|
||||
cdp_RegItf* (* RegisterItf) (cdp_ItfKind,
|
||||
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_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;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ extern cdp_Itf_SoundVtbl_v1 cdp_sound_itf_v1;
|
||||
bool cdp_InitApi (void);
|
||||
void cdp_UninitApi (void);
|
||||
cdp_Error cdp_GetApiError (void);
|
||||
cdp_Itf* cdp_GetInterface (cdp_ItfKind itf_kind, cdp_ApiVersion api_ver);
|
||||
cdp_Itf* cdp_GetInterface (const char* name, cdp_ApiVersion);
|
||||
cdp_ItfReg* cdp_GetInterfaceReg (const char* name, cdp_ApiVersion);
|
||||
|
||||
#endif /* _CDPISND_H */
|
||||
|
||||
@@ -41,27 +41,40 @@ typedef struct
|
||||
uint16 host_ver_major; // minimum host version required, purely informational
|
||||
uint16 host_ver_minor;
|
||||
|
||||
uint32 _32_reserved1[4]; // reserved members: set to all 0s or CDP_MODINFO_RESERVED1
|
||||
// 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* name;
|
||||
const char* ver_string;
|
||||
const char* author;
|
||||
const char* url;
|
||||
const char* comments;
|
||||
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
|
||||
|
||||
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
|
||||
// TODO: decide whether more EPs are necessary and if not move
|
||||
// EPs above info-string members, abolishing _sz_reserved2
|
||||
bool (* module_init) (cdp_Itf_Host* hostitf);
|
||||
// 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,0}
|
||||
#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 \
|
||||
|
||||
@@ -36,7 +36,11 @@ dlopen (const char *filename, int flag)
|
||||
{
|
||||
HMODULE hlib;
|
||||
|
||||
hlib = LoadLibraryA (filename);
|
||||
if (filename == NULL)
|
||||
hlib = GetModuleHandleA(NULL);
|
||||
else
|
||||
hlib = LoadLibraryA (filename);
|
||||
|
||||
if (!hlib)
|
||||
wdl_last_error = GetLastError ();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user