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