Merge remote-tracking branch 'github/master'
authorRudolf Polzer <divverent@alientrap.org>
Tue, 27 Mar 2012 10:11:37 +0000 (12:11 +0200)
committerRudolf Polzer <divverent@alientrap.org>
Tue, 27 Mar 2012 10:11:37 +0000 (12:11 +0200)
Conflicts:
.gitignore
config.py
libs/synapse/synapse.cpp
plugins/imagehl/lbmlib.cpp
plugins/surface_heretic2/surfacedialog.cpp
plugins/surface_ufoai/surfacedialog.cpp
radiant/brushscript.cpp
radiant/main.cpp
radiant/preferences.cpp
tools/quake3/common/cmdlib.c
tools/quake3/common/cmdlib.h
tools/quake3/q3map2/path_init.c
windows_compile_guide/index.html

1  2 
contrib/bobtoolz/DBrush.cpp
libs/splines/splines.cpp
libs/splines/util_str.cpp
tools/quake3/common/cmdlib.c
tools/quake3/common/cmdlib.h
tools/quake3/common/inout.c
tools/quake3/q3map2/main.c
tools/quake3/q3map2/path_init.c
tools/quake3/q3map2/q3map2.h

index 7c24cd0fa4ff3f25be30322c26f2257612ba3468,3e54e79717b554c6857a43bf87c721fb48dedc85..4a2b9c097969c4fa9766ab0ffd3cda41d5b211b5
  //
  //////////////////////////////////////////////////////////////////////
  
 -#include "StdAfx.h"
 +#include "DBrush.h"
  
 -#ifdef _WIN32
 +#ifdef WIN32
  #pragma warning(disable : 4786)
  #endif
  
 -#include "DBrush.h"
 +#include <list>
 +#include "str.h"
 +
 +#include "DPoint.h"
 +#include "DPlane.h"
 +#include "DEPair.h"
 +#include "DPatch.h"
 +#include "DEntity.h"
  #include "DWinding.h"
 +
  #include "dialogs/dialogs-gtk.h"
  
  #include "misc.h"
  
 +#include "iundo.h"
 +
 +#include "generic/referencecounted.h"
 +
 +#include "scenelib.h"
 +
  //////////////////////////////////////////////////////////////////////
  // Construction/Destruction
  //////////////////////////////////////////////////////////////////////
  
  DBrush::DBrush( int ID ){
        m_nBrushID = ID;
 -      bBoundsBuilt = FALSE;
 +      bBoundsBuilt = false;
 +      QER_entity = NULL;
        QER_brush = NULL;
  }
  
@@@ -67,11 -52,11 +67,11 @@@ DBrush::~DBrush()
  // Implementation
  //////////////////////////////////////////////////////////////////////
  
 -DPlane* DBrush::AddFace( vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData ){
 +DPlane* DBrush::AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const _QERFaceData* texData ){
  #ifdef _DEBUG
  //    Sys_Printf("(%f %f %f) (%f %f %f) (%f %f %f)\n", va[0], va[1], va[2], vb[0], vb[1], vb[2], vc[0], vc[1], vc[2]);
  #endif
 -      bBoundsBuilt = FALSE;
 +      bBoundsBuilt = false;
        DPlane* newFace = new DPlane( va, vb, vc, texData );
        faceList.push_back( newFace );
  
@@@ -85,12 -70,12 +85,12 @@@ int DBrush::BuildPoints()
                return 0;                   // with only 3 faces u can't have a bounded soild
  
        }
 -      for ( list<DPlane *>::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++ )
 +      for ( std::list<DPlane *>::const_iterator p1 = faceList.begin(); p1 != faceList.end(); p1++ )
        {
 -              list<DPlane *>::const_iterator p2 = p1;
 +              std::list<DPlane *>::const_iterator p2 = p1;
                for ( p2++; p2 != faceList.end(); p2++ )
                {
 -                      list<DPlane *>::const_iterator p3 = p2;
 +                      std::list<DPlane *>::const_iterator p3 = p2;
                        for ( p3++; p3 != faceList.end(); p3++ )
                        {
                                vec3_t pnt;
@@@ -98,7 -83,7 +98,7 @@@
                                        int pos = PointPosition( pnt );
  
                                        if ( pos == POINT_IN_BRUSH ) { // ???? shouldn't happen here
 -                                              Sys_Printf( "ERROR:: Build Brush Points: Point IN brush!!!\n" );
 +                                              globalErrorStream() << "ERROR:: Build Brush Points: Point IN brush!!!\n";
                                        }
                                        else if ( pos == POINT_ON_BRUSH ) { // normal point
                                                if ( !HasPoint( pnt ) ) {
  //    Sys_Printf("%i points on brush\n", pointList.size());
  #endif
  
 -      return pointList.size();
 +      return static_cast<int>( pointList.size() );
  }
  
 -void DBrush::LoadFromBrush_t( brush_t* brush, bool textured ){
 -      ClearFaces();
 -      ClearPoints();
 +void DBrush_addFace( DBrush& brush, const _QERFaceData& faceData ){
 +      brush.AddFace( vector3_to_array( faceData.m_p0 ), vector3_to_array( faceData.m_p1 ), vector3_to_array( faceData.m_p2 ), 0 );
 +}
 +typedef ReferenceCaller1<DBrush, const _QERFaceData&, DBrush_addFace> DBrushAddFaceCaller;
  
 -      for ( int i = g_FuncTable.m_pfnGetFaceCount( brush ) - 1; i >= 0 ; i-- )
 -      {   // running backwards so i dont have to use the count function each time (OPT)
 -              _QERFaceData* faceData = g_FuncTable.m_pfnGetFaceData( brush, i );
 +void DBrush_addFaceTextured( DBrush& brush, const _QERFaceData& faceData ){
 +      brush.AddFace( vector3_to_array( faceData.m_p0 ), vector3_to_array( faceData.m_p1 ), vector3_to_array( faceData.m_p2 ), &faceData );
 +}
 +typedef ReferenceCaller1<DBrush, const _QERFaceData&, DBrush_addFaceTextured> DBrushAddFaceTexturedCaller;
  
 -              if ( faceData == NULL ) {
 -                      DoMessageBox( "Null pointer returned", "WARNING!", MB_OK );
 -              }
 +void DBrush::LoadFromBrush( scene::Instance& brush, bool textured ){
 +      ClearFaces();
 +      ClearPoints();
  
 -              if ( textured ) {
 -                      AddFace( faceData->m_v1, faceData->m_v2, faceData->m_v3, faceData );
 -              }
 -              else{
 -                      AddFace( faceData->m_v1, faceData->m_v2, faceData->m_v3, NULL );
 -              }
 -      }
 +      GlobalBrushCreator().Brush_forEachFace( brush.path().top(), textured ? BrushFaceDataCallback( DBrushAddFaceTexturedCaller( *this ) ) : BrushFaceDataCallback( DBrushAddFaceCaller( *this ) ) );
  
 -      QER_brush = brush;
 +      QER_entity = brush.path().parent().get_pointer();
 +      QER_brush = brush.path().top().get_pointer();
  }
  
  int DBrush::PointPosition( vec3_t pnt ){
        int state = POINT_IN_BRUSH; // if nothing happens point is inside brush
  
 -      for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
 +      for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
        {
                float dist = ( *chkPlane )->DistanceToPoint( pnt );
  
  }
  
  void DBrush::ClearPoints(){
 -      for ( list<DPoint *>::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++ ) {
 +      for ( std::list<DPoint *>::const_iterator deadPoint = pointList.begin(); deadPoint != pointList.end(); deadPoint++ ) {
                delete *deadPoint;
        }
        pointList.clear();
  }
  
  void DBrush::ClearFaces(){
 -      bBoundsBuilt = FALSE;
 -      for ( list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ )
 +      bBoundsBuilt = false;
 +      for ( std::list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ )
        {
                delete *deadPlane;
        }
@@@ -186,31 -174,31 +186,31 @@@ void DBrush::AddPoint( vec3_t pnt )
  }
  
  bool DBrush::HasPoint( vec3_t pnt ){
 -      for ( list<DPoint *>::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++ )
 +      for ( std::list<DPoint *>::const_iterator chkPoint = pointList.begin(); chkPoint != pointList.end(); chkPoint++ )
        {
                if ( **chkPoint == pnt ) {
 -                      return TRUE;
 +                      return true;
                }
        }
  
 -      return FALSE;
 +      return false;
  }
  
  int DBrush::RemoveRedundantPlanes(){
        int cnt = 0;
 -      list<DPlane *>::iterator chkPlane;
 +      std::list<DPlane *>::iterator chkPlane;
  
        // find duplicate planes
 -      list<DPlane *>::iterator p1 = faceList.begin();
 +      std::list<DPlane *>::iterator p1 = faceList.begin();
  
        while ( p1 != faceList.end() )
        {
 -              list<DPlane *>::iterator p2 = p1;
 +              std::list<DPlane *>::iterator p2 = p1;
  
                for ( p2++; p2 != faceList.end(); p2++ )
                {
                        if ( **p1 == **p2 ) {
 -                              if ( !strcmp( ( *p1 )->texInfo.m_TextureName, "textures/common/caulk" ) ) {
 +                              if ( !strcmp( ( *p1 )->m_shader.c_str(), "textures/common/caulk" ) ) {
                                        delete *p1;
                                        p1 = faceList.erase( p1 );    // duplicate plane
                                }
@@@ -271,13 -259,13 +271,13 @@@ bool DBrush::GetBounds( vec3_t min, vec
        BuildBounds();
  
        if ( !bBoundsBuilt ) {
 -              return FALSE;
 +              return false;
        }
  
        VectorCopy( bbox_min, min );
        VectorCopy( bbox_max, max );
  
 -      return TRUE;
 +      return true;
  }
  
  bool DBrush::BBoxCollision( DBrush* chkBrush ){
        chkBrush->GetBounds( min2, max2 );
  
        if ( min1[0] >= max2[0] ) {
 -              return FALSE;
 +              return false;
        }
        if ( min1[1] >= max2[1] ) {
 -              return FALSE;
 +              return false;
        }
        if ( min1[2] >= max2[2] ) {
 -              return FALSE;
 +              return false;
        }
  
        if ( max1[0] <= min2[0] ) {
 -              return FALSE;
 +              return false;
        }
        if ( max1[1] <= min2[1] ) {
 -              return FALSE;
 +              return false;
        }
        if ( max1[2] <= min2[2] ) {
 -              return FALSE;
 +              return false;
        }
  
 -      return TRUE;
 +      return true;
  }
  
  DPlane* DBrush::HasPlane( DPlane* chkPlane ){
 -      for ( list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
 +      for ( std::list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
        {
                if ( **brushPlane == *chkPlane ) {
                        return *brushPlane;
@@@ -325,26 -313,26 +325,26 @@@ bool DBrush::IsCutByPlane( DPlane *cutt
  
        if ( pointList.size() == 0 ) {
                if ( BuildPoints() == 0 ) {
 -                      return FALSE;
 +                      return false;
                }
        }
  
 -      list<DPoint *>::const_iterator chkPnt = pointList.begin();
 +      std::list<DPoint *>::const_iterator chkPnt = pointList.begin();
  
        if ( chkPnt == pointList.end() ) {
 -              return FALSE;
 +              return false;
        }
  
        float dist = cuttingPlane->DistanceToPoint( ( *chkPnt )->_pnt );
  
        if ( dist > MAX_ROUND_ERROR ) {
 -              isInFront = FALSE;
 +              isInFront = false;
        }
        else if ( dist < MAX_ROUND_ERROR ) {
 -              isInFront = TRUE;
 +              isInFront = true;
        }
        else{
 -              return TRUE;
 +              return true;
        }
  
        for ( chkPnt++ = pointList.begin(); chkPnt != pointList.end(); chkPnt++ )
  
                if ( dist > MAX_ROUND_ERROR ) {
                        if ( isInFront ) {
 -                              return TRUE;
 +                              return true;
                        }
                }
                else if ( dist < MAX_ROUND_ERROR ) {
                        if ( !isInFront ) {
 -                              return TRUE;
 +                              return true;
                        }
                }
                else{
 -                      return TRUE;
 +                      return true;
                }
        }
  
 -      return FALSE;
 +      return false;
  }
  
 -brush_t* DBrush::BuildInRadiant( bool allowDestruction, int* changeCnt, entity_t* entity ){
 +
 +scene::Node* DBrush::BuildInRadiant( bool allowDestruction, int* changeCnt, scene::Node* entity ){
        if ( allowDestruction ) {
 -              bool kill = TRUE;
 +              bool kill = true;
  
 -              for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
 +              for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
                {
                        if ( ( *chkPlane )->m_bChkOk ) {
 -                              kill = FALSE;
 +                              kill = false;
                                break;
                        }
                }
  
        //+djbob: fixed bug when brush had no faces "phantom brush" in radiant.
        if ( faceList.size() < 4 ) {
 -              Sys_Printf( "Possible Phantom Brush Found, will not rebuild\n" );
 +              globalErrorStream() << "Possible Phantom Brush Found, will not rebuild\n";
                return NULL;
        }
        //-djbob
  
 -      QER_brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();
 +      NodeSmartReference node( GlobalBrushCreator().createBrush() );
  
 -      for ( list<DPlane *>::const_iterator buildPlane = faceList.begin(); buildPlane != faceList.end(); buildPlane++ ) {
 -              if ( ( *buildPlane )->AddToBrush_t( QER_brush ) && changeCnt ) {
 +      for ( std::list<DPlane *>::const_iterator buildPlane = faceList.begin(); buildPlane != faceList.end(); buildPlane++ ) {
 +              if ( ( *buildPlane )->AddToBrush( node ) && changeCnt ) {
                        ( *changeCnt )++;
                }
        }
  
        if ( entity ) {
 -              g_FuncTable.m_pfnCommitBrushHandleToEntity( QER_brush, entity );
 -              g_BrushTable.m_pfnBrush_Build( QER_brush, false, false, false, false );
 -              g_BrushTable.m_pfnBrush_AddToList( QER_brush, g_AppDataTable.m_pfnSelectedBrushes() );
 +              Node_getTraversable( *entity )->insert( node );
        }
        else {
 -              g_FuncTable.m_pfnCommitBrushHandle( QER_brush );
 +              Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( node );
        }
  
 -      return QER_brush;
 +      QER_entity = entity;
 +      QER_brush = node.get_pointer();
 +
 +      return node.get_pointer();
  }
  
  void DBrush::CutByPlane( DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2 ){
        DBrush* b1 = new DBrush;
        DBrush* b2 = new DBrush;
  
 -      for ( list<DPlane *>::const_iterator parsePlane = faceList.begin(); parsePlane != faceList.end(); parsePlane++ )
 +      for ( std::list<DPlane *>::const_iterator parsePlane = faceList.begin(); parsePlane != faceList.end(); parsePlane++ )
        {
                b1->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL );
                b2->AddFace( ( *parsePlane )->points[0], ( *parsePlane )->points[1], ( *parsePlane )->points[2], NULL );
  bool DBrush::IntersectsWith( DBrush *chkBrush ){
        if ( pointList.size() == 0 ) {
                if ( BuildPoints() == 0 ) {
 -                      return FALSE;   // invalid brush!!!!
 +                      return false;   // invalid brush!!!!
  
                }
        }
        if ( chkBrush->pointList.size() == 0 ) {
                if ( chkBrush->BuildPoints() == 0 ) {
 -                      return FALSE;   // invalid brush!!!!
 +                      return false;   // invalid brush!!!!
  
                }
        }
        if ( !BBoxCollision( chkBrush ) ) {
 -              return FALSE;
 +              return false;
        }
  
 -      list<DPlane *>::const_iterator iplPlane;
 +      std::list<DPlane *>::const_iterator iplPlane;
  
        for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ )
        {
  
 -              bool allInFront = TRUE;
 -              for ( list<DPoint *>::const_iterator iPoint = chkBrush->pointList.begin(); iPoint != chkBrush->pointList.end(); iPoint++ )
 +              bool allInFront = true;
 +              for ( std::list<DPoint *>::const_iterator iPoint = chkBrush->pointList.begin(); iPoint != chkBrush->pointList.end(); iPoint++ )
                {
                        if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) {
 -                              allInFront = FALSE;
 +                              allInFront = false;
                                break;
                        }
                }
                if ( allInFront ) {
 -                      return FALSE;
 +                      return false;
                }
        }
  
        for ( iplPlane = chkBrush->faceList.begin(); iplPlane != chkBrush->faceList.end(); iplPlane++ )
        {
 -              bool allInFront = TRUE;
 -              for ( list<DPoint *>::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++ )
 +              bool allInFront = true;
 +              for ( std::list<DPoint *>::const_iterator iPoint = pointList.begin(); iPoint != pointList.end(); iPoint++ )
                {
                        if ( ( *iplPlane )->DistanceToPoint( ( *iPoint )->_pnt ) < -MAX_ROUND_ERROR ) {
 -                              allInFront = FALSE;
 +                              allInFront = false;
                                break;
                        }
                }
                if ( allInFront ) {
 -                      return FALSE;
 +                      return false;
                }
        }
  
 -      return TRUE;
 +      return true;
  }
  
  bool DBrush::IntersectsWith( DPlane* p1, DPlane* p2, vec3_t v ) {
        vec3_t vDown = { 0, 0, -1 };
  
 -      list<DPlane *>::const_iterator iplPlane;
 +      std::list<DPlane *>::const_iterator iplPlane;
        for ( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++ ) {
                DPlane* p = ( *iplPlane );
  
                }
                if ( p->PlaneIntersection( p1, p2, v ) ) {
                        if ( PointPosition( v ) != POINT_OUT_BRUSH ) {
 -                              return TRUE;
 +                              return true;
                        }
                }
        }
  
 -      return FALSE;
 +      return false;
  }
  
  void DBrush::BuildBounds(){
                        }
                }
  
 -              list<DPoint *>::const_iterator first = pointList.begin();
 +              std::list<DPoint *>::const_iterator first = pointList.begin();
                VectorCopy( ( *first )->_pnt, bbox_min );
                VectorCopy( ( *first )->_pnt, bbox_max );
  
 -              list<DPoint *>::const_iterator point = pointList.begin();
 +              std::list<DPoint *>::const_iterator point = pointList.begin();
                for ( point++; point != pointList.end(); point++ )
                {
                        if ( ( *point )->_pnt[0] > bbox_max[0] ) {
                        }
                }
  
 -              bBoundsBuilt = TRUE;
 +              bBoundsBuilt = true;
        }
  }
  
@@@ -562,23 -548,23 +562,23 @@@ bool DBrush::BBoxTouch( DBrush *chkBrus
        chkBrush->GetBounds( min2, max2 );
  
        if ( ( min1[0] - max2[0] ) > MAX_ROUND_ERROR ) {
 -              return FALSE;
 +              return false;
        }
        if ( ( min1[1] - max2[1] ) > MAX_ROUND_ERROR ) {
 -              return FALSE;
 +              return false;
        }
        if ( ( min1[2] - max2[2] ) > MAX_ROUND_ERROR ) {
 -              return FALSE;
 +              return false;
        }
  
        if ( ( min2[0] - max1[0] ) > MAX_ROUND_ERROR ) {
 -              return FALSE;
 +              return false;
        }
        if ( ( min2[1] - max1[1] ) > MAX_ROUND_ERROR ) {
 -              return FALSE;
 +              return false;
        }
        if ( ( min2[2] - max1[2] ) > MAX_ROUND_ERROR ) {
 -              return FALSE;
 +              return false;
        }
  
        int cnt = 0;
        }
  
        if ( cnt > 1 ) {
 -              return FALSE;
 +              return false;
        }
  
 -      return TRUE;
 +      return true;
  }
  
 -void DBrush::ResetChecks( list<Str>* exclusionList ){
 -      for ( list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
 +void DBrush::ResetChecks( std::list<Str>* exclusionList ){
 +      for ( std::list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
        {
 -              bool set = FALSE;
 +              bool set = false;
  
                if ( exclusionList ) {
 -                      for ( list<Str>::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ )
 +                      for ( std::list<Str>::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ )
                        {
 -                              if ( strstr( ( *resetPlane )->texInfo.m_TextureName, eTexture->GetBuffer() ) ) {
 -                                      set = TRUE;
 +                              if ( strstr( ( *resetPlane )->m_shader.c_str(), eTexture->GetBuffer() ) ) {
 +                                      set = true;
                                        break;
                                }
                        }
  }
  
  DPlane* DBrush::HasPlaneInverted( DPlane *chkPlane ){
 -      for ( list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
 +      for ( std::list<DPlane *>::const_iterator brushPlane = faceList.begin(); brushPlane != faceList.end(); brushPlane++ )
        {
                if ( **brushPlane != *chkPlane ) {
                        if ( fabs( ( *brushPlane )->_d + chkPlane->_d ) < 0.1 ) {
  }
  
  bool DBrush::HasTexture( const char *textureName ){
 -      for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
 +      for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
        {
 -              if ( strstr( ( *chkPlane )->texInfo.m_TextureName, textureName ) ) {
 -                      return TRUE;
 +              if ( strstr( ( *chkPlane )->m_shader.c_str(), textureName ) ) {
 +                      return true;
                }
  
        }
 -      return FALSE;
 +      return false;
  }
  
  bool DBrush::IsDetail(){
 -      for ( list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
 +      for ( std::list<DPlane *>::const_iterator chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
        {
 -              if ( ( *chkPlane )->texInfo.m_nContents & FACE_DETAIL ) {
 -                      return TRUE;
 +              if ( ( *chkPlane )->texInfo.contents & FACE_DETAIL ) {
 +                      return true;
                }
  
        }
 -      return FALSE;
 +      return false;
  }
  
  void DBrush::BuildFromWinding( DWinding *w ){
        if ( w->numpoints < 3 ) {
 -              Sys_ERROR( "Winding has invalid number of points" );
 +              globalErrorStream() << "Winding has invalid number of points";
                return;
        }
  
  void DBrush::SaveToFile( FILE *pFile ){
        fprintf( pFile, "{\n" );
  
 -      for ( list<DPlane *>::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++ )
 +      for ( std::list<DPlane *>::const_iterator pp = faceList.begin(); pp != faceList.end(); pp++ )
        {
                char buffer[512];
  
                                 ( *pp )->points[0][0], ( *pp )->points[0][1], ( *pp )->points[0][2],
                                 ( *pp )->points[1][0], ( *pp )->points[1][1], ( *pp )->points[1][2],
                                 ( *pp )->points[2][0], ( *pp )->points[2][1], ( *pp )->points[2][2],
 -                               ( *pp )->texInfo.m_TextureName,
 -                               ( *pp )->texInfo.m_fShift[0], ( *pp )->texInfo.m_fShift[1],
 -                               ( *pp )->texInfo.m_fScale[0], ( *pp )->texInfo.m_fScale[0],
 -                               ( *pp )->texInfo.m_fRotate );
 +                               ( *pp )->m_shader.c_str(),
 +                               ( *pp )->texInfo.m_texdef.shift[0], ( *pp )->texInfo.m_texdef.shift[1],
 +                               ( *pp )->texInfo.m_texdef.scale[0], ( *pp )->texInfo.m_texdef.scale[0],
 +                               ( *pp )->texInfo.m_texdef.rotate );
  
-               fprintf( pFile, buffer );
+               fprintf( pFile, "%s", buffer );
        }
  
        fprintf( pFile, "}\n" );
  }
  
  void DBrush::Rotate( vec3_t vOrigin, vec3_t vRotation ){
 -      for ( list<DPlane *>::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++ )
 +      for ( std::list<DPlane *>::const_iterator rotPlane = faceList.begin(); rotPlane != faceList.end(); rotPlane++ )
        {
                for ( int i = 0; i < 3; i++ )
                        VectorRotate( ( *rotPlane )->points[i], vRotation, vOrigin );
@@@ -736,89 -722,89 +736,89 @@@ void DBrush::RotateAboutCentre( vec3_t 
  bool DBrush::ResetTextures( const char* textureName, float fScale[2],    float fShift[2],    int rotation, const char* newTextureName,
                                                        int bResetTextureName,   int bResetScale[2], int bResetShift[2], int bResetRotation ){
        if ( textureName ) {
 -              bool changed = FALSE;
 -              for ( list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
 +              bool changed = false;
 +              for ( std::list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
                {
 -                      if ( !strcmp( ( *resetPlane )->texInfo.m_TextureName, textureName ) ) {
 +                      if ( !strcmp( ( *resetPlane )->m_shader.c_str(), textureName ) ) {
                                if ( bResetTextureName ) {
 -                                      strcpy( ( *resetPlane )->texInfo.m_TextureName, newTextureName );
 +                                      ( *resetPlane )->m_shader = newTextureName;
                                }
  
                                if ( bResetScale[0] ) {
 -                                      ( *resetPlane )->texInfo.m_fScale[0] = fScale[0];
 +                                      ( *resetPlane )->texInfo.m_texdef.scale[0] = fScale[0];
                                }
                                if ( bResetScale[1] ) {
 -                                      ( *resetPlane )->texInfo.m_fScale[1] = fScale[1];
 +                                      ( *resetPlane )->texInfo.m_texdef.scale[1] = fScale[1];
                                }
  
                                if ( bResetShift[0] ) {
 -                                      ( *resetPlane )->texInfo.m_fShift[0] = fShift[0];
 +                                      ( *resetPlane )->texInfo.m_texdef.shift[0] = fShift[0];
                                }
                                if ( bResetShift[1] ) {
 -                                      ( *resetPlane )->texInfo.m_fShift[1] = fShift[1];
 +                                      ( *resetPlane )->texInfo.m_texdef.shift[1] = fShift[1];
                                }
  
                                if ( bResetRotation ) {
 -                                      ( *resetPlane )->texInfo.m_fRotate = (float)rotation;
 +                                      ( *resetPlane )->texInfo.m_texdef.rotate = (float)rotation;
                                }
  
 -                              changed = TRUE;
 +                              changed = true;
                        }
                }
                return changed; // no point rebuilding unless we need to, only slows things down
        }
        else
        {
 -              for ( list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
 +              for ( std::list<DPlane *>::const_iterator resetPlane = faceList.begin(); resetPlane != faceList.end(); resetPlane++ )
                {
                        if ( bResetTextureName ) {
 -                              strcpy( ( *resetPlane )->texInfo.m_TextureName, newTextureName );
 +                              ( *resetPlane )->m_shader = newTextureName;
                        }
  
                        if ( bResetScale[0] ) {
 -                              ( *resetPlane )->texInfo.m_fScale[0] = fScale[0];
 +                              ( *resetPlane )->texInfo.m_texdef.scale[0] = fScale[0];
                        }
                        if ( bResetScale[1] ) {
 -                              ( *resetPlane )->texInfo.m_fScale[1] = fScale[1];
 +                              ( *resetPlane )->texInfo.m_texdef.scale[1] = fScale[1];
                        }
  
                        if ( bResetShift[0] ) {
 -                              ( *resetPlane )->texInfo.m_fShift[0] = fShift[0];
 +                              ( *resetPlane )->texInfo.m_texdef.shift[0] = fShift[0];
                        }
                        if ( bResetShift[1] ) {
 -                              ( *resetPlane )->texInfo.m_fShift[1] = fShift[1];
 +                              ( *resetPlane )->texInfo.m_texdef.shift[1] = fShift[1];
                        }
  
                        if ( bResetRotation ) {
 -                              ( *resetPlane )->texInfo.m_fRotate = (float)rotation;
 +                              ( *resetPlane )->texInfo.m_texdef.rotate = (float)rotation;
                        }
                }
 -              return TRUE;
 +              return true;
        }
  }
  
  bool DBrush::operator ==( DBrush* other ){
 -      list<DPlane *>::const_iterator chkPlane;
 +      std::list<DPlane *>::const_iterator chkPlane;
  
        for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
        {
                if ( !other->HasPlane( ( *chkPlane ) ) ) {
 -                      return FALSE;
 +                      return false;
                }
        }
  
        for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ )
        {
                if ( !HasPlane( ( *chkPlane ) ) ) {
 -                      return FALSE;
 +                      return false;
                }
        }
  
 -      return TRUE;
 +      return true;
  }
  
 -DPlane* DBrush::AddFace( vec3_t va, vec3_t vb, vec3_t vc, const char *textureName, bool bDetail ){
 -      bBoundsBuilt = FALSE;
 +DPlane* DBrush::AddFace( const vec3_t va, const vec3_t vb, const vec3_t vc, const char *textureName, bool bDetail ){
 +      bBoundsBuilt = false;
        DPlane* newFace = new DPlane( va, vb, vc, textureName, bDetail );
        faceList.push_back( newFace );
  
  DPlane* DBrush::FindPlaneWithClosestNormal( vec_t* normal ) {
        vec_t bestDot = -2;
        DPlane* bestDotPlane = NULL;
 -      list<DPlane *>::const_iterator chkPlane;
 +      std::list<DPlane *>::const_iterator chkPlane;
        for ( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) {
                DPlane* pPlane = ( *chkPlane );
  
@@@ -851,7 -837,7 +851,7 @@@ int DBrush::FindPointsForPlane( DPlane
  
        BuildPoints();
  
 -      for ( list<DPoint *>::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) {
 +      for ( std::list<DPoint *>::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) {
                DPoint* point = ( *points );
  
                if ( fabs( plane->DistanceToPoint( point->_pnt ) ) < MAX_ROUND_ERROR ) {
  }
  
  void DBrush::RemovePlane( DPlane* plane ) {
 -      bBoundsBuilt = FALSE;
 -      for ( list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) {
 +      bBoundsBuilt = false;
 +      for ( std::list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) {
                if ( *deadPlane == plane ) {
                        delete *deadPlane;
                        faceList.remove( plane );
                }
        }
  }
 -
 -void DBrush::RemoveFromRadiant( void ) {
 -      if ( QER_brush ) {
 -              g_FuncTable.m_pfnDeleteBrushHandle( QER_brush );
 -      }
 -}
diff --combined libs/splines/splines.cpp
index 42c3493958744bf3ab89b578e4be6dbcdfcf786a,b9b7c0c90e4907514e497ed252f2356a8bcdc3f4..05cb3bf972c09d5b6723be51710b0c088f9fac5a
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -   Copyright (C) 1999-2007 id Software, Inc. and contributors.
 +   Copyright (C) 1999-2006 Id Software, Inc. and contributors.
     For a list of contributors, see the accompanying CONTRIBUTORS file.
  
     This file is part of GtkRadiant.
@@@ -96,17 -96,17 +96,17 @@@ idCameraDef *g_splineList = &splineList
  idVec3 idSplineList::zero( 0,0,0 );
  
  void glLabeledPoint( idVec3 &color, idVec3 &point, float size, const char *label ) {
 -      qglColor3fv( color );
 -      qglPointSize( size );
 -      qglBegin( GL_POINTS );
 -      qglVertex3fv( point );
 -      qglEnd();
 +      glColor3fv( color );
 +      glPointSize( size );
 +      glBegin( GL_POINTS );
 +      glVertex3fv( point );
 +      glEnd();
        idVec3 v = point;
        v.x += 1;
        v.y += 1;
        v.z += 1;
 -      qglRasterPos3fv( v );
 -      qglCallLists( strlen( label ), GL_UNSIGNED_BYTE, label );
 +      glRasterPos3fv( v );
 +      glCallLists( strlen( label ), GL_UNSIGNED_BYTE, label );
  }
  
  
@@@ -119,30 -119,30 +119,30 @@@ void glBox( idVec3 &color, idVec3 &poin
        maxs[0] += size;
        maxs[1] -= size;
        maxs[2] += size;
 -      qglColor3fv( color );
 -      qglBegin( GL_LINE_LOOP );
 -      qglVertex3f( mins[0],mins[1],mins[2] );
 -      qglVertex3f( maxs[0],mins[1],mins[2] );
 -      qglVertex3f( maxs[0],maxs[1],mins[2] );
 -      qglVertex3f( mins[0],maxs[1],mins[2] );
 -      qglEnd();
 -      qglBegin( GL_LINE_LOOP );
 -      qglVertex3f( mins[0],mins[1],maxs[2] );
 -      qglVertex3f( maxs[0],mins[1],maxs[2] );
 -      qglVertex3f( maxs[0],maxs[1],maxs[2] );
 -      qglVertex3f( mins[0],maxs[1],maxs[2] );
 -      qglEnd();
 -
 -      qglBegin( GL_LINES );
 -      qglVertex3f( mins[0],mins[1],mins[2] );
 -      qglVertex3f( mins[0],mins[1],maxs[2] );
 -      qglVertex3f( mins[0],maxs[1],maxs[2] );
 -      qglVertex3f( mins[0],maxs[1],mins[2] );
 -      qglVertex3f( maxs[0],mins[1],mins[2] );
 -      qglVertex3f( maxs[0],mins[1],maxs[2] );
 -      qglVertex3f( maxs[0],maxs[1],maxs[2] );
 -      qglVertex3f( maxs[0],maxs[1],mins[2] );
 -      qglEnd();
 +      glColor3fv( color );
 +      glBegin( GL_LINE_LOOP );
 +      glVertex3f( mins[0],mins[1],mins[2] );
 +      glVertex3f( maxs[0],mins[1],mins[2] );
 +      glVertex3f( maxs[0],maxs[1],mins[2] );
 +      glVertex3f( mins[0],maxs[1],mins[2] );
 +      glEnd();
 +      glBegin( GL_LINE_LOOP );
 +      glVertex3f( mins[0],mins[1],maxs[2] );
 +      glVertex3f( maxs[0],mins[1],maxs[2] );
 +      glVertex3f( maxs[0],maxs[1],maxs[2] );
 +      glVertex3f( mins[0],maxs[1],maxs[2] );
 +      glEnd();
 +
 +      glBegin( GL_LINES );
 +      glVertex3f( mins[0],mins[1],mins[2] );
 +      glVertex3f( mins[0],mins[1],maxs[2] );
 +      glVertex3f( mins[0],maxs[1],maxs[2] );
 +      glVertex3f( mins[0],maxs[1],mins[2] );
 +      glVertex3f( maxs[0],mins[1],mins[2] );
 +      glVertex3f( maxs[0],mins[1],maxs[2] );
 +      glVertex3f( maxs[0],maxs[1],maxs[2] );
 +      glVertex3f( maxs[0],maxs[1],mins[2] );
 +      glEnd();
  
  }
  
@@@ -256,14 -256,14 +256,14 @@@ void idSplineList::draw( bool editMode 
        }
  
  
 -      qglColor3fv( controlColor );
 -      qglPointSize( 5 );
 +      glColor3fv( controlColor );
 +      glPointSize( 5 );
  
 -      qglBegin( GL_POINTS );
 +      glBegin( GL_POINTS );
        for ( i = 0; i < controlPoints.Num(); i++ ) {
 -              qglVertex3fv( *controlPoints[i] );
 +              glVertex3fv( *controlPoints[i] );
        }
 -      qglEnd();
 +      glEnd();
  
        if ( editMode ) {
                for ( i = 0; i < controlPoints.Num(); i++ ) {
        }
  
        //Draw the curve
 -      qglColor3fv( pathColor );
 -      qglBegin( GL_LINE_STRIP );
 +      glColor3fv( pathColor );
 +      glBegin( GL_LINE_STRIP );
        int count = splinePoints.Num();
        for ( i = 0; i < count; i++ ) {
 -              qglVertex3fv( *splinePoints[i] );
 +              glVertex3fv( *splinePoints[i] );
        }
 -      qglEnd();
 +      glEnd();
  
        if ( editMode ) {
 -              qglColor3fv( segmentColor );
 -              qglPointSize( 3 );
 -              qglBegin( GL_POINTS );
 +              glColor3fv( segmentColor );
 +              glPointSize( 3 );
 +              glBegin( GL_POINTS );
                for ( i = 0; i < count; i++ ) {
 -                      qglVertex3fv( *splinePoints[i] );
 +                      glVertex3fv( *splinePoints[i] );
                }
 -              qglEnd();
 +              glEnd();
        }
        if ( count > 0 ) {
                //assert(activeSegment >=0 && activeSegment < count);
@@@ -393,7 -393,6 +393,6 @@@ void idSplineList::setSelectedPoint( id
  
  const idVec3 *idSplineList::getPosition( long t ) {
        static idVec3 interpolatedPos;
-       static long lastTime = -1;
  
        int count = splineTime.Num();
        if ( count == 0 ) {
@@@ -644,7 -643,6 +643,6 @@@ bool idCameraDef::waitEvent( int index 
  
  void idCameraDef::buildCamera() {
        int i;
-       int lastSwitch = 0;
        idList<float> waits;
        idList<int> targets;
  
        // we have a base time layout for the path and the target path
        // now we need to layer on any wait or speed changes
        for ( i = 0; i < events.Num(); i++ ) {
-               idCameraEvent *ev = events[i];
                events[i]->setTriggered( false );
                switch ( events[i]->getType() ) {
                case idCameraEvent::EVENT_TARGET: {
@@@ -864,7 -861,8 +861,8 @@@ void idCameraDef::parse( const char *( 
  bool idCameraDef::load( const char *filename ) {
        char *buf;
        const char *buf_p;
-       int length = FS_ReadFile( filename, (void **)&buf );
+       FS_ReadFile( filename, (void **)&buf );
        if ( !buf ) {
                return false;
        }
@@@ -1363,7 -1361,6 +1361,6 @@@ void idSplinePosition::write( fileHandl
  }
  
  void idCameraDef::addTarget( const char *name, idCameraPosition::positionType type ) {
-       const char *text = ( name == NULL ) ? va( "target0%d", numTargets() + 1 ) : name;
        idCameraPosition *pos = newFromType( type );
        if ( pos ) {
                pos->setName( name );
index 8ac9dea3a8f5a80781f18ff1013898304dcbbe73,52a01a365fa592f875416a47b09657c54e285852..62fdaedc50f6f5905beb1b22977841568ab7d0bb
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -   Copyright (C) 1999-2007 id Software, Inc. and contributors.
 +   Copyright (C) 1999-2006 Id Software, Inc. and contributors.
     For a list of contributors, see the accompanying CONTRIBUTORS file.
  
     This file is part of GtkRadiant.
@@@ -487,9 -487,6 +487,6 @@@ void TestStringClas
        i = a.length();                 // i == 0
        i = c.length();                 // i == 4
  
-       const char *s1 = a.c_str(); // s1 == "\0"
-       const char *s2 = c.c_str(); // s2 == "test\0"
        t = new idStr();                        // t->len == 0, t->data == "\0"
        delete t;                           // t == ?
  
index 5164001c04fae612b26de2758328c07e01fbfb03,35f4d75bd68dcb0767c820e73963420a8607c1c8..41fd1ca140c7b15389c706e447d76e200379b14c
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -   Copyright (C) 1999-2007 id Software, Inc. and contributors.
 +   Copyright (C) 1999-2006 Id Software, Inc. and contributors.
     For a list of contributors, see the accompanying CONTRIBUTORS file.
  
     This file is part of GtkRadiant.
@@@ -34,7 -34,7 +34,7 @@@
  #include <sys/types.h>
  #include <sys/stat.h>
  
 -#ifdef _WIN32
 +#ifdef WIN32
  #include <direct.h>
  #include <windows.h>
  #endif
@@@ -188,7 -188,7 +188,7 @@@ void SetQdirFromPath( const char *path 
                        }
                        strncpy( qdir, path, c + len + count - path );
                        Sys_Printf( "qdir: %s\n", qdir );
 -                      for ( i = 0; i < strlen( qdir ); i++ )
 +                      for ( i = 0; i < (int) strlen( qdir ); i++ )
                        {
                                if ( qdir[i] == '\\' ) {
                                        qdir[i] = '/';
                                if ( *c == '/' || *c == '\\' ) {
                                        strncpy( gamedir, path, c + 1 - path );
  
 -                                      for ( i = 0; i < strlen( gamedir ); i++ )
 +                                      for ( i = 0; i < (int) strlen( gamedir ); i++ )
                                        {
                                                if ( gamedir[i] == '\\' ) {
                                                        gamedir[i] = '/';
@@@ -244,7 -244,10 +244,10 @@@ char *ExpandArg( const char *path )
  
  char *ExpandPath( const char *path ){
        static char full[1024];
-       if ( !*qdir || path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
 -      if ( !qdir[0] ) {
++      if ( !qdir ) {
+               Error( "ExpandPath called without qdir set" );
+       }
+       if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
                strcpy( full, path );
                return full;
        }
  
  char *ExpandGamePath( const char *path ){
        static char full[1024];
-       if ( !*gamedir ) {
 -      if ( !qdir[0] ) {
 -              Error( "ExpandGamePath called without qdir set" );
++      if ( !gamedir[0] ) {
 +              Error( "ExpandGamePath called without gamedir set" );
        }
        if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
                strcpy( full, path );
@@@ -324,9 -327,7 +327,9 @@@ void Q_getwd( char *out )
        strcat( out, "\\" );
  #else
        // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
 -      getcwd( out, 256 );
 +      if ( !getcwd( out, 256 ) ) {
 +              *out = 0;
 +      }
        strcat( out, "/" );
  #endif
        while ( out[i] != 0 )
  
  
  void Q_mkdir( const char *path ){
 +      char parentbuf[256];
 +      const char *p = NULL;
 +      int retry = 2;
 +      while ( retry-- )
 +      {
  #ifdef WIN32
 -      if ( _mkdir( path ) != -1 ) {
 -              return;
 -      }
 +              const char *q = NULL;
 +              if ( _mkdir( path ) != -1 ) {
 +                      return;
 +              }
 +              if ( errno == ENOENT ) {
 +                      p = strrchr( path, '/' );
 +                      q = strrchr( path, '\\' );
 +                      if ( q && ( !p || q < p ) ) {
 +                              p = q;
 +                      }
 +              }
  #else
 -      if ( mkdir( path, 0777 ) != -1 ) {
 -              return;
 -      }
 +              if ( mkdir( path, 0777 ) != -1 ) {
 +                      return;
 +              }
 +              if ( errno == ENOENT ) {
 +                      p = strrchr( path, '/' );
 +              }
  #endif
 +              if ( p ) {
 +                      strncpy( parentbuf, path, sizeof( parentbuf ) );
 +                      if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
 +                              parentbuf[p - path] = 0;
 +                              Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
 +                              Q_mkdir( parentbuf );
 +                              continue;
 +                      }
 +              }
 +              break;
 +      }
        if ( errno != EEXIST ) {
                Error( "mkdir %s: %s",path, strerror( errno ) );
        }
index 3c9b5a543d07c72373103f50d076855fb61b19d6,3fb98febc98457d9438a089882a41f937dfa0f6d..f6f5e4d17106108c173a13e8e15cd53e32fb3e9d
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -   Copyright (C) 1999-2007 id Software, Inc. and contributors.
 +   Copyright (C) 1999-2006 Id Software, Inc. and contributors.
     For a list of contributors, see the accompanying CONTRIBUTORS file.
  
     This file is part of GtkRadiant.
  #endif
  
  
- #define MAX_OS_PATH     1024
 +#ifdef PATH_MAX
 +#define MAX_OS_PATH     PATH_MAX
 +#else
+ #define MAX_OS_PATH     4096
 +#endif
  #define MEM_BLOCKSIZE 4096
  
  // the dec offsetof macro doesnt work very well...
@@@ -99,11 -95,7 +99,11 @@@ void ExpandWildcards( int *argc, char *
  
  double I_FloatTime( void );
  
 -void    Error( const char *error, ... );
 +void    Error( const char *error, ... )
 +#ifdef __GNUC__
 +__attribute__( ( noreturn ) )
 +#endif
 +;
  int     CheckParm( const char *check );
  
  FILE    *SafeOpenWrite( const char *filename );
index 6920995fcb8d8838bcfecd6272d60a861155ed70,7adbf23e28cc380121ceb6b4e077cc2b16e9bb1f..2c1758a76b08f35a9f96675eb20fdc320fe28e45
@@@ -1,5 -1,5 +1,5 @@@
  /*
 -   Copyright (C) 1999-2007 id Software, Inc. and contributors.
 +   Copyright (C) 1999-2006 Id Software, Inc. and contributors.
     For a list of contributors, see the accompanying CONTRIBUTORS file.
  
     This file is part of GtkRadiant.
@@@ -43,6 -43,7 +43,7 @@@
  #include "libxml/tree.h"
  
  // utf8 conversion
+ #include <glib.h>
  #include <glib/gconvert.h>
  #include <glib/gmem.h>
  
@@@ -70,8 -71,8 +71,8 @@@ xmlNodePtr xml_NodeForVec( vec3_t v )
        char buf[1024];
  
        sprintf( buf, "%f %f %f", v[0], v[1], v[2] );
 -      ret = xmlNewNode( NULL, "point" );
 -      xmlNodeSetContent( ret, buf );
 +      ret = xmlNewNode( NULL, (xmlChar*)"point" );
 +      xmlNodeSetContent( ret, (xmlChar*)buf );
        return ret;
  }
  
@@@ -93,7 -94,7 +94,7 @@@ void xml_SendNode( xmlNodePtr node )
                // l_net library defines an upper limit of MAX_NETMESSAGE
                // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
                // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
 -              while ( pos < xml_buf->use )
 +              while ( pos < (int)xml_buf->use )
                {
                        // what size are we gonna send now?
                        ( xml_buf->use - pos < MAX_NETMESSAGE - 10 ) ? ( size = xml_buf->use - pos ) : ( size = MAX_NETMESSAGE - 10 );
@@@ -148,15 -149,15 +149,15 @@@ void xml_Select( char *msg, int entityn
  
        // now build a proper "select" XML node
        sprintf( buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg );
 -      node = xmlNewNode( NULL, "select" );
 -      xmlNodeSetContent( node, buf );
 +      node = xmlNewNode( NULL, (xmlChar*)"select" );
 +      xmlNodeSetContent( node, (xmlChar*)buf );
        level[0] = (int)'0' + ( bError ? SYS_ERR : SYS_WRN )  ;
        level[1] = 0;
 -      xmlSetProp( node, "level", (char *)&level );
 +      xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
        // a 'select' information
        sprintf( buf, "%i %i", entitynum, brushnum );
 -      select = xmlNewNode( NULL, "brush" );
 -      xmlNodeSetContent( select, buf );
 +      select = xmlNewNode( NULL, (xmlChar*)"brush" );
 +      xmlNodeSetContent( select, (xmlChar*)buf );
        xmlAddChild( node, select );
        xml_SendNode( node );
  
@@@ -175,15 -176,15 +176,15 @@@ void xml_Point( char *msg, vec3_t pt )
        char buf[1024];
        char level[2];
  
 -      node = xmlNewNode( NULL, "pointmsg" );
 -      xmlNodeSetContent( node, msg );
 +      node = xmlNewNode( NULL, (xmlChar*)"pointmsg" );
 +      xmlNodeSetContent( node, (xmlChar*)msg );
        level[0] = (int)'0' + SYS_ERR;
        level[1] = 0;
 -      xmlSetProp( node, "level", (char *)&level );
 +      xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
        // a 'point' node
        sprintf( buf, "%g %g %g", pt[0], pt[1], pt[2] );
 -      point = xmlNewNode( NULL, "point" );
 -      xmlNodeSetContent( point, buf );
 +      point = xmlNewNode( NULL, (xmlChar*)"point" );
 +      xmlNodeSetContent( point, (xmlChar*)buf );
        xmlAddChild( node, point );
        xml_SendNode( node );
  
@@@ -199,11 -200,11 +200,11 @@@ void xml_Winding( char *msg, vec3_t p[]
        char level[2];
        int i;
  
 -      node = xmlNewNode( NULL, "windingmsg" );
 -      xmlNodeSetContent( node, msg );
 +      node = xmlNewNode( NULL, (xmlChar*)"windingmsg" );
 +      xmlNodeSetContent( node, (xmlChar*)msg );
        level[0] = (int)'0' + SYS_ERR;
        level[1] = 0;
 -      xmlSetProp( node, "level", (char *)&level );
 +      xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
        // a 'winding' node
        sprintf( buf, "%i ", numpoints );
        for ( i = 0; i < numpoints; i++ )
                strcat( buf, smlbuf );
        }
  
 -      winding = xmlNewNode( NULL, "winding" );
 -      xmlNodeSetContent( winding, buf );
 +      winding = xmlNewNode( NULL, (xmlChar*)"winding" );
 +      xmlNodeSetContent( winding, (xmlChar*)buf );
        xmlAddChild( node, winding );
        xml_SendNode( node );
  
@@@ -239,7 -240,7 +240,7 @@@ void Broadcast_Setup( const char *dest 
        char sMsg[1024];
  
        Net_Setup();
 -      Net_StringToAddress( (char *)dest, &address );
 +      Net_StringToAddress( dest, &address );
        brdcst_socket = Net_Connect( &address, 0 );
        if ( brdcst_socket ) {
                // send in a header
@@@ -281,19 -282,19 +282,19 @@@ void FPrintf( int flag, char *buf )
         */
        if ( !bGotXML ) {
                // initialize
 -              doc = xmlNewDoc( "1.0" );
 -              doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL );
 +              doc = xmlNewDoc( (xmlChar*)"1.0" );
 +              doc->children = xmlNewDocRawNode( doc, NULL, (xmlChar*)"q3map_feedback", NULL );
                bGotXML = qtrue;
        }
 -      node = xmlNewNode( NULL, "message" );
 +      node = xmlNewNode( NULL, (xmlChar*)"message" );
        {
                gchar* utf8 = g_locale_to_utf8( buf, -1, NULL, NULL, NULL );
 -              xmlNodeSetContent( node, utf8 );
 +              xmlNodeSetContent( node, (xmlChar*)utf8 );
                g_free( utf8 );
        }
        level[0] = (int)'0' + flag;
        level[1] = 0;
 -      xmlSetProp( node, "level", (char *)&level );
 +      xmlSetProp( node, (xmlChar*)"level", (xmlChar *)&level );
  
        xml_SendNode( node );
  }
index b53a6973c56c9afcf87f7fac53fa90cc386765be,e74a89cfc76141b124fc1f030a59b61d3a1cc9ef..76591a2ad29391bfd6b54cf43b17b912ace87f9a
@@@ -1,4 -1,4 +1,4 @@@
 -/* -------------------------------------------------------------------------------
 +/* -------------------------------------------------------------------------------;
  
     Copyright (C) 1999-2007 id Software, Inc. and contributors.
     For a list of contributors, see the accompanying CONTRIBUTORS file.
@@@ -36,8 -36,6 +36,8 @@@
  /* dependencies */
  #include "q3map2.h"
  
 +
 +
  /*
     Random()
     returns a pseudorandom number between 0 and 1
@@@ -48,6 -46,38 +48,38 @@@ vec_t Random( void )
  }
  
  
+ char *Q_strncpyz( char *dst, const char *src, size_t len ) {
+       if ( len == 0 ) {
+               abort();
+       }
+       strncpy( dst, src, len );
+       dst[ len - 1 ] = '\0';
+       return dst;
+ }
+ char *Q_strcat( char *dst, size_t dlen, const char *src ) {
+       size_t n = strlen( dst  );
+       if ( n > dlen ) {
+               abort(); /* buffer overflow */
+       }
+       return Q_strncpyz( dst + n, src, dlen - n );
+ }
+ char *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen ) {
+       size_t n = strlen( dst );
+       if ( n > dlen ) {
+               abort(); /* buffer overflow */
+       }
+       return Q_strncpyz( dst + n, src, MIN( slen, dlen - n ) );
+ }
  
  /*
     ExitQ3Map()
@@@ -61,765 -91,17 +93,765 @@@ static void ExitQ3Map( void )
        }
  }
  
 -static int MD4BlockChecksum( void * buffer, int length ) {
 -      unsigned char digest[16];
 -      int checksum;
  
 -      md4_get_digest( buffer, length, digest );
 -      /* I suppose it has to be done that way for legacy reasons? */
 -      checksum = digest[0] & ( digest[1] << 8 ) & ( digest[2] << 16 ) & ( digest[3] << 24 );
 -      checksum ^= digest[4] & ( digest[5] << 8 ) & ( digest[6] << 16 ) & ( digest[7] << 24 );
 -      checksum ^= digest[8] & ( digest[9] << 8 ) & ( digest[10] << 16 ) & ( digest[11] << 24 );
 -      checksum ^= digest[12] & ( digest[13] << 8 ) & ( digest[14] << 16 ) & ( digest[15] << 24 );
 -      return checksum;
 +
 +/* minimap stuff */
 +
 +typedef struct minimap_s
 +{
 +      bspModel_t *model;
 +      int width;
 +      int height;
 +      int samples;
 +      float *sample_offsets;
 +      float sharpen_boxmult;
 +      float sharpen_centermult;
 +      float boost, brightness, contrast;
 +      float *data1f;
 +      float *sharpendata1f;
 +      vec3_t mins, size;
 +}
 +minimap_t;
 +static minimap_t minimap;
 +
 +qboolean BrushIntersectionWithLine( bspBrush_t *brush, vec3_t start, vec3_t dir, float *t_in, float *t_out ){
 +      int i;
 +      qboolean in = qfalse, out = qfalse;
 +      bspBrushSide_t *sides = &bspBrushSides[brush->firstSide];
 +
 +      for ( i = 0; i < brush->numSides; ++i )
 +      {
 +              bspPlane_t *p = &bspPlanes[sides[i].planeNum];
 +              float sn = DotProduct( start, p->normal );
 +              float dn = DotProduct( dir, p->normal );
 +              if ( dn == 0 ) {
 +                      if ( sn > p->dist ) {
 +                              return qfalse; // outside!
 +                      }
 +              }
 +              else
 +              {
 +                      float t = ( p->dist - sn ) / dn;
 +                      if ( dn < 0 ) {
 +                              if ( !in || t > *t_in ) {
 +                                      *t_in = t;
 +                                      in = qtrue;
 +                                      // as t_in can only increase, and t_out can only decrease, early out
 +                                      if ( out && *t_in >= *t_out ) {
 +                                              return qfalse;
 +                                      }
 +                              }
 +                      }
 +                      else
 +                      {
 +                              if ( !out || t < *t_out ) {
 +                                      *t_out = t;
 +                                      out = qtrue;
 +                                      // as t_in can only increase, and t_out can only decrease, early out
 +                                      if ( in && *t_in >= *t_out ) {
 +                                              return qfalse;
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +      return in && out;
 +}
 +
 +static float MiniMapSample( float x, float y ){
 +      vec3_t org, dir;
 +      int i, bi;
 +      float t0, t1;
 +      float samp;
 +      bspBrush_t *b;
 +      bspBrushSide_t *s;
 +      int cnt;
 +
 +      org[0] = x;
 +      org[1] = y;
 +      org[2] = 0;
 +      dir[0] = 0;
 +      dir[1] = 0;
 +      dir[2] = 1;
 +
 +      cnt = 0;
 +      samp = 0;
 +      for ( i = 0; i < minimap.model->numBSPBrushes; ++i )
 +      {
 +              bi = minimap.model->firstBSPBrush + i;
 +              if ( opaqueBrushes[bi >> 3] & ( 1 << ( bi & 7 ) ) ) {
 +                      b = &bspBrushes[bi];
 +
 +                      // sort out mins/maxs of the brush
 +                      s = &bspBrushSides[b->firstSide];
 +                      if ( x < -bspPlanes[s[0].planeNum].dist ) {
 +                              continue;
 +                      }
 +                      if ( x > +bspPlanes[s[1].planeNum].dist ) {
 +                              continue;
 +                      }
 +                      if ( y < -bspPlanes[s[2].planeNum].dist ) {
 +                              continue;
 +                      }
 +                      if ( y > +bspPlanes[s[3].planeNum].dist ) {
 +                              continue;
 +                      }
 +
 +                      if ( BrushIntersectionWithLine( b, org, dir, &t0, &t1 ) ) {
 +                              samp += t1 - t0;
 +                              ++cnt;
 +                      }
 +              }
 +      }
 +
 +      return samp;
 +}
 +
 +void RandomVector2f( float v[2] ){
 +      do
 +      {
 +              v[0] = 2 * Random() - 1;
 +              v[1] = 2 * Random() - 1;
 +      }
 +      while ( v[0] * v[0] + v[1] * v[1] > 1 );
 +}
 +
 +static void MiniMapRandomlySupersampled( int y ){
 +      int x, i;
 +      float *p = &minimap.data1f[y * minimap.width];
 +      float ymin = minimap.mins[1] + minimap.size[1] * ( y / (float) minimap.height );
 +      float dx   =                   minimap.size[0]      / (float) minimap.width;
 +      float dy   =                   minimap.size[1]      / (float) minimap.height;
 +      float uv[2];
 +      float thisval;
 +
 +      for ( x = 0; x < minimap.width; ++x )
 +      {
 +              float xmin = minimap.mins[0] + minimap.size[0] * ( x / (float) minimap.width );
 +              float val = 0;
 +
 +              for ( i = 0; i < minimap.samples; ++i )
 +              {
 +                      RandomVector2f( uv );
 +                      thisval = MiniMapSample(
 +                              xmin + ( uv[0] + 0.5 ) * dx, /* exaggerated random pattern for better results */
 +                              ymin + ( uv[1] + 0.5 ) * dy  /* exaggerated random pattern for better results */
 +                              );
 +                      val += thisval;
 +              }
 +              val /= minimap.samples * minimap.size[2];
 +              *p++ = val;
 +      }
 +}
 +
 +static void MiniMapSupersampled( int y ){
 +      int x, i;
 +      float *p = &minimap.data1f[y * minimap.width];
 +      float ymin = minimap.mins[1] + minimap.size[1] * ( y / (float) minimap.height );
 +      float dx   =                   minimap.size[0]      / (float) minimap.width;
 +      float dy   =                   minimap.size[1]      / (float) minimap.height;
 +
 +      for ( x = 0; x < minimap.width; ++x )
 +      {
 +              float xmin = minimap.mins[0] + minimap.size[0] * ( x / (float) minimap.width );
 +              float val = 0;
 +
 +              for ( i = 0; i < minimap.samples; ++i )
 +              {
 +                      float thisval = MiniMapSample(
 +                              xmin + minimap.sample_offsets[2 * i + 0] * dx,
 +                              ymin + minimap.sample_offsets[2 * i + 1] * dy
 +                              );
 +                      val += thisval;
 +              }
 +              val /= minimap.samples * minimap.size[2];
 +              *p++ = val;
 +      }
 +}
 +
 +static void MiniMapNoSupersampling( int y ){
 +      int x;
 +      float *p = &minimap.data1f[y * minimap.width];
 +      float ymin = minimap.mins[1] + minimap.size[1] * ( ( y + 0.5 ) / (float) minimap.height );
 +
 +      for ( x = 0; x < minimap.width; ++x )
 +      {
 +              float xmin = minimap.mins[0] + minimap.size[0] * ( ( x + 0.5 ) / (float) minimap.width );
 +              *p++ = MiniMapSample( xmin, ymin ) / minimap.size[2];
 +      }
 +}
 +
 +static void MiniMapSharpen( int y ){
 +      int x;
 +      qboolean up = ( y > 0 );
 +      qboolean down = ( y < minimap.height - 1 );
 +      float *p = &minimap.data1f[y * minimap.width];
 +      float *q = &minimap.sharpendata1f[y * minimap.width];
 +
 +      for ( x = 0; x < minimap.width; ++x )
 +      {
 +              qboolean left = ( x > 0 );
 +              qboolean right = ( x < minimap.width - 1 );
 +              float val = p[0] * minimap.sharpen_centermult;
 +
 +              if ( left && up ) {
 +                      val += p[-1 - minimap.width] * minimap.sharpen_boxmult;
 +              }
 +              if ( left && down ) {
 +                      val += p[-1 + minimap.width] * minimap.sharpen_boxmult;
 +              }
 +              if ( right && up ) {
 +                      val += p[+1 - minimap.width] * minimap.sharpen_boxmult;
 +              }
 +              if ( right && down ) {
 +                      val += p[+1 + minimap.width] * minimap.sharpen_boxmult;
 +              }
 +
 +              if ( left ) {
 +                      val += p[-1] * minimap.sharpen_boxmult;
 +              }
 +              if ( right ) {
 +                      val += p[+1] * minimap.sharpen_boxmult;
 +              }
 +              if ( up ) {
 +                      val += p[-minimap.width] * minimap.sharpen_boxmult;
 +              }
 +              if ( down ) {
 +                      val += p[+minimap.width] * minimap.sharpen_boxmult;
 +              }
 +
 +              ++p;
 +              *q++ = val;
 +      }
 +}
 +
 +static void MiniMapContrastBoost( int y ){
 +      int x;
 +      float *q = &minimap.data1f[y * minimap.width];
 +      for ( x = 0; x < minimap.width; ++x )
 +      {
 +              *q = *q * minimap.boost / ( ( minimap.boost - 1 ) * *q + 1 );
 +              ++q;
 +      }
 +}
 +
 +static void MiniMapBrightnessContrast( int y ){
 +      int x;
 +      float *q = &minimap.data1f[y * minimap.width];
 +      for ( x = 0; x < minimap.width; ++x )
 +      {
 +              *q = *q * minimap.contrast + minimap.brightness;
 +              ++q;
 +      }
 +}
 +
 +void MiniMapMakeMinsMaxs( vec3_t mins_in, vec3_t maxs_in, float border, qboolean keepaspect ){
 +      vec3_t mins, maxs, extend;
 +      VectorCopy( mins_in, mins );
 +      VectorCopy( maxs_in, maxs );
 +
 +      // line compatible to nexuiz mapinfo
 +      Sys_Printf( "size %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
 +
 +      if ( keepaspect ) {
 +              VectorSubtract( maxs, mins, extend );
 +              if ( extend[1] > extend[0] ) {
 +                      mins[0] -= ( extend[1] - extend[0] ) * 0.5;
 +                      maxs[0] += ( extend[1] - extend[0] ) * 0.5;
 +              }
 +              else
 +              {
 +                      mins[1] -= ( extend[0] - extend[1] ) * 0.5;
 +                      maxs[1] += ( extend[0] - extend[1] ) * 0.5;
 +              }
 +      }
 +
 +      /* border: amount of black area around the image */
 +      /* input: border, 1-2*border, border but we need border/(1-2*border) */
 +
 +      VectorSubtract( maxs, mins, extend );
 +      VectorScale( extend, border / ( 1 - 2 * border ), extend );
 +
 +      VectorSubtract( mins, extend, mins );
 +      VectorAdd( maxs, extend, maxs );
 +
 +      VectorCopy( mins, minimap.mins );
 +      VectorSubtract( maxs, mins, minimap.size );
 +
 +      // line compatible to nexuiz mapinfo
 +      Sys_Printf( "size_texcoords %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
 +}
 +
 +/*
 +   MiniMapSetupBrushes()
 +   determines solid non-sky brushes in the world
 + */
 +
 +void MiniMapSetupBrushes( void ){
 +      SetupBrushesFlags( C_SOLID | C_SKY, C_SOLID, 0, 0 );
 +      // at least one must be solid
 +      // none may be sky
 +      // not all may be nodraw
 +}
 +
 +qboolean MiniMapEvaluateSampleOffsets( int *bestj, int *bestk, float *bestval ){
 +      float val, dx, dy;
 +      int j, k;
 +
 +      *bestj = *bestk = -1;
 +      *bestval = 3; /* max possible val is 2 */
 +
 +      for ( j = 0; j < minimap.samples; ++j )
 +              for ( k = j + 1; k < minimap.samples; ++k )
 +              {
 +                      dx = minimap.sample_offsets[2 * j + 0] - minimap.sample_offsets[2 * k + 0];
 +                      dy = minimap.sample_offsets[2 * j + 1] - minimap.sample_offsets[2 * k + 1];
 +                      if ( dx > +0.5 ) {
 +                              dx -= 1;
 +                      }
 +                      if ( dx < -0.5 ) {
 +                              dx += 1;
 +                      }
 +                      if ( dy > +0.5 ) {
 +                              dy -= 1;
 +                      }
 +                      if ( dy < -0.5 ) {
 +                              dy += 1;
 +                      }
 +                      val = dx * dx + dy * dy;
 +                      if ( val < *bestval ) {
 +                              *bestj = j;
 +                              *bestk = k;
 +                              *bestval = val;
 +                      }
 +              }
 +
 +      return *bestval < 3;
 +}
 +
 +void MiniMapMakeSampleOffsets(){
 +      int i, j, k, jj, kk;
 +      float val, valj, valk, sx, sy, rx, ry;
 +
 +      Sys_Printf( "Generating good sample offsets (this may take a while)...\n" );
 +
 +      /* start with entirely random samples */
 +      for ( i = 0; i < minimap.samples; ++i )
 +      {
 +              minimap.sample_offsets[2 * i + 0] = Random();
 +              minimap.sample_offsets[2 * i + 1] = Random();
 +      }
 +
 +      for ( i = 0; i < 1000; ++i )
 +      {
 +              if ( MiniMapEvaluateSampleOffsets( &j, &k, &val ) ) {
 +                      sx = minimap.sample_offsets[2 * j + 0];
 +                      sy = minimap.sample_offsets[2 * j + 1];
 +                      minimap.sample_offsets[2 * j + 0] = rx = Random();
 +                      minimap.sample_offsets[2 * j + 1] = ry = Random();
 +                      if ( !MiniMapEvaluateSampleOffsets( &jj, &kk, &valj ) ) {
 +                              valj = -1;
 +                      }
 +                      minimap.sample_offsets[2 * j + 0] = sx;
 +                      minimap.sample_offsets[2 * j + 1] = sy;
 +
 +                      sx = minimap.sample_offsets[2 * k + 0];
 +                      sy = minimap.sample_offsets[2 * k + 1];
 +                      minimap.sample_offsets[2 * k + 0] = rx;
 +                      minimap.sample_offsets[2 * k + 1] = ry;
 +                      if ( !MiniMapEvaluateSampleOffsets( &jj, &kk, &valk ) ) {
 +                              valk = -1;
 +                      }
 +                      minimap.sample_offsets[2 * k + 0] = sx;
 +                      minimap.sample_offsets[2 * k + 1] = sy;
 +
 +                      if ( valj > valk ) {
 +                              if ( valj > val ) {
 +                                      /* valj is the greatest */
 +                                      minimap.sample_offsets[2 * j + 0] = rx;
 +                                      minimap.sample_offsets[2 * j + 1] = ry;
 +                                      i = -1;
 +                              }
 +                              else
 +                              {
 +                                      /* valj is the greater and it is useless - forget it */
 +                              }
 +                      }
 +                      else
 +                      {
 +                              if ( valk > val ) {
 +                                      /* valk is the greatest */
 +                                      minimap.sample_offsets[2 * k + 0] = rx;
 +                                      minimap.sample_offsets[2 * k + 1] = ry;
 +                                      i = -1;
 +                              }
 +                              else
 +                              {
 +                                      /* valk is the greater and it is useless - forget it */
 +                              }
 +                      }
 +              }
 +              else{
 +                      break;
 +              }
 +      }
 +}
 +
 +void MergeRelativePath( char *out, const char *absolute, const char *relative ){
 +      const char *endpos = absolute + strlen( absolute );
 +      while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) )
 +              --endpos;
 +      while ( relative[0] == '.' && relative[1] == '.' && ( relative[2] == '/' || relative[2] == '\\' ) )
 +      {
 +              relative += 3;
 +              while ( endpos != absolute )
 +              {
 +                      --endpos;
 +                      if ( *endpos == '/' || *endpos == '\\' ) {
 +                              break;
 +                      }
 +              }
 +              while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) )
 +                      --endpos;
 +      }
 +      memcpy( out, absolute, endpos - absolute );
 +      out[endpos - absolute] = '/';
 +      strcpy( out + ( endpos - absolute + 1 ), relative );
 +}
 +
 +int MiniMapBSPMain( int argc, char **argv ){
 +      char minimapFilename[1024];
 +      char basename[1024];
 +      char path[1024];
 +      char relativeMinimapFilename[1024];
 +      qboolean autolevel;
 +      float minimapSharpen;
 +      float border;
 +      byte *data4b, *p;
 +      float *q;
 +      int x, y;
 +      int i;
 +      miniMapMode_t mode;
 +      vec3_t mins, maxs;
 +      qboolean keepaspect;
 +
 +      /* arg checking */
 +      if ( argc < 2 ) {
 +              Sys_Printf( "Usage: q3map [-v] -minimap [-size n] [-sharpen f] [-samples n | -random n] [-o filename.tga] [-minmax Xmin Ymin Zmin Xmax Ymax Zmax] <mapname>\n" );
 +              return 0;
 +      }
 +
 +      /* load the BSP first */
 +      strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
 +      StripExtension( source );
 +      DefaultExtension( source, ".bsp" );
 +      Sys_Printf( "Loading %s\n", source );
 +      BeginMapShaderFile( source );
 +      LoadShaderInfo();
 +      LoadBSPFile( source );
 +
 +      minimap.model = &bspModels[0];
 +      VectorCopy( minimap.model->mins, mins );
 +      VectorCopy( minimap.model->maxs, maxs );
 +
 +      *minimapFilename = 0;
 +      minimapSharpen = game->miniMapSharpen;
 +      minimap.width = minimap.height = game->miniMapSize;
 +      border = game->miniMapBorder;
 +      keepaspect = game->miniMapKeepAspect;
 +      mode = game->miniMapMode;
 +
 +      autolevel = qfalse;
 +      minimap.samples = 1;
 +      minimap.sample_offsets = NULL;
 +      minimap.boost = 1.0;
 +      minimap.brightness = 0.0;
 +      minimap.contrast = 1.0;
 +
 +      /* process arguments */
 +      for ( i = 1; i < ( argc - 1 ); i++ )
 +      {
 +              if ( !strcmp( argv[ i ],  "-size" ) ) {
 +                      minimap.width = minimap.height = atoi( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Image size set to %i\n", minimap.width );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-sharpen" ) ) {
 +                      minimapSharpen = atof( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Sharpening coefficient set to %f\n", minimapSharpen );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-samples" ) ) {
 +                      minimap.samples = atoi( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Samples set to %i\n", minimap.samples );
 +                      if ( minimap.sample_offsets ) {
 +                              free( minimap.sample_offsets );
 +                      }
 +                      minimap.sample_offsets = malloc( 2 * sizeof( *minimap.sample_offsets ) * minimap.samples );
 +                      MiniMapMakeSampleOffsets();
 +              }
 +              else if ( !strcmp( argv[ i ],  "-random" ) ) {
 +                      minimap.samples = atoi( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Random samples set to %i\n", minimap.samples );
 +                      if ( minimap.sample_offsets ) {
 +                              free( minimap.sample_offsets );
 +                      }
 +                      minimap.sample_offsets = NULL;
 +              }
 +              else if ( !strcmp( argv[ i ],  "-border" ) ) {
 +                      border = atof( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Border set to %f\n", border );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-keepaspect" ) ) {
 +                      keepaspect = qtrue;
 +                      Sys_Printf( "Keeping aspect ratio by letterboxing\n", border );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-nokeepaspect" ) ) {
 +                      keepaspect = qfalse;
 +                      Sys_Printf( "Not keeping aspect ratio\n", border );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-o" ) ) {
 +                      strcpy( minimapFilename, argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Output file name set to %s\n", minimapFilename );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-minmax" ) && i < ( argc - 7 ) ) {
 +                      mins[0] = atof( argv[i + 1] );
 +                      mins[1] = atof( argv[i + 2] );
 +                      mins[2] = atof( argv[i + 3] );
 +                      maxs[0] = atof( argv[i + 4] );
 +                      maxs[1] = atof( argv[i + 5] );
 +                      maxs[2] = atof( argv[i + 6] );
 +                      i += 6;
 +                      Sys_Printf( "Map mins/maxs overridden\n" );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-gray" ) ) {
 +                      mode = MINIMAP_MODE_GRAY;
 +                      Sys_Printf( "Writing as white-on-black image\n" );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-black" ) ) {
 +                      mode = MINIMAP_MODE_BLACK;
 +                      Sys_Printf( "Writing as black alpha image\n" );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-white" ) ) {
 +                      mode = MINIMAP_MODE_WHITE;
 +                      Sys_Printf( "Writing as white alpha image\n" );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-boost" ) && i < ( argc - 2 ) ) {
 +                      minimap.boost = atof( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Contrast boost set to %f\n", minimap.boost );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-brightness" ) && i < ( argc - 2 ) ) {
 +                      minimap.brightness = atof( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Brightness set to %f\n", minimap.brightness );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-contrast" ) && i < ( argc - 2 ) ) {
 +                      minimap.contrast = atof( argv[i + 1] );
 +                      i++;
 +                      Sys_Printf( "Contrast set to %f\n", minimap.contrast );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-autolevel" ) ) {
 +                      autolevel = qtrue;
 +                      Sys_Printf( "Auto level enabled\n", border );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-noautolevel" ) ) {
 +                      autolevel = qfalse;
 +                      Sys_Printf( "Auto level disabled\n", border );
 +              }
 +      }
 +
 +      MiniMapMakeMinsMaxs( mins, maxs, border, keepaspect );
 +
 +      if ( !*minimapFilename ) {
 +              ExtractFileBase( source, basename );
 +              ExtractFilePath( source, path );
 +              sprintf( relativeMinimapFilename, game->miniMapNameFormat, basename );
 +              MergeRelativePath( minimapFilename, path, relativeMinimapFilename );
 +              Sys_Printf( "Output file name automatically set to %s\n", minimapFilename );
 +      }
 +      ExtractFilePath( minimapFilename, path );
 +      Q_mkdir( path );
 +
 +      if ( minimapSharpen >= 0 ) {
 +              minimap.sharpen_centermult = 8 * minimapSharpen + 1;
 +              minimap.sharpen_boxmult    =    -minimapSharpen;
 +      }
 +
 +      minimap.data1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) );
 +      data4b = safe_malloc( minimap.width * minimap.height * 4 );
 +      if ( minimapSharpen >= 0 ) {
 +              minimap.sharpendata1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) );
 +      }
 +
 +      MiniMapSetupBrushes();
 +
 +      if ( minimap.samples <= 1 ) {
 +              Sys_Printf( "\n--- MiniMapNoSupersampling (%d) ---\n", minimap.height );
 +              RunThreadsOnIndividual( minimap.height, qtrue, MiniMapNoSupersampling );
 +      }
 +      else
 +      {
 +              if ( minimap.sample_offsets ) {
 +                      Sys_Printf( "\n--- MiniMapSupersampled (%d) ---\n", minimap.height );
 +                      RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSupersampled );
 +              }
 +              else
 +              {
 +                      Sys_Printf( "\n--- MiniMapRandomlySupersampled (%d) ---\n", minimap.height );
 +                      RunThreadsOnIndividual( minimap.height, qtrue, MiniMapRandomlySupersampled );
 +              }
 +      }
 +
 +      if ( minimap.boost != 1.0 ) {
 +              Sys_Printf( "\n--- MiniMapContrastBoost (%d) ---\n", minimap.height );
 +              RunThreadsOnIndividual( minimap.height, qtrue, MiniMapContrastBoost );
 +      }
 +
 +      if ( autolevel ) {
 +              Sys_Printf( "\n--- MiniMapAutoLevel (%d) ---\n", minimap.height );
 +              float mi = 1, ma = 0;
 +              float s, o;
 +
 +              // TODO threads!
 +              q = minimap.data1f;
 +              for ( y = 0; y < minimap.height; ++y )
 +                      for ( x = 0; x < minimap.width; ++x )
 +                      {
 +                              float v = *q++;
 +                              if ( v < mi ) {
 +                                      mi = v;
 +                              }
 +                              if ( v > ma ) {
 +                                      ma = v;
 +                              }
 +                      }
 +              if ( ma > mi ) {
 +                      s = 1 / ( ma - mi );
 +                      o = mi / ( ma - mi );
 +
 +                      // equations:
 +                      //   brightness + contrast * v
 +                      // after autolevel:
 +                      //   brightness + contrast * (v * s - o)
 +                      // =
 +                      //   (brightness - contrast * o) + (contrast * s) * v
 +                      minimap.brightness = minimap.brightness - minimap.contrast * o;
 +                      minimap.contrast *= s;
 +
 +                      Sys_Printf( "Auto level: Brightness changed to %f\n", minimap.brightness );
 +                      Sys_Printf( "Auto level: Contrast changed to %f\n", minimap.contrast );
 +              }
 +              else{
 +                      Sys_Printf( "Auto level: failed because all pixels are the same value\n" );
 +              }
 +      }
 +
 +      if ( minimap.brightness != 0 || minimap.contrast != 1 ) {
 +              Sys_Printf( "\n--- MiniMapBrightnessContrast (%d) ---\n", minimap.height );
 +              RunThreadsOnIndividual( minimap.height, qtrue, MiniMapBrightnessContrast );
 +      }
 +
 +      if ( minimap.sharpendata1f ) {
 +              Sys_Printf( "\n--- MiniMapSharpen (%d) ---\n", minimap.height );
 +              RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSharpen );
 +              q = minimap.sharpendata1f;
 +      }
 +      else
 +      {
 +              q = minimap.data1f;
 +      }
 +
 +      Sys_Printf( "\nConverting..." );
 +
 +      switch ( mode )
 +      {
 +      case MINIMAP_MODE_GRAY:
 +              p = data4b;
 +              for ( y = 0; y < minimap.height; ++y )
 +                      for ( x = 0; x < minimap.width; ++x )
 +                      {
 +                              byte b;
 +                              float v = *q++;
 +                              if ( v < 0 ) {
 +                                      v = 0;
 +                              }
 +                              if ( v > 255.0 / 256.0 ) {
 +                                      v = 255.0 / 256.0;
 +                              }
 +                              b = v * 256;
 +                              *p++ = b;
 +                      }
 +              Sys_Printf( " writing to %s...", minimapFilename );
 +              WriteTGAGray( minimapFilename, data4b, minimap.width, minimap.height );
 +              break;
 +      case MINIMAP_MODE_BLACK:
 +              p = data4b;
 +              for ( y = 0; y < minimap.height; ++y )
 +                      for ( x = 0; x < minimap.width; ++x )
 +                      {
 +                              byte b;
 +                              float v = *q++;
 +                              if ( v < 0 ) {
 +                                      v = 0;
 +                              }
 +                              if ( v > 255.0 / 256.0 ) {
 +                                      v = 255.0 / 256.0;
 +                              }
 +                              b = v * 256;
 +                              *p++ = 0;
 +                              *p++ = 0;
 +                              *p++ = 0;
 +                              *p++ = b;
 +                      }
 +              Sys_Printf( " writing to %s...", minimapFilename );
 +              WriteTGA( minimapFilename, data4b, minimap.width, minimap.height );
 +              break;
 +      case MINIMAP_MODE_WHITE:
 +              p = data4b;
 +              for ( y = 0; y < minimap.height; ++y )
 +                      for ( x = 0; x < minimap.width; ++x )
 +                      {
 +                              byte b;
 +                              float v = *q++;
 +                              if ( v < 0 ) {
 +                                      v = 0;
 +                              }
 +                              if ( v > 255.0 / 256.0 ) {
 +                                      v = 255.0 / 256.0;
 +                              }
 +                              b = v * 256;
 +                              *p++ = 255;
 +                              *p++ = 255;
 +                              *p++ = 255;
 +                              *p++ = b;
 +                      }
 +              Sys_Printf( " writing to %s...", minimapFilename );
 +              WriteTGA( minimapFilename, data4b, minimap.width, minimap.height );
 +              break;
 +      }
 +
 +      Sys_Printf( " done.\n" );
 +
 +      /* return to sender */
 +      return 0;
 +}
 +
 +
 +
 +
 +
 +/*
 +   MD4BlockChecksum()
 +   calculates an md4 checksum for a block of data
 + */
 +
 +static int MD4BlockChecksum( void *buffer, int length ){
 +      return Com_BlockChecksum( buffer, length );
  }
  
  /*
@@@ -996,8 -278,8 +1028,8 @@@ int AnalyzeBSP( int argc, char **argv )
                lump = (byte*) header + offset;
                lumpInt = LittleLong( (int) *( (int*) lump ) );
                lumpFloat = LittleFloat( (float) *( (float*) lump ) );
 -              memcpy( lumpString, (char*) lump, ( length < 1024 ? length : 1024 ) );
 -              lumpString[ 1024 ] = '\0';
 +              memcpy( lumpString, (char*) lump, ( (size_t)length < sizeof( lumpString ) ? (size_t)length : sizeof( lumpString ) - 1 ) );
 +              lumpString[ sizeof( lumpString ) - 1 ] = '\0';
  
                /* print basic lump info */
                Sys_Printf( "Lump:          %d\n", i );
@@@ -1115,72 -397,6 +1147,72 @@@ int BSPInfo( int count, char **fileName
  }
  
  
 +static void ExtrapolateTexcoords( const float *axyz, const float *ast, const float *bxyz, const float *bst, const float *cxyz, const float *cst, const float *axyz_new, float *ast_out, const float *bxyz_new, float *bst_out, const float *cxyz_new, float *cst_out ){
 +      vec4_t scoeffs, tcoeffs;
 +      float md;
 +      m4x4_t solvematrix;
 +
 +      vec3_t norm;
 +      vec3_t dab, dac;
 +      VectorSubtract( bxyz, axyz, dab );
 +      VectorSubtract( cxyz, axyz, dac );
 +      CrossProduct( dab, dac, norm );
 +
 +      // assume:
 +      //   s = f(x, y, z)
 +      //   s(v + norm) = s(v) when n ortho xyz
 +
 +      // s(v) = DotProduct(v, scoeffs) + scoeffs[3]
 +
 +      // solve:
 +      //   scoeffs * (axyz, 1) == ast[0]
 +      //   scoeffs * (bxyz, 1) == bst[0]
 +      //   scoeffs * (cxyz, 1) == cst[0]
 +      //   scoeffs * (norm, 0) == 0
 +      // scoeffs * [axyz, 1 | bxyz, 1 | cxyz, 1 | norm, 0] = [ast[0], bst[0], cst[0], 0]
 +      solvematrix[0] = axyz[0];
 +      solvematrix[4] = axyz[1];
 +      solvematrix[8] = axyz[2];
 +      solvematrix[12] = 1;
 +      solvematrix[1] = bxyz[0];
 +      solvematrix[5] = bxyz[1];
 +      solvematrix[9] = bxyz[2];
 +      solvematrix[13] = 1;
 +      solvematrix[2] = cxyz[0];
 +      solvematrix[6] = cxyz[1];
 +      solvematrix[10] = cxyz[2];
 +      solvematrix[14] = 1;
 +      solvematrix[3] = norm[0];
 +      solvematrix[7] = norm[1];
 +      solvematrix[11] = norm[2];
 +      solvematrix[15] = 0;
 +
 +      md = m4_det( solvematrix );
 +      if ( md * md < 1e-10 ) {
 +              Sys_Printf( "Cannot invert some matrix, some texcoords aren't extrapolated!" );
 +              return;
 +      }
 +
 +      m4x4_invert( solvematrix );
 +
 +      scoeffs[0] = ast[0];
 +      scoeffs[1] = bst[0];
 +      scoeffs[2] = cst[0];
 +      scoeffs[3] = 0;
 +      m4x4_transform_vec4( solvematrix, scoeffs );
 +      tcoeffs[0] = ast[1];
 +      tcoeffs[1] = bst[1];
 +      tcoeffs[2] = cst[1];
 +      tcoeffs[3] = 0;
 +      m4x4_transform_vec4( solvematrix, tcoeffs );
 +
 +      ast_out[0] = scoeffs[0] * axyz_new[0] + scoeffs[1] * axyz_new[1] + scoeffs[2] * axyz_new[2] + scoeffs[3];
 +      ast_out[1] = tcoeffs[0] * axyz_new[0] + tcoeffs[1] * axyz_new[1] + tcoeffs[2] * axyz_new[2] + tcoeffs[3];
 +      bst_out[0] = scoeffs[0] * bxyz_new[0] + scoeffs[1] * bxyz_new[1] + scoeffs[2] * bxyz_new[2] + scoeffs[3];
 +      bst_out[1] = tcoeffs[0] * bxyz_new[0] + tcoeffs[1] * bxyz_new[1] + tcoeffs[2] * bxyz_new[2] + tcoeffs[3];
 +      cst_out[0] = scoeffs[0] * cxyz_new[0] + scoeffs[1] * cxyz_new[1] + scoeffs[2] * cxyz_new[2] + scoeffs[3];
 +      cst_out[1] = tcoeffs[0] * cxyz_new[0] + tcoeffs[1] * cxyz_new[1] + tcoeffs[2] * cxyz_new[2] + tcoeffs[3];
 +}
  
  /*
     ScaleBSPMain()
   */
  
  int ScaleBSPMain( int argc, char **argv ){
 -      int i;
 -      float f, scale;
 +      int i, j;
 +      float f, a;
 +      vec3_t scale;
        vec3_t vec;
        char str[ 1024 ];
 +      int uniform, axis;
 +      qboolean texscale;
 +      float *old_xyzst = NULL;
 +      float spawn_ref = 0;
  
  
        /* arg checking */
 -      if ( argc < 2 ) {
 -              Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
 +      if ( argc < 3 ) {
 +              Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
                return 0;
        }
  
 +      texscale = qfalse;
 +      for ( i = 1; i < argc - 2; ++i )
 +      {
 +              if ( !strcmp( argv[i], "-tex" ) ) {
 +                      texscale = qtrue;
 +              }
 +              else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
 +                      spawn_ref = atof( argv[i + 1] );
 +                      ++i;
 +              }
 +              else{
 +                      break;
 +              }
 +      }
 +
        /* get scale */
 -      scale = atof( argv[ argc - 2 ] );
 -      if ( scale == 0.0f ) {
 -              Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
 +      // if(argc-2 >= i) // always true
 +      scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
 +      if ( argc - 3 >= i ) {
 +              scale[1] = scale[0] = atof( argv[ argc - 3 ] );
 +      }
 +      if ( argc - 4 >= i ) {
 +              scale[0] = atof( argv[ argc - 4 ] );
 +      }
 +
 +      uniform = ( ( scale[0] == scale[1] ) && ( scale[1] == scale[2] ) );
 +
 +      if ( scale[0] == 0.0f || scale[1] == 0.0f || scale[2] == 0.0f ) {
 +              Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
                Sys_Printf( "Non-zero scale value required.\n" );
                return 0;
        }
        {
                /* scale origin */
                GetVectorForKey( &entities[ i ], "origin", vec );
 -              if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) ) {
 -                      VectorScale( vec, scale, vec );
 +              if ( ( vec[ 0 ] || vec[ 1 ] || vec[ 2 ] ) ) {
 +                      if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
 +                              vec[2] += spawn_ref;
 +                      }
 +                      vec[0] *= scale[0];
 +                      vec[1] *= scale[1];
 +                      vec[2] *= scale[2];
 +                      if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
 +                              vec[2] -= spawn_ref;
 +                      }
                        sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
                        SetKeyValue( &entities[ i ], "origin", str );
                }
  
 +              a = FloatForKey( &entities[ i ], "angle" );
 +              if ( a == -1 || a == -2 ) { // z scale
 +                      axis = 2;
 +              }
 +              else if ( fabs( sin( DEG2RAD( a ) ) ) < 0.707 ) {
 +                      axis = 0;
 +              }
 +              else{
 +                      axis = 1;
 +              }
 +
                /* scale door lip */
                f = FloatForKey( &entities[ i ], "lip" );
                if ( f ) {
 -                      f *= scale;
 +                      f *= scale[axis];
                        sprintf( str, "%f", f );
                        SetKeyValue( &entities[ i ], "lip", str );
                }
 +
 +              /* scale plat height */
 +              f = FloatForKey( &entities[ i ], "height" );
 +              if ( f ) {
 +                      f *= scale[2];
 +                      sprintf( str, "%f", f );
 +                      SetKeyValue( &entities[ i ], "height", str );
 +              }
 +
 +              // TODO maybe allow a definition file for entities to specify which values are scaled how?
        }
  
        /* scale models */
        for ( i = 0; i < numBSPModels; i++ )
        {
 -              VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
 -              VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
 +              bspModels[ i ].mins[0] *= scale[0];
 +              bspModels[ i ].mins[1] *= scale[1];
 +              bspModels[ i ].mins[2] *= scale[2];
 +              bspModels[ i ].maxs[0] *= scale[0];
 +              bspModels[ i ].maxs[1] *= scale[1];
 +              bspModels[ i ].maxs[2] *= scale[2];
        }
  
        /* scale nodes */
        for ( i = 0; i < numBSPNodes; i++ )
        {
 -              VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
 -              VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
 +              bspNodes[ i ].mins[0] *= scale[0];
 +              bspNodes[ i ].mins[1] *= scale[1];
 +              bspNodes[ i ].mins[2] *= scale[2];
 +              bspNodes[ i ].maxs[0] *= scale[0];
 +              bspNodes[ i ].maxs[1] *= scale[1];
 +              bspNodes[ i ].maxs[2] *= scale[2];
        }
  
        /* scale leafs */
        for ( i = 0; i < numBSPLeafs; i++ )
        {
 -              VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
 -              VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
 +              bspLeafs[ i ].mins[0] *= scale[0];
 +              bspLeafs[ i ].mins[1] *= scale[1];
 +              bspLeafs[ i ].mins[2] *= scale[2];
 +              bspLeafs[ i ].maxs[0] *= scale[0];
 +              bspLeafs[ i ].maxs[1] *= scale[1];
 +              bspLeafs[ i ].maxs[2] *= scale[2];
 +      }
 +
 +      if ( texscale ) {
 +              Sys_Printf( "Using texture unlocking (and probably breaking texture alignment a lot)\n" );
 +              old_xyzst = safe_malloc( sizeof( *old_xyzst ) * numBSPDrawVerts * 5 );
 +              for ( i = 0; i < numBSPDrawVerts; i++ )
 +              {
 +                      old_xyzst[5 * i + 0] = bspDrawVerts[i].xyz[0];
 +                      old_xyzst[5 * i + 1] = bspDrawVerts[i].xyz[1];
 +                      old_xyzst[5 * i + 2] = bspDrawVerts[i].xyz[2];
 +                      old_xyzst[5 * i + 3] = bspDrawVerts[i].st[0];
 +                      old_xyzst[5 * i + 4] = bspDrawVerts[i].st[1];
 +              }
        }
  
        /* scale drawverts */
        for ( i = 0; i < numBSPDrawVerts; i++ )
 -              VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
 +      {
 +              bspDrawVerts[i].xyz[0] *= scale[0];
 +              bspDrawVerts[i].xyz[1] *= scale[1];
 +              bspDrawVerts[i].xyz[2] *= scale[2];
 +              bspDrawVerts[i].normal[0] /= scale[0];
 +              bspDrawVerts[i].normal[1] /= scale[1];
 +              bspDrawVerts[i].normal[2] /= scale[2];
 +              VectorNormalize( bspDrawVerts[i].normal, bspDrawVerts[i].normal );
 +      }
 +
 +      if ( texscale ) {
 +              for ( i = 0; i < numBSPDrawSurfaces; i++ )
 +              {
 +                      switch ( bspDrawSurfaces[i].surfaceType )
 +                      {
 +                      case SURFACE_FACE:
 +                      case SURFACE_META:
 +                              if ( bspDrawSurfaces[i].numIndexes % 3 ) {
 +                                      Error( "Not a triangulation!" );
 +                              }
 +                              for ( j = bspDrawSurfaces[i].firstIndex; j < bspDrawSurfaces[i].firstIndex + bspDrawSurfaces[i].numIndexes; j += 3 )
 +                              {
 +                                      int ia = bspDrawIndexes[j] + bspDrawSurfaces[i].firstVert, ib = bspDrawIndexes[j + 1] + bspDrawSurfaces[i].firstVert, ic = bspDrawIndexes[j + 2] + bspDrawSurfaces[i].firstVert;
 +                                      bspDrawVert_t *a = &bspDrawVerts[ia], *b = &bspDrawVerts[ib], *c = &bspDrawVerts[ic];
 +                                      float *oa = &old_xyzst[ia * 5], *ob = &old_xyzst[ib * 5], *oc = &old_xyzst[ic * 5];
 +                                      // extrapolate:
 +                                      //   a->xyz -> oa
 +                                      //   b->xyz -> ob
 +                                      //   c->xyz -> oc
 +                                      ExtrapolateTexcoords(
 +                                              &oa[0], &oa[3],
 +                                              &ob[0], &ob[3],
 +                                              &oc[0], &oc[3],
 +                                              a->xyz, a->st,
 +                                              b->xyz, b->st,
 +                                              c->xyz, c->st );
 +                              }
 +                              break;
 +                      }
 +              }
 +      }
  
        /* scale planes */
 -      for ( i = 0; i < numBSPPlanes; i++ )
 -              bspPlanes[ i ].dist *= scale;
 +      if ( uniform ) {
 +              for ( i = 0; i < numBSPPlanes; i++ )
 +              {
 +                      bspPlanes[ i ].dist *= scale[0];
 +              }
 +      }
 +      else
 +      {
 +              for ( i = 0; i < numBSPPlanes; i++ )
 +              {
 +                      bspPlanes[ i ].normal[0] /= scale[0];
 +                      bspPlanes[ i ].normal[1] /= scale[1];
 +                      bspPlanes[ i ].normal[2] /= scale[2];
 +                      f = 1 / VectorLength( bspPlanes[i].normal );
 +                      VectorScale( bspPlanes[i].normal, f, bspPlanes[i].normal );
 +                      bspPlanes[ i ].dist *= f;
 +              }
 +      }
  
        /* scale gridsize */
        GetVectorForKey( &entities[ 0 ], "gridsize", vec );
        if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) == 0.0f ) {
                VectorCopy( gridSize, vec );
        }
 -      VectorScale( vec, scale, vec );
 +      vec[0] *= scale[0];
 +      vec[1] *= scale[1];
 +      vec[2] *= scale[2];
        sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
        SetKeyValue( &entities[ 0 ], "gridsize", str );
  
 +      /* inject command line parameters */
 +      InjectCommandLine( argv, 0, argc - 1 );
 +
        /* write the bsp */
        UnparseEntities();
        StripExtension( source );
  }
  
  
 +/*
 +   PseudoCompileBSP()
 +   a stripped down ProcessModels
 + */
 +void PseudoCompileBSP( qboolean need_tree ){
 +      int models;
 +      char modelValue[10];
 +      entity_t *entity;
 +      face_t *faces;
 +      tree_t *tree;
 +      node_t *node;
 +      brush_t *brush;
 +      side_t *side;
 +      int i;
 +
 +      SetDrawSurfacesBuffer();
 +      mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
 +      memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
 +      numMapDrawSurfs = 0;
 +
 +      BeginBSPFile();
 +      models = 1;
 +      for ( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
 +      {
 +              /* get entity */
 +              entity = &entities[ mapEntityNum ];
 +              if ( entity->brushes == NULL && entity->patches == NULL ) {
 +                      continue;
 +              }
 +
 +              if ( mapEntityNum != 0 ) {
 +                      sprintf( modelValue, "*%d", models++ );
 +                      SetKeyValue( entity, "model", modelValue );
 +              }
 +
 +              /* process the model */
 +              Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
 +              BeginModel();
 +
 +              entity->firstDrawSurf = numMapDrawSurfs;
 +
 +              ClearMetaTriangles();
 +              PatchMapDrawSurfs( entity );
 +
 +              if ( mapEntityNum == 0 && need_tree ) {
 +                      faces = MakeStructuralBSPFaceList( entities[0].brushes );
 +                      tree = FaceBSP( faces );
 +                      node = tree->headnode;
 +              }
 +              else
 +              {
 +                      node = AllocNode();
 +                      node->planenum = PLANENUM_LEAF;
 +                      tree = AllocTree();
 +                      tree->headnode = node;
 +              }
 +
 +              /* a minimized ClipSidesIntoTree */
 +              for ( brush = entity->brushes; brush; brush = brush->next )
 +              {
 +                      /* walk the brush sides */
 +                      for ( i = 0; i < brush->numsides; i++ )
 +                      {
 +                              /* get side */
 +                              side = &brush->sides[ i ];
 +                              if ( side->winding == NULL ) {
 +                                      continue;
 +                              }
 +                              /* shader? */
 +                              if ( side->shaderInfo == NULL ) {
 +                                      continue;
 +                              }
 +                              /* save this winding as a visible surface */
 +                              DrawSurfaceForSide( entity, brush, side, side->winding );
 +                      }
 +              }
 +
 +              if ( meta ) {
 +                      ClassifyEntitySurfaces( entity );
 +                      MakeEntityDecals( entity );
 +                      MakeEntityMetaTriangles( entity );
 +                      SmoothMetaTriangles();
 +                      MergeMetaTriangles();
 +              }
 +              FilterDrawsurfsIntoTree( entity, tree );
 +
 +              FilterStructuralBrushesIntoTree( entity, tree );
 +              FilterDetailBrushesIntoTree( entity, tree );
 +
 +              EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes );
 +              EndModel( entity, node );
 +      }
 +      EndBSPFile( qfalse );
 +}
  
  /*
     ConvertBSPMain()
@@@ -1541,20 -518,15 +1573,20 @@@ int ConvertBSPMain( int argc, char **ar
        int i;
        int ( *convertFunc )( char * );
        game_t  *convertGame;
 +      char ext[1024];
 +      qboolean map_allowed, force_bsp, force_map;
  
  
        /* set default */
        convertFunc = ConvertBSPToASE;
        convertGame = NULL;
 +      map_allowed = qfalse;
 +      force_bsp = qfalse;
 +      force_map = qfalse;
  
        /* arg checking */
        if ( argc < 1 ) {
 -              Sys_Printf( "Usage: q3map -convert [-format <ase|map>] [-v] <mapname>\n" );
 +              Sys_Printf( "Usage: q3map -convert [-format <ase|obj|map_bp|map>] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] <mapname>\n" );
                return 0;
        }
  
                        i++;
                        if ( !Q_stricmp( argv[ i ], "ase" ) ) {
                                convertFunc = ConvertBSPToASE;
 +                              map_allowed = qfalse;
 +                      }
 +                      else if ( !Q_stricmp( argv[ i ], "obj" ) ) {
 +                              convertFunc = ConvertBSPToOBJ;
 +                              map_allowed = qfalse;
 +                      }
 +                      else if ( !Q_stricmp( argv[ i ], "map_bp" ) ) {
 +                              convertFunc = ConvertBSPToMap_BP;
 +                              map_allowed = qtrue;
                        }
                        else if ( !Q_stricmp( argv[ i ], "map" ) ) {
                                convertFunc = ConvertBSPToMap;
 +                              map_allowed = qtrue;
                        }
                        else
                        {
                                convertGame = GetGame( argv[ i ] );
 +                              map_allowed = qfalse;
                                if ( convertGame == NULL ) {
                                        Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
                                }
                        }
                }
 +              else if ( !strcmp( argv[ i ],  "-ne" ) ) {
 +                      normalEpsilon = atof( argv[ i + 1 ] );
 +                      i++;
 +                      Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-de" ) ) {
 +                      distanceEpsilon = atof( argv[ i + 1 ] );
 +                      i++;
 +                      Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
 +              }
 +              else if ( !strcmp( argv[ i ],  "-shaderasbitmap" ) || !strcmp( argv[ i ],  "-shadersasbitmap" ) ) {
 +                      shadersAsBitmap = qtrue;
 +              }
 +              else if ( !strcmp( argv[ i ],  "-lightmapastexcoord" ) || !strcmp( argv[ i ],  "-lightmapsastexcoord" ) ) {
 +                      lightmapsAsTexcoord = qtrue;
 +              }
 +              else if ( !strcmp( argv[ i ],  "-deluxemapastexcoord" ) || !strcmp( argv[ i ],  "-deluxemapsastexcoord" ) ) {
 +                      lightmapsAsTexcoord = qtrue;
 +                      deluxemap = qtrue;
 +              }
 +              else if ( !strcmp( argv[ i ],  "-readbsp" ) ) {
 +                      force_bsp = qtrue;
 +              }
 +              else if ( !strcmp( argv[ i ],  "-readmap" ) ) {
 +                      force_map = qtrue;
 +              }
 +              else if ( !strcmp( argv[ i ],  "-meta" ) ) {
 +                      meta = qtrue;
 +              }
 +              else if ( !strcmp( argv[ i ],  "-patchmeta" ) ) {
 +                      meta = qtrue;
 +                      patchMeta = qtrue;
 +              }
        }
  
 -      /* clean up map name */
 -      strcpy( source, ExpandArg( argv[ i ] ) );
 -      StripExtension( source );
 -      DefaultExtension( source, ".bsp" );
 -
        LoadShaderInfo();
  
 -      Sys_Printf( "Loading %s\n", source );
 -
 -      /* ydnar: load surface file */
 -      //%     LoadSurfaceExtraFile( source );
 +      /* clean up map name */
 +      strcpy( source, ExpandArg( argv[i] ) );
 +      ExtractFileExtension( source, ext );
  
 -      LoadBSPFile( source );
 +      if ( !map_allowed && !force_map ) {
 +              force_bsp = qtrue;
 +      }
  
 -      /* parse bsp entities */
 -      ParseEntities();
 +      if ( force_map || ( !force_bsp && !Q_stricmp( ext, "map" ) && map_allowed ) ) {
 +              if ( !map_allowed ) {
 +                      Sys_Printf( "WARNING: the requested conversion should not be done from .map files. Compile a .bsp first.\n" );
 +              }
 +              StripExtension( source );
 +              DefaultExtension( source, ".map" );
 +              Sys_Printf( "Loading %s\n", source );
 +              LoadMapFile( source, qfalse, convertGame == NULL );
 +              PseudoCompileBSP( convertGame != NULL );
 +      }
 +      else
 +      {
 +              StripExtension( source );
 +              DefaultExtension( source, ".bsp" );
 +              Sys_Printf( "Loading %s\n", source );
 +              LoadBSPFile( source );
 +              ParseEntities();
 +      }
  
        /* bsp format convert? */
        if ( convertGame != NULL ) {
@@@ -1709,10 -625,8 +1741,10 @@@ int main( int argc, char **argv )
  
                /* verbose */
                else if ( !strcmp( argv[ i ], "-v" ) ) {
 -                      verbose = qtrue;
 -                      argv[ i ] = NULL;
 +                      if ( !verbose ) {
 +                              verbose = qtrue;
 +                              argv[ i ] = NULL;
 +                      }
                }
  
                /* force */
  
        Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
        Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
 -      Sys_Printf( "GtkRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
 +      Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
        Sys_Printf( "%s\n", Q3MAP_MOTD );
  
        /* ydnar: new path initialization */
        InitPaths( &argc, argv );
  
 +      /* set game options */
 +      if ( !patchSubdivisions ) {
 +              patchSubdivisions = game->patchSubdivisions;
 +      }
 +
        /* check if we have enough options left to attempt something */
        if ( argc < 2 ) {
                Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
                r = ConvertBSPMain( argc - 1, argv + 1 );
        }
  
 +      /* div0: minimap */
 +      else if ( !strcmp( argv[ 1 ], "-minimap" ) ) {
 +              r = MiniMapBSPMain( argc - 1, argv + 1 );
 +      }
 +
        /* ydnar: otherwise create a bsp */
        else{
                r = BSPMain( argc, argv );
index 2591c5bf45b54ba9e7467bd43a42e9f9f139ae28,901f07fc3f64db841221fd26e82558564fab6d29..07ebc31b1e154dc2ade01a871560ad49a3b1635a
@@@ -49,7 -49,7 +49,7 @@@ int numBasePaths
  char                    *basePaths[ MAX_BASE_PATHS ];
  int numGamePaths;
  char                    *gamePaths[ MAX_GAME_PATHS ];
 -
 +char                    *homeBasePath = NULL;
  
  
  /*
@@@ -66,32 -66,23 +66,27 @@@ char *LokiGetHomeDir( void )
        #ifndef Q_UNIX
        return NULL;
        #else
+       static char     buf[ 4096 ];
+       struct passwd   pw, *pwp;
        char            *home;
-       uid_t id;
-       struct passwd   *pwd;
 +      static char homeBuf[MAX_OS_PATH];
  
  
        /* get the home environment variable */
        home = getenv( "HOME" );
-       if ( home == NULL ) {
-               /* do some more digging */
-               id = getuid();
-               setpwent();
-               while ( ( pwd = getpwent() ) != NULL )
-               {
-                       if ( pwd->pw_uid == id ) {
-                               home = pwd->pw_dir;
-                               break;
-                       }
 -      if ( home ) {
 -              return Q_strncpyz( buf, home, sizeof( buf ) );
 -      }
+       /* look up home dir in password database */
 -      if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
 -              return pw.pw_dir;
++      if(!home)
++      {
++              if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
++                      return pw.pw_dir;
 +              }
-               endpwent();
        }
  
 -      return NULL;
 +      snprintf( homeBuf, sizeof( homeBuf ), "%s/.", home );
 +
 +      /* return it */
 +      return homeBuf;
        #endif
  }
  
   */
  
  void LokiInitPaths( char *argv0 ){
 +      char        *home;
 +
 +      if ( !homePath ) {
 +              /* get home dir */
 +              home = LokiGetHomeDir();
 +              if ( home == NULL ) {
 +                      home = ".";
 +              }
 +
 +              /* set home path */
 +              homePath = home;
 +      }
 +      else{
 +              home = homePath;
 +      }
 +
        #ifndef Q_UNIX
        /* this is kinda crap, but hey */
        strcpy( installPath, "../" );
        #else
        char temp[ MAX_OS_PATH ];
 -      char        *home;
 +      char last0[ 2 ];
        char        *path;
        char        *last;
        qboolean found;
  
  
 -      /* get home dir */
 -      home = LokiGetHomeDir();
 -      if ( home == NULL ) {
 -              home = ".";
 -      }
 -
+       path = getenv( "PATH" );
        /* do some path divining */
-       strcpy( temp, argv0 );
-       if ( strrchr( argv0, '/' ) ) {
+       Q_strncpyz( temp, argv0, sizeof( temp ) );
+       if ( strrchr( temp, '/' ) ) {
                argv0 = strrchr( argv0, '/' ) + 1;
        }
-       else
-       {
-               /* get path environment variable */
-               path = getenv( "PATH" );
-               /* minor setup */
-               last = last0;
-               last[ 0 ] = path[ 0 ];
-               last[ 1 ] = '\0';
+       else if ( path ) {
                found = qfalse;
+               last = path;
  
                /* go through each : segment of path */
                while ( last[ 0 ] != '\0' && found == qfalse )
  
                        /* found home dir candidate */
                        if ( *path == '~' ) {
-                               strcpy( temp, home );
+                               Q_strncpyz( temp, home, sizeof( temp ) );
                                path++;
                        }
  
                        /* concatenate */
                        if ( last > ( path + 1 ) ) {
-                               strncat( temp, path, ( last - path ) );
-                               strcat( temp, "/" );
+                               Q_strncat( temp, sizeof( temp ), path, ( last - path ) );
+                               Q_strcat( temp, sizeof( temp ), "/" );
                        }
-                       strcat( temp, "./" );
-                       strcat( temp, argv0 );
+                       Q_strcat( temp, sizeof( temp ), "./" );
+                       Q_strcat( temp, sizeof( temp ), argv0 );
  
                        /* verify the path */
                        if ( access( temp, X_OK ) == 0 ) {
                *( strrchr( installPath, '/' ) ) = '\0';
                *( strrchr( installPath, '/' ) + 1 ) = '\0';
        }
 -
 -      /* set home path */
 -      homePath = home;
        #endif
  }
  
@@@ -277,52 -256,29 +267,52 @@@ void AddBasePath( char *path )
   */
  
  void AddHomeBasePath( char *path ){
 -      #ifdef Q_UNIX
        int i;
        char temp[ MAX_OS_PATH ];
 +      int homePathLen;
  
 +      if ( !homePath ) {
 +              return;
 +      }
  
        /* dummy check */
        if ( path == NULL || path[ 0 ] == '\0' ) {
                return;
        }
  
 +      /* strip leading dot, if homePath does not end in /. */
 +      homePathLen = strlen( homePath );
 +      if ( !strcmp( path, "." ) ) {
 +              /* -fs_homebase . means that -fs_home is to be used as is */
 +              strcpy( temp, homePath );
 +      }
 +      else if ( homePathLen >= 2 && !strcmp( homePath + homePathLen - 2, "/." ) ) {
 +              /* remove trailing /. of homePath */
 +              homePathLen -= 2;
 +
 +              /* concatenate home dir and path */
 +              sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
 +      }
 +      else
 +      {
 +              /* remove leading . of path */
 +              if ( path[0] == '.' ) {
 +                      ++path;
 +              }
 +
 +              /* concatenate home dir and path */
 +              sprintf( temp, "%s/%s", homePath, path );
 +      }
 +
        /* make a hole */
 -      for ( i = 0; i < ( MAX_BASE_PATHS - 1 ); i++ )
 +      for ( i = ( MAX_BASE_PATHS - 2 ); i >= 0; i-- )
                basePaths[ i + 1 ] = basePaths[ i ];
  
 -      /* concatenate home dir and path */
 -      sprintf( temp, "%s/%s", homePath, path );
 -
        /* add it to the list */
        basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
        strcpy( basePaths[ 0 ], temp );
        CleanPath( basePaths[ 0 ] );
        numBasePaths++;
 -      #endif
  }
  
  
@@@ -405,20 -361,6 +395,20 @@@ void InitPaths( int *argc, char **argv 
                        argv[ i ] = NULL;
                }
  
 +              /* -fs_forbiddenpath */
 +              else if ( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 ) {
 +                      if ( ++i >= *argc ) {
 +                              Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
 +                      }
 +                      argv[ i - 1 ] = NULL;
 +                      if ( g_numForbiddenDirs < VFS_MAXDIRS ) {
 +                              strncpy( g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX );
 +                              g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
 +                              ++g_numForbiddenDirs;
 +                      }
 +                      argv[ i ] = NULL;
 +              }
 +
                /* -fs_basepath */
                else if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
                        if ( ++i >= *argc ) {
                        AddGamePath( argv[ i ] );
                        argv[ i ] = NULL;
                }
 +
 +              /* -fs_home */
 +              else if ( strcmp( argv[ i ], "-fs_home" ) == 0 ) {
 +                      if ( ++i >= *argc ) {
 +                              Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
 +                      }
 +                      argv[ i - 1 ] = NULL;
 +                      homePath = argv[i];
 +                      argv[ i ] = NULL;
 +              }
 +
 +              /* -fs_homebase */
 +              else if ( strcmp( argv[ i ], "-fs_homebase" ) == 0 ) {
 +                      if ( ++i >= *argc ) {
 +                              Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
 +                      }
 +                      argv[ i - 1 ] = NULL;
 +                      homeBasePath = argv[i];
 +                      argv[ i ] = NULL;
 +              }
 +
 +              /* -fs_homepath - sets both of them */
 +              else if ( strcmp( argv[ i ], "-fs_homepath" ) == 0 ) {
 +                      if ( ++i >= *argc ) {
 +                              Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
 +                      }
 +                      argv[ i - 1 ] = NULL;
 +                      homePath = argv[i];
 +                      homeBasePath = ".";
 +                      argv[ i ] = NULL;
 +              }
        }
  
        /* remove processed arguments */
        }
  
        /* this only affects unix */
 -      AddHomeBasePath( game->homeBasePath );
 +      if ( homeBasePath ) {
 +              AddHomeBasePath( homeBasePath );
 +      }
 +      else{
 +              AddHomeBasePath( game->homeBasePath );
 +      }
  
        /* initialize vfs paths */
        if ( numBasePaths > MAX_BASE_PATHS ) {
index 935d1c7f078baa9ff936670d85510cea5fe584b2,245e34c6cb34298ff989684bcf3db4adbc129f32..bbb3e76e73518d27b8bc12ef7a42ca46f51b2188
  
  
  /* version */
 -#define Q3MAP_VERSION   "2.5.17"
 -#define Q3MAP_MOTD      "Last one turns the lights off"
 +#ifndef Q3MAP_VERSION
 +#error no Q3MAP_VERSION defined
 +#endif
 +#define Q3MAP_MOTD      "Your map saw the pretty lights from q3map2's BFG"
 +
  
  
  
@@@ -71,6 -68,7 +71,6 @@@
  #include "cmdlib.h"
  #include "mathlib.h"
  #include "md5lib.h"
 -#include "md4lib.h"
  #include "ddslib.h"
  
  #include "picomodel.h"
  #include "inout.h"
  #include "vfs.h"
  #include "png.h"
 -
 +#include "md4.h"
  #include <stdlib.h>
  
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
+ #define MAX(a, b) ((a) > (b) ? (a) : (b))
  
  
  /* -------------------------------------------------------------------------------
  #define Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES   1
  #define Q3MAP2_EXPERIMENTAL_SNAP_NORMAL_FIX     1
  #define Q3MAP2_EXPERIMENTAL_SNAP_PLANE_FIX      1
 -#define Q3MAP2_EXPERIMENTAL_MODEL_CLIPPING_FIX      1
  
  /* general */
  #define MAX_QPATH               64
  #define DEF_RADIOSITY_BOUNCE    1.0f    /* ydnar: default to 100% re-emitted light */
  
  #define MAX_SHADER_INFO         8192
 -#define MAX_CUST_SURFACEPARMS   64
 +#define MAX_CUST_SURFACEPARMS   256
  
  #define SHADER_MAX_VERTEXES     1000
  #define SHADER_MAX_INDEXES      ( 6 * SHADER_MAX_VERTEXES )
  /* bsp */
  #define MAX_PATCH_SIZE          32
  #define MAX_BRUSH_SIDES         1024
 -#define MAX_BUILD_SIDES         300
 +#define MAX_BUILD_SIDES         1024
  
  #define MAX_EXPANDED_AXIS       128
  
  #define HINT_PRIORITY           1000        /* ydnar: force hint splits first and antiportal/areaportal splits last */
  #define ANTIPORTAL_PRIORITY     -1000
  #define AREAPORTAL_PRIORITY     -1000
 +#define DETAIL_PRIORITY     -3000
  
  #define PSIDE_FRONT             1
  #define PSIDE_BACK              2
  
  #define PORTALFILE              "PRT1"
  
 -#define MAX_PORTALS             32768
 +#define MAX_PORTALS             0x20000 /* same as MAX_MAP_PORTALS */
  #define MAX_SEPERATORS          MAX_POINTS_ON_WINDING
  #define MAX_POINTS_ON_FIXED_WINDING 24  /* ydnar: increased this from 12 at the expense of more memory */
 -#define MAX_PORTALS_ON_LEAF     128
 +#define MAX_PORTALS_ON_LEAF     1024
  
  
  /* light */
  #define LIGHT_FAST_TEMP         512
  #define LIGHT_FAST_ACTUAL       ( LIGHT_FAST | LIGHT_FAST_TEMP )
  #define LIGHT_NEGATIVE          1024
 +#define LIGHT_UNNORMALIZED      2048    /* vortex: do not normalize _color */
  
  #define LIGHT_SUN_DEFAULT       ( LIGHT_ATTEN_ANGLE | LIGHT_GRID | LIGHT_SURFACES )
  #define LIGHT_AREA_DEFAULT      ( LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES )    /* q3a and wolf are the same */
  #define GRID_EPSILON            0.0f
  
  #define DEFAULT_LIGHTMAP_SAMPLE_SIZE    16
 +#define DEFAULT_LIGHTMAP_MIN_SAMPLE_SIZE    0
  #define DEFAULT_LIGHTMAP_SAMPLE_OFFSET  1.0f
  #define DEFAULT_SUBDIVIDE_THRESHOLD     1.0f
  
  #define BSP_LUXEL_SIZE          3
  #define RAD_LUXEL_SIZE          3
  #define SUPER_LUXEL_SIZE        4
 +#define SUPER_FLAG_SIZE         4
 +#define FLAG_FORCE_SUBSAMPLING 1
 +#define FLAG_ALREADY_SUBSAMPLED 2
  #define SUPER_ORIGIN_SIZE       3
  #define SUPER_NORMAL_SIZE       4
  #define SUPER_DELUXEL_SIZE      3
  #define BSP_DELUXEL_SIZE        3
 +#define SUPER_FLOODLIGHT_SIZE   4
  
  #define VERTEX_LUXEL( s, v )    ( vertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
  #define RAD_VERTEX_LUXEL( s, v )( radVertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
  #define BSP_LUXEL( s, x, y )    ( lm->bspLuxels[ s ] + ( ( ( ( y ) * lm->w ) + ( x ) ) * BSP_LUXEL_SIZE ) )
  #define RAD_LUXEL( s, x, y )    ( lm->radLuxels[ s ] + ( ( ( ( y ) * lm->w ) + ( x ) ) * RAD_LUXEL_SIZE ) )
  #define SUPER_LUXEL( s, x, y )  ( lm->superLuxels[ s ] + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_LUXEL_SIZE ) )
 +#define SUPER_FLAG( x, y )  ( lm->superFlags + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_FLAG_SIZE ) )
  #define SUPER_DELUXEL( x, y )   ( lm->superDeluxels + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_DELUXEL_SIZE ) )
  #define BSP_DELUXEL( x, y )     ( lm->bspDeluxels + ( ( ( ( y ) * lm->w ) + ( x ) ) * BSP_DELUXEL_SIZE ) )
  #define SUPER_CLUSTER( x, y )   ( lm->superClusters + ( ( ( y ) * lm->sw ) + ( x ) ) )
  #define SUPER_ORIGIN( x, y )    ( lm->superOrigins + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_ORIGIN_SIZE ) )
  #define SUPER_NORMAL( x, y )    ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) )
  #define SUPER_DIRT( x, y )      ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) + 3 )   /* stash dirtyness in normal[ 3 ] */
 +#define SUPER_FLOODLIGHT( x, y )    ( lm->superFloodLight + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_FLOODLIGHT_SIZE ) )
  
  
  
  #define MAX_LIGHTMAP_SHADERS    256
  
  /* ok to increase these at the expense of more memory */
 -#define MAX_MAP_MODELS          0x400
 -#define MAX_MAP_BRUSHES         0x10000
 -#define MAX_MAP_ENTITIES        0x1000      //%       0x800   /* ydnar */
 -#define MAX_MAP_ENTSTRING       0x80000     //%       0x40000 /* ydnar */
 -#define MAX_MAP_SHADERS         0x800       //%       0x400   /* ydnar */
 -
  #define MAX_MAP_AREAS           0x100       /* MAX_MAP_AREA_BYTES in q_shared must match! */
  #define MAX_MAP_FOGS            30          //& 0x100 /* RBSP (32 - world fog - goggles) */
 -#define MAX_MAP_PLANES          0x100000    //%       0x20000 /* ydnar for md */
 -#define MAX_MAP_NODES           0x20000
 -#define MAX_MAP_BRUSHSIDES      0x100000    //%       0x20000 /* ydnar */
  #define MAX_MAP_LEAFS           0x20000
 -#define MAX_MAP_LEAFFACES       0x100000    //%       0x20000 /* ydnar */
 -#define MAX_MAP_LEAFBRUSHES     0x40000
  #define MAX_MAP_PORTALS         0x20000
  #define MAX_MAP_LIGHTING        0x800000
  #define MAX_MAP_LIGHTGRID       0x100000    //%       0x800000 /* ydnar: set to points, not bytes */
 -#define MAX_MAP_VISIBILITY      0x200000
 +#define MAX_MAP_VISCLUSTERS     0x4000 // <= MAX_MAP_LEAFS
 +#define MAX_MAP_VISIBILITY      ( VIS_HEADER_SIZE + MAX_MAP_VISCLUSTERS * ( ( ( MAX_MAP_VISCLUSTERS + 63 ) & ~63 ) >> 3 ) )
  
  #define MAX_MAP_DRAW_SURFS      0x20000
 -#define MAX_MAP_DRAW_VERTS      0x100000
 -#define MAX_MAP_DRAW_INDEXES    0x80000
  
  #define MAX_MAP_ADVERTISEMENTS  30
  
@@@ -523,7 -527,7 +525,7 @@@ typedef struct 
     ------------------------------------------------------------------------------- */
  
  /* ydnar: for smaller structs */
 -typedef char qb_t;
 +typedef unsigned char qb_t;
  
  
  /* ydnar: for q3map_tcMod */
@@@ -540,13 -544,6 +542,13 @@@ typedef struct surfaceParm_
  }
  surfaceParm_t;
  
 +typedef enum
 +{
 +      MINIMAP_MODE_GRAY,
 +      MINIMAP_MODE_BLACK,
 +      MINIMAP_MODE_WHITE
 +}
 +miniMapMode_t;
  
  typedef struct game_s
  {
        qboolean wolfLight;                                 /* when true, lights work like wolf q3map  */
        int lightmapSize;                                   /* bsp lightmap width/height */
        float lightmapGamma;                                /* default lightmap gamma */
 +      qboolean lightmapsRGB;                              /* default lightmap sRGB mode */
 +      qboolean texturesRGB;                               /* default texture sRGB mode */
 +      qboolean colorsRGB;                             /* default color sRGB mode */
 +      float lightmapExposure;                             /* default lightmap exposure */
        float lightmapCompensate;                           /* default lightmap compensate value */
 +      float gridScale;                                    /* vortex: default lightgrid scale (affects both directional and ambient spectres) */
 +      float gridAmbientScale;                             /* vortex: default lightgrid ambient spectre scale */
 +      qboolean lightAngleHL;                              /* jal: use half-lambert curve for light angle attenuation */
 +      qboolean noStyles;                                  /* use lightstyles hack or not */
 +      qboolean keepLights;                                /* keep light entities on bsp */
 +      int patchSubdivisions;                              /* default patch subdivisions tolerance */
 +      qboolean patchShadows;                              /* patch casting enabled */
 +      qboolean deluxeMap;                                 /* compile deluxemaps */
 +      int deluxeMode;                                     /* deluxemap mode (0 - modelspace, 1 - tangentspace with renormalization, 2 - tangentspace without renormalization) */
 +      int miniMapSize;                                    /* minimap size */
 +      float miniMapSharpen;                               /* minimap sharpening coefficient */
 +      float miniMapBorder;                                /* minimap border amount */
 +      qboolean miniMapKeepAspect;                         /* minimap keep aspect ratio by letterboxing */
 +      miniMapMode_t miniMapMode;                          /* minimap mode */
 +      char                *miniMapNameFormat;             /* minimap name format */
        char                *bspIdent;                      /* 4-letter bsp file prefix */
        int bspVersion;                                     /* bsp version to use */
        qboolean lumpSwap;                                  /* cod-style len/ofs order */
@@@ -649,14 -627,6 +651,14 @@@ typedef struct remap_
  }
  remap_t;
  
 +typedef struct skinfile_s
 +{
 +      struct skinfile_s   *next;
 +      char name[ 1024 ];
 +      char to[ MAX_QPATH ];
 +}
 +skinfile_t;
 +
  
  /* wingdi.h hack, it's the same: 0 */
  #undef CM_NONE
@@@ -671,12 -641,8 +673,12 @@@ typedef enu
        CM_ALPHA_SCALE,
        CM_COLOR_DOT_PRODUCT,
        CM_ALPHA_DOT_PRODUCT,
 +      CM_COLOR_DOT_PRODUCT_SCALE,
 +      CM_ALPHA_DOT_PRODUCT_SCALE,
        CM_COLOR_DOT_PRODUCT_2,
 -      CM_ALPHA_DOT_PRODUCT_2
 +      CM_ALPHA_DOT_PRODUCT_2,
 +      CM_COLOR_DOT_PRODUCT_2_SCALE,
 +      CM_ALPHA_DOT_PRODUCT_2_SCALE
  }
  colorModType_t;
  
@@@ -713,7 -679,6 +715,7 @@@ typedef struct shaderInfo_
        char                *backShader;                    /* for surfaces that generate different front and back passes */
        char                *cloneShader;                   /* ydnar: for cloning of a surface */
        char                *remapShader;                   /* ydnar: remap a shader in final stage */
 +      char                *deprecateShader;               /* vortex: shader is deprecated and replaced by this on use */
  
        surfaceModel_t      *surfaceModel;                  /* ydnar: for distribution of models */
        foliage_t           *foliage;                       /* ydnar/splash damage: wolf et foliage */
        qb_t noFog;                                         /* ydnar: supress fogging */
        qb_t clipModel;                                     /* ydnar: solid model hack */
        qb_t noVertexLight;                                 /* ydnar: leave vertex color alone */
 +      qb_t noDirty;                                       /* jal: do not apply the dirty pass to this surface */
  
        byte styleMarker;                                   /* ydnar: light styles hack */
  
        vec3_t averageColor;
        byte lightStyle;
  
 +      /* vortex: per-surface floodlight */
 +      float floodlightDirectionScale;
 +      vec3_t floodlightRGB;
 +      float floodlightIntensity;
 +      float floodlightDistance;
 +
        qb_t lmMergable;                                    /* ydnar */
        int lmCustomWidth, lmCustomHeight;                  /* ydnar */
        float lmBrightness;                                 /* ydnar */
@@@ -827,7 -785,7 +829,7 @@@ typedef struct face_
        struct face_s       *next;
        int planenum;
        int priority;
 -      qboolean checked;
 +      //qboolean                      checked;
        int compileFlags;
        winding_t           *w;
  }
@@@ -839,8 -797,7 +841,8 @@@ typedef struct plane_
        vec3_t normal;
        vec_t dist;
        int type;
 -      struct plane_s      *hash_chain;
 +      int counter;
 +      int hash_chain;
  }
  plane_t;
  
@@@ -907,9 -864,7 +909,9 @@@ typedef struct brush_
        shaderInfo_t        *celShader;         /* :) */
  
        /* ydnar: gs mods */
 +      int lightmapSampleSize;                 /* jal : entity based _lightmapsamplesize */
        float lightmapScale;
 +      float shadeAngleDegrees;               /* jal : entity based _shadeangle */
        vec3_t eMins, eMaxs;
        indexMap_t          *im;
  
@@@ -960,7 -915,6 +962,7 @@@ typedef struct parseMesh_
        shaderInfo_t        *celShader;             /* :) */
  
        /* ydnar: gs mods */
 +      int lightmapSampleSize;                     /* jal : entity based _lightmapsamplesize */
        float lightmapScale;
        vec3_t eMins, eMaxs;
        indexMap_t          *im;
@@@ -1059,9 -1013,6 +1061,9 @@@ typedef struct mapDrawSurface_
        /* ydnar: per-surface (per-entity, actually) lightmap sample size scaling */
        float lightmapScale;
  
 +      /* jal: per-surface (per-entity, actually) shadeangle */
 +      float shadeAngleDegrees;
 +
        /* ydnar: surface classification */
        vec3_t mins, maxs;
        vec3_t lightmapAxis;
@@@ -1104,7 -1055,6 +1106,7 @@@ typedef struct metaTriangle_
        shaderInfo_t        *si;
        side_t              *side;
        int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
 +      float shadeAngleDegrees;
        vec4_t plane;
        vec3_t lightmapAxis;
        int indexes[ 3 ];
@@@ -1128,7 -1078,6 +1130,7 @@@ typedef struc
        int mapEntityNum, firstDrawSurf;
        int firstBrush, numBrushes;                     /* only valid during BSP compile */
        epair_t             *epairs;
 +      vec3_t originbrush_origin;
  }
  entity_t;
  
@@@ -1162,8 -1111,6 +1164,8 @@@ typedef struct node_
        entity_t            *occupant;      /* for leak file testing */
  
        struct portal_s     *portals;       /* also on nodes during construction */
 +
 +      qboolean has_structural_children;
  }
  node_t;
  
@@@ -1321,7 -1268,6 +1323,7 @@@ typedef struct light_
        float radiusByDist;                 /* for spotlights */
        float fade;                         /* ydnar: from wolf, for linear lights */
        float angleScale;                   /* ydnar: stolen from vlight for K */
 +      float extraDist;                    /* "extra dimension" distance of the light, to kill hot spots */
  
        float add;                          /* ydnar: used for area lights */
        float envelope;                     /* ydnar: units until falloff < tolerance */
@@@ -1367,15 -1313,12 +1369,15 @@@ typedef struc
  
        /* input and output */
        vec3_t color;                       /* starts out at full color, may be reduced if transparent surfaces are crossed */
 +      vec3_t colorNoShadow;               /* result color with no shadow casting */
 +      vec3_t directionContribution;              /* result contribution to the deluxe map */
  
        /* output */
        vec3_t hit;
        int compileFlags;                   /* for determining surface compile flags traced through */
        qboolean passSolid;
        qboolean opaque;
 +      vec_t forceSubsampling;           /* needs subsampling (alphashadow), value = max color contribution possible from it */
  
        /* working data */
        int numTestNodes;
@@@ -1441,13 -1384,6 +1443,13 @@@ typedef struct rawLightmap_
        int numLightClusters, *lightClusters;
  
        int sampleSize, actualSampleSize, axisNum;
 +
 +      /* vortex: per-surface floodlight */
 +      float floodlightDirectionScale;
 +      vec3_t floodlightRGB;
 +      float floodlightIntensity;
 +      float floodlightDistance;
 +
        int entityNum;
        int recvShadows;
        vec3_t mins, maxs, axis, origin, *vecs;
        float                   *bspLuxels[ MAX_LIGHTMAPS ];
        float                   *radLuxels[ MAX_LIGHTMAPS ];
        float                   *superLuxels[ MAX_LIGHTMAPS ];
 +      unsigned char               *superFlags;
        float                   *superOrigins;
        float                   *superNormals;
        int                     *superClusters;
  
        float                   *superDeluxels; /* average light direction */
        float                   *bspDeluxels;
 +      float                   *superFloodLight;
  }
  rawLightmap_t;
  
@@@ -1491,7 -1425,7 +1493,7 @@@ rawGridPoint_t
  
  typedef struct surfaceInfo_s
  {
 -      bspModel_t          *model;
 +      int modelindex;
        shaderInfo_t        *si;
        rawLightmap_t       *lm;
        int parentSurfaceNum, childSurfaceNum;
  }
  surfaceInfo_t;
  
 -
 -
  /* -------------------------------------------------------------------------------
  
     prototypes
  
  /* main.c */
  vec_t                       Random( void );
+ char                        *Q_strncpyz( char *dst, const char *src, size_t len );
+ char                        *Q_strcat( char *dst, size_t dlen, const char *src );
+ char                        *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen );
  int                         BSPInfo( int count, char **fileNames );
  int                         ScaleBSPMain( int argc, char **argv );
  int                         ConvertMain( int argc, char **argv );
@@@ -1528,15 -1467,11 +1533,15 @@@ int                         BSPMain( in
  
  /* convert_map.c */
  int                         ConvertBSPToMap( char *bspName );
 +int                         ConvertBSPToMap_BP( char *bspName );
  
  
  /* convert_ase.c */
  int                         ConvertBSPToASE( char *bspName );
  
 +/* convert_obj.c */
 +int                         ConvertBSPToOBJ( char *bspName );
 +
  
  /* brush.c */
  sideRef_t                   *AllocSideRef( side_t *side, sideRef_t *next );
@@@ -1583,11 -1518,11 +1588,11 @@@ void                        MakeNormalV
  
  
  /* map.c */
 -void                        LoadMapFile( char *filename, qboolean onlyLights );
 +void                        LoadMapFile( char *filename, qboolean onlyLights, qboolean noCollapseGroups );
  int                         FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points );
  int                         PlaneTypeForNormal( vec3_t normal );
  void                        AddBrushBevels( void );
 -brush_t                     *FinishBrush( void );
 +brush_t                     *FinishBrush( qboolean noCollapseGroups );
  
  
  /* portals.c */
@@@ -1597,10 -1532,7 +1602,10 @@@ void                        SplitNodePo
  
  qboolean                    PortalPassable( portal_t *p );
  
 -qboolean                    FloodEntities( tree_t *tree );
 +#define FLOODENTITIES_LEAKED 1
 +#define FLOODENTITIES_GOOD 0
 +#define FLOODENTITIES_EMPTY -1
 +int                     FloodEntities( tree_t *tree );
  void                        FillOutside( node_t *headnode );
  void                        FloodAreas( tree_t *tree );
  face_t                      *VisibleFaces( entity_t *e, tree_t *tree );
@@@ -1625,7 -1557,7 +1630,7 @@@ void                        SetLightSty
  int                         EmitShader( const char *shader, int *contentFlags, int *surfaceFlags );
  
  void                        BeginBSPFile( void );
 -void                        EndBSPFile( void );
 +void                        EndBSPFile( qboolean do_write );
  void                        EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes );
  void                        EmitFogs( void );
  
@@@ -1644,7 -1576,6 +1649,7 @@@ void                        FreeTreePor
  void                        ParsePatch( qboolean onlyLights );
  mesh_t                      *SubdivideMesh( mesh_t in, float maxError, float minLength );
  void                        PatchMapDrawSurfs( entity_t *e );
 +void                        TriangulatePatchSurface( entity_t *e, mapDrawSurface_t *ds );
  
  
  /* tjunction.c */
@@@ -1667,10 -1598,10 +1672,10 @@@ tree_t                      *FaceBSP( f
  
  /* model.c */
  void                        PicoPrintFunc( int level, const char *str );
 -void                        PicoLoadFileFunc( char *name, byte **buffer, int *bufSize );
 -picoModel_t                 *FindModel( char *name, int frame );
 -picoModel_t                 *LoadModel( char *name, int frame );
 -void                        InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale );
 +void                        PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize );
 +picoModel_t                 *FindModel( const char *name, int frame );
 +picoModel_t                 *LoadModel( const char *name, int frame );
 +void                        InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle );
  void                        AddTriangleModels( entity_t *e );
  
  
  mapDrawSurface_t            *AllocDrawSurface( surfaceType_t type );
  void                        FinishSurface( mapDrawSurface_t *ds );
  void                        StripFaceSurface( mapDrawSurface_t *ds );
 +void                        MaxAreaFaceSurface( mapDrawSurface_t *ds );
  qboolean                    CalcSurfaceTextureRange( mapDrawSurface_t *ds );
  qboolean                    CalcLightmapAxis( vec3_t normal, vec3_t axis );
  void                        ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds );
@@@ -1691,7 -1621,7 +1696,7 @@@ void                        ClearSurfac
  void                        AddEntitySurfaceModels( entity_t *e );
  mapDrawSurface_t            *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w );
  mapDrawSurface_t            *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
 -mapDrawSurface_t            *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, char *flareShader, int lightStyle );
 +mapDrawSurface_t            *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, const char *flareShader, int lightStyle );
  mapDrawSurface_t            *DrawSurfaceForShader( char *shader );
  void                        ClipSidesIntoTree( entity_t *e, tree_t *tree );
  void                        MakeDebugPortalSurfs( tree_t *tree );
@@@ -1700,8 -1630,6 +1705,8 @@@ void                        SubdivideFa
  void                        AddEntitySurfaceModels( entity_t *e );
  int                         AddSurfaceModels( mapDrawSurface_t *ds );
  void                        FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
 +void                        EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds );
 +void                        EmitTriangleSurface( mapDrawSurface_t *ds );
  
  
  /* surface_fur.c */
@@@ -1719,7 -1647,6 +1724,7 @@@ void                        MakeEntityM
  void                        FixMetaTJunctions( void );
  void                        SmoothMetaTriangles( void );
  void                        MergeMetaTriangles( void );
 +void                        EmitMetaStats(); // vortex: print meta statistics even in no-verbose mode
  
  
  /* surface_extra.c */
@@@ -1733,7 -1660,6 +1738,7 @@@ int                         GetSurfaceE
  int                         GetSurfaceExtraCastShadows( int num );
  int                         GetSurfaceExtraRecvShadows( int num );
  int                         GetSurfaceExtraSampleSize( int num );
 +int                         GetSurfaceExtraMinSampleSize( int num );
  float                       GetSurfaceExtraLongestCurve( int num );
  void                        GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis );
  
@@@ -1745,8 -1671,6 +1750,8 @@@ void                        LoadSurface
  void                        ProcessDecals( void );
  void                        MakeEntityDecals( entity_t *e );
  
 +/* map.c */
 +void                        TextureAxisFromPlane( plane_t *pln, vec3_t xv, vec3_t yv );
  
  /* brush_primit.c */
  void                        ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY );
@@@ -1800,16 -1724,9 +1805,16 @@@ void                        SetupDirt()
  float                       DirtForSample( trace_t *trace );
  void                        DirtyRawLightmap( int num );
  
 +void                        SetupFloodLight();
 +void                        FloodlightRawLightmaps();
 +void                        FloodlightIlluminateLightmap( rawLightmap_t *lm );
 +float                       FloodLightForSample( trace_t *trace, float floodLightDistance, qboolean floodLightLowQuality );
 +void                        FloodLightRawLightmap( int num );
 +
  void                        IlluminateRawLightmap( int num );
  void                        IlluminateVertexes( int num );
  
 +void                        SetupBrushesFlags( int mask_any, int test_any, int mask_all, int test_all );
  void                        SetupBrushes( void );
  void                        SetupClusters( void );
  qboolean                    ClusterVisible( int a, int b );
@@@ -1860,7 -1777,6 +1865,7 @@@ void                        EmitVertexR
  
  void                        LoadShaderInfo( void );
  shaderInfo_t                *ShaderInfoForShader( const char *shader );
 +shaderInfo_t                *ShaderInfoForShaderNull( const char *shader );
  
  
  /* bspfile_abstract.c */
@@@ -1876,7 -1792,6 +1881,7 @@@ void                        SwapBlock( 
  int                         GetLumpElements( bspHeader_t *header, int lump, int size );
  void                        *GetLump( bspHeader_t *header, int lump );
  int                         CopyLump( bspHeader_t *header, int lump, void *dest, int size );
 +int                         CopyLump_Allocate( bspHeader_t *header, int lump, void **dest, int size, int *allocationVariable );
  void                        AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length );
  
  void                        LoadBSPFile( const char *filename );
@@@ -1888,15 -1803,12 +1893,15 @@@ void                        ParseEntiti
  void                        UnparseEntities( void );
  void                        PrintEntity( const entity_t *ent );
  void                        SetKeyValue( entity_t *ent, const char *key, const char *value );
 +qboolean                    KeyExists( const entity_t *ent, const char *key ); /* VorteX: check if key exists */
  const char                  *ValueForKey( const entity_t *ent, const char *key );
  int                         IntForKey( const entity_t *ent, const char *key );
  vec_t                       FloatForKey( const entity_t *ent, const char *key );
  void                        GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec );
  entity_t                    *FindTargetEntity( const char *target );
  void                        GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows );
 +void InjectCommandLine( char **argv, int beginArgs, int endArgs );
 +
  
  
  /* bspfile_ibsp.c */
@@@ -1936,8 -1848,6 +1941,8 @@@ Q_EXTERN game_t games[
                                                                #include "game_quakelive.h" /* most be after game_quake3.h as they share defines! */
        ,
                                                                #include "game_nexuiz.h" /* most be after game_quake3.h as they share defines! */
 +      ,
 +                                                              #include "game_xonotic.h" /* most be after game_quake3.h as they share defines! */
        ,
                                                                #include "game_tremulous.h" /*LinuxManMikeC: must be after game_quake3.h, depends on #define's set in it */
        ,
        ,
                                                                #include "game_reaction.h" /* must be after game_quake3.h */
        ,
 -      { NULL }                                /* null game */
 +                                                              #include "game_darkplaces.h"    /* vortex: darkplaces q1 engine */
 +      ,
 +                                                              #include "game_dq.h"    /* vortex: deluxe quake game ( darkplaces q1 engine) */
 +      ,
 +                                                              #include "game_prophecy.h"  /* vortex: prophecy game ( darkplaces q1 engine) */
 +      ,
 +                                                              #include "game__null.h" /* null game (must be last item) */
        };
  #endif
  Q_EXTERN game_t             *game Q_ASSIGN( &games[ 0 ] );
@@@ -2015,9 -1919,6 +2020,9 @@@ Q_EXTERN qboolean nofog Q_ASSIGN( qfals
  Q_EXTERN qboolean noHint Q_ASSIGN( qfalse );                        /* ydnar */
  Q_EXTERN qboolean renameModelShaders Q_ASSIGN( qfalse );            /* ydnar */
  Q_EXTERN qboolean skyFixHack Q_ASSIGN( qfalse );                    /* ydnar */
 +Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse );                      /* 27 */
 +Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse );                   /* div0 */
 +Q_EXTERN qboolean maxAreaFaceSurface Q_ASSIGN( qfalse );                    /* divVerent */
  
  Q_EXTERN int patchSubdivisions Q_ASSIGN( 8 );                       /* ydnar: -patchmeta subdivisions */
  
@@@ -2034,12 -1935,6 +2039,12 @@@ Q_EXTERN qboolean emitFlares Q_ASSIGN( 
  Q_EXTERN qboolean debugSurfaces Q_ASSIGN( qfalse );
  Q_EXTERN qboolean debugInset Q_ASSIGN( qfalse );
  Q_EXTERN qboolean debugPortals Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean lightmapTriangleCheck Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean lightmapExtraVisClusterNudge Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean lightmapFill Q_ASSIGN( qfalse );
 +Q_EXTERN int metaAdequateScore Q_ASSIGN( -1 );
 +Q_EXTERN int metaGoodScore Q_ASSIGN( -1 );
 +Q_EXTERN float metaMaxBBoxDistance Q_ASSIGN( -1 );
  
  #if Q3MAP2_EXPERIMENTAL_SNAP_NORMAL_FIX
  // Increasing the normalEpsilon to compensate for new logic in SnapNormal(), where
@@@ -2082,16 -1977,13 +2087,16 @@@ Q_EXTERN char source[ 1024 ]
  Q_EXTERN char outbase[ 32 ];
  
  Q_EXTERN int sampleSize;                                    /* lightmap sample size in units */
 +Q_EXTERN int minSampleSize;                                 /* minimum sample size to use at all */
 +Q_EXTERN int sampleScale;                                   /* vortex: lightmap sample scale (ie quality)*/
  
  Q_EXTERN int mapEntityNum Q_ASSIGN( 0 );
  
  Q_EXTERN int entitySourceBrushes;
  
 -Q_EXTERN plane_t mapplanes[ MAX_MAP_PLANES ];               /* mapplanes[ num ^ 1 ] will always be the mirror or mapplanes[ num ] */
 -Q_EXTERN int nummapplanes;                                  /* nummapplanes will always be even */
 +Q_EXTERN plane_t            *mapplanes Q_ASSIGN( NULL );  /* mapplanes[ num ^ 1 ] will always be the mirror or mapplanes[ num ] */
 +Q_EXTERN int nummapplanes Q_ASSIGN( 0 );                    /* nummapplanes will always be even */
 +Q_EXTERN int allocatedmapplanes Q_ASSIGN( 0 );
  Q_EXTERN int numMapPatches;
  Q_EXTERN vec3_t mapMins, mapMaxs;
  
@@@ -2114,7 -2006,6 +2119,7 @@@ Q_EXTERN int numMapDrawSurfs
  Q_EXTERN int numSurfacesByType[ NUM_SURFACE_TYPES ];
  Q_EXTERN int numClearedSurfaces;
  Q_EXTERN int numStripSurfaces;
 +Q_EXTERN int numMaxAreaSurfaces;
  Q_EXTERN int numFanSurfaces;
  Q_EXTERN int numMergedSurfaces;
  Q_EXTERN int numMergedVerts;
@@@ -2161,12 -2052,13 +2166,12 @@@ Q_EXTERN qboolean fastvis
  Q_EXTERN qboolean noPassageVis;
  Q_EXTERN qboolean passageVisOnly;
  Q_EXTERN qboolean mergevis;
 +Q_EXTERN qboolean mergevisportals;
  Q_EXTERN qboolean nosort;
  Q_EXTERN qboolean saveprt;
  Q_EXTERN qboolean hint;             /* ydnar */
  Q_EXTERN char inbase[ MAX_QPATH ];
 -
 -/* other bits */
 -Q_EXTERN int totalvis;
 +Q_EXTERN char globalCelShader[ MAX_QPATH ];
  
  Q_EXTERN float farPlaneDist;                /* rr2do2, rf, mre, ydnar all contributed to this one... */
  
@@@ -2207,13 -2099,10 +2212,13 @@@ Q_EXTERN vportal_t          *sorted_por
  
  /* commandline arguments */
  Q_EXTERN qboolean wolfLight Q_ASSIGN( qfalse );
 +Q_EXTERN float extraDist Q_ASSIGN( 0.0f );
  Q_EXTERN qboolean loMem Q_ASSIGN( qfalse );
  Q_EXTERN qboolean noStyles Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean keepLights Q_ASSIGN( qfalse );
  
  Q_EXTERN int sampleSize Q_ASSIGN( DEFAULT_LIGHTMAP_SAMPLE_SIZE );
 +Q_EXTERN int minSampleSize Q_ASSIGN( DEFAULT_LIGHTMAP_MIN_SAMPLE_SIZE );
  Q_EXTERN qboolean noVertexLighting Q_ASSIGN( qfalse );
  Q_EXTERN qboolean noGridLighting Q_ASSIGN( qfalse );
  
@@@ -2224,10 -2113,8 +2229,10 @@@ Q_EXTERN qboolean cpmaHack Q_ASSIGN( qf
  
  Q_EXTERN qboolean deluxemap Q_ASSIGN( qfalse );
  Q_EXTERN qboolean debugDeluxemap Q_ASSIGN( qfalse );
 +Q_EXTERN int deluxemode Q_ASSIGN( 0 );                  /* deluxemap format (0 - modelspace, 1 - tangentspace with renormalization, 2 - tangentspace without renormalization) */
  
  Q_EXTERN qboolean fast Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean fastpoint Q_ASSIGN( qtrue );
  Q_EXTERN qboolean faster Q_ASSIGN( qfalse );
  Q_EXTERN qboolean fastgrid Q_ASSIGN( qfalse );
  Q_EXTERN qboolean fastbounce Q_ASSIGN( qfalse );
@@@ -2243,19 -2130,14 +2248,19 @@@ Q_EXTERN qboolean shade Q_ASSIGN( qfals
  Q_EXTERN float shadeAngleDegrees Q_ASSIGN( 0.0f );
  Q_EXTERN int superSample Q_ASSIGN( 0 );
  Q_EXTERN int lightSamples Q_ASSIGN( 1 );
 +Q_EXTERN qboolean lightRandomSamples Q_ASSIGN( qfalse );
 +Q_EXTERN int lightSamplesSearchBoxSize Q_ASSIGN( 1 );
  Q_EXTERN qboolean filter Q_ASSIGN( qfalse );
  Q_EXTERN qboolean dark Q_ASSIGN( qfalse );
  Q_EXTERN qboolean sunOnly Q_ASSIGN( qfalse );
  Q_EXTERN int approximateTolerance Q_ASSIGN( 0 );
  Q_EXTERN qboolean noCollapse Q_ASSIGN( qfalse );
 +Q_EXTERN int lightmapSearchBlockSize Q_ASSIGN( 0 );
  Q_EXTERN qboolean exportLightmaps Q_ASSIGN( qfalse );
  Q_EXTERN qboolean externalLightmaps Q_ASSIGN( qfalse );
  Q_EXTERN int lmCustomSize Q_ASSIGN( LIGHTMAP_WIDTH );
 +Q_EXTERN char *             lmCustomDir Q_ASSIGN( NULL );
 +Q_EXTERN int lmLimitSize Q_ASSIGN( 0 );
  
  Q_EXTERN qboolean dirty Q_ASSIGN( qfalse );
  Q_EXTERN qboolean dirtDebug Q_ASSIGN( qfalse );
@@@ -2264,15 -2146,6 +2269,15 @@@ Q_EXTERN float dirtDepth Q_ASSIGN( 128.
  Q_EXTERN float dirtScale Q_ASSIGN( 1.0f );
  Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
  
 +/* 27: floodlighting */
 +Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
 +Q_EXTERN vec3_t floodlightRGB;
 +Q_EXTERN float floodlightIntensity Q_ASSIGN( 512.0f );
 +Q_EXTERN float floodlightDistance Q_ASSIGN( 1024.0f );
 +Q_EXTERN float floodlightDirectionScale Q_ASSIGN( 1.0f );
 +
  Q_EXTERN qboolean dump Q_ASSIGN( qfalse );
  Q_EXTERN qboolean debug Q_ASSIGN( qfalse );
  Q_EXTERN qboolean debugUnused Q_ASSIGN( qfalse );
@@@ -2286,27 -2159,12 +2291,27 @@@ Q_EXTERN float maxMapDistance Q_ASSIGN
  
  /* for run time tweaking of light sources */
  Q_EXTERN float pointScale Q_ASSIGN( 7500.0f );
 +Q_EXTERN float spotScale Q_ASSIGN( 7500.0f );
  Q_EXTERN float areaScale Q_ASSIGN( 0.25f );
  Q_EXTERN float skyScale Q_ASSIGN( 1.0f );
  Q_EXTERN float bounceScale Q_ASSIGN( 0.25f );
  
 +/* jal: alternative angle attenuation curve */
 +Q_EXTERN qboolean lightAngleHL Q_ASSIGN( qfalse );
 +
 +/* vortex: gridscale and gridambientscale */
 +Q_EXTERN float gridScale Q_ASSIGN( 1.0f );
 +Q_EXTERN float gridAmbientScale Q_ASSIGN( 1.0f );
 +Q_EXTERN float gridDirectionality Q_ASSIGN( 1.0f );
 +Q_EXTERN float gridAmbientDirectionality Q_ASSIGN( 0.0f );
 +Q_EXTERN qboolean inGrid Q_ASSIGN( 0 );
 +
  /* ydnar: lightmap gamma/compensation */
  Q_EXTERN float lightmapGamma Q_ASSIGN( 1.0f );
 +Q_EXTERN float lightmapsRGB Q_ASSIGN( qfalse );
 +Q_EXTERN float texturesRGB Q_ASSIGN( qfalse );
 +Q_EXTERN float colorsRGB Q_ASSIGN( qfalse );
 +Q_EXTERN float lightmapExposure Q_ASSIGN( 0.0f );
  Q_EXTERN float lightmapCompensate Q_ASSIGN( 1.0f );
  
  /* ydnar: for runtime tweaking of falloff tolerance */
@@@ -2315,10 -2173,6 +2320,10 @@@ Q_EXTERN qboolean exactPointToPolygon Q
  Q_EXTERN float formFactorValueScale Q_ASSIGN( 3.0f );
  Q_EXTERN float linearScale Q_ASSIGN( 1.0f / 8000.0f );
  
 +// for .ase conversion
 +Q_EXTERN qboolean shadersAsBitmap Q_ASSIGN( qfalse );
 +Q_EXTERN qboolean lightmapsAsTexcoord Q_ASSIGN( qfalse );
 +
  Q_EXTERN light_t            *lights;
  Q_EXTERN int numPointLights;
  Q_EXTERN int numSpotLights;
@@@ -2415,9 -2269,6 +2420,9 @@@ Q_EXTERN int numBSPLightmaps Q_ASSIGN( 
  Q_EXTERN int numExtLightmaps Q_ASSIGN( 0 );
  Q_EXTERN outLightmap_t      *outLightmaps Q_ASSIGN( NULL );
  
 +/* vortex: per surface floodlight statictics */
 +Q_EXTERN int numSurfacesFloodlighten Q_ASSIGN( 0 );
 +
  /* grid points */
  Q_EXTERN int numRawGridPoints Q_ASSIGN( 0 );
  Q_EXTERN rawGridPoint_t     *rawGridPoints Q_ASSIGN( NULL );
@@@ -2457,47 -2308,37 +2462,47 @@@ Q_EXTERN vec3_t gridSiz
  
  Q_EXTERN int numEntities Q_ASSIGN( 0 );
  Q_EXTERN int numBSPEntities Q_ASSIGN( 0 );
 -Q_EXTERN entity_t entities[ MAX_MAP_ENTITIES ];
 +Q_EXTERN int allocatedEntities Q_ASSIGN( 0 );
 +Q_EXTERN entity_t*          entities Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPModels Q_ASSIGN( 0 );
 -Q_EXTERN bspModel_t bspModels[ MAX_MAP_MODELS ];
 +Q_EXTERN int allocatedBSPModels Q_ASSIGN( 0 );
 +Q_EXTERN bspModel_t*        bspModels Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPShaders Q_ASSIGN( 0 );
 -Q_EXTERN bspShader_t bspShaders[ MAX_MAP_MODELS ];
 +Q_EXTERN int allocatedBSPShaders Q_ASSIGN( 0 );
 +Q_EXTERN bspShader_t*       bspShaders Q_ASSIGN( 0 );
  
  Q_EXTERN int bspEntDataSize Q_ASSIGN( 0 );
 -Q_EXTERN char bspEntData[ MAX_MAP_ENTSTRING ];
 +Q_EXTERN int allocatedBSPEntData Q_ASSIGN( 0 );
 +Q_EXTERN char               *bspEntData Q_ASSIGN( 0 );
  
  Q_EXTERN int numBSPLeafs Q_ASSIGN( 0 );
  Q_EXTERN bspLeaf_t bspLeafs[ MAX_MAP_LEAFS ];
  
  Q_EXTERN int numBSPPlanes Q_ASSIGN( 0 );
 -Q_EXTERN bspPlane_t bspPlanes[ MAX_MAP_PLANES ];
 +Q_EXTERN int allocatedBSPPlanes Q_ASSIGN( 0 );
 +Q_EXTERN bspPlane_t         *bspPlanes;
  
  Q_EXTERN int numBSPNodes Q_ASSIGN( 0 );
 -Q_EXTERN bspNode_t bspNodes[ MAX_MAP_NODES ];
 +Q_EXTERN int allocatedBSPNodes Q_ASSIGN( 0 );
 +Q_EXTERN bspNode_t*         bspNodes Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPLeafSurfaces Q_ASSIGN( 0 );
 -Q_EXTERN int bspLeafSurfaces[ MAX_MAP_LEAFFACES ];
 +Q_EXTERN int allocatedBSPLeafSurfaces Q_ASSIGN( 0 );
 +Q_EXTERN int*               bspLeafSurfaces Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPLeafBrushes Q_ASSIGN( 0 );
 -Q_EXTERN int bspLeafBrushes[ MAX_MAP_LEAFBRUSHES ];
 +Q_EXTERN int allocatedBSPLeafBrushes Q_ASSIGN( 0 );
 +Q_EXTERN int*               bspLeafBrushes Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPBrushes Q_ASSIGN( 0 );
 -Q_EXTERN bspBrush_t bspBrushes[ MAX_MAP_BRUSHES ];
 +Q_EXTERN int allocatedBSPBrushes Q_ASSIGN( 0 );
 +Q_EXTERN bspBrush_t*        bspBrushes Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPBrushSides Q_ASSIGN( 0 );
 -Q_EXTERN bspBrushSide_t bspBrushSides[ MAX_MAP_BRUSHSIDES ];
 +Q_EXTERN int allocatedBSPBrushSides Q_ASSIGN( 0 );
 +Q_EXTERN bspBrushSide_t*    bspBrushSides Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPLightBytes Q_ASSIGN( 0 );
  Q_EXTERN byte               *bspLightBytes Q_ASSIGN( NULL );
@@@ -2512,11 -2353,10 +2517,11 @@@ Q_EXTERN int numBSPVisBytes Q_ASSIGN( 
  Q_EXTERN byte bspVisBytes[ MAX_MAP_VISIBILITY ];
  
  Q_EXTERN int numBSPDrawVerts Q_ASSIGN( 0 );
 -Q_EXTERN bspDrawVert_t      *bspDrawVerts Q_ASSIGN( NULL );
 +Q_EXTERN bspDrawVert_t          *bspDrawVerts Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPDrawIndexes Q_ASSIGN( 0 );
 -Q_EXTERN int bspDrawIndexes[ MAX_MAP_DRAW_INDEXES ];
 +Q_EXTERN int allocatedBSPDrawIndexes Q_ASSIGN( 0 );
 +Q_EXTERN int                *bspDrawIndexes Q_ASSIGN( NULL );
  
  Q_EXTERN int numBSPDrawSurfaces Q_ASSIGN( 0 );
  Q_EXTERN bspDrawSurface_t   *bspDrawSurfaces Q_ASSIGN( NULL );
@@@ -2527,30 -2367,6 +2532,30 @@@ Q_EXTERN bspFog_t bspFogs[ MAX_MAP_FOG
  Q_EXTERN int numBSPAds Q_ASSIGN( 0 );
  Q_EXTERN bspAdvertisement_t bspAds[ MAX_MAP_ADVERTISEMENTS ];
  
 +#define AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def ) \
 +      do \
 +      { \
 +              if ( reqitem >= allocated )     \
 +              { \
 +                      if ( allocated == 0 ) { \
 +                              allocated = def; } \
 +                      while ( reqitem >= allocated && allocated )     \
 +                              allocated *= 2; \
 +                      if ( !allocated || allocated > 2147483647 / (int)sizeof( *ptr ) ) \
 +                      { \
 +                              Error( # ptr " over 2 GB" ); \
 +                      } \
 +                      ptr = realloc( ptr, sizeof( *ptr ) * allocated ); \
 +                      if ( !ptr ) { \
 +                              Error( # ptr " out of memory" ); } \
 +              } \
 +      } \
 +      while ( 0 )
 +
 +#define AUTOEXPAND_BY_REALLOC_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC( bsp ## suffix, numBSP ## suffix, allocatedBSP ## suffix, def )
 +
 +#define Image_LinearFloatFromsRGBFloat( c ) ( ( ( c ) <= 0.04045f ) ? ( c ) * ( 1.0f / 12.92f ) : (float)pow( ( ( c ) + 0.055f ) * ( 1.0f / 1.055f ), 2.4f ) )
 +#define Image_sRGBFloatFromLinearFloat( c ) ( ( ( c ) < 0.0031308f ) ? ( c ) * 12.92f : 1.055f * (float)pow( ( c ), 1.0f / 2.4f ) - 0.055f )
  
  /* end marker */
  #endif