1
2//-------------------------------------------------------------------
3// OFFSETS FOR INTERNAL QUAKE.EXE DATA STRUCTURES
4//-------------------------------------------------------------------
5
6float SV_ACTIVE				;// = %0; - might need to change this for linux/mac
7float SV_PAUSED				;// = %1; - might need to change this for linux/mac
8float SV_LOADGAME			;// = %2; - might need to change this for linux/mac
9float SV_TIME				;// = %4; - might need to change this for linux/mac
10float SV_LASTCHECK			;// = %6; - might need to change this for linux/mac
11float SV_LASTCHECKTIME			= %8;
12float SV_NAME					= %10;
13float SV_MODELNAME				= %26;
14float SV_WORLDMODEL				= %42;
15float SV_MODEL_PRECACHE			= %43;
16float SV_MODELS					= %299;
17float SV_SOUND_PRECACHE			= %555;
18float SV_LIGHTSTYLES			= %811;
19float SV_NUM_EDICTS				= %875;
20float SV_MAX_EDICTS				= %876;
21float SV_EDICTS					= %877;
22float SV_STATE					= %878;
23float SV_DATAGRAM				= %879;
24float SV_DATAGRAM_BUF			= %884;
25float SV_RELIABLE_DATAGRAM		= %1140;
26float SV_RELIABLE_DATAGRAM_BUF	= %1145;
27float SV_SIGNON					= %1401;
28float SV_SIGNON_DATA			= %1403;
29float SV_SIGNON_MAXSIZE			= %1404;
30float SV_SIGNON_CURSIZE			= %1405;
31float SV_SIGNON_BUF				= %1406;
32
33float CL_ACTIVE			;// = %0; - might need to change this for linux/mac
34float CL_SPAWNED		;// = %1; - might need to change this for linux/mac
35float CL_DROPASAP		;// = %2; - might need to change this for linux/mac
36float CL_PRIVILEGED		;// = %3; - might need to change this for linux/mac
37float CL_SENDSIGNON		;// = %4; - might need to change this for linux/mac
38float CL_LAST_MESSAGE		= %6;
39float CL_NETCONNECTION		= %8;
40float CL_CMD				= %9;
41float CL_CMD_FORWARD		= %12;
42float CL_CMD_SIDE			= %13;
43float CL_CMD_UP				= %14;
44float CL_WISHDIR			= %15;
45float CL_MESSAGE			= %18;
46float CL_MESSAGE_DATA		= %20;
47float CL_MESSAGE_MAXSIZE	= %21;
48float CL_MESSAGE_CURSIZE	= %22;
49float CL_MSGBUF				= %23;
50float CL_EDICT				= %2023;
51float CL_NAME				= %2024;
52float CL_COLORS				= %2032;
53float CL_PING_TIMES			= %2033;
54float CL_NUM_PINGS			= %2049;
55float CL_SPAWN_PARMS		= %2050;
56float CL_OLD_FRAGS			= %2066;
57
58float QS_ADDR			;// = %4118; - might need to change this for linux/mac
59float QS_IN_ADDR		;// = %4119; - might need to change this for linux/mac
60float QS_ADDRESS		;// = %4122; - might need to change this for linux/mac
61
62float PR_VERSION		= %0;
63float PR_CRC			= %1;
64float PR_OFS_STATEMENTS	= %2;
65float PR_NUMSTATEMENTS	= %3;
66float PR_OFS_GLOBALDEFS	= %4;
67float PR_NUMGLOBALDEFS	= %5;
68float PR_OFS_FIELDDEFS	= %6;
69float PR_NUMFIELDDEFS	= %7;
70float PR_OFS_FUNCTIONS	= %8;
71float PR_NUMFUNCTIONS	= %9;
72float PR_OFS_STRINGS	= %10;
73float PR_NUMSTRINGS		= %11;
74float PR_OFS_GLOBALS	= %12;
75float PR_NUMGLOBALS		= %13;
76float PR_ENTITYFIELDS	= %14;
77
78//-------------------------------------------------------------------
79// INTERNAL CONSTANTS
80//-------------------------------------------------------------------
81
82float PR_EDICT_SIZE;
83float HUNK_SENTINAL = 0x1df001ed;
84float ED_FREE	= %-24;
85
86// big/little endian stuff
87float NOALIGN;
88float BIG_ENDIAN;
89float B546L542;
90float B542L546;
91float B457L463;
92
93// conversions
94float PSTRING_TO_PQUAKEC;
95float PQUAKEC_TO_PSTRING;
96float PC_TO_PQUAKEC;
97float PC_TO_PSTRING;
98float PQUAKEC_TO_PC;
99float PSTRING_TO_PC;
100
101// progs header - SET BY COMPILER
102entity progs;
103
104// quake sv data structure
105entity sv;
106
107//-------------------------------------------------------------------
108// HEXADECIMAL PRINTING FUNCTIONS
109//-------------------------------------------------------------------
110
111float (float i) NegInt;
112
113string hex = "0":"1":"2":"3":"4":"5":"6":"7":"8":"9":"a":"b":"c":"d":"e":"f";
114
115//
116//  H E X  1 6
117//
118void (float i) hex16 =
119{
120	local float d;
121	d = floor(i / 4096);
122	i = i - d * 4096;
123	dprint(hex[d * %2]);
124	d = floor(i / 256);
125	i = i - d * 256;
126	dprint(hex[d * %2]);
127	d = floor(i / 16);
128	i = i - d * 16;
129	dprint(hex[d * %2], hex[i * %2]);
130};
131
132//
133//  H E X  3 2
134//
135void (float i) hex32 =
136{
137	local float high, low;
138
139	&%544 = i;
140	&B546L542 = %0;
141	low = world[%112];
142	&B542L546 = i;
143	high = world[%112];
144
145	hex16(high / %1);
146	hex16(low / %1);
147
148	local string s;
149	if (high < %256)
150		s = ftos(i / %1);
151	else if (high > %65280)
152		s = ftos(-1 * (NegInt(i) / %1));
153	else
154		s = ftos(low / %1);
155	dprint("  (", s, ")\n");
156};
157
158//-------------------------------------------------------------------
159// INTEGER ARITHMETIC
160//-------------------------------------------------------------------
161
162//
163//  A D D  I N T
164//
165float (float a, float b) AddInt =
166{
167	local vector va, vb, sum;
168
169	&%544 = a;
170	&B546L542 = %0;
171	va_x = world[%112];
172	&B542L546 = a;
173	va_y = world[%112];
174
175	&%544 = b;
176	&B546L542 = %0;
177	vb_x = world[%112];
178	&B542L546 = b;
179	vb_y = world[%112];
180
181	sum = va + vb;
182	if (sum_x > %65535)
183	{
184		sum_x = sum_x - %65536;
185		sum_y = sum_y + %1;
186	}
187	&%544 = sum_x;
188	&B546L542 = sum_y;
189	return world[%112];
190};
191
192//
193//  S U B  I N T
194//
195float (float a, float b) SubInt =
196{
197	local vector va, vb, sum;
198
199	&%544 = a;
200	&B546L542 = %0;
201	va_x = world[%112];
202	&B542L546 = a;
203	va_y = world[%112];
204
205	&%544 = b;
206	&B546L542 = %0;
207	vb_x = world[%112];
208	&B542L546 = b;
209	vb_y = world[%112];
210
211	vb_x = %65536 - vb_x;
212	vb_y = %65535 - vb_y;
213	if (vb_x > %65535)
214	{
215		vb_x = %0;
216		vb_y = vb_y + %1;
217	}
218
219	sum = va + vb;
220	if (sum_x > %65535)
221	{
222		sum_x = sum_x - %65536;
223		sum_y = sum_y + %1;
224	}
225	&%544 = sum_x;
226	&B546L542 = sum_y;
227	return world[%112];
228};
229
230//
231//  N E G  I N T
232//
233float (float a) NegInt =
234{
235	local float high, low;
236
237	&%544 = a;
238	&B546L542 = %0;
239	low = world[%112];
240	&B542L546 = a;
241	high = world[%112];
242
243	low = %65536 - low;
244	high = %65535 - high;
245	if (low > %65535)
246	{
247		low = %0;
248		high = high + %1;
249	}
250	&%544 = low;
251	&B546L542 = high;
252	return world[%112];
253};
254
255//-------------------------------------------------------------------
256// STRING UTILITIES
257//-------------------------------------------------------------------
258
259//
260//  F N S T R I N G
261//
262//  Print out the name of a function given a pointer to the function
263//
264void (float f) fnstring =
265{
266	local float p;
267
268	p = AddInt(&progs, progs[PR_OFS_FUNCTIONS]);
269	p = AddInt(p, f * 36);
270	dprint(@(*p)[%4], "\n");
271
272};
273
274//
275//  S T R C P Y
276//
277//  Copy the source string to the destination string
278//
279float (string dst, string src) strcpy =
280{
281	local float data, cursize;
282
283	data = sv[SV_SIGNON_DATA];
284	cursize = sv[SV_SIGNON_CURSIZE];
285
286	sv[SV_SIGNON_CURSIZE] = 0;
287	sv[SV_SIGNON_DATA] = AddInt(&dst, PSTRING_TO_PC);
288	WriteString(MSG_INIT, src);
289
290	sv[SV_SIGNON_DATA] = data;
291	sv[SV_SIGNON_CURSIZE] = cursize;
292};
293
294//-------------------------------------------------------------------
295// INITIALIZATION
296//-------------------------------------------------------------------
297
298//
299//  I N T E R N A L  I N I T
300//
301void () InternalInit =
302{
303	local float p, p2;
304
305	&%548 = %0;
306	&%550 = %1;
307
308	BIG_ENDIAN = world[%113];
309	if (BIG_ENDIAN)
310	{
311		dprint("Big Endian architecture detected\n");
312		B542L546 = %542;
313		B546L542 = %546;
314		B457L463 = %457;
315	}
316	else
317	{
318		dprint("Little Endian architecture detected\n");
319		B542L546 = %546;
320		B546L542 = %542;
321		B457L463 = %463;
322	}
323
324	PSTRING_TO_PQUAKEC = AddInt(&progs, progs[PR_OFS_STRINGS]);
325	PQUAKEC_TO_PSTRING = NegInt(PSTRING_TO_PQUAKEC);
326	p = AddInt(&mapname, PSTRING_TO_PQUAKEC);
327	p2 = NegInt((*p)[%33]);
328	PC_TO_PQUAKEC = AddInt(PSTRING_TO_PQUAKEC, p2);
329	PC_TO_PSTRING = AddInt(PC_TO_PQUAKEC, PQUAKEC_TO_PSTRING);
330	PQUAKEC_TO_PC = NegInt(PC_TO_PQUAKEC);
331	PSTRING_TO_PC = NegInt(PC_TO_PSTRING);
332
333	sv = *AddInt(p, %-40);
334
335	PR_EDICT_SIZE = 4 * (progs[PR_ENTITYFIELDS] / %1) + 96;
336
337	if ((BIG_ENDIAN && sv[%5]) || (!BIG_ENDIAN && sv[%4]))
338	{
339		dprint("Alignment detected\n");
340
341		NOALIGN = 0;
342
343		SV_ACTIVE			= %0;
344		SV_PAUSED			= %1;
345		SV_LOADGAME			= %2;
346		SV_TIME				= %4;
347		SV_LASTCHECK		= %6;
348
349		CL_ACTIVE			= %0;
350		CL_SPAWNED			= %1;
351		CL_DROPASAP			= %2;
352		CL_PRIVILEGED		= %3;
353		CL_SENDSIGNON		= %4;
354
355		QS_ADDR				= %4118;
356		QS_IN_ADDR			= %4119;
357		QS_ADDRESS			= %4122;
358	}
359	else
360	{
361		dprint("No alignment detected\n");
362
363		NOALIGN = 1;
364
365		SV_ACTIVE			= %2;
366		SV_PAUSED			= %3;
367		SV_LOADGAME			= %4;
368		SV_TIME				= %5;
369		SV_LASTCHECK		= %7;
370
371		CL_ACTIVE			= %1;
372		CL_SPAWNED			= %2;
373		CL_DROPASAP			= %3;
374		CL_PRIVILEGED		= %4;
375		CL_SENDSIGNON		= %5;
376
377		QS_ADDR				= %4117;
378		QS_IN_ADDR			= %4118;
379		QS_ADDRESS			= %4121;
380	}
381};
382
383//--------------------------------------------------------------------
384// HUNK STUFF
385//--------------------------------------------------------------------
386
387entity lasth, currh;
388
389// Create some storage space for hunk names.
390// NOTE: the two string constants *must* be different or only one of them
391// will be allocated with the /Od option is used.
392//
393string hunkname = "00000000";
394string prevname = "00000001";
395
396void () InitHunkSearch =
397{
398	lasth = currh = *AddInt(&progs, %-16);
399};
400
401void (float h) GetHunkName =
402{
403	local float p, p2;
404	p = AddInt(&hunkname, PSTRING_TO_PQUAKEC);
405	p2 = AddInt(&prevname, PSTRING_TO_PQUAKEC);
406	(*p2)[%0] = (*p)[%0];
407	(*p2)[%1] = (*p)[%1];
408	(*p)[%0] = (*h)[%2];
409	(*p)[%1] = (*h)[%3];
410};
411
412float (float h) PrintHunk =
413{
414	local float samecount;
415	local float samesize;
416	local float h2;
417
418	samecount = 0;
419	samesize = 0;
420
421	dprint("--- HUNK ---\n");
422
423	h2 = h;
424	while (1)
425	{
426		GetHunkName(h);
427		if (hunkname == prevname && (!samecount || samesize == (*h)[%1]))
428		{
429			samecount = samecount + 1;
430			samesize = (*h)[%1];
431		}
432		else
433		{
434			if (samecount)
435			{
436				dprint(ftos(samecount), " x ", prevname, " : ");
437				dprint(ftos(samesize / %1), "\n");
438			}
439			samecount = 1;
440			samesize = (*h)[%1];
441		}
442		if (prevname == "edicts")
443			return h2;
444
445		h = AddInt(h, (*h)[%1]);
446	}
447};
448
449void () SearchHunk =
450{
451	local float i;
452	local string hname = "XXXXXXXX";
453	local float p;
454
455	p = AddInt(&hname, PSTRING_TO_PQUAKEC);
456
457	dprint("-- SeachHunk --\n");
458
459	currh = *AddInt(&currh, %-131072);
460	for (i = %32764 ; i >= %0 ; i = i - %4)
461	{
462		if (*currh[i] == *HUNK_SENTINAL)
463		{
464			if (currh[i + %1] == SubInt(SubInt(&lasth, &currh), 4 * i))
465			{
466				(*p)[%0] = currh[i + %2];
467				(*p)[%1] = currh[i + %3];
468				dprint("found ", hname, "\n");
469				lasth = *AddInt(&currh, 4 * i);
470				if (hname == "zone")
471				{
472					PrintHunk(&lasth);
473					dprint("Found start of hunk in ");
474					dprint(ftos(framecount), " frames\n");
475					lasth = *0;
476					return;
477				}
478			}
479		}
480	}
481};
482
483