diff options
Diffstat (limited to 'q3asm')
| -rwxr-xr-x | q3asm/Makefile | 13 | ||||
| -rwxr-xr-x | q3asm/README.Id | 10 | ||||
| -rwxr-xr-x | q3asm/cmdlib.c | 1206 | ||||
| -rwxr-xr-x | q3asm/cmdlib.h | 160 | ||||
| -rwxr-xr-x | q3asm/lib.txt | 31 | ||||
| -rwxr-xr-x | q3asm/mathlib.h | 94 | ||||
| -rwxr-xr-x | q3asm/notes.txt | 16 | ||||
| -rwxr-xr-x | q3asm/ops.txt | 132 | ||||
| -rwxr-xr-x | q3asm/opstrings.h | 175 | ||||
| -rwxr-xr-x | q3asm/q3asm.c | 1047 | ||||
| -rwxr-xr-x | q3asm/q3asm.sln | 28 | ||||
| -rwxr-xr-x | q3asm/q3asm.vcproj | 195 | ||||
| -rwxr-xr-x | q3asm/qfiles.h | 485 | 
13 files changed, 3592 insertions, 0 deletions
diff --git a/q3asm/Makefile b/q3asm/Makefile new file mode 100755 index 0000000..b53640a --- /dev/null +++ b/q3asm/Makefile @@ -0,0 +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
 +
 diff --git a/q3asm/README.Id b/q3asm/README.Id new file mode 100755 index 0000000..30f44b2 --- /dev/null +++ b/q3asm/README.Id @@ -0,0 +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
 diff --git a/q3asm/cmdlib.c b/q3asm/cmdlib.c new file mode 100755 index 0000000..630ac57 --- /dev/null +++ b/q3asm/cmdlib.c @@ -0,0 +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);
 +}
 diff --git a/q3asm/cmdlib.h b/q3asm/cmdlib.h new file mode 100755 index 0000000..b7be51b --- /dev/null +++ b/q3asm/cmdlib.h @@ -0,0 +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
 diff --git a/q3asm/lib.txt b/q3asm/lib.txt new file mode 100755 index 0000000..7abf270 --- /dev/null +++ b/q3asm/lib.txt @@ -0,0 +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
 +
 diff --git a/q3asm/mathlib.h b/q3asm/mathlib.h new file mode 100755 index 0000000..8034808 --- /dev/null +++ b/q3asm/mathlib.h @@ -0,0 +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
 diff --git a/q3asm/notes.txt b/q3asm/notes.txt new file mode 100755 index 0000000..4a016f0 --- /dev/null +++ b/q3asm/notes.txt @@ -0,0 +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
 diff --git a/q3asm/ops.txt b/q3asm/ops.txt new file mode 100755 index 0000000..992e288 --- /dev/null +++ b/q3asm/ops.txt @@ -0,0 +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,
 +
 +
 diff --git a/q3asm/opstrings.h b/q3asm/opstrings.h new file mode 100755 index 0000000..51f2bf3 --- /dev/null +++ b/q3asm/opstrings.h @@ -0,0 +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 },
 +
 +
 diff --git a/q3asm/q3asm.c b/q3asm/q3asm.c new file mode 100755 index 0000000..836e427 --- /dev/null +++ b/q3asm/q3asm.c @@ -0,0 +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;
 +}
 +
 diff --git a/q3asm/q3asm.sln b/q3asm/q3asm.sln new file mode 100755 index 0000000..5f44a09 --- /dev/null +++ b/q3asm/q3asm.sln @@ -0,0 +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
 diff --git a/q3asm/q3asm.vcproj b/q3asm/q3asm.vcproj new file mode 100755 index 0000000..49266b4 --- /dev/null +++ b/q3asm/q3asm.vcproj @@ -0,0 +1,195 @@ +<?xml version="1.0" encoding="Windows-1252"?>
 +<VisualStudioProject
 +	ProjectType="Visual C++"
 +	Version="7.10"
 +	Name="q3asm"
 +	SccProjectName=""$/source/q3asm", 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 new file mode 100755 index 0000000..9515acf --- /dev/null +++ b/q3asm/qfiles.h @@ -0,0 +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
  | 
