We just reached 20,000 articles on this wiki!
If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Angry Birds Arcade

From The Cutting Room Floor
Jump to navigation Jump to search

Click to upload a new image...Dummy link

Angry Birds Arcade

Developer: Play Mechanix
Publishers: Raw Thrills, ICE
Platform: Arcade (Raw Thrills PC-based)
Released in US: 2015


SourceIcon.png This game has uncompiled source code.
DevTextIcon.png This game has hidden development-related text.


So very stubbly.
This page is rather stubbly and could use some expansion.
Are you a bad enough dude to rescue this article?

It's Angry Birds in an Arcade! It may be a game off the big mobile phenomenon but we all know it won't ever top Pac-Man.

Developer Leftovers

Maya directories

Versions 0.26, 1.08, 1.12, 1.13, 1.15 and 1.17 have a few Maya directories in the data folder of the game, all are empty. Language based directories were likely added in 1.05 and removed in 1.15+. It's likely these were used to contain source material of the game's prerendered movies.

maya
maya_arabic
maya_portuguese
maya_russian
maya_spanish
maya_turkish

Source headers

Hmmm...
To do:
Figure out how to decrypt and upload them here.

There's four leftover source headers files in the prod/headers directory. Two for the G6 Engine, the game, and one for likely a ticket redemption library.

User profile and root directory

Hmmm...
To do:
  • Find the other codenames.
  • Sort content and upload here.
  • There's a leftover KDevelop cache directory in root/.cache/kdevduchain, having a LOT of development text and possibly raw source code from both the game, engine and other proprietary libraries. The project file is removed, but it may be possible to recover the content from the String Index and Comment Repository.

In the full hard drive of version 1.18 of the game from Dave & Busters, the Linux profile directory, being raw and the root directory have a small portion of leftover source code at the root of the said directories and logs likely from a developer's computer likely interacting with an internal SVN repo that was later locally removed from the hard drive, along with a makefile. Interestingly, some code was carried from dino's source directory, being Jurassic Park Arcade, as well as motogp (the MotoGP arcade game) and 2XL.

datadigest.c tends to be from an SSL library for Play Mechanix and Raw Thrills, in a directory called pmrt_ssl.

// datadigest.c
// Play Mechanix - Video Game System
// Copyright (c) 2007 Play Mechanix Inc. All Rights Reserved
//

#include "datadigest.h"

#if defined(_WIN32)
#include <windows.h>
#else //Linux
#include <unistd.h>
#endif //_WIN32

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>

// to print err string:
// 	printf( "ERR: %s\n", ERR_error_string(ERR_get_error(),NULL) );


void FreeDataDigestHandle(DataDigestHandle *ddh)
{
	if( ddh == NULL )
		return;

	if ( ddh->digest_bio != NULL )
		BIO_free(ddh->digest_bio);

	if ( ddh->null_bio != NULL )
		BIO_free(ddh->null_bio);

	ddh->digest_bio = NULL;
	ddh->null_bio = NULL;
	memset(ddh->digest,0,sizeof(ddh->digest));
	ddh->digest_len = 0;

}

int CloseDataDigest(DataDigestHandle *ddh )
{
	FreeDataDigestHandle(ddh);
	return 0;
}

int ComputeDataDigest(DataDigestHandle *ddh )
{
	int ec;
	EVP_MD_CTX *mdcp;
	if( ddh == NULL )
		return DATADIGEST_RESULT_INVALID_HANDLE;
	mdcp = NULL;
	ec = BIO_get_md_ctx(ddh->digest_bio, &mdcp );
	if ( ec < 0 || mdcp == NULL )
	{
		FreeDataDigestHandle(ddh);
		return DATADIGEST_RESULT_FAILURE;
	}

	// clear out old digest
	memset(ddh->digest,0,sizeof(ddh->digest));
	ddh->digest_len = 0;

	ec = EVP_DigestFinal( mdcp, ddh->digest, &ddh->digest_len );
	if ( ec < 0 )
	{
		FreeDataDigestHandle(ddh);
		return DATADIGEST_RESULT_FAILURE;
	}


	// reset digest, so we can use it digest some more/different data
	BIO_set_md(ddh->digest_bio, ddh->digest_method);

	BIO_reset(ddh->digest_bio);


	return DATADIGEST_RESULT_SUCCESS;
}

int InitDataDigest(DataDigestHandle *ddh, int method )
{
	// const EVP_MD *digest_method = NULL;

	if( ddh == NULL )
		return DATADIGEST_RESULT_INVALID_HANDLE;

	ddh->digest_bio = NULL;

	// setup to digest stream
	ddh->digest_bio = BIO_new(BIO_f_md());
	if ( ddh->digest_bio == NULL )
	{
		FreeDataDigestHandle(ddh);
		return DATADIGEST_RESULT_FAILURE;
	}


	switch(method)
	{
	case DIGEST_MD5:
		ddh->digest_method = EVP_md5();
		break;
	case DIGEST_SHA1:
		ddh->digest_method = EVP_sha1();
		break;
	default: // no digest
		ddh->digest_method = EVP_md_null();
		break;
	}

	// set digest method
	if( BIO_set_md(ddh->digest_bio, ddh->digest_method) < 0 )
	{
		FreeDataDigestHandle(ddh);
		return DATADIGEST_RESULT_FAILURE;
	}



	// setup null stream
	ddh->null_bio = BIO_new(BIO_s_null());
	if ( ddh->null_bio == NULL )
	{
		FreeDataDigestHandle(ddh);
		return DATADIGEST_RESULT_FAILURE;
	}

	// chain the bios
	if ( BIO_push(ddh->digest_bio,ddh->null_bio)  < 0 ) 
	{
		FreeDataDigestHandle(ddh);
		return DATADIGEST_RESULT_FAILURE;
	}



	return DATADIGEST_RESULT_SUCCESS;

}

int WriteToDataDigest( DataDigestHandle *ddh, void *data, int *size )
{
	int ec;
	if( ddh == NULL || ddh->digest_bio == NULL )
		return DATADIGEST_RESULT_INVALID_HANDLE;

	if ( data == NULL || size == NULL || *size <= 0 )
		return DATADIGEST_RESULT_INVALID_PARAMS;



	ec = BIO_write(ddh->digest_bio, data, *size );
	if ( ec <= 0 )
		return DATADIGEST_RESULT_FAILURE;


	*size = ec;

	return DATADIGEST_RESULT_SUCCESS;
}


int DataDigestMem( int method, void *data, int size, unsigned char *digest, unsigned int *digest_len )
{
	int ec,s;
	DataDigestHandle ddh[100];

	if ( data == NULL || size <= 0 || digest == NULL || digest_len == NULL || *digest_len <= 0 )
	{
		return DATADIGEST_RESULT_INVALID_PARAMS;
	}

	ec = InitDataDigest( &ddh[0], method );
	if ( ec != DATADIGEST_RESULT_SUCCESS )
		return ec;

	s = size;
	ec = WriteToDataDigest( &ddh[0], data, &s );
	if ( ec != DATADIGEST_RESULT_SUCCESS || s != size )
	{
		CloseDataDigest(&ddh[0]);
		return DATADIGEST_RESULT_FAILURE;
	}

	ec = ComputeDataDigest(&ddh[0]);
	if ( ec != DATADIGEST_RESULT_SUCCESS )
	{
		CloseDataDigest(&ddh[0]);
		return ec;
	}

	// didn't provide enough space for digest
	if ( ddh[0].digest_len > *digest_len )
	{
		CloseDataDigest(&ddh[0]);
		return DATADIGEST_RESULT_FAILURE;
	}

	// zero out existing data
	memset(digest,0,*digest_len);
	// copy the digest and it's length
	memcpy(digest,ddh[0].digest,ddh[0].digest_len);
	*digest_len = ddh[0].digest_len;

	// all done!
	CloseDataDigest(&ddh[0]);
	return DATADIGEST_RESULT_SUCCESS;

}

int DataDigestFile( int method, char *filename, unsigned char *digest, unsigned int *digest_len )
{

	int ec;
	BIO *file_bio;
	BIO *digest_bio;
	char buf[1024];
	unsigned int len;
	const EVP_MD *digest_method = NULL;
	EVP_MD_CTX *mdcp = NULL;

	file_bio = NULL;
	digest_bio = NULL;

	// set file bio
	file_bio = BIO_new_file(filename,"rb");
	if ( file_bio == NULL )
	{
		return DATADIGEST_RESULT_FAILURE;
	}

	// setup to digest stream
	digest_bio = BIO_new(BIO_f_md());
	if ( digest_bio == NULL )
	{
		BIO_free(file_bio);
		return DATADIGEST_RESULT_FAILURE;
	}

	switch(method)
	{
	case DIGEST_MD5:
		digest_method = EVP_md5();
		break;
	case DIGEST_SHA1:
		digest_method = EVP_sha1();
		break;
	default: // no digest
		digest_method = EVP_md_null();
		break;
	}

	// set digest method
	if( BIO_set_md(digest_bio, digest_method) < 0 )
	{
		BIO_free(file_bio);
		BIO_free(digest_bio);
		return DATADIGEST_RESULT_FAILURE;
	}


	// chain the bios
	if ( BIO_push(digest_bio,file_bio)  < 0 ) 
	{
		BIO_free(file_bio);
		BIO_free(digest_bio);
		return DATADIGEST_RESULT_FAILURE;
	}


	// read in data 1k at a time
	ec = 0;
	while ( ec >= 0 )
	{
		ec = BIO_read(digest_bio, buf, sizeof(buf) );
		if ( ec == 0 && BIO_should_retry(digest_bio) == 0 ) // EOF
			break;
		if ( ec < 0 )
			break;
	}

	// read failed :(
	if ( ec < 0 )
	{
		BIO_free(file_bio);
		BIO_free(digest_bio);
		return DATADIGEST_RESULT_FAILURE;
	}

	// extract digest value
	ec = BIO_get_md_ctx(digest_bio, &mdcp );
	if ( ec < 0 || mdcp == NULL )
	{
		BIO_free(file_bio);
		BIO_free(digest_bio);
		return DATADIGEST_RESULT_FAILURE;
	}


	len = EVP_MD_CTX_size(mdcp);
	// didn't provide enough space for digest!
	if ( len > *digest_len )
	{
		BIO_free(file_bio);
		BIO_free(digest_bio);
		return DATADIGEST_RESULT_FAILURE;
	}

	// clear out  any existing data
	memset(digest,0,*digest_len);

	ec = EVP_DigestFinal( mdcp, digest, digest_len );
	if ( ec < 0 )
	{
		BIO_free(file_bio);
		BIO_free(digest_bio);
		return DATADIGEST_RESULT_FAILURE;
	}

	// all done!
	BIO_free(file_bio);
	BIO_free(digest_bio);

	return DATADIGEST_RESULT_SUCCESS;

}


int ConvertDataDigestToHexString( unsigned char *digest, unsigned int digest_len, char *dest, unsigned int dest_len, char seperator )
{
	unsigned int i;
	char buf[4];
	if ( digest == NULL || dest == NULL )
		return -1;
//	if ( dest_len < 3 * digest_len )
//		return -2;

	memset( dest, 0, dest_len );

	if ( seperator > 0 )
	{
		for ( i = 0; i < digest_len - 1; i++ )
		{
			sprintf( buf, "%02x%c", digest[i], seperator );
			if ( dest_len > 3 ) // need room for new chars plus NULL terminator
			{
				strncat(dest, buf, 3 );
				dest_len -= 3;
			}
		}
		// do last byte w/o a trailing seperator
		sprintf( buf, "%02x", digest[digest_len-1] );
		if ( dest_len > 2 )  // need room for new chars plus NULL terminator
		{
			strncat(dest, buf, 2 );
			dest_len -= 2;
		}

	}
	else
	{
		// no seperator
		for ( i = 0; i < digest_len ; i++ )
		{
			sprintf( buf, "%02x", digest[i] );
			if ( dest_len > 2 ) // need room for new chars plus NULL terminator
			{
				strncat(dest, buf, 2 );
				dest_len -= 2;
			}
		}
	}



	return 0;

}

int ConvertHexStringToDataDigest( char *src, unsigned int src_len, unsigned char *digest, unsigned int digest_len, char seperator )
{
	unsigned int i,j;
	int ec;
	char buf[3];
	char *start;
	if ( digest == NULL || src == NULL )
		return -1;
	if (seperator > 0 &&  src_len < 3 * digest_len )
		return -2;
	if (seperator <= 0 &&  src_len < 2 * digest_len )
		return -2;

	memset( digest, 0, digest_len );

	j = 0;
	start = src;
	for ( i = 0; i < digest_len; i++ )
	{
		memset( buf, 0, 3 );
		memcpy( buf, start, 2 );

		sscanf(buf, "%02x", &ec );
		digest[i] = ec;
		if ( seperator > 0 )
		{
			start+=3;
			j += 3;
		}
		else
		{
			start+=2;
			j += 2;
		}
		if ( j > src_len )
			break;
	}

	return 0;

}

int DataDigestCmp( unsigned char *digest1, unsigned char *digest2, unsigned int digest_len )
{
	unsigned int i;
	if ( digest1 == NULL || digest2 == NULL )
		return -1;

	for ( i = 0; i < digest_len; i++ )
	{
		if ( digest1[i] != digest2[i] )
			return 1;
	}

	return 0;
}


int SaveFileWithDataDigest( int method, char *filename, void *data, int data_size )
{
	int ec = 0;
	FILE *fh = NULL;
	unsigned char digest[DATADIGEST_MAX_DIGEST_LEN] = {0};
	unsigned int  digest_size = sizeof(digest);

	if ( ! filename || ! data || data_size <= 0 )
		return -1;


	ec = DataDigestMem( method, data, data_size, digest, &digest_size );
	if (ec!=0)
	{
		// something bad happened with the digest.  :(
		return ec;
	}

	fh = fopen( filename, "wb" );
	if ( ! fh )
	{
		return -2;
	}

	ec = fwrite( &digest_size, sizeof(digest_size), 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		return -3;
	}
	ec = fwrite( digest, digest_size, 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		return -4;
	}
	ec = fwrite( &data_size, sizeof(data_size), 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		return -5;
	}
	ec = fwrite( data, data_size, 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		return -6;
	}

	fclose(fh);
	return 0;

}

int LoadFileWithDataDigest( int method, char *filename, void **data, int *data_size, void *(*malloc_func)(size_t), void (*free_func)(void *), int nullTerminate )
{
	int ec = 0;
	int mallocd = 0;
	int required_size = 0;
	int size = 0;
	FILE *fh = NULL;
	unsigned char digest[DATADIGEST_MAX_DIGEST_LEN] = {0};
	unsigned int  digest_size = sizeof(digest);

	unsigned char digest_test[DATADIGEST_MAX_DIGEST_LEN] = {0};
	unsigned int  digest_test_size = sizeof(digest_test);

	if ( ! malloc_func )
		malloc_func = malloc;
	if ( ! free_func )
		free_func = free;


	if ( ! filename || ! data  )
		return -1;
	if ( *data != NULL && data_size == NULL )
		return -2;




	fh = fopen( filename, "rb" );
	if ( ! fh )
	{
		return -2;
	}

	ec = fread( &digest_size, sizeof(digest_size), 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		return -3;
	}

	ec = fread( digest, digest_size, 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		return -4;
	}

	ec = fread( &size, sizeof(size), 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		return -5;
	}

	if ( nullTerminate )
		required_size = size + 2;  // nullterminate enough for uns16 buffer
	else
		required_size = size;

	if ( *data == NULL )
	{
		*data = malloc_func(required_size);
		mallocd=1;
		if ( ! *data )
		{
			fclose(fh);
			return -6;
		}
	}
	else
	{
		if ( *data_size < required_size )
		{
			// not enough space!
			fclose(fh);
			return -7;
		}
	}

	// clear out the buffer first, this nullTerminates if required_size > size
	memset(*data,0,required_size);

	ec = fread( *data, size, 1, fh );
	if ( ec != 1 )
	{
		fclose(fh);
		if ( mallocd )
			free_func(*data);
		return -8;
	}
	fclose(fh);

	if ( data_size )
		*data_size = required_size;


	// now check if the data digest matches
	ec = DataDigestMem( method, *data, size, digest_test, &digest_test_size );
	if (ec!=0)
	{
		// something bad happened with the digest.  :(
		if ( mallocd )
			free_func(*data);
		return -9;
	}

	ec = DataDigestCmp( digest_test, digest, digest_test_size );
	if ( ec ) // not a match
	{
		if ( mallocd )
			free_func(*data);
		return -10;
	}

	return 0;

}

vid.c tends to be from the G6 Engine, in pm/g6/g6engine/src/g6.

// vid.c
//
//	video graphics interface - pc
//	Play Mechanix Platform Independent Video System
//	Copyright 1998-2014 Play Mechanix Inc. All Rights Reserved
//
// JFL 07 Oct 04; from ah

///#include <GL/freeglut.h>

#include "g6.h"

// dimensions of our gun space, used by GunWorldPos for converting gun to world cords
// some bogus dflt values...
//int gGunSpace[4] = { 0, 0, 100, 100 };

HashTable gFogSettings;


VidDispInfo VidDisp; // display info computed

/*
// useful/common GL matrices
GLint vglViewport[4]; // 0,0,width,height
GLdouble vglProjection[16];
GLdouble vglModelView[16];
*/

// frame
typedef struct _vp {
  struct _vp *next;
  uns32 flags;
} Vid;

void* vidSysMem0=NUL;
///////////////////////////////////////////////////////////////////////////////
// VID


int VidSetup(int fullscreen, int screen_width, int screen_height, float aspect_ratio )
{
	VidDisp.fullscreen = fullscreen;
	VidDisp.screenW = screen_width;
	VidDisp.screenH = screen_height;
	VidDisp.screenAspectRatio = aspect_ratio;
	return 0;
}


int VidInit(void)
{
	int ec = 0, i=0;
	float angle_radians = 0.0f;
	vidSysMem0=NUL;
	// MEMZ(VidDisp);

	// setup dflt fog
	VidDisp.fogMode=GL_LINEAR;
	VidDisp.fogNear=10000.0;
	VidDisp.fogFar=10001.0;
	VidDisp.fogDensity=0.20f;
	VidDisp.fogRGBA[0]=1.0f;
	VidDisp.fogRGBA[1]=1.0f;
	VidDisp.fogRGBA[2]=1.0f;
	VidDisp.fogRGBA[3]=0.0f; // alpha is used for the fog clamp, 0 means no clamp on the fog (go to full fog)
	VidDisp.flags|=M_VIDDISP_FOG|M_VIDDISP_FOG_C;

	VidDisp.ReflectionMapScale = 1.0f;

	/*
	VidDisp.gridSize=10;
	VidDisp.gridDim=10;
	*/


	if(sizeof(GLfloat)!=sizeof(float))
	{
		// assumptions are made in the data & program
		LOCKUP(BP_VIDINIT);
		return -2;
	}

	VidDisp.blanktex = 255;

	VidDisp.dbgDisableTex[0] = 0;

	VidDisp.dbgDisableDiff = 0;
	VidDisp.dbgDisableSpec = 0;
	VidDisp.dbgUseDbgShiny = 0;
	VidDisp.dbgShiny = 2;




	VidDisp.ShadSplitLambda = RenderG.SHADMAP_SPLIT_LAMBDA;

	VidDisp.dbgOverrideTexEnable = 0;
	for( i=0; i<VIDDISP_MAX_TEXOVERRIDE_SLOTS; i++ )
	{
		VidDisp.dbgOverrideTex[i] = 0;
		VidDisp.dbgOverrideRes[i] = NULL;
	}

	VidDisp.dbgDisablePostFX = 0;

	VidDisp.global_facesort_angle = DEFAULT_GLOBAL_FACE_RESORT_ANGLE;
	VidDisp.dbgUseFacesortThreshold = 0;
	angle_radians = DEFAULT_GLOBAL_FACE_RESORT_ANGLE * (PI/180.0f);
	VidDisp.dbgFacesortThreshold = cosf(angle_radians);

	VidDisp.VSyncAvailable = 0;
	VidDisp.VSyncMode = 0;
	VidDisp.VSyncOn = -1;


	strncpy( VidDisp.ScreenGrab.name, "screen_grab", COUNT(VidDisp.ScreenGrab.name) );
	VidDisp.takeScreenshot = 0;

	//
	// CREATE VIDEO WINDOW/SCREEN
	//
	VidSetDflt2DCamDim( (float)VidDisp.screenW, (float)VidDisp.screenH  );

	if( (ec=WndOpen(VidDisp.screenW,VidDisp.screenH,VidDisp.fullscreen, SystemInfoGetValue(SYSINFO_GAME_FULLNAME)) ) < 0 )
	{
		SysLog("WndOpen() failed! (ec=%d)\n", ec);
		goto BAIL;
	}

	if( (ec=VidStart()) < 0 )
	{
		SysLog("VidStart() failed! (ec=%d)\n", ec);
		goto BAIL;
	}

	// this may seem like an odd place for this, but it must come after
	// we have opened a window...
#ifdef SYS_PC
	ec = glewInit();
#endif
	WndShowCursor(0);


	// initialize the system font, which requires glewInit to be called first.
	// note that the corresponding FontSysQuit occurs during FontFinal()
	FontSysInit();


BAIL:
	return ec;
} // VidInit()

// JFL 03 Sep 04
void VidFinal(void)
{
} // VidFinal()

// JFL 22 Sep 04
int VidReset(uns reset)
{
	VidDisp.flags&=~(M_VIDDISP_FOG);

#ifdef FORCE_VID_ROTATE_RIGHT
	VidDisp.flags|=M_VIDDISP_ROTATE_RIGHT;
#endif


	/*
	if ( VidDisp.ActiveShader != NULL )
	{
		DisableShaders();
		VidDisp.ActiveShader = NULL;
	}
	*/


	VidDisp.DisableLightGroupLights = 0;
	VidDisp.ReflectionLightGroup = -1;

	// setup dflt fog
	VidDisp.fogMode=GL_LINEAR;
	VidDisp.fogNear=10000.0;
	VidDisp.fogFar=10001.0;
	VidDisp.fogDensity=0.20f;
	VidDisp.fogRGBA[0]=1.0f;
	VidDisp.fogRGBA[1]=1.0f;
	VidDisp.fogRGBA[2]=1.0f;
	VidDisp.fogRGBA[3]=1.0f; // alpha is used for the fog clamp, 0 means no clamp on the fog (go to full fog), 1 means no fog
	VidDisp.flags|=M_VIDDISP_FOG|M_VIDDISP_FOG_C;


	VidDisp.ReflectionMapScale = 1.0f;

	V3SetXYZ(VidDisp.ClearColor,0,0,0);
	V3SetXYZ(VidDisp.ReflectionMapClearColor,0,0,0);

	VidDisp.VSyncOn = -1;
	VidSetVSyncMode(RenderG.DFLT_VSYNC);

	VidSetMinFrameTime(RenderG.DFLT_MINFRAMETIME);
	VidDisp.LoadingScreenActive = 0;


	return 0;
} // VidReset()


//
// IsExtensionSupported
//	Check to see if OpenGL extension is supported
//	from:
//	http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=45
//
// in:
//	szTargetExtension = ptr to character string name of extension
// out:
//	<>0 = supported
// global:
//
// GNP 25 Nov 05
//
uns8 IsExtensionSupported( char* szTargetExtension )
{
	const unsigned char *pszExtensions = NULL;
	const unsigned char *pszStart;
	unsigned char *pszWhere, *pszTerminator;

	// Extension names should not have spaces
	pszWhere = (unsigned char *) strchr( szTargetExtension, ' ' );
	if( pszWhere || *szTargetExtension == '\0' )
		return(0);

	// Get Extensions String
	pszExtensions = glGetString( GL_EXTENSIONS );

	// Search The Extensions String For An Exact Copy
	pszStart = pszExtensions;
	for(;;)
	{
		pszWhere = (unsigned char *) strstr( (const char *) pszStart, szTargetExtension );
		if( !pszWhere )
			break;
		pszTerminator = pszWhere + strlen( szTargetExtension );
		if( pszWhere == pszStart || *( pszWhere - 1 ) == ' ' )
			if( *pszTerminator == ' ' || *pszTerminator == '\0' )
				return(1);
		pszStart = pszTerminator;
	}
	return(0);
//DONE("IsExtensionSupported")
} // IsExtensionSupported

// JFL 03 Sep 04
// JFL 07 Oct 04
int VidStart( )
{
	int ec;
	GLint i1;
	float v[4];
	char buf[128];


	/*
	VidDisp.screenW = screen_width;
	VidDisp.screenH = screen_height;
	VidDisp.screenAspectRatio = aspect_ratio;
	*/

	//
	// OpenGL settings
	//

	VidDisp.apiVendor = (void*)glGetString(GL_VENDOR);
	VidDisp.apiVersion = (void*)glGetString(GL_VERSION);
	VidDisp.apiRenderer = (void*)glGetString(GL_RENDERER);
	VidDisp.apiExtensions = (void*)glGetString(GL_EXTENSIONS);

	StringChangeCase( VidDisp.apiVendor, buf, 0 );
	if ( strstr( buf, "nvidia" ) )
		RenderG.PLATFORM_NVIDIA = 1;
	else if ( strstr( buf, "ati" ) )
		RenderG.PLATFORM_ATI = 1;

#if DEBUG
	SysLog("GL Vendor: %s\n",VidDisp.apiVendor);
	SysLog("GL Version: %s\n",VidDisp.apiVersion);
	SysLog("GL Renderer: %s\n",VidDisp.apiRenderer);

// prints a list of OpenGL extensions
#if 0
	SysLog("GL Extensions:\n");
	s1=VidDisp.apiExtensions;
	while ((s2 = strchr(s1,0x20)) != NULL)
	{
		int pos;
		pos = s2-s1;
		strncpy(tS,s1,pos+1);
		tS[pos+1]=0;
		SysLog("%s\n",tS);
		s1=s2+1;
	}
#endif

#endif //DEBUG

	// Figure out if the platform and video driver can support VSync
#if defined SYS_PC
	if ( strstr(VidDisp.apiExtensions, "WGL_EXT_swap_control") != NULL )
	{
		VidDisp.VSyncAvailable = 1;
		// TODO: Check whether Windows platform can support adaptive VSync
		//if (strstr(VidDisp.apiExtensions, "EXT_swap_control_tear") != NULL )
		//	VidDisp.VSyncAvailable = 2;
	}
#elif defined SYS_LINUX
	// TODO: Add check to see if the Linux platform and the driver can support VSync
	VidDisp.VSyncAvailable = 1;
#endif // defined SYS_PC
		


	// we really don't want nicest here?!?!?
	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_FASTEST);//GL_NICEST);

#if DEBUG
	// 1=bilinear 2=anisotropic
	glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &i1);
	SysLog("GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = %d\n",i1);
#endif //DEBUG

	// glEnable(GL_POLYGON_SMOOTH);

	//Using GL Hints it's not recommended. Performance of Your program will 
	//get much lower. If You want to make antialiasing of polygons try enabling
	//GL_POLYGON_SMOOTH, but remember that You also have to enable GL_BLEND 
	//with glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
	//Else method of antialiasing is multisample, but You can be sure that 
	//it will eat many of FPS

	// http://developer.nvidia.com/object/gdc_ogl_multisample.html
	// Will's research:
	// http://www.opengl.org/resources/tutorials/sig99/advanced99/course_slides/vissim/sld031.htm
	// http://www.nvnews.net/previews/geforce_6600_gt/page_3.shtml
	// http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_filter_anisotropic.txt
	// http://www.opengl.org/resources/tutorials/advanced/advanced98/notes/node37.html
	// http://www.sulaco.co.za/tut4.htm
	// http://www.opengl.org/resources/tutorials/sig99/advanced99/notes/node56.html
	// http://www.flipcode.com/articles/article_advgltextures.shtml

	// set defaults
	// routines must save & restore these settings if changed

	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_FALSE);
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_FALSE);
	glFrontFace(GL_CCW); // front faces counter clock wise
	glDisable(GL_SCISSOR_TEST);
	glDisable(GL_STENCIL_TEST);
	glDisable(GL_COLOR_LOGIC_OP);
	glDisable(GL_INDEX_LOGIC_OP);

	glClearDepth(1.0f);
	glClearStencil(0);

	// default global ambient light
	v[0]=v[1]=v[2]=0;v[3]=1;
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,v);

	glGetIntegerv(GL_MAX_TEXTURE_SIZE,&i1);
	if(i1<2048)
		BP(BP_VIDSTART); // game needs at least 2048x2048 texture size


	ec=0;

	return ec;
} // VidStart()




// from res.c
extern ResDataCam sys2d_cam;
extern ResDataCam sys3d_cam;

void VidSetDflt2DCamDim( float w, float h )
{
	VidDisp.Cam2D_W = w;
	VidDisp.Cam2D_H = h;

	sys2d_cam.trans[0] = VidDisp.Cam2D_W / 2.0f;
	sys2d_cam.trans[1] = VidDisp.Cam2D_H / 2.0f;

	sys2d_cam.orthoWidth = VidDisp.Cam2D_W;
}



void VidSetRecording(int on, char *filename )
{
	if ( on && filename )
	{
		VidDisp.enableRecording=on;
		strncpy(VidDisp.RecordingFile,filename, sizeof(VidDisp.RecordingFile) );
	}
	else
		VidDisp.enableRecording=0;

}


int VidFogInit()
{
	int error_code = 0;
	// load fog settings...
	if (HashTableCreate( &gFogSettings, 128, MemAllocCoreConfig, MemFree ) < -1) {
		SysLog("Failed to create hash table for fog; Game is in an unstable state!\n");
		BP(-1);

		error_code = -2;
		return error_code;
	}
	if (VidLoadFog() < 0) {
		error_code = -1;
	}
	return error_code;

}

int VidSetFogValues( char *name, float	Density, float	Near, float	Far, float	*RGBA  )
{
	int ec = 0;
	char buf[32];
	
	if ( ! name || ! RGBA )
		return -1;

	snprintf( buf,  sizeof(buf), "%f", Density );
	ec = HashTable2dSetStringByString( &gFogSettings, name, "density", buf );
	if ( ec < 0 )
		return ec;
	snprintf( buf,  sizeof(buf), "%f", Near );
	ec = HashTable2dSetStringByString( &gFogSettings, name, "near", buf );
	if ( ec < 0 )
		return ec;
	snprintf( buf,  sizeof(buf), "%f", Far );
	ec = HashTable2dSetStringByString( &gFogSettings, name, "far", buf );
	if ( ec < 0 )
		return ec;

	snprintf( buf,  sizeof(buf), "%f", RGBA[0] );
	ec = HashTable2dSetStringByString( &gFogSettings, name, "red", buf );
	if ( ec < 0 )
		return ec;

	snprintf( buf,  sizeof(buf), "%f", RGBA[1] );
	ec = HashTable2dSetStringByString( &gFogSettings, name, "green", buf );
	if ( ec < 0 )
		return ec;

	snprintf( buf,  sizeof(buf), "%f", RGBA[2] );
	ec = HashTable2dSetStringByString( &gFogSettings, name, "blue", buf );
	if ( ec < 0 )
		return ec;

	snprintf( buf,  sizeof(buf), "%f", RGBA[3] );
	ec = HashTable2dSetStringByString( &gFogSettings, name, "clamp", buf );
	if ( ec < 0 )
		return ec;


	return ec;

}
int VidUseFog( char *name )
{
	if ( name == NULL )
		return 0;
	VidDisp.fogMode = GL_LINEAR;
	VidDisp.fogDensity = HashTable2dConfGetFloat( &gFogSettings, name, "density", VidDisp.fogDensity );
	VidDisp.fogNear = HashTable2dConfGetFloat( &gFogSettings, name, "near", VidDisp.fogNear );
	VidDisp.fogFar = HashTable2dConfGetFloat( &gFogSettings, name, "far", VidDisp.fogFar );
	VidDisp.fogRGBA[0] = HashTable2dConfGetFloat( &gFogSettings, name, "red", VidDisp.fogRGBA[0] );
	VidDisp.fogRGBA[1] = HashTable2dConfGetFloat( &gFogSettings, name, "green", VidDisp.fogRGBA[1] );
	VidDisp.fogRGBA[2] = HashTable2dConfGetFloat( &gFogSettings, name, "blue", VidDisp.fogRGBA[2] );
	VidDisp.fogRGBA[3] = HashTable2dConfGetFloat( &gFogSettings, name, "clamp", VidDisp.fogRGBA[3] );
	VidDisp.flags |= M_VIDDISP_FOG|M_VIDDISP_FOG_C;

	return 0;
}

int FogLoadFile( char *file, void *data )
{
	char *c;
	char name[64];
	int ec;
	HashTable ht = { 0, };
	HashTable *oht;


	StringGetNameFromPath( file, name, sizeof(name), NULL );
	c = strstr(name,".");
	if ( c )
		*c = '\0';

	// maybe a '.blahblah' file (like .svn)
	if ( name[0]=='\0' )
		return 0;

	ec = FileAccess_LoadFileHashTableStringByString( FILEACCESS_TYPE_FOG, file, &ht, MemAllocCoreConfig );
	if ( ec < 0 )
		goto BAIL;

	oht = HashTable2dGetTableByString( &gFogSettings, name );
	if ( oht )
		HashTableFree( oht );

	ec = HashTableSetNodeDataByString( &gFogSettings, name, &ht, sizeof(HashTable) );
	if ( ec < 0 )
		goto BAIL;


	ec = 0;
BAIL:
	if ( ec < 0 ) {
		SysLog( "Error loading fog file: %s\n", file );
	}
	return ec;


}
int VidLoadFog()
{
	return FileAccess_WalkFiles( FILEACCESS_TYPE_FOG, NULL, FILEACCESS_RESULT_MODE_FULLPATHS, FogLoadFile, NULL ); 
}

int VidReloadFog()
{
	HashTableFree( &gFogSettings );
	HashTableCreate( &gFogSettings, 128, MemAllocCoreConfig, MemFree );
	return VidLoadFog();
}


int VidSaveFog( char* fog_name )
{
	char filename[FILEACCESS_MAX_FILENAME_LEN];
	char fullpath[FILEACCESS_MAX_FILENAME_LEN];
	int ec;
	int i,count = 0;
	HashTable *ht;
	char **keys;
	char *name;
	char *buffer;
	int buffer_len;

	keys = NULL;

	count = HashTableGetStringKeys( &gFogSettings, &keys, 0 );
	for ( i = 0 ; i < count; i++ )
	{
		name=keys[i];
		if ( strcmp(fog_name, name) != 0 ) {
			continue;
		}

		ht = HashTable2dGetTableByString( &gFogSettings, name );
		if ( ht )
		{
			snprintf(filename, COUNT(filename), "%s.txt", name );
			ec = FileAccess_GetFileSavePath( FILEACCESS_TYPE_FOG, NULL, filename, fullpath, COUNT(fullpath) );
			/*
			ec = FileAccess_FindFile( FILEACCESS_TYPE_FOG, NULL, filename, fullpath, COUNT(fullpath) );
			if ( ec < 0 )
			{
				// else save to dflt path
				path[0]='\0'; // safety
				FileAccess_GetPath( FILEACCESS_TYPE_FOG, path, COUNT(path) );
				snprintf(fullpath, COUNT(fullpath), "%s/%s", path, filename );
			}
			*/
			buffer=NULL;
			buffer_len=0;
			ec = FileAccess_SaveFileHashTableStringByString( FILEACCESS_TYPE_FOG, fullpath, ht );
			if ( ec < 0 )
			{
				SysLog( "Error saving fog file '%s'\n", fullpath );
				return ec;
			}
		}
	}

	MemFree( keys );
	keys = NULL;

	return 0;
	//	return HashTable2dSaveStringByString( &gFogSettings, buf, ".", " = " );
}



/*
int WaterLoadFile( char *file, void *data )
{
	int count;
	char *c;
	char name[64];
	int ec;
	VidWaterParams vwp = { 0, };

	StringGetNameFromPath( file, name, sizeof(name), NULL );
	c = strstr(name,".");
	if ( c )
		*c = '\0';

	// maybe a '.blahblah' file (like .svn)
	if ( name[0]=='\0' )
		return 0;

	ec = FileAccess_LoadFileRTDT( FILEACCESS_TYPE_WATER, file, "VidWaterParams", &vwp );
	if ( ec < 0 ) {
		SysLog( "Error loading water file: %s\n", file );
		return ec;
	}

	strcpy( vwp.name, name );

	count = *(int*)data;
	gWaterSets.params[count] = vwp;
	count++;
	*(int*)data = count;


	return 0;


}


int VidLoadWater()
{
	int i;
	int ec;
	int count = 1;
	float trans[3],rot[3];
	V3Cpy(trans,gWaterSets.trans);
	V3Cpy(rot,gWaterSets.rot);
	memset(&gWaterSets,0,sizeof(gWaterSets));

	ec = FileAccess_WalkFiles( FILEACCESS_TYPE_WATER, NULL, FILEACCESS_RESULT_MODE_FULLPATHS, WaterLoadFile, &count  );

	// ec = RTDataTypeParser_LoadFromFile( &gRTDTParser, "VidWaterSettings", &gWaterSets, buf, NULL, NULL );

	for ( i = 0; i < COUNT(gWaterSets.params); i++ )
	{		
		gWaterSets.params[i].wave[0].scale[2]=1.0f; 
		gWaterSets.params[i].wave[1].scale[2]=1.0f;
		gWaterSets.params[i].LastUpdate = 0;
	}
	V3Cpy(gWaterSets.trans,trans);
	V3Cpy(gWaterSets.rot,rot);

	// Set up the first entry in the list as the "default" entry
	strncpy(gWaterSets.params[0].name, "default", sizeof(gWaterSets.params[0].name) - 1);
	gWaterSets.params[0].uNormalMapAmp =	1.0f;
	gWaterSets.params[0].uDistortionAmp =	0.080508f;
	gWaterSets.params[0].uVertAmp =			0.0f;
	gWaterSets.params[0].uMinReflectivity =	0.216102f;
	gWaterSets.params[0].uReflectionScale =	0.360170f;
	gWaterSets.params[0].uReflectionDistortion =	0.881356;
	V2Zero(gWaterSets.params[0].uVertSpeed);
	V2Zero(gWaterSets.params[0].uVertFreq);
	V3Zero(gWaterSets.params[0].wave[0].rot);
	V3Zero(gWaterSets.params[0].wave[0].speed);
	V3Zero(gWaterSets.params[0].wave[0].pos);
	V3SetXYZ(gWaterSets.params[0].wave[0].scale, 0.0f, 0.0f, 1.0f);
	V3Zero(gWaterSets.params[0].wave[1].rot);
	V3Zero(gWaterSets.params[0].wave[1].speed);
	V3Zero(gWaterSets.params[0].wave[1].pos);
	V3SetXYZ(gWaterSets.params[0].wave[1].scale, 0.0f, 0.0f, 1.0f);
	gWaterSets.params[0].LastUpdate = 0;
	

	return ec;
}

int VidReloadWater()
{
	return VidLoadWater();
}

int VidSaveWater( char *water_name )
{
	char filename[FILEACCESS_MAX_FILENAME_LEN];
	char fullpath[FILEACCESS_MAX_FILENAME_LEN];

	int ec,i;
	VidWaterParams *vwp;

	for ( i = 0; i < COUNT(gWaterSets.params); i++ )
	{		
		vwp = &gWaterSets.params[i];

		if ( (vwp->name[0] == '\0') || (strcmp(water_name, vwp->name) != 0) ) {
			continue;
		}

		snprintf(filename, COUNT(filename), "%s.txt",  vwp->name );

		ec = FileAccess_GetFileSavePath( FILEACCESS_TYPE_WATER, NULL, filename, fullpath, COUNT(fullpath) );
		if ( ec < 0 )
			return ec;

		ec = FileAccess_SaveFileRTDT( FILEACCESS_TYPE_WATER, fullpath, "VidWaterParams", vwp, 0 );
		return ec;
	}

	// Did not save anything
	ec = -1;
	return ec;
}

int VidWaterSetReflectionPlaneRes( char *name )
{
	Res *r;
	ResDataKan *kan;
	ResDataKanKey *key;
	if ( ! name )
		return -1;
	r = ResFindSubNth( NULL, name, RESSUB_KAN, 0 );
	if ( ! r || ! r->data )
		return -2;
	kan=(ResDataKan*)r->data;
	key=(ResDataKanKey*)&kan[1];

	VidWaterSetReflectionPlane( &key->rts[RESDATAKANKEY_CH_TX], &key->rts[RESDATAKANKEY_CH_RX] );
	return 0;
}


void VidWaterSetReflectionPlane( float *trans, float *rot )
{
	if ( ! rot || ! trans )
		return;
	V3Cpy( gWaterSets.rot, rot );
	V3Cpy( gWaterSets.trans, trans );
}

int VidWaterUpdatePos(int preset)
{
	int i;
	float TimeDelta;
	if ( preset > COUNT(gWaterSets.params) || preset < 0 )
		return -1;
	if ( gWaterSets.params[preset].LastUpdate==0 || gWaterSets.params[preset].LastUpdate != GameWaveTime )
	{
		TimeDelta = (float)GameLoopDelta / 200000.0f;

		for ( i = 0; i < 3; i++ )
		{
			gWaterSets.params[preset].wave[0].pos[i] += TimeDelta * gWaterSets.params[preset].wave[0].speed[i];
			gWaterSets.params[preset].wave[1].pos[i] += TimeDelta * gWaterSets.params[preset].wave[1].speed[i];
			// wrap around 1.0
			gWaterSets.params[preset].wave[0].pos[i] -= (int)gWaterSets.params[preset].wave[0].pos[i];
			gWaterSets.params[preset].wave[1].pos[i] -= (int)gWaterSets.params[preset].wave[1].pos[i];
		}


		gWaterSets.params[preset].LastUpdate = GameWaveTime;
	}
	return 0;

}

int VidWaterGetPresetByName( char *name )
{
	int i;
	if ( ! name || name[0] == '\0' )
		return 0;
	for ( i = 0; i < COUNT(gWaterSets.params); i++ )
	{
		if ( strcmp(name,gWaterSets.params[i].name) == 0 )
			return i;
	}
	return 0;
}
*/

void VidSetGfxCardBrightness(float brightness)
{
#if defined(SYS_LINUX)
	char cmd[64]={0};

	// This command assumes that "export DISPLAY=0:0" has been called at some point. Should be called in a start-up script.
	sprintf(cmd, "nvidia-settings -a Brightness=%0.2f", brightness);
	system(cmd);
#endif
}

void VidSetGfxCardContrast(float contrast)
{
#if defined(SYS_LINUX)
	char cmd[64]={0};

	// as of driver nvidia 275.43, setting contrast resets brightness setting (and vice versa)
	// so can only pick one of the two, for now we pick brightness
	// This command assumes that "export DISPLAY=0:0" has been called at some point. Should be called in a start-up script.
	//sprintf(cmd, "nvidia-settings -a Contrast=%0.2f", contrast);
	//system(cmd);
#endif
}

void VidSetGlobalFaceResortAngle(float angle)
{
	VidDisp.global_facesort_angle = angle;
}


void VidSetVSyncMode(int mode)
{
	switch(mode)
	{
	case VID_VSYNC_MODE_OFF:
	default:
		VidEnableVSync(0);
		break;

	case VID_VSYNC_MODE_ON:
		VidEnableVSync(1);
		break;

	case VID_VSYNC_MODE_ON_SMART:
		VidEnableVSync(-1);
		break;
	}

	VidDisp.VSyncMode = mode;
}


void VidEnableVSync(int on)
{
	if ( on != VidDisp.VSyncOn )
	{
	#if defined SYS_LINUX
		//glXSwapIntervalSGI(on);
	#else	// defined SYS_LINUX (system is Windows)
		wglSwapIntervalEXT(on);
	#endif	// defined SYS_LINUX
	}
	VidDisp.VSyncOn = on;
}


void VidSetMinFrameTime(uns64 msecs)
{
	VidDisp.MinFrameTime = msecs;
}


void VidLoadingScreenAdv( char *text )
{
	float m4[16];
	char buf[256];

	dbgLogGLErrors( "Before LoadScreen" );


 	glViewport( 0, 0, VidDisp.screenW, VidDisp.screenH );
	glClearColor( 0, 0, 0, 0 );
	glClear( GL_COLOR_BUFFER_BIT );

	dbgLogGLErrors( "Before proj mat" );


	RenderState_SetColor(1, 1, 1, 1.0f);
	RenderState_SetMatrixMode(GL_PROJECTION);
	camOrtho( 0, VidDisp.screenW, VidDisp.screenH, 0, 1.0f, 1000.0f, m4 );
	glLoadMatrixf( m4 );

	dbgLogGLErrors( "Before model view" );

	RenderState_SetMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef( 0, 0, -100.0f );

	dbgLogGLErrors( "Before cull face" );

	RenderState_SetCullFace( RENDERSTATE_CULL_FACE_NONE );

	dbgLogGLErrors( "Before bind tex" );

	RenderState_BindTex(0, GL_TEXTURE0, 0 );

	dbgLogGLErrors( "Before LoadScreen Font Draws" );


	snprintf( buf, COUNT(buf), "Welcome to %s v%s\n", SystemInfoGetValue(SYSINFO_GAME_FULLNAME), SystemInfoGetValue(SYSINFO_GAME_VER));
	FontSysX(buf, 20, 20, 1024, 1024);

	snprintf( buf, COUNT(buf), "Initializing Systems, Please Be Patient.\n" );
	FontSysX(buf, 20, 35, 1024, 1024);
	FontSysX(text, 20, 50, 1024, 1024);

	WndSwap(WndCur());

	RenderState_SetCullFace( RENDERSTATE_CULL_FACE_BACK );
	RenderState_SetMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	RenderState_SetMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	dbgLogGLErrors( "After LoadScreen" );

	return;

}

// EOF



makefile tends to be from the G6 Engine.

# makefile -- gnu make
# g6 engine

# get the subversion repo rev number
SVNDEF := -D'G6_SVN_REV="$(shell /usr/bin/svnversion -n /pm/g6/g6engine/. | sed -e 's/.*://g' )"' -D'LIBRARIES_SVN_REV="$(shell /usr/bin/svnversion -n /pm/libraries/.)"'

COFILES = $(patsubst %.c,%.o,$(wildcard g6/*.c))
CPPOFILES = $(patsubst %.cpp,%.opp,$(wildcard g6/*.cpp))

TOOL3OFILES = $(patsubst %.cpp,%.opp,$(wildcard g6/tool3/*.cpp))
DIAGOFILES = $(patsubst %.c,%.o,$(wildcard g6/Diag/*.c))

TARGETLIB = libg6.a

DEPENDTESTFILE = makedeptest
DEPENDLIBFILE = makedeplib

CC	= gcc
CPP	= g++
CFLAGS = -DSYS_LINUX
CFLAGS+=$(SVNDEF)
#CFLAGS  += -O0 -ggdb
#CFLAGS  += -O3
#CFLAGS += -DDEBUG
#CFLAGS += -DPRODUCTION -DNO_TOOL

# "-DLINUX" is needed for PhysX!!!!!
CFLAGS += -DLINUX -fno-stack-protector
CFLAGS += -I g6
CFLAGS += -I /pm/include
CFLAGS += -I /pm/include/libtheoraplayer
CFLAGS += -I /pm/include/bullet
CFLAGS += -I /pm/include/bullet/BulletFileLoader
CFLAGS += -I /pm/include/bullet/BulletWorldImporter
CFLAGS += -I /usr/include/SDL
CFLAGS +=-I /usr/X11/include
CPPFLAGS=$(CFLAGS)
LINKFLAGS  =  -Xlinker -Map -Xlinker $(TARGET).map

.PHONY: all clean debug prod

all: debug 

debug: CFLAGS+=-O0 -DDEBUG -ggdb
debug: CPPFLAGS=$(CFLAGS)
debug: $(TARGETLIB)


prod: CFLAGS+=-O3 -DPRODUCTION -DNO_TOOL -DUSE_DONGLE_NOISE_THREAD -ggdb
prod: CPPFLAGS=$(CFLAGS)
prod: $(TARGETLIB)


$(TARGETLIB) : $(COFILES) $(CPPOFILES) $(TOOL3OFILES) $(DIAGOFILES) makefile
	ar rs $(TARGETLIB) $(COFILES) $(CPPOFILES) $(TOOL3OFILES) $(DIAGOFILES)
	-mkdir -p /pm/include/g6
	-mkdir -p /pm/include/g6/tool3
	-mkdir -p /pm/include/g6/Diag
	-cp $(TARGETLIB) /pm/lib
	-cp g6/*.h /pm/include/g6
	-cp g6/tool3/*.h /pm/include/g6/tool3
	-cp g6/tool3/*.hpp /pm/include/g6/tool3
	-cp g6/Diag/*.h /pm/include/g6/Diag

clean:
	-rm $(COFILES) $(CPPOFILES) $(TOOL3OFILES) $(DIAGOFILES) $(TARGETLIB)


g6/%.o : g6/%.c
	$(CC) $(CFLAGS) -c $< -o $@

g6/%.opp : g6/%.cpp
	$(CPP) $(CPPFLAGS) -c $< -o $@
	
g6/tool3/%.opp : g6/tool3/%.cpp
	$(CPP) $(CPPFLAGS) -c $< -o $@

g6/Diag/%.o : g6/Diag/%.c
	$(CC) $(CFLAGS) -c $< -o $@


A Samba config for the eyes of the said companies.

#
#  Generic Samba configuration file for Raw Thrills / PlayMechanix 
#

#======================= Global Settings =======================

[global]

## Browsing/Identification ###

	workgroup = WORKGROUP
	server string = %h server (Samba, Ubuntu)
	dns proxy = no
	name resolve order = lmhosts host wins bcast

#### Networking ####
#### Debugging/Accounting ####

	log file = /var/log/samba/log.%m
	max log size = 1000
	syslog = 0
	panic action = /usr/share/samba/panic-action %d


####### Authentication #######

	security = user
	encrypt passwords = true
	passdb backend = tdbsam
	obey pam restrictions = yes
	unix password sync = yes
	
	passwd program = /usr/bin/passwd %u
	passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .

	pam password change = yes
	map to guest = bad user

########## Domains ###########
########## Printing ##########
############ Misc ############

	socket options = TCP_NODELAY

	# Some defaults for winbind
	idmap uid = 10000-20000
	idmap gid = 10000-20000
	template shell = /bin/bash
	usershare max shares = 100
	usershare allow guests = no

#======================= Share Definitions =======================

[pm]
	path = /pm
	writeable = yes
	browseable = yes
	valid users = raw
	
[pm_collection]
	path = /pm_collection
	writeable = yes
	browseable = yes
	valid users = raw

	
# EOF