1 /*
2 	bi_msgbuf.c
3 
4 	CSQC message buffer builtins
5 
6 	Copyright (C) 2012 Bill Currie <bill:taniwha.org>
7 
8 	Author: Bill Currie <bill:taniwha.org>
9 	Date: 2012/2/6
10 
11 	This program is free software; you can redistribute it and/or
12 	modify it under the terms of the GNU General Public License
13 	as published by the Free Software Foundation; either version 2
14 	of the License, or (at your option) any later version.
15 
16 	This program is distributed in the hope that it will be useful,
17 	but WITHOUT ANY WARRANTY; without even the implied warranty of
18 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 	See the GNU General Public License for more details.
21 
22 	You should have received a copy of the GNU General Public License
23 	along with this program; if not, write to:
24 
25 		Free Software Foundation, Inc.
26 		59 Temple Place - Suite 330
27 		Boston, MA  02111-1307, USA
28 
29 */
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33 
34 #include <stdlib.h>
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #endif
38 #ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 #endif
41 
42 #include "QF/msg.h"
43 #include "QF/progs.h"
44 
45 #include "rua_internal.h"
46 
47 typedef struct msgbuf_s {
48 	struct msgbuf_s *next;
49 	struct msgbuf_s **prev;
50 	qmsg_t      msg;
51 	sizebuf_t   sizebuf;
52 } msgbuf_t;
53 
54 typedef struct {
55 	PR_RESMAP (msgbuf_t) msgbuf_map;
56 } msgbuf_resources_t;
57 
58 static msgbuf_t *
msgbuf_new(msgbuf_resources_t * res)59 msgbuf_new (msgbuf_resources_t *res)
60 {
61 	PR_RESNEW (msgbuf_t, res->msgbuf_map);
62 }
63 
64 static void
msgbuf_free(progs_t * pr,msgbuf_resources_t * res,msgbuf_t * msgbuf)65 msgbuf_free (progs_t *pr, msgbuf_resources_t *res, msgbuf_t *msgbuf)
66 {
67 	PR_Zone_Free (pr, msgbuf->sizebuf.data);
68 	PR_RESFREE (msgbuf_t, res->msgbuf_map, msgbuf);
69 }
70 
71 static void
msgbuf_reset(msgbuf_resources_t * res)72 msgbuf_reset (msgbuf_resources_t *res)
73 {
74 	PR_RESRESET (msgbuf_t, res->msgbuf_map);
75 }
76 
77 static inline msgbuf_t *
msgbuf_get(msgbuf_resources_t * res,int index)78 msgbuf_get (msgbuf_resources_t *res, int index)
79 {
80 	PR_RESGET(res->msgbuf_map, index);
81 }
82 
83 static inline int
msgbuf_index(msgbuf_resources_t * res,msgbuf_t * msgbuf)84 msgbuf_index (msgbuf_resources_t *res, msgbuf_t *msgbuf)
85 {
86 	PR_RESINDEX(res->msgbuf_map, msgbuf);
87 }
88 
89 static void
bi_msgbuf_clear(progs_t * pr,void * data)90 bi_msgbuf_clear (progs_t *pr, void *data)
91 {
92 	msgbuf_resources_t *res = (msgbuf_resources_t *) data;
93 
94 	msgbuf_reset (res);
95 }
96 
97 static int
alloc_msgbuf(msgbuf_resources_t * res,byte * buf,int size)98 alloc_msgbuf (msgbuf_resources_t *res, byte *buf, int size)
99 {
100 	msgbuf_t   *msgbuf = msgbuf_new (res);
101 
102 	if (!msgbuf)
103 		return 0;
104 
105 	memset (&msgbuf->msg, 0, sizeof (msgbuf->msg));
106 	msgbuf->msg.message = &msgbuf->sizebuf;
107 	memset (&msgbuf->sizebuf, 0, sizeof (msgbuf->sizebuf));
108 	msgbuf->sizebuf.data = buf;
109 	msgbuf->sizebuf.maxsize = size;
110 	return msgbuf_index (res, msgbuf);
111 }
112 
113 static msgbuf_t *
get_msgbuf(progs_t * pr,const char * name,int msgbuf)114 get_msgbuf (progs_t *pr, const char *name, int msgbuf)
115 {
116 	msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf");
117 	msgbuf_t   *mb = msgbuf_get (res, msgbuf);
118 
119 	if (!mb)
120 		PR_RunError (pr, "invalid msgbuf handle passed to %s", name + 3);
121 	return mb;
122 }
123 
124 static void
bi_MsgBuf_New(progs_t * pr)125 bi_MsgBuf_New (progs_t *pr)
126 {
127 	msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf");
128 	int         size = P_INT (pr, 0);
129 	byte       *buf;
130 
131 	buf = PR_Zone_Malloc (pr, size);
132 	R_INT (pr) = alloc_msgbuf (res, buf, size);
133 }
134 
135 static void
bi_MsgBuf_Delete(progs_t * pr)136 bi_MsgBuf_Delete (progs_t *pr)
137 {
138 	msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf");
139 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
140 	msgbuf_free (pr, res, mb);
141 }
142 
143 static void
bi_MsgBuf_FromFile(progs_t * pr)144 bi_MsgBuf_FromFile (progs_t *pr)
145 {
146 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
147 	QFile      *file = QFile_GetFile (pr, P_INT (pr, 1));
148 	int         bytes;
149 
150 	SZ_Clear (&mb->sizebuf);
151 	bytes = Qread (file, mb->sizebuf.data, mb->sizebuf.maxsize);
152 	mb->sizebuf.cursize = bytes;
153 	MSG_BeginReading (&mb->msg);
154 }
155 
156 static void
bi_MsgBuf_MaxSize(progs_t * pr)157 bi_MsgBuf_MaxSize (progs_t *pr)
158 {
159 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
160 	R_INT (pr) = mb->sizebuf.maxsize;
161 }
162 
163 static void
bi_MsgBuf_CurSize(progs_t * pr)164 bi_MsgBuf_CurSize (progs_t *pr)
165 {
166 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
167 	R_INT (pr) = mb->sizebuf.cursize;
168 }
169 
170 static void
bi_MsgBuf_ReadCount(progs_t * pr)171 bi_MsgBuf_ReadCount (progs_t *pr)
172 {
173 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
174 	R_INT (pr) = mb->msg.readcount;
175 }
176 
177 static void
bi_MsgBuf_DataPtr(progs_t * pr)178 bi_MsgBuf_DataPtr (progs_t *pr)
179 {
180 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
181 	byte       *ptr = mb->sizebuf.data + mb->msg.readcount;
182 	R_INT (pr) = ptr - (byte *) pr->pr_strings;
183 }
184 
185 static void
bi_MsgBuf_Clear(progs_t * pr)186 bi_MsgBuf_Clear (progs_t *pr)
187 {
188 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
189 	SZ_Clear (&mb->sizebuf);
190 }
191 
192 static void
bi_MsgBuf_WriteByte(progs_t * pr)193 bi_MsgBuf_WriteByte (progs_t *pr)
194 {
195 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
196 	MSG_WriteByte (&mb->sizebuf, P_INT (pr, 1));
197 }
198 
199 static void
bi_MsgBuf_WriteShort(progs_t * pr)200 bi_MsgBuf_WriteShort (progs_t *pr)
201 {
202 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
203 	MSG_WriteShort (&mb->sizebuf, P_INT (pr, 1));
204 }
205 
206 static void
bi_MsgBuf_WriteLong(progs_t * pr)207 bi_MsgBuf_WriteLong (progs_t *pr)
208 {
209 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
210 	MSG_WriteLong (&mb->sizebuf, P_INT (pr, 1));
211 }
212 
213 static void
bi_MsgBuf_WriteFloat(progs_t * pr)214 bi_MsgBuf_WriteFloat (progs_t *pr)
215 {
216 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
217 	MSG_WriteFloat (&mb->sizebuf, P_FLOAT (pr, 1));
218 }
219 
220 static void
bi_MsgBuf_WriteString(progs_t * pr)221 bi_MsgBuf_WriteString (progs_t *pr)
222 {
223 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
224 	MSG_WriteString (&mb->sizebuf, P_GSTRING (pr, 1));
225 }
226 #if 0
227 static void
228 bi_MsgBuf_WriteBytes (progs_t *pr)
229 {
230 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
231 	MSG_WriteBytes (&mb->sizebuf, P_INT (pr, 1));
232 }
233 #endif
234 static void
bi_MsgBuf_WriteCoord(progs_t * pr)235 bi_MsgBuf_WriteCoord (progs_t *pr)
236 {
237 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
238 	MSG_WriteCoord (&mb->sizebuf, P_FLOAT (pr, 1));
239 }
240 
241 static void
bi_MsgBuf_WriteCoordV(progs_t * pr)242 bi_MsgBuf_WriteCoordV (progs_t *pr)
243 {
244 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
245 	MSG_WriteCoordV (&mb->sizebuf, P_VECTOR (pr, 1));
246 }
247 
248 static void
bi_MsgBuf_WriteCoordAngleV(progs_t * pr)249 bi_MsgBuf_WriteCoordAngleV (progs_t *pr)
250 {
251 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
252 	MSG_WriteCoordAngleV (&mb->sizebuf,
253 						  P_VECTOR (pr, 1), P_VECTOR (pr, 2));
254 }
255 
256 static void
bi_MsgBuf_WriteAngle(progs_t * pr)257 bi_MsgBuf_WriteAngle (progs_t *pr)
258 {
259 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
260 	MSG_WriteAngle (&mb->sizebuf, P_FLOAT (pr, 1));
261 }
262 
263 static void
bi_MsgBuf_WriteAngleV(progs_t * pr)264 bi_MsgBuf_WriteAngleV (progs_t *pr)
265 {
266 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
267 	MSG_WriteAngleV (&mb->sizebuf, P_VECTOR (pr, 1));
268 }
269 
270 static void
bi_MsgBuf_WriteAngle16(progs_t * pr)271 bi_MsgBuf_WriteAngle16 (progs_t *pr)
272 {
273 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
274 	MSG_WriteAngle16 (&mb->sizebuf, P_FLOAT (pr, 1));
275 }
276 
277 static void
bi_MsgBuf_WriteAngle16V(progs_t * pr)278 bi_MsgBuf_WriteAngle16V (progs_t *pr)
279 {
280 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
281 	MSG_WriteAngle16V (&mb->sizebuf, P_VECTOR (pr, 1));
282 }
283 
284 static void
bi_MsgBuf_WriteUTF8(progs_t * pr)285 bi_MsgBuf_WriteUTF8 (progs_t *pr)
286 {
287 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
288 	MSG_WriteUTF8 (&mb->sizebuf, P_INT (pr, 1));
289 }
290 
291 static void
bi_MsgBuf_BeginReading(progs_t * pr)292 bi_MsgBuf_BeginReading (progs_t *pr)
293 {
294 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
295 	MSG_BeginReading (&mb->msg);
296 }
297 
298 static void
bi_MsgBuf_ReadByte(progs_t * pr)299 bi_MsgBuf_ReadByte (progs_t *pr)
300 {
301 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
302 	R_INT (pr) = MSG_ReadByte (&mb->msg);
303 }
304 
305 static void
bi_MsgBuf_ReadShort(progs_t * pr)306 bi_MsgBuf_ReadShort (progs_t *pr)
307 {
308 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
309 	R_INT (pr) = MSG_ReadShort (&mb->msg);
310 }
311 
312 static void
bi_MsgBuf_ReadLong(progs_t * pr)313 bi_MsgBuf_ReadLong (progs_t *pr)
314 {
315 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
316 	R_INT (pr) = MSG_ReadLong (&mb->msg);
317 }
318 
319 static void
bi_MsgBuf_ReadFloat(progs_t * pr)320 bi_MsgBuf_ReadFloat (progs_t *pr)
321 {
322 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
323 	R_FLOAT (pr) = MSG_ReadFloat (&mb->msg);
324 }
325 
326 static void
bi_MsgBuf_ReadString(progs_t * pr)327 bi_MsgBuf_ReadString (progs_t *pr)
328 {
329 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
330 	const char *str;
331 
332 	str = MSG_ReadString (&mb->msg);
333 	RETURN_STRING (pr, str);
334 }
335 #if 0
336 static void
337 bi_MsgBuf_ReadBytes (progs_t *pr)
338 {
339 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
340 	MSG_ReadBytes (&mb->msg);
341 }
342 #endif
343 static void
bi_MsgBuf_ReadCoord(progs_t * pr)344 bi_MsgBuf_ReadCoord (progs_t *pr)
345 {
346 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
347 	R_FLOAT (pr) = MSG_ReadCoord (&mb->msg);
348 }
349 
350 static void
bi_MsgBuf_ReadCoordV(progs_t * pr)351 bi_MsgBuf_ReadCoordV (progs_t *pr)
352 {
353 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
354 	MSG_ReadCoordV (&mb->msg, R_VECTOR (pr));
355 }
356 
357 static void
bi_MsgBuf_ReadCoordAngleV(progs_t * pr)358 bi_MsgBuf_ReadCoordAngleV (progs_t *pr)
359 {
360 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
361 	MSG_ReadCoordAngleV (&mb->msg, P_GPOINTER (pr, 1)->vector_var,
362 						 P_GPOINTER (pr, 2)->vector_var);
363 }
364 
365 static void
bi_MsgBuf_ReadAngle(progs_t * pr)366 bi_MsgBuf_ReadAngle (progs_t *pr)
367 {
368 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
369 	R_FLOAT (pr) = MSG_ReadAngle (&mb->msg);
370 }
371 
372 static void
bi_MsgBuf_ReadAngleV(progs_t * pr)373 bi_MsgBuf_ReadAngleV (progs_t *pr)
374 {
375 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
376 	MSG_ReadAngleV (&mb->msg, R_VECTOR (pr));
377 }
378 
379 static void
bi_MsgBuf_ReadAngle16(progs_t * pr)380 bi_MsgBuf_ReadAngle16 (progs_t *pr)
381 {
382 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
383 	R_FLOAT (pr) = MSG_ReadAngle16 (&mb->msg);
384 }
385 
386 static void
bi_MsgBuf_ReadAngle16V(progs_t * pr)387 bi_MsgBuf_ReadAngle16V (progs_t *pr)
388 {
389 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
390 	MSG_ReadAngle16V (&mb->msg, R_VECTOR (pr));
391 }
392 
393 static void
bi_MsgBuf_ReadUTF8(progs_t * pr)394 bi_MsgBuf_ReadUTF8 (progs_t *pr)
395 {
396 	msgbuf_t   *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0));
397 	R_INT (pr) = MSG_ReadUTF8 (&mb->msg);
398 }
399 
400 static builtin_t builtins[] = {
401 	{"MsgBuf_New",				bi_MsgBuf_New,				-1},
402 	{"MsgBuf_Delete",			bi_MsgBuf_Delete,			-1},
403 	{"MsgBuf_FromFile",			bi_MsgBuf_FromFile,			-1},
404 	{"MsgBuf_MaxSize",			bi_MsgBuf_MaxSize,			-1},
405 	{"MsgBuf_CurSize",			bi_MsgBuf_CurSize,			-1},
406 	{"MsgBuf_ReadCount",		bi_MsgBuf_ReadCount,		-1},
407 	{"MsgBuf_DataPtr",			bi_MsgBuf_DataPtr,			-1},
408 
409 	{"MsgBuf_Clear",			bi_MsgBuf_Clear,			-1},
410 	{"MsgBuf_WriteByte",		bi_MsgBuf_WriteByte,		-1},
411 	{"MsgBuf_WriteShort",		bi_MsgBuf_WriteShort,		-1},
412 	{"MsgBuf_WriteLong",		bi_MsgBuf_WriteLong,		-1},
413 	{"MsgBuf_WriteFloat",		bi_MsgBuf_WriteFloat,		-1},
414 	{"MsgBuf_WriteString",		bi_MsgBuf_WriteString,		-1},
415 //	{"MsgBuf_WriteBytes",		bi_MsgBuf_WriteBytes,		-1},
416 	{"MsgBuf_WriteCoord",		bi_MsgBuf_WriteCoord,		-1},
417 	{"MsgBuf_WriteCoordV",		bi_MsgBuf_WriteCoordV,		-1},
418 	{"MsgBuf_WriteCoordAngleV",	bi_MsgBuf_WriteCoordAngleV,	-1},
419 	{"MsgBuf_WriteAngle",		bi_MsgBuf_WriteAngle,		-1},
420 	{"MsgBuf_WriteAngleV",		bi_MsgBuf_WriteAngleV,		-1},
421 	{"MsgBuf_WriteAngle16",		bi_MsgBuf_WriteAngle16,		-1},
422 	{"MsgBuf_WriteAngle16V",	bi_MsgBuf_WriteAngle16V,	-1},
423 	{"MsgBuf_WriteUTF8",		bi_MsgBuf_WriteUTF8,		-1},
424 
425 	{"MsgBuf_BeginReading",		bi_MsgBuf_BeginReading,		-1},
426 	{"MsgBuf_ReadByte",			bi_MsgBuf_ReadByte,			-1},
427 	{"MsgBuf_ReadShort",		bi_MsgBuf_ReadShort,		-1},
428 	{"MsgBuf_ReadLong",			bi_MsgBuf_ReadLong,			-1},
429 	{"MsgBuf_ReadFloat",		bi_MsgBuf_ReadFloat,		-1},
430 	{"MsgBuf_ReadString",		bi_MsgBuf_ReadString,		-1},
431 //	{"MsgBuf_ReadBytes",		bi_MsgBuf_ReadBytes,		-1},
432 	{"MsgBuf_ReadCoord",		bi_MsgBuf_ReadCoord,		-1},
433 	{"MsgBuf_ReadCoordV",		bi_MsgBuf_ReadCoordV,		-1},
434 	{"MsgBuf_ReadCoordAngleV",	bi_MsgBuf_ReadCoordAngleV,	-1},
435 	{"MsgBuf_ReadAngle",		bi_MsgBuf_ReadAngle,		-1},
436 	{"MsgBuf_ReadAngleV",		bi_MsgBuf_ReadAngleV,		-1},
437 	{"MsgBuf_ReadAngle16",		bi_MsgBuf_ReadAngle16,		-1},
438 	{"MsgBuf_ReadAngle16V",		bi_MsgBuf_ReadAngle16V,		-1},
439 	{"MsgBuf_ReadUTF8",			bi_MsgBuf_ReadUTF8,			-1},
440 	{0}
441 };
442 
443 void
RUA_MsgBuf_Init(progs_t * pr,int secure)444 RUA_MsgBuf_Init (progs_t *pr, int secure)
445 {
446 	msgbuf_resources_t *res = calloc (sizeof (msgbuf_resources_t), 1);
447 
448 	PR_Resources_Register (pr, "MsgBuf", res, bi_msgbuf_clear);
449 	PR_RegisterBuiltins (pr, builtins);
450 }
451