aboutsummaryrefslogtreecommitdiffstats
path: root/q3asm
diff options
context:
space:
mode:
authorzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 17:39:27 +0000
committerzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 17:39:27 +0000
commit6bf20c78f5b69d40bcc4931df93d29198435ab67 (patch)
treee3eda937a05d7db42de725b7013bd0344b987f34 /q3asm
parent872d4d7f55af706737ffb361bb76ad13e7496770 (diff)
downloadioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.tar.gz
ioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.zip
newlines fixed
git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'q3asm')
-rwxr-xr-xq3asm/Makefile26
-rwxr-xr-xq3asm/README.Id20
-rwxr-xr-xq3asm/cmdlib.c2412
-rwxr-xr-xq3asm/cmdlib.h320
-rwxr-xr-xq3asm/lib.txt62
-rwxr-xr-xq3asm/mathlib.h188
-rwxr-xr-xq3asm/notes.txt32
-rwxr-xr-xq3asm/ops.txt264
-rwxr-xr-xq3asm/opstrings.h350
-rwxr-xr-xq3asm/q3asm.c2094
-rwxr-xr-xq3asm/q3asm.sln56
-rwxr-xr-xq3asm/q3asm.vcproj390
-rwxr-xr-xq3asm/qfiles.h970
13 files changed, 3592 insertions, 3592 deletions
diff --git a/q3asm/Makefile b/q3asm/Makefile
index b53640a..d576a03 100755
--- a/q3asm/Makefile
+++ b/q3asm/Makefile
@@ -1,13 +1,13 @@
-# yeah, couldn't do more simple really
-
-CC=gcc
-CFLAGS=-g -Wall
-
-default: q3asm
-
-q3asm: q3asm.c cmdlib.c
- $(CC) $(CFLAGS) -o $@ $^
-
-clean:
- rm -f q3asm *~ *.o
-
+# yeah, couldn't do more simple really
+
+CC=gcc
+CFLAGS=-g -Wall
+
+default: q3asm
+
+q3asm: q3asm.c cmdlib.c
+ $(CC) $(CFLAGS) -o $@ $^
+
+clean:
+ rm -f q3asm *~ *.o
+
diff --git a/q3asm/README.Id b/q3asm/README.Id
index 30f44b2..adacb50 100755
--- a/q3asm/README.Id
+++ b/q3asm/README.Id
@@ -1,10 +1,10 @@
-2002-10-25 Timothee Besset <ttimo@idsoftware.com>
-If you are looking for a faster version of the q3asm tool, try:
-http://www.icculus.org/~phaethon/q3/q3asm-turbo/q3asm-turbo.html
-
-2001-10-31 Timothee Besset <ttimo@idsoftware.com>
-updated from the $/source/q3asm code
-modified for portability and use with >= 1.31 mod source release
-
-the cmdlib.c cmdlib.h mathlib.h qfiles.h have been copied from
-$/source/common
+2002-10-25 Timothee Besset <ttimo@idsoftware.com>
+If you are looking for a faster version of the q3asm tool, try:
+http://www.icculus.org/~phaethon/q3/q3asm-turbo/q3asm-turbo.html
+
+2001-10-31 Timothee Besset <ttimo@idsoftware.com>
+updated from the $/source/q3asm code
+modified for portability and use with >= 1.31 mod source release
+
+the cmdlib.c cmdlib.h mathlib.h qfiles.h have been copied from
+$/source/common
diff --git a/q3asm/cmdlib.c b/q3asm/cmdlib.c
index 630ac57..d6483f8 100755
--- a/q3asm/cmdlib.c
+++ b/q3asm/cmdlib.c
@@ -1,1206 +1,1206 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// cmdlib.c
-
-#include "cmdlib.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef WIN32
-#include <direct.h>
-#include <windows.h>
-#endif
-
-#ifdef __linux
-#include <unistd.h>
-#endif
-
-#ifdef NeXT
-#include <libc.h>
-#endif
-
-#define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
-#define PATHSEPERATOR '/'
-
-// set these before calling CheckParm
-int myargc;
-char **myargv;
-
-char com_token[1024];
-qboolean com_eof;
-
-qboolean archive;
-char archivedir[1024];
-
-
-/*
-===================
-ExpandWildcards
-
-Mimic unix command line expansion
-===================
-*/
-#define MAX_EX_ARGC 1024
-int ex_argc;
-char *ex_argv[MAX_EX_ARGC];
-#ifdef _WIN32
-#include "io.h"
-void ExpandWildcards( int *argc, char ***argv )
-{
- struct _finddata_t fileinfo;
- int handle;
- int i;
- char filename[1024];
- char filebase[1024];
- char *path;
-
- ex_argc = 0;
- for (i=0 ; i<*argc ; i++)
- {
- path = (*argv)[i];
- if ( path[0] == '-'
- || ( !strstr(path, "*") && !strstr(path, "?") ) )
- {
- ex_argv[ex_argc++] = path;
- continue;
- }
-
- handle = _findfirst (path, &fileinfo);
- if (handle == -1)
- return;
-
- ExtractFilePath (path, filebase);
-
- do
- {
- sprintf (filename, "%s%s", filebase, fileinfo.name);
- ex_argv[ex_argc++] = copystring (filename);
- } while (_findnext( handle, &fileinfo ) != -1);
-
- _findclose (handle);
- }
-
- *argc = ex_argc;
- *argv = ex_argv;
-}
-#else
-void ExpandWildcards (int *argc, char ***argv)
-{
-}
-#endif
-
-#ifdef WIN_ERROR
-#include <windows.h>
-/*
-=================
-Error
-
-For abnormal program terminations in windowed apps
-=================
-*/
-void Error( const char *error, ... )
-{
- va_list argptr;
- char text[1024];
- char text2[1024];
- int err;
-
- err = GetLastError ();
-
- va_start (argptr,error);
- vsprintf (text, error,argptr);
- va_end (argptr);
-
- sprintf (text2, "%s\nGetLastError() = %i", text, err);
- MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
-
- exit (1);
-}
-
-#else
-/*
-=================
-Error
-
-For abnormal program terminations in console apps
-=================
-*/
-void Error( const char *error, ...)
-{
- va_list argptr;
-
- _printf ("\n************ ERROR ************\n");
-
- va_start (argptr,error);
- vprintf (error,argptr);
- va_end (argptr);
- _printf ("\r\n");
-
- exit (1);
-}
-#endif
-
-// only printf if in verbose mode
-qboolean verbose = qfalse;
-void qprintf( const char *format, ... ) {
- va_list argptr;
-
- if (!verbose)
- return;
-
- va_start (argptr,format);
- vprintf (format,argptr);
- va_end (argptr);
-
-}
-
-#ifdef WIN32
-HWND hwndOut = NULL;
-qboolean lookedForServer = qfalse;
-UINT wm_BroadcastCommand = -1;
-#endif
-
-void _printf( const char *format, ... ) {
- va_list argptr;
- char text[4096];
-#ifdef WIN32
- ATOM a;
-#endif
- va_start (argptr,format);
- vsprintf (text, format, argptr);
- va_end (argptr);
-
- printf(text);
-
-#ifdef WIN32
- if (!lookedForServer) {
- lookedForServer = qtrue;
- hwndOut = FindWindow(NULL, "Q3Map Process Server");
- if (hwndOut) {
- wm_BroadcastCommand = RegisterWindowMessage( "Q3MPS_BroadcastCommand" );
- }
- }
- if (hwndOut) {
- a = GlobalAddAtom(text);
- PostMessage(hwndOut, wm_BroadcastCommand, 0, (LPARAM)a);
- }
-#endif
-}
-
-
-/*
-
-qdir will hold the path up to the quake directory, including the slash
-
- f:\quake\
- /raid/quake/
-
-gamedir will hold qdir + the game directory (id1, id2, etc)
-
- */
-
-char qdir[1024];
-char gamedir[1024];
-char writedir[1024];
-
-void SetQdirFromPath( const char *path )
-{
- char temp[1024];
- const char *c;
- const char *sep;
- int len, count;
-
- if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
- { // path is partial
- Q_getwd (temp);
- strcat (temp, path);
- path = temp;
- }
-
- // search for "quake2" in path
-
- len = strlen(BASEDIRNAME);
- for (c=path+strlen(path)-1 ; c != path ; c--)
- {
- int i;
-
- if (!Q_strncasecmp (c, BASEDIRNAME, len))
- {
- //
- //strncpy (qdir, path, c+len+2-path);
- // the +2 assumes a 2 or 3 following quake which is not the
- // case with a retail install
- // so we need to add up how much to the next separator
- sep = c + len;
- count = 1;
- while (*sep && *sep != '/' && *sep != '\\')
- {
- sep++;
- count++;
- }
- strncpy (qdir, path, c+len+count-path);
- qprintf ("qdir: %s\n", qdir);
- for ( i = 0; i < strlen( qdir ); i++ )
- {
- if ( qdir[i] == '\\' )
- qdir[i] = '/';
- }
-
- c += len+count;
- while (*c)
- {
- if (*c == '/' || *c == '\\')
- {
- strncpy (gamedir, path, c+1-path);
-
- for ( i = 0; i < strlen( gamedir ); i++ )
- {
- if ( gamedir[i] == '\\' )
- gamedir[i] = '/';
- }
-
- qprintf ("gamedir: %s\n", gamedir);
-
- if ( !writedir[0] )
- strcpy( writedir, gamedir );
- else if ( writedir[strlen( writedir )-1] != '/' )
- {
- writedir[strlen( writedir )] = '/';
- writedir[strlen( writedir )+1] = 0;
- }
-
- return;
- }
- c++;
- }
- Error ("No gamedir in %s", path);
- return;
- }
- }
- Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
-}
-
-char *ExpandArg (const char *path)
-{
- static char full[1024];
-
- if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
- {
- Q_getwd (full);
- strcat (full, path);
- }
- else
- strcpy (full, path);
- return full;
-}
-
-char *ExpandPath (const char *path)
-{
- static char full[1024];
- if (!qdir)
- Error ("ExpandPath called without qdir set");
- if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
- strcpy( full, path );
- return full;
- }
- sprintf (full, "%s%s", qdir, path);
- return full;
-}
-
-char *ExpandGamePath (const char *path)
-{
- static char full[1024];
- if (!qdir)
- Error ("ExpandGamePath called without qdir set");
- if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
- strcpy( full, path );
- return full;
- }
- sprintf (full, "%s%s", gamedir, path);
- return full;
-}
-
-char *ExpandPathAndArchive (const char *path)
-{
- char *expanded;
- char archivename[1024];
-
- expanded = ExpandPath (path);
-
- if (archive)
- {
- sprintf (archivename, "%s/%s", archivedir, path);
- QCopyFile (expanded, archivename);
- }
- return expanded;
-}
-
-
-char *copystring(const char *s)
-{
- char *b;
- b = malloc(strlen(s)+1);
- strcpy (b, s);
- return b;
-}
-
-
-
-/*
-================
-I_FloatTime
-================
-*/
-double I_FloatTime (void)
-{
- time_t t;
-
- time (&t);
-
- return t;
-#if 0
-// more precise, less portable
- struct timeval tp;
- struct timezone tzp;
- static int secbase;
-
- gettimeofday(&tp, &tzp);
-
- if (!secbase)
- {
- secbase = tp.tv_sec;
- return tp.tv_usec/1000000.0;
- }
-
- return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
-#endif
-}
-
-void Q_getwd (char *out)
-{
- int i = 0;
-
-#ifdef WIN32
- _getcwd (out, 256);
- strcat (out, "\\");
-#else
- getcwd (out, 256);
- strcat (out, "/");
-#endif
-
- while ( out[i] != 0 )
- {
- if ( out[i] == '\\' )
- out[i] = '/';
- i++;
- }
-}
-
-
-void Q_mkdir (const char *path)
-{
-#ifdef WIN32
- if (_mkdir (path) != -1)
- return;
-#else
- if (mkdir (path, 0777) != -1)
- return;
-#endif
- if (errno != EEXIST)
- Error ("mkdir %s: %s",path, strerror(errno));
-}
-
-/*
-============
-FileTime
-
-returns -1 if not present
-============
-*/
-int FileTime (const char *path)
-{
- struct stat buf;
-
- if (stat (path,&buf) == -1)
- return -1;
-
- return buf.st_mtime;
-}
-
-
-
-/*
-==============
-COM_Parse
-
-Parse a token out of a string
-==============
-*/
-char *COM_Parse (char *data)
-{
- int c;
- int len;
-
- len = 0;
- com_token[0] = 0;
-
- if (!data)
- return NULL;
-
-// skip whitespace
-skipwhite:
- while ( (c = *data) <= ' ')
- {
- if (c == 0)
- {
- com_eof = qtrue;
- return NULL; // end of file;
- }
- data++;
- }
-
-// skip // comments
- if (c=='/' && data[1] == '/')
- {
- while (*data && *data != '\n')
- data++;
- goto skipwhite;
- }
-
-
-// handle quoted strings specially
- if (c == '\"')
- {
- data++;
- do
- {
- c = *data++;
- if (c=='\"')
- {
- com_token[len] = 0;
- return data;
- }
- com_token[len] = c;
- len++;
- } while (1);
- }
-
-// parse single characters
- if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
- {
- com_token[len] = c;
- len++;
- com_token[len] = 0;
- return data+1;
- }
-
-// parse a regular word
- do
- {
- com_token[len] = c;
- data++;
- len++;
- c = *data;
- if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
- break;
- } while (c>32);
-
- com_token[len] = 0;
- return data;
-}
-
-
-int Q_strncasecmp (const char *s1, const char *s2, int n)
-{
- int c1, c2;
-
- do
- {
- c1 = *s1++;
- c2 = *s2++;
-
- if (!n--)
- return 0; // strings are equal until end point
-
- if (c1 != c2)
- {
- if (c1 >= 'a' && c1 <= 'z')
- c1 -= ('a' - 'A');
- if (c2 >= 'a' && c2 <= 'z')
- c2 -= ('a' - 'A');
- if (c1 != c2)
- return -1; // strings not equal
- }
- } while (c1);
-
- return 0; // strings are equal
-}
-
-int Q_stricmp (const char *s1, const char *s2)
-{
- return Q_strncasecmp (s1, s2, 99999);
-}
-
-
-char *strupr (char *start)
-{
- char *in;
- in = start;
- while (*in)
- {
- *in = toupper(*in);
- in++;
- }
- return start;
-}
-
-char *strlower (char *start)
-{
- char *in;
- in = start;
- while (*in)
- {
- *in = tolower(*in);
- in++;
- }
- return start;
-}
-
-
-/*
-=============================================================================
-
- MISC FUNCTIONS
-
-=============================================================================
-*/
-
-
-/*
-=================
-CheckParm
-
-Checks for the given parameter in the program's command line arguments
-Returns the argument number (1 to argc-1) or 0 if not present
-=================
-*/
-int CheckParm (const char *check)
-{
- int i;
-
- for (i = 1;i<myargc;i++)
- {
- if ( !Q_stricmp(check, myargv[i]) )
- return i;
- }
-
- return 0;
-}
-
-
-
-/*
-================
-Q_filelength
-================
-*/
-int Q_filelength (FILE *f)
-{
- int pos;
- int end;
-
- pos = ftell (f);
- fseek (f, 0, SEEK_END);
- end = ftell (f);
- fseek (f, pos, SEEK_SET);
-
- return end;
-}
-
-
-FILE *SafeOpenWrite (const char *filename)
-{
- FILE *f;
-
- f = fopen(filename, "wb");
-
- if (!f)
- Error ("Error opening %s: %s",filename,strerror(errno));
-
- return f;
-}
-
-FILE *SafeOpenRead (const char *filename)
-{
- FILE *f;
-
- f = fopen(filename, "rb");
-
- if (!f)
- Error ("Error opening %s: %s",filename,strerror(errno));
-
- return f;
-}
-
-
-void SafeRead (FILE *f, void *buffer, int count)
-{
- if ( fread (buffer, 1, count, f) != (size_t)count)
- Error ("File read failure");
-}
-
-
-void SafeWrite (FILE *f, const void *buffer, int count)
-{
- if (fwrite (buffer, 1, count, f) != (size_t)count)
- Error ("File write failure");
-}
-
-
-/*
-==============
-FileExists
-==============
-*/
-qboolean FileExists (const char *filename)
-{
- FILE *f;
-
- f = fopen (filename, "r");
- if (!f)
- return qfalse;
- fclose (f);
- return qtrue;
-}
-
-/*
-==============
-LoadFile
-==============
-*/
-int LoadFile( const char *filename, void **bufferptr )
-{
- FILE *f;
- int length;
- void *buffer;
-
- f = SafeOpenRead (filename);
- length = Q_filelength (f);
- buffer = malloc (length+1);
- ((char *)buffer)[length] = 0;
- SafeRead (f, buffer, length);
- fclose (f);
-
- *bufferptr = buffer;
- return length;
-}
-
-
-/*
-==============
-LoadFileBlock
--
-rounds up memory allocation to 4K boundry
--
-==============
-*/
-int LoadFileBlock( const char *filename, void **bufferptr )
-{
- FILE *f;
- int length, nBlock, nAllocSize;
- void *buffer;
-
- f = SafeOpenRead (filename);
- length = Q_filelength (f);
- nAllocSize = length;
- nBlock = nAllocSize % MEM_BLOCKSIZE;
- if ( nBlock > 0) {
- nAllocSize += MEM_BLOCKSIZE - nBlock;
- }
- buffer = malloc (nAllocSize+1);
- memset(buffer, 0, nAllocSize+1);
- SafeRead (f, buffer, length);
- fclose (f);
-
- *bufferptr = buffer;
- return length;
-}
-
-
-/*
-==============
-TryLoadFile
-
-Allows failure
-==============
-*/
-int TryLoadFile (const char *filename, void **bufferptr)
-{
- FILE *f;
- int length;
- void *buffer;
-
- *bufferptr = NULL;
-
- f = fopen (filename, "rb");
- if (!f)
- return -1;
- length = Q_filelength (f);
- buffer = malloc (length+1);
- ((char *)buffer)[length] = 0;
- SafeRead (f, buffer, length);
- fclose (f);
-
- *bufferptr = buffer;
- return length;
-}
-
-
-/*
-==============
-SaveFile
-==============
-*/
-void SaveFile (const char *filename, const void *buffer, int count)
-{
- FILE *f;
-
- f = SafeOpenWrite (filename);
- SafeWrite (f, buffer, count);
- fclose (f);
-}
-
-
-
-void DefaultExtension (char *path, const char *extension)
-{
- char *src;
-//
-// if path doesnt have a .EXT, append extension
-// (extension should include the .)
-//
- src = path + strlen(path) - 1;
-
- while (*src != '/' && *src != '\\' && src != path)
- {
- if (*src == '.')
- return; // it has an extension
- src--;
- }
-
- strcat (path, extension);
-}
-
-
-void DefaultPath (char *path, const char *basepath)
-{
- char temp[128];
-
- if (path[0] == PATHSEPERATOR)
- return; // absolute path location
- strcpy (temp,path);
- strcpy (path,basepath);
- strcat (path,temp);
-}
-
-
-void StripFilename (char *path)
-{
- int length;
-
- length = strlen(path)-1;
- while (length > 0 && path[length] != PATHSEPERATOR)
- length--;
- path[length] = 0;
-}
-
-void StripExtension (char *path)
-{
- int length;
-
- length = strlen(path)-1;
- while (length > 0 && path[length] != '.')
- {
- length--;
- if (path[length] == '/')
- return; // no extension
- }
- if (length)
- path[length] = 0;
-}
-
-
-/*
-====================
-Extract file parts
-====================
-*/
-// FIXME: should include the slash, otherwise
-// backing to an empty path will be wrong when appending a slash
-void ExtractFilePath (const char *path, char *dest)
-{
- const char *src;
-
- src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
- while (src != path && *(src-1) != '\\' && *(src-1) != '/')
- src--;
-
- memcpy (dest, path, src-path);
- dest[src-path] = 0;
-}
-
-void ExtractFileBase (const char *path, char *dest)
-{
- const char *src;
-
- src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
- while (src != path && *(src-1) != PATHSEPERATOR)
- src--;
-
- while (*src && *src != '.')
- {
- *dest++ = *src++;
- }
- *dest = 0;
-}
-
-void ExtractFileExtension (const char *path, char *dest)
-{
- const char *src;
-
- src = path + strlen(path) - 1;
-
-//
-// back up until a . or the start
-//
- while (src != path && *(src-1) != '.')
- src--;
- if (src == path)
- {
- *dest = 0; // no extension
- return;
- }
-
- strcpy (dest,src);
-}
-
-
-/*
-==============
-ParseNum / ParseHex
-==============
-*/
-int ParseHex (const char *hex)
-{
- const char *str;
- int num;
-
- num = 0;
- str = hex;
-
- while (*str)
- {
- num <<= 4;
- if (*str >= '0' && *str <= '9')
- num += *str-'0';
- else if (*str >= 'a' && *str <= 'f')
- num += 10 + *str-'a';
- else if (*str >= 'A' && *str <= 'F')
- num += 10 + *str-'A';
- else
- Error ("Bad hex number: %s",hex);
- str++;
- }
-
- return num;
-}
-
-
-int ParseNum (const char *str)
-{
- if (str[0] == '$')
- return ParseHex (str+1);
- if (str[0] == '0' && str[1] == 'x')
- return ParseHex (str+2);
- return atol (str);
-}
-
-
-
-/*
-============================================================================
-
- BYTE ORDER FUNCTIONS
-
-============================================================================
-*/
-
-#ifdef _SGI_SOURCE
-#define __BIG_ENDIAN__
-#endif
-
-#ifdef __BIG_ENDIAN__
-
-short LittleShort (short l)
-{
- byte b1,b2;
-
- b1 = l&255;
- b2 = (l>>8)&255;
-
- return (b1<<8) + b2;
-}
-
-short BigShort (short l)
-{
- return l;
-}
-
-
-int LittleLong (int l)
-{
- byte b1,b2,b3,b4;
-
- b1 = l&255;
- b2 = (l>>8)&255;
- b3 = (l>>16)&255;
- b4 = (l>>24)&255;
-
- return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int BigLong (int l)
-{
- return l;
-}
-
-
-float LittleFloat (float l)
-{
- union {byte b[4]; float f;} in, out;
-
- in.f = l;
- out.b[0] = in.b[3];
- out.b[1] = in.b[2];
- out.b[2] = in.b[1];
- out.b[3] = in.b[0];
-
- return out.f;
-}
-
-float BigFloat (float l)
-{
- return l;
-}
-
-
-#else
-
-
-short BigShort (short l)
-{
- byte b1,b2;
-
- b1 = l&255;
- b2 = (l>>8)&255;
-
- return (b1<<8) + b2;
-}
-
-short LittleShort (short l)
-{
- return l;
-}
-
-
-int BigLong (int l)
-{
- byte b1,b2,b3,b4;
-
- b1 = l&255;
- b2 = (l>>8)&255;
- b3 = (l>>16)&255;
- b4 = (l>>24)&255;
-
- return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int LittleLong (int l)
-{
- return l;
-}
-
-float BigFloat (float l)
-{
- union {byte b[4]; float f;} in, out;
-
- in.f = l;
- out.b[0] = in.b[3];
- out.b[1] = in.b[2];
- out.b[2] = in.b[1];
- out.b[3] = in.b[0];
-
- return out.f;
-}
-
-float LittleFloat (float l)
-{
- return l;
-}
-
-
-#endif
-
-
-//=======================================================
-
-
-// FIXME: byte swap?
-
-// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
-// and the initial and final xor values shown below... in other words, the
-// CCITT standard CRC used by XMODEM
-
-#define CRC_INIT_VALUE 0xffff
-#define CRC_XOR_VALUE 0x0000
-
-static unsigned short crctable[256] =
-{
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
- 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
- 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
- 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
- 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
- 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
- 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
- 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
- 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
- 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
- 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
- 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
- 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
- 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
- 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
- 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
- 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
- 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
- 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
- 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
- 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
- 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
- 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
- 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
- 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
- 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
- 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
- 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
- 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
- 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
- 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
- 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
-};
-
-void CRC_Init(unsigned short *crcvalue)
-{
- *crcvalue = CRC_INIT_VALUE;
-}
-
-void CRC_ProcessByte(unsigned short *crcvalue, byte data)
-{
- *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
-}
-
-unsigned short CRC_Value(unsigned short crcvalue)
-{
- return crcvalue ^ CRC_XOR_VALUE;
-}
-//=============================================================================
-
-/*
-============
-CreatePath
-============
-*/
-void CreatePath (const char *path)
-{
- const char *ofs;
- char c;
- char dir[1024];
-
-#ifdef _WIN32
- int olddrive = -1;
-
- if ( path[1] == ':' )
- {
- olddrive = _getdrive();
- _chdrive( toupper( path[0] ) - 'A' + 1 );
- }
-#endif
-
- if (path[1] == ':')
- path += 2;
-
- for (ofs = path+1 ; *ofs ; ofs++)
- {
- c = *ofs;
- if (c == '/' || c == '\\')
- { // create the directory
- memcpy( dir, path, ofs - path );
- dir[ ofs - path ] = 0;
- Q_mkdir( dir );
- }
- }
-
-#ifdef _WIN32
- if ( olddrive != -1 )
- {
- _chdrive( olddrive );
- }
-#endif
-}
-
-
-/*
-============
-QCopyFile
-
- Used to archive source files
-============
-*/
-void QCopyFile (const char *from, const char *to)
-{
- void *buffer;
- int length;
-
- length = LoadFile (from, &buffer);
- CreatePath (to);
- SaveFile (to, buffer, length);
- free (buffer);
-}
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// cmdlib.c
+
+#include "cmdlib.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <direct.h>
+#include <windows.h>
+#endif
+
+#ifdef __linux
+#include <unistd.h>
+#endif
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+
+#define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
+#define PATHSEPERATOR '/'
+
+// set these before calling CheckParm
+int myargc;
+char **myargv;
+
+char com_token[1024];
+qboolean com_eof;
+
+qboolean archive;
+char archivedir[1024];
+
+
+/*
+===================
+ExpandWildcards
+
+Mimic unix command line expansion
+===================
+*/
+#define MAX_EX_ARGC 1024
+int ex_argc;
+char *ex_argv[MAX_EX_ARGC];
+#ifdef _WIN32
+#include "io.h"
+void ExpandWildcards( int *argc, char ***argv )
+{
+ struct _finddata_t fileinfo;
+ int handle;
+ int i;
+ char filename[1024];
+ char filebase[1024];
+ char *path;
+
+ ex_argc = 0;
+ for (i=0 ; i<*argc ; i++)
+ {
+ path = (*argv)[i];
+ if ( path[0] == '-'
+ || ( !strstr(path, "*") && !strstr(path, "?") ) )
+ {
+ ex_argv[ex_argc++] = path;
+ continue;
+ }
+
+ handle = _findfirst (path, &fileinfo);
+ if (handle == -1)
+ return;
+
+ ExtractFilePath (path, filebase);
+
+ do
+ {
+ sprintf (filename, "%s%s", filebase, fileinfo.name);
+ ex_argv[ex_argc++] = copystring (filename);
+ } while (_findnext( handle, &fileinfo ) != -1);
+
+ _findclose (handle);
+ }
+
+ *argc = ex_argc;
+ *argv = ex_argv;
+}
+#else
+void ExpandWildcards (int *argc, char ***argv)
+{
+}
+#endif
+
+#ifdef WIN_ERROR
+#include <windows.h>
+/*
+=================
+Error
+
+For abnormal program terminations in windowed apps
+=================
+*/
+void Error( const char *error, ... )
+{
+ va_list argptr;
+ char text[1024];
+ char text2[1024];
+ int err;
+
+ err = GetLastError ();
+
+ va_start (argptr,error);
+ vsprintf (text, error,argptr);
+ va_end (argptr);
+
+ sprintf (text2, "%s\nGetLastError() = %i", text, err);
+ MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
+
+ exit (1);
+}
+
+#else
+/*
+=================
+Error
+
+For abnormal program terminations in console apps
+=================
+*/
+void Error( const char *error, ...)
+{
+ va_list argptr;
+
+ _printf ("\n************ ERROR ************\n");
+
+ va_start (argptr,error);
+ vprintf (error,argptr);
+ va_end (argptr);
+ _printf ("\r\n");
+
+ exit (1);
+}
+#endif
+
+// only printf if in verbose mode
+qboolean verbose = qfalse;
+void qprintf( const char *format, ... ) {
+ va_list argptr;
+
+ if (!verbose)
+ return;
+
+ va_start (argptr,format);
+ vprintf (format,argptr);
+ va_end (argptr);
+
+}
+
+#ifdef WIN32
+HWND hwndOut = NULL;
+qboolean lookedForServer = qfalse;
+UINT wm_BroadcastCommand = -1;
+#endif
+
+void _printf( const char *format, ... ) {
+ va_list argptr;
+ char text[4096];
+#ifdef WIN32
+ ATOM a;
+#endif
+ va_start (argptr,format);
+ vsprintf (text, format, argptr);
+ va_end (argptr);
+
+ printf(text);
+
+#ifdef WIN32
+ if (!lookedForServer) {
+ lookedForServer = qtrue;
+ hwndOut = FindWindow(NULL, "Q3Map Process Server");
+ if (hwndOut) {
+ wm_BroadcastCommand = RegisterWindowMessage( "Q3MPS_BroadcastCommand" );
+ }
+ }
+ if (hwndOut) {
+ a = GlobalAddAtom(text);
+ PostMessage(hwndOut, wm_BroadcastCommand, 0, (LPARAM)a);
+ }
+#endif
+}
+
+
+/*
+
+qdir will hold the path up to the quake directory, including the slash
+
+ f:\quake\
+ /raid/quake/
+
+gamedir will hold qdir + the game directory (id1, id2, etc)
+
+ */
+
+char qdir[1024];
+char gamedir[1024];
+char writedir[1024];
+
+void SetQdirFromPath( const char *path )
+{
+ char temp[1024];
+ const char *c;
+ const char *sep;
+ int len, count;
+
+ if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
+ { // path is partial
+ Q_getwd (temp);
+ strcat (temp, path);
+ path = temp;
+ }
+
+ // search for "quake2" in path
+
+ len = strlen(BASEDIRNAME);
+ for (c=path+strlen(path)-1 ; c != path ; c--)
+ {
+ int i;
+
+ if (!Q_strncasecmp (c, BASEDIRNAME, len))
+ {
+ //
+ //strncpy (qdir, path, c+len+2-path);
+ // the +2 assumes a 2 or 3 following quake which is not the
+ // case with a retail install
+ // so we need to add up how much to the next separator
+ sep = c + len;
+ count = 1;
+ while (*sep && *sep != '/' && *sep != '\\')
+ {
+ sep++;
+ count++;
+ }
+ strncpy (qdir, path, c+len+count-path);
+ qprintf ("qdir: %s\n", qdir);
+ for ( i = 0; i < strlen( qdir ); i++ )
+ {
+ if ( qdir[i] == '\\' )
+ qdir[i] = '/';
+ }
+
+ c += len+count;
+ while (*c)
+ {
+ if (*c == '/' || *c == '\\')
+ {
+ strncpy (gamedir, path, c+1-path);
+
+ for ( i = 0; i < strlen( gamedir ); i++ )
+ {
+ if ( gamedir[i] == '\\' )
+ gamedir[i] = '/';
+ }
+
+ qprintf ("gamedir: %s\n", gamedir);
+
+ if ( !writedir[0] )
+ strcpy( writedir, gamedir );
+ else if ( writedir[strlen( writedir )-1] != '/' )
+ {
+ writedir[strlen( writedir )] = '/';
+ writedir[strlen( writedir )+1] = 0;
+ }
+
+ return;
+ }
+ c++;
+ }
+ Error ("No gamedir in %s", path);
+ return;
+ }
+ }
+ Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
+}
+
+char *ExpandArg (const char *path)
+{
+ static char full[1024];
+
+ if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
+ {
+ Q_getwd (full);
+ strcat (full, path);
+ }
+ else
+ strcpy (full, path);
+ return full;
+}
+
+char *ExpandPath (const char *path)
+{
+ static char full[1024];
+ if (!qdir)
+ Error ("ExpandPath called without qdir set");
+ if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+ strcpy( full, path );
+ return full;
+ }
+ sprintf (full, "%s%s", qdir, path);
+ return full;
+}
+
+char *ExpandGamePath (const char *path)
+{
+ static char full[1024];
+ if (!qdir)
+ Error ("ExpandGamePath called without qdir set");
+ if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+ strcpy( full, path );
+ return full;
+ }
+ sprintf (full, "%s%s", gamedir, path);
+ return full;
+}
+
+char *ExpandPathAndArchive (const char *path)
+{
+ char *expanded;
+ char archivename[1024];
+
+ expanded = ExpandPath (path);
+
+ if (archive)
+ {
+ sprintf (archivename, "%s/%s", archivedir, path);
+ QCopyFile (expanded, archivename);
+ }
+ return expanded;
+}
+
+
+char *copystring(const char *s)
+{
+ char *b;
+ b = malloc(strlen(s)+1);
+ strcpy (b, s);
+ return b;
+}
+
+
+
+/*
+================
+I_FloatTime
+================
+*/
+double I_FloatTime (void)
+{
+ time_t t;
+
+ time (&t);
+
+ return t;
+#if 0
+// more precise, less portable
+ struct timeval tp;
+ struct timezone tzp;
+ static int secbase;
+
+ gettimeofday(&tp, &tzp);
+
+ if (!secbase)
+ {
+ secbase = tp.tv_sec;
+ return tp.tv_usec/1000000.0;
+ }
+
+ return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
+#endif
+}
+
+void Q_getwd (char *out)
+{
+ int i = 0;
+
+#ifdef WIN32
+ _getcwd (out, 256);
+ strcat (out, "\\");
+#else
+ getcwd (out, 256);
+ strcat (out, "/");
+#endif
+
+ while ( out[i] != 0 )
+ {
+ if ( out[i] == '\\' )
+ out[i] = '/';
+ i++;
+ }
+}
+
+
+void Q_mkdir (const char *path)
+{
+#ifdef WIN32
+ if (_mkdir (path) != -1)
+ return;
+#else
+ if (mkdir (path, 0777) != -1)
+ return;
+#endif
+ if (errno != EEXIST)
+ Error ("mkdir %s: %s",path, strerror(errno));
+}
+
+/*
+============
+FileTime
+
+returns -1 if not present
+============
+*/
+int FileTime (const char *path)
+{
+ struct stat buf;
+
+ if (stat (path,&buf) == -1)
+ return -1;
+
+ return buf.st_mtime;
+}
+
+
+
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+ int c;
+ int len;
+
+ len = 0;
+ com_token[0] = 0;
+
+ if (!data)
+ return NULL;
+
+// skip whitespace
+skipwhite:
+ while ( (c = *data) <= ' ')
+ {
+ if (c == 0)
+ {
+ com_eof = qtrue;
+ return NULL; // end of file;
+ }
+ data++;
+ }
+
+// skip // comments
+ if (c=='/' && data[1] == '/')
+ {
+ while (*data && *data != '\n')
+ data++;
+ goto skipwhite;
+ }
+
+
+// handle quoted strings specially
+ if (c == '\"')
+ {
+ data++;
+ do
+ {
+ c = *data++;
+ if (c=='\"')
+ {
+ com_token[len] = 0;
+ return data;
+ }
+ com_token[len] = c;
+ len++;
+ } while (1);
+ }
+
+// parse single characters
+ if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+ {
+ com_token[len] = c;
+ len++;
+ com_token[len] = 0;
+ return data+1;
+ }
+
+// parse a regular word
+ do
+ {
+ com_token[len] = c;
+ data++;
+ len++;
+ c = *data;
+ if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+ break;
+ } while (c>32);
+
+ com_token[len] = 0;
+ return data;
+}
+
+
+int Q_strncasecmp (const char *s1, const char *s2, int n)
+{
+ int c1, c2;
+
+ do
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if (!n--)
+ return 0; // strings are equal until end point
+
+ if (c1 != c2)
+ {
+ if (c1 >= 'a' && c1 <= 'z')
+ c1 -= ('a' - 'A');
+ if (c2 >= 'a' && c2 <= 'z')
+ c2 -= ('a' - 'A');
+ if (c1 != c2)
+ return -1; // strings not equal
+ }
+ } while (c1);
+
+ return 0; // strings are equal
+}
+
+int Q_stricmp (const char *s1, const char *s2)
+{
+ return Q_strncasecmp (s1, s2, 99999);
+}
+
+
+char *strupr (char *start)
+{
+ char *in;
+ in = start;
+ while (*in)
+ {
+ *in = toupper(*in);
+ in++;
+ }
+ return start;
+}
+
+char *strlower (char *start)
+{
+ char *in;
+ in = start;
+ while (*in)
+ {
+ *in = tolower(*in);
+ in++;
+ }
+ return start;
+}
+
+
+/*
+=============================================================================
+
+ MISC FUNCTIONS
+
+=============================================================================
+*/
+
+
+/*
+=================
+CheckParm
+
+Checks for the given parameter in the program's command line arguments
+Returns the argument number (1 to argc-1) or 0 if not present
+=================
+*/
+int CheckParm (const char *check)
+{
+ int i;
+
+ for (i = 1;i<myargc;i++)
+ {
+ if ( !Q_stricmp(check, myargv[i]) )
+ return i;
+ }
+
+ return 0;
+}
+
+
+
+/*
+================
+Q_filelength
+================
+*/
+int Q_filelength (FILE *f)
+{
+ int pos;
+ int end;
+
+ pos = ftell (f);
+ fseek (f, 0, SEEK_END);
+ end = ftell (f);
+ fseek (f, pos, SEEK_SET);
+
+ return end;
+}
+
+
+FILE *SafeOpenWrite (const char *filename)
+{
+ FILE *f;
+
+ f = fopen(filename, "wb");
+
+ if (!f)
+ Error ("Error opening %s: %s",filename,strerror(errno));
+
+ return f;
+}
+
+FILE *SafeOpenRead (const char *filename)
+{
+ FILE *f;
+
+ f = fopen(filename, "rb");
+
+ if (!f)
+ Error ("Error opening %s: %s",filename,strerror(errno));
+
+ return f;
+}
+
+
+void SafeRead (FILE *f, void *buffer, int count)
+{
+ if ( fread (buffer, 1, count, f) != (size_t)count)
+ Error ("File read failure");
+}
+
+
+void SafeWrite (FILE *f, const void *buffer, int count)
+{
+ if (fwrite (buffer, 1, count, f) != (size_t)count)
+ Error ("File write failure");
+}
+
+
+/*
+==============
+FileExists
+==============
+*/
+qboolean FileExists (const char *filename)
+{
+ FILE *f;
+
+ f = fopen (filename, "r");
+ if (!f)
+ return qfalse;
+ fclose (f);
+ return qtrue;
+}
+
+/*
+==============
+LoadFile
+==============
+*/
+int LoadFile( const char *filename, void **bufferptr )
+{
+ FILE *f;
+ int length;
+ void *buffer;
+
+ f = SafeOpenRead (filename);
+ length = Q_filelength (f);
+ buffer = malloc (length+1);
+ ((char *)buffer)[length] = 0;
+ SafeRead (f, buffer, length);
+ fclose (f);
+
+ *bufferptr = buffer;
+ return length;
+}
+
+
+/*
+==============
+LoadFileBlock
+-
+rounds up memory allocation to 4K boundry
+-
+==============
+*/
+int LoadFileBlock( const char *filename, void **bufferptr )
+{
+ FILE *f;
+ int length, nBlock, nAllocSize;
+ void *buffer;
+
+ f = SafeOpenRead (filename);
+ length = Q_filelength (f);
+ nAllocSize = length;
+ nBlock = nAllocSize % MEM_BLOCKSIZE;
+ if ( nBlock > 0) {
+ nAllocSize += MEM_BLOCKSIZE - nBlock;
+ }
+ buffer = malloc (nAllocSize+1);
+ memset(buffer, 0, nAllocSize+1);
+ SafeRead (f, buffer, length);
+ fclose (f);
+
+ *bufferptr = buffer;
+ return length;
+}
+
+
+/*
+==============
+TryLoadFile
+
+Allows failure
+==============
+*/
+int TryLoadFile (const char *filename, void **bufferptr)
+{
+ FILE *f;
+ int length;
+ void *buffer;
+
+ *bufferptr = NULL;
+
+ f = fopen (filename, "rb");
+ if (!f)
+ return -1;
+ length = Q_filelength (f);
+ buffer = malloc (length+1);
+ ((char *)buffer)[length] = 0;
+ SafeRead (f, buffer, length);
+ fclose (f);
+
+ *bufferptr = buffer;
+ return length;
+}
+
+
+/*
+==============
+SaveFile
+==============
+*/
+void SaveFile (const char *filename, const void *buffer, int count)
+{
+ FILE *f;
+
+ f = SafeOpenWrite (filename);
+ SafeWrite (f, buffer, count);
+ fclose (f);
+}
+
+
+
+void DefaultExtension (char *path, const char *extension)
+{
+ char *src;
+//
+// if path doesnt have a .EXT, append extension
+// (extension should include the .)
+//
+ src = path + strlen(path) - 1;
+
+ while (*src != '/' && *src != '\\' && src != path)
+ {
+ if (*src == '.')
+ return; // it has an extension
+ src--;
+ }
+
+ strcat (path, extension);
+}
+
+
+void DefaultPath (char *path, const char *basepath)
+{
+ char temp[128];
+
+ if (path[0] == PATHSEPERATOR)
+ return; // absolute path location
+ strcpy (temp,path);
+ strcpy (path,basepath);
+ strcat (path,temp);
+}
+
+
+void StripFilename (char *path)
+{
+ int length;
+
+ length = strlen(path)-1;
+ while (length > 0 && path[length] != PATHSEPERATOR)
+ length--;
+ path[length] = 0;
+}
+
+void StripExtension (char *path)
+{
+ int length;
+
+ length = strlen(path)-1;
+ while (length > 0 && path[length] != '.')
+ {
+ length--;
+ if (path[length] == '/')
+ return; // no extension
+ }
+ if (length)
+ path[length] = 0;
+}
+
+
+/*
+====================
+Extract file parts
+====================
+*/
+// FIXME: should include the slash, otherwise
+// backing to an empty path will be wrong when appending a slash
+void ExtractFilePath (const char *path, char *dest)
+{
+ const char *src;
+
+ src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+ while (src != path && *(src-1) != '\\' && *(src-1) != '/')
+ src--;
+
+ memcpy (dest, path, src-path);
+ dest[src-path] = 0;
+}
+
+void ExtractFileBase (const char *path, char *dest)
+{
+ const char *src;
+
+ src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+ while (src != path && *(src-1) != PATHSEPERATOR)
+ src--;
+
+ while (*src && *src != '.')
+ {
+ *dest++ = *src++;
+ }
+ *dest = 0;
+}
+
+void ExtractFileExtension (const char *path, char *dest)
+{
+ const char *src;
+
+ src = path + strlen(path) - 1;
+
+//
+// back up until a . or the start
+//
+ while (src != path && *(src-1) != '.')
+ src--;
+ if (src == path)
+ {
+ *dest = 0; // no extension
+ return;
+ }
+
+ strcpy (dest,src);
+}
+
+
+/*
+==============
+ParseNum / ParseHex
+==============
+*/
+int ParseHex (const char *hex)
+{
+ const char *str;
+ int num;
+
+ num = 0;
+ str = hex;
+
+ while (*str)
+ {
+ num <<= 4;
+ if (*str >= '0' && *str <= '9')
+ num += *str-'0';
+ else if (*str >= 'a' && *str <= 'f')
+ num += 10 + *str-'a';
+ else if (*str >= 'A' && *str <= 'F')
+ num += 10 + *str-'A';
+ else
+ Error ("Bad hex number: %s",hex);
+ str++;
+ }
+
+ return num;
+}
+
+
+int ParseNum (const char *str)
+{
+ if (str[0] == '$')
+ return ParseHex (str+1);
+ if (str[0] == '0' && str[1] == 'x')
+ return ParseHex (str+2);
+ return atol (str);
+}
+
+
+
+/*
+============================================================================
+
+ BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+#ifdef _SGI_SOURCE
+#define __BIG_ENDIAN__
+#endif
+
+#ifdef __BIG_ENDIAN__
+
+short LittleShort (short l)
+{
+ byte b1,b2;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+
+ return (b1<<8) + b2;
+}
+
+short BigShort (short l)
+{
+ return l;
+}
+
+
+int LittleLong (int l)
+{
+ byte b1,b2,b3,b4;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+ b3 = (l>>16)&255;
+ b4 = (l>>24)&255;
+
+ return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int BigLong (int l)
+{
+ return l;
+}
+
+
+float LittleFloat (float l)
+{
+ union {byte b[4]; float f;} in, out;
+
+ in.f = l;
+ out.b[0] = in.b[3];
+ out.b[1] = in.b[2];
+ out.b[2] = in.b[1];
+ out.b[3] = in.b[0];
+
+ return out.f;
+}
+
+float BigFloat (float l)
+{
+ return l;
+}
+
+
+#else
+
+
+short BigShort (short l)
+{
+ byte b1,b2;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+
+ return (b1<<8) + b2;
+}
+
+short LittleShort (short l)
+{
+ return l;
+}
+
+
+int BigLong (int l)
+{
+ byte b1,b2,b3,b4;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+ b3 = (l>>16)&255;
+ b4 = (l>>24)&255;
+
+ return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int LittleLong (int l)
+{
+ return l;
+}
+
+float BigFloat (float l)
+{
+ union {byte b[4]; float f;} in, out;
+
+ in.f = l;
+ out.b[0] = in.b[3];
+ out.b[1] = in.b[2];
+ out.b[2] = in.b[1];
+ out.b[3] = in.b[0];
+
+ return out.f;
+}
+
+float LittleFloat (float l)
+{
+ return l;
+}
+
+
+#endif
+
+
+//=======================================================
+
+
+// FIXME: byte swap?
+
+// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
+// and the initial and final xor values shown below... in other words, the
+// CCITT standard CRC used by XMODEM
+
+#define CRC_INIT_VALUE 0xffff
+#define CRC_XOR_VALUE 0x0000
+
+static unsigned short crctable[256] =
+{
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+void CRC_Init(unsigned short *crcvalue)
+{
+ *crcvalue = CRC_INIT_VALUE;
+}
+
+void CRC_ProcessByte(unsigned short *crcvalue, byte data)
+{
+ *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
+}
+
+unsigned short CRC_Value(unsigned short crcvalue)
+{
+ return crcvalue ^ CRC_XOR_VALUE;
+}
+//=============================================================================
+
+/*
+============
+CreatePath
+============
+*/
+void CreatePath (const char *path)
+{
+ const char *ofs;
+ char c;
+ char dir[1024];
+
+#ifdef _WIN32
+ int olddrive = -1;
+
+ if ( path[1] == ':' )
+ {
+ olddrive = _getdrive();
+ _chdrive( toupper( path[0] ) - 'A' + 1 );
+ }
+#endif
+
+ if (path[1] == ':')
+ path += 2;
+
+ for (ofs = path+1 ; *ofs ; ofs++)
+ {
+ c = *ofs;
+ if (c == '/' || c == '\\')
+ { // create the directory
+ memcpy( dir, path, ofs - path );
+ dir[ ofs - path ] = 0;
+ Q_mkdir( dir );
+ }
+ }
+
+#ifdef _WIN32
+ if ( olddrive != -1 )
+ {
+ _chdrive( olddrive );
+ }
+#endif
+}
+
+
+/*
+============
+QCopyFile
+
+ Used to archive source files
+============
+*/
+void QCopyFile (const char *from, const char *to)
+{
+ void *buffer;
+ int length;
+
+ length = LoadFile (from, &buffer);
+ CreatePath (to);
+ SaveFile (to, buffer, length);
+ free (buffer);
+}
diff --git a/q3asm/cmdlib.h b/q3asm/cmdlib.h
index b7be51b..0d7dfc3 100755
--- a/q3asm/cmdlib.h
+++ b/q3asm/cmdlib.h
@@ -1,160 +1,160 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// cmdlib.h
-
-#ifndef __CMDLIB__
-#define __CMDLIB__
-
-#ifdef _WIN32
-#pragma warning(disable : 4244) // MIPS
-#pragma warning(disable : 4136) // X86
-#pragma warning(disable : 4051) // ALPHA
-
-#pragma warning(disable : 4018) // signed/unsigned mismatch
-#pragma warning(disable : 4305) // truncate from double to float
-
-#pragma check_stack(off)
-
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-
-#ifdef _WIN32
-
-#pragma intrinsic( memset, memcpy )
-
-#endif
-
-#ifndef __BYTEBOOL__
-#define __BYTEBOOL__
-typedef enum { qfalse, qtrue } qboolean;
-typedef unsigned char byte;
-#endif
-
-#define MAX_OS_PATH 1024
-#define MEM_BLOCKSIZE 4096
-
-// the dec offsetof macro doesnt work very well...
-#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
-
-
-// set these before calling CheckParm
-extern int myargc;
-extern char **myargv;
-
-char *strupr (char *in);
-char *strlower (char *in);
-int Q_strncasecmp( const char *s1, const char *s2, int n );
-int Q_stricmp( const char *s1, const char *s2 );
-void Q_getwd( char *out );
-
-int Q_filelength (FILE *f);
-int FileTime( const char *path );
-
-void Q_mkdir( const char *path );
-
-extern char qdir[1024];
-extern char gamedir[1024];
-extern char writedir[1024];
-void SetQdirFromPath( const char *path );
-char *ExpandArg( const char *path ); // from cmd line
-char *ExpandPath( const char *path ); // from scripts
-char *ExpandGamePath (const char *path);
-char *ExpandPathAndArchive( const char *path );
-
-
-double I_FloatTime( void );
-
-void Error( const char *error, ... );
-int CheckParm( const char *check );
-
-FILE *SafeOpenWrite( const char *filename );
-FILE *SafeOpenRead( const char *filename );
-void SafeRead (FILE *f, void *buffer, int count);
-void SafeWrite (FILE *f, const void *buffer, int count);
-
-int LoadFile( const char *filename, void **bufferptr );
-int LoadFileBlock( const char *filename, void **bufferptr );
-int TryLoadFile( const char *filename, void **bufferptr );
-void SaveFile( const char *filename, const void *buffer, int count );
-qboolean FileExists( const char *filename );
-
-void DefaultExtension( char *path, const char *extension );
-void DefaultPath( char *path, const char *basepath );
-void StripFilename( char *path );
-void StripExtension( char *path );
-
-void ExtractFilePath( const char *path, char *dest );
-void ExtractFileBase( const char *path, char *dest );
-void ExtractFileExtension( const char *path, char *dest );
-
-int ParseNum (const char *str);
-
-short BigShort (short l);
-short LittleShort (short l);
-int BigLong (int l);
-int LittleLong (int l);
-float BigFloat (float l);
-float LittleFloat (float l);
-
-
-char *COM_Parse (char *data);
-
-extern char com_token[1024];
-extern qboolean com_eof;
-
-char *copystring(const char *s);
-
-
-void CRC_Init(unsigned short *crcvalue);
-void CRC_ProcessByte(unsigned short *crcvalue, byte data);
-unsigned short CRC_Value(unsigned short crcvalue);
-
-void CreatePath( const char *path );
-void QCopyFile( const char *from, const char *to );
-
-extern qboolean archive;
-extern char archivedir[1024];
-
-
-extern qboolean verbose;
-void qprintf( const char *format, ... );
-void _printf( const char *format, ... );
-
-void ExpandWildcards( int *argc, char ***argv );
-
-
-// for compression routines
-typedef struct
-{
- void *data;
- int count, width, height;
-} cblock_t;
-
-
-#endif
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// cmdlib.h
+
+#ifndef __CMDLIB__
+#define __CMDLIB__
+
+#ifdef _WIN32
+#pragma warning(disable : 4244) // MIPS
+#pragma warning(disable : 4136) // X86
+#pragma warning(disable : 4051) // ALPHA
+
+#pragma warning(disable : 4018) // signed/unsigned mismatch
+#pragma warning(disable : 4305) // truncate from double to float
+
+#pragma check_stack(off)
+
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+
+#pragma intrinsic( memset, memcpy )
+
+#endif
+
+#ifndef __BYTEBOOL__
+#define __BYTEBOOL__
+typedef enum { qfalse, qtrue } qboolean;
+typedef unsigned char byte;
+#endif
+
+#define MAX_OS_PATH 1024
+#define MEM_BLOCKSIZE 4096
+
+// the dec offsetof macro doesnt work very well...
+#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
+
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+char *strupr (char *in);
+char *strlower (char *in);
+int Q_strncasecmp( const char *s1, const char *s2, int n );
+int Q_stricmp( const char *s1, const char *s2 );
+void Q_getwd( char *out );
+
+int Q_filelength (FILE *f);
+int FileTime( const char *path );
+
+void Q_mkdir( const char *path );
+
+extern char qdir[1024];
+extern char gamedir[1024];
+extern char writedir[1024];
+void SetQdirFromPath( const char *path );
+char *ExpandArg( const char *path ); // from cmd line
+char *ExpandPath( const char *path ); // from scripts
+char *ExpandGamePath (const char *path);
+char *ExpandPathAndArchive( const char *path );
+
+
+double I_FloatTime( void );
+
+void Error( const char *error, ... );
+int CheckParm( const char *check );
+
+FILE *SafeOpenWrite( const char *filename );
+FILE *SafeOpenRead( const char *filename );
+void SafeRead (FILE *f, void *buffer, int count);
+void SafeWrite (FILE *f, const void *buffer, int count);
+
+int LoadFile( const char *filename, void **bufferptr );
+int LoadFileBlock( const char *filename, void **bufferptr );
+int TryLoadFile( const char *filename, void **bufferptr );
+void SaveFile( const char *filename, const void *buffer, int count );
+qboolean FileExists( const char *filename );
+
+void DefaultExtension( char *path, const char *extension );
+void DefaultPath( char *path, const char *basepath );
+void StripFilename( char *path );
+void StripExtension( char *path );
+
+void ExtractFilePath( const char *path, char *dest );
+void ExtractFileBase( const char *path, char *dest );
+void ExtractFileExtension( const char *path, char *dest );
+
+int ParseNum (const char *str);
+
+short BigShort (short l);
+short LittleShort (short l);
+int BigLong (int l);
+int LittleLong (int l);
+float BigFloat (float l);
+float LittleFloat (float l);
+
+
+char *COM_Parse (char *data);
+
+extern char com_token[1024];
+extern qboolean com_eof;
+
+char *copystring(const char *s);
+
+
+void CRC_Init(unsigned short *crcvalue);
+void CRC_ProcessByte(unsigned short *crcvalue, byte data);
+unsigned short CRC_Value(unsigned short crcvalue);
+
+void CreatePath( const char *path );
+void QCopyFile( const char *from, const char *to );
+
+extern qboolean archive;
+extern char archivedir[1024];
+
+
+extern qboolean verbose;
+void qprintf( const char *format, ... );
+void _printf( const char *format, ... );
+
+void ExpandWildcards( int *argc, char ***argv );
+
+
+// for compression routines
+typedef struct
+{
+ void *data;
+ int count, width, height;
+} cblock_t;
+
+
+#endif
diff --git a/q3asm/lib.txt b/q3asm/lib.txt
index 7abf270..737a030 100755
--- a/q3asm/lib.txt
+++ b/q3asm/lib.txt
@@ -1,31 +1,31 @@
-
-strlen
-strcasecmp
-tolower
-strcat
-strncpy
-strcmp
-strcpy
-strchr
-
-vsprintf
-
-memcpy
-memset
-rand
-
-atoi
-atof
-
-abs
-
-floor
-fabs
-tan
-atan
-sqrt
-log
-cos
-sin
-atan2
-
+
+strlen
+strcasecmp
+tolower
+strcat
+strncpy
+strcmp
+strcpy
+strchr
+
+vsprintf
+
+memcpy
+memset
+rand
+
+atoi
+atof
+
+abs
+
+floor
+fabs
+tan
+atan
+sqrt
+log
+cos
+sin
+atan2
+
diff --git a/q3asm/mathlib.h b/q3asm/mathlib.h
index 8034808..f88bf58 100755
--- a/q3asm/mathlib.h
+++ b/q3asm/mathlib.h
@@ -1,94 +1,94 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#ifndef __MATHLIB__
-#define __MATHLIB__
-
-// mathlib.h
-
-#include <math.h>
-
-#ifdef DOUBLEVEC_T
-typedef double vec_t;
-#else
-typedef float vec_t;
-#endif
-typedef vec_t vec2_t[3];
-typedef vec_t vec3_t[3];
-typedef vec_t vec4_t[4];
-
-#define SIDE_FRONT 0
-#define SIDE_ON 2
-#define SIDE_BACK 1
-#define SIDE_CROSS -2
-
-#define Q_PI 3.14159265358979323846
-#define DEG2RAD( a ) ( ( (a) * Q_PI ) / 180.0F )
-#define RAD2DEG( a ) ( ( (a) * 180.0f ) / Q_PI )
-
-extern vec3_t vec3_origin;
-
-#define EQUAL_EPSILON 0.001
-
-// plane types are used to speed some tests
-// 0-2 are axial planes
-#define PLANE_X 0
-#define PLANE_Y 1
-#define PLANE_Z 2
-#define PLANE_NON_AXIAL 3
-
-qboolean VectorCompare( const vec3_t v1, const vec3_t v2 );
-
-#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
-#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
-#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
-#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
-#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
-#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
-#define VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
-void Vec10Copy( vec_t *in, vec_t *out );
-
-vec_t Q_rint (vec_t in);
-vec_t _DotProduct (vec3_t v1, vec3_t v2);
-void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
-void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
-void _VectorCopy (vec3_t in, vec3_t out);
-void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
-
-double VectorLength( const vec3_t v );
-
-void VectorMA( const vec3_t va, double scale, const vec3_t vb, vec3_t vc );
-
-void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross );
-vec_t VectorNormalize( const vec3_t in, vec3_t out );
-vec_t ColorNormalize( const vec3_t in, vec3_t out );
-void VectorInverse (vec3_t v);
-
-void ClearBounds (vec3_t mins, vec3_t maxs);
-void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs );
-
-qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c );
-
-void NormalToLatLong( const vec3_t normal, byte bytes[2] );
-
-int PlaneTypeForNormal (vec3_t normal);
-
-#endif
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __MATHLIB__
+#define __MATHLIB__
+
+// mathlib.h
+
+#include <math.h>
+
+#ifdef DOUBLEVEC_T
+typedef double vec_t;
+#else
+typedef float vec_t;
+#endif
+typedef vec_t vec2_t[3];
+typedef vec_t vec3_t[3];
+typedef vec_t vec4_t[4];
+
+#define SIDE_FRONT 0
+#define SIDE_ON 2
+#define SIDE_BACK 1
+#define SIDE_CROSS -2
+
+#define Q_PI 3.14159265358979323846
+#define DEG2RAD( a ) ( ( (a) * Q_PI ) / 180.0F )
+#define RAD2DEG( a ) ( ( (a) * 180.0f ) / Q_PI )
+
+extern vec3_t vec3_origin;
+
+#define EQUAL_EPSILON 0.001
+
+// plane types are used to speed some tests
+// 0-2 are axial planes
+#define PLANE_X 0
+#define PLANE_Y 1
+#define PLANE_Z 2
+#define PLANE_NON_AXIAL 3
+
+qboolean VectorCompare( const vec3_t v1, const vec3_t v2 );
+
+#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
+#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
+#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
+#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
+#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
+#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
+#define VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
+void Vec10Copy( vec_t *in, vec_t *out );
+
+vec_t Q_rint (vec_t in);
+vec_t _DotProduct (vec3_t v1, vec3_t v2);
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorCopy (vec3_t in, vec3_t out);
+void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
+
+double VectorLength( const vec3_t v );
+
+void VectorMA( const vec3_t va, double scale, const vec3_t vb, vec3_t vc );
+
+void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross );
+vec_t VectorNormalize( const vec3_t in, vec3_t out );
+vec_t ColorNormalize( const vec3_t in, vec3_t out );
+void VectorInverse (vec3_t v);
+
+void ClearBounds (vec3_t mins, vec3_t maxs);
+void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs );
+
+qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c );
+
+void NormalToLatLong( const vec3_t normal, byte bytes[2] );
+
+int PlaneTypeForNormal (vec3_t normal);
+
+#endif
diff --git a/q3asm/notes.txt b/q3asm/notes.txt
index 4a016f0..63297f3 100755
--- a/q3asm/notes.txt
+++ b/q3asm/notes.txt
@@ -1,16 +1,16 @@
-
-don't do any paramter conversion (double to float, etc)
-
-
-
-Why?
-
-Security.
-Portability.
-
-It may be more aproachable.
-
-can still use regular dlls for development purposes
-
-lcc
-q3asm
+
+don't do any paramter conversion (double to float, etc)
+
+
+
+Why?
+
+Security.
+Portability.
+
+It may be more aproachable.
+
+can still use regular dlls for development purposes
+
+lcc
+q3asm
diff --git a/q3asm/ops.txt b/q3asm/ops.txt
index 992e288..e897f49 100755
--- a/q3asm/ops.txt
+++ b/q3asm/ops.txt
@@ -1,132 +1,132 @@
-CNSTF,
-CNSTI,
-CNSTP,
-CNSTU,
-
-ARGB,
-ARGF,
-ARGI,
-ARGP,
-ARGU,
-
-ASGNB,
-ASGNF,
-ASGNI,
-ASGNP,
-ASGNU,
-
-INDIRB,
-INDIRF,
-INDIRI,
-INDIRP,
-INDIRU,
-
-CVFF,
-CVFI,
-
-CVIF,
-CVII,
-CVIU,
-
-CVPU,
-
-CVUI,
-CVUP,
-CVUU,
-
-NEGF,
-NEGI,
-
-CALLB,
-CALLF,
-CALLI,
-CALLP,
-CALLU,
-CALLV,
-
-RETF,
-RETI,
-RETP,
-RETU,
-RETV,
-
-ADDRGP,
-
-ADDRFP,
-
-ADDRLP,
-
-ADDF,
-ADDI,
-ADDP,
-ADDU,
-
-SUBF,
-SUBI,
-SUBP,
-SUBU,
-
-LSHI,
-LSHU,
-
-MODI,
-MODU,
-
-RSHI,
-RSHU,
-
-BANDI,
-BANDU,
-
-BCOMI,
-BCOMU,
-
-BORI,
-BORU,
-
-BXORI,
-BXORU,
-
-DIVF,
-DIVI,
-DIVU,
-
-MULF,
-MULI,
-MULU,
-
-EQF,
-EQI,
-EQU,
-
-GEF,
-GEI,
-GEU,
-
-GTF,
-GTI,
-GTU,
-
-LEF,
-LEI,
-LEU,
-
-LTF,
-LTI,
-LTU,
-
-NEF,
-NEI,
-NEU,
-
-JUMPV,
-
-LABELV,
-
-LOADB,
-LOADF,
-LOADI,
-LOADP,
-LOADU,
-
-
+CNSTF,
+CNSTI,
+CNSTP,
+CNSTU,
+
+ARGB,
+ARGF,
+ARGI,
+ARGP,
+ARGU,
+
+ASGNB,
+ASGNF,
+ASGNI,
+ASGNP,
+ASGNU,
+
+INDIRB,
+INDIRF,
+INDIRI,
+INDIRP,
+INDIRU,
+
+CVFF,
+CVFI,
+
+CVIF,
+CVII,
+CVIU,
+
+CVPU,
+
+CVUI,
+CVUP,
+CVUU,
+
+NEGF,
+NEGI,
+
+CALLB,
+CALLF,
+CALLI,
+CALLP,
+CALLU,
+CALLV,
+
+RETF,
+RETI,
+RETP,
+RETU,
+RETV,
+
+ADDRGP,
+
+ADDRFP,
+
+ADDRLP,
+
+ADDF,
+ADDI,
+ADDP,
+ADDU,
+
+SUBF,
+SUBI,
+SUBP,
+SUBU,
+
+LSHI,
+LSHU,
+
+MODI,
+MODU,
+
+RSHI,
+RSHU,
+
+BANDI,
+BANDU,
+
+BCOMI,
+BCOMU,
+
+BORI,
+BORU,
+
+BXORI,
+BXORU,
+
+DIVF,
+DIVI,
+DIVU,
+
+MULF,
+MULI,
+MULU,
+
+EQF,
+EQI,
+EQU,
+
+GEF,
+GEI,
+GEU,
+
+GTF,
+GTI,
+GTU,
+
+LEF,
+LEI,
+LEU,
+
+LTF,
+LTI,
+LTU,
+
+NEF,
+NEI,
+NEU,
+
+JUMPV,
+
+LABELV,
+
+LOADB,
+LOADF,
+LOADI,
+LOADP,
+LOADU,
+
+
diff --git a/q3asm/opstrings.h b/q3asm/opstrings.h
index 51f2bf3..f611b3e 100755
--- a/q3asm/opstrings.h
+++ b/q3asm/opstrings.h
@@ -1,175 +1,175 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-{ "BREAK", OP_BREAK },
-
-{ "CNSTF4", OP_CONST },
-{ "CNSTI4", OP_CONST },
-{ "CNSTP4", OP_CONST },
-{ "CNSTU4", OP_CONST },
-
-{ "CNSTI2", OP_CONST },
-{ "CNSTU2", OP_CONST },
-
-{ "CNSTI1", OP_CONST },
-{ "CNSTU1", OP_CONST },
-
-//{ "ARGB", OP_ARG },
-//{ "ARGF", OP_ARG },
-//{ "ARGI", OP_ARG },
-//{ "ARGP", OP_ARG },
-//{ "ARGU", OP_ARG },
-
-{ "ASGNB", OP_BLOCK_COPY },
-{ "ASGNF4", OP_STORE4 },
-{ "ASGNI4", OP_STORE4 },
-{ "ASGNP4", OP_STORE4 },
-{ "ASGNU4", OP_STORE4 },
-
-{ "ASGNI2", OP_STORE2 },
-{ "ASGNU2", OP_STORE2 },
-
-{ "ASGNI1", OP_STORE1 },
-{ "ASGNU1", OP_STORE1 },
-
-{ "INDIRB", OP_IGNORE }, // block copy deals with this
-{ "INDIRF4", OP_LOAD4 },
-{ "INDIRI4", OP_LOAD4 },
-{ "INDIRP4", OP_LOAD4 },
-{ "INDIRU4", OP_LOAD4 },
-
-{ "INDIRI2", OP_LOAD2 },
-{ "INDIRU2", OP_LOAD2 },
-
-{ "INDIRI1", OP_LOAD1 },
-{ "INDIRU1", OP_LOAD1 },
-
-{ "CVFF4", OP_UNDEF },
-{ "CVFI4", OP_CVFI },
-
-{ "CVIF4", OP_CVIF },
-{ "CVII4", OP_SEX8 }, // will be either SEX8 or SEX16
-{ "CVII1", OP_IGNORE },
-{ "CVII2", OP_IGNORE },
-{ "CVIU4", OP_IGNORE },
-
-{ "CVPU4", OP_IGNORE },
-
-{ "CVUI4", OP_IGNORE },
-{ "CVUP4", OP_IGNORE },
-{ "CVUU4", OP_IGNORE },
-
-{ "CVUU1", OP_IGNORE },
-
-{ "NEGF4", OP_NEGF },
-{ "NEGI4", OP_NEGI },
-
-//{ "CALLB", OP_UNDEF },
-//{ "CALLF", OP_UNDEF },
-//{ "CALLI", OP_UNDEF },
-//{ "CALLP", OP_UNDEF },
-//{ "CALLU", OP_UNDEF },
-//{ "CALLV", OP_CALL },
-
-//{ "RETF", OP_UNDEF },
-//{ "RETI", OP_UNDEF },
-//{ "RETP", OP_UNDEF },
-//{ "RETU", OP_UNDEF },
-//{ "RETV", OP_UNDEF },
-
-{ "ADDRGP4", OP_CONST },
-
-//{ "ADDRFP", OP_PARM },
-//{ "ADDRLP", OP_LOCAL },
-
-{ "ADDF4", OP_ADDF },
-{ "ADDI4", OP_ADD },
-{ "ADDP4", OP_ADD },
-{ "ADDP", OP_ADD },
-{ "ADDU4", OP_ADD },
-
-{ "SUBF4", OP_SUBF },
-{ "SUBI4", OP_SUB },
-{ "SUBP4", OP_SUB },
-{ "SUBU4", OP_SUB },
-
-{ "LSHI4", OP_LSH },
-{ "LSHU4", OP_LSH },
-
-{ "MODI4", OP_MODI },
-{ "MODU4", OP_MODU },
-
-{ "RSHI4", OP_RSHI },
-{ "RSHU4", OP_RSHU },
-
-{ "BANDI4", OP_BAND },
-{ "BANDU4", OP_BAND },
-
-{ "BCOMI4", OP_BCOM },
-{ "BCOMU4", OP_BCOM },
-
-{ "BORI4", OP_BOR },
-{ "BORU4", OP_BOR },
-
-{ "BXORI4", OP_BXOR },
-{ "BXORU4", OP_BXOR },
-
-{ "DIVF4", OP_DIVF },
-{ "DIVI4", OP_DIVI },
-{ "DIVU4", OP_DIVU },
-
-{ "MULF4", OP_MULF },
-{ "MULI4", OP_MULI },
-{ "MULU4", OP_MULU },
-
-{ "EQF4", OP_EQF },
-{ "EQI4", OP_EQ },
-{ "EQU4", OP_EQ },
-
-{ "GEF4", OP_GEF },
-{ "GEI4", OP_GEI },
-{ "GEU4", OP_GEU },
-
-{ "GTF4", OP_GTF },
-{ "GTI4", OP_GTI },
-{ "GTU4", OP_GTU },
-
-{ "LEF4", OP_LEF },
-{ "LEI4", OP_LEI },
-{ "LEU4", OP_LEU },
-
-{ "LTF4", OP_LTF },
-{ "LTI4", OP_LTI },
-{ "LTU4", OP_LTU },
-
-{ "NEF4", OP_NEF },
-{ "NEI4", OP_NE },
-{ "NEU4", OP_NE },
-
-{ "JUMPV", OP_JUMP },
-
-{ "LOADB4", OP_UNDEF },
-{ "LOADF4", OP_UNDEF },
-{ "LOADI4", OP_UNDEF },
-{ "LOADP4", OP_UNDEF },
-{ "LOADU4", OP_UNDEF },
-
-
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+{ "BREAK", OP_BREAK },
+
+{ "CNSTF4", OP_CONST },
+{ "CNSTI4", OP_CONST },
+{ "CNSTP4", OP_CONST },
+{ "CNSTU4", OP_CONST },
+
+{ "CNSTI2", OP_CONST },
+{ "CNSTU2", OP_CONST },
+
+{ "CNSTI1", OP_CONST },
+{ "CNSTU1", OP_CONST },
+
+//{ "ARGB", OP_ARG },
+//{ "ARGF", OP_ARG },
+//{ "ARGI", OP_ARG },
+//{ "ARGP", OP_ARG },
+//{ "ARGU", OP_ARG },
+
+{ "ASGNB", OP_BLOCK_COPY },
+{ "ASGNF4", OP_STORE4 },
+{ "ASGNI4", OP_STORE4 },
+{ "ASGNP4", OP_STORE4 },
+{ "ASGNU4", OP_STORE4 },
+
+{ "ASGNI2", OP_STORE2 },
+{ "ASGNU2", OP_STORE2 },
+
+{ "ASGNI1", OP_STORE1 },
+{ "ASGNU1", OP_STORE1 },
+
+{ "INDIRB", OP_IGNORE }, // block copy deals with this
+{ "INDIRF4", OP_LOAD4 },
+{ "INDIRI4", OP_LOAD4 },
+{ "INDIRP4", OP_LOAD4 },
+{ "INDIRU4", OP_LOAD4 },
+
+{ "INDIRI2", OP_LOAD2 },
+{ "INDIRU2", OP_LOAD2 },
+
+{ "INDIRI1", OP_LOAD1 },
+{ "INDIRU1", OP_LOAD1 },
+
+{ "CVFF4", OP_UNDEF },
+{ "CVFI4", OP_CVFI },
+
+{ "CVIF4", OP_CVIF },
+{ "CVII4", OP_SEX8 }, // will be either SEX8 or SEX16
+{ "CVII1", OP_IGNORE },
+{ "CVII2", OP_IGNORE },
+{ "CVIU4", OP_IGNORE },
+
+{ "CVPU4", OP_IGNORE },
+
+{ "CVUI4", OP_IGNORE },
+{ "CVUP4", OP_IGNORE },
+{ "CVUU4", OP_IGNORE },
+
+{ "CVUU1", OP_IGNORE },
+
+{ "NEGF4", OP_NEGF },
+{ "NEGI4", OP_NEGI },
+
+//{ "CALLB", OP_UNDEF },
+//{ "CALLF", OP_UNDEF },
+//{ "CALLI", OP_UNDEF },
+//{ "CALLP", OP_UNDEF },
+//{ "CALLU", OP_UNDEF },
+//{ "CALLV", OP_CALL },
+
+//{ "RETF", OP_UNDEF },
+//{ "RETI", OP_UNDEF },
+//{ "RETP", OP_UNDEF },
+//{ "RETU", OP_UNDEF },
+//{ "RETV", OP_UNDEF },
+
+{ "ADDRGP4", OP_CONST },
+
+//{ "ADDRFP", OP_PARM },
+//{ "ADDRLP", OP_LOCAL },
+
+{ "ADDF4", OP_ADDF },
+{ "ADDI4", OP_ADD },
+{ "ADDP4", OP_ADD },
+{ "ADDP", OP_ADD },
+{ "ADDU4", OP_ADD },
+
+{ "SUBF4", OP_SUBF },
+{ "SUBI4", OP_SUB },
+{ "SUBP4", OP_SUB },
+{ "SUBU4", OP_SUB },
+
+{ "LSHI4", OP_LSH },
+{ "LSHU4", OP_LSH },
+
+{ "MODI4", OP_MODI },
+{ "MODU4", OP_MODU },
+
+{ "RSHI4", OP_RSHI },
+{ "RSHU4", OP_RSHU },
+
+{ "BANDI4", OP_BAND },
+{ "BANDU4", OP_BAND },
+
+{ "BCOMI4", OP_BCOM },
+{ "BCOMU4", OP_BCOM },
+
+{ "BORI4", OP_BOR },
+{ "BORU4", OP_BOR },
+
+{ "BXORI4", OP_BXOR },
+{ "BXORU4", OP_BXOR },
+
+{ "DIVF4", OP_DIVF },
+{ "DIVI4", OP_DIVI },
+{ "DIVU4", OP_DIVU },
+
+{ "MULF4", OP_MULF },
+{ "MULI4", OP_MULI },
+{ "MULU4", OP_MULU },
+
+{ "EQF4", OP_EQF },
+{ "EQI4", OP_EQ },
+{ "EQU4", OP_EQ },
+
+{ "GEF4", OP_GEF },
+{ "GEI4", OP_GEI },
+{ "GEU4", OP_GEU },
+
+{ "GTF4", OP_GTF },
+{ "GTI4", OP_GTI },
+{ "GTU4", OP_GTU },
+
+{ "LEF4", OP_LEF },
+{ "LEI4", OP_LEI },
+{ "LEU4", OP_LEU },
+
+{ "LTF4", OP_LTF },
+{ "LTI4", OP_LTI },
+{ "LTU4", OP_LTU },
+
+{ "NEF4", OP_NEF },
+{ "NEI4", OP_NE },
+{ "NEU4", OP_NE },
+
+{ "JUMPV", OP_JUMP },
+
+{ "LOADB4", OP_UNDEF },
+{ "LOADF4", OP_UNDEF },
+{ "LOADI4", OP_UNDEF },
+{ "LOADP4", OP_UNDEF },
+{ "LOADU4", OP_UNDEF },
+
+
diff --git a/q3asm/q3asm.c b/q3asm/q3asm.c
index 836e427..b19c361 100755
--- a/q3asm/q3asm.c
+++ b/q3asm/q3asm.c
@@ -1,1047 +1,1047 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "qfiles.h"
-
-/* MSVC-ism fix. */
-#define atoi(s) strtoul(s,NULL,10)
-
-char outputFilename[MAX_OS_PATH];
-
-// the zero page size is just used for detecting run time faults
-#define ZERO_PAGE_SIZE 0 // 256
-
-typedef enum {
- OP_UNDEF,
-
- OP_IGNORE,
-
- OP_BREAK,
-
- OP_ENTER,
- OP_LEAVE,
- OP_CALL,
- OP_PUSH,
- OP_POP,
-
- OP_CONST,
- OP_LOCAL,
-
- OP_JUMP,
-
- //-------------------
-
- OP_EQ,
- OP_NE,
-
- OP_LTI,
- OP_LEI,
- OP_GTI,
- OP_GEI,
-
- OP_LTU,
- OP_LEU,
- OP_GTU,
- OP_GEU,
-
- OP_EQF,
- OP_NEF,
-
- OP_LTF,
- OP_LEF,
- OP_GTF,
- OP_GEF,
-
- //-------------------
-
- OP_LOAD1,
- OP_LOAD2,
- OP_LOAD4,
- OP_STORE1,
- OP_STORE2,
- OP_STORE4, // *(stack[top-1]) = stack[yop
- OP_ARG,
- OP_BLOCK_COPY,
-
- //-------------------
-
- OP_SEX8,
- OP_SEX16,
-
- OP_NEGI,
- OP_ADD,
- OP_SUB,
- OP_DIVI,
- OP_DIVU,
- OP_MODI,
- OP_MODU,
- OP_MULI,
- OP_MULU,
-
- OP_BAND,
- OP_BOR,
- OP_BXOR,
- OP_BCOM,
-
- OP_LSH,
- OP_RSHI,
- OP_RSHU,
-
- OP_NEGF,
- OP_ADDF,
- OP_SUBF,
- OP_DIVF,
- OP_MULF,
-
- OP_CVIF,
- OP_CVFI
-} opcode_t;
-
-typedef struct {
- int imageBytes; // after decompression
- int entryPoint;
- int stackBase;
- int stackSize;
-} executableHeader_t;
-
-typedef enum {
- CODESEG,
- DATASEG, // initialized 32 bit data, will be byte swapped
- LITSEG, // strings
- BSSSEG, // 0 filled
- NUM_SEGMENTS
-} segmentName_t;
-
-#define MAX_IMAGE 0x400000
-
-typedef struct {
- byte image[MAX_IMAGE];
- int imageUsed;
- int segmentBase; // only valid on second pass
-} segment_t;
-
-typedef struct symbol_s {
- struct symbol_s *next;
- int hash;
- segment_t *segment;
- char *name;
- int value;
-} symbol_t;
-
-
-segment_t segment[NUM_SEGMENTS];
-segment_t *currentSegment;
-
-int passNumber;
-
-int numSymbols;
-int errorCount;
-
-symbol_t *symbols;
-symbol_t *lastSymbol;
-
-
-#define MAX_ASM_FILES 256
-int numAsmFiles;
-char *asmFiles[MAX_ASM_FILES];
-char *asmFileNames[MAX_ASM_FILES];
-
-int currentFileIndex;
-char *currentFileName;
-int currentFileLine;
-
-//int stackSize = 16384;
-int stackSize = 0x10000;
-
-// we need to convert arg and ret instructions to
-// stores to the local stack frame, so we need to track the
-// characteristics of the current functions stack frame
-int currentLocals; // bytes of locals needed by this function
-int currentArgs; // bytes of largest argument list called from this function
-int currentArgOffset; // byte offset in currentArgs to store next arg, reset each call
-
-#define MAX_LINE_LENGTH 1024
-char lineBuffer[MAX_LINE_LENGTH];
-int lineParseOffset;
-char token[MAX_LINE_LENGTH];
-
-int instructionCount;
-
-typedef struct {
- char *name;
- int opcode;
-} sourceOps_t;
-
-sourceOps_t sourceOps[] = {
-#include "opstrings.h"
-};
-
-#define NUM_SOURCE_OPS ( sizeof( sourceOps ) / sizeof( sourceOps[0] ) )
-
-int opcodesHash[ NUM_SOURCE_OPS ];
-
-
-/*
-=============
-HashString
-=============
-*/
-int HashString( char *s ) {
- int v = 0;
-
- while ( *s ) {
- v += *s;
- s++;
- }
- return v;
-}
-
-
-/*
-============
-CodeError
-============
-*/
-void CodeError( char *fmt, ... ) {
- va_list argptr;
-
- errorCount++;
-
- printf( "%s:%i ", currentFileName, currentFileLine );
-
- va_start( argptr,fmt );
- vprintf( fmt,argptr );
- va_end( argptr );
-}
-
-/*
-============
-EmitByte
-============
-*/
-void EmitByte( segment_t *seg, int v ) {
- if ( seg->imageUsed >= MAX_IMAGE ) {
- Error( "MAX_IMAGE" );
- }
- seg->image[ seg->imageUsed ] = v;
- seg->imageUsed++;
-}
-
-/*
-============
-EmitInt
-============
-*/
-void EmitInt( segment_t *seg, int v ) {
- if ( seg->imageUsed >= MAX_IMAGE - 4) {
- Error( "MAX_IMAGE" );
- }
- seg->image[ seg->imageUsed ] = v & 255;
- seg->image[ seg->imageUsed + 1 ] = ( v >> 8 ) & 255;
- seg->image[ seg->imageUsed + 2 ] = ( v >> 16 ) & 255;
- seg->image[ seg->imageUsed + 3 ] = ( v >> 24 ) & 255;
- seg->imageUsed += 4;
-}
-
-/*
-============
-DefineSymbol
-
-Symbols can only be defined on pass 0
-============
-*/
-void DefineSymbol( char *sym, int value ) {
- symbol_t *s, *after;
- char expanded[MAX_LINE_LENGTH];
- int hash;
-
- if ( passNumber == 1 ) {
- return;
- }
-
- // TTimo
- // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=381
- // as a security, bail out if vmMain entry point is not first
- if (!Q_stricmp(sym, "vmMain"))
- if (value)
- Error( "vmMain must be the first symbol in the qvm (got offset %d)\n", value );
-
- // add the file prefix to local symbols to guarantee unique
- if ( sym[0] == '$' ) {
- sprintf( expanded, "%s_%i", sym, currentFileIndex );
- sym = expanded;
- }
-
- hash = HashString( sym );
-
- for ( s = symbols ; s ; s = s->next ) {
- if ( hash == s->hash && !strcmp( sym, s->name ) ) {
- CodeError( "Multiple definitions for %s\n", sym );
- return;
- }
- }
-
- s = malloc( sizeof( *s ) );
- s->name = copystring( sym );
- s->hash = hash;
- s->value = value;
- s->segment = currentSegment;
-
- lastSymbol = s; /* for the move-to-lit-segment byteswap hack */
-
- // insert it in order
- if ( !symbols || s->value < symbols->value ) {
- s->next = symbols;
- symbols = s;
- return;
- }
-
- for ( after = symbols ; after->next && after->next->value < value ; after = after->next ) {
- }
- s->next = after->next;
- after->next = s;
-}
-
-
-/*
-============
-LookupSymbol
-
-Symbols can only be evaluated on pass 1
-============
-*/
-int LookupSymbol( char *sym ) {
- symbol_t *s;
- char expanded[MAX_LINE_LENGTH];
- int hash;
-
- if ( passNumber == 0 ) {
- return 0;
- }
-
- // add the file prefix to local symbols to guarantee unique
- if ( sym[0] == '$' ) {
- sprintf( expanded, "%s_%i", sym, currentFileIndex );
- sym = expanded;
- }
-
- hash = HashString( sym );
- for ( s = symbols ; s ; s = s->next ) {
- if ( hash == s->hash && !strcmp( sym, s->name ) ) {
- return s->segment->segmentBase + s->value;
- }
- }
-
- CodeError( "ERROR: symbol %s undefined\n", sym );
- passNumber = 0;
- DefineSymbol( sym, 0 ); // so more errors aren't printed
- passNumber = 1;
- return 0;
-}
-
-
-/*
-==============
-ExtractLine
-
-Extracts the next line from the given text block.
-If a full line isn't parsed, returns NULL
-Otherwise returns the updated parse pointer
-===============
-*/
-char *ExtractLine( char *data ) {
- int i;
-
- currentFileLine++;
- lineParseOffset = 0;
- token[0] = 0;
-
- if ( data[0] == 0 ) {
- lineBuffer[0] = 0;
- return NULL;
- }
-
- for ( i = 0 ; i < MAX_LINE_LENGTH ; i++ ) {
- if ( data[i] == 0 || data[i] == '\n' ) {
- break;
- }
- }
- if ( i == MAX_LINE_LENGTH ) {
- CodeError( "MAX_LINE_LENGTH" );
- return data;
- }
- memcpy( lineBuffer, data, i );
- lineBuffer[i] = 0;
- data += i;
- if ( data[0] == '\n' ) {
- data++;
- }
- return data;
-}
-
-
-/*
-==============
-Parse
-
-Parse a token out of linebuffer
-==============
-*/
-qboolean Parse( void ) {
- int c;
- int len;
-
- len = 0;
- token[0] = 0;
-
- // skip whitespace
- while ( lineBuffer[ lineParseOffset ] <= ' ' ) {
- if ( lineBuffer[ lineParseOffset ] == 0 ) {
- return qfalse;
- }
- lineParseOffset++;
- }
-
- // skip ; comments
- c = lineBuffer[ lineParseOffset ];
- if ( c == ';' ) {
- return qfalse;
- }
-
-
- // parse a regular word
- do {
- token[len] = c;
- len++;
- lineParseOffset++;
- c = lineBuffer[ lineParseOffset ];
- } while (c>32);
-
- token[len] = 0;
- return qtrue;
-}
-
-
-/*
-==============
-ParseValue
-==============
-*/
-int ParseValue( void ) {
- Parse();
- return atoi( token );
-}
-
-
-/*
-==============
-ParseExpression
-==============
-*/
-int ParseExpression(void) {
- int i, j;
- char sym[MAX_LINE_LENGTH];
- int v;
-
- if ( token[0] == '-' ) {
- i = 1;
- } else {
- i = 0;
- }
-
- for ( ; i < MAX_LINE_LENGTH ; i++ ) {
- if ( token[i] == '+' || token[i] == '-' || token[i] == 0 ) {
- break;
- }
- }
-
- memcpy( sym, token, i );
- sym[i] = 0;
-
- if ( ( sym[0] >= '0' && sym[0] <= '9' ) || sym[0] == '-' ) {
- v = atoi( sym );
- } else {
- v = LookupSymbol( sym );
- }
-
- // parse add / subtract offsets
- while ( token[i] != 0 ) {
- for ( j = i + 1 ; j < MAX_LINE_LENGTH ; j++ ) {
- if ( token[j] == '+' || token[j] == '-' || token[j] == 0 ) {
- break;
- }
- }
-
- memcpy( sym, token+i+1, j-i-1 );
- sym[j-i-1] = 0;
-
- if ( token[i] == '+' ) {
- v += atoi( sym );
- }
- if ( token[i] == '-' ) {
- v -= atoi( sym );
- }
- i = j;
- }
-
- return v;
-}
-
-
-/*
-==============
-HackToSegment
-
-BIG HACK: I want to put all 32 bit values in the data
-segment so they can be byte swapped, and all char data in the lit
-segment, but switch jump tables are emited in the lit segment and
-initialized strng variables are put in the data segment.
-
-I can change segments here, but I also need to fixup the
-label that was just defined
-
-Note that the lit segment is read-write in the VM, so strings
-aren't read only as in some architectures.
-==============
-*/
-void HackToSegment( segmentName_t seg ) {
- if ( currentSegment == &segment[seg] ) {
- return;
- }
-
- currentSegment = &segment[seg];
- if ( passNumber == 0 ) {
- lastSymbol->segment = currentSegment;
- lastSymbol->value = currentSegment->imageUsed;
- }
-}
-
-/*
-==============
-AssembleLine
-
-==============
-*/
-void AssembleLine( void ) {
- int v, v2;
- int i;
- int hash;
-
- Parse();
- if ( !token[0] ) {
- return;
- }
-
- hash = HashString( token );
-
- for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) {
- if ( hash == opcodesHash[i] && !strcmp( token, sourceOps[i].name ) ) {
- int opcode;
- int expression;
-
- if ( sourceOps[i].opcode == OP_UNDEF ) {
- CodeError( "Undefined opcode: %s\n", token );
- }
- if ( sourceOps[i].opcode == OP_IGNORE ) {
- return; // we ignore most conversions
- }
-
- // sign extensions need to check next parm
- opcode = sourceOps[i].opcode;
- if ( opcode == OP_SEX8 ) {
- Parse();
- if ( token[0] == '1' ) {
- opcode = OP_SEX8;
- } else if ( token[0] == '2' ) {
- opcode = OP_SEX16;
- } else {
- CodeError( "Bad sign extension: %s\n", token );
- return;
- }
- }
-
- // check for expression
- Parse();
- if ( token[0] && sourceOps[i].opcode != OP_CVIF
- && sourceOps[i].opcode != OP_CVFI ) {
- expression = ParseExpression();
-
- // code like this can generate non-dword block copies:
- // auto char buf[2] = " ";
- // we are just going to round up. This might conceivably
- // be incorrect if other initialized chars follow.
- if ( opcode == OP_BLOCK_COPY ) {
- expression = ( expression + 3 ) & ~3;
- }
-
- EmitByte( &segment[CODESEG], opcode );
- EmitInt( &segment[CODESEG], expression );
- } else {
- EmitByte( &segment[CODESEG], opcode );
- }
-
- instructionCount++;
- return;
- }
- }
-
- // call instructions reset currentArgOffset
- if ( !strncmp( token, "CALL", 4 ) ) {
- EmitByte( &segment[CODESEG], OP_CALL );
- instructionCount++;
- currentArgOffset = 0;
- return;
- }
-
- // arg is converted to a reversed store
- if ( !strncmp( token, "ARG", 3 ) ) {
- EmitByte( &segment[CODESEG], OP_ARG );
- instructionCount++;
- if ( 8 + currentArgOffset >= 256 ) {
- CodeError( "currentArgOffset >= 256" );
- return;
- }
- EmitByte( &segment[CODESEG], 8 + currentArgOffset );
- currentArgOffset += 4;
- return;
- }
-
- // ret just leaves something on the op stack
- if ( !strncmp( token, "RET", 3 ) ) {
- EmitByte( &segment[CODESEG], OP_LEAVE );
- instructionCount++;
- EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs );
- return;
- }
-
- // pop is needed to discard the return value of
- // a function
- if ( !strncmp( token, "pop", 3 ) ) {
- EmitByte( &segment[CODESEG], OP_POP );
- instructionCount++;
- return;
- }
-
- // address of a parameter is converted to OP_LOCAL
- if ( !strncmp( token, "ADDRF", 5 ) ) {
- instructionCount++;
- Parse();
- v = ParseExpression();
- v = 16 + currentArgs + currentLocals + v;
- EmitByte( &segment[CODESEG], OP_LOCAL );
- EmitInt( &segment[CODESEG], v );
- return;
- }
-
- // address of a local is converted to OP_LOCAL
- if ( !strncmp( token, "ADDRL", 5 ) ) {
- instructionCount++;
- Parse();
- v = ParseExpression();
- v = 8 + currentArgs + v;
- EmitByte( &segment[CODESEG], OP_LOCAL );
- EmitInt( &segment[CODESEG], v );
- return;
- }
-
- if ( !strcmp( token, "proc" ) ) {
- char name[1024];
-
- Parse(); // function name
- strcpy( name, token );
-
- DefineSymbol( token, instructionCount ); // segment[CODESEG].imageUsed );
-
- currentLocals = ParseValue(); // locals
- currentLocals = ( currentLocals + 3 ) & ~3;
- currentArgs = ParseValue(); // arg marshalling
- currentArgs = ( currentArgs + 3 ) & ~3;
-
- if ( 8 + currentLocals + currentArgs >= 32767 ) {
- CodeError( "Locals > 32k in %s\n", name );
- }
-
- instructionCount++;
- EmitByte( &segment[CODESEG], OP_ENTER );
- EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs );
- return;
- }
- if ( !strcmp( token, "endproc" ) ) {
- Parse(); // skip the function name
- v = ParseValue(); // locals
- v2 = ParseValue(); // arg marshalling
-
- // all functions must leave something on the opstack
- instructionCount++;
- EmitByte( &segment[CODESEG], OP_PUSH );
-
- instructionCount++;
- EmitByte( &segment[CODESEG], OP_LEAVE );
- EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs );
-
- return;
- }
-
-
- if ( !strcmp( token, "address" ) ) {
- Parse();
- v = ParseExpression();
-
- HackToSegment( DATASEG );
- EmitInt( currentSegment, v );
- return;
- }
- if ( !strcmp( token, "export" ) ) {
- return;
- }
- if ( !strcmp( token, "import" ) ) {
- return;
- }
- if ( !strcmp( token, "code" ) ) {
- currentSegment = &segment[CODESEG];
- return;
- }
- if ( !strcmp( token, "bss" ) ) {
- currentSegment = &segment[BSSSEG];
- return;
- }
- if ( !strcmp( token, "data" ) ) {
- currentSegment = &segment[DATASEG];
- return;
- }
- if ( !strcmp( token, "lit" ) ) {
- currentSegment = &segment[LITSEG];
- return;
- }
- if ( !strcmp( token, "line" ) ) {
- return;
- }
- if ( !strcmp( token, "file" ) ) {
- return;
- }
-
- if ( !strcmp( token, "equ" ) ) {
- char name[1024];
-
- Parse();
- strcpy( name, token );
- Parse();
- DefineSymbol( name, atoi(token) );
- return;
- }
-
- if ( !strcmp( token, "align" ) ) {
- v = ParseValue();
- currentSegment->imageUsed = (currentSegment->imageUsed + v - 1 ) & ~( v - 1 );
- return;
- }
-
- if ( !strcmp( token, "skip" ) ) {
- v = ParseValue();
- currentSegment->imageUsed += v;
- return;
- }
-
- if ( !strcmp( token, "byte" ) ) {
- v = ParseValue();
- v2 = ParseValue();
-
- if ( v == 1 ) {
- HackToSegment( LITSEG );
- } else if ( v == 4 ) {
- HackToSegment( DATASEG );
- } else if ( v == 2 ) {
- CodeError( "16 bit initialized data not supported" );
- }
-
- // emit little endien
- for ( i = 0 ; i < v ; i++ ) {
- EmitByte( currentSegment, v2 );
- v2 >>= 8;
- }
- return;
- }
-
- // code labels are emited as instruction counts, not byte offsets,
- // because the physical size of the code will change with
- // different run time compilers and we want to minimize the
- // size of the required translation table
- if ( !strncmp( token, "LABEL", 5 ) ) {
- Parse();
- if ( currentSegment == &segment[CODESEG] ) {
- DefineSymbol( token, instructionCount );
- } else {
- DefineSymbol( token, currentSegment->imageUsed );
- }
- return;
- }
-
- CodeError( "Unknown token: %s\n", token );
-}
-
-/*
-==============
-InitTables
-==============
-*/
-void InitTables( void ) {
- int i;
-
- for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) {
- opcodesHash[i] = HashString( sourceOps[i].name );
- }
-}
-
-
-/*
-==============
-WriteMapFile
-==============
-*/
-void WriteMapFile( void ) {
- FILE *f;
- symbol_t *s;
- char imageName[MAX_OS_PATH];
- int seg;
-
- strcpy( imageName, outputFilename );
- StripExtension( imageName );
- strcat( imageName, ".map" );
-
- printf( "Writing %s...\n", imageName );
- f = SafeOpenWrite( imageName );
- for ( seg = CODESEG ; seg <= BSSSEG ; seg++ ) {
- for ( s = symbols ; s ; s = s->next ) {
- if ( s->name[0] == '$' ) {
- continue; // skip locals
- }
- if ( &segment[seg] != s->segment ) {
- continue;
- }
- fprintf( f, "%i %8x %s\n", seg, s->value, s->name );
- }
- }
- fclose( f );
-}
-
-/*
-===============
-WriteVmFile
-===============
-*/
-void WriteVmFile( void ) {
- char imageName[MAX_OS_PATH];
- vmHeader_t header;
- FILE *f;
-
- printf( "%i total errors\n", errorCount );
- strcpy( imageName, outputFilename );
- StripExtension( imageName );
- strcat( imageName, ".qvm" );
-
- remove( imageName );
-
- printf( "code segment: %7i\n", segment[CODESEG].imageUsed );
- printf( "data segment: %7i\n", segment[DATASEG].imageUsed );
- printf( "lit segment: %7i\n", segment[LITSEG].imageUsed );
- printf( "bss segment: %7i\n", segment[BSSSEG].imageUsed );
- printf( "instruction count: %i\n", instructionCount );
- if ( errorCount != 0 ) {
- printf( "Not writing a file due to errors\n" );
- return;
- }
-
- header.vmMagic = VM_MAGIC;
- header.instructionCount = instructionCount;
- header.codeOffset = sizeof( header );
- header.codeLength = segment[CODESEG].imageUsed;
- header.dataOffset = header.codeOffset + segment[CODESEG].imageUsed;
- header.dataLength = segment[DATASEG].imageUsed;
- header.litLength = segment[LITSEG].imageUsed;
- header.bssLength = segment[BSSSEG].imageUsed;
-
- printf( "Writing to %s\n", imageName );
-
- CreatePath( imageName );
- f = SafeOpenWrite( imageName );
- SafeWrite( f, &header, sizeof( header ) );
- SafeWrite( f, &segment[CODESEG].image, segment[CODESEG].imageUsed );
- SafeWrite( f, &segment[DATASEG].image, segment[DATASEG].imageUsed );
- SafeWrite( f, &segment[LITSEG].image, segment[LITSEG].imageUsed );
- fclose( f );
-}
-
-/*
-===============
-Assemble
-===============
-*/
-void Assemble( void ) {
- int i;
- char filename[MAX_OS_PATH];
- char *ptr;
-
- printf( "outputFilename: %s\n", outputFilename );
-
- for ( i = 0 ; i < numAsmFiles ; i++ ) {
- strcpy( filename, asmFileNames[ i ] );
- DefaultExtension( filename, ".asm" );
- LoadFile( filename, (void **)&asmFiles[i] );
- }
-
- // assemble
- for ( passNumber = 0 ; passNumber < 2 ; passNumber++ ) {
- segment[LITSEG].segmentBase = segment[DATASEG].imageUsed;
- segment[BSSSEG].segmentBase = segment[LITSEG].segmentBase + segment[LITSEG].imageUsed;
- for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) {
- segment[i].imageUsed = 0;
- }
- segment[DATASEG].imageUsed = 4; // skip the 0 byte, so NULL pointers are fixed up properly
- instructionCount = 0;
-
- for ( i = 0 ; i < numAsmFiles ; i++ ) {
- currentFileIndex = i;
- currentFileName = asmFileNames[ i ];
- currentFileLine = 0;
- printf("pass %i: %s\n", passNumber, currentFileName );
- ptr = asmFiles[i];
- while ( ptr ) {
- ptr = ExtractLine( ptr );
- AssembleLine();
- }
- }
-
- // align all segment
- for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) {
- segment[i].imageUsed = (segment[i].imageUsed + 3) & ~3;
- }
- }
-
- // reserve the stack in bss
- DefineSymbol( "_stackStart", segment[BSSSEG].imageUsed );
- segment[BSSSEG].imageUsed += stackSize;
- DefineSymbol( "_stackEnd", segment[BSSSEG].imageUsed );
-
- // write the image
- WriteVmFile();
-
- // write the map file even if there were errors
- WriteMapFile();
-}
-
-
-/*
-=============
-ParseOptionFile
-
-=============
-*/
-void ParseOptionFile( const char *filename ) {
- char expanded[MAX_OS_PATH];
- char *text, *text_p;
-
- strcpy( expanded, filename );
- DefaultExtension( expanded, ".q3asm" );
- LoadFile( expanded, (void **)&text );
- if ( !text ) {
- return;
- }
-
- text_p = text;
-
- while( ( text_p = COM_Parse( text_p ) ) != 0 ) {
- if ( !strcmp( com_token, "-o" ) ) {
- // allow output override in option file
- text_p = COM_Parse( text_p );
- if ( text_p ) {
- strcpy( outputFilename, com_token );
- }
- continue;
- }
-
- asmFileNames[ numAsmFiles ] = copystring( com_token );
- numAsmFiles++;
- }
-}
-
-/*
-==============
-main
-==============
-*/
-int main( int argc, char **argv ) {
- int i;
- double start, end;
-
-// _chdir( "/quake3/jccode/cgame/lccout" ); // hack for vc profiler
-
- if ( argc < 2 ) {
- Error( "usage: q3asm [-o output] <files> or q3asm -f <listfile>\n" );
- }
-
- start = I_FloatTime ();
- InitTables();
-
- // default filename is "q3asm"
- strcpy( outputFilename, "q3asm" );
- numAsmFiles = 0;
-
- for ( i = 1 ; i < argc ; i++ ) {
- if ( argv[i][0] != '-' ) {
- break;
- }
- if ( !strcmp( argv[i], "-o" ) ) {
- if ( i == argc - 1 ) {
- Error( "-o must preceed a filename" );
- }
- strcpy( outputFilename, argv[ i+1 ] );
- i++;
- continue;
- }
-
- if ( !strcmp( argv[i], "-f" ) ) {
- if ( i == argc - 1 ) {
- Error( "-f must preceed a filename" );
- }
- ParseOptionFile( argv[ i+1 ] );
- i++;
- continue;
- }
- Error( "Unknown option: %s", argv[i] );
- }
-
- // the rest of the command line args are asm files
- for ( ; i < argc ; i++ ) {
- asmFileNames[ numAsmFiles ] = copystring( argv[ i ] );
- numAsmFiles++;
- }
-
- Assemble();
-
- end = I_FloatTime ();
- printf ("%5.0f seconds elapsed\n", end-start);
-
- return 0;
-}
-
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "qfiles.h"
+
+/* MSVC-ism fix. */
+#define atoi(s) strtoul(s,NULL,10)
+
+char outputFilename[MAX_OS_PATH];
+
+// the zero page size is just used for detecting run time faults
+#define ZERO_PAGE_SIZE 0 // 256
+
+typedef enum {
+ OP_UNDEF,
+
+ OP_IGNORE,
+
+ OP_BREAK,
+
+ OP_ENTER,
+ OP_LEAVE,
+ OP_CALL,
+ OP_PUSH,
+ OP_POP,
+
+ OP_CONST,
+ OP_LOCAL,
+
+ OP_JUMP,
+
+ //-------------------
+
+ OP_EQ,
+ OP_NE,
+
+ OP_LTI,
+ OP_LEI,
+ OP_GTI,
+ OP_GEI,
+
+ OP_LTU,
+ OP_LEU,
+ OP_GTU,
+ OP_GEU,
+
+ OP_EQF,
+ OP_NEF,
+
+ OP_LTF,
+ OP_LEF,
+ OP_GTF,
+ OP_GEF,
+
+ //-------------------
+
+ OP_LOAD1,
+ OP_LOAD2,
+ OP_LOAD4,
+ OP_STORE1,
+ OP_STORE2,
+ OP_STORE4, // *(stack[top-1]) = stack[yop
+ OP_ARG,
+ OP_BLOCK_COPY,
+
+ //-------------------
+
+ OP_SEX8,
+ OP_SEX16,
+
+ OP_NEGI,
+ OP_ADD,
+ OP_SUB,
+ OP_DIVI,
+ OP_DIVU,
+ OP_MODI,
+ OP_MODU,
+ OP_MULI,
+ OP_MULU,
+
+ OP_BAND,
+ OP_BOR,
+ OP_BXOR,
+ OP_BCOM,
+
+ OP_LSH,
+ OP_RSHI,
+ OP_RSHU,
+
+ OP_NEGF,
+ OP_ADDF,
+ OP_SUBF,
+ OP_DIVF,
+ OP_MULF,
+
+ OP_CVIF,
+ OP_CVFI
+} opcode_t;
+
+typedef struct {
+ int imageBytes; // after decompression
+ int entryPoint;
+ int stackBase;
+ int stackSize;
+} executableHeader_t;
+
+typedef enum {
+ CODESEG,
+ DATASEG, // initialized 32 bit data, will be byte swapped
+ LITSEG, // strings
+ BSSSEG, // 0 filled
+ NUM_SEGMENTS
+} segmentName_t;
+
+#define MAX_IMAGE 0x400000
+
+typedef struct {
+ byte image[MAX_IMAGE];
+ int imageUsed;
+ int segmentBase; // only valid on second pass
+} segment_t;
+
+typedef struct symbol_s {
+ struct symbol_s *next;
+ int hash;
+ segment_t *segment;
+ char *name;
+ int value;
+} symbol_t;
+
+
+segment_t segment[NUM_SEGMENTS];
+segment_t *currentSegment;
+
+int passNumber;
+
+int numSymbols;
+int errorCount;
+
+symbol_t *symbols;
+symbol_t *lastSymbol;
+
+
+#define MAX_ASM_FILES 256
+int numAsmFiles;
+char *asmFiles[MAX_ASM_FILES];
+char *asmFileNames[MAX_ASM_FILES];
+
+int currentFileIndex;
+char *currentFileName;
+int currentFileLine;
+
+//int stackSize = 16384;
+int stackSize = 0x10000;
+
+// we need to convert arg and ret instructions to
+// stores to the local stack frame, so we need to track the
+// characteristics of the current functions stack frame
+int currentLocals; // bytes of locals needed by this function
+int currentArgs; // bytes of largest argument list called from this function
+int currentArgOffset; // byte offset in currentArgs to store next arg, reset each call
+
+#define MAX_LINE_LENGTH 1024
+char lineBuffer[MAX_LINE_LENGTH];
+int lineParseOffset;
+char token[MAX_LINE_LENGTH];
+
+int instructionCount;
+
+typedef struct {
+ char *name;
+ int opcode;
+} sourceOps_t;
+
+sourceOps_t sourceOps[] = {
+#include "opstrings.h"
+};
+
+#define NUM_SOURCE_OPS ( sizeof( sourceOps ) / sizeof( sourceOps[0] ) )
+
+int opcodesHash[ NUM_SOURCE_OPS ];
+
+
+/*
+=============
+HashString
+=============
+*/
+int HashString( char *s ) {
+ int v = 0;
+
+ while ( *s ) {
+ v += *s;
+ s++;
+ }
+ return v;
+}
+
+
+/*
+============
+CodeError
+============
+*/
+void CodeError( char *fmt, ... ) {
+ va_list argptr;
+
+ errorCount++;
+
+ printf( "%s:%i ", currentFileName, currentFileLine );
+
+ va_start( argptr,fmt );
+ vprintf( fmt,argptr );
+ va_end( argptr );
+}
+
+/*
+============
+EmitByte
+============
+*/
+void EmitByte( segment_t *seg, int v ) {
+ if ( seg->imageUsed >= MAX_IMAGE ) {
+ Error( "MAX_IMAGE" );
+ }
+ seg->image[ seg->imageUsed ] = v;
+ seg->imageUsed++;
+}
+
+/*
+============
+EmitInt
+============
+*/
+void EmitInt( segment_t *seg, int v ) {
+ if ( seg->imageUsed >= MAX_IMAGE - 4) {
+ Error( "MAX_IMAGE" );
+ }
+ seg->image[ seg->imageUsed ] = v & 255;
+ seg->image[ seg->imageUsed + 1 ] = ( v >> 8 ) & 255;
+ seg->image[ seg->imageUsed + 2 ] = ( v >> 16 ) & 255;
+ seg->image[ seg->imageUsed + 3 ] = ( v >> 24 ) & 255;
+ seg->imageUsed += 4;
+}
+
+/*
+============
+DefineSymbol
+
+Symbols can only be defined on pass 0
+============
+*/
+void DefineSymbol( char *sym, int value ) {
+ symbol_t *s, *after;
+ char expanded[MAX_LINE_LENGTH];
+ int hash;
+
+ if ( passNumber == 1 ) {
+ return;
+ }
+
+ // TTimo
+ // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=381
+ // as a security, bail out if vmMain entry point is not first
+ if (!Q_stricmp(sym, "vmMain"))
+ if (value)
+ Error( "vmMain must be the first symbol in the qvm (got offset %d)\n", value );
+
+ // add the file prefix to local symbols to guarantee unique
+ if ( sym[0] == '$' ) {
+ sprintf( expanded, "%s_%i", sym, currentFileIndex );
+ sym = expanded;
+ }
+
+ hash = HashString( sym );
+
+ for ( s = symbols ; s ; s = s->next ) {
+ if ( hash == s->hash && !strcmp( sym, s->name ) ) {
+ CodeError( "Multiple definitions for %s\n", sym );
+ return;
+ }
+ }
+
+ s = malloc( sizeof( *s ) );
+ s->name = copystring( sym );
+ s->hash = hash;
+ s->value = value;
+ s->segment = currentSegment;
+
+ lastSymbol = s; /* for the move-to-lit-segment byteswap hack */
+
+ // insert it in order
+ if ( !symbols || s->value < symbols->value ) {
+ s->next = symbols;
+ symbols = s;
+ return;
+ }
+
+ for ( after = symbols ; after->next && after->next->value < value ; after = after->next ) {
+ }
+ s->next = after->next;
+ after->next = s;
+}
+
+
+/*
+============
+LookupSymbol
+
+Symbols can only be evaluated on pass 1
+============
+*/
+int LookupSymbol( char *sym ) {
+ symbol_t *s;
+ char expanded[MAX_LINE_LENGTH];
+ int hash;
+
+ if ( passNumber == 0 ) {
+ return 0;
+ }
+
+ // add the file prefix to local symbols to guarantee unique
+ if ( sym[0] == '$' ) {
+ sprintf( expanded, "%s_%i", sym, currentFileIndex );
+ sym = expanded;
+ }
+
+ hash = HashString( sym );
+ for ( s = symbols ; s ; s = s->next ) {
+ if ( hash == s->hash && !strcmp( sym, s->name ) ) {
+ return s->segment->segmentBase + s->value;
+ }
+ }
+
+ CodeError( "ERROR: symbol %s undefined\n", sym );
+ passNumber = 0;
+ DefineSymbol( sym, 0 ); // so more errors aren't printed
+ passNumber = 1;
+ return 0;
+}
+
+
+/*
+==============
+ExtractLine
+
+Extracts the next line from the given text block.
+If a full line isn't parsed, returns NULL
+Otherwise returns the updated parse pointer
+===============
+*/
+char *ExtractLine( char *data ) {
+ int i;
+
+ currentFileLine++;
+ lineParseOffset = 0;
+ token[0] = 0;
+
+ if ( data[0] == 0 ) {
+ lineBuffer[0] = 0;
+ return NULL;
+ }
+
+ for ( i = 0 ; i < MAX_LINE_LENGTH ; i++ ) {
+ if ( data[i] == 0 || data[i] == '\n' ) {
+ break;
+ }
+ }
+ if ( i == MAX_LINE_LENGTH ) {
+ CodeError( "MAX_LINE_LENGTH" );
+ return data;
+ }
+ memcpy( lineBuffer, data, i );
+ lineBuffer[i] = 0;
+ data += i;
+ if ( data[0] == '\n' ) {
+ data++;
+ }
+ return data;
+}
+
+
+/*
+==============
+Parse
+
+Parse a token out of linebuffer
+==============
+*/
+qboolean Parse( void ) {
+ int c;
+ int len;
+
+ len = 0;
+ token[0] = 0;
+
+ // skip whitespace
+ while ( lineBuffer[ lineParseOffset ] <= ' ' ) {
+ if ( lineBuffer[ lineParseOffset ] == 0 ) {
+ return qfalse;
+ }
+ lineParseOffset++;
+ }
+
+ // skip ; comments
+ c = lineBuffer[ lineParseOffset ];
+ if ( c == ';' ) {
+ return qfalse;
+ }
+
+
+ // parse a regular word
+ do {
+ token[len] = c;
+ len++;
+ lineParseOffset++;
+ c = lineBuffer[ lineParseOffset ];
+ } while (c>32);
+
+ token[len] = 0;
+ return qtrue;
+}
+
+
+/*
+==============
+ParseValue
+==============
+*/
+int ParseValue( void ) {
+ Parse();
+ return atoi( token );
+}
+
+
+/*
+==============
+ParseExpression
+==============
+*/
+int ParseExpression(void) {
+ int i, j;
+ char sym[MAX_LINE_LENGTH];
+ int v;
+
+ if ( token[0] == '-' ) {
+ i = 1;
+ } else {
+ i = 0;
+ }
+
+ for ( ; i < MAX_LINE_LENGTH ; i++ ) {
+ if ( token[i] == '+' || token[i] == '-' || token[i] == 0 ) {
+ break;
+ }
+ }
+
+ memcpy( sym, token, i );
+ sym[i] = 0;
+
+ if ( ( sym[0] >= '0' && sym[0] <= '9' ) || sym[0] == '-' ) {
+ v = atoi( sym );
+ } else {
+ v = LookupSymbol( sym );
+ }
+
+ // parse add / subtract offsets
+ while ( token[i] != 0 ) {
+ for ( j = i + 1 ; j < MAX_LINE_LENGTH ; j++ ) {
+ if ( token[j] == '+' || token[j] == '-' || token[j] == 0 ) {
+ break;
+ }
+ }
+
+ memcpy( sym, token+i+1, j-i-1 );
+ sym[j-i-1] = 0;
+
+ if ( token[i] == '+' ) {
+ v += atoi( sym );
+ }
+ if ( token[i] == '-' ) {
+ v -= atoi( sym );
+ }
+ i = j;
+ }
+
+ return v;
+}
+
+
+/*
+==============
+HackToSegment
+
+BIG HACK: I want to put all 32 bit values in the data
+segment so they can be byte swapped, and all char data in the lit
+segment, but switch jump tables are emited in the lit segment and
+initialized strng variables are put in the data segment.
+
+I can change segments here, but I also need to fixup the
+label that was just defined
+
+Note that the lit segment is read-write in the VM, so strings
+aren't read only as in some architectures.
+==============
+*/
+void HackToSegment( segmentName_t seg ) {
+ if ( currentSegment == &segment[seg] ) {
+ return;
+ }
+
+ currentSegment = &segment[seg];
+ if ( passNumber == 0 ) {
+ lastSymbol->segment = currentSegment;
+ lastSymbol->value = currentSegment->imageUsed;
+ }
+}
+
+/*
+==============
+AssembleLine
+
+==============
+*/
+void AssembleLine( void ) {
+ int v, v2;
+ int i;
+ int hash;
+
+ Parse();
+ if ( !token[0] ) {
+ return;
+ }
+
+ hash = HashString( token );
+
+ for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) {
+ if ( hash == opcodesHash[i] && !strcmp( token, sourceOps[i].name ) ) {
+ int opcode;
+ int expression;
+
+ if ( sourceOps[i].opcode == OP_UNDEF ) {
+ CodeError( "Undefined opcode: %s\n", token );
+ }
+ if ( sourceOps[i].opcode == OP_IGNORE ) {
+ return; // we ignore most conversions
+ }
+
+ // sign extensions need to check next parm
+ opcode = sourceOps[i].opcode;
+ if ( opcode == OP_SEX8 ) {
+ Parse();
+ if ( token[0] == '1' ) {
+ opcode = OP_SEX8;
+ } else if ( token[0] == '2' ) {
+ opcode = OP_SEX16;
+ } else {
+ CodeError( "Bad sign extension: %s\n", token );
+ return;
+ }
+ }
+
+ // check for expression
+ Parse();
+ if ( token[0] && sourceOps[i].opcode != OP_CVIF
+ && sourceOps[i].opcode != OP_CVFI ) {
+ expression = ParseExpression();
+
+ // code like this can generate non-dword block copies:
+ // auto char buf[2] = " ";
+ // we are just going to round up. This might conceivably
+ // be incorrect if other initialized chars follow.
+ if ( opcode == OP_BLOCK_COPY ) {
+ expression = ( expression + 3 ) & ~3;
+ }
+
+ EmitByte( &segment[CODESEG], opcode );
+ EmitInt( &segment[CODESEG], expression );
+ } else {
+ EmitByte( &segment[CODESEG], opcode );
+ }
+
+ instructionCount++;
+ return;
+ }
+ }
+
+ // call instructions reset currentArgOffset
+ if ( !strncmp( token, "CALL", 4 ) ) {
+ EmitByte( &segment[CODESEG], OP_CALL );
+ instructionCount++;
+ currentArgOffset = 0;
+ return;
+ }
+
+ // arg is converted to a reversed store
+ if ( !strncmp( token, "ARG", 3 ) ) {
+ EmitByte( &segment[CODESEG], OP_ARG );
+ instructionCount++;
+ if ( 8 + currentArgOffset >= 256 ) {
+ CodeError( "currentArgOffset >= 256" );
+ return;
+ }
+ EmitByte( &segment[CODESEG], 8 + currentArgOffset );
+ currentArgOffset += 4;
+ return;
+ }
+
+ // ret just leaves something on the op stack
+ if ( !strncmp( token, "RET", 3 ) ) {
+ EmitByte( &segment[CODESEG], OP_LEAVE );
+ instructionCount++;
+ EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs );
+ return;
+ }
+
+ // pop is needed to discard the return value of
+ // a function
+ if ( !strncmp( token, "pop", 3 ) ) {
+ EmitByte( &segment[CODESEG], OP_POP );
+ instructionCount++;
+ return;
+ }
+
+ // address of a parameter is converted to OP_LOCAL
+ if ( !strncmp( token, "ADDRF", 5 ) ) {
+ instructionCount++;
+ Parse();
+ v = ParseExpression();
+ v = 16 + currentArgs + currentLocals + v;
+ EmitByte( &segment[CODESEG], OP_LOCAL );
+ EmitInt( &segment[CODESEG], v );
+ return;
+ }
+
+ // address of a local is converted to OP_LOCAL
+ if ( !strncmp( token, "ADDRL", 5 ) ) {
+ instructionCount++;
+ Parse();
+ v = ParseExpression();
+ v = 8 + currentArgs + v;
+ EmitByte( &segment[CODESEG], OP_LOCAL );
+ EmitInt( &segment[CODESEG], v );
+ return;
+ }
+
+ if ( !strcmp( token, "proc" ) ) {
+ char name[1024];
+
+ Parse(); // function name
+ strcpy( name, token );
+
+ DefineSymbol( token, instructionCount ); // segment[CODESEG].imageUsed );
+
+ currentLocals = ParseValue(); // locals
+ currentLocals = ( currentLocals + 3 ) & ~3;
+ currentArgs = ParseValue(); // arg marshalling
+ currentArgs = ( currentArgs + 3 ) & ~3;
+
+ if ( 8 + currentLocals + currentArgs >= 32767 ) {
+ CodeError( "Locals > 32k in %s\n", name );
+ }
+
+ instructionCount++;
+ EmitByte( &segment[CODESEG], OP_ENTER );
+ EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs );
+ return;
+ }
+ if ( !strcmp( token, "endproc" ) ) {
+ Parse(); // skip the function name
+ v = ParseValue(); // locals
+ v2 = ParseValue(); // arg marshalling
+
+ // all functions must leave something on the opstack
+ instructionCount++;
+ EmitByte( &segment[CODESEG], OP_PUSH );
+
+ instructionCount++;
+ EmitByte( &segment[CODESEG], OP_LEAVE );
+ EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs );
+
+ return;
+ }
+
+
+ if ( !strcmp( token, "address" ) ) {
+ Parse();
+ v = ParseExpression();
+
+ HackToSegment( DATASEG );
+ EmitInt( currentSegment, v );
+ return;
+ }
+ if ( !strcmp( token, "export" ) ) {
+ return;
+ }
+ if ( !strcmp( token, "import" ) ) {
+ return;
+ }
+ if ( !strcmp( token, "code" ) ) {
+ currentSegment = &segment[CODESEG];
+ return;
+ }
+ if ( !strcmp( token, "bss" ) ) {
+ currentSegment = &segment[BSSSEG];
+ return;
+ }
+ if ( !strcmp( token, "data" ) ) {
+ currentSegment = &segment[DATASEG];
+ return;
+ }
+ if ( !strcmp( token, "lit" ) ) {
+ currentSegment = &segment[LITSEG];
+ return;
+ }
+ if ( !strcmp( token, "line" ) ) {
+ return;
+ }
+ if ( !strcmp( token, "file" ) ) {
+ return;
+ }
+
+ if ( !strcmp( token, "equ" ) ) {
+ char name[1024];
+
+ Parse();
+ strcpy( name, token );
+ Parse();
+ DefineSymbol( name, atoi(token) );
+ return;
+ }
+
+ if ( !strcmp( token, "align" ) ) {
+ v = ParseValue();
+ currentSegment->imageUsed = (currentSegment->imageUsed + v - 1 ) & ~( v - 1 );
+ return;
+ }
+
+ if ( !strcmp( token, "skip" ) ) {
+ v = ParseValue();
+ currentSegment->imageUsed += v;
+ return;
+ }
+
+ if ( !strcmp( token, "byte" ) ) {
+ v = ParseValue();
+ v2 = ParseValue();
+
+ if ( v == 1 ) {
+ HackToSegment( LITSEG );
+ } else if ( v == 4 ) {
+ HackToSegment( DATASEG );
+ } else if ( v == 2 ) {
+ CodeError( "16 bit initialized data not supported" );
+ }
+
+ // emit little endien
+ for ( i = 0 ; i < v ; i++ ) {
+ EmitByte( currentSegment, v2 );
+ v2 >>= 8;
+ }
+ return;
+ }
+
+ // code labels are emited as instruction counts, not byte offsets,
+ // because the physical size of the code will change with
+ // different run time compilers and we want to minimize the
+ // size of the required translation table
+ if ( !strncmp( token, "LABEL", 5 ) ) {
+ Parse();
+ if ( currentSegment == &segment[CODESEG] ) {
+ DefineSymbol( token, instructionCount );
+ } else {
+ DefineSymbol( token, currentSegment->imageUsed );
+ }
+ return;
+ }
+
+ CodeError( "Unknown token: %s\n", token );
+}
+
+/*
+==============
+InitTables
+==============
+*/
+void InitTables( void ) {
+ int i;
+
+ for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) {
+ opcodesHash[i] = HashString( sourceOps[i].name );
+ }
+}
+
+
+/*
+==============
+WriteMapFile
+==============
+*/
+void WriteMapFile( void ) {
+ FILE *f;
+ symbol_t *s;
+ char imageName[MAX_OS_PATH];
+ int seg;
+
+ strcpy( imageName, outputFilename );
+ StripExtension( imageName );
+ strcat( imageName, ".map" );
+
+ printf( "Writing %s...\n", imageName );
+ f = SafeOpenWrite( imageName );
+ for ( seg = CODESEG ; seg <= BSSSEG ; seg++ ) {
+ for ( s = symbols ; s ; s = s->next ) {
+ if ( s->name[0] == '$' ) {
+ continue; // skip locals
+ }
+ if ( &segment[seg] != s->segment ) {
+ continue;
+ }
+ fprintf( f, "%i %8x %s\n", seg, s->value, s->name );
+ }
+ }
+ fclose( f );
+}
+
+/*
+===============
+WriteVmFile
+===============
+*/
+void WriteVmFile( void ) {
+ char imageName[MAX_OS_PATH];
+ vmHeader_t header;
+ FILE *f;
+
+ printf( "%i total errors\n", errorCount );
+ strcpy( imageName, outputFilename );
+ StripExtension( imageName );
+ strcat( imageName, ".qvm" );
+
+ remove( imageName );
+
+ printf( "code segment: %7i\n", segment[CODESEG].imageUsed );
+ printf( "data segment: %7i\n", segment[DATASEG].imageUsed );
+ printf( "lit segment: %7i\n", segment[LITSEG].imageUsed );
+ printf( "bss segment: %7i\n", segment[BSSSEG].imageUsed );
+ printf( "instruction count: %i\n", instructionCount );
+ if ( errorCount != 0 ) {
+ printf( "Not writing a file due to errors\n" );
+ return;
+ }
+
+ header.vmMagic = VM_MAGIC;
+ header.instructionCount = instructionCount;
+ header.codeOffset = sizeof( header );
+ header.codeLength = segment[CODESEG].imageUsed;
+ header.dataOffset = header.codeOffset + segment[CODESEG].imageUsed;
+ header.dataLength = segment[DATASEG].imageUsed;
+ header.litLength = segment[LITSEG].imageUsed;
+ header.bssLength = segment[BSSSEG].imageUsed;
+
+ printf( "Writing to %s\n", imageName );
+
+ CreatePath( imageName );
+ f = SafeOpenWrite( imageName );
+ SafeWrite( f, &header, sizeof( header ) );
+ SafeWrite( f, &segment[CODESEG].image, segment[CODESEG].imageUsed );
+ SafeWrite( f, &segment[DATASEG].image, segment[DATASEG].imageUsed );
+ SafeWrite( f, &segment[LITSEG].image, segment[LITSEG].imageUsed );
+ fclose( f );
+}
+
+/*
+===============
+Assemble
+===============
+*/
+void Assemble( void ) {
+ int i;
+ char filename[MAX_OS_PATH];
+ char *ptr;
+
+ printf( "outputFilename: %s\n", outputFilename );
+
+ for ( i = 0 ; i < numAsmFiles ; i++ ) {
+ strcpy( filename, asmFileNames[ i ] );
+ DefaultExtension( filename, ".asm" );
+ LoadFile( filename, (void **)&asmFiles[i] );
+ }
+
+ // assemble
+ for ( passNumber = 0 ; passNumber < 2 ; passNumber++ ) {
+ segment[LITSEG].segmentBase = segment[DATASEG].imageUsed;
+ segment[BSSSEG].segmentBase = segment[LITSEG].segmentBase + segment[LITSEG].imageUsed;
+ for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) {
+ segment[i].imageUsed = 0;
+ }
+ segment[DATASEG].imageUsed = 4; // skip the 0 byte, so NULL pointers are fixed up properly
+ instructionCount = 0;
+
+ for ( i = 0 ; i < numAsmFiles ; i++ ) {
+ currentFileIndex = i;
+ currentFileName = asmFileNames[ i ];
+ currentFileLine = 0;
+ printf("pass %i: %s\n", passNumber, currentFileName );
+ ptr = asmFiles[i];
+ while ( ptr ) {
+ ptr = ExtractLine( ptr );
+ AssembleLine();
+ }
+ }
+
+ // align all segment
+ for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) {
+ segment[i].imageUsed = (segment[i].imageUsed + 3) & ~3;
+ }
+ }
+
+ // reserve the stack in bss
+ DefineSymbol( "_stackStart", segment[BSSSEG].imageUsed );
+ segment[BSSSEG].imageUsed += stackSize;
+ DefineSymbol( "_stackEnd", segment[BSSSEG].imageUsed );
+
+ // write the image
+ WriteVmFile();
+
+ // write the map file even if there were errors
+ WriteMapFile();
+}
+
+
+/*
+=============
+ParseOptionFile
+
+=============
+*/
+void ParseOptionFile( const char *filename ) {
+ char expanded[MAX_OS_PATH];
+ char *text, *text_p;
+
+ strcpy( expanded, filename );
+ DefaultExtension( expanded, ".q3asm" );
+ LoadFile( expanded, (void **)&text );
+ if ( !text ) {
+ return;
+ }
+
+ text_p = text;
+
+ while( ( text_p = COM_Parse( text_p ) ) != 0 ) {
+ if ( !strcmp( com_token, "-o" ) ) {
+ // allow output override in option file
+ text_p = COM_Parse( text_p );
+ if ( text_p ) {
+ strcpy( outputFilename, com_token );
+ }
+ continue;
+ }
+
+ asmFileNames[ numAsmFiles ] = copystring( com_token );
+ numAsmFiles++;
+ }
+}
+
+/*
+==============
+main
+==============
+*/
+int main( int argc, char **argv ) {
+ int i;
+ double start, end;
+
+// _chdir( "/quake3/jccode/cgame/lccout" ); // hack for vc profiler
+
+ if ( argc < 2 ) {
+ Error( "usage: q3asm [-o output] <files> or q3asm -f <listfile>\n" );
+ }
+
+ start = I_FloatTime ();
+ InitTables();
+
+ // default filename is "q3asm"
+ strcpy( outputFilename, "q3asm" );
+ numAsmFiles = 0;
+
+ for ( i = 1 ; i < argc ; i++ ) {
+ if ( argv[i][0] != '-' ) {
+ break;
+ }
+ if ( !strcmp( argv[i], "-o" ) ) {
+ if ( i == argc - 1 ) {
+ Error( "-o must preceed a filename" );
+ }
+ strcpy( outputFilename, argv[ i+1 ] );
+ i++;
+ continue;
+ }
+
+ if ( !strcmp( argv[i], "-f" ) ) {
+ if ( i == argc - 1 ) {
+ Error( "-f must preceed a filename" );
+ }
+ ParseOptionFile( argv[ i+1 ] );
+ i++;
+ continue;
+ }
+ Error( "Unknown option: %s", argv[i] );
+ }
+
+ // the rest of the command line args are asm files
+ for ( ; i < argc ; i++ ) {
+ asmFileNames[ numAsmFiles ] = copystring( argv[ i ] );
+ numAsmFiles++;
+ }
+
+ Assemble();
+
+ end = I_FloatTime ();
+ printf ("%5.0f seconds elapsed\n", end-start);
+
+ return 0;
+}
+
diff --git a/q3asm/q3asm.sln b/q3asm/q3asm.sln
index 5f44a09..48438df 100755
--- a/q3asm/q3asm.sln
+++ b/q3asm/q3asm.sln
@@ -1,28 +1,28 @@
-Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3asm", "q3asm.vcproj", "{E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Global
- GlobalSection(SourceCodeControl) = preSolution
- SccNumberOfProjects = 1
- SccProjectUniqueName0 = q3asm.vcproj
- SccProjectName0 = \u0022$/source/q3asm\u0022,\u0020YUCAAAAA
- SccLocalPath0 = .
- SccProvider0 = MSSCCI:Perforce\u0020SCM
- EndGlobalSection
- GlobalSection(SolutionConfiguration) = preSolution
- Debug = Debug
- Release = Release
- EndGlobalSection
- GlobalSection(ProjectConfiguration) = postSolution
- {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Debug.ActiveCfg = Debug|Win32
- {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Debug.Build.0 = Debug|Win32
- {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Release.ActiveCfg = Release|Win32
- {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Release.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- EndGlobalSection
- GlobalSection(ExtensibilityAddIns) = postSolution
- EndGlobalSection
-EndGlobal
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3asm", "q3asm.vcproj", "{E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SourceCodeControl) = preSolution
+ SccNumberOfProjects = 1
+ SccProjectUniqueName0 = q3asm.vcproj
+ SccProjectName0 = \u0022$/source/q3asm\u0022,\u0020YUCAAAAA
+ SccLocalPath0 = .
+ SccProvider0 = MSSCCI:Perforce\u0020SCM
+ EndGlobalSection
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Debug.ActiveCfg = Debug|Win32
+ {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Debug.Build.0 = Debug|Win32
+ {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Release.ActiveCfg = Release|Win32
+ {E0D6B319-6F95-4ABA-9BE0-5454CAA5C8CD}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/q3asm/q3asm.vcproj b/q3asm/q3asm.vcproj
index 49266b4..76bdc0b 100755
--- a/q3asm/q3asm.vcproj
+++ b/q3asm/q3asm.vcproj
@@ -1,195 +1,195 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.10"
- Name="q3asm"
- SccProjectName="&quot;$/source/q3asm&quot;, YUCAAAAA"
- SccLocalPath=".">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Release|Win32"
- OutputDirectory=".\Release"
- IntermediateDirectory=".\Release"
- ConfigurationType="1"
- UseOfMFC="0"
- ATLMinimizesCRunTimeLibraryUsage="FALSE"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="../common"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
- StringPooling="TRUE"
- RuntimeLibrary="4"
- EnableFunctionLevelLinking="TRUE"
- UsePrecompiledHeader="2"
- PrecompiledHeaderFile=".\Release/q3asm.pch"
- AssemblerListingLocation=".\Release/"
- ObjectFile=".\Release/"
- ProgramDataBaseFileName=".\Release/"
- WarningLevel="3"
- SuppressStartupBanner="TRUE"
- CompileAs="0"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- OutputFile=".\Release/q3asm.exe"
- LinkIncremental="1"
- SuppressStartupBanner="TRUE"
- ProgramDatabaseFile=".\Release/q3asm.pdb"
- SubSystem="1"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"
- TypeLibraryName=".\Release/q3asm.tlb"
- HeaderFileName=""/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="NDEBUG"
- Culture="1033"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCXMLDataGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- <Tool
- Name="VCManagedWrapperGeneratorTool"/>
- <Tool
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
- </Configuration>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory=".\Debug"
- IntermediateDirectory=".\Debug"
- ConfigurationType="1"
- UseOfMFC="0"
- ATLMinimizesCRunTimeLibraryUsage="FALSE"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="../common"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
- BasicRuntimeChecks="3"
- RuntimeLibrary="5"
- UsePrecompiledHeader="2"
- PrecompiledHeaderFile=".\Debug/q3asm.pch"
- AssemblerListingLocation=".\Debug/"
- ObjectFile=".\Debug/"
- ProgramDataBaseFileName=".\Debug/"
- WarningLevel="3"
- SuppressStartupBanner="TRUE"
- DebugInformationFormat="4"
- CompileAs="0"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- OutputFile=".\Debug/q3asm.exe"
- LinkIncremental="2"
- SuppressStartupBanner="TRUE"
- GenerateDebugInformation="TRUE"
- ProgramDatabaseFile=".\Debug/q3asm.pdb"
- SubSystem="1"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"
- TypeLibraryName=".\Debug/q3asm.tlb"
- HeaderFileName=""/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"
- PreprocessorDefinitions="_DEBUG"
- Culture="1033"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCXMLDataGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- <Tool
- Name="VCManagedWrapperGeneratorTool"/>
- <Tool
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
- <File
- RelativePath="cmdlib.c">
- <FileConfiguration
- Name="Release|Win32">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""/>
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- BasicRuntimeChecks="3"/>
- </FileConfiguration>
- </File>
- <File
- RelativePath="q3asm.c">
- <FileConfiguration
- Name="Release|Win32">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""/>
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories=""
- PreprocessorDefinitions=""
- BasicRuntimeChecks="3"/>
- </FileConfiguration>
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl">
- <File
- RelativePath="..\common\cmdlib.h">
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="q3asm"
+ SccProjectName="&quot;$/source/q3asm&quot;, YUCAAAAA"
+ SccLocalPath=".">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../common"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/q3asm.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Release/q3asm.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\Release/q3asm.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/q3asm.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../common"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/q3asm.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Debug/q3asm.exe"
+ LinkIncremental="2"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/q3asm.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/q3asm.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="cmdlib.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="q3asm.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\common\cmdlib.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/q3asm/qfiles.h b/q3asm/qfiles.h
index 9515acf..b2fd455 100755
--- a/q3asm/qfiles.h
+++ b/q3asm/qfiles.h
@@ -1,485 +1,485 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#ifndef __QFILES_H__
-#define __QFILES_H__
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-// surface geometry should not exceed these limits
-#define SHADER_MAX_VERTEXES 1000
-#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES)
-
-
-// the maximum size of game reletive pathnames
-#define MAX_QPATH 64
-
-/*
-========================================================================
-
-QVM files
-
-========================================================================
-*/
-
-#define VM_MAGIC 0x12721444
-typedef struct {
- int vmMagic;
-
- int instructionCount;
-
- int codeOffset;
- int codeLength;
-
- int dataOffset;
- int dataLength;
- int litLength; // ( dataLength - litLength ) should be byteswapped on load
- int bssLength; // zero filled memory appended to datalength
-} vmHeader_t;
-
-
-/*
-========================================================================
-
-PCX files are used for 8 bit images
-
-========================================================================
-*/
-
-typedef struct {
- char manufacturer;
- char version;
- char encoding;
- char bits_per_pixel;
- unsigned short xmin,ymin,xmax,ymax;
- unsigned short hres,vres;
- unsigned char palette[48];
- char reserved;
- char color_planes;
- unsigned short bytes_per_line;
- unsigned short palette_type;
- char filler[58];
- unsigned char data; // unbounded
-} pcx_t;
-
-
-/*
-========================================================================
-
-TGA files are used for 24/32 bit images
-
-========================================================================
-*/
-
-typedef struct _TargaHeader {
- unsigned char id_length, colormap_type, image_type;
- unsigned short colormap_index, colormap_length;
- unsigned char colormap_size;
- unsigned short x_origin, y_origin, width, height;
- unsigned char pixel_size, attributes;
-} TargaHeader;
-
-
-
-/*
-========================================================================
-
-.MD3 triangle model file format
-
-========================================================================
-*/
-
-#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I')
-#define MD3_VERSION 15
-
-// limits
-#define MD3_MAX_LODS 3
-#define MD3_MAX_TRIANGLES 8192 // per surface
-#define MD3_MAX_VERTS 4096 // per surface
-#define MD3_MAX_SHADERS 256 // per surface
-#define MD3_MAX_FRAMES 1024 // per model
-#define MD3_MAX_SURFACES 32 // per model
-#define MD3_MAX_TAGS 16 // per frame
-
-// vertex scales
-#define MD3_XYZ_SCALE (1.0/64)
-
-typedef struct md3Frame_s {
- vec3_t bounds[2];
- vec3_t localOrigin;
- float radius;
- char name[16];
-} md3Frame_t;
-
-typedef struct md3Tag_s {
- char name[MAX_QPATH]; // tag name
- vec3_t origin;
- vec3_t axis[3];
-} md3Tag_t;
-
-/*
-** md3Surface_t
-**
-** CHUNK SIZE
-** header sizeof( md3Surface_t )
-** shaders sizeof( md3Shader_t ) * numShaders
-** triangles[0] sizeof( md3Triangle_t ) * numTriangles
-** st sizeof( md3St_t ) * numVerts
-** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames
-*/
-typedef struct {
- int ident; //
-
- char name[MAX_QPATH]; // polyset name
-
- int flags;
- int numFrames; // all surfaces in a model should have the same
-
- int numShaders; // all surfaces in a model should have the same
- int numVerts;
-
- int numTriangles;
- int ofsTriangles;
-
- int ofsShaders; // offset from start of md3Surface_t
- int ofsSt; // texture coords are common for all frames
- int ofsXyzNormals; // numVerts * numFrames
-
- int ofsEnd; // next surface follows
-} md3Surface_t;
-
-typedef struct {
- char name[MAX_QPATH];
- int shaderIndex; // for in-game use
-} md3Shader_t;
-
-typedef struct {
- int indexes[3];
-} md3Triangle_t;
-
-typedef struct {
- float st[2];
-} md3St_t;
-
-typedef struct {
- short xyz[3];
- short normal;
-} md3XyzNormal_t;
-
-typedef struct {
- int ident;
- int version;
-
- char name[MAX_QPATH]; // model name
-
- int flags;
-
- int numFrames;
- int numTags;
- int numSurfaces;
-
- int numSkins;
-
- int ofsFrames; // offset for first frame
- int ofsTags; // numFrames * numTags
- int ofsSurfaces; // first surface, others follow
-
- int ofsEnd; // end of file
-} md3Header_t;
-
-/*
-==============================================================================
-
-MD4 file format
-
-==============================================================================
-*/
-
-#define MD4_IDENT (('4'<<24)+('P'<<16)+('D'<<8)+'I')
-#define MD4_VERSION 1
-#define MD4_MAX_BONES 128
-
-typedef struct {
- int boneIndex; // these are indexes into the boneReferences,
- float boneWeight; // not the global per-frame bone list
- vec3_t offset;
-} md4Weight_t;
-
-typedef struct {
- vec3_t normal;
- vec2_t texCoords;
- int numWeights;
- md4Weight_t weights[1]; // variable sized
-} md4Vertex_t;
-
-typedef struct {
- int indexes[3];
-} md4Triangle_t;
-
-typedef struct {
- int ident;
-
- char name[MAX_QPATH]; // polyset name
- char shader[MAX_QPATH];
- int shaderIndex; // for in-game use
-
- int ofsHeader; // this will be a negative number
-
- int numVerts;
- int ofsVerts;
-
- int numTriangles;
- int ofsTriangles;
-
- // Bone references are a set of ints representing all the bones
- // present in any vertex weights for this surface. This is
- // needed because a model may have surfaces that need to be
- // drawn at different sort times, and we don't want to have
- // to re-interpolate all the bones for each surface.
- int numBoneReferences;
- int ofsBoneReferences;
-
- int ofsEnd; // next surface follows
-} md4Surface_t;
-
-typedef struct {
- float matrix[3][4];
-} md4Bone_t;
-
-typedef struct {
- vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame
- vec3_t localOrigin; // midpoint of bounds, used for sphere cull
- float radius; // dist from localOrigin to corner
- char name[16];
- md4Bone_t bones[1]; // [numBones]
-} md4Frame_t;
-
-typedef struct {
- int numSurfaces;
- int ofsSurfaces; // first surface, others follow
- int ofsEnd; // next lod follows
-} md4LOD_t;
-
-typedef struct {
- int ident;
- int version;
-
- char name[MAX_QPATH]; // model name
-
- // frames and bones are shared by all levels of detail
- int numFrames;
- int numBones;
- int ofsFrames; // md4Frame_t[numFrames]
-
- // each level of detail has completely separate sets of surfaces
- int numLODs;
- int ofsLODs;
-
- int ofsEnd; // end of file
-} md4Header_t;
-
-
-/*
-==============================================================================
-
- .BSP file format
-
-==============================================================================
-*/
-
-
-#define BSP_IDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I')
- // little-endian "IBSP"
-
-#define BSP_VERSION 46
-
-
-// there shouldn't be any problem with increasing these values at the
-// expense of more memory allocation in the utilities
-#define MAX_MAP_MODELS 0x400
-#define MAX_MAP_BRUSHES 0x8000
-#define MAX_MAP_ENTITIES 0x800
-#define MAX_MAP_ENTSTRING 0x40000
-#define MAX_MAP_SHADERS 0x400
-
-#define MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match!
-#define MAX_MAP_FOGS 0x100
-#define MAX_MAP_PLANES 0x20000
-#define MAX_MAP_NODES 0x20000
-#define MAX_MAP_BRUSHSIDES 0x20000
-#define MAX_MAP_LEAFS 0x20000
-#define MAX_MAP_LEAFFACES 0x20000
-#define MAX_MAP_LEAFBRUSHES 0x40000
-#define MAX_MAP_PORTALS 0x20000
-#define MAX_MAP_LIGHTING 0x800000
-#define MAX_MAP_LIGHTGRID 0x800000
-#define MAX_MAP_VISIBILITY 0x200000
-
-#define MAX_MAP_DRAW_SURFS 0x20000
-#define MAX_MAP_DRAW_VERTS 0x80000
-#define MAX_MAP_DRAW_INDEXES 0x80000
-
-
-// key / value pair sizes in the entities lump
-#define MAX_KEY 32
-#define MAX_VALUE 1024
-
-// the editor uses these predefined yaw angles to orient entities up or down
-#define ANGLE_UP -1
-#define ANGLE_DOWN -2
-
-#define LIGHTMAP_WIDTH 128
-#define LIGHTMAP_HEIGHT 128
-
-
-//=============================================================================
-
-
-typedef struct {
- int fileofs, filelen;
-} lump_t;
-
-#define LUMP_ENTITIES 0
-#define LUMP_SHADERS 1
-#define LUMP_PLANES 2
-#define LUMP_NODES 3
-#define LUMP_LEAFS 4
-#define LUMP_LEAFSURFACES 5
-#define LUMP_LEAFBRUSHES 6
-#define LUMP_MODELS 7
-#define LUMP_BRUSHES 8
-#define LUMP_BRUSHSIDES 9
-#define LUMP_DRAWVERTS 10
-#define LUMP_DRAWINDEXES 11
-#define LUMP_FOGS 12
-#define LUMP_SURFACES 13
-#define LUMP_LIGHTMAPS 14
-#define LUMP_LIGHTGRID 15
-#define LUMP_VISIBILITY 16
-#define HEADER_LUMPS 17
-
-typedef struct {
- int ident;
- int version;
-
- lump_t lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct {
- float mins[3], maxs[3];
- int firstSurface, numSurfaces;
- int firstBrush, numBrushes;
-} dmodel_t;
-
-typedef struct {
- char shader[MAX_QPATH];
- int surfaceFlags;
- int contentFlags;
-} dshader_t;
-
-// planes x^1 is allways the opposite of plane x
-
-typedef struct {
- float normal[3];
- float dist;
-} dplane_t;
-
-typedef struct {
- int planeNum;
- int children[2]; // negative numbers are -(leafs+1), not nodes
- int mins[3]; // for frustom culling
- int maxs[3];
-} dnode_t;
-
-typedef struct {
- int cluster; // -1 = opaque cluster (do I still store these?)
- int area;
-
- int mins[3]; // for frustum culling
- int maxs[3];
-
- int firstLeafSurface;
- int numLeafSurfaces;
-
- int firstLeafBrush;
- int numLeafBrushes;
-} dleaf_t;
-
-typedef struct {
- int planeNum; // positive plane side faces out of the leaf
- int shaderNum;
-} dbrushside_t;
-
-typedef struct {
- int firstSide;
- int numSides;
- int shaderNum; // the shader that determines the contents flags
-} dbrush_t;
-
-typedef struct {
- char shader[MAX_QPATH];
- int brushNum;
- int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
-} dfog_t;
-
-typedef struct {
- vec3_t xyz;
- float st[2];
- float lightmap[2];
- vec3_t normal;
- byte color[4];
-} drawVert_t;
-
-typedef enum {
- MST_BAD,
- MST_PLANAR,
- MST_PATCH,
- MST_TRIANGLE_SOUP,
- MST_FLARE
-} mapSurfaceType_t;
-
-typedef struct {
- int shaderNum;
- int fogNum;
- int surfaceType;
-
- int firstVert;
- int numVerts;
-
- int firstIndex;
- int numIndexes;
-
- int lightmapNum;
- int lightmapX, lightmapY;
- int lightmapWidth, lightmapHeight;
-
- vec3_t lightmapOrigin;
- vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds
-
- int patchWidth;
- int patchHeight;
-} dsurface_t;
-
-
-#endif
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __QFILES_H__
+#define __QFILES_H__
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+// surface geometry should not exceed these limits
+#define SHADER_MAX_VERTEXES 1000
+#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES)
+
+
+// the maximum size of game reletive pathnames
+#define MAX_QPATH 64
+
+/*
+========================================================================
+
+QVM files
+
+========================================================================
+*/
+
+#define VM_MAGIC 0x12721444
+typedef struct {
+ int vmMagic;
+
+ int instructionCount;
+
+ int codeOffset;
+ int codeLength;
+
+ int dataOffset;
+ int dataLength;
+ int litLength; // ( dataLength - litLength ) should be byteswapped on load
+ int bssLength; // zero filled memory appended to datalength
+} vmHeader_t;
+
+
+/*
+========================================================================
+
+PCX files are used for 8 bit images
+
+========================================================================
+*/
+
+typedef struct {
+ char manufacturer;
+ char version;
+ char encoding;
+ char bits_per_pixel;
+ unsigned short xmin,ymin,xmax,ymax;
+ unsigned short hres,vres;
+ unsigned char palette[48];
+ char reserved;
+ char color_planes;
+ unsigned short bytes_per_line;
+ unsigned short palette_type;
+ char filler[58];
+ unsigned char data; // unbounded
+} pcx_t;
+
+
+/*
+========================================================================
+
+TGA files are used for 24/32 bit images
+
+========================================================================
+*/
+
+typedef struct _TargaHeader {
+ unsigned char id_length, colormap_type, image_type;
+ unsigned short colormap_index, colormap_length;
+ unsigned char colormap_size;
+ unsigned short x_origin, y_origin, width, height;
+ unsigned char pixel_size, attributes;
+} TargaHeader;
+
+
+
+/*
+========================================================================
+
+.MD3 triangle model file format
+
+========================================================================
+*/
+
+#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I')
+#define MD3_VERSION 15
+
+// limits
+#define MD3_MAX_LODS 3
+#define MD3_MAX_TRIANGLES 8192 // per surface
+#define MD3_MAX_VERTS 4096 // per surface
+#define MD3_MAX_SHADERS 256 // per surface
+#define MD3_MAX_FRAMES 1024 // per model
+#define MD3_MAX_SURFACES 32 // per model
+#define MD3_MAX_TAGS 16 // per frame
+
+// vertex scales
+#define MD3_XYZ_SCALE (1.0/64)
+
+typedef struct md3Frame_s {
+ vec3_t bounds[2];
+ vec3_t localOrigin;
+ float radius;
+ char name[16];
+} md3Frame_t;
+
+typedef struct md3Tag_s {
+ char name[MAX_QPATH]; // tag name
+ vec3_t origin;
+ vec3_t axis[3];
+} md3Tag_t;
+
+/*
+** md3Surface_t
+**
+** CHUNK SIZE
+** header sizeof( md3Surface_t )
+** shaders sizeof( md3Shader_t ) * numShaders
+** triangles[0] sizeof( md3Triangle_t ) * numTriangles
+** st sizeof( md3St_t ) * numVerts
+** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames
+*/
+typedef struct {
+ int ident; //
+
+ char name[MAX_QPATH]; // polyset name
+
+ int flags;
+ int numFrames; // all surfaces in a model should have the same
+
+ int numShaders; // all surfaces in a model should have the same
+ int numVerts;
+
+ int numTriangles;
+ int ofsTriangles;
+
+ int ofsShaders; // offset from start of md3Surface_t
+ int ofsSt; // texture coords are common for all frames
+ int ofsXyzNormals; // numVerts * numFrames
+
+ int ofsEnd; // next surface follows
+} md3Surface_t;
+
+typedef struct {
+ char name[MAX_QPATH];
+ int shaderIndex; // for in-game use
+} md3Shader_t;
+
+typedef struct {
+ int indexes[3];
+} md3Triangle_t;
+
+typedef struct {
+ float st[2];
+} md3St_t;
+
+typedef struct {
+ short xyz[3];
+ short normal;
+} md3XyzNormal_t;
+
+typedef struct {
+ int ident;
+ int version;
+
+ char name[MAX_QPATH]; // model name
+
+ int flags;
+
+ int numFrames;
+ int numTags;
+ int numSurfaces;
+
+ int numSkins;
+
+ int ofsFrames; // offset for first frame
+ int ofsTags; // numFrames * numTags
+ int ofsSurfaces; // first surface, others follow
+
+ int ofsEnd; // end of file
+} md3Header_t;
+
+/*
+==============================================================================
+
+MD4 file format
+
+==============================================================================
+*/
+
+#define MD4_IDENT (('4'<<24)+('P'<<16)+('D'<<8)+'I')
+#define MD4_VERSION 1
+#define MD4_MAX_BONES 128
+
+typedef struct {
+ int boneIndex; // these are indexes into the boneReferences,
+ float boneWeight; // not the global per-frame bone list
+ vec3_t offset;
+} md4Weight_t;
+
+typedef struct {
+ vec3_t normal;
+ vec2_t texCoords;
+ int numWeights;
+ md4Weight_t weights[1]; // variable sized
+} md4Vertex_t;
+
+typedef struct {
+ int indexes[3];
+} md4Triangle_t;
+
+typedef struct {
+ int ident;
+
+ char name[MAX_QPATH]; // polyset name
+ char shader[MAX_QPATH];
+ int shaderIndex; // for in-game use
+
+ int ofsHeader; // this will be a negative number
+
+ int numVerts;
+ int ofsVerts;
+
+ int numTriangles;
+ int ofsTriangles;
+
+ // Bone references are a set of ints representing all the bones
+ // present in any vertex weights for this surface. This is
+ // needed because a model may have surfaces that need to be
+ // drawn at different sort times, and we don't want to have
+ // to re-interpolate all the bones for each surface.
+ int numBoneReferences;
+ int ofsBoneReferences;
+
+ int ofsEnd; // next surface follows
+} md4Surface_t;
+
+typedef struct {
+ float matrix[3][4];
+} md4Bone_t;
+
+typedef struct {
+ vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame
+ vec3_t localOrigin; // midpoint of bounds, used for sphere cull
+ float radius; // dist from localOrigin to corner
+ char name[16];
+ md4Bone_t bones[1]; // [numBones]
+} md4Frame_t;
+
+typedef struct {
+ int numSurfaces;
+ int ofsSurfaces; // first surface, others follow
+ int ofsEnd; // next lod follows
+} md4LOD_t;
+
+typedef struct {
+ int ident;
+ int version;
+
+ char name[MAX_QPATH]; // model name
+
+ // frames and bones are shared by all levels of detail
+ int numFrames;
+ int numBones;
+ int ofsFrames; // md4Frame_t[numFrames]
+
+ // each level of detail has completely separate sets of surfaces
+ int numLODs;
+ int ofsLODs;
+
+ int ofsEnd; // end of file
+} md4Header_t;
+
+
+/*
+==============================================================================
+
+ .BSP file format
+
+==============================================================================
+*/
+
+
+#define BSP_IDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I')
+ // little-endian "IBSP"
+
+#define BSP_VERSION 46
+
+
+// there shouldn't be any problem with increasing these values at the
+// expense of more memory allocation in the utilities
+#define MAX_MAP_MODELS 0x400
+#define MAX_MAP_BRUSHES 0x8000
+#define MAX_MAP_ENTITIES 0x800
+#define MAX_MAP_ENTSTRING 0x40000
+#define MAX_MAP_SHADERS 0x400
+
+#define MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match!
+#define MAX_MAP_FOGS 0x100
+#define MAX_MAP_PLANES 0x20000
+#define MAX_MAP_NODES 0x20000
+#define MAX_MAP_BRUSHSIDES 0x20000
+#define MAX_MAP_LEAFS 0x20000
+#define MAX_MAP_LEAFFACES 0x20000
+#define MAX_MAP_LEAFBRUSHES 0x40000
+#define MAX_MAP_PORTALS 0x20000
+#define MAX_MAP_LIGHTING 0x800000
+#define MAX_MAP_LIGHTGRID 0x800000
+#define MAX_MAP_VISIBILITY 0x200000
+
+#define MAX_MAP_DRAW_SURFS 0x20000
+#define MAX_MAP_DRAW_VERTS 0x80000
+#define MAX_MAP_DRAW_INDEXES 0x80000
+
+
+// key / value pair sizes in the entities lump
+#define MAX_KEY 32
+#define MAX_VALUE 1024
+
+// the editor uses these predefined yaw angles to orient entities up or down
+#define ANGLE_UP -1
+#define ANGLE_DOWN -2
+
+#define LIGHTMAP_WIDTH 128
+#define LIGHTMAP_HEIGHT 128
+
+
+//=============================================================================
+
+
+typedef struct {
+ int fileofs, filelen;
+} lump_t;
+
+#define LUMP_ENTITIES 0
+#define LUMP_SHADERS 1
+#define LUMP_PLANES 2
+#define LUMP_NODES 3
+#define LUMP_LEAFS 4
+#define LUMP_LEAFSURFACES 5
+#define LUMP_LEAFBRUSHES 6
+#define LUMP_MODELS 7
+#define LUMP_BRUSHES 8
+#define LUMP_BRUSHSIDES 9
+#define LUMP_DRAWVERTS 10
+#define LUMP_DRAWINDEXES 11
+#define LUMP_FOGS 12
+#define LUMP_SURFACES 13
+#define LUMP_LIGHTMAPS 14
+#define LUMP_LIGHTGRID 15
+#define LUMP_VISIBILITY 16
+#define HEADER_LUMPS 17
+
+typedef struct {
+ int ident;
+ int version;
+
+ lump_t lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct {
+ float mins[3], maxs[3];
+ int firstSurface, numSurfaces;
+ int firstBrush, numBrushes;
+} dmodel_t;
+
+typedef struct {
+ char shader[MAX_QPATH];
+ int surfaceFlags;
+ int contentFlags;
+} dshader_t;
+
+// planes x^1 is allways the opposite of plane x
+
+typedef struct {
+ float normal[3];
+ float dist;
+} dplane_t;
+
+typedef struct {
+ int planeNum;
+ int children[2]; // negative numbers are -(leafs+1), not nodes
+ int mins[3]; // for frustom culling
+ int maxs[3];
+} dnode_t;
+
+typedef struct {
+ int cluster; // -1 = opaque cluster (do I still store these?)
+ int area;
+
+ int mins[3]; // for frustum culling
+ int maxs[3];
+
+ int firstLeafSurface;
+ int numLeafSurfaces;
+
+ int firstLeafBrush;
+ int numLeafBrushes;
+} dleaf_t;
+
+typedef struct {
+ int planeNum; // positive plane side faces out of the leaf
+ int shaderNum;
+} dbrushside_t;
+
+typedef struct {
+ int firstSide;
+ int numSides;
+ int shaderNum; // the shader that determines the contents flags
+} dbrush_t;
+
+typedef struct {
+ char shader[MAX_QPATH];
+ int brushNum;
+ int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
+} dfog_t;
+
+typedef struct {
+ vec3_t xyz;
+ float st[2];
+ float lightmap[2];
+ vec3_t normal;
+ byte color[4];
+} drawVert_t;
+
+typedef enum {
+ MST_BAD,
+ MST_PLANAR,
+ MST_PATCH,
+ MST_TRIANGLE_SOUP,
+ MST_FLARE
+} mapSurfaceType_t;
+
+typedef struct {
+ int shaderNum;
+ int fogNum;
+ int surfaceType;
+
+ int firstVert;
+ int numVerts;
+
+ int firstIndex;
+ int numIndexes;
+
+ int lightmapNum;
+ int lightmapX, lightmapY;
+ int lightmapWidth, lightmapHeight;
+
+ vec3_t lightmapOrigin;
+ vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds
+
+ int patchWidth;
+ int patchHeight;
+} dsurface_t;
+
+
+#endif