diff --git a/plugins/memory.c b/plugins/memory.c new file mode 100644 index 00000000..33eef0cf --- /dev/null +++ b/plugins/memory.c @@ -0,0 +1,120 @@ +//a qvm compatable malloc/free interface + +//This is seperate from qvm_api.c because this has a chunk of memory that simply isn't needed in all plugins. + +#include "plugin.h" + +struct memhead_s +{ + int size; + int isfree; + struct memhead_s *next; + struct memhead_s *prev; +}; + +#ifndef MEMSIZE +#define MEMSIZE 1024*64 //64kb +#endif + +static struct memhead_s *head; +static char memory[MEMSIZE]; + +//we create two dummies at the start and end +//these will never be freed +//we then have dynamic allocation in the middle. +//sizes include the headers + +void *malloc(int size) +{ + struct memhead_s *lasthead; + + if (size <= 0) + return NULL; + + size = ((size+4) & 3) + sizeof(struct memhead_s); //round up + if (!head) + { //first call + struct memhead_s *last; + struct memhead_s *middle; + struct memhead_s *first; + + first = (struct memhead_s*)memory; + last= (struct memhead_s*)((char*)memory - sizeof(struct memhead_s)); + first->size = last->size = sizeof(struct memhead_s); + first->isfree = last->isfree = false; + + middle = (struct memhead_s*)((char*)first+first->size); + middle->size = sizeof(memory) - sizeof(struct memhead_s)*3; + middle->isfree = true; + + last->next = first; + last->prev = middle; + first->next = middle; + first->prev = last; + middle->next = last; + middle->prev = first; + + head = middle; + } + lasthead = head; + + do + { + if (head->isfree) + if (head->size >= size) + { + if (head->size > size + sizeof(struct memhead_s)+1) + { //split + struct memhead_s *split; + split = (struct memhead_s*)((char*)head + size); + split->size = head->size - size; + head->size = size; + split->next = head->next; + split->prev = head; + head->next = split; + split->next->prev = split; + split->isfree = true; + head->isfree = false; + } + else + { //no point in splitting + head->isfree = false; + } + + return (char*)head + sizeof(struct memhead_s); + } + head = head->next; + } while (lasthead != head); + + return NULL; +} + +static struct memhead_s *mergeblock(struct memhead_s *b1, struct memhead_s *b2) +{ + //b1 and b2 must be in logical order + + b1->next = b2->next; + b2->next->prev = b1; + b1->size += b2->size; + + return b1; +} + +void free(void *mem) +{ //the foot hopefully isn't going to be freed + struct memhead_s *block; + block = (struct memhead_s*)((char*)mem - sizeof(struct memhead_s)); + + if (block->isfree) + Sys_Error("(plugin) Double free\n"); + block->isfree = true; + + if (block->prev->isfree) + { //merge previous with this + block = mergeblock(block->prev, block); + } + if (block->next) + { //merge next with this + block = mergeblock(block, block->next); + } +} diff --git a/plugins/plugin.c b/plugins/plugin.c index a8e76f4e..2b08cf06 100644 --- a/plugins/plugin.c +++ b/plugins/plugin.c @@ -73,7 +73,10 @@ BUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //abort the entire engine. 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. +BUILTINR(int, Cmd_Argc, (void)); //abort the entire engine. +#undef ARGNAMES +#define ARGNAMES ,msg +BUILTIN(void, Cmd_TokenizeString, (char *msg)); //abort the entire engine. #undef ARGNAMES #define ARGNAMES ,text,insert @@ -96,7 +99,7 @@ BUILTINR(float, Cvar_GetFloat, (char *name)); 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. +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 @@ -129,6 +132,10 @@ BUILTIN(void, Draw_Colour3f, (float r, float g, float b)); BUILTIN(void, Draw_Colour4f, (float r, float g, float b, float a)); #undef ARGNAMES +#define ARGNAMES ,s +BUILTIN(void, SCR_CenterPrint, (char *s)); +#undef ARGNAMES + #define ARGNAMES ,src,srcwidth,srcheight,x,y,width,height BUILTIN(void, Media_ShowFrameRGBA_32, (void *src, int srcwidth, int srcheight, int x, int y, int width, int height)); #undef ARGNAMES @@ -167,6 +174,9 @@ BUILTIN(void, memcpy, (void *out, void *in, int len)); #define ARGNAMES ,out,in,len BUILTIN(void, memset, (void *out, int in, int len)); #undef ARGNAMES +#define ARGNAMES ,out,in,len +BUILTIN(void, memmove, (void *out, void *in, int len)); +#undef ARGNAMES #endif char *va(char *format, ...) //Identical in function to the one in Quake, though I can assure you that I wrote it... @@ -208,6 +218,7 @@ void Plug_InitStandardBuiltins(void) { #ifdef Q3_VM CHECKBUILTIN(memcpy); + CHECKBUILTIN(memmove); CHECKBUILTIN(memset); #endif @@ -253,6 +264,7 @@ void Plug_InitStandardBuiltins(void) CHECKBUILTIN(Draw_Colourp); CHECKBUILTIN(Draw_Colour3f); CHECKBUILTIN(Draw_Colour4f); + CHECKBUILTIN(SCR_CenterPrint); CHECKBUILTIN(Media_ShowFrameRGBA_32); diff --git a/plugins/plugin.h b/plugins/plugin.h index 8c53cae0..65e17a91 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -17,6 +17,12 @@ typedef char *va_list; #define va_end(va) (va = NULL) #define NULL (void*)0 + +void *malloc(int size); +void free(void *mem); +char *strstr(char *str, const char *sub); +void strlcpy(char *d, const char *s, int n); + #else #include @@ -35,10 +41,16 @@ typedef char *va_list; #endif extern int (*plugin_syscall)( int arg, ... ); +#ifdef _WIN32 +void strlcpy(char *d, const char *s, int n); +int snprintf(char *buffer, int maxlen, char *format, ...); +#endif + #endif typedef enum {false, true} qboolean; typedef void *qhandle_t; +typedef float vec3_t[3]; @@ -53,15 +65,16 @@ EBUILTIN(unsigned int, Sys_Milliseconds, ()); EBUILTIN(void, Cmd_AddCommand, (char *buffer)); //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(int, Cmd_Argc, (void)); //abort the entire engine. EBUILTIN(void, Cmd_AddText, (char *text, qboolean insert)); +EBUILTIN(void, Cmd_Tokenize, (char *msg)); //abort the entire engine. 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(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)); @@ -79,6 +92,7 @@ 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)); +EBUILTIN(void, SCR_CenterPrint, (char *s)); EBUILTIN(int, Net_TCPConnect, (char *ip, int port)); EBUILTIN(int, Net_TCPListen, (char *ip, int port, int maxcount)); @@ -87,6 +101,8 @@ EBUILTIN(int, Net_Recv, (int socket, void *buffer, int len)); EBUILTIN(int, Net_Send, (int socket, void *buffer, int len)); EBUILTIN(void, Net_Close, (int socket)); #define N_WOULDBLOCK -1 +#define NET_CLIENTPORT -1 +#define NET_SERVERPORT -2 diff --git a/plugins/qvm_api.c b/plugins/qvm_api.c index e4687673..6b1e13a4 100644 --- a/plugins/qvm_api.c +++ b/plugins/qvm_api.c @@ -244,7 +244,7 @@ int strlen(const char *s) return len; } -int strncmp (char *s1, char *s2, int count) +int strncmp (const char *s1, const char *s2, int count) { while (1) { @@ -261,7 +261,7 @@ int strncmp (char *s1, char *s2, int count) return -1; } -int strcmp(char *s1, char *s2) +int strcmp(const char *s1, const char *s2) { while(*s1) { @@ -275,7 +275,7 @@ int strcmp(char *s1, char *s2) return 0; } -char *strstr(char *str, char *sub) +char *strstr(char *str, const char *sub) { char *p; char *p2; @@ -295,9 +295,82 @@ char *strstr(char *str, char *sub) return NULL; } +char *strchr(char *str, char sub) +{ + char *p; + char *p2; + + while(*str) + { + if (*str == sub) + return str; + str++; + } + + return NULL; +} + +int atoi(char *str) +{ + int sign; + int num; + int base = 10; + + while(*(unsigned char*)str < ' ' && *str) + str++; + + if (*str == '-') + { + sign = -1; + str++; + } + + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + { + base = 16; + str += 2; + } + + while(1) + { + if (*str >= '0' && *str <= '9') + num = num*base + (*str - '0'); + else if (*str >= 'a' && *str <= 'a'+base-10) + num = num*base + (*str - 'a')+10; + else if (*str >= 'A' && *str <= 'A'+base-10) + num = num*base + (*str - 'A')+10; + else break; //bad char + } + return num*sign; +} + +void strcpy(char *d, const char *s) +{ + while (*s) + { + *d++ = *s++; + } + *d='\0'; +} + +static long randx = 1; +void srand(unsigned int x) +{ + randx = x; +} +int getseed(void) +{ + return randx; +} +int rand(void) +{ + return(((randx = randx*1103515245 + 12345)>>16) & 077777); +} + + #endif -void Q_strncpyz(char *d, const char *s, int n) +void strlcpy(char *d, const char *s, int n) { int i; n--;