/*
	Combat Team 2 initialization code
	Made by Ismo Horppu on 1996 - 1997
*/

#include <stdio.h>
#include <mem.h>
#include <go32.h>
#include <dos.h>
#include <stdlib.h>
#include <dpmi.h>
#include <time.h>
#include <conio.h>
#include <sys/farptr.h>

#include "types.h"
#include "ct2gen.h"
#include "ct2graph.h"
#include "ct2pal.h"
#include "m320x200.h"
#include "emouse.h"
#include "ct2eng.h"
#include "decomp.h"
#include "font.h"
#include "kb.h"
#include "okb.h"
#include "timer.h"
#include "rnd.h"
#include "sb_lib.h"
#include "sbdetect.h"
#include "sb_misc.h"
#include "init.h"
#include "button.h"
#include "event.h"
#include "ct2cred.h"
#include "window.h"
#include "ecadd.h"
#include "efile.h"
#include "keytable.h"

/*
	loads samples
*/
int InitSamples (void)
{
	int sample_counter;
	
	for (sample_counter = 0; sample_counter < CURRENT_CT2_SAMPLES; sample_counter++){
		sample[sample_counter] = sb_load_sample (samplefile[sample_counter], _SB_RAW);
		
		if (sample[sample_counter] == NULL){
	  	textcolor (LIGHTRED);
			cprintf ("Error %d on samplefile %s\n\r\n\r", sb_digi_error, samplefile[sample_counter]);
			return -1;
		}
	}
	
	return 0;
}

void CorruptMessage (char *fname)
{
 	textcolor (LIGHTRED);
	cprintf ("Corrupted config file %s - please run restcfg.bat !\n\r", fname);
}

/*
	frees samples
*/
void FreeSamples (void)
{
	int sample_counter;
	
	for (sample_counter = 0; sample_counter < CURRENT_CT2_SAMPLES; sample_counter++){
		sb_free_sample (sample[sample_counter]);
	}
}

/*	
	loads CT2 config file 
*/
int LoadConfig (char *fname)
{
	int stat;
	int counter;
	
	if ((f = fopen (fname, "rb")) == NULL){
		textcolor (LIGHTRED);
		cprintf ("Can't find config file %s - please run restcfg.bat !\n\r", fname);
		return -1;
	
	}
	
	for (counter = 0; counter < MAX_KEYS; counter++){
		keys[counter] = fgetc (f);
		
		if (feof (f)){
			fclose (f);
			CorruptMessage (fname);
			return -2;
		}
	}
	
	stat = fread (&scard, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sc_base, 1, 2, f);

	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sc_dma_lo, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sc_dma_hi, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sc_irq, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sc_type, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&default_players, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sound_amplify, 1, 2, f);
	
	if (stat != 2){
		fclose (f);		
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&brightness, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sc_force_stereo, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&sc_ai, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&human_players, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&silent_AI_turn, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&activate_music, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&MouseControlFlag, 1, 1, f);
	
	if (stat != 1){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&keyfirstdelay, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&keynextdelay, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	stat = fread (&firedelay, 1, 2, f);
	
	if (stat != 2){
		fclose (f);
		CorruptMessage (fname);
		return -2;
	}
	
	fclose (f);
	return 0;
}

/*
	saves config file
*/
int SaveConfig (char *fname)
{
	int stat;
	
	if ((f = fopen (fname, "wb")) == NULL){
	 	textcolor (LIGHTRED);
		cprintf ("Can't open config file %s\n\r", fname);
		return -1;
	}
	
	stat = fwrite (&keys[0], 1, 15, f);
	
	if (stat != 15){
		fclose (f);
		return -2;
	}
	
	fwrite (&scard, 1, 1, f);
	fwrite (&sc_base, 1, 2, f);
	fwrite (&sc_dma_lo, 1, 1, f);
	fwrite (&sc_dma_hi, 1, 1, f);
	fwrite (&sc_irq, 1, 1, f);
	fwrite (&sc_type, 1, 1, f);
	
	fwrite (&default_players, 1, 2, f);
	fwrite (&sound_amplify, 1, 2, f);
	fwrite (&brightness, 1, 2, f);
	fwrite (&sc_force_stereo, 1, 1, f);
	fwrite (&sc_ai, 1, 1, f);
	
	fwrite (&human_players, 1, 2, f);
	fwrite (&silent_AI_turn, 1, 2, f);
	fwrite (&activate_music, 1, 2, f);
	fwrite (&MouseControlFlag, 1, 1, f);
	fwrite (&keyfirstdelay, 1, 2, f);
	fwrite (&keynextdelay, 1, 2, f);
	fwrite (&firedelay, 1, 2, f);

	fclose (f);
	return 0;
}

/*
	opens file for reading
*/
int ReadOpenFile (char *fname)
{
	if ((f = fopen (fname, "rb")) == NULL){
	 	textcolor (LIGHTRED);
		cprintf ("File %s not found\n\r", fname);
		return -1;
	}

	return 0;
}

/*
	puts soldiers on map
*/
void PutSoldiersOnMap (void)
{
	int x, y, z;
	int zsoldier;
	int zplayer;
	int dir;
	int frame;
	int c = 0;
	
	for (zplayer = 0; zplayer < default_players; zplayer++){
		for (zsoldier = 0; zsoldier < MAX_START; zsoldier++){
			x = PlayerStartX[zsoldier][zplayer];
			y = PlayerStartY[zsoldier][zplayer];
			z = PlayerStartZ[zsoldier][zplayer];
			dir = rnd (4);
			frame = rnd (7);
			Object[x][y][z] = dir * 7 + frame;
			health[zplayer][zsoldier] = 100;
		
			if (zplayer > human_players - 1){
				weapon[c] = rnd (4);
				ammo[c] = ammo_count[weapon[c]];
			}
			
			else{
				weapon[c] = 255;
				ammo[c] = 0;
			}
			
			c++;
			
			if (zplayer <= human_players - 1){
				player_type[zplayer] = HUMAN;
			}
			
			else{
				player_type[zplayer] = COMPUTER;
			}
		}
	}
}

/*
	Loads Combat Team 2 map to memory
*/
int LoadMap (char *mapfile)
{
	long counter;
	BYTE value;
	WORD items;
	DWORD crc;
	int bstat;
	int x, y, z;
	int plr;

	// clear start positions counts for each player
	for (counter = 0; counter < PLAYERS; counter++){
		startpos[counter] = 0;
	}
	
	// load game map
	bstat = ReadOpenFile (mapfile);

	if (bstat != 0){
		return bstat + 300;
	}

	crc = 0;

	// load in mapblocks
	for (z = 0; z < Zlevels; z++){
		for (y = 0; y < MapHeight; y++){
			for (x = 0; x < MapWidth; x++){
				items = fread (&value, 1, 1, f);

				if (items != 1){
					fclose (f);
					cprintf ("File %s run out of data (file is corrupted)\n\r", mapfile);
					return -7;
				}

				crc += (DWORD) value;

				if (value >= 63 && value <= 66){
					plr = value - 63;

					if (startpos[plr] < MAX_START){
						PlayerStartX[startpos[plr]][plr] = x;
						PlayerStartY[startpos[plr]][plr] = y;
						PlayerStartZ[startpos[plr]][plr] = z;
						startpos[plr]++;
					}

					value = 9;
				}

				if (value >= 59 && value <= 62){
					plr = value - 59;

					if (startpos[plr] <= MAX_START){
						PlayerStartX[startpos[plr]][plr] = x;
						PlayerStartY[startpos[plr]][plr] = y;
						PlayerStartZ[startpos[plr]][plr] = z;
						startpos[plr]++;
					}

					value = 0;
				}

				Map[x][y][z] = value;
			}
		}
	}

	// check is there enough start positions
	for (x = 0; x < PLAYERS; x++){
		if (startpos[x] < 8){
			cprintf ("Player %d hasn't got 8 start positions (only %d/8)\n\r", x + 1, startpos[x]);
			cprintf ("There must be 8 start positions for all players !!!\n\r");
			return -8;
		}
	}

	for (x = 0; x < MapWidth; x++){
		for (y = 0; y < MapHeight; y++){
			for (z = 0; z < Zlevels; z++){
				Object[x][y][z] = 255;
				MapTeam[x][y][z] = 255;	// none
			}
		}
	}

	PutSoldiersOnMap ();

	manX = PlayerStartX[0][0];
	manY = PlayerStartY[0][0];
	manZ = PlayerStartZ[0][0];
	startX = manX;
	startY = manY;
	startZ = manZ;
	
	// load in light levels
	crc = 0;
	for (z = 0; z < Zlevels; z++){
		for (y = 0; y < MapHeight; y++){
			for (x = 0; x < MapWidth; x++){
				items = fread (&value, 1, 1, f);

				if (items != 1){
					fclose (f);
					cprintf ("File %s run out of data (file is corrupted)\n\r", mapfile);
					return -9;
				}

				LightLevel[x][y][z] = 7 - value;
				crc += (DWORD) value;
			}
		}
	}

	fclose (f);
	return 0;
}

/*
	loads game palette (equal to DP2's default palette)
*/
int LoadPalette (void)
{
	int bstat;
	DWORD crc;
	long counter;
	WORD items;
	BYTE value;

	cprintf ("Loading .\\data\\palette.dat\n\r");
	bstat = ReadOpenFile (".\\data\\palette.dat");

	if (bstat != 0){
		return bstat + 400;
	}

	crc = 0;
	for (counter = 0; counter < PalEntries; counter++){
		items = fread (&value, 1, 1, f);

		if (items != 1){
			fclose (f);
			cprintf ("File .\\data\\palette.dat run out of data (file is corrupted)\n\r");
			return -10;
		}

		Palette[counter] = value;
		crc += (DWORD) value;
	}

	fclose (f);
	return 0;
}

/*
	initalizes Combat Team II's data
*/
int InitData (void)
{
	long counter;
	BYTE value;
	WORD value16;
	WORD items;
	DWORD crc;
	int bstat;
	int x, y, z;
	int plr;
	int rc;

	cprintf ("Allocating menuPTR\n\r");
	if ((menuPTR = (BYTE *) malloc (78 * 128)) == NULL){
		cprintf ("Not enough memory for mouse pop menus\n\r");
		return -1;
	}

	allocated += 78 * 128;
	menu_init = 1;

	cprintf ("Allocating Mode 0x13 (320x200x8b) Virtual Buffer\n\r");
	if ((VB = (BYTE *) malloc (64000)) == NULL){
		cprintf ("Not enough memory for virtual buffer\n\r");
		return -2;
	}

	allocated += 64000;
	vb_init = 1;

	cprintf ("Allocating MousePointers\n\r");
	if ((mousePTR = (BYTE *) malloc (16 * 16 * MousePointers)) == NULL){
	 	textcolor (LIGHTRED);
		cprintf ("Not enough memory for mouse pointers\n\r");
		return -3;
	}

	allocated += 16 * 16 * MousePointers;
	mouse_init = 1;

	cprintf ("Loading .\\data\\menus.dat\n\r");
	// load mouse pop menu (disabled)
	bstat = ReadOpenFile (".\\data\\menus.dat");
	
	if (bstat != 0){
	 	textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\menus.dat\n\r", bstat);
		return bstat + 100;
	}

	crc = 0;
	for (counter = 0; counter < (DWORD) 78 * 128; counter++){
		items = fread (&value, 1, 1, f);

		if (items != 1){
			fclose (f);
			textcolor (LIGHTRED);
			cprintf ("File .\\data\\menus.dat run out of data (file is corrupted)\n\r");
			return -5;
		}

		menuPTR[counter] = value;
		crc += (DWORD) value;
	}

	fclose (f);
	
	cprintf ("Loading .\\data\\pointers.dat\n\r");
	// load game pointers (disabled)
	bstat = ReadOpenFile (".\\data\\pointers.dat");
	
	if (bstat != 0){
	 	textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\pointers.dat\n\r", bstat);
		return bstat + 200;
	}

	crc = 0;
	for (counter = 0; counter < (DWORD) MousePointers * MousePointerWidth * MousePointerHeight; counter++){
		items = fread (&value, 1, 1, f);

		if (items != 1){
			fclose (f);
		 	textcolor (LIGHTRED);
			cprintf ("File .\\data\\pointers.dat run out of data (file is corrupted)\n\r");
			return -6;
		}

		mousePTR[counter] = value;
		crc += (DWORD) value;
	}

	fclose (f);

	cprintf ("Loading .\\maps\\map.dat\n\r");
	// call map load routine
	bstat = LoadMap (".\\maps\\map.dat");

	if (bstat != 0){
	 	textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\maps\\map.dat\n\r", bstat);
		return bstat;
	}
	
	// check is there enough start positions
	for (x = 0; x < PLAYERS; x++){
		if (startpos[x] < 8){
			textcolor (LIGHTRED);
			cprintf ("Player %d hasn't got 8 start positions (only %d/8)\n\r", x + 1, startpos[x]);
			cprintf ("There must be 8 start positions for all players !!!\n\r");
			return -8;
		}
	}

	for (x = 0; x < MapWidth; x++){
		for (y = 0; y < MapHeight; y++){
			for (z = 0; z < Zlevels; z++){
				Object[x][y][z] = 255;
				MapTeam[x][y][z] = 255;	// none
			}
		}
	}

	PutSoldiersOnMap ();

	manX = PlayerStartX[0][0];
	manY = PlayerStartY[0][0];
	manZ = PlayerStartZ[0][0];
	startX = manX;
	startY = manY;
	startZ = manZ;

	cprintf ("Loading .\\data\\palette.dat\n\r");
	// load game map
	bstat = ReadOpenFile (".\\data\\palette.dat");

	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\palette.dat\n\r", bstat);
		return bstat + 400;
	}

	crc = 0;
	for (counter = 0; counter < PalEntries; counter++){
		items = fread (&value, 1, 1, f);

		if (items != 1){
			fclose (f);
			textcolor (LIGHTRED);
			cprintf ("File .\\data\\palette.dat run out of data (file is corrupted)\n\r");
			return -10;
		}

		Palette[counter] = value;
		crc += (DWORD) value;
	}

	fclose (f);

	cprintf ("Loading .\\data\\ct2ptrs.dat\n\r");
	bstat = ReadOpenFile (".\\data\\ct2ptrs.dat");
	
	if (bstat != 0){
	 	textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\ct2ptrs.dat\n\r", bstat);
		return bstat + 600;
	}
	
	for (crc = 0; crc < 16; crc++){
		for (counter = 0; counter < 16; counter++){
			selectPTR[crc][counter] = fgetc (f);
		}
	}
	
	for (crc = 0; crc < 16; crc++){
		for (counter = 0; counter < 16; counter++){
			targetPTR[crc][counter] = fgetc (f);
		}
	}
	
	fclose (f);
	
	// init rest data here
	bstat = InitRestData ();

	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("InitRestData returned error %d\n\r", bstat);
		return bstat + 500;
	}

	cprintf ("Loading .\\data\\5x6font.dat\n\r");
	/*
		font load code
	*/
	bstat = LoadFonts (".\\data\\5x6font.dat");

	if (bstat != 0){
	 	textcolor (LIGHTRED);
		cprintf ("LoadFonts returned error %d with file .\\data\\5x6font.dat\n\r", bstat);
		return -11;
	}
	
	bstat = InitCADD ();

	if (bstat != 0){
  	textcolor (LIGHTRED);
		cprintf ("InitCADD returned error %d\n\r", bstat);
		return -12;
	}

	CADD_init = 1;
	Set_Timer (1000);
	timer_init = 1;
	Set_Keyboard ();
	kb_init = 1;
	return 0;
}

/*
	loads in additional CT2 data
*/
int InitRestData (void)
{
	int bstat;
	FILE *df;
	long c;
	
	cprintf ("Loading .\\data\\block.cdf\n\r");
	bstat = ReadDataFile (".\\data\\block.cdf");

	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\block.cdf\n\r", bstat);
		return bstat;
	}
	
	cprintf ("Decompressing block.cdf\n\r");
	DeCompressedSize ();

	if ((TargetPointer = (BYTE *) malloc (RawSize)) == NULL){
		textcolor (LIGHTRED);
		cprintf ("Not enough memory for target pointer (block)\n\r");
		return -12;
	}

	allocated += RawSize;
	DeCompressMemory ();
	free (DataPointer);	// data pointer can now be freed
	blockPTR = TargetPointer;
	block_init = 1;
	fclose (f);
	
	/*
		new sprite load code
	*/
	
	cprintf ("Loading .\\data\\sprite.cdf\n\r");
	bstat = ReadDataFile (".\\data\\sprite.cdf");

	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\sprite.cdf\n\r", bstat);
		return bstat;
	}
	
	cprintf ("Decompressing sprite.cdf\n\r");
	DeCompressedSize ();	// calculate raw sprite data size

	// allocate target memory area
	if ((TargetPointer = (BYTE *) malloc (RawSize + 16384L)) == NULL){
		textcolor (LIGHTRED);
		cprintf ("Not enough memory for target pointer (sprite)\n\r");
		return -13;
	}

	allocated += RawSize + 16384L;
	DeCompressMemory ();	// decompress packed sprite data to memory
	free (DataPointer);	// data pointer can now be freed
	spritePTR = TargetPointer;	// target pointer will be auto. freed
	fclose (f);
	sprite_init = 1;

	/*
		load dead.dat file
		(in end of sprite frames)
	*/
	
	cprintf ("Loading .\\data\\dead.dat\n\r");

	if ((df = fopen (".\\data\\dead.dat", "rb")) == NULL){
		textcolor (LIGHTRED);
		cprintf ("File .\\data\\dead.dat not found\n\r");
		return -14;
	}
	
	for (c = 0; c < 16384; c++){
		spritePTR[RawSize + c] = fgetc (df);
	}
	
	fclose (df);

	/* 
		new art load code (enabled now !!!)
	*/

	cprintf ("Loading .\\story\\art.cdf\n\r");
	bstat = ReadDataFile (".\\story\\art.cdf");
	
	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\story\\art.cdf\n\r", bstat);
		return bstat;
	}

	cprintf ("Decompressing art.cdf\n\r");	
	DeCompressedSize ();

	// allocate target memory area
	if ((TargetPointer = (BYTE *) malloc (RawSize)) == NULL){
		textcolor (LIGHTRED);
		cprintf ("Not enough memory for target pointer (art)\n\r");
		return -4;
	}

	allocated += RawSize;
	DeCompressMemory ();	// decompress packed sprite data to memory
	free (DataPointer);	// data pointer can now be freed
	artPTR = TargetPointer;	// target pointer will be auto. freed*/
	fclose (f);
	art_init = 1;
	
	/*
		load CT2 start picture
	*/
	
	cprintf ("Loading .\\data\\ct2s.pic\n\r");
	bstat = ReadDataFile (".\\data\\ct2s.pic");
	
	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\ct2s.pic\n\r", bstat);
		return bstat;
	}
	
	cprintf ("Decompressing ct2s.pic\n\r");
	DeCompressedSize ();
	
	if ((TargetPointer = (BYTE *) malloc (RawSize)) == NULL){
		textcolor (LIGHTRED);
		cprintf ("Not enough memory for start picture\n\r");
		return -15;
	}
	
	allocated += RawSize;
	DeCompressMemory ();
	free (DataPointer);	// data pointer can now be freed
	pic1_ptr = TargetPointer;
	fclose (f);
	pic1_init = 1;

	cprintf ("Loading .\\data\\mapsel.pic\n\r");
	bstat = ReadDataFile (".\\data\\mapsel.pic");
	
	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\mapsel.pic\n\r", bstat);
		return bstat;
	}
	
	cprintf ("Decompressing mapsel.pic\n\r");
	DeCompressedSize ();
	
	if ((TargetPointer = (BYTE *) malloc (RawSize)) == NULL){
		textcolor (LIGHTRED);
		cprintf ("Not enough memory for map select picture\n\r");
		return -15;
	}
	
	allocated += RawSize;
	DeCompressMemory ();
	free (DataPointer);	// data pointer can now be freed
	pic2_ptr = TargetPointer;
	fclose (f);
	pic2_init = 1;
	
	cprintf ("Loading .\\data\\shop.pic\n\r");
	bstat = ReadDataFile (".\\data\\shop.pic");
	
	if (bstat != 0){
		textcolor (LIGHTRED);
		cprintf ("ReadDataFile returned error %d with file .\\data\\shop.pic\n\r", bstat);
		return bstat;
	}
	
	cprintf ("Decompressing shop.pic\n\r");
	DeCompressedSize ();
	
	if ((TargetPointer = (BYTE *) malloc (RawSize)) == NULL){
		textcolor (LIGHTRED);
		cprintf ("Not enough memory for shop picture\n\r");
		return -15;
	}
	
	allocated += RawSize;
	DeCompressMemory ();
	free (DataPointer);	// data pointer can now be freed
	pic3_ptr = TargetPointer;
	fclose (f);
	pic3_init = 1;
	
	bstat = InitCreditScroller ();
	if (bstat != 0) return bstat;
	credit_init = 1;
	return 0;
}

/*
	displays intro text
*/
int IntroText (char *fname, int sx, int sy)
{
	int x, y;
	FILE *f;
	char text_buffer[80];

	x = sx;
	y = sy;

	if ((f = fopen (fname, "rb")) == NULL) return -1;

	while (1){
		fgets (text_buffer, 80, f);
		if (feof(f)) break;
		DisplayString (text_buffer, sx, sy);
		sy += XSCALEDHEIGHT + 1;

		if (sy >= 199){
			break;
		}
	}

	fclose (f);
	return 0;
}

/*
	displays start intro
*/
void Intro (void)
{
	long pic;
	unsigned char k = 255;
	int fade_cnt;

	// these txt files will be encoded soon....	
	char *text[6] = {
		".\\story\\story1.txt",
		".\\story\\story2.txt",
		".\\story\\story3.txt",
		".\\story\\story4.txt",
		".\\story\\story5.txt",
		".\\story\\story6.txt"
	};

	//	but here the ct2 start screen code
	ShadeFont (64 + 32, 1);
//	ShadeFont (32, 1);
	
	SetWindowColors (10 * 16, 10 * 16 + 32, 10 * 16 + 10, 10 * 16 + 8);

	// story code
	for (pic = 0; pic < 6; pic++){
		ClearVB (VB);
		PutClippedInvImage16 (artPTR + pic * 64000L, 0, 0, 320, 200, VB);
		
		// 10 * 16 + x
		DrawExclusiveWindow (0, 0, 320, 50, "", 4);
		
		IntroText (text[pic], 0, 0);// was pic - 2
		RefreshVRAM (VB);	// copy "black screen" to VRAM
		
		if (k != 255){
			while (keytable[k] == PRESSED);
		}

		k = WaitKB ();
		
		// ESC pressed -> QUIT
		if (k == 1){
			pic = 6;
			ClearVB (VB);
			RefreshVRAM (VB);
		}
	}

	// back to ct2 start screen
}

/*
	loads in a text file
*/
int LoadTextFile (char *fname, WORD bytes)
{
	FILE *f;
	BYTE v;
	DWORD off;

	if ((f = fopen (fname, "rb")) == NULL) return -1;

	for (off = 0; off < bytes; off++){
		v = fgetc (f);
		WriteMem (off, v);
	}

	fclose (f);
}

/*
	displays start warning message
*/
int GraphWarning (void)
{
	int by, stat;
	
	char *EventNames[2] = {
		"ACCEPT",
		"DISAGREE, EXIT"
	};
	
	ClearEvents ();

	ShadeFont (80, 1);
	SetWindowColors (162, 174, 165, 168);
	DrawWindow (0, 0, 320, 200, "Combat Team 2, version 0.80 BETA, WARNING MESSAGE", 10);
	
	ShadeFont (200, 1);
	DisplayString ("This is a BETA release of this game.", 10, 15);
	DisplayString ("Agreeing with this warning means that you are", 10, 25);
	DisplayString ("willing to continue with your own risk. And I,", 10, 35);
	DisplayString ("the mader of this game, am NOT responsible from", 10, 45);
	DisplayString ("any damages that this game can cause to you.", 10, 55);
	by = 90;

	ShadeFont (80, 1);
//	SetButtonColors (162, 174, 164, 166);
	
	for (stat = 0; stat < 2; stat++){
		DrawTextedButton (10, by, 128, 10, 0, EventNames[stat]);
		AddEvent (10, by, 128, 10);
		by += 12;
	}
	
	RefreshVRAM (VB);
	SetPointerPosition (160, 100);
	ShowMouse ();
	
	while (1){
		UpdateMouse ();
		stat = CheckEvents (mousex, mousey);
		
		if (stat != -1 && mouseb == LEFTB){
			HideMouse ();
			by = 90 + stat * 12;
			DrawTextedButton (10, by, 128, 10, 1, EventNames[stat]);
			RefreshVRAM (VB);
			delay (250);
			if (stat == 0) return 0;
			else return -1;
		}
	}
	
	SetButtonColors (18, 30, 22, 24);
}

/*
	display end message
*/
int End (void)
{
	char k;
	int s;

	_setcursortype (_NOCURSOR);
	s = LoadTextFile (".\\data\\end.bin", 2080);

	if (s != 0){
		return -1;
	}

	_setcursortype (_NORMALCURSOR);
	gotoxy (1, 14);
	return 0;
}

/*
	darkens palette to specified level (brightness)
*/
void DarkenPalette (void)
{
	int c;
	int data;
		
	for (c = 0; c < PalEntries; c++){
		data = Palette[c] * brightness;
		data /= 64;
		Palette[c] = (BYTE) data;
	}
}

/*
	checks if mouse cursor in specified area
*/
int xInArea (int sx, int sy, int w, int h)
{
	if (mousex >= sx && mousex <= sx + w - 1 &&
	mousey >= sy && mousey <= sy + h - 1){
		return 1;
	}

	return 0;
}

void StartRefresh (void)
{
	int cx, by, stat;
	
	ShadeFont (148, 1);

	ClearVB (VB);
	Mem2Mem (pic1_ptr, VB);
	RefreshVRAM (VB);
	
	cx = strlen ("START SINGLE MISSION");
	cx *= 6;
	cx = 160 - cx / 2;
	by = 100;

	ClearEvents ();

	for (stat = 0; stat < 6; stat++){
		DrawTextedButton (cx, by, 128, 10, 0, StartEventNames[stat]);
		AddEvent (cx, by, 128, 10);
		by += 12;
	}

	RefreshVRAM (VB);
	ShowMouse ();
}

/*
	key config screen...
*/
void KeyConfigScreen (void)
{
	int xreleased = 0;
	int kc, by = 15;
	int stat;
	BYTE inkey;
	
	ClearEvents ();
	DrawWindow (0, 0, 320, 200, "CONFIGURE GAME KEYS", 10);
	
	for (kc = 0; kc < MAX_KEYS; kc++){
		DisplayString (KeyActionNames[kc], 20, by);
		DrawTextedButton (20 + 100, by - 2, 128, 10, 0, keynames[keys[kc]]);
		AddEvent (20 + 100, by - 2, 128, 10); 
		by += 12;
	}

	RefreshVRAM (VB);
	ShowMouse ();
	
	while (1){
		UpdateMouse ();
		
		if (mouseb == 0){
			xreleased = 1;
		}
		
		stat = CheckEvents (mousex, mousey);

		if (mouseb == LEFTB && xreleased == 1 && stat == -1) break;
		
		if (stat != -1 && mouseb == LEFTB && xreleased == 1){
			by = 15 + 12 * stat;
			DrawTextedButton (20 + 100, by - 2, 128, 10, 1, keynames[keys[stat]]);
			HideMouse ();
			RefreshVRAM (VB);
			inkey = WaitKB ();
		
			if (inkey != ESC){
				keys[stat] = inkey;
			}
			
			DrawWindow (0, 0, 320, 200, "CONFIGURE GAME KEYS", 10);
			
			by = 15;
			
			for (kc = 0; kc < MAX_KEYS; kc++){
				DisplayString (KeyActionNames[kc], 20, by);
				DrawTextedButton (20 + 100, by - 2, 128, 10, 0, keynames[keys[kc]]);
				by += 12;
			}
			
			RefreshVRAM (VB);
			ShowMouse ();
			xreleased = 0;
		}
	}
	
	HideMouse ();
}

/*
	routines to configure the game
*/
void ConfigGame (void)
{
	int released = 0, xreleased = 0;
	int by = 20, cx = 20;
	int stat;
	char output [4];
	
	ShadeFont (80, 1);
	SetWindowColors (162, 174, 165, 168);

	ClearEvents ();
	DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
	
	for (stat = 0; stat < 13; stat++){
		switch (stat){
			case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
			case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
			case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
			case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
		}

		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	sprintf (output, "%d", firedelay);
	DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
	sprintf (output, "%d", keyfirstdelay);
	DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
	sprintf (output, "%d", keynextdelay);
	DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
	sprintf (output, "%d", brightness);
	DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
	sprintf (output, "%d", default_players);
	DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);
	sprintf (output, "%d", human_players);
	DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	while (1){
		UpdateMouse ();
		
		if (mouseb == 0){
			xreleased = 1;
			released = 1;
		}
		//if (mouseb != 0 && released == 1) return;
		
		stat = CheckEvents (mousex, mousey);
	
		// default players++ ?
		if (stat == 1 && mouseb == LEFTB && xreleased == 1){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			default_players++;
			
			if (default_players > 4){
				default_players = 2;
			}
			
			if (human_players > default_players)
			{
				human_players = default_players;
			}
			
			delay (250);
			DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
			sprintf (output, "%d", firedelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
			sprintf (output, "%d", keyfirstdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
			sprintf (output, "%d", keynextdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
			sprintf (output, "%d", brightness);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
			sprintf (output, "%d", human_players);
			DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
			sprintf (output, "%d", default_players);
			DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);

			by = 20;
			
			for (stat = 0; stat < 13; stat++){
					switch (stat){
						case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
						case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
						case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
						case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
			 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
					}

				by += 12;
			}
		
			RefreshVRAM (VB);	
			xreleased = 0;
			ShowMouse ();
		}
		
		// human players++ ?
		if (stat == 2 && mouseb == LEFTB && xreleased == 1){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			
			human_players++;
			if (human_players > default_players) human_players = 1;
			
			delay (250);
			DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
			sprintf (output, "%d", firedelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
			sprintf (output, "%d", keyfirstdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
			sprintf (output, "%d", keynextdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
			sprintf (output, "%d", brightness);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
			sprintf (output, "%d", human_players);
			DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
			sprintf (output, "%d", default_players);
			DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);

			by = 20;
			
			for (stat = 0; stat < 13; stat++){
				switch (stat){
					case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
					case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
					case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
					case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
		 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
				}

				by += 12;
			}
			
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}
		
		// brightness++ ?
		if (stat == 3 && mouseb == LEFTB){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (125);
			brightness++;
			if (brightness > 64) brightness = 0;
			DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
			sprintf (output, "%d", firedelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
			sprintf (output, "%d", keyfirstdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
			sprintf (output, "%d", keynextdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
			sprintf (output, "%d", brightness);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
			sprintf (output, "%d", human_players);
			DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
			sprintf (output, "%d", default_players);
			DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);

			by = 20;
			
			for (stat = 0; stat < 13; stat++){
				switch (stat){
					case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
					case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
					case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
					case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
		 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
				}

				by += 12;
			}
			
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}
		
		// fire delay += 5 ???
		if (stat == 10 && mouseb == LEFTB){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (125);
			firedelay += 5;
			if (firedelay > 100) firedelay = 5;
			DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
			sprintf (output, "%d", firedelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
			sprintf (output, "%d", keyfirstdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
			sprintf (output, "%d", keynextdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
			sprintf (output, "%d", brightness);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
			sprintf (output, "%d", human_players);
			DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
			sprintf (output, "%d", default_players);
			DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);

			by = 20;
			
			for (stat = 0; stat < 13; stat++){
				switch (stat){
					case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
					case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
					case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
					case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
		 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
				}

				by += 12;
			}
			
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}
		
		// kb next delay += 25 ???
		if (stat == 9 && mouseb == LEFTB){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (125);
			keynextdelay += 25;
			if (keynextdelay > 250) keynextdelay = 50;
			DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
			sprintf (output, "%d", firedelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
			sprintf (output, "%d", keyfirstdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
			sprintf (output, "%d", keynextdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
			sprintf (output, "%d", brightness);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
			sprintf (output, "%d", human_players);
			DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
			sprintf (output, "%d", default_players);
			DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);

			by = 20;
			
			for (stat = 0; stat < 13; stat++){
				switch (stat){
					case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
					case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
					case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
					case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
		 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
				}

				by += 12;
			}
			
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}
		
			// kb first delay += 50 ???
		if (stat == 8 && mouseb == LEFTB){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (125);
			keyfirstdelay += 50;
			if (keyfirstdelay > 500) keyfirstdelay = 200;
			DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
			sprintf (output, "%d", firedelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
			sprintf (output, "%d", keyfirstdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
			sprintf (output, "%d", keynextdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
			sprintf (output, "%d", brightness);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
			sprintf (output, "%d", human_players);
			DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
			sprintf (output, "%d", default_players);
			DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);

			by = 20;
			
			for (stat = 0; stat < 13; stat++){
				switch (stat){
					case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
					case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
					case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
					case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
		 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
				}

				by += 12;
			}
			
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}
				
		// activate music ?
		if (stat == 4 && mouseb == LEFTB && xreleased == 1){
			by = 20 + stat * 12;
			activate_music ^= 1;
			DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}

		// silent ai turn ?
		if (stat == 5 && mouseb == LEFTB && xreleased == 1){
			by = 20 + stat * 12;
			silent_AI_turn ^= 1;
			DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}
		
		// mouse control ?
		if (stat == 11 && mouseb == LEFTB && xreleased == 1){
			by = 20 + stat * 12;
			MouseControlFlag ^= 1;
			DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			xreleased = 0;
			ShowMouse ();
		}
		
		// exit -> done ?
		if (stat == 12 && mouseb == LEFTB && released == 1){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}	
	
		// save config ?	
		if (stat == 6 && mouseb == LEFTB && xreleased == 1){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			SaveConfig ("config.ct2");
			delay (250);
			DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]);
			RefreshVRAM (VB);
			ShowMouse ();
			xreleased = 0;
		}
		
		if (stat == 0 && mouseb == LEFTB && xreleased == 1){
			by = 20 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, ConfigEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			KeyConfigScreen ();
			
			DrawWindow (0, 0, 320, 200, "GAME SETTINGS", 10);
			ClearEvents ();
			
			for (stat = 0; stat < 13; stat++){
				switch (stat){
					case 4:	DrawTextedButton (cx, by, 128, 10, activate_music, ConfigEventNames[stat]); break;
					case 5: DrawTextedButton (cx, by, 128, 10, silent_AI_turn, ConfigEventNames[stat]); break;
					case 7: DrawTextedButton (cx, by, 128, 10, scard > 0, ConfigEventNames[stat]); break;
					case 11: DrawTextedButton (cx, by, 128, 10, MouseControlFlag, ConfigEventNames[stat]); break;
		 			default: DrawTextedButton (cx, by, 128, 10, 0, ConfigEventNames[stat]); break;
				}
		
				AddEvent (cx, by, 128, 10);
				by += 12;
			}
	
			sprintf (output, "%d", firedelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 10 + 3 - 20);
			sprintf (output, "%d", keyfirstdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 8 + 3 - 20);
			sprintf (output, "%d", keynextdelay);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 9 + 3 - 20);
			sprintf (output, "%d", brightness);
			DisplayString (output, 20 + 128 + 8, 40 + 12 * 3 + 3 - 20);
			sprintf (output, "%d", human_players);
			DisplayString (output, 20 + 128 + 8, 40 + 24 + 3 - 20);
			sprintf (output, "%d", default_players);
			DisplayString (output, 20 + 128 + 8, 40 + 12 + 3 - 20);

			RefreshVRAM (VB);
			ShowMouse ();
			xreleased = 0;	
		}
	}

	SetWindowColors (10 * 16, 10 * 16 + 32, 10 * 16 + 10, 10 * 16 + 8);
}

void BuySoldierRefresh (void)
{
	char xreleased = 0;
	int cx = 20, by = 40;
	int stat;
	char output[64 + 1];
	long index;

	DrawWindow (0, 0, 320, 200, "BUY NEW SOLDIER", 10);
	
	for (stat = 0; stat < 3; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, BuySoldierEvents[stat]);
		by += 12;
	}

	sprintf (output, "Team Soldiers %lu, Money %lu dollars", CaddTeam->teamsoldiers, CaddTeam->money);
	DisplayString (output, 20, 20);

	// display info
	index = CaddGeneratedSoldier->SoldierCurrent->FirstName;
	sprintf (output, "FIRSTNAME %s", CaddName->GetFirstName (index));
	DisplayString (output, 20, 100);
	index = CaddGeneratedSoldier->SoldierCurrent->SurName;
	sprintf (output, "SURNAME %s", CaddName->GetSurName (index));
	DisplayString (output, 20, 112);
	sprintf (output, "STRENGTH %lu CONSTITUTION %lu COST %lu dollars",
	CaddGeneratedSoldier->SoldierCurrent->Strength, 
	CaddGeneratedSoldier->SoldierCurrent->Constitution,
	CaddGeneratedSoldier->SoldierCurrent->Cost);
	DisplayString (output, 20, 124);
	sprintf (output, "HPHEAD %lu HPCHEST %lu HPLARM %lu HPRARM %lu",
	CaddGeneratedSoldier->SoldierCurrent->HP[0],
	CaddGeneratedSoldier->SoldierCurrent->HP[1],
	CaddGeneratedSoldier->SoldierCurrent->HP[2],
	CaddGeneratedSoldier->SoldierCurrent->HP[3]);
	DisplayString (output, 20, 136);
	sprintf (output, "HPABDO %lu HPLLEG %lu HPRLEG %lu",
	CaddGeneratedSoldier->SoldierCurrent->HP[4],
	CaddGeneratedSoldier->SoldierCurrent->HP[5],
	CaddGeneratedSoldier->SoldierCurrent->HP[6]);
	DisplayString (output, 20, 148);
	sprintf (output, "FIRESKILL %lu", 
	CaddGeneratedSoldier->SoldierCurrent->FireSkill);
	DisplayString (output, 20, 160);

	RefreshVRAM (VB);
}

void BuySoldier (long mixedFlag)
{
	char xreleased = 0;
	int cx = 20, by = 40;
	int stat;
	char output[64 + 1];
	long index;
	
	DrawWindow (0, 0, 320, 200, "BUY NEW SOLDIER", 10);
	ClearEvents ();
	
	for (stat = 0; stat < 3; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, BuySoldierEvents[stat]);
		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	sprintf (output, "Team Soldiers %lu, Money %lu dollars", CaddTeam->teamsoldiers, CaddTeam->money);
	DisplayString (output, 20, 20);
	
	CaddGeneratedSoldier->GenerateSoldier (CaddTeam->country, mixedFlag);

	// display info
	index = CaddGeneratedSoldier->SoldierCurrent->FirstName;
	sprintf (output, "FIRSTNAME %s", CaddName->GetFirstName (index));
	DisplayString (output, 20, 100);
	index = CaddGeneratedSoldier->SoldierCurrent->SurName;
	sprintf (output, "SURNAME %s", CaddName->GetSurName (index));
	DisplayString (output, 20, 112);
	sprintf (output, "STRENGTH %lu CONSTITUTION %lu COST %lu dollars",
	CaddGeneratedSoldier->SoldierCurrent->Strength, 
	CaddGeneratedSoldier->SoldierCurrent->Constitution,
	CaddGeneratedSoldier->SoldierCurrent->Cost);
	DisplayString (output, 20, 124);
	sprintf (output, "HPHEAD %lu HPCHEST %lu HPLARM %lu HPRARM %lu",
	CaddGeneratedSoldier->SoldierCurrent->HP[0],
	CaddGeneratedSoldier->SoldierCurrent->HP[1],
	CaddGeneratedSoldier->SoldierCurrent->HP[2],
	CaddGeneratedSoldier->SoldierCurrent->HP[3]);
	DisplayString (output, 20, 136);
	sprintf (output, "HPABDO %lu HPLLEG %lu HPRLEG %lu",
	CaddGeneratedSoldier->SoldierCurrent->HP[4],
	CaddGeneratedSoldier->SoldierCurrent->HP[5],
	CaddGeneratedSoldier->SoldierCurrent->HP[6]);
	DisplayString (output, 20, 148);
	sprintf (output, "FIRESKILL %lu", 
	CaddGeneratedSoldier->SoldierCurrent->FireSkill);
	DisplayString (output, 20, 160);

	RefreshVRAM (VB);
	ShowMouse ();
	
	while (1){
		UpdateMouse ();
		if (mouseb == 0) xreleased = 1;
		stat = CheckEvents (mousex, mousey);
		
		if (stat == 0 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, BuySoldierEvents[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			CaddGeneratedSoldier->GenerateSoldier (CaddTeam->country, mixedFlag);
			BuySoldierRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
		
		if (stat == 1 && mouseb == LEFTB && xreleased == 1 
		&& CaddTeam->money >= CaddGeneratedSoldier->SoldierCurrent->Cost &&
		CaddTeam->teamsoldiers < 16){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, BuySoldierEvents[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			// copy from generated to current soldier + add soldier !
			DuplicateGeneratedSoldier (-1);
			CaddSoldier->AddSoldier ();
			CaddTeam->money -= CaddGeneratedSoldier->SoldierCurrent->Cost;
			CaddTeam->teamsoldiers++;
			CaddGeneratedSoldier->GenerateSoldier (CaddTeam->country, mixedFlag);
			BuySoldierRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
		
		// exit ???
		if (stat == 2 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, BuySoldierEvents[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}
	}
}

void NewTeamRefresh (void)
{
	char output[40];
	
	DrawWindow (0, 0, 320, 200, "NEW TEAM", 10);

	sprintf (output, "Team Money %lu dollars", CaddTeam->money);
	DisplayString (output, 20, 20);
	sprintf (output, "Team Soldiers %lu", CaddTeam->teamsoldiers);
	DisplayString (output, 20, 30);
	sprintf (output, "Team Country %s, ID %lu", CaddCountry->ReturnCountry (CaddTeam->country),
	CaddTeam->ID);
	DisplayString (output, 20, 40);
	sprintf (output, "Team Name %s", CaddTeam->name);
	DisplayString (output, 20, 50);
}

long InputTeamName (int x, int y)
{
	int index, lindex;
	BYTE kr;
	
	for (index = 0; index < 32; index++){
		tname[index] = 0;
	}
	
	index = 0;
	SetRepeat (150, 75);

	while (1){
		for (lindex = 0; lindex < 32; lindex++){
			CaddTeam->name[lindex & 31] = tname[lindex & 31];
		}

		NewTeamRefresh ();
		RefreshVRAM (VB);
		
		kr = WaitKB ();
		if (kr == ESC) break;
		else if (kr == ENTER) break;

		else if (kr == 14 && index > 0){
			index--;
			tname[index & 31] = 0;
		}
		
		else if (kr >= 2 && kr <= 11){
			tname[index & 31] = KeyConvertTable2[kr - 2];
				
			if (index < 14){
				index++;
			}
		}

		else if (kr >= 16 && kr <= 50){
			tname[index & 31] = KeyConvertTable[kr - 16];
				
			if (index < 14){
				index++;
			}
		}
	}

	SetRepeat (250, 75);
}

void RealSaveRefresh (char tFlag)
{
	int cx = 10, by = 10;
	int stat;
	char xreleased = 0;
	char output[32];
	long starty = 0;
	
	ShadeFont (80, 1);
	SetWindowColors (162, 174, 165, 168);
	DrawWindow (0, 0, 320, 200, "CHOOSE OR TYPE TEAMFILE TO SAVE", 10);
	
	if (tFlag){
		sprintf (output, "team file %s", tname);
		DisplayString (output, 20, 24);
	}
	
	RefreshVRAM (VB);
}

long InputTeamSaveFileName (int x, int y)
{
	int index, lindex;
	BYTE kr;
	char *ext = ".CTF";
	
	for (index = 0; index < 32; index++){
		tname[index] = 0;
	}
	
	index = 0;
	SetRepeat (150, 75);

	while (1){
		RealSaveRefresh (1);
		RefreshVRAM (VB);
		
		kr = WaitKB ();
		if (kr == ESC) break;
		
		else if (kr == ENTER){
			for (lindex = 0; lindex < 4; lindex++){
				tname[index + lindex] = ext[lindex];
			}
			
			break;
		}

		else if (kr == 14 && index > 0){
			index--;
			tname[index & 31] = 0;
		}
		
		else if (kr >= 2 && kr <= 11){
			tname[index & 31] = KeyConvertTable2[kr - 2];
				
			if (index < 8){
				index++;
			}
		}

		else if (kr >= 16 && kr <= 50){
			tname[index & 31] = KeyConvertTable[kr - 16];
				
			if (index < 8){
				index++;
			}
		}
	}

	SetRepeat (250, 75);
}

/*
	code to build a new team !
*/
void NewTeam (void)
{
	char xreleased = 0;
	char waspressed = 0;
	int cx = 20, by = 60;
	int stat;
	char output[32];
	
	DrawWindow (0, 0, 320, 200, "NEW TEAM, SELECT COUNTRY AND ENTER TEAM NAME", 10);
	ClearEvents ();
	
	for (stat = 0; stat < 3; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, NewTeamEvents2[stat]);
		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	sprintf (output, "Team Money %lu dollars", CaddTeam->money);
	DisplayString (output, 20, 20);
	sprintf (output, "Team Soldiers %lu", CaddTeam->teamsoldiers);
	DisplayString (output, 20, 30);
	sprintf (output, "Team Country %s, ID %lu", 
	CaddCountry->ReturnCountry (CaddTeam->country), CaddTeam->ID);
	DisplayString (output, 20, 40);
	sprintf (output, "Team Name %s", CaddTeam->name);
	DisplayString (output, 20, 50);

	RefreshVRAM (VB);
	ShowMouse ();

	while (mouseb != 0){
		UpdateMouse ();
	}
	
	timer_start = 1;
	timer_ticks = 0;
	
	while (1){
		UpdateMouse ();
		
		if (mouseb == 0){
			if (waspressed == 1){
				waspressed = 0;
				HideMouse ();
				NewTeamRefresh ();
				by = 60;
				DrawTextedButton (cx, by, 128, 10, 0, NewTeamEvents2[0]);
			 	DrawTextedButton (cx, by + 12, 128, 10, 0, NewTeamEvents2[1]);
		 	 	DrawTextedButton (cx, by + 24, 128, 10, 0, NewTeamEvents2[2]);
				RefreshVRAM (VB);
				ShowMouse ();
			}
			
			xreleased = 1;
		}
		
		stat = CheckEvents (mousex, mousey);
		
		// change country ???
		if (stat == 0 && mouseb == LEFTB && timer_ticks > 200){
			CaddTeam->country++;

			if (CaddTeam->country >= CaddCountry->countries - 1){
				CaddTeam->country = 0;	
			}
			
			timer_ticks = 0;
			HideMouse ();
			NewTeamRefresh ();
			by = 60;
			DrawTextedButton (cx, by, 128, 10, 1, NewTeamEvents2[0]);
		 	DrawTextedButton (cx, by + 12, 128, 10, 0, NewTeamEvents2[1]);
	 		DrawTextedButton (cx, by + 24, 128, 10, 0, NewTeamEvents2[2]);
			RefreshVRAM (VB);
			ShowMouse ();
			waspressed = 1;
		}
		
		// enter team name ???
		else if (stat == 1 && mouseb == LEFTB && xreleased == 1){
			HideMouse ();
			NewTeamRefresh ();
	 		
			RefreshVRAM (VB);
			InputTeamName (20 + 100, 60 + 24);
	 		ClearEvents ();
			by = 60;
			
	 		for (stat = 0; stat < 3; stat++){
		 		DrawTextedButton (cx, by, 128, 10, 0, NewTeamEvents2[stat]);
				AddEvent (cx, by, 128, 10);
				by += 12;
			}

			RefreshVRAM (VB);
			ShowMouse ();
			xreleased = 0;
			waspressed = 1;
		}
				
		// exit ???
		else if (stat == 2 && mouseb == LEFTB && xreleased == 1 
		&& CaddTeam->country != -1){
			by = 60 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, NewTeamEvents2[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}
	}
	
	timer_start = 0;
}

void TeamEditorRefresh (void)
{
	int by = 40, cx = 20;
	int stat;
	
	ClearEvents ();
	DrawWindow (0, 0, 320, 200, "TEAM EDITOR", 10);
	
	for (stat = 0; stat < 8; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, EditorEventNames[stat]);
		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	RefreshVRAM (VB);
}

void SellTeamRefresh (void)
{
	char xreleased = 0;
	char waspressed = 0;
	int cx = 20, by = 18;
	int stat;
	long cnt;
	char output[48];
	long index, index2;
	
	DrawWindow (0, 0, 320, 200, "SELL TEAM MEMBERS", 10);
	ClearEvents ();

	for (stat = 0; stat < 1; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, SellMembersEvents[stat]);
 		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	sprintf (output, "Members %lu Money %lu Country %s", 
	CaddTeam->teamsoldiers,
	CaddTeam->money,
	CaddCountry->ReturnCountry (CaddTeam->country));
	DisplayString (output, 20, 10);
	
	cx = 20;
	by = 29;
	
	if (CaddTeam->teamsoldiers > 0){
		for (cnt = 0; cnt < CaddTeam->teamsoldiers; cnt++){
			CaddSoldier->SelectSoldier (cnt);
			index = CaddSoldier->SoldierSelected->FirstName;
			index2 = CaddSoldier->SoldierSelected->SurName;
			sprintf (output, "%lu. Name %s %s",
			cnt + 1, CaddName->GetFirstName (index), CaddName->GetSurName (index2));
			DrawTextedButton (cx, by + cnt * 11, 164, 10, 0, output);
			AddEvent (cx, by + cnt * 11, 128, 10);
		}
	}
	
	RefreshVRAM (VB);
}

void SellTeamMembers (void)
{
	char xreleased = 0;
	char waspressed = 0;
	int cx = 20, by = 18;
	int stat;
	long cnt;
	char output[48];
	long index, index2;
	
	DrawWindow (0, 0, 320, 200, "SELL TEAM MEMBERS", 10);
	ClearEvents ();
	
	for (stat = 0; stat < 1; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, SellMembersEvents[stat]);
		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	sprintf (output, "Members %lu Money %lu Country %s", 
	CaddTeam->teamsoldiers,
	CaddTeam->money,
	CaddCountry->ReturnCountry (CaddTeam->country));
	DisplayString (output, 20, 10);
	
	cx = 20;
	by = 29;
	
	if (CaddTeam->teamsoldiers > 0){
		for (cnt = 0; cnt < CaddTeam->teamsoldiers; cnt++){
			CaddSoldier->SelectSoldier (cnt);
			index = CaddSoldier->SoldierSelected->FirstName;
			index2 = CaddSoldier->SoldierSelected->SurName;
			sprintf (output, "%lu. Name %s %s",
			cnt + 1, CaddName->GetFirstName (index), CaddName->GetSurName (index2));
			DrawTextedButton (cx, by + cnt * 11, 164, 10, 0, output);
			AddEvent (cx, by + cnt * 11, 128, 10);
		}
	}
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	while (1){
		UpdateMouse ();
		if (mouseb == 0) xreleased = 1;
		
		stat = CheckEvents (mousex, mousey);
		
		if (stat == 0 && mouseb == LEFTB && xreleased == 1){
			by = 18 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, SellMembersEvents[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}
		
		if (stat > 0 && mouseb == LEFTB && xreleased == 1){
			by = 29;
			cx = 20;
			CaddSoldier->SelectSoldier (stat - 1);
			index = CaddSoldier->SoldierSelected->FirstName;
			index2 = CaddSoldier->SoldierSelected->SurName;
			sprintf (output, "%lu. Name %s %s",
			stat, CaddName->GetFirstName (index), CaddName->GetSurName (index2));
			DrawTextedButton (cx, by + (stat - 1) * 11, 164, 10, 1, output);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			CaddTeam->money += CaddSoldier->SoldierSelected->Cost;
			CaddSoldier->DeleteSoldier (stat - 1);
			CaddTeam->teamsoldiers--;
			SellTeamRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
	}
}

/*
	shows team member list
*/
void ShowTeamMembers (void)
{
	char xreleased = 0;
	char waspressed = 0;
	int cx = 20, by = 18;
	int stat;
	long cnt;
	char output[48];
	long index, index2;
	
	DrawWindow (0, 0, 320, 200, "TEAM MEMBER LIST", 10);
	ClearEvents ();
	
	for (stat = 0; stat < 1; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, NewTeamEvents[stat]);
		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	sprintf (output, "Members %lu Money %lu Country %s Active %lu", 
	CaddTeam->teamsoldiers,
	CaddTeam->money,
	CaddCountry->ReturnCountry (CaddTeam->country),
	CaddTeam->activesoldiers);
	DisplayString (output, 20, 10);
	
	if (CaddTeam->teamsoldiers > 0){
		for (cnt = 0; cnt < CaddTeam->teamsoldiers; cnt++){
			CaddSoldier->SelectSoldier (cnt);
			
			index = CaddSoldier->SoldierSelected->FirstName;
			index2 = CaddSoldier->SoldierSelected->SurName;
			
			sprintf (output, "    Name %s %s Active %lu",
			CaddName->GetFirstName (index), 
			CaddName->GetSurName (index2),
			CaddSoldier->SoldierSelected->active);
			
			DisplayString (output, 20, 30 + cnt * 8);
			
			sprintf (output, "%lu.", cnt + 1);
			DrawTextedButton2 (cx, 30 + cnt * 8 - 1, 4 * 5, 8, 0, output, -1);
			AddEvent (cx, 30 + cnt * 8 - 1, 4 * 5, 8);
		}
	}
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	while (1){
		UpdateMouse ();
		
		if (mouseb == 0){
			xreleased = 1;
		}
		
		stat = CheckEvents (mousex, mousey);
		
		// done ???
		if (stat == 0 && mouseb == LEFTB && xreleased == 1){
			by = 18 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, NewTeamEvents[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}
		
		else if (stat > 0 && mouseb == LEFTB && xreleased == 1){
			by = 30 + (stat - 1) * 8 - 1;
			sprintf (output, "%lu.", stat);
			DrawTextedButton (cx, by, 4 * 5, 8, 1, output);
			HideMouse ();
			RefreshVRAM (VB);
			ShowMouse ();
			delay (250);
			HideMouse ();
			DrawTextedButton (cx, by, 4 * 5, 8, 0, output);
			CaddSoldier->SelectSoldier (stat - 1);
			
			if (CaddTeam->activesoldiers < 8 && CaddSoldier->SoldierSelected->active == 0){
				CaddSoldier->SoldierSelected->active = 1;
				CaddTeam->activesoldiers++;
			}
			
			else{
					CaddSoldier->SoldierSelected->active = 0;
					CaddTeam->activesoldiers--;
			}

			by = 18;
			DrawWindow (0, 0, 320, 200, "TEAM MEMBER LIST", 10);
			ClearEvents ();
	
			for (stat = 0; stat < 1; stat++){
		 		DrawTextedButton (cx, by, 128, 10, 0, NewTeamEvents[stat]);
				AddEvent (cx, by, 128, 10);
				by += 12;
			}
	
			sprintf (output, "Members %lu Money %lu Country %s Active %lu", 
			CaddTeam->teamsoldiers,
			CaddTeam->money,
			CaddCountry->ReturnCountry (CaddTeam->country),
			CaddTeam->activesoldiers);
			DisplayString (output, 20, 10);
		
			if (CaddTeam->teamsoldiers > 0){
				for (cnt = 0; cnt < CaddTeam->teamsoldiers; cnt++){
					CaddSoldier->SelectSoldier (cnt);
					
					index = CaddSoldier->SoldierSelected->FirstName;
					index2 = CaddSoldier->SoldierSelected->SurName;
			
					sprintf (output, "    Name %s %s Active %lu",
					CaddName->GetFirstName (index), 
					CaddName->GetSurName (index2),
					CaddSoldier->SoldierSelected->active);
				
					DisplayString (output, 20, 30 + cnt * 8);
			
					sprintf (output, "%lu.", cnt + 1);
					DrawTextedButton2 (cx, 30 + cnt * 8 - 1, 4 * 5, 8, 0, output, -1);
					AddEvent (cx, 30 + cnt * 8 - 1, 4 * 5, 8);
				}
			}
	
			RefreshVRAM (VB);
			ShowMouse ();
		}
	}
}

/*
	initializes file system
*/
long InitFileSystem (void)
{
	long stat;

	stat = InitFileNames ();
	if (stat != 0) return stat;
	stat = ReadDirectoryList (".\\teams\\*.ctf");
	if (stat != 0) return stat;
}

/*
	frees file system
*/
long FreeFileSystem (void)
{
	return FreeFileNames ();
}

/*
	display directory list (max 16 files)
*/
long DisplayFiles (int sx, int sy, long startfile, long files, char addFlag)
{
	int cx, by;
	long stat;
	
	cx = sx;
	by = sy;
	
	for (stat = 0; stat < files; stat++){
		if (startfile + stat < XFN->FileNames - 1){
			XFN->SelectName (startfile + stat);
 			DrawTextedButton (cx, by, 128, 10, 0, Selected->Name);

			// add Flag fixes infinite add event calls bug !!!
			if (addFlag){
				AddEvent (cx, by, 128, 10);
			}
		}
		
		by += 11;
	}
	
	return 0;
}

/*
	display directory list (max 16 files)
*/
long ExtDisplayFiles (int sx, int sy, long startfile, long files, char addFlag, long pressed)
{
	int cx, by;
	long stat;
	
	cx = sx;
	by = sy;
	
	for (stat = 0; stat < files; stat++){
		if (startfile + stat < XFN->FileNames - 1){
			XFN->SelectName (startfile + stat);

			if (stat == pressed){
	 			DrawTextedButton (cx, by, 128, 10, 1, Selected->Name);
	 		}
	 		
	 		else{
	 			 DrawTextedButton (cx, by, 128, 10, 0, Selected->Name);
	 		}

			// add Flag fixes infinite add event calls bug !!!
			if (addFlag){
				AddEvent (cx, by, 128, 10);
			}
		}
		
		by += 11;
	}
	
	return 0;
}


/*
	load team screen refresh
*/
void LoadTeamRefresh (void)
{
	int cx = 10, by = 10;
	int stat;
	char xreleased = 0;
	char output[16];

	for (stat = 0; stat < 3; stat++){
 		DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 0, LoadEvents[stat]);
	}

	sprintf (output, "%lu team files", XFN->FileNames - 1);
	DisplayString (output, 235, 12);
	HideMouse ();
	RefreshVRAM (VB);
	ShowMouse ();
}

/*
	load team code
*/
long RealLoadTeam (long player, int doneFlag, int nofileFlag)
{
	int cx = 10, by = 10;
	int stat;
	char xreleased = 0;
	char output[32];
	long starty = 0;
	
	stat = InitFileSystem ();
	if (stat != 0) return stat;
	
	if (XFN->FileNames - 1 < 1 && nofileFlag){
		asm("
			movw $0x3, %ax
			int $0x10
		");
		
		textcolor (LIGHTRED);
		cprintf (".\\teams\\ directory contains 0 team files (*.ctf)\n\r");
		return -256;
	}
	
	if (XFN->FileNames - 1 < human_players && player){
		asm("
			movw $0x3, %ax
			int $0x10
		");
		
		textcolor (LIGHTRED);
		cprintf (".\\teams\\ directory contains less than %lu team files (*.ctf)\n\r", human_players);
		return -256;
	}
	
	ClearEvents ();
	ShadeFont (80, 1);
	SetWindowColors (162, 174, 165, 168);

	if (player){
		sprintf (output, "PLAYER %lu CHOOSE TEAMFILE", player);
		DrawWindow (0, 0, 320, 200, output, 10);
	}
	
	else{
		DrawWindow (0, 0, 320, 200, "CHOOSE TEAMFILE TO LOAD", 10);
	}
	
	for (stat = 0; stat < 3; stat++){
 		DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 0, LoadEvents[stat]);
		AddEvent (cx + leXPs[stat], by, leLEN[stat], 10);
	}

	DisplayFiles (20, 21, starty, 16, 1);
	sprintf (output, "%lu team files", XFN->FileNames - 1);
	DisplayString (output, 235, 12);
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	timer_start = 1;
	timer_ticks = 0;
	
	while (1){
		UpdateMouse ();
		
		if (mouseb == 0 && xreleased == 0){
			LoadTeamRefresh ();
			xreleased = 1;
		}
		
		stat = CheckEvents (mousex, mousey);

		// scroll up ???
		if (stat == 0 && mouseb == LEFTB && timer_ticks > 150 && starty > 0){
			timer_ticks = 0;
			DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 1, LoadEvents[stat]);
			HideMouse ();
			starty--;
			DisplayFiles (20, 21, starty, 16, 0);
			RefreshVRAM (VB);
			ShowMouse ();
			xreleased = 0;
		}

		// scroll down ???
		if (stat == 1 && mouseb == LEFTB && timer_ticks > 150){
			timer_ticks = 0;
			
			if (starty < XFN->FileNames - 17 && XFN->FileNames > 16){
				DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 1, LoadEvents[stat]);
				HideMouse ();
				starty++;
				DisplayFiles (20, 21, starty, 16, 0);
				RefreshVRAM (VB);
				ShowMouse ();
				xreleased = 0;
			}
		}
		
		// exit ???
		if (stat == 2 && mouseb == LEFTB && xreleased == 1 && doneFlag == 1){
			DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 1, LoadEvents[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}
		
		if (stat > 2 && mouseb == LEFTB && xreleased == 1){
			if (player == 0){
				ExtDisplayFiles (20, 21, starty, 16, 0, (long) (stat - 3));
				HideMouse ();
				RefreshVRAM (VB);
				delay (250);
				xreleased = 0;
				LoadTeam (XFN->GetName ((long) (stat - 3)));
				break;
			}
			
			else{
				if (player == 1){
					ExtDisplayFiles (20, 21, starty, 16, 0, (long) (stat - 3));
					HideMouse ();
					RefreshVRAM (VB);
					delay (250);
					xreleased = 0;
					LoadTeam (XFN->GetName ((long) (stat - 3)));
					TeamFile[player - 1] = XFN->GetName ((long) stat - 3);
					break;
				}
				
				else if (player > 1){
					TeamFile[player - 1] = XFN->GetName ((long) stat - 3);

					if (strcmp (TeamFile[player - 2], TeamFile[player - 1]) != 0){
						ExtDisplayFiles (20, 21, starty, 16, 0, (long) (stat - 3));
						HideMouse ();
						RefreshVRAM (VB);
						delay (250);
						xreleased = 0;
						LoadTeam (XFN->GetName ((long) (stat - 3)));
						break;
					}
				}
			}
			
		
		}
	}

	timer_start = 0;
	stat = FreeFileSystem ();
	return 0;
}

/*
	saves team
*/
long RealSaveTeam (void)
{
	int cx = 10, by = 10;
	int stat;
	char xreleased = 0;
	char output[16];
	long starty = 0;
	
	stat = InitFileSystem ();
	if (stat != 0) return stat;
	
	ClearEvents ();
	ShadeFont (80, 1);
	SetWindowColors (162, 174, 165, 168);

	DrawWindow (0, 0, 320, 200, "CHOOSE OR TYPE TEAMFILE TO SAVE", 10);
	
	for (stat = 0; stat < 4; stat++){
 		DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 0, LoadEvents[stat]);
		AddEvent (cx + leXPs[stat], by, leLEN[stat], 10);
	}

	DisplayFiles (20, 21, starty, 16, 1);
	sprintf (output, "%lu team files", XFN->FileNames - 1);
	DisplayString (output, 235, 24);
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	timer_start = 1;
	timer_ticks = 0;
	
	while (1){
		UpdateMouse ();
		
		if (mouseb == 0 && xreleased == 0){
			HideMouse ();
			RealSaveRefresh (0);
			
			for (stat = 0; stat < 4; stat++){
		 		DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 0, LoadEvents[stat]);
			}

			sprintf (output, "%lu team files", XFN->FileNames - 1);
			DisplayString (output, 235, 24);
			DisplayFiles (20, 21, starty, 16, 1);
			RefreshVRAM (VB);
			ShowMouse ();
			xreleased = 1;
		}
		
		stat = CheckEvents (mousex, mousey);

		// scroll up ???
		if (stat == 0 && mouseb == LEFTB && timer_ticks > 150 && starty > 0){
			timer_ticks = 0;
			DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 1, LoadEvents[stat]);
			HideMouse ();
			starty--;
			DisplayFiles (20, 21, starty, 16, 0);
			RefreshVRAM (VB);
			ShowMouse ();
			xreleased = 0;
		}

		// scroll down ???
		if (stat == 1 && mouseb == LEFTB && timer_ticks > 150){
			timer_ticks = 0;
			
			if (starty < XFN->FileNames - 17 && XFN->FileNames > 16){
				DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 1, LoadEvents[stat]);
				HideMouse ();
				starty++;
				DisplayFiles (20, 21, starty, 16, 0);
				RefreshVRAM (VB);
				ShowMouse ();
				xreleased = 0;
			}
		}
		
		// exit ???
		if (stat == 2 && mouseb == LEFTB && xreleased == 1){
			DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 1, LoadEvents[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}
		
		// enter team filename ?
		if (stat == 3 && mouseb == LEFTB && xreleased == 1){
				HideMouse ();
				InputTeamSaveFileName (20, 12);
				
				CaddTeam->ID = (long) (XFN->FileNames & 0xFFFF) * 0x10000;
				CaddTeam->ID += (long) _farpeekw (_go32_conventional_mem_selector (), (0x40 * 16) + 0x6C);
				SaveTeam (tname);
					
				for (stat = 0; stat < 4; stat++){
			 		DrawTextedButton (cx + leXPs[stat], by, leLEN[stat], 10, 0, LoadEvents[stat]);
				}
	
				DisplayFiles (20, 21, starty, 16, 1);
				sprintf (output, "%lu team files", XFN->FileNames - 1);
				DisplayString (output, 235, 24);
				
				RefreshVRAM (VB);
				ShowMouse ();
				xreleased = 0;
				
				if (CaddTeam->activesoldiers < 1){
					ClearVB (VB);
					DisplayString ("Warning, no active soldiers in team !", 10, 10);
					RefreshVRAM (VB);
					while (!no_key ());
					WaitKB ();
				}
				
				if (CaddTeam->teamsoldiers < 1){
					ClearVB (VB);
					DisplayString ("Warning, no soldiers in team !", 10, 10);
					RefreshVRAM (VB);
					while (!no_key ());
					WaitKB ();
				}
		}
		
		if (stat > 3 && mouseb == LEFTB && xreleased == 1){
			if (CaddTeam->activesoldiers < 1){
				ClearVB (VB);
				DisplayString ("Warning, no active soldiers in team !", 10, 10);
				RefreshVRAM (VB);
				while (!no_key ());
				WaitKB ();
			}
				
			if (CaddTeam->teamsoldiers < 1){
				ClearVB (VB);
				DisplayString ("Warning, no soldiers in team !", 10, 10);
				RefreshVRAM (VB);
				while (!no_key ());
				WaitKB ();
			}
			
			ExtDisplayFiles (20, 21, starty, 16, 0, (long) (stat - 4));
			HideMouse ();
			
			RefreshVRAM (VB);
			delay (250);
			xreleased = 0;
			CaddTeam->ID = (long) (XFN->FileNames & 0xFFFF) * 0x10000;
			CaddTeam->ID += (long) _farpeekw (_go32_conventional_mem_selector (), (0x40 * 16) + 0x6C);
			SaveTeam (XFN->GetName ((long) (stat - 4)));
			break;
		}
	}

	timer_start = 0;
	stat = FreeFileSystem ();
	return 0;
}
/*
	Lets you build your own team 
*/
long TeamEditor (void)
{
	char xreleased;
	int stat;
	int by = 40;
	int cx = 20;
	
	/*
		new team code here !
	*/
	stat = InitTeam ();

	if (stat != 0){
		return stat;
	}

	ClearEvents ();
	ShadeFont (80, 1);
	SetWindowColors (162, 174, 165, 168);

	DrawWindow (0, 0, 320, 200, "TEAM EDITOR", 10);
	
	for (stat = 0; stat < 8; stat++){
 		DrawTextedButton (cx, by, 128, 10, 0, EditorEventNames[stat]);
		AddEvent (cx, by, 128, 10);
		by += 12;
	}
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	// coming soon configurable start money
	CaddTeam->money = 45000;
	CaddTeam->teamsoldiers = 0;
	CaddTeam->activesoldiers = 0;
	CaddTeam->country = -1;
	CaddTeam->ID = 0;
	
	for (stat = 0; stat < 32; stat++){
		CaddTeam->name[stat] = 0;
	}

	while (1){
		UpdateMouse ();
		stat = CheckEvents (mousex, mousey);
		if (mouseb == 0) xreleased = 1;
		
		if (stat == 0 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			ClearVB (VB);
			NewTeam ();
			TeamEditorRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
		
		// country soldier ?
		if (stat == 1 && mouseb == LEFTB && xreleased == 1 && CaddTeam->country != -1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			ClearVB (VB);
			BuySoldier (0);
			TeamEditorRefresh ();
			ShowMouse ();
			xreleased = 0;
		}

		// mixed soldier ?		
		if (stat == 2 && mouseb == LEFTB && xreleased == 1 && CaddTeam->country != -1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			ClearVB (VB);
			BuySoldier (1);
			TeamEditorRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
		
		// sell soldier ?
		if (stat == 3 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			ClearVB (VB);
			SellTeamMembers ();
			TeamEditorRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
		
		// show team members ?
		if (stat == 4 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			ClearVB (VB);
			ShowTeamMembers ();
			TeamEditorRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
		
		// load team ?
		if (stat == 5 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			ClearVB (VB);
			RealLoadTeam (0, 1, 0);
			TeamEditorRefresh ();
			ShowMouse ();
			xreleased = 0;
		}

		// save team ?
		if (stat == 6 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			ClearVB (VB);
			RealSaveTeam ();
			TeamEditorRefresh ();
			ShowMouse ();
			xreleased = 0;
		}
		
		// exit ???
		if (stat == 7 && mouseb == LEFTB && xreleased == 1){
			by = 40 + stat * 12;
			DrawTextedButton (cx, by, 128, 10, 1, EditorEventNames[stat]);
			HideMouse ();
			RefreshVRAM (VB);
			delay (250);
			break;
		}
	}
		
	SetWindowColors (10 * 16, 10 * 16 + 32, 10 * 16 + 10, 10 * 16 + 8);
	stat = FreeTeam ();
}

/*
	start screen "code"
*/
int Start (void)
{
	int stat, by;
	int cx;
	
	cx = strlen ("START SINGLE MISSION");
	cx *= 6;
	cx = 160 - cx / 2;
	StartRefresh ();
	SetPointerPosition (160, 100);
	
	while (1){
		UpdateMouse ();
		stat = CheckEvents (mousex, mousey);
		
		if (stat != -1 && mouseb == LEFTB){
			by = 100 + stat * 12;
			
			// Team Editor ???
			if (stat == 0){
				HideMouse ();
				DrawTextedButton (cx, by, 128, 10, 1, StartEventNames[0]);
				RefreshVRAM (VB);
				delay (250);
				ClearVB (VB);
				RefreshVRAM (VB);
				TeamEditor ();
				StartRefresh ();				
				
				while (mouseb != 0){
					UpdateMouse ();
				}
			}
			
			if (stat == 1){
				HideMouse ();
				DrawTextedButton (cx, by, 128, 10, 1, StartEventNames[1]);
				RefreshVRAM (VB);
				delay (250);
				ShadeFont (32, 1);
				return 0;
			}
			
			if (stat == 5){
				HideMouse ();
				DrawTextedButton (cx, by, 128, 10, 1, StartEventNames[5]);
				RefreshVRAM (VB);
				delay (250);
				ShadeFont (32, 1);
				return 1;
			}
			
			// credits ???
			if (stat == 4){
				HideMouse ();
				DrawTextedButton (cx, by, 128, 10, 1, StartEventNames[4]);
				RefreshVRAM (VB);
				delay (250);
				ClearVB (VB);
				RefreshVRAM (VB);
				StartScrollerDown ();
				StartRefresh ();
				
				while (mouseb != 0){
					UpdateMouse ();
				}
			}
			
			// configure ???
			if (stat == 3){
				HideMouse ();
				DrawTextedButton (cx, by, 128, 10, 1, StartEventNames[3]);
				RefreshVRAM (VB);
				delay (250);
				ClearVB (VB);
				RefreshVRAM (VB);
				ConfigGame ();
				StartRefresh ();				
				
				while (mouseb != 0){
					UpdateMouse ();
				}
			}
		}
	}
}

/*
	mapselect routine
*/
int MapSelect (void)
{
	int cmap = 1;
	int stat, ls;
	int cx, by;
		
	ClearVB (VB);
	Mem2Mem (pic2_ptr, VB);
	ShadeFont (32, 1);


	cx = 14;
	cx *= 6;
	cx = 160 - cx / 2;
	by = 80;
	
	ClearEvents ();

	for (stat = 0; stat < MAPS; stat++){
		DrawTextedButton (cx, by, 84, 10, 0, realmaps[stat]);
		AddEvent (cx, by, 84, 10);
		by += 12;
	}
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	while (mouseb == LEFTB){
		UpdateMouse ();
	}
	
	while (1){
		UpdateMouse ();

		stat = CheckEvents (mousex, mousey);
		
		if (stat != -1 && mouseb == LEFTB){
			cmap = stat + 1;
			break;
		}
	}
	
	HideMouse ();
	
	by = 80 + (cmap - 1) * 12;
	DrawTextedButton (cx, by, 84, 10, 1, realmaps[cmap - 1]);
	RefreshVRAM (VB);
	delay (250);
	
	ls = LoadMap (maps[cmap - 1]);
	if (ls != 0) return ls;
	
	return 0;
}

/*
	Shopping code
	- Heavily modified for making CADD support possible
*/
void Shop (void)
{
	int cp = 0;
	int sold = 0;
	char output[80];
	long pm[PLAYERS];
	long mm;
	int c;
	int cx = 0;
	unsigned char key;
	int pc, sc;
	int bad;
	int ins;
	int nw = 0;
	int stat;
	int cpx;
	long scroll_index = 0;
	
	// reset player moneys to start money
	for (c = 0; c < default_players; c++){
		//pm[c] = START_MONEY;
		pm[c] = TI[c].money;
	}
	
	SetRepeat (500, 125);
	
	// this is the update code
	ClearVB (VB);
	Mem2Mem (pic3_ptr, VB);
	sprintf (output, "PLAYER %d of %d", cp + 1, human_players);
	DisplayString (output, 15, 15);
	sprintf (output, "SOLDIER %d of %d", sold + 1, TI[cp].soldiers);
	DisplayString (output, 15, 30);
	
	sprintf (output, "%lu DOLLARS LEFT", pm[cp]);
	DisplayString (output, 15, 45);
	
	if (SI[cp * 8 + sold].Weapon == -1){
		sprintf (output, "CURRENT WEAPON, NONE");
	}
		
	else{
		sprintf (output, "CURRENT WEAPON, %s, %lu CLIPS", 
		CaddWeapon->GetName (SI[cp * 8 + sold].Weapon),
		SI[cp * 8 + sold].Ammo);
	}
	
	DisplayString (output, 15, 60);
	ClearEvents ();
	
	// player buttons
	DrawTextedButton (120, 13, 34, 10, 0, "NEXT");
	AddEvent (120, 13, 34, 10);
	DrawTextedButton (120 + 40, 13, 34, 10, 0, "PREV");
	AddEvent (120 + 40, 13, 34, 10);

	// soldier(s) buttons
	DrawTextedButton (120, 28, 34, 10, 0, "NEXT");
	AddEvent (120, 28, 34, 10);
	DrawTextedButton (120 + 40, 28, 34, 10, 0, "PREV");
	AddEvent (120 + 40, 28, 34, 10);

	cpx = 320 / 2 - 34 / 2;
	DrawTextedButton (cpx, 180, 34, 10, 0, "DONE");
	AddEvent (cpx, 180, 34, 10);

	DrawTextedButton (15, 80, 64, 10, 0, "BUY AMMO");
	AddEvent (15, 80, 64, 10);
	DrawTextedButton (15 + 92, 80, 64, 10, 0, "SELL AMMO");
	AddEvent (15 + 92, 80, 64, 10);
	
	// buy/sell buttons
	DisplayString ("WEAPON LIST", 15, 92);

	for (c = 0; c < 4; c++){
		DrawTextedButton (15, 100 + (c + 1) * 12, 176, 10, 0,
		CaddWeapon->GetName (c + scroll_index));
		AddEvent (15, 100 + (c + 1) * 12, 176, 10);
		
		CaddWeapon->Select (c + scroll_index);
		sprintf (output, "cost %lu,ammo %lu",
		CaddWeapon->WeaponSelected->Cost,
		CaddWeapon->WeaponSelected->MagCost);
		// display weapon price
	
		DrawTextedButton (15 + 190, 100 + (c + 1) * 12, 113, 10, 1, output);
	}
	
	// LoadEvents[0]&[1] draw code -> scroll up/down wlist !
	DrawTextedButton (15, 99, 96, 10, 0, LoadEvents[0]);
	AddEvent (15, 99, 96, 10);
	DrawTextedButton (15 + 100, 99, 96, 10, 0, LoadEvents[1]);
	AddEvent (15 + 100, 99, 96, 10);
	
	RefreshVRAM (VB);
	ShowMouse ();
	
	while (1){
		while (1){
			UpdateMouse ();
			stat = CheckEvents (mousex, mousey);
			if (stat != -1 && mouseb == LEFTB) break;
			if (mouseb == RIGHTB) break;
		}
		
		switch (stat){
			case 0: cp++; if (cp > human_players - 1) cp = 0; sold = 0; break;
			case 1: cp--; if (cp < 0) cp = human_players - 1; sold = 0; break;
			case 2: sold++; if (sold > TI[cp].soldiers - 1) sold = 0; break;
			case 3: sold--; if (sold < 0) sold = TI[cp].soldiers - 1; break;
			case 11: if (scroll_index > 0) scroll_index--; break;
			case 12: if (scroll_index < CaddWeapon->weapons - 5) scroll_index++; break;
		}
		
		// buy ammo
		if (stat == 5 && SI[cp * 8 + sold].Weapon != -1){
			CaddWeapon->Select (SI[cp * 8 + sold].Weapon);

			if (pm[cp] >= CaddWeapon->WeaponSelected->MagCost){
				// up to 12 magazines...
				if (SI[cp * 8 + sold].Ammo < 12){
					SI[cp * 8 + sold].Ammo++;
					SI[cp * 8 + sold].Inmag = 
					CaddWeapon->WeaponSelected->MagSize;
					pm[cp] -= CaddWeapon->WeaponSelected->MagCost;
				}
			}
		}
		
		// sell ammo
		else if (stat == 6 && SI[cp * 8 + sold].Weapon != -1){
			if (SI[cp * 8 + sold].Ammo > 0){
				CaddWeapon->Select (SI[cp * 8 + sold].Weapon);
				
				pm[cp] += (long) SI[cp * 8 + sold].Ammo * 
				CaddWeapon->WeaponSelected->MagCost;
				SI[cp * 8 + sold].Ammo = 0;
			}
		}
		
		// buy/sell weapon (4 slots)
		else if (stat >= 7 && stat <= 10){
			long slot;
			
			slot = stat - 7;
			
			// buy weapon ?
			if (SI[cp * 8 + sold].Weapon == -1){
				CaddWeapon->Select (scroll_index + slot);
				
				if (pm[cp] >= CaddWeapon->WeaponSelected->Cost){
					SI[cp * 8 + sold].Weapon = scroll_index + slot;
					pm[cp] -= CaddWeapon->WeaponSelected->Cost;
				}
			}
			
			// sell weapon ???
			else{
				CaddWeapon->Select (SI[cp * 8 + sold].Weapon);
				pm[cp] += CaddWeapon->WeaponSelected->Cost;
				SI[cp * 8 + sold].Weapon = -1;
				
				// sell ammo too !!!
				
				if (SI[cp * 8 + sold].Ammo > 0){
					pm[cp] += CaddWeapon->WeaponSelected->MagCost 
					* SI[cp * 8 + sold].Ammo;
					SI[cp * 8 + sold].Ammo = 0;
					
					/*
						yes, you get money from in mag bullets !!!
					*/
					pm[cp] += (CaddWeapon->WeaponSelected->MagCost 
					* SI[cp * 8 + sold].Inmag) / CaddWeapon->WeaponSelected->MagSize;
					
					SI[cp * 8 + sold].Inmag = 0;
				}
			}
		}
		
		Mem2Mem (pic3_ptr, VB);
		sprintf (output, "PLAYER %d of %d", cp + 1, human_players);
		DisplayString (output, 15, 15);
		sprintf (output, "SOLDIER %d of %d", sold + 1, TI[cp].soldiers);
		DisplayString (output, 15, 30);
		sprintf (output, "%lu DOLLARS LEFT", pm[cp]);
		DisplayString (output, 15, 45);
		
		if (SI[cp * 8 + sold].Weapon == -1){
			sprintf (output, "CURRENT WEAPON, NONE");
		}
		
		else{
			sprintf (output, "CURRENT WEAPON, WEAPON %s, %lu CLIPS", 
			CaddWeapon->GetName (SI[cp * 8 + sold].Weapon), 
			SI[cp * 8 + sold].Ammo);
		}
		
		DisplayString (output, 15, 60);
		
		// buy/sell buttons
		DisplayString ("WEAPON LIST", 15, 92);

		for (c = 0; c < 4; c++){
			DrawTextedButton (15, 100 + (c + 1) * 12, 176, 10, 0,
			CaddWeapon->GetName (c + scroll_index));
			AddEvent (15, 100 + (c + 1) * 12, 176, 10);
			
			CaddWeapon->Select (c + scroll_index);
			sprintf (output, "cost %lu,ammo %lu",
			CaddWeapon->WeaponSelected->Cost,
			CaddWeapon->WeaponSelected->MagCost);
			DrawTextedButton (15 + 190, 100 + (c + 1) * 12, 113, 10, 1, output);
		}
		
		DrawTextedButton (15, 99, 96, 10, 0, LoadEvents[0]);
		DrawTextedButton (15 + 100, 99, 96, 10, 0, LoadEvents[1]);
		
		switch (stat){
			case 0:	DrawTextedButton (120, 13, 34, 10, 1, "NEXT"); break;
			default: DrawTextedButton (120, 13, 34, 10, 0, "NEXT"); break;
		}
		
		switch (stat){
			case 1:	DrawTextedButton (120 + 40, 13, 34, 10, 1, "PREV"); break;
			default: DrawTextedButton (120 + 40, 13, 34, 10, 0, "PREV"); break;
		}
		
		switch (stat){
			case 2:	DrawTextedButton (120, 28, 34, 10, 1, "NEXT"); break;
		 	default: DrawTextedButton (120, 28, 34, 10, 0, "NEXT"); break;
		}
	
		switch (stat){
			case 3:	DrawTextedButton (120 + 40, 28, 34, 10, 1, "PREV"); break;
			default: DrawTextedButton (120 + 40, 28, 34, 10, 0, "PREV"); break;
		};
		
		switch (stat){
			case 4:	DrawTextedButton (cpx, 180, 34, 10, 1, "DONE"); break;
			default: DrawTextedButton (cpx, 180, 34, 10, 0, "DONE"); break;
		};
		
		switch (stat){
			case 5: DrawTextedButton (15, 80, 64, 10, 1, "BUY AMMO"); break;
			default: DrawTextedButton (15, 80, 64, 10, 0, "BUY AMMO"); break;
		}
		
		switch (stat){
			case 6: DrawTextedButton (15 + 92, 80, 64, 10, 1, "SELL AMMO"); break;
			default: DrawTextedButton (15 + 92, 80, 64, 10, 0, "SELL AMMO"); break;
		}
		
		if (stat >= 7 && stat <= 10){
			// display weapon names
			DrawTextedButton (15, 100 + (stat - 6) * 12, 176, 10, 1,
			CaddWeapon->GetName ((stat - 7) + scroll_index));
		}
		
		switch (stat){
			case 11: DrawTextedButton (15, 99, 96, 10, 1, LoadEvents[0]); break;
			default: DrawTextedButton (15, 99, 96, 10, 0, LoadEvents[0]); break;
		}
		
		switch (stat){
			case 12: DrawTextedButton (15 + 100, 99, 96, 10, 1, LoadEvents[1]); break;
			default: DrawTextedButton (15 + 100, 99, 96, 10, 0, LoadEvents[1]); break;
		}
		
		HideMouse ();
		RefreshVRAM (VB);
		ShowMouse ();
		timer_ticks = 0;
		timer_start = 1;

		if (stat == 4){
			while (timer_ticks < 200);
			bad = 0;
			
			for (pc = 0; pc < default_players; pc++){
				if (pm[pc] < 0 ) bad = 1;
			}
			
			if (bad == 0){
				for (pc = 0; pc < human_players; pc++){
					TI[pc].money = pm[pc];
				}
				
				break;
			}
		}
		
		timer_ticks = 0;
		timer_start = 1;
		
		while (mouseb == LEFTB){
			UpdateMouse ();
			if (timer_ticks >= 150) break;
		}
		
		timer_start = timer_ticks = 0;
		UpdateMouse ();
		
		if (mouseb != LEFTB){
			DrawTextedButton (120, 13, 34, 10, 0, "NEXT");
			DrawTextedButton (120 + 40, 13, 34, 10, 0, "PREV");
			DrawTextedButton (120, 28, 34, 10, 0, "NEXT");
			DrawTextedButton (120 + 40, 28, 34, 10, 0, "PREV");
		
			// display weapon names
			DrawTextedButton (15, 100 + (0 + 1) * 12, 96, 10, 0,
			CaddWeapon->GetName (scroll_index));

			DrawTextedButton (15, 100 + (1 + 1) * 12, 96, 10, 0,
			CaddWeapon->GetName (scroll_index + 1));

			DrawTextedButton (15, 100 + (2 + 1) * 12, 96, 10, 0,
			CaddWeapon->GetName (scroll_index + 2));

			DrawTextedButton (15, 100 + (3 + 1) * 12, 96, 10, 0,
			CaddWeapon->GetName (scroll_index + 3));

			DrawTextedButton (15, 80, 64, 10, 0, "BUY AMMO");
			DrawTextedButton (15 + 92, 80, 64, 10, 0, "SELL AMMO");
			
			DrawTextedButton (15, 99, 96, 10, 0, LoadEvents[0]);
			DrawTextedButton (15 + 100, 99, 96, 10, 0, LoadEvents[1]);
			
			for (c = 0; c < 4; c++){
				DrawTextedButton (15, 100 + (c + 1) * 12, 176, 10, 0,
				CaddWeapon->GetName (c + scroll_index));
				AddEvent (15, 100 + (c + 1) * 12, 176, 10);
			
				CaddWeapon->Select (c + scroll_index);
				sprintf (output, "cost %lu,ammo %lu",
				CaddWeapon->WeaponSelected->Cost,
				CaddWeapon->WeaponSelected->MagCost);
				DrawTextedButton (15 + 190, 100 + (c + 1) * 12, 113, 10, 1, output);
			}
				
				HideMouse ();
				RefreshVRAM (VB);
				ShowMouse ();
		}
	}
	
	HideMouse ();
	SetRepeat (250, 75);
}

void InitCPU (void)
{
	long CPU, xsold, xc, BaseHitPoints;

	randomize ();
	
	for (CPU = 0; CPU < PLAYERS; CPU++){
		for (xsold = 0; xsold < 8; xsold++){
			if (CPU >= human_players){
				TI[CPU].soldiers = MAX_START;
				
				if (xsold > 0){
					while (1){
						SI[CPU * 8 + xsold].Weapon = rnd (CaddWeapon->weapons - 1);
						if (SI[CPU * 8 + xsold].Weapon !=
						SI[CPU * 8 + xsold - 1].Weapon) break;
					}
				}
				
				else{
					SI[CPU * 8 + xsold].Weapon = rnd (CaddWeapon->weapons - 1);
				}
				
				SI[CPU * 8 + xsold].Kills = 0;
				SI[CPU * 8 + xsold].Experience = rand ()% 500;
				SI[CPU * 8 + xsold].Cost =
				SI[CPU * 8 + xsold].Experience * 50;
				SI[CPU * 8 + xsold].Ammo = 12;
				CaddWeapon->Select (SI[CPU * 8 + xsold].Weapon);
				SI[CPU * 8 + xsold].Inmag = 
				CaddWeapon->WeaponSelected->MagSize;
				
				SI[CPU * 8 + xsold].Strength = rnd (14) + 1;
				SI[CPU * 8 + xsold].Constitution = rnd (14) + 1;
				
				BaseHitPoints = SI[CPU * 8 + xsold].Strength +
				SI[CPU * 8 + xsold].Constitution;
				
				SI[CPU * 8 + xsold].HP[HEAD_HPS] = BaseHitPoints;
				SI[CPU * 8 + xsold].HP[CHEST_HPS] = BaseHitPoints * 3;
				SI[CPU * 8 + xsold].HP[LEFTARM_HPS] = BaseHitPoints * 2;
				SI[CPU * 8 + xsold].HP[RIGHTARM_HPS] = BaseHitPoints * 2;
				SI[CPU * 8 + xsold].HP[ABDOMEN_HPS] = BaseHitPoints * 2;
				SI[CPU * 8 + xsold].HP[LEFTLEG_HPS] = BaseHitPoints * 2;
				SI[CPU * 8 + xsold].HP[RIGHTLEG_HPS] = BaseHitPoints * 2;
				
				for (xc = 0; xc < 7; xc++){
					SI[CPU * 8 + xsold].OHP[xc] = 
					SI[CPU * 8 + xsold].HP[xc];
				}
			}
		}
	}
}

/*
	opposite action as in CopyData function
*/
void TransferData (long player)
{
	long realsoldier, cnt;
	long newindex = 0;
	
	// store soldier info	
	for (realsoldier = 0; realsoldier < CaddTeam->activesoldiers; realsoldier++){
		while (1){
			CaddSoldier->SelectSoldier (newindex);

			if (CaddSoldier->SoldierSelected->active == 1){
				break;
			}
			
			newindex++;

			if (newindex > 7){	// something's wrong...
				return;
			}
		}
		
		// select new index
		CaddSoldier->SelectSoldier (newindex);
		
		for (cnt = 0; cnt < 7; cnt++){
			CaddSoldier->SoldierSelected->HP[cnt] = 
			SI[player * 8 + realsoldier].HP[cnt];
		}
		
		CaddSoldier->SoldierSelected->Weapon =
		SI[player * 8 + realsoldier].Weapon;
				
		CaddSoldier->SoldierSelected->Ammo =
		SI[player * 8 + realsoldier].Ammo;
		
		CaddSoldier->SoldierSelected->Inmag =
		SI[player * 8 + realsoldier].Inmag;
		
		CaddSoldier->SoldierSelected->APs = 
		SI[player * 8 + realsoldier].APs;
				
		CaddSoldier->SoldierSelected->Kills =
		SI[player * 8 + realsoldier].Kills;

		CaddSoldier->SoldierSelected->Experience =
		SI[player * 8 + realsoldier].Experience;

		CaddSoldier->SoldierSelected->Rank = 
		SI[player * 8 + realsoldier].Rank;
		
		CaddSoldier->SoldierSelected->FireSkill =
		SI[player * 8 + realsoldier].FireSkill;
		newindex++;	// skip this soldier
	}
}

/*
	copies from CADD C++ classes and links to C structures
*/
void CopyData (long player)
{
	long realsoldier, cnt, scnt;
	long newindex = 0;
	
	// store team info
	TI[player].money = CaddTeam->money;
	TI[player].soldiers = CaddTeam->activesoldiers;

	// store soldier info	
	for (scnt = 0; scnt < TI[player].soldiers; scnt++){
		while (1){
			CaddSoldier->SelectSoldier (newindex);
			if (CaddSoldier->SoldierSelected->active == 1) break;
			newindex++;

			if (newindex > 7){	// something's wrong...
				return;
			}
		}
		
		realsoldier = scnt;
		
		CaddSoldier->SelectSoldier (newindex);
		SI[player * 8 + realsoldier].Team = CaddTeam->ID;
		SI[player * 8 + realsoldier].FirstName = 
		CaddSoldier->SoldierSelected->FirstName;
		SI[player * 8 + realsoldier].SurName = 
		CaddSoldier->SoldierSelected->SurName;
		
		for (cnt = 0; cnt < 7; cnt++){
			SI[player * 8 + realsoldier].HP[cnt] = 
			CaddSoldier->SoldierSelected->HP[cnt];
			SI[player * 8 + realsoldier].OHP[cnt] = 
			CaddSoldier->SoldierSelected->HP[cnt];
		}
		
		SI[player * 8 + realsoldier].Weapon = 
		CaddSoldier->SoldierSelected->Weapon;
		
		SI[player * 8 + realsoldier].Ammo = 
		CaddSoldier->SoldierSelected->Ammo;
		
		SI[player * 8 + realsoldier].Inmag = 
		CaddSoldier->SoldierSelected->Inmag;
		
		SI[player * 8 + realsoldier].APs = 
		CaddSoldier->SoldierSelected->APs;
		
		SI[player * 8 + realsoldier].Strength = 
		CaddSoldier->SoldierSelected->Strength;
		
		SI[player * 8 + realsoldier].Constitution = 
		CaddSoldier->SoldierSelected->Constitution;

		SI[player * 8 + realsoldier].Kills = 
		CaddSoldier->SoldierSelected->Kills;

		SI[player * 8 + realsoldier].Experience = 
		CaddSoldier->SoldierSelected->Experience;

		SI[player * 8 + realsoldier].Rank =
		CaddSoldier->SoldierSelected->Rank;

		SI[player * 8 + realsoldier].Cost = 
		CaddSoldier->SoldierSelected->Cost;

		SI[player * 8 + realsoldier].Load = 
		CaddSoldier->SoldierSelected->Load;
		
		SI[player * 8 + realsoldier].FireSkill = 
		CaddSoldier->SoldierSelected->FireSkill;
		
		// init CADD Soldier link list index (important&must be valid !!)
		SI[player * 8 + realsoldier].CaddSoldierIndex = realsoldier;

		// armor not yet supported...
		SI[player * 8 + realsoldier].Armor = -1;
		newindex++;	// skip current soldier
	}
}

/*
	Updates team file when needed
	(like when somebody has died, etc)
*/
long UpdateTeamFile (void)
{
	long cnt, xc, stat, xsold, deletes;
	long rsold, done;
	int by = 20;
	char output[40];
	
	maxy = 199;
	
	for (cnt = 0; cnt < human_players; cnt++){
		deletes = 0;
		stat = LoadTeam (TeamFile[cnt]);
		
		if (stat != 0){
			printf ("load failed\n");
			return stat;
		}
		
		// update C++ class links if needed
		TransferData (cnt);
		CaddTeam->money = TI[cnt].money;

		// loop through all "active" soldiers
		for (xsold = 0; xsold < TI[cnt].soldiers; xsold++){
			// check from deads, active soldiers
			rsold = SI[cnt * 8 + xsold].CaddSoldierIndex;
			done = 0;
			
			for (xc = 0; xc < 7; xc++){
				if (SI[cnt * 8 + xsold].HP[xc] <= -SI[cnt * 8 + xsold].OHP[xc] && done == 0){
					CaddTeam->teamsoldiers--;
					CaddSoldier->SelectSoldier (rsold);
					
					if (CaddSoldier->SoldierSelected->active){
						CaddTeam->activesoldiers--;
					}
					
					CaddSoldier->DeleteSoldier (rsold);
					deletes++;
					done = 1;
				}
			}
		}
	
		sprintf (output, "Player %lu, %lu deads", cnt + 1, deletes);
		DisplayString (output, 20, by);
		by += 10;
		RefreshVRAM (VB);
		
		stat = SaveTeam (TeamFile[cnt]);
		
		if (stat != 0){
			printf ("save failed\n");
			return stat;	
		}
	}
	
	DisplayString ("PRESS ANY KEY TO CONTINUE", 20, 180);
	RefreshVRAM (VB);
	while (!no_key());
	WaitKB ();
	maxy = 199 - 32;
	return 0;
}

/*
	Calculates load APs loss
*/
void CalcLoadAPsLoss (void)
{
	long cnt, xc;

	for (cnt = 0; cnt < PLAYERS; cnt++){	
		for (xc = 0; xc < TI[cnt].soldiers; xc++){
			if (SI[cnt * 8 + xc].Weapon != -1){
				CaddWeapon->Select (SI[cnt * 8 + xc].Weapon);
				SI[cnt * 8 + xc].Load =
				CaddWeapon->WeaponSelected->Weight;
			}
			
			else{
				SI[cnt * 8 + xc].Load = 0;
			}

			if (cnt < human_players){
				//printf ("load is %lu KGs\n", SI[cnt * 8 + xc].Load);
			}
		}
	}
}

/*
	selects human player team file
*/
long SelectHumanPlayerTeamFiles (void)
{
	long cnt, xs, c, xc;
	
	for (cnt = 0; cnt < human_players; cnt++){
		xs = InitTeam ();
		
		if (xs != 0){
			textcolor (LIGHTRED);
			cprintf ("InitTeam error %d\n\r", xs);
			return xs + cnt;
		}
		
		xs = RealLoadTeam (cnt + 1, 0, 1);
	
		if (xs != 0){
			textcolor (LIGHTRED);
			cprintf ("RealLoadTeam error %d\n\r", xs);
			return xs + cnt;
		}
		
		// copy from C++ class links to C structures
		CopyData (cnt);
		
		if (CaddTeam->activesoldiers > 8 || CaddTeam->activesoldiers < 1){
			asm ("
				movw $0x3, %ax
				int $0x10
			");

			textcolor (LIGHTRED);
			cprintf ("Invalid active soldier count %lu\n\r", CaddTeam->activesoldiers);
			return -64;
		}
	
		KillSoldiers (cnt, 8 - CaddTeam->activesoldiers);
		FreeTeam ();
	}
	
	// initializes CPU's soldier structures
	InitCPU ();
	CalcLoadAPsLoss ();
	ShadeFont (32, 1);
	return 0;
}

/*
	Initializes Combat Team II
*/
int InitCT2 (void)
{
	signed char istat;
	signed long int fps, time;
	int stat, c;
	char *headline = "<Initializing Combat Team 2 - version 0.80á>";
	long cnt, xc;
	
	delay (1000);
	_set_screen_lines (50);
	clrscr ();
	cprintf ("\n\r");
	
	textcolor (BLUE);
	textbackground (BLUE);
	
	for (stat = 1; stat < 80; stat++){
		gotoxy (stat, 1);
		cprintf ("%c", 219);
	}
	
	textcolor (YELLOW);
	gotoxy (40 - strlen (headline) / 2, 1);
	cprintf ("%s", headline);
	
	textcolor (LIGHTGREEN);
	textbackground (BLACK);
	gotoxy (1, 3);
		
	InitGraphPointer ();
	istat = CheckInstalled ();

	if (istat != -1){
		cprintf ("No mouse found (please run your mouse driver)\n\r");
		return -1;
	}

	stat = LoadConfig ("config.ct2");

	if (stat != 0){
		return stat;
	}
	
	if (scard != 0){
		cprintf ("Installing SoundBlaster driver with sampling rate 11025Hz\n\r");

		if (sb_install_driver (11025) != SB_SUCCESS) {
			textcolor (LIGHTRED);
			cprintf ("Driver error: %s\n\r", sb_driver_error);
			return 1000;
		}
		
		cprintf ("Hope you hear a pop now...\n\r");
		scard_init = 1;
		istat = InitSamples ();
		if (istat != 0) return istat + 1500;
		sample_init = 1;
	
		SetStereoVolumes (32, 0);
		sb_mix_sample (sample[5]);
		SetStereoVolumes (0, 32);
		sb_mix_sample (sample[6]);
		SetStereoVolumes (32, 32);
		cprintf ("Or actually two test explosion sounds !!!\n\r\n\r");
		delay (250);
		
		if (activate_music){
			cprintf ("Loading .\\music\\army.mod\n\r");
			mod=sb_load_mod_file (".\\music\\army.mod");

		  if(mod==NULL) {
		  	textcolor (LIGHTRED);
		    cprintf ("MOD Error (file .\\music\\army.mod): %s\n\r\n\r",sb_mod_error);
		    sb_uninstall_driver();
		    exit(1);
			}
			
		  mod_loaded = 1;
		  mod_init = 1;
		 }
  }
  
  /*
  	this should prevent from GPF error
  */
  stat = InitTeam ();
	
	if (stat != 0){
		textcolor (LIGHTRED);
		cprintf ("Team Init error %d\n\r", stat);
		return stat;
	}
	
	stat = FreeTeam ();
	
	istat = InitData ();
	if (istat != 0) return istat;
	delay (1000);
	
	InitGraph ();
	istat =  (int) _farpeekb (_go32_conventional_mem_selector (), (0x40 * 16) + 0x49);

	if (istat != 0x13){
		textcolor (LIGHTRED);
		cprintf ("Your display card doesn't support Mode 13H (320x200x8b)\n\r");
		return istat;
	}
	
	SetHorizontalLimits (minx, maxx * 2);
	SetVerticalLimits (miny, maxy);

	// show intro seqs
	SetPalette (&Palette[0]);
	
	// display start warning
	stat = GraphWarning ();

	if (stat != 0){
		CloseGraph ();
		return -255;
	}
		
	Intro ();
	stat = Start ();
	
	if (stat == 1){
		return stat;
	}
	
	stat = MapSelect ();
	
	if (stat != 0){
		return stat;
	}

	stat = SelectHumanPlayerTeamFiles ();
	
	if (stat != 0){
		textcolor (LIGHTRED);
		cprintf ("InitTeam returned error %d\n\r", stat);
		return -64;	
	}
	
	Shop ();
	
	DarkenPalette ();
	SetPalette (&Palette[0]);

	if (scard != 0 && mod_loaded == 1){
	  if(!sb_mod_active){
			if (activate_music == 1){
				sb_mod_play(mod);
			}
		}
	}

	UpdateGame ();
	return 0;
}

/*
	closegraph + end screen
*/
int CloseGame (void)
{
	int stat;
	
  	CloseGraph ();
        
	// display amount of frames per second

	stat = End ();

	if (stat != 0){
	 	textcolor (LIGHTRED);
		cprintf ("File end.bin is missing\n\r");
		return -1;
	}
	
	return 0;
}

/*
	start menu
*/
int StartMenu (void)
{
	int stat, c;
	long cnt, xc;
	
	LoadPalette ();
	SetPalette (&Palette[0]);

	stat = Start ();
	
	if (stat == 1){
		return stat;
	}
	
	stat = MapSelect ();
	
	if (stat != 0){
		return stat;
	}

	stat = SelectHumanPlayerTeamFiles ();
	
	if (stat != 0){
	  	textcolor (LIGHTRED);
		cprintf ("InitTeam returned error %d\n\r", stat);
		return -64;	
	}

	Shop ();
	DarkenPalette ();
	SetPalette (&Palette[0]);

	if(!sb_mod_active){
		if (activate_music == 1){
			sb_mod_play(mod);
		}
	}
	
	UpdateGame ();
	return 0;
}

/*
	Frees memory buffers & closes current graphics mode
*/
int FreeCT2 (void)
{
	Restore_Timer ();
	Restore_Keyboard ();
	free (blockPTR);
	free (VB);
	free (mousePTR);
	free (menuPTR);
	free (spritePTR);
	
	// new
	free (pic1_ptr);
	free (pic2_ptr);
	free (pic3_ptr);
	free (artPTR);

	FreeFonts ();
	FreeCADD ();
	
	if (scard != 0){
		sb_uninstall_driver ();
		
		if (activate_music == 1){
			sb_free_mod_file (mod);
		}
		
		FreeSamples ();
	}

	return 0;
}

/*
	custom/save free allocated item(s)
*/
void CustomFree (void)
{
	if (timer_init == 1){
		Restore_Timer ();
	}
	
	if (kb_init == 1){
		Restore_Keyboard ();
	}
	
	if (block_init == 1){
		free (blockPTR);
	}
	
	if (vb_init == 1){
		free (VB);
	}
	
	if (mouse_init == 1){
		free (mousePTR);
	}
	
	if (menu_init == 1){
		free (menuPTR);
	}
	
	if (sprite_init == 1){
		free (spritePTR);
	}
	
	if (font_init == 1){
		FreeFonts ();
	}
	
	if (CADD_init == 1){
		FreeCADD ();
	}
	
	if (pic1_init == 1){
		free (pic1_ptr);
	}
	
	if (pic2_init == 1){
		free (pic2_ptr);
	}
	
	if (pic3_init == 1){
		free (pic3_ptr);
	}
	
	if (art_init == 1){
		free (artPTR);
	}
	
	if (scard != 0){
		if (scard_init == 1){
			sb_uninstall_driver ();
		}
		
		if (activate_music == 1){
			if (mod_init == 1){
				sb_free_mod_file (mod);
			}
		}
		
		if (sample_init == 1){
			FreeSamples ();	
		}
	}
	
	if (credit_init == 1){
		FreeCreditScroller ();
	}
}