mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 13:21:36 +00:00
The four files used by ALL plugins.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@337 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
e3518a7c1f
commit
ce0c0c7a1c
4 changed files with 656 additions and 0 deletions
242
plugins/plugin.c
Normal file
242
plugins/plugin.c
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
//contains generic plugin code for dll/qvm
|
||||||
|
//it's this one or the engine...
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
export_t func;
|
||||||
|
} exports_t;
|
||||||
|
extern exports_t exports[16];
|
||||||
|
|
||||||
|
int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int args[12];
|
||||||
|
args[0] = arg0;
|
||||||
|
args[1] = arg1;
|
||||||
|
args[2] = arg2;
|
||||||
|
args[3] = arg3;
|
||||||
|
args[4] = arg4;
|
||||||
|
args[5] = arg5;
|
||||||
|
args[6] = arg6;
|
||||||
|
args[7] = arg7;
|
||||||
|
args[8] = arg8;
|
||||||
|
args[9] = arg9;
|
||||||
|
args[10] = arg10;
|
||||||
|
args[11] = arg11;
|
||||||
|
// return exports[command].func(args);
|
||||||
|
ret = exports[command].func(args);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef Q3_VM
|
||||||
|
int (*syscall)( int arg, ... );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PASSFLOAT(f) *(int*)&(f)
|
||||||
|
|
||||||
|
#define ARGNAMES ,funcname
|
||||||
|
BUILTINR(void*, Plug_GetEngineFunction, (char *funcname));
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,funcname,expnum
|
||||||
|
BUILTINR(int, Plug_ExportToEngine, (char *funcname, int expnum));
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,text
|
||||||
|
BUILTIN(void, Con_Print, (char *text)); //on to main console.
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,message
|
||||||
|
BUILTIN(void, Sys_Error, (char *message)); //abort the entire engine.
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,buffer,bufsize
|
||||||
|
BUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //abort the entire engine.
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,argnum,buffer,bufsize
|
||||||
|
BUILTIN(void, Cmd_Argv, (int argnum, char *buffer, int bufsize)); //abort the entire engine.
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES
|
||||||
|
BUILTIN(void, Cmd_Argc, (void)); //abort the entire engine.
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,text,insert
|
||||||
|
BUILTIN(void, Cmd_AddText, (char *text, qboolean insert)); //abort the entire engine.
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,name,value
|
||||||
|
BUILTIN(void, Cvar_SetString, (char *name, char *value));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,name,value
|
||||||
|
BUILTIN(void, Cvar_SetFloat, (char *name, float value));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,name,retstring,sizeofretstring
|
||||||
|
BUILTINR(qboolean, Cvar_GetString, (char *name, char *retstring, int sizeofretstring));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,name
|
||||||
|
BUILTINR(float, Cvar_GetFloat, (char *name));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,name,defaultval,flags,grouphint
|
||||||
|
BUILTINR(qhandle_t, Cvar_Register, (char *name, char *defaultval, int flags, char *grouphint));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,handle,modificationcount,stringv,floatv
|
||||||
|
BUILTINR(int, Cvar_Update, (qhandle_t handle, int modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged.
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,pnum,stats,maxstats
|
||||||
|
BUILTIN(void, CL_GetStats, (int pnum, unsigned int *stats, int maxstats));
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,soundname
|
||||||
|
BUILTIN(void, LocalSound, (char *soundname));
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,name,iswadimage
|
||||||
|
BUILTINR(qhandle_t, Draw_LoadImage, (char *name, qboolean iswadimage)); //wad image is ONLY for loading out of q1 gfx.wad
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(w),PASSFLOAT(h),PASSFLOAT(s1),PASSFLOAT(t1),PASSFLOAT(s2),PASSFLOAT(t2),image
|
||||||
|
BUILTIN(void, Draw_Image, (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(w),PASSFLOAT(h)
|
||||||
|
BUILTIN(void, Draw_Fill, (int x, int y, int w, int h));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,x,y,characture
|
||||||
|
BUILTIN(void, Draw_Character, (int x, int y, unsigned int characture));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,palcol
|
||||||
|
BUILTIN(void, Draw_Colourp, (int palcol));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,PASSFLOAT(r),PASSFLOAT(g),PASSFLOAT(b)
|
||||||
|
BUILTIN(void, Draw_Colour3f, (float r, float g, float b));
|
||||||
|
#undef ARGNAMES
|
||||||
|
#define ARGNAMES ,PASSFLOAT(r),PASSFLOAT(g),PASSFLOAT(b),PASSFLOAT(a)
|
||||||
|
BUILTIN(void, Draw_Colour4f, (float r, float g, float b, float a));
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,mnum
|
||||||
|
BUILTIN(void, Menu_Control, (int mnum));
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
#define ARGNAMES ,keyname
|
||||||
|
BUILTINR(int, Key_GetKeyCode, (char *keyname));
|
||||||
|
#undef ARGNAMES
|
||||||
|
|
||||||
|
char *va(char *format, ...) //Identical in function to the one in Quake, though I can assure you that I wrote it...
|
||||||
|
{ //It's not exactly hard, just easy to use, so gets duplicated lots.
|
||||||
|
va_list argptr;
|
||||||
|
static char string[1024];
|
||||||
|
|
||||||
|
va_start (argptr, format);
|
||||||
|
vsnprintf (string, sizeof(string), format,argptr);
|
||||||
|
va_end (argptr);
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Con_Printf(char *format, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
static char string[1024];
|
||||||
|
|
||||||
|
va_start (argptr, format);
|
||||||
|
vsnprintf (string, sizeof(string), format,argptr);
|
||||||
|
va_end (argptr);
|
||||||
|
|
||||||
|
Con_Print(string);
|
||||||
|
}
|
||||||
|
void Sys_Errorf(char *format, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
static char string[1024];
|
||||||
|
|
||||||
|
va_start (argptr, format);
|
||||||
|
vsnprintf (string, sizeof(string), format,argptr);
|
||||||
|
va_end (argptr);
|
||||||
|
|
||||||
|
Sys_Error(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plug_InitStandardBuiltins(void)
|
||||||
|
{
|
||||||
|
CHECKBUILTIN(Plug_ExportToEngine);
|
||||||
|
CHECKBUILTIN(Con_Print);
|
||||||
|
CHECKBUILTIN(Sys_Error);
|
||||||
|
|
||||||
|
CHECKBUILTIN(Cmd_Args);
|
||||||
|
CHECKBUILTIN(Cmd_Argv);
|
||||||
|
CHECKBUILTIN(Cmd_Argc);
|
||||||
|
CHECKBUILTIN(Cmd_AddText);
|
||||||
|
|
||||||
|
CHECKBUILTIN(Cvar_SetString);
|
||||||
|
CHECKBUILTIN(Cvar_SetFloat);
|
||||||
|
CHECKBUILTIN(Cvar_GetString);
|
||||||
|
CHECKBUILTIN(Cvar_GetFloat);
|
||||||
|
CHECKBUILTIN(Cvar_Register);
|
||||||
|
CHECKBUILTIN(Cvar_Update);
|
||||||
|
|
||||||
|
CHECKBUILTIN(CL_GetStats);
|
||||||
|
CHECKBUILTIN(LocalSound);
|
||||||
|
CHECKBUILTIN(Menu_Control);
|
||||||
|
CHECKBUILTIN(Key_GetKeyCode);
|
||||||
|
|
||||||
|
CHECKBUILTIN(Draw_LoadImage);
|
||||||
|
CHECKBUILTIN(Draw_Image);
|
||||||
|
CHECKBUILTIN(Draw_Fill);
|
||||||
|
CHECKBUILTIN(Draw_Character);
|
||||||
|
CHECKBUILTIN(Draw_Colourp);
|
||||||
|
CHECKBUILTIN(Draw_Colour3f);
|
||||||
|
CHECKBUILTIN(Draw_Colour4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef Q3_VM
|
||||||
|
void dllEntry( int (QDECL *syscallptr)( int arg,... ) ) {
|
||||||
|
syscall = syscallptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vmvideo_t vid;
|
||||||
|
int Plug_UpdateVideo(int *args)
|
||||||
|
{
|
||||||
|
vid.width = args[0];
|
||||||
|
vid.height = args[1];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Plug_InitAPI(int *args)
|
||||||
|
{
|
||||||
|
#ifdef Q3_VM
|
||||||
|
Plug_GetEngineFunction = (void*)args[0];
|
||||||
|
#else
|
||||||
|
BUILTIN_Plug_GetEngineFunction = args[0];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Plug_InitStandardBuiltins();
|
||||||
|
|
||||||
|
Plug_Export("UpdateVideo", Plug_UpdateVideo);
|
||||||
|
return Plug_Init(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Plug_Export(char *name, export_t func)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(exports)/sizeof(exports[0]); i++)
|
||||||
|
{
|
||||||
|
if (!exports[i].name)
|
||||||
|
{
|
||||||
|
exports[i].name = name;
|
||||||
|
exports[i].func = func;
|
||||||
|
return Plug_ExportToEngine(name, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Sys_Error("Plugin exports too many functions");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports_t exports[sizeof(exports)/sizeof(exports[0])] = {
|
||||||
|
{"Plug_Init", Plug_InitAPI},
|
||||||
|
};
|
||||||
|
|
3
plugins/plugin.def
Normal file
3
plugins/plugin.def
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
EXPORTS
|
||||||
|
vmMain
|
||||||
|
dllEntry
|
120
plugins/plugin.h
Normal file
120
plugins/plugin.h
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
#ifdef Q3_VM
|
||||||
|
|
||||||
|
//qvms just call the return value, and the engine works out which one it called.
|
||||||
|
#define EBUILTIN(t, n, args) extern t (*n) args
|
||||||
|
#define BUILTINR(t, n, args) t (*n) args
|
||||||
|
#define BUILTIN(t, n, args) t (*n) args
|
||||||
|
#define CHECKBUILTIN(n) n = (void*)Plug_GetEngineFunction(#n);
|
||||||
|
#define BUILTINISVALID(n) n!=NULL
|
||||||
|
|
||||||
|
#define double float //all floats are 32bit, qvm stuff
|
||||||
|
|
||||||
|
typedef char *va_list;
|
||||||
|
#define va_start(va,f) (va = (char *)&f + sizeof(int))
|
||||||
|
#define va_arg(va, type) (*(type *)((va += sizeof(int)) - sizeof(int)))
|
||||||
|
#define va_end(va) (va = NULL)
|
||||||
|
#define NULL (void*)0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
//DLLs need a wrapper to add the extra parameter and call a boring function.
|
||||||
|
#define EBUILTIN(t, n, args) extern int BUILTIN_##n; t n args
|
||||||
|
#define BUILTINR(t, n, args) int BUILTIN_##n; t n args {return (t)syscall(BUILTIN_##n ARGNAMES);}
|
||||||
|
#define BUILTIN(t, n, args) int BUILTIN_##n; t n args {syscall(BUILTIN_##n ARGNAMES);}
|
||||||
|
#define CHECKBUILTIN(n) BUILTIN_##n = (int)Plug_GetEngineFunction(#n);
|
||||||
|
#define BUILTINISVALID(n) BUILTIN_##n != 0
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define QDECL __cdecl
|
||||||
|
#else
|
||||||
|
#define QDECL
|
||||||
|
#endif
|
||||||
|
extern int (*syscall)( int arg, ... );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {false, true} qboolean;
|
||||||
|
typedef void *qhandle_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Basic builtins:
|
||||||
|
EBUILTIN(void*, Plug_GetEngineFunction, (char *funcname)); //set up in vmMain, use this to get all other builtins
|
||||||
|
EBUILTIN(void, Con_Print, (char *text)); //on to main console.
|
||||||
|
EBUILTIN(void, Sys_Error, (char *message)); //abort the entire engine.
|
||||||
|
|
||||||
|
EBUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //abort the entire engine.
|
||||||
|
EBUILTIN(void, Cmd_Argv, (int argnum, char *buffer, int bufsize)); //abort the entire engine.
|
||||||
|
EBUILTIN(void, Cmd_Argc, (void)); //abort the entire engine.
|
||||||
|
EBUILTIN(void, Cmd_AddText, (char *text, qboolean insert));
|
||||||
|
|
||||||
|
EBUILTIN(void, Cvar_SetString, (char *name, char *value));
|
||||||
|
EBUILTIN(void, Cvar_SetFloat, (char *name, float value));
|
||||||
|
EBUILTIN(qboolean, Cvar_GetString, (char *name, char *retstring, int sizeofretstring));
|
||||||
|
EBUILTIN(float, Cvar_GetFloat, (char *name));
|
||||||
|
EBUILTIN(qhandle_t, Cvar_Register, (char *name, char *defaultval, int flags, char *grouphint));
|
||||||
|
EBUILTIN(int, Cvar_Update, (qhandle_t handle, int modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged.
|
||||||
|
|
||||||
|
EBUILTIN(void, LocalSound, (char *soundname));
|
||||||
|
EBUILTIN(void, CL_GetStats, (int pnum, unsigned int *stats, int maxstats));
|
||||||
|
|
||||||
|
EBUILTIN(void, Menu_Control, (int mnum));
|
||||||
|
EBUILTIN(int, Key_GetKeyCode, (char *keyname));
|
||||||
|
|
||||||
|
EBUILTIN(qhandle_t, Draw_LoadImage, (char *name, qboolean iswadimage)); //wad image is ONLY for loading out of q1 gfx.wad
|
||||||
|
EBUILTIN(void, Draw_Image, (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image));
|
||||||
|
EBUILTIN(void, Draw_Fill, (int x, int y, int w, int h));
|
||||||
|
EBUILTIN(void, Draw_Character, (int x, int y, unsigned int characture));
|
||||||
|
EBUILTIN(void, Draw_Colourp, (int palcol));
|
||||||
|
EBUILTIN(void, Draw_Colour3f, (float r, float g, float b));
|
||||||
|
EBUILTIN(void, Draw_Colour4f, (float r, float g, float b, float a));
|
||||||
|
|
||||||
|
typedef int (*export_t) (int *args);
|
||||||
|
char *va(char *format, ...);
|
||||||
|
int Plug_Init(int *args);
|
||||||
|
qboolean Plug_Export(char *name, export_t func);
|
||||||
|
void Con_Printf(char *format, ...);
|
||||||
|
void Sys_Errorf(char *format, ...);
|
||||||
|
typedef unsigned char qbyte;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
char string[256];
|
||||||
|
char *group;
|
||||||
|
int flags;
|
||||||
|
float value;
|
||||||
|
qhandle_t handle;
|
||||||
|
int modificationcount;
|
||||||
|
} vmcvar_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} vmvideo_t;
|
||||||
|
extern vmvideo_t vid;
|
||||||
|
|
||||||
|
#define VMCvar_SetString(c,v) \
|
||||||
|
do{ \
|
||||||
|
strcpy(c->string, v); \
|
||||||
|
c->value = (float)atof(v); \
|
||||||
|
Cvar_SetString(c->name, c->string); \
|
||||||
|
} while (0)
|
||||||
|
#define VMCvar_SetFloat(c,v) \
|
||||||
|
do { \
|
||||||
|
snprintf(c->string, sizeof(c->string), "%f", v);\
|
||||||
|
c->value = (float)(v); \
|
||||||
|
Cvar_SetFloat(c->name, c->value); \
|
||||||
|
} while(0) \
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_INFO_KEY 64
|
||||||
|
char *Info_ValueForKey (char *s, char *key);
|
||||||
|
void Info_RemoveKey (char *s, char *key);
|
||||||
|
void Info_RemovePrefixedKeys (char *start, char prefix);
|
||||||
|
void Info_RemoveNonStarKeys (char *start);
|
||||||
|
void Info_SetValueForKey (char *s, char *key, char *value, int maxsize);
|
||||||
|
void Info_SetValueForStarKey (char *s, char *key, char *value, int maxsize);
|
||||||
|
|
291
plugins/qvm_api.c
Normal file
291
plugins/qvm_api.c
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
/* An implementation of some 'standard' functions */
|
||||||
|
|
||||||
|
/* We use this with msvc too, because msvc's implementations of
|
||||||
|
_snprintf and _vsnprint differ - besides, this way we can make
|
||||||
|
sure qvms handle all the printf stuff that dlls do*/
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
this is a fairly basic implementation.
|
||||||
|
don't expect it to do much.
|
||||||
|
You can probably get a better version from somewhere.
|
||||||
|
*/
|
||||||
|
int vsnprintf(char *buffer, int maxlen, char *format, va_list vargs)
|
||||||
|
{
|
||||||
|
int tokens=0;
|
||||||
|
char *string;
|
||||||
|
char tempbuffer[64];
|
||||||
|
int _int;
|
||||||
|
float _float;
|
||||||
|
int i;
|
||||||
|
int use0s;
|
||||||
|
int precision;
|
||||||
|
|
||||||
|
if (!maxlen)
|
||||||
|
return 0;
|
||||||
|
maxlen--;
|
||||||
|
|
||||||
|
while(*format)
|
||||||
|
{
|
||||||
|
switch(*format)
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
precision= 0;
|
||||||
|
use0s=0;
|
||||||
|
retry:
|
||||||
|
switch(*(++format))
|
||||||
|
{
|
||||||
|
case '0':
|
||||||
|
if (!precision)
|
||||||
|
{
|
||||||
|
use0s=true;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
precision=precision*10+*format-'0';
|
||||||
|
goto retry;
|
||||||
|
case '%': /*emit a %*/
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *format;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
string = va_arg(vargs, char *);
|
||||||
|
if (!string)
|
||||||
|
string = "(null)";
|
||||||
|
if (precision)
|
||||||
|
{
|
||||||
|
while (*string && precision--)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *string++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (*string)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *string++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokens++;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
_int = va_arg(vargs, char);
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = _int;
|
||||||
|
tokens++;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
_int = va_arg(vargs, int);
|
||||||
|
if (_int < 0)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = '-';
|
||||||
|
_int *= -1;
|
||||||
|
}
|
||||||
|
i = sizeof(tempbuffer)-2;
|
||||||
|
tempbuffer[sizeof(tempbuffer)-1] = '\0';
|
||||||
|
while(_int)
|
||||||
|
{
|
||||||
|
tempbuffer[i] = _int%10 + '0';
|
||||||
|
_int/=10;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
string = tempbuffer+i+1;
|
||||||
|
|
||||||
|
if (!*string)
|
||||||
|
{
|
||||||
|
i=61;
|
||||||
|
string = tempbuffer+i+1;
|
||||||
|
string[0] = '0';
|
||||||
|
string[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
precision -= 62-i;
|
||||||
|
while (precision>0)
|
||||||
|
{
|
||||||
|
string--;
|
||||||
|
if (use0s)
|
||||||
|
*string = '0';
|
||||||
|
else
|
||||||
|
*string = ' ';
|
||||||
|
precision--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*string)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *string++;
|
||||||
|
}
|
||||||
|
tokens++;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
_float = va_arg(vargs, float);
|
||||||
|
|
||||||
|
//integer part.
|
||||||
|
_int = (int)_float;
|
||||||
|
if (_int < 0)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = '-';
|
||||||
|
_int *= -1;
|
||||||
|
}
|
||||||
|
i = sizeof(tempbuffer)-2;
|
||||||
|
tempbuffer[sizeof(tempbuffer)-1] = '\0';
|
||||||
|
while(_int)
|
||||||
|
{
|
||||||
|
tempbuffer[i--] = _int%10 + '0';
|
||||||
|
_int/=10;
|
||||||
|
}
|
||||||
|
string = tempbuffer+i+1;
|
||||||
|
while (*string)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *string++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_int = sizeof(tempbuffer)-2-i;
|
||||||
|
|
||||||
|
//floating point part.
|
||||||
|
_float -= (int)_float;
|
||||||
|
i = 0;
|
||||||
|
tempbuffer[i++] = '.';
|
||||||
|
while(_float - (int)_float)
|
||||||
|
{
|
||||||
|
if (i + _int > 7) //remove the excess presision.
|
||||||
|
break;
|
||||||
|
|
||||||
|
_float*=10;
|
||||||
|
tempbuffer[i++] = (int)_float%10 + '0';
|
||||||
|
}
|
||||||
|
if (i == 1) //no actual fractional part
|
||||||
|
{
|
||||||
|
tokens++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//concatinate to our string
|
||||||
|
tempbuffer[i] = '\0';
|
||||||
|
string = tempbuffer;
|
||||||
|
while (*string)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *string++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
string = "ERROR IN FORMAT";
|
||||||
|
while (*string)
|
||||||
|
{
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *string++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (--maxlen < 0)
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
*buffer++ = *format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
{*buffer++='\0';return tokens;}
|
||||||
|
}
|
||||||
|
|
||||||
|
int snprintf(char *buffer, int maxlen, char *format, ...)
|
||||||
|
{
|
||||||
|
int p;
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
va_start (argptr, format);
|
||||||
|
p = vsnprintf (buffer, maxlen, format,argptr);
|
||||||
|
va_end (argptr);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q3_VM
|
||||||
|
int strlen(const char *s)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
while(*s++)
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strncmp (char *s1, char *s2, int count)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (!count--)
|
||||||
|
return 0;
|
||||||
|
if (*s1 != *s2)
|
||||||
|
return -1; // strings not equal
|
||||||
|
if (!*s1)
|
||||||
|
return 0; // strings are equal
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp(char *s1, char *s2)
|
||||||
|
{
|
||||||
|
while(*s1)
|
||||||
|
{
|
||||||
|
if (*s1 != *s2)
|
||||||
|
return *s1<*s1?-1:1;
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
if (*s2) //s2 was longer.
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strstr(char *str, char *sub)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *p2;
|
||||||
|
int l = strlen(sub)-1;
|
||||||
|
if (l < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
if (*str == *sub)
|
||||||
|
{
|
||||||
|
if (!strncmp (str+1, sub+1, l))
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in a new issue