mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-10 14:52:00 +00:00
* Removed Q3ASM_TURBO defines from q3asm
* Removed q3asm qfiles.h and redirected it to qcommon qfiles.h
This commit is contained in:
parent
ecd73786d5
commit
8295a83897
2 changed files with 4 additions and 992 deletions
|
@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "mathlib.h"
|
#include "mathlib.h"
|
||||||
#include "qfiles.h"
|
#include "../../qcommon/qfiles.h"
|
||||||
|
|
||||||
/* MSVC-ism fix. */
|
/* MSVC-ism fix. */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -30,7 +30,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* 19079 total symbols in FI, 2002 Jan 23 */
|
/* 19079 total symbols in FI, 2002 Jan 23 */
|
||||||
#define Q3ASM_TURBO
|
|
||||||
#define DEFAULT_HASHTABLE_SIZE 2048
|
#define DEFAULT_HASHTABLE_SIZE 2048
|
||||||
|
|
||||||
char outputFilename[MAX_OS_PATH];
|
char outputFilename[MAX_OS_PATH];
|
||||||
|
@ -155,7 +154,6 @@ typedef struct symbol_s {
|
||||||
int value;
|
int value;
|
||||||
} symbol_t;
|
} symbol_t;
|
||||||
|
|
||||||
#ifdef Q3ASM_TURBO
|
|
||||||
typedef struct hashchain_s {
|
typedef struct hashchain_s {
|
||||||
void *data;
|
void *data;
|
||||||
struct hashchain_s *next;
|
struct hashchain_s *next;
|
||||||
|
@ -169,7 +167,6 @@ typedef struct hashtable_s {
|
||||||
int symtablelen = DEFAULT_HASHTABLE_SIZE;
|
int symtablelen = DEFAULT_HASHTABLE_SIZE;
|
||||||
hashtable_t *symtable;
|
hashtable_t *symtable;
|
||||||
hashtable_t *optable;
|
hashtable_t *optable;
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
|
|
||||||
segment_t segment[NUM_SEGMENTS];
|
segment_t segment[NUM_SEGMENTS];
|
||||||
segment_t *currentSegment;
|
segment_t *currentSegment;
|
||||||
|
@ -225,7 +222,6 @@ sourceOps_t sourceOps[] = {
|
||||||
int opcodesHash[ NUM_SOURCE_OPS ];
|
int opcodesHash[ NUM_SOURCE_OPS ];
|
||||||
|
|
||||||
|
|
||||||
#ifdef Q3ASM_TURBO
|
|
||||||
|
|
||||||
int
|
int
|
||||||
vreport (const char* fmt, va_list vp)
|
vreport (const char* fmt, va_list vp)
|
||||||
|
@ -463,24 +459,12 @@ ThingToConvertDecimalIntoSigned32SoThatAtoiDoesntCapAt7FFFFFFF (const char *s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
HashString
|
HashString
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
int HashString( char *s ) {
|
|
||||||
int v = 0;
|
|
||||||
|
|
||||||
while ( *s ) {
|
|
||||||
v += *s;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
/* Default hash function of Kazlib 1.19, slightly modified. */
|
/* Default hash function of Kazlib 1.19, slightly modified. */
|
||||||
unsigned int HashString (const char *key)
|
unsigned int HashString (const char *key)
|
||||||
{
|
{
|
||||||
|
@ -504,7 +488,6 @@ unsigned int HashString (const char *key)
|
||||||
}
|
}
|
||||||
return abs(acc);
|
return abs(acc);
|
||||||
}
|
}
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -561,57 +544,6 @@ Symbols can only be defined on pass 0
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void DefineSymbol( char *sym, int value ) {
|
void DefineSymbol( char *sym, int value ) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
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;
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
/* Hand optimization by PhaethonH */
|
/* Hand optimization by PhaethonH */
|
||||||
symbol_t *s;
|
symbol_t *s;
|
||||||
char expanded[MAX_LINE_LENGTH];
|
char expanded[MAX_LINE_LENGTH];
|
||||||
|
@ -657,7 +589,6 @@ void DefineSymbol( char *sym, int value ) {
|
||||||
lastSymbol->next = s;
|
lastSymbol->next = s;
|
||||||
lastSymbol = s;
|
lastSymbol = s;
|
||||||
}
|
}
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -669,34 +600,6 @@ Symbols can only be evaluated on pass 1
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
int LookupSymbol( char *sym ) {
|
int LookupSymbol( char *sym ) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
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;
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
symbol_t *s;
|
symbol_t *s;
|
||||||
char expanded[MAX_LINE_LENGTH];
|
char expanded[MAX_LINE_LENGTH];
|
||||||
int hash;
|
int hash;
|
||||||
|
@ -732,7 +635,6 @@ int LookupSymbol( char *sym ) {
|
||||||
DefineSymbol( sym, 0 ); // so more errors aren't printed
|
DefineSymbol( sym, 0 ); // so more errors aren't printed
|
||||||
passNumber = 1;
|
passNumber = 1;
|
||||||
return 0;
|
return 0;
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -746,38 +648,10 @@ Otherwise returns the updated parse pointer
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
char *ExtractLine( char *data ) {
|
char *ExtractLine( char *data ) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
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;
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
/* Goal:
|
/* Goal:
|
||||||
Given a string `data', extract one text line into buffer `lineBuffer' that is no longer than MAX_LINE_LENGTH characters long.
|
Given a string `data', extract one text line into buffer `lineBuffer' that
|
||||||
Return value is remainder of `data' that isn't part of `lineBuffer'.
|
is no longer than MAX_LINE_LENGTH characters long. Return value is
|
||||||
|
remainder of `data' that isn't part of `lineBuffer'.
|
||||||
-PH
|
-PH
|
||||||
*/
|
*/
|
||||||
/* Hand-optimized by PhaethonH */
|
/* Hand-optimized by PhaethonH */
|
||||||
|
@ -805,7 +679,6 @@ char *ExtractLine( char *data ) {
|
||||||
lineBuffer[(p - data)] = 0;
|
lineBuffer[(p - data)] = 0;
|
||||||
p += (*p == '\n') ? 1 : 0; /* Skip over final newline. */
|
p += (*p == '\n') ? 1 : 0; /* Skip over final newline. */
|
||||||
return p;
|
return p;
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -817,39 +690,6 @@ Parse a token out of linebuffer
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
qboolean Parse( void ) {
|
qboolean Parse( void ) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
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;
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
/* Hand-optimized by PhaethonH */
|
/* Hand-optimized by PhaethonH */
|
||||||
const char *p, *q;
|
const char *p, *q;
|
||||||
|
|
||||||
|
@ -877,7 +717,6 @@ qboolean Parse( void ) {
|
||||||
lineParseOffset = p - lineBuffer;
|
lineParseOffset = p - lineBuffer;
|
||||||
|
|
||||||
return qtrue;
|
return qtrue;
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -898,54 +737,6 @@ ParseExpression
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
int ParseExpression(void) {
|
int ParseExpression(void) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
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;
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
/* Hand optimization, PhaethonH */
|
/* Hand optimization, PhaethonH */
|
||||||
int i, j;
|
int i, j;
|
||||||
char sym[MAX_LINE_LENGTH];
|
char sym[MAX_LINE_LENGTH];
|
||||||
|
@ -997,7 +788,6 @@ int ParseExpression(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1035,8 +825,6 @@ void HackToSegment( segmentName_t seg ) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Q3ASM_TURBO
|
|
||||||
|
|
||||||
//#define STAT(L) report("STAT " L "\n");
|
//#define STAT(L) report("STAT " L "\n");
|
||||||
#define STAT(L)
|
#define STAT(L)
|
||||||
#define ASM(O) int TryAssemble##O ()
|
#define ASM(O) int TryAssemble##O ()
|
||||||
|
@ -1370,25 +1158,6 @@ STAT("LABEL");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============
|
==============
|
||||||
AssembleLine
|
AssembleLine
|
||||||
|
@ -1396,12 +1165,8 @@ AssembleLine
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
void AssembleLine( void ) {
|
void AssembleLine( void ) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
int v, v2;
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
hashchain_t *hc;
|
hashchain_t *hc;
|
||||||
sourceOps_t *op;
|
sourceOps_t *op;
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
int i;
|
int i;
|
||||||
int hash;
|
int hash;
|
||||||
|
|
||||||
|
@ -1412,249 +1177,6 @@ void AssembleLine( void ) {
|
||||||
|
|
||||||
hash = HashString( token );
|
hash = HashString( token );
|
||||||
|
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
/*
|
/*
|
||||||
Opcode search using hash table.
|
Opcode search using hash table.
|
||||||
Since the opcodes stays mostly fixed, this may benefit even more from a tree.
|
Since the opcodes stays mostly fixed, this may benefit even more from a tree.
|
||||||
|
@ -1771,8 +1293,6 @@ Empirical frequency statistics from FI 2001.01.23:
|
||||||
ASM(BSS)
|
ASM(BSS)
|
||||||
ASM(DATA)
|
ASM(DATA)
|
||||||
|
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
|
|
||||||
CodeError( "Unknown token: %s\n", token );
|
CodeError( "Unknown token: %s\n", token );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1782,13 +1302,6 @@ InitTables
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
void InitTables( void ) {
|
void InitTables( void ) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for ( i = 0 ; i < NUM_SOURCE_OPS ; i++ ) {
|
|
||||||
opcodesHash[i] = HashString( sourceOps[i].name );
|
|
||||||
}
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
symtable = hashtable_new(symtablelen);
|
symtable = hashtable_new(symtablelen);
|
||||||
|
@ -1798,7 +1311,6 @@ void InitTables( void ) {
|
||||||
opcodesHash[i] = HashString( sourceOps[i].name );
|
opcodesHash[i] = HashString( sourceOps[i].name );
|
||||||
hashtable_add(optable, opcodesHash[i], sourceOps + i);
|
hashtable_add(optable, opcodesHash[i], sourceOps + i);
|
||||||
}
|
}
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1928,11 +1440,9 @@ void Assemble( void ) {
|
||||||
for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) {
|
for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) {
|
||||||
segment[i].imageUsed = (segment[i].imageUsed + 3) & ~3;
|
segment[i].imageUsed = (segment[i].imageUsed + 3) & ~3;
|
||||||
}
|
}
|
||||||
#ifdef Q3ASM_TURBO
|
|
||||||
if (passNumber == 0) {
|
if (passNumber == 0) {
|
||||||
sort_symbols();
|
sort_symbols();
|
||||||
}
|
}
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reserve the stack in bss
|
// reserve the stack in bss
|
||||||
|
@ -1996,9 +1506,6 @@ int main( int argc, char **argv ) {
|
||||||
// _chdir( "/quake3/jccode/cgame/lccout" ); // hack for vc profiler
|
// _chdir( "/quake3/jccode/cgame/lccout" ); // hack for vc profiler
|
||||||
|
|
||||||
if ( argc < 2 ) {
|
if ( argc < 2 ) {
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
Error( "usage: q3asm [-o output] <files> or q3asm -f <listfile>\n" );
|
|
||||||
#else /* Q3ASM_TURBO */
|
|
||||||
Error("Usage: %s [OPTION]... [FILES]...\n\
|
Error("Usage: %s [OPTION]... [FILES]...\n\
|
||||||
Assemble LCC bytecode assembly to Q3VM bytecode.\n\
|
Assemble LCC bytecode assembly to Q3VM bytecode.\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -2007,13 +1514,9 @@ Assemble LCC bytecode assembly to Q3VM bytecode.\n\
|
||||||
-b BUCKETS Set symbol hash table to BUCKETS buckets\n\
|
-b BUCKETS Set symbol hash table to BUCKETS buckets\n\
|
||||||
-v Verbose compilation report\n\
|
-v Verbose compilation report\n\
|
||||||
", argv[0]);
|
", argv[0]);
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start = I_FloatTime ();
|
start = I_FloatTime ();
|
||||||
#ifndef Q3ASM_TURBO
|
|
||||||
InitTables();
|
|
||||||
#endif /* !Q3ASM_TURBO */
|
|
||||||
|
|
||||||
// default filename is "q3asm"
|
// default filename is "q3asm"
|
||||||
strcpy( outputFilename, "q3asm" );
|
strcpy( outputFilename, "q3asm" );
|
||||||
|
@ -2042,7 +1545,6 @@ Assemble LCC bytecode assembly to Q3VM bytecode.\n\
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q3ASM_TURBO
|
|
||||||
if (!strcmp(argv[i], "-b")) {
|
if (!strcmp(argv[i], "-b")) {
|
||||||
if (i == argc - 1) {
|
if (i == argc - 1) {
|
||||||
Error("-b requires an argument");
|
Error("-b requires an argument");
|
||||||
|
@ -2051,7 +1553,6 @@ Assemble LCC bytecode assembly to Q3VM bytecode.\n\
|
||||||
symtablelen = atoi(argv[i]);
|
symtablelen = atoi(argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
|
|
||||||
if( !strcmp( argv[ i ], "-v" ) ) {
|
if( !strcmp( argv[ i ], "-v" ) ) {
|
||||||
/* Verbosity option added by Timbo, 2002.09.14.
|
/* Verbosity option added by Timbo, 2002.09.14.
|
||||||
|
@ -2077,12 +1578,9 @@ Motivation: not wanting to scrollback for pages to find asm error.
|
||||||
numAsmFiles++;
|
numAsmFiles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q3ASM_TURBO
|
|
||||||
InitTables();
|
InitTables();
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
Assemble();
|
Assemble();
|
||||||
|
|
||||||
#ifdef Q3ASM_TURBO
|
|
||||||
{
|
{
|
||||||
symbol_t *s;
|
symbol_t *s;
|
||||||
|
|
||||||
|
@ -2095,7 +1593,6 @@ Motivation: not wanting to scrollback for pages to find asm error.
|
||||||
hashtable_stats(optable);
|
hashtable_stats(optable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* Q3ASM_TURBO */
|
|
||||||
|
|
||||||
end = I_FloatTime ();
|
end = I_FloatTime ();
|
||||||
report ("%5.0f seconds elapsed\n", end-start);
|
report ("%5.0f seconds elapsed\n", end-start);
|
||||||
|
|
|
@ -1,485 +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 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
|
|
Loading…
Reference in a new issue