diff options
author | Tim Angus <tim@ngus.net> | 2005-12-10 03:08:56 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2005-12-10 03:08:56 +0000 |
commit | 3b447421efc76ba76fbdae62f893fc6916af5433 (patch) | |
tree | 035963614a2e6333b6d38667b5142c2c0e7863c7 /ioq3-r437/src/tools/asm | |
parent | 08446c16acbbb9a9d12fccb21e27cfa29d076e77 (diff) |
* Well I fucked that up then...
Diffstat (limited to 'ioq3-r437/src/tools/asm')
-rw-r--r-- | ioq3-r437/src/tools/asm/Makefile | 44 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/README.Id | 10 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/cmdlib.c | 1219 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/cmdlib.h | 160 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/lib.txt | 31 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/mathlib.h | 94 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/notes.txt | 16 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/ops.txt | 132 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/opstrings.h | 175 | ||||
-rw-r--r-- | ioq3-r437/src/tools/asm/q3asm.c | 1628 |
10 files changed, 0 insertions, 3509 deletions
diff --git a/ioq3-r437/src/tools/asm/Makefile b/ioq3-r437/src/tools/asm/Makefile deleted file mode 100644 index 0d64f14d..00000000 --- a/ioq3-r437/src/tools/asm/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# yeah, couldn't do more simple really - -PLATFORM=$(shell uname|sed -e s/_.*//|tr A-Z a-z) -ifeq ($(PLATFORM),mingw32) - BINEXT=.exe -else - BINEXT= -endif - -ifeq ($(PLATFORM),SunOS) - INSTALL=ginstall -else - INSTALL=install -endif - -CC=gcc -Q3ASM_CFLAGS=-O2 -Wall -Werror -fno-strict-aliasing - -ifeq ($(PLATFORM),darwin) - LCC_CFLAGS += -DMACOS_X=1 -endif - -ifndef USE_CCACHE - USE_CCACHE=0 -endif - -ifeq ($(USE_CCACHE),1) - CC := ccache $(CC) - CXX := ccache $(CXX) -endif - -default: q3asm - -q3asm: q3asm.c cmdlib.c - $(CC) $(Q3ASM_CFLAGS) -o $@ $^ - -clean: - rm -f q3asm *~ *.o - -install: default - $(INSTALL) -s -m 0755 q3asm$(BINEXT) ../ - -uninstall: - rm -f ../q3asm$(BINEXT) diff --git a/ioq3-r437/src/tools/asm/README.Id b/ioq3-r437/src/tools/asm/README.Id deleted file mode 100644 index adacb50d..00000000 --- a/ioq3-r437/src/tools/asm/README.Id +++ /dev/null @@ -1,10 +0,0 @@ -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/ioq3-r437/src/tools/asm/cmdlib.c b/ioq3-r437/src/tools/asm/cmdlib.c deleted file mode 100644 index b1bd4eb2..00000000 --- a/ioq3-r437/src/tools/asm/cmdlib.c +++ /dev/null @@ -1,1219 +0,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 Quake III Arena source code; 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> -#elif defined(NeXT) -#include <libc.h> -#else -#include <unistd.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; -} - -#ifdef MAX_PATH -#undef MAX_PATH -#endif -#define MAX_PATH 4096 -static FILE* myfopen(const char* filename, const char* mode) -{ - char* p; - char fn[MAX_PATH]; - - fn[0] = '\0'; - strncat(fn, filename, sizeof(fn)-1); - - for(p=fn;*p;++p) if(*p == '\\') *p = '/'; - - return fopen(fn, mode); -} - - -FILE *SafeOpenWrite (const char *filename) -{ - FILE *f; - - f = myfopen(filename, "wb"); - - if (!f) - Error ("Error opening %s: %s",filename,strerror(errno)); - - return f; -} - -FILE *SafeOpenRead (const char *filename) -{ - FILE *f; - - f = myfopen(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 = myfopen (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 = myfopen (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/ioq3-r437/src/tools/asm/cmdlib.h b/ioq3-r437/src/tools/asm/cmdlib.h deleted file mode 100644 index 57f642ab..00000000 --- a/ioq3-r437/src/tools/asm/cmdlib.h +++ /dev/null @@ -1,160 +0,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 Quake III Arena source code; 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 _MSC_VER -#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 _MSC_VER - -#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/ioq3-r437/src/tools/asm/lib.txt b/ioq3-r437/src/tools/asm/lib.txt deleted file mode 100644 index 737a030a..00000000 --- a/ioq3-r437/src/tools/asm/lib.txt +++ /dev/null @@ -1,31 +0,0 @@ - -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/ioq3-r437/src/tools/asm/mathlib.h b/ioq3-r437/src/tools/asm/mathlib.h deleted file mode 100644 index 39722992..00000000 --- a/ioq3-r437/src/tools/asm/mathlib.h +++ /dev/null @@ -1,94 +0,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 Quake III Arena source code; 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/ioq3-r437/src/tools/asm/notes.txt b/ioq3-r437/src/tools/asm/notes.txt deleted file mode 100644 index 63297f30..00000000 --- a/ioq3-r437/src/tools/asm/notes.txt +++ /dev/null @@ -1,16 +0,0 @@ - -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/ioq3-r437/src/tools/asm/ops.txt b/ioq3-r437/src/tools/asm/ops.txt deleted file mode 100644 index e897f496..00000000 --- a/ioq3-r437/src/tools/asm/ops.txt +++ /dev/null @@ -1,132 +0,0 @@ -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/ioq3-r437/src/tools/asm/opstrings.h b/ioq3-r437/src/tools/asm/opstrings.h deleted file mode 100644 index f4a79055..00000000 --- a/ioq3-r437/src/tools/asm/opstrings.h +++ /dev/null @@ -1,175 +0,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 Quake III Arena source code; 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/ioq3-r437/src/tools/asm/q3asm.c b/ioq3-r437/src/tools/asm/q3asm.c deleted file mode 100644 index 93af582f..00000000 --- a/ioq3-r437/src/tools/asm/q3asm.c +++ /dev/null @@ -1,1628 +0,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 Quake III Arena source code; 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 "../../qcommon/qfiles.h" - -/* 19079 total symbols in FI, 2002 Jan 23 */ -#define DEFAULT_HASHTABLE_SIZE 2048 - -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 - JTRGSEG, // psuedo-segment that contains only jump table targets - 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; - -typedef struct hashchain_s { - void *data; - struct hashchain_s *next; -} hashchain_t; - -typedef struct hashtable_s { - int buckets; - hashchain_t **table; -} hashtable_t; - -int symtablelen = DEFAULT_HASHTABLE_SIZE; -hashtable_t *symtable; -hashtable_t *optable; - -segment_t segment[NUM_SEGMENTS]; -segment_t *currentSegment; - -int passNumber; - -int numSymbols; -int errorCount; - -typedef struct options_s { - qboolean verbose; - qboolean writeMapFile; - qboolean vanillaQ3Compatibility; -} options_t; - -options_t options = { 0 }; - -symbol_t *symbols; -symbol_t *lastSymbol = 0; /* Most recent symbol defined. */ - - -#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 ]; - - - -int -vreport (const char* fmt, va_list vp) -{ - if (options.verbose != qtrue) - return 0; - return vprintf(fmt, vp); -} - -int -report (const char *fmt, ...) -{ - va_list va; - int retval; - - va_start(va, fmt); - retval = vreport(fmt, va); - va_end(va); - return retval; -} - -/* The chain-and-bucket hash table. -PH */ - -void -hashtable_init (hashtable_t *H, int buckets) -{ - H->buckets = buckets; - H->table = calloc(H->buckets, sizeof(*(H->table))); - return; -} - -hashtable_t * -hashtable_new (int buckets) -{ - hashtable_t *H; - - H = malloc(sizeof(hashtable_t)); - hashtable_init(H, buckets); - return H; -} - -/* No destroy/destructor. No need. */ - -void -hashtable_add (hashtable_t *H, int hashvalue, void *datum) -{ - hashchain_t *hc, **hb; - - hashvalue = (abs(hashvalue) % H->buckets); - hb = &(H->table[hashvalue]); - if (*hb == 0) - { - /* Empty bucket. Create new one. */ - *hb = calloc(1, sizeof(**hb)); - hc = *hb; - } - else - { - /* Get hc to point to last node in chain. */ - for (hc = *hb; hc && hc->next; hc = hc->next); - hc->next = calloc(1, sizeof(*hc)); - hc = hc->next; - } - hc->data = datum; - hc->next = 0; - return; -} - -hashchain_t * -hashtable_get (hashtable_t *H, int hashvalue) -{ - hashvalue = (abs(hashvalue) % H->buckets); - return (H->table[hashvalue]); -} - -void -hashtable_stats (hashtable_t *H) -{ - int len, empties, longest, nodes; - int i; - float meanlen; - hashchain_t *hc; - - report("Stats for hashtable %08X", H); - empties = 0; - longest = 0; - nodes = 0; - for (i = 0; i < H->buckets; i++) - { - if (H->table[i] == 0) - { empties++; continue; } - for (hc = H->table[i], len = 0; hc; hc = hc->next, len++); - if (len > longest) { longest = len; } - nodes += len; - } - meanlen = (float)(nodes) / (H->buckets - empties); -#if 0 -/* Long stats display */ - report(" Total buckets: %d\n", H->buckets); - report(" Total stored nodes: %d\n", nodes); - report(" Longest chain: %d\n", longest); - report(" Empty chains: %d\n", empties); - report(" Mean non-empty chain length: %f\n", meanlen); -#else //0 -/* Short stats display */ - report(", %d buckets, %d nodes", H->buckets, nodes); - report("\n"); - report(" Longest chain: %d, empty chains: %d, mean non-empty: %f", longest, empties, meanlen); -#endif //0 - report("\n"); -} - - -/* Kludge. */ -/* Check if symbol already exists. */ -/* Returns 0 if symbol does NOT already exist, non-zero otherwise. */ -int -hashtable_symbol_exists (hashtable_t *H, int hash, char *sym) -{ - hashchain_t *hc; - symbol_t *s; - - hash = (abs(hash) % H->buckets); - hc = H->table[hash]; - if (hc == 0) - { - /* Empty chain means this symbol has not yet been defined. */ - return 0; - } - for (; hc; hc = hc->next) - { - s = (symbol_t*)hc->data; -// if ((hash == s->hash) && (strcmp(sym, s->name) == 0)) -/* We _already_ know the hash is the same. That's why we're probing! */ - if (strcmp(sym, s->name) == 0) - { - /* Symbol collisions -- symbol already exists. */ - return 1; - } - } - return 0; /* Can't find collision. */ -} - - - - -/* Comparator function for quicksorting. */ -int -symlist_cmp (const void *e1, const void *e2) -{ - const symbol_t *a, *b; - - a = *(const symbol_t **)e1; - b = *(const symbol_t **)e2; -//crumb("Symbol comparison (1) %d to (2) %d\n", a->value, b->value); - return ( a->value - b->value); -} - -/* - Sort the symbols list by using QuickSort (qsort()). - This may take a LOT of memory (a few megabytes?), but memory is cheap these days. - However, qsort(3) already exists, and I'm really lazy. - -PH -*/ -void -sort_symbols () -{ - int i, elems; - symbol_t *s; - symbol_t **symlist; - -//crumb("sort_symbols: Constructing symlist array\n"); - for (elems = 0, s = symbols; s; s = s->next, elems++) /* nop */ ; - symlist = malloc(elems * sizeof(symbol_t*)); - for (i = 0, s = symbols; s; s = s->next, i++) - { - symlist[i] = s; - } -//crumbf("sort_symbols: Quick-sorting %d symbols\n", elems); - qsort(symlist, elems, sizeof(symbol_t*), symlist_cmp); -//crumbf("sort_symbols: Reconstructing symbols list\n"); - s = symbols = symlist[0]; - for (i = 1; i < elems; i++) - { - s->next = symlist[i]; - s = s->next; - } - lastSymbol = s; - s->next = 0; -//crumbf("sort_symbols: verifying..."); fflush(stdout); - for (i = 0, s = symbols; s; s = s->next, i++) /*nop*/ ; -//crumbf(" %d elements\n", i); - free(symlist); /* d'oh. no gc. */ -} - - -#ifdef _MSC_VER -#define INT64 __int64 -#define atoi64 _atoi64 -#else -#define INT64 long long int -#define atoi64 atoll -#endif - -/* - Problem: - BYTE values are specified as signed decimal string. A properly functional - atoip() will cap large signed values at 0x7FFFFFFF. Negative word values are - often specified as very large decimal values by lcc. Therefore, values that - should be between 0x7FFFFFFF and 0xFFFFFFFF come out as 0x7FFFFFFF when using - atoi(). Bad. - - This function is one big evil hack to work around this problem. -*/ -int atoiNoCap (const char *s) -{ - INT64 l; - union { - unsigned int u; - signed int i; - } retval; - - l = atoi64(s); - /* Now smash to signed 32 bits accordingly. */ - if (l < 0) { - retval.i = (int)l; - } else { - retval.u = (unsigned int)l; - } - return retval.i; /* <- union hackage. I feel dirty with this. -PH */ -} - - - -/* -============= -HashString -============= -*/ -/* Default hash function of Kazlib 1.19, slightly modified. */ -unsigned int HashString (const char *key) -{ - static unsigned long randbox[] = { - 0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U, - 0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU, - 0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU, - 0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU, - }; - - const char *str = key; - unsigned int acc = 0; - - while (*str) { - acc ^= randbox[(*str + acc) & 0xf]; - acc = (acc << 1) | (acc >> 31); - acc &= 0xffffffffU; - acc ^= randbox[((*str++ >> 4) + acc) & 0xf]; - acc = (acc << 2) | (acc >> 30); - acc &= 0xffffffffU; - } - return abs(acc); -} - - -/* -============ -CodeError -============ -*/ -void CodeError( char *fmt, ... ) { - va_list argptr; - - errorCount++; - - report( "%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 ) { - /* Hand optimization by PhaethonH */ - symbol_t *s; - char expanded[MAX_LINE_LENGTH]; - int hash; - - if ( passNumber == 1 ) { - return; - } - - // add the file prefix to local symbols to guarantee unique - if ( sym[0] == '$' ) { - sprintf( expanded, "%s_%i", sym, currentFileIndex ); - sym = expanded; - } - - hash = HashString( sym ); - - if (hashtable_symbol_exists(symtable, hash, sym)) { - CodeError( "Multiple definitions for %s\n", sym ); - return; - } - - s = malloc( sizeof( *s ) ); - s->next = NULL; - s->name = copystring( sym ); - s->hash = hash; - s->value = value; - s->segment = currentSegment; - - hashtable_add(symtable, hash, s); - -/* - Hash table lookup already speeds up symbol lookup enormously. - We postpone sorting until end of pass 0. - Since we're not doing the insertion sort, lastSymbol should always - wind up pointing to the end of list. - This allows constant time for adding to the list. - -PH -*/ - if (symbols == 0) { - lastSymbol = symbols = s; - } else { - lastSymbol->next = s; - lastSymbol = s; - } -} - - -/* -============ -LookupSymbol - -Symbols can only be evaluated on pass 1 -============ -*/ -int LookupSymbol( char *sym ) { - symbol_t *s; - char expanded[MAX_LINE_LENGTH]; - int hash; - hashchain_t *hc; - - 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 ); - -/* - Hand optimization by PhaethonH - - Using a hash table with chain/bucket for lookups alone sped up q3asm by almost 3x for me. - -PH -*/ - for (hc = hashtable_get(symtable, hash); hc; hc = hc->next) { - s = (symbol_t*)hc->data; /* ugly typecasting, but it's fast! */ - 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 ) { -/* Goal: - Given a string `data', extract one text line into buffer `lineBuffer' that - is no longer than MAX_LINE_LENGTH characters long. Return value is - remainder of `data' that isn't part of `lineBuffer'. - -PH -*/ - /* Hand-optimized by PhaethonH */ - char *p, *q; - - currentFileLine++; - - lineParseOffset = 0; - token[0] = 0; - *lineBuffer = 0; - - p = q = data; - if (!*q) { - return NULL; - } - - for ( ; !((*p == 0) || (*p == '\n')); p++) /* nop */ ; - - if ((p - q) >= MAX_LINE_LENGTH) { - CodeError( "MAX_LINE_LENGTH" ); - return data; - } - - memcpy( lineBuffer, data, (p - data) ); - lineBuffer[(p - data)] = 0; - p += (*p == '\n') ? 1 : 0; /* Skip over final newline. */ - return p; -} - - -/* -============== -Parse - -Parse a token out of linebuffer -============== -*/ -qboolean Parse( void ) { - /* Hand-optimized by PhaethonH */ - const char *p, *q; - - /* Because lineParseOffset is only updated just before exit, this makes this code version somewhat harder to debug under a symbolic debugger. */ - - *token = 0; /* Clear token. */ - - // skip whitespace - for (p = lineBuffer + lineParseOffset; *p && (*p <= ' '); p++) /* nop */ ; - - // skip ; comments - /* die on end-of-string */ - if ((*p == ';') || (*p == 0)) { - lineParseOffset = p - lineBuffer; - return qfalse; - } - - q = p; /* Mark the start of token. */ - /* Find separator first. */ - for ( ; *p > 32; p++) /* nop */ ; /* XXX: unsafe assumptions. */ - /* *p now sits on separator. Mangle other values accordingly. */ - strncpy(token, q, p - q); - token[p - q] = 0; - - lineParseOffset = p - lineBuffer; - - return qtrue; -} - - -/* -============== -ParseValue -============== -*/ -int ParseValue( void ) { - Parse(); - return atoiNoCap( token ); -} - - -/* -============== -ParseExpression -============== -*/ -int ParseExpression(void) { - /* Hand optimization, PhaethonH */ - int i, j; - char sym[MAX_LINE_LENGTH]; - int v; - - /* Skip over a leading minus. */ - for ( i = ((token[0] == '-') ? 1 : 0) ; i < MAX_LINE_LENGTH ; i++ ) { - if ( token[i] == '+' || token[i] == '-' || token[i] == 0 ) { - break; - } - } - - memcpy( sym, token, i ); - sym[i] = 0; - - switch (*sym) { /* Resolve depending on first character. */ -/* Optimizing compilers can convert cases into "calculated jumps". I think these are faster. -PH */ - case '-': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - v = atoiNoCap(sym); - break; - default: - v = LookupSymbol(sym); - break; - } - - // 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; - - switch (token[i]) { - case '+': - v += atoiNoCap(sym); - break; - case '-': - v -= atoiNoCap(sym); - break; - } - - 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; - } -} - - - - - - - -//#define STAT(L) report("STAT " L "\n"); -#define STAT(L) -#define ASM(O) int TryAssemble##O () - - -/* - These clauses were moved out from AssembleLine() to allow reordering of if's. - An optimizing compiler should reconstruct these back into inline code. - -PH -*/ - - // call instructions reset currentArgOffset -ASM(CALL) -{ - if ( !strncmp( token, "CALL", 4 ) ) { -STAT("CALL"); - EmitByte( &segment[CODESEG], OP_CALL ); - instructionCount++; - currentArgOffset = 0; - return 1; - } - return 0; -} - - // arg is converted to a reversed store -ASM(ARG) -{ - if ( !strncmp( token, "ARG", 3 ) ) { -STAT("ARG"); - EmitByte( &segment[CODESEG], OP_ARG ); - instructionCount++; - if ( 8 + currentArgOffset >= 256 ) { - CodeError( "currentArgOffset >= 256" ); - return 1; - } - EmitByte( &segment[CODESEG], 8 + currentArgOffset ); - currentArgOffset += 4; - return 1; - } - return 0; -} - - // ret just leaves something on the op stack -ASM(RET) -{ - if ( !strncmp( token, "RET", 3 ) ) { -STAT("RET"); - EmitByte( &segment[CODESEG], OP_LEAVE ); - instructionCount++; - EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs ); - return 1; - } - return 0; -} - - // pop is needed to discard the return value of - // a function -ASM(POP) -{ - if ( !strncmp( token, "pop", 3 ) ) { -STAT("POP"); - EmitByte( &segment[CODESEG], OP_POP ); - instructionCount++; - return 1; - } - return 0; -} - - // address of a parameter is converted to OP_LOCAL -ASM(ADDRF) -{ - int v; - if ( !strncmp( token, "ADDRF", 5 ) ) { -STAT("ADDRF"); - instructionCount++; - Parse(); - v = ParseExpression(); - v = 16 + currentArgs + currentLocals + v; - EmitByte( &segment[CODESEG], OP_LOCAL ); - EmitInt( &segment[CODESEG], v ); - return 1; - } - return 0; -} - - // address of a local is converted to OP_LOCAL -ASM(ADDRL) -{ - int v; - if ( !strncmp( token, "ADDRL", 5 ) ) { -STAT("ADDRL"); - instructionCount++; - Parse(); - v = ParseExpression(); - v = 8 + currentArgs + v; - EmitByte( &segment[CODESEG], OP_LOCAL ); - EmitInt( &segment[CODESEG], v ); - return 1; - } - return 0; -} - -ASM(PROC) -{ - char name[1024]; - if ( !strcmp( token, "proc" ) ) { -STAT("PROC"); - 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 1; - } - return 0; -} - - -ASM(ENDPROC) -{ - int v, v2; - if ( !strcmp( token, "endproc" ) ) { -STAT("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 1; - } - return 0; -} - - -ASM(ADDRESS) -{ - int v; - if ( !strcmp( token, "address" ) ) { -STAT("ADDRESS"); - Parse(); - v = ParseExpression(); - -/* Addresses are 32 bits wide, and therefore go into data segment. */ - HackToSegment( DATASEG ); - EmitInt( currentSegment, v ); - if( passNumber == 1 && token[ 0 ] == '$' ) // crude test for labels - EmitInt( &segment[ JTRGSEG ], v ); - return 1; - } - return 0; -} - -ASM(EXPORT) -{ - if ( !strcmp( token, "export" ) ) { -STAT("EXPORT"); - return 1; - } - return 0; -} - -ASM(IMPORT) -{ - if ( !strcmp( token, "import" ) ) { -STAT("IMPORT"); - return 1; - } - return 0; -} - -ASM(CODE) -{ - if ( !strcmp( token, "code" ) ) { -STAT("CODE"); - currentSegment = &segment[CODESEG]; - return 1; - } - return 0; -} - -ASM(BSS) -{ - if ( !strcmp( token, "bss" ) ) { -STAT("BSS"); - currentSegment = &segment[BSSSEG]; - return 1; - } - return 0; -} - -ASM(DATA) -{ - if ( !strcmp( token, "data" ) ) { -STAT("DATA"); - currentSegment = &segment[DATASEG]; - return 1; - } - return 0; -} - -ASM(LIT) -{ - if ( !strcmp( token, "lit" ) ) { -STAT("LIT"); - currentSegment = &segment[LITSEG]; - return 1; - } - return 0; -} - -ASM(LINE) -{ - if ( !strcmp( token, "line" ) ) { -STAT("LINE"); - return 1; - } - return 0; -} - -ASM(FILE) -{ - if ( !strcmp( token, "file" ) ) { -STAT("FILE"); - return 1; - } - return 0; -} - -ASM(EQU) -{ - char name[1024]; - if ( !strcmp( token, "equ" ) ) { -STAT("EQU"); - Parse(); - strcpy( name, token ); - Parse(); - DefineSymbol( name, atoiNoCap(token) ); - return 1; - } - return 0; -} - -ASM(ALIGN) -{ - int v; - if ( !strcmp( token, "align" ) ) { -STAT("ALIGN"); - v = ParseValue(); - currentSegment->imageUsed = (currentSegment->imageUsed + v - 1 ) & ~( v - 1 ); - return 1; - } - return 0; -} - -ASM(SKIP) -{ - int v; - if ( !strcmp( token, "skip" ) ) { -STAT("SKIP"); - v = ParseValue(); - currentSegment->imageUsed += v; - return 1; - } - return 0; -} - -ASM(BYTE) -{ - int i, v, v2; - if ( !strcmp( token, "byte" ) ) { -STAT("BYTE"); - v = ParseValue(); - v2 = ParseValue(); - - if ( v == 1 ) { -/* Character (1-byte) values go into lit(eral) segment. */ - HackToSegment( LITSEG ); - } else if ( v == 4 ) { -/* 32-bit (4-byte) values go into data segment. */ - HackToSegment( DATASEG ); - } else if ( v == 2 ) { -/* and 16-bit (2-byte) values will cause q3asm to barf. */ - CodeError( "16 bit initialized data not supported" ); - } - - // emit little endien - for ( i = 0 ; i < v ; i++ ) { - EmitByte( currentSegment, (v2 & 0xFF) ); /* paranoid ANDing -PH */ - v2 >>= 8; - } - return 1; - } - return 0; -} - - // 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 -ASM(LABEL) -{ - if ( !strncmp( token, "LABEL", 5 ) ) { -STAT("LABEL"); - Parse(); - if ( currentSegment == &segment[CODESEG] ) { - DefineSymbol( token, instructionCount ); - } else { - DefineSymbol( token, currentSegment->imageUsed ); - } - return 1; - } - return 0; -} - - - -/* -============== -AssembleLine - -============== -*/ -void AssembleLine( void ) { - hashchain_t *hc; - sourceOps_t *op; - int i; - int hash; - - Parse(); - if ( !token[0] ) { - return; - } - - hash = HashString( token ); - -/* - Opcode search using hash table. - Since the opcodes stays mostly fixed, this may benefit even more from a tree. - Always with the tree :) - -PH -*/ - for (hc = hashtable_get(optable, hash); hc; hc = hc->next) { - op = (sourceOps_t*)(hc->data); - i = op - sourceOps; - if ((hash == opcodesHash[i]) && (!strcmp(token, op->name))) { - int opcode; - int expression; - - if ( op->opcode == OP_UNDEF ) { - CodeError( "Undefined opcode: %s\n", token ); - } - if ( op->opcode == OP_IGNORE ) { - return; // we ignore most conversions - } - - // sign extensions need to check next parm - opcode = op->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] && op->opcode != OP_CVIF - && op->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; - } - } - -/* This falls through if an assembly opcode is not found. -PH */ - -/* The following should be sorted in sequence of statistical frequency, most frequent first. -PH */ -/* -Empirical frequency statistics from FI 2001.01.23: - 109892 STAT ADDRL - 72188 STAT BYTE - 51150 STAT LINE - 50906 STAT ARG - 43704 STAT IMPORT - 34902 STAT LABEL - 32066 STAT ADDRF - 23704 STAT CALL - 7720 STAT POP - 7256 STAT RET - 5198 STAT ALIGN - 3292 STAT EXPORT - 2878 STAT PROC - 2878 STAT ENDPROC - 2812 STAT ADDRESS - 738 STAT SKIP - 374 STAT EQU - 280 STAT CODE - 176 STAT LIT - 102 STAT FILE - 100 STAT BSS - 68 STAT DATA - - -PH -*/ - -#undef ASM -#define ASM(O) if (TryAssemble##O ()) return; - - ASM(ADDRL) - ASM(BYTE) - ASM(LINE) - ASM(ARG) - ASM(IMPORT) - ASM(LABEL) - ASM(ADDRF) - ASM(CALL) - ASM(POP) - ASM(RET) - ASM(ALIGN) - ASM(EXPORT) - ASM(PROC) - ASM(ENDPROC) - ASM(ADDRESS) - ASM(SKIP) - ASM(EQU) - ASM(CODE) - ASM(LIT) - ASM(FILE) - ASM(BSS) - ASM(DATA) - - CodeError( "Unknown token: %s\n", token ); -} - -/* -============== -InitTables -============== -*/ -void InitTables( void ) { - int i; - - symtable = hashtable_new(symtablelen); - optable = hashtable_new(100); /* There's hardly 100 opcodes anyway. */ - - for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) { - opcodesHash[i] = HashString( sourceOps[i].name ); - hashtable_add(optable, opcodesHash[i], sourceOps + i); - } -} - - -/* -============== -WriteMapFile -============== -*/ -void WriteMapFile( void ) { - FILE *f; - symbol_t *s; - char imageName[MAX_OS_PATH]; - int seg; - - strcpy( imageName, outputFilename ); - StripExtension( imageName ); - strcat( imageName, ".map" ); - - report( "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; - int headerSize; - - report( "%i total errors\n", errorCount ); - - strcpy( imageName, outputFilename ); - StripExtension( imageName ); - strcat( imageName, ".qvm" ); - - remove( imageName ); - - report( "code segment: %7i\n", segment[CODESEG].imageUsed ); - report( "data segment: %7i\n", segment[DATASEG].imageUsed ); - report( "lit segment: %7i\n", segment[LITSEG].imageUsed ); - report( "bss segment: %7i\n", segment[BSSSEG].imageUsed ); - report( "instruction count: %i\n", instructionCount ); - - if ( errorCount != 0 ) { - report( "Not writing a file due to errors\n" ); - return; - } - - if( !options.vanillaQ3Compatibility ) { - header.vmMagic = VM_MAGIC_VER2; - headerSize = sizeof( header ); - } else { - header.vmMagic = VM_MAGIC; - - // Don't write the VM_MAGIC_VER2 bits when maintaining 1.32b compatibility. - // (I know this isn't strictly correct due to padding, but then platforms - // that pad wouldn't be able to write a correct header anyway). Note: if - // vmHeader_t changes, this needs to be adjusted too. - headerSize = sizeof( header ) - sizeof( header.jtrgLength ); - } - - header.instructionCount = instructionCount; - header.codeOffset = headerSize; - 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; - header.jtrgLength = segment[JTRGSEG].imageUsed; - - report( "Writing to %s\n", imageName ); - - CreatePath( imageName ); - f = SafeOpenWrite( imageName ); - SafeWrite( f, &header, headerSize ); - SafeWrite( f, &segment[CODESEG].image, segment[CODESEG].imageUsed ); - SafeWrite( f, &segment[DATASEG].image, segment[DATASEG].imageUsed ); - SafeWrite( f, &segment[LITSEG].image, segment[LITSEG].imageUsed ); - - if( !options.vanillaQ3Compatibility ) { - SafeWrite( f, &segment[JTRGSEG].image, segment[JTRGSEG].imageUsed ); - } - - fclose( f ); -} - -/* -=============== -Assemble -=============== -*/ -void Assemble( void ) { - int i; - char filename[MAX_OS_PATH]; - char *ptr; - - report( "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; - segment[JTRGSEG].segmentBase = segment[BSSSEG].segmentBase + segment[BSSSEG].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; - report("pass %i: %s\n", passNumber, currentFileName ); - fflush( NULL ); - 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; - } - if (passNumber == 0) { - sort_symbols(); - } - } - - // 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 - if( options.writeMapFile ) { - 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: %s [OPTION]... [FILES]...\n\ -Assemble LCC bytecode assembly to Q3VM bytecode.\n\ -\n\ - -o OUTPUT Write assembled output to file OUTPUT.qvm\n\ - -f LISTFILE Read options and list of files to assemble from LISTFILE\n\ - -b BUCKETS Set symbol hash table to BUCKETS buckets\n\ - -v Verbose compilation report\n\ - -vq3 Produce a qvm file compatible with Q3 1.32b\n\ -", argv[0]); - } - - start = I_FloatTime (); - - // 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" ); - } -/* Timbo of Tremulous pointed out -o not working; stock ID q3asm folded in the change. Yay. */ - 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; - } - - if (!strcmp(argv[i], "-b")) { - if (i == argc - 1) { - Error("-b requires an argument"); - } - i++; - symtablelen = atoiNoCap(argv[i]); - continue; - } - - if( !strcmp( argv[ i ], "-v" ) ) { -/* Verbosity option added by Timbo, 2002.09.14. -By default (no -v option), q3asm remains silent except for critical errors. -Verbosity turns on all messages, error or not. -Motivation: not wanting to scrollback for pages to find asm error. -*/ - options.verbose = qtrue; - continue; - } - - if( !strcmp( argv[ i ], "-m" ) ) { - options.writeMapFile = qtrue; - continue; - } - - if( !strcmp( argv[ i ], "-vq3" ) ) { - options.vanillaQ3Compatibility = qtrue; - 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++; - } - - InitTables(); - Assemble(); - - { - symbol_t *s; - - for ( i = 0, s = symbols ; s ; s = s->next, i++ ) /* nop */ ; - - if (options.verbose) - { - report("%d symbols defined\n", i); - hashtable_stats(symtable); - hashtable_stats(optable); - } - } - - end = I_FloatTime (); - report ("%5.0f seconds elapsed\n", end-start); - - return errorCount; -} - |