// temp.cpp : Defines the entry point for the console application.
//

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <memory.h>
#include <string.h>

#include "twister.h"

#include "inter.h"
#include "gameover.h"
#include "game.h"
#include "spec.h"
#include "menu.h"
#include "conf.h"
#include "manual.h"

#include "unmo3.h"

void screen_shot(CON_OUTPUT* s, const char* name=0)
{
	const static unsigned char ansi_pal[16*3] =
	{
		  0,  0,  0,
		170,  0,  0,
		  0,170,  0,
		170, 85,  0,
		  0,  0,170,
		170,  0,170,
		  0,170,170,
		170,170,170,
		 85, 85, 85,
		255, 85, 85,
		 85,255, 85,
		255,255, 85,
		 85, 85,255,
		255, 85,255,
		 85,255,255,
		255,255,255
	};

	char path[1024];
	if (name)
		sprintf_s(path,1024,"%s%s.xp",shot_path(),name);
	else
		sprintf_s(path,1024,"%s%X.xp",shot_path(),get_time());

	FILE* f=0;
	fopen_s(&f,path,"wb");

	if (f)
	{
		int ver = -1;
		fwrite(&ver,4,1,f);

		int layers = 1;
		fwrite(&layers,4,1,f);

		fwrite(&s->w,4,1,f);
		fwrite(&s->h,4,1,f);

		const unsigned char* fg = ansi_pal+3*0;
		const unsigned char* bg = ansi_pal+3*15;

		for (int x=0; x<s->w; x++)
		{
			for (int y=0; y<s->h; y++)
			{
				int code = s->buf[x + y*(s->w+1)];
				fwrite(&code,4,1,f);

				if (s->color)
				{
					fg = ansi_pal + 3*(s->color[x + y*(s->w+1)] & 0x0F);
					bg = ansi_pal + 3*((s->color[x + y*(s->w+1)] >> 4) & 0x0F);
				}

				fwrite(fg,3,1,f);
				fwrite(bg,3,1,f);
			}
		}

		fclose(f);
	}
}

#if 0
// +1: always true, higher values makes it harder to get true
//  0: exception!
// -1: always false, lower values makes it easier to get true
#define MOD_RAND(mod) ( mod && ( mod>0 ? twister_rand()%mod==0 : twister_rand()%(-mod)!=0 ) )

void MakeTerrain(const char* path, int len)
{
	twister_seed(get_time());

	int checkpoints = 5;

	// cracks & craters
	// and enemies inside and on their boundaries
	int hole_dist=80;

	int crack_mod = 4;
	
	int hole_creature_mod = 1; 
	int hole_edge_enemy_mod = 1;

	int hole_edge_t=1;
	int hole_edge_m=1;
	int hole_edge_h1=1;
	int hole_edge_h2=1;
	int hole_edge_h3=1;

	int enemy_dist = 50;
	int enemy_t=1;
	int enemy_m=1;
	int enemy_h1=1;
	int enemy_h2=1;
	int enemy_h3=1;
	int enemy_b1=1;
	int enemy_b2=1;
	int enemy_b3=1;
	int enemy_b4=1;
	int enemy_r=1;

	int terrain_harmonics=10;

	int enemy_U=5;
	int enemy_D=5;
	int enemy_B=5;

	FILE* f=0;
	fopen_s(&f,path,"wt");

	// desired input:
	// -------------------------
	// begin_difficulty 1..100
	// end_difficult 1..100
	// length: 500..10000
	// checkpoints: 1..length/500
	// modes: [mine_filed / flies / regular] x checkpoints


	struct HARMONIC
	{
		HARMONIC()
		{
			Init();
			age = twister_rand() % ( attack + sustain + decay);
		}

		void Init()
		{
			freq = (twister_rand()%1024 + 100)*0.0001f;
			ampl = 0.04f/freq;
			ampl *= (twister_rand()%1024 + 100)/1124.0f;
			attack = twister_rand()%32+16;
			sustain = twister_rand()%256+32;
			decay = twister_rand()%32+16;
			age = 0;
		}

		float Get()
		{
			if (age>=attack+sustain+decay)
				Init();

			float vol = ampl;

			if (age<attack)
				vol*=(float)(age-attack)/(float)attack;

			if (age>attack+sustain)
				vol*=(float)(attack+sustain+decay-age)/(float)decay;

			float h = sinf(age*freq)*vol;

			age++;

			return h;
		}

		float freq;
		float ampl;
		int attack;
		int sustain;
		int decay;
		int age;
	};

	// generate basic terrain
	HARMONIC gen[10];
	char* arr = (char*)malloc(len+1);
	char* spr = (char*)malloc(len+1);
	arr[len]=0;
	spr[len]=0;

	memset(spr,' ',len);
	spr[1]='@';

	int last_r = 0;

	for (int n=0; n<checkpoints; n++)
	{
		int cp = (n+1)*len/checkpoints-1;
		spr[cp]='#';
	}

	for (int i=0; i<len; i++)
	{
		float h=0.0f;
		for (int j=0; j<terrain_harmonics; j++)
			h+=gen[j].Get();
		arr[i] = 3 + (int)floorf(h+0.5f);
	}

	// clamp to 0-7
	for (int i=0; i<len; i++)
	{
		arr[i] = MAX(0,arr[i]);
		arr[i] = MIN(7,arr[i]);
	}

	// filter out tiny pops
	for (int i=2; i<len; i++)
	{
		if (arr[i-2] == arr[i])
			arr[i-1] = arr[i];
	}

	int max_slope=7;
	for (int i=max_slope; i<len; i++)
	{
		int ilo=i;
		int ihi=i;
		int lo=arr[i];
		int hi=arr[i];
		for (int j=i-max_slope; j<=i; j++)
		{
			if (arr[j]<lo)
			{
				lo=arr[j];
				ilo=j;
			}
			if (arr[j]>hi)
			{
				hi=arr[j];
				ihi=j;
			}
		}

		if (hi-lo>1)
		{
			// make 1:7 slope until convergence with arr

			if (ilo<ihi)
			{
				while (arr[ilo+1]==lo)
					ilo++;
				int j=ilo+1;
				while (j<len)
				{
					int slope = lo + (j-ilo)/max_slope;
					if (arr[j]<=slope)
						break;
					arr[j]=slope;
					j++;
				}
			}
			else
			{
				while (arr[ihi+1]==hi)
					ihi++;
				int j=ihi+1;
				while (j<len)
				{
					int slope = hi - (j-ihi)/max_slope;
					if (arr[j]>=slope)
						break;
					arr[j]=slope;
					j++;
				}
			}
		}
	}

	// distribution
	int hole_edge_enemy[]={'t','m','h1','h2','h3'};
	int hole_edge_width[]={8,4,4,8,13};
	int hole_edge_ratio[]={hole_edge_t,hole_edge_m,hole_edge_h1,hole_edge_h2,hole_edge_h3};
	int hole_edge_sum=hole_edge_t+hole_edge_m+hole_edge_h1+hole_edge_h2+hole_edge_h3;

	if (hole_dist)
	for (int i=80; i<len-40-hole_dist; i+=hole_dist)
	{
		// todo:
		// ensure no nearby checkpoints!
		bool ok=true;
		for (int n=0; n<checkpoints; n++)
		{
			int cp = (n+1)*len/checkpoints-1;
			if (ABS(cp-i)<hole_dist)
			{
				ok=false;
				break;
			}
		}

		if (!ok)
			continue;

		int pos = i+twister_rand()%hole_dist;

		int edge_left = -1;
		int edge_right = -1;

		if (MOD_RAND(crack_mod))
		{
			int crack_width=8;
			int width = twister_rand()%crack_width+6;

			// crack
			int l=pos+2;
			int r=pos+width-2;

			for (int j=pos; j<l; j++)
				arr[j]=MIN(arr[j],arr[j-1]-1);
			for (int j=pos+width-1; j>=r; j--)
				arr[j]=MIN(arr[j],arr[j+1]-1);

			arr[l]=MIN(arr[l],arr[l-1]-2);
			arr[r-1]=MIN(arr[r-1],arr[r]-2);

			l++;
			r--;

			arr[l]=MIN(arr[l],arr[l-1]-3);
			arr[r-1]=MIN(arr[r-1],arr[r]-3);


			for (int j=l+1; j<r-1; j++)
				arr[j]=-2;

			edge_left = pos;
			edge_right = pos+width;
		}
		else
		{
			int width = 14+2*(twister_rand()%3);

			float y = width*0.5f;
			float r = sqrtf(2.0f)*y;
			float x = pos+y;

			int h = MAX(arr[pos],arr[pos+width/*-1*/]);

			for (int j=pos; j<pos+width; j++)
				arr[j]= MIN(arr[j],h-MAX(0,(int)floorf(0.5f+sqrtf(r*r-(j-x)*(j-x)) - y)));

			// if creature, ensure flat base 8
			if (MOD_RAND(hole_creature_mod))
			{
				int h = arr[pos+width/2-4];
				for (int j=pos+width/2-4; j<pos+width/2+4; j++)
					arr[j]=h;
				spr[pos+width/2-4] = 'c';
			}

			edge_left = pos;
			edge_right = pos+width;
		}

		for (int j=edge_left; j<=edge_right; j++)
		{
			if (spr[j]==' ')
				spr[j]='.';
		}

		if (hole_edge_sum && MOD_RAND(hole_edge_enemy_mod))
		{
			// pick random side(s)
			int side = twister_rand()%3 - 1;

			// if side is 0 or 1 ensure there is enough space to checkpoint
			// if not, change side to -1
			if (side>=0)
			{
				int i = side==0 ? edge_right+2 : edge_right+2+30;
				for (int n=0; n<checkpoints; n++)
				{
					int cp = (n+1)*len/checkpoints-1;
					if (ABS(cp-i)<enemy_dist)
					{
						side=-1;
						break;
					}
				}
			}

			// pick random enemy from repertoire
			int enemy = twister_rand()%hole_edge_sum;

			int j=0;
			for (j=0; enemy>=hole_edge_ratio[j]; j++)
				enemy-=hole_edge_ratio[j];

			int kind = hole_edge_enemy[j];
			if (kind=='h3' && side==0) // no h3 at right side
				side=1;

			int width = hole_edge_width[j];
			int epos;
			if (side<0)
				epos = edge_left-1 - width;
			else
			if (side==0)
				epos = edge_right+2;
			else
			{
				if (kind=='t') 
					epos = edge_right+2+30; // bit more space
				else
					epos = edge_right+2+20; // with landing place
			}

			int h=(arr[epos-1]+arr[epos+width+1]+1)/2;

			for (int j=epos-1; j<epos+width+1; j++)
			{
				arr[j]=h;
			}

			if (side!=0)
			{
				int k=arr[epos-2]-h;

				if (k)
				for (int j=epos-2; j>=0; j--)
				{
					int slope = h + (k>0 ? (epos-j)/max_slope : (j-epos)/max_slope);
					if (k>0 && arr[j]<slope)
						break;
					if (k<0 && arr[j]>slope)
						break;
					arr[j] = slope;
				}
			}

			if (side>0)
			{
				int k=arr[epos+width+1]-h;

				if (k)
				for (int j=epos+width+1; j<len; j++)
				{
					int slope = h + (k>0 ? (j-(epos+width))/max_slope : (epos+width-j)/max_slope);
					if (k>0 && arr[j]<slope)
						break;
					if (k<0 && arr[j]>slope)
						break;
					arr[j] = slope;
				}
			}

			for (int c=-1; c<=width; c++)
			{
				if (spr[epos+c]==' ')
					spr[epos+c]='.';
			}

			for (int c=0; c<4; c++)
			{
				if (kind & (0xFF000000>>(c*8)))
				{
					spr[epos]=(kind>>(24-c*8))&0xFF;
					epos++;
				}
			}

		}

		i=pos;
	}

	int enemy[]={'t','m','h1','h2','h3', 'b1','b2','b3','b4', 'r'};
	int enemy_width[]={8,4,4,8,13, 3,4,8,9, 0};
	int enemy_ratio[]={enemy_t,enemy_m,enemy_h1,enemy_h2,enemy_h3, enemy_b1,enemy_b2,enemy_b3,enemy_b4, enemy_r};
	int enemy_sum=enemy_t+enemy_m+enemy_h1+enemy_h2+enemy_h3 +enemy_b1+enemy_b2+enemy_b3+enemy_b4 + enemy_r;

	// place oridinary enemies (where possible)
	if (enemy_dist)
	for (int i=100; i<len-80; i+=enemy_dist)
	{
		// pick enemy kind
		int renemy = twister_rand()%enemy_sum;

		int e=0;
		for (e=0; renemy>=enemy_ratio[e]; e++)
			renemy-=enemy_ratio[e];

		int kind = enemy[e];
		if (kind=='r')
		{
			if (last_r<i-400) // 400 is min-distance between rockets
			{

				bool ok=true;
				for (int k=i-enemy_dist; k<i+enemy_dist; k++)
				{
					if (spr[k]!=' ')
					{
						ok=false;
						break;
					}
				}

				if (ok)
				{
					for (int j=i-280; j<=i-280+5; j++) // 280 is actual offset between 'r' and required jump
					{
						if (spr[j]==' ' || spr[j]=='.' || spr[j]=='-')
						{
							spr[j]='r';
							last_r = i;
							break;
						}
					}
				}
			}

			if (last_r==i)
			{
				// rocket in place, reserve space for jump
				for (int j=i; j<i+20; j++)
				{
					if (spr[j]==' ')
						spr[j]='-';
				}

				continue;
			}

			// can't put anything here
			if (enemy_sum-enemy_r<=0)
				continue;

			// pick different kind
			renemy = twister_rand()%(enemy_sum-enemy_r);

			for (e=0; renemy>=enemy_ratio[e]; e++)
				renemy-=enemy_ratio[e];

			kind = enemy[e];
		}

		i+=twister_rand()%enemy_dist;
		int width=0;
		for (int j=i; j<len-80; j++)
		{
			if (arr[j]!=arr[i])
			{
				i=j;
				width=0;
			}
			width++;

			if (width>=enemy_width[e]+4)
			{
				// ensure no other enemies nearby
				bool ok=true;
				for (int k=i-enemy_dist; k<i+enemy_dist; k++)
				{
					if (spr[k]!=' ')
					{
						width-=j-i;
						i=j;
						ok=false;
						break;
					}
				}

				if (ok)
					break;
			}
		}

		if (width>=enemy_width[e]+4)
		{
			for (int c=-1; c<=enemy_width[e]; c++)
			{
				if (spr[i+2+c]==' ')
					spr[i+2+c]='.';
			}
			// fine, put it @ i
			for (int c=0; c<4; c++)
			{
				if (kind & (0xFF000000>>(c*8)))
				{
					spr[i+2]=(kind>>(24-c*8))&0xFF;
					i++;
				}
			}
		}
	}

	// add hi-freq texture (keep space from sprites)
	int texlen = twister_rand()%1+2;
	for (int i=10; i<len-10; i+=twister_rand()%8+8)
	{
		int h=arr[i];
		bool ch=true;
		for (int j=i-10; j<=i; j++)
		{
			if (arr[j]!=h)
			{
				ch=false;
				break;
			}
		}

		for (int j=i-10; j<i+texlen; j++)
			 if (spr[j]!=' ' || spr[j]=='#')
			 {
				 ch=false;
				 break;
			 }

		if (ch)
		{
			for (int j=i-5; j<i-5+texlen; j++)
				arr[j]--;

			texlen = twister_rand()%1+2;
		}
	}

	// flies

	int pcp=0;
	for (int n=0; n<checkpoints; n++)
	{
		int fly_sum = enemy_U + enemy_D + enemy_B;
		int fly_ratio[] = {enemy_U,enemy_D,enemy_B};
		int fly_kind[] = {'U','D','B'};

		int cp = (n+1)*len/checkpoints-1;

		while (fly_sum)
		{
			int pos = pcp + twister_rand()%(cp-pcp-10);
			for (int k=pos; k<pos+10; k++)
			{
				if (spr[k]==' ' || spr[k]=='.' || spr[k]=='-')
				{
					int renemy=twister_rand()%fly_sum;
					int e=0;
					for (e=0; renemy>=fly_ratio[e]; e++)
						renemy-=fly_ratio[e];

					int kind = fly_kind[e];

					fly_sum--;
					fly_ratio[e]--;

					spr[k] = kind;
					break;
				}
			}
		}

		pcp = cp;
	}

	for (int i=0; i<len; i++)
		arr[i]+='0';

	fwrite(spr,len,1,f);
	fwrite("\n",1,1,f);
	fwrite(arr,len,1,f);
	fwrite("\n",1,1,f);
	fclose(f);

	test_area[0].height = arr;
	test_area[0].sprite = spr;
	//free(arr);
	//free(spr);

}
#endif

MODAL* modal = 0;
SCREEN global_screen(90,28,' ',cl_transp);


struct CAMPAIGN_MODAL : MODAL
{
	// we can have one of 2 sub-modals active: gamelevel or interscreen
	MODAL* level_modal;
	MODAL* inter_modal;

	int iCourse;
	int iLevel;
	int iSubLev;

	SCREEN* s;
	int w;
	int h;

	int lives;
	int score;
	const COURSE* current_course;
	const LEVEL* current_level;

	int level_time;

	int startlives; // lives when entering level
	char hitbin[1024]; // so max level size is 8192!

	virtual ~CAMPAIGN_MODAL()
	{
		if (level_modal)
			delete level_modal;
		if (inter_modal)
			delete inter_modal;
	}

	CAMPAIGN_MODAL(SCREEN* scr, int ic, int il)
	{
		s=scr;
		w=scr->w;
		h=scr->h;

		iCourse = ic;
		iLevel  = il;
		iSubLev = 0;

		// iSubLev = 4;

		lives = 3;
		score = 0;
		current_course = campaign + iCourse;
		current_level = current_course->level + iLevel;

		startlives = lives;

		memset(hitbin,0,1024);
		level_time = 0;

		FILE* record_file = 0;
		fopen_s(&record_file,record_path(),"wb");
		if (record_file)
		{
			// write header
			unsigned char sign[8]="REC0";
			fwrite(sign,4,1,record_file);

			fwrite(&iCourse,4,1,record_file);
			fwrite(&iLevel,4,1,record_file);
			fwrite(&iSubLev,4,1,record_file);
			fwrite(&lives,4,1,record_file);

			// this part must be written before each (re)spawn!
			fwrite(&w,4,1,record_file);
			fwrite(&h,4,1,record_file);
			twister_write(record_file);

			crypt_ini();

			int n[4];
			memcpy(n,conf_player.name,16);
			n[0] ^= score;
			n[1] ^= score;
			n[2] ^= score;
			n[3] ^= score;
			crypt_enc(n+0);
			crypt_enc(n+1);
			crypt_enc(n+2);
			crypt_enc(n+3);
			fwrite(n,1,16,record_file);

			int a =conf_player.avatar;
			a ^= score;
			crypt_enc(&a);
			fwrite(&a,4,1,record_file);

			fclose(record_file);
			// ready for appending
		}

		level_modal = new LEVEL_MODAL(
			&global_screen,
			lives,startlives,
			&score,
			&level_time,
			conf_player.name,
			current_course->name,
			current_level,
			iSubLev, hitbin);

		inter_modal = 0;
	}

	virtual int Run()
	{
		// RETURN -2 is reserved for temporal exits to menu
		// RETURN -3 is permanent end of game exit.

		if (level_modal)
		{
			// in-game
			int ret = level_modal->Run();

			w=s->w;
			h=s->h;

			if (ret>=0)
			{
				// player just died in returned sublevel
				lives--;

				if (lives)
				{
					iSubLev = ret;

					delete level_modal;

					FILE* record_file = 0;
					fopen_s(&record_file,record_path(),"ab");
					if (record_file)
					{
						int t;
						
						t=w^score; 
						crypt_enc(&t);
						fwrite(&t,4,1,record_file);
						
						t=h^score; 
						crypt_enc(&t);
						fwrite(&t,4,1,record_file);
						
						twister_write(record_file);

						fclose(record_file);
					}

					level_modal = new LEVEL_MODAL(
						&global_screen,
						lives,startlives,
						&score,
						&level_time,
						conf_player.name,
						current_course->name,
						current_level,
						iSubLev, hitbin);
				}
				else
				{
					// game over
					delete level_modal;
					level_modal = 0;

					FILE* record_file = 0;
					fopen_s(&record_file,record_path(),"ab");
					if (record_file)
					{
						unsigned int chk[5] = 
						{
							twister_rand(),
							twister_rand(),
							crypt_chk(),
							twister_rand(),
							twister_rand()
						};

						fwrite(chk,1,15+(rand()%5),record_file);
						fclose(record_file);
					}

					// post recording to the server
					// delete recording file?
					post_hiscore();
					
					inter_modal = new GAMEOVER_MODAL(
						&global_screen,
						&score,
						current_level);
				}

				return 0;
			}

			// quit
			if (ret==-2)
			{
				// quit to menu, pause & show confirmation?
				// maybe not necessary as we are going to have continue thing!
				// ...

				// destroy game
				/*
				delete level_modal;
				level_modal = 0;
				*/

				return -2;
			}

			if (ret==-3)
			{
				// still playing
				return -1;
			}

			///////////////////////////
			// so ret is -1

			// level finished. 
			// prepare interscreen

			// calc hitacc from hitbin
			int hitacc = 0;
			for (int i=0; i<1024; i++)
			{
				unsigned char b = hitbin[i];
				while (b)
				{
					if (b&1)
						hitacc++;
					b >>= 1;
				}
			}

			// parse level data to find hitmax
			int hitmax = 0;
			for (int i=0; current_level->sprite[i]; i++)
			{
				char spr = current_level->sprite[i];
				switch (spr)
				{
					case 'U':
					case 'D':
					case 'B':
					case 'r':
					case 't':
					case 'c':
					case 'h':
					case 'b':
						hitmax++;
				}
			}

			delete level_modal;
			level_modal = 0;

			inter_modal = new INTER_MODAL(
				&global_screen,
				lives, startlives,
				&score,
				current_course->name,
				current_level,
				level_time,
				hitacc, hitmax);


			// increment level
			level_time = 0;
			hitacc = 0;
			startlives = lives;
			memset(hitbin,0,1024);

			iSubLev=0;
			current_level++;
			iLevel++;
			if (!current_level->height)
			{
				current_course++;
				iCourse++;

				// update progress in conf
				if (iCourse>conf_campaign.passed)
				{
					conf_campaign.passed = iCourse;
					SaveConf();
				}

				if (!current_course->level || (current_course->flags&0x1))
				{
					current_course = campaign + 0;
					iCourse=0;
					// RANDOM GENERATOR SURVIVAL MDOE ?
				}
				current_level = current_course->level + 0;
				iLevel=0;
			}

			return -1;
		}
		else
		if (inter_modal)
		{
			int ret = inter_modal->Run();

			w=s->w;
			h=s->h;

			if (!lives)
			{
				if (ret)
				{
					delete inter_modal;
					inter_modal = 0;
					// gameover->menu
					// either by esc or any key
					return -3;
				}
				return -1;
			}

			if (ret == -1)
			{
				// next level
				delete inter_modal;
				inter_modal = 0;

				FILE* record_file = 0;
				fopen_s(&record_file,record_path(),"ab");
				if (record_file)
				{

					int t;
					
					t=w^score; 
					crypt_enc(&t);
					fwrite(&t,4,1,record_file);
					
					t=h^score; 
					crypt_enc(&t);
					fwrite(&t,4,1,record_file);
					
					twister_write(record_file);

					fclose(record_file);
				}

				level_modal = new LEVEL_MODAL(
					&global_screen,
					lives,startlives,
					&score,
					&level_time,
					conf_player.name,
					current_course->name,
					current_level,
					iSubLev, hitbin);
				return -1;
			}
			
			if (ret == -2)
			{
				// quit to menu?

				/*
				delete inter_modal;
				inter_modal = 0;
				*/

				return -2;
			}
		}

		return -1;
	}
};

struct MENU_MODAL : MODAL
{
	MODAL* sub_modal; // currently null or campaign_modal
	MODAL* hold_modal;

	MENU_MODAL()
	{
		hold_modal = 0;
		sub_modal = 0;
	}

	virtual ~MENU_MODAL()
	{
		if (sub_modal)
			delete sub_modal;
		if (hold_modal)
			delete hold_modal;

		hold_modal = 0;
		sub_modal = 0;
		FreeMenu();
	}

	virtual int Run()
	{
		if (sub_modal)
		{
			// campaign / ... ?
			int ret = sub_modal->Run();

			if (ret == -3)
			{
				// quit to menu doesn't change current play pattern
				// ensures only we have full range loop
				PlayLoop(0,-1,0,29);				

				// permanent end
				if (hold_modal)
				{
					delete hold_modal;
					hold_modal = 0;
				}
				if (sub_modal)
				{
					delete sub_modal;
					sub_modal = 0;
				}

				return 0;
			}
			else
			if (ret == -2)
			{
				// temporal exit to menu
				// doesn't change mo3 loop at all !

				if (hold_modal)
				{
					delete hold_modal;
					hold_modal = 0;
				}

				hold_modal = sub_modal;
				sub_modal = 0;

				/*
				delete sub_modal;
				sub_modal = 0;
				*/

				return 0;
			}


			/*
			if (ret<0)
			{
				// back to menu (game over or user requested exit)
				sub_modal=0;
			}
			*/
		}
		else
		{
			int ret = RunMenu(&global_screen);

			if (ret == -3)
			{
				if (sub_modal)
					delete sub_modal;

				sub_modal = 0;

				if (hold_modal)
				{
					// same mo3 loop !
					// (not modified when temporarily entering menu during game)

					sub_modal = hold_modal;
					hold_modal = 0;
				}
				else
				{
					// new game will enter new loop after fade
					FadeOut(2000);

					sub_modal = new CAMPAIGN_MODAL(&global_screen,
						conf_campaign.course,
						conf_campaign.level >= 0 ? conf_campaign.level : 0);
				}
			}
		}

		return 0;
	}
};

MENU_MODAL menu_modal;

void ClearOnHold()
{
	if (menu_modal.hold_modal)
	{
		CAMPAIGN_MODAL* cm = (CAMPAIGN_MODAL*)menu_modal.hold_modal;
		delete cm;
		menu_modal.hold_modal = 0;
	}
}

// used by menu to sync with paused game
bool GameOnHold(int* course, int* level, int* sublevel, int* percent, int* score, int* lives)
{
	if (menu_modal.hold_modal)
	{
		CAMPAIGN_MODAL* cm = (CAMPAIGN_MODAL*)menu_modal.hold_modal;

		if (course)
			*course = cm->iCourse;
		if (level)
			*level  = cm->iLevel;
		if (score)
			*score  = cm->score;

		if (cm->level_modal)
		{
			LEVEL_MODAL* lm = (LEVEL_MODAL*)cm->level_modal;
			if (lives)
				*lives  = lm->lives; // this one is more fresh
			

			if (lm->t.check_passed+1 >= lm->t.check_points)
			{
				if (sublevel)
					*sublevel = lm->t.check_passed-1;
				if (percent)
					*percent = 100;
			}
			else
			{
				if (sublevel)
					*sublevel = lm->t.check_passed;

				int from=0;
				from = lm->t.check_point[lm->t.check_passed];
				if (from<0)
					from=0;

				int end = lm->t.check_point[lm->t.check_passed+1];

				if (percent)
					*percent  = MIN(100, 100*(lm->t.scroll-lm->t.w - from) / (end-from));
			}
		}
		else
		{
			if (lives)
				*lives  = cm->lives;

			// level is already incremented
			if (sublevel)
				*sublevel = 0; // means last, same as last check_passed

			if (percent)
				*percent = 0;  // means end

			/*
			*sublevel = -1; // means last, same as last check_passed
			*percent = 100;  // means end
			*/
		}

		return true;
	}

	return false;
}

struct INTRO_MODAL : MODAL
{
	int ret;

	SPRITE chassis;
	SPRITE fr_wheel;
	SPRITE bk_wheel;
	SPRITE ascii;
	SPRITE patrol;
	SPRITE bkgnd;
	SPRITE bkcut;

	SPRITE prompt;

	int x;
	int w;
	int h;

	unsigned long bt;
	unsigned long fade_tm;

	int terrain_pos;
	signed char fr_terrain[336];
	signed char bk_terrain[336];

	SCREEN* s;

	void Init(SCREEN* scr)
	{
		s = scr;
		w = s->w;
		h = s->h;

		x=-64;

		terrain_pos=0;

		for (int i=0; i<336; i++)
		{
			if ((i/16)%3==0)
				fr_terrain[i] = (signed char)(-1.7 * sin(3.131592*i/8));
			if ((i/16)%3==1)
				bk_terrain[i] = (signed char)(1.7 * sin(3.131592*(i+63)/8));
		}

		bt = get_time();
		fade_tm=0;
	}

	INTRO_MODAL() :
		chassis(&scene_chassis),
		fr_wheel(&scene_fr_wheel),
		bk_wheel(&scene_bk_wheel),
		ascii(&scene_ascii),
		patrol(&scene_patrol),
		bkgnd(&mountains),
		bkcut(&dunes),
		prompt("PRESS ANY KEY TO CONTINUE")

	{
		ret = 0;

		bkgnd.attrib_mask = 0x0F;
		bkcut.attrib_mask = 0x00;
		bkcut.attrib_over = 0x01;
		prompt.attrib_mask=0;
	}

	virtual int Run()
	{
		const static char ascii_str[] = {1,2,3,4,4};
		const static int ascii_krn[] =  {0,0,0,1,2};
		const static int ascii_frm[] =  {0,10,5,20,0};

		const static int bk_wheel_x[2]={20,38};
		const static int fr_wheel_x[3]={3,11,26};
		const static int wheel_y = 8;
		const static int suspension[4]={4,8,35,10};

		if (s->color)
			s->tcolor = 0x07;

		while(1)
		{
			unsigned long ct = get_time();

			int fr = (ct-bt)/15;
			int wfr = (ct-bt)/32;

			int ffr = (ct-fade_tm)/10;
			if (!fade_tm)
				ffr=0;

			if (ffr>100)
			{
				modal = &menu_modal;
				break;
			}

			int dw = 0;
			int dh = 0;
			get_terminal_wh(&dw,&dh);

			int nw = dw;
			int nh = dh;

		
			if (nw>160)
				nw=160;
			if (nw<80)
				nw=80;
			if (nh>50)
				nh=50;
			if (nh<25)
				nh=25;

			if (w!=nw || h!=nh)
			{
				s->Resize(nw,nh);

				w=nw;
				h=nh;
			}

			s->Clear();

			int dx = terrain_pos-chassis.width;

			int y = 3+ (s->h - chassis.height - fr_wheel.height/2) / 2;

			int mx = (s->w - bkgnd.width)/2;
			// int my = MAX(0,MIN(terrain_pos/4-30,16));

			int mt = terrain_pos*2-60;
			mt = MAX(0,mt);
			mt = MIN(43,mt);

			int sfr = fr;
			int scroll1 = (sfr/2)%160;
			int scroll2 = (sfr/4)%160;

			int my = (int)floorf(-1.0f+20.0f * sinf(3.141592f*(mt-0.5f)/64.0f) );
			int ca = MIN(fr,32);
			ca = (int)(32*(0.5f-0.5f*cosf(3.141592f*ca/32)));
			int cy = (s->h*(32-ca) + (y + patrol.height-10)*ca + 16) / 32;

			int mh = bkgnd.height;// clamp to bottom of bkcut
			if ( y + patrol.height-my-ffr/4 + mh > cy-ffr/2 + bkcut.height)
				mh = cy-ffr/2 + bkcut.height - (y + patrol.height-my-ffr/4);

			if (mh>0 && mt>=10)
			{
				bkgnd.Paint(s,mx-scroll2,y + patrol.height-my-ffr/4,0,0,-1,mh/*my*/);
				bkgnd.Paint(s,mx-scroll2+160,y + patrol.height-my-ffr/4,0,0,-1,mh/*my*/);
			}

			bkcut.Paint(s,mx-scroll1,cy-ffr/2,0,0,-1,-1);
			bkcut.Paint(s,mx-scroll1+160,cy-ffr/2,0,0,-1,-1);

			int left = (s->w - patrol.width)/2;
			int right = dx+x+4;
			if ( right>left )
			{
				patrol.Paint(s,left, y+3 + ffr, 0,0, right-left, -1, 0, false);
			}

			bk_wheel.SetFrame(wfr+0);
			bk_wheel.Paint(s,dx + x+bk_wheel_x[0],y+wheel_y + bk_terrain[(terrain_pos+bk_wheel_x[0])%256],0,0);
			bk_wheel.SetFrame(wfr+2);
			bk_wheel.Paint(s,dx + x+bk_wheel_x[1],y+wheel_y + bk_terrain[(terrain_pos+bk_wheel_x[1])%256],0,0);

			for (int sy = y+suspension[1]; sy<y+suspension[3]; sy++)
			{
				if (sy>=0 && sy<s->h)
				for (int sx = dx+x+suspension[0]; sx<dx+x+suspension[2]; sx++)
				{
					if (sx>=0 && sx<s->w)
						s->buf[(s->w+1)*sy+sx]=' ';
				}
			}

			chassis.Paint(s,dx + x,y,0,0);

			fr_wheel.SetFrame(wfr+1);
			fr_wheel.Paint(s,dx + x+fr_wheel_x[0],y+wheel_y + fr_terrain[(terrain_pos+fr_wheel_x[0])%256],0,0);
			fr_wheel.SetFrame(wfr+3);
			fr_wheel.Paint(s,dx + x+fr_wheel_x[1],y+wheel_y + fr_terrain[(terrain_pos+fr_wheel_x[1])%256],0,0);
			fr_wheel.SetFrame(wfr+5);
			fr_wheel.Paint(s,dx + x+fr_wheel_x[2],y+wheel_y + fr_terrain[(terrain_pos+fr_wheel_x[2])%256],0,0);

			int half = (s->w + chassis.width - x) + 50;
			int afr = (fr-half)/30;
			afr = MAX(-1,afr);
			afr = MIN(5,afr);

			int ax = (s->w - (5*10-ascii_krn[4]))/2;
		
			int i=0;
			for (; i<afr; i++)
			{
				if (i==afr-1 && (fr-half)-afr*30<ascii_frm[i])
					break;
				ascii.SetFrame(ascii_str[i]);
				ascii.Paint(s,ax+i*10 - ascii_krn[i], -ffr + y - ascii.height +1,0,0, -1,-1, 0,false);
			}

			if (afr<0)
				i=afr;
			if (i<5 && i>=0 && (fr&7)<4)
			{
				ascii.SetFrame(0);
				ascii.Paint(s,ax+i*10 - ascii_krn[i], -ffr +y - ascii.height +1,0,0, -1,-1, 0,false);
			}

			if (fr>half+150+100 && !fade_tm)
			{
				if ((fr&63)<32)
					prompt.attrib_over=0x0B;
				else
					prompt.attrib_over=0x03;

				if (s->color || (fr&63)<32)
					prompt.Paint(s, (s->w-prompt.width)/2 , y+chassis.height + (s->h - (y+chassis.height) + 2)/2, 0,0);
			}

			s->Write(dw,dh,0,0,-1,-1);

			terrain_pos = fr;
			if (terrain_pos > s->w + chassis.width - 2*x)
				terrain_pos = s->w + chassis.width - 2*x;

			int _ret = InterScreenInput();

			if (_ret == -2)
			{
				modal = &menu_modal;
				break;
			}

			if (_ret && !fade_tm /**/ && fr>half+150+100 /**/)
			{
				fade_tm=get_time();
			}

			break;
		}

		if (s->color)
			s->tcolor = cl_transp;

		return 0;
	}
};

INTRO_MODAL intro_modal;

/*
#define FREAD(buf,siz,cnt,fil) if ( fread(buf,siz,cnt,fil) != cnt ) exit(-1)
*/

int FREAD(void* buf, int siz, int cnt, FILE* fil)
{
	if ( fread(buf,siz,cnt,fil) != cnt ) 
		exit(-1);
	return cnt;
}


int validate_score(const char* path, int* avatar, char* name)
{
	// record_path()
	FILE* record_file = 0;
	fopen_s(&record_file,path,"rb");
	if (!record_file)
		exit(-1);

	int iCourse;
	int iLevel;
	int iSubLev;
	int lives;
	int startlives;
	int w;
	int h;

	int score=0;
	int level_time=0;

	int n[4];
	int a=0;

	const COURSE* current_course=0;
	const LEVEL* current_level=0;
	char hitbin[1024];
	memset(hitbin,0,1024);

	if (record_file)
	{
		// in case of file truncation
		// simply reject by exit(0)

		// read header
		unsigned char sign[8];
		FREAD(sign,4,1,record_file);
		if (memcmp(sign,"REC0",4)!=0)
			exit(-1);

		FREAD(&iCourse,4,1,record_file);
		FREAD(&iLevel,4,1,record_file);
		FREAD(&iSubLev,4,1,record_file);
		FREAD(&lives,4,1,record_file);
		if (lives!=3)
			exit(-1);

		startlives = lives;

		// this part must be written before each (re)spawn!
		FREAD(&w,4,1,record_file);
		if (w<80 || w>160)
			exit(-1);
		FREAD(&h,4,1,record_file);
		if (h<25 || h>50)
			exit(-1);
		twister_read(record_file);

		crypt_ini();

		FREAD(n,1,16,record_file);
		crypt_dec(n+0);
		crypt_dec(n+1);
		crypt_dec(n+2);
		crypt_dec(n+3);
		n[0]^=score;
		n[1]^=score;
		n[2]^=score;
		n[3]^=score;

		FREAD(&a,1,4,record_file);
		crypt_dec(&a);
		a^=score;

		if (name)
			memcpy(name,n,16);
		if (avatar)
			*avatar=a;
	}

	current_course = campaign + iCourse;
	current_level = current_course->level + iLevel;

	global_screen.Resize(w,h);

	LEVEL_MODAL* level_modal = new LEVEL_MODAL(
		&global_screen,
		lives,startlives,
		&score,
		&level_time,
		name,
		current_course->name,
		current_level,
		iSubLev, hitbin,
		record_file); // <<<<<<<<<<< !!!!!!!!!!!!!!!!!!!!!!

	bool export_movie = false; // true;
	int export_ticks_per_frame = 2; // 30fps?
	int export_tick = 0;
	int export_frame = 0;

	while (1)
	{
		if (export_movie)
		{
			if (export_tick == export_ticks_per_frame)
			{
				char name[1024];
				sprintf_s(name, 1024, "export_%05d",export_frame);
				screen_shot(&global_screen, name);
				export_frame++;
				export_tick = 0;
			}
			export_tick++;
		}
		int ret = level_modal->Run();
		if (ret>=0)
		{
			// player died in returned sublev
			lives--;

			delete level_modal;

			if (lives)
			{
				iSubLev = ret;

				// in case of file truncation
				// simply reject by exit(0)

				FREAD(&w,4,1,record_file);
				crypt_dec(&w);
				w^=score;
				if (w<80 || w>160)
					exit(-1);
				FREAD(&h,4,1,record_file);
				crypt_dec(&h);
				h^=score;
				if (h<25 || h>50)
					exit(-1);
				twister_read(record_file);

				global_screen.Resize(w,h);

				level_modal = new LEVEL_MODAL(
					&global_screen,
					lives,startlives,
					&score,
					&level_time,
					name,
					current_course->name,
					current_level,
					iSubLev, hitbin,
					record_file); // <<<<<<<<<<< !!!!!!!!!!!!!!!!!!!!!!

				continue;
			}
			else
			{
				unsigned int tail[3];
				FREAD(tail,1,12,record_file);

				// DONE!
				fclose(record_file);

				if (tail[2] != crypt_chk())
					exit(-1);

				return score;
			}
		}

		if (ret==-2)
		{
			// quit, should not happen
			break;
		}

		if (ret==-3)
		{
			// still playing
			continue;
		}

		// level finished
		// prepare for next level / course

		// calc hitacc from hitbin
		int hitacc = 0;
		for (int i=0; i<1024; i++)
		{
			unsigned char b = hitbin[i];
			while (b)
			{
				if (b&1)
					hitacc++;
				b >>= 1;
			}
		}

		// parse level data to find hitmax
		int hitmax = 0;
		for (int i=0; current_level->sprite[i]; i++)
		{
			char spr = current_level->sprite[i];
			switch (spr)
			{
				case 'U':
				case 'D':
				case 'B':
				case 'r':
				case 't':
				case 'c':
				case 'h':
				case 'b':
					hitmax++;
			}
		}

		delete level_modal;

		// add bonuses!!!

		if (lives>1)
			score += 1000 * (lives-1);

		if (level_time<current_level->time_limit)
			score += (current_level->time_limit - level_time)/10;

		score += 100*100*hitacc / hitmax;

		// increment level
		startlives = lives;
		level_time = 0;
		memset(hitbin,0,1024);

		iSubLev=0;
		current_level++;
		iLevel++;
		if (!current_level->height)
		{
			current_course++;
			iCourse++;
			if (!current_course->level || (current_course->flags&0x1))
			{
				current_course = campaign + 0;
				iCourse=0;
				// RANDOM GENERATOR SURVIVAL MDOE ?
			}
			current_level = current_course->level + 0;
			iLevel=0;
		}


		FREAD(&w,4,1,record_file);
		crypt_dec(&w);
		w^=score;
		if (w<80 || w>160)
			exit(-1);
		FREAD(&h,4,1,record_file);
		crypt_dec(&h);
		h^=score;
		if (h<25 || h>50)
			exit(-1);
		twister_read(record_file);

		global_screen.Resize(w,h);

		level_modal = new LEVEL_MODAL(
			&global_screen,
			lives,startlives,
			&score,
			&level_time,
			name,
			current_course->name,
			current_level,
			iSubLev, hitbin,
			record_file); // <<<<<<<<<<< !!!!!!!!!!!!!!!!!!!!!!
	}

	delete level_modal;

	fclose(record_file);
	
	return -1;
}

/*
unsigned char font_14_psf[]=
{
	// PSF1
	0x36,0x04,
	0x02,0x0E,  // hastbl = 02, height = 0E

	// BITMAPS
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x00,0x6C,0xEE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,
	0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x10,0x38,0x10,0x6C,0xEE,0x6C,0x10,0x38,0x00,0x00,0x00,
	0x00,0x00,0x10,0x38,0x7C,0x7C,0xFE,0xFE,0x6C,0x10,0x38,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,
	0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,
	0x00,0x00,0x00,0x00,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,
	0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0x99,0x99,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,
	0x00,0x00,0x1E,0x0E,0x1E,0x36,0x78,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,
	0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,
	0x00,0x00,0x1E,0x1A,0x1E,0x18,0x18,0x18,0x78,0xF8,0x70,0x00,0x00,0x00,
	0x00,0x3E,0x36,0x3E,0x36,0x36,0x76,0xF6,0x66,0x0E,0x1E,0x0C,0x00,0x00,
	0x00,0x18,0xDB,0x7E,0x3C,0x66,0x66,0x3C,0x7E,0xDB,0x18,0x00,0x00,0x00,
	0x00,0x00,0x80,0xE0,0xF0,0xFC,0xFE,0xFC,0xF0,0xE0,0x80,0x00,0x00,0x00,
	0x00,0x00,0x02,0x0E,0x3E,0x7E,0xFE,0x7E,0x3E,0x0E,0x02,0x00,0x00,0x00,
	0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,
	0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,
	0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,
	0x00,0x7C,0xC6,0xC6,0x60,0x7C,0xF6,0xDE,0x7C,0x0C,0xC6,0xC6,0x7C,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0x00,0x00,0x00,
	0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,
	0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x0C,0x0E,0xFF,0x0E,0x0C,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x30,0x70,0xFE,0x70,0x30,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x24,0x66,0xFF,0x66,0x24,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x10,0x38,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,
	0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,
	0x00,0x36,0x36,0x36,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,
	0x00,0x18,0x18,0x7C,0xC6,0xC0,0x78,0x3C,0x06,0xC6,0x7C,0x18,0x18,0x00,
	0x00,0x06,0x06,0xCC,0xCC,0x18,0x18,0x30,0x30,0x66,0x66,0xC0,0xC0,0x00,
	0x00,0x00,0x38,0x6C,0x38,0x38,0x76,0xF6,0xCE,0xCC,0x76,0x00,0x00,0x00,
	0x00,0x0C,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,
	0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,
	0x00,0x00,0x00,0x00,0x6C,0x38,0xFE,0x38,0x6C,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x0C,0x18,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,
	0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x60,0xC0,0xC0,0x00,
	0x00,0x00,0x7C,0xC6,0xCE,0xDE,0xF6,0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x18,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x00,0x00,0x00,
	0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00,0x0C,0x0C,0x0C,0x18,0x00,
	0x00,0x00,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,
	0x00,0x00,0x3C,0x66,0xC0,0xC0,0xC0,0xC0,0xC0,0x66,0x3C,0x00,0x00,0x00,
	0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,
	0x00,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,
	0x00,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0xC0,0xC0,0xCE,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0x70,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xCC,0xD8,0xF0,0xF0,0xD8,0xCC,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xC6,0xEE,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xC6,0xE6,0xE6,0xF6,0xDE,0xCE,0xCE,0xC6,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0x7C,0x06,0x00,0x00,
	0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC0,0x60,0x38,0x0C,0x06,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0xC6,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0x00,0xFE,0xC6,0x8C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,
	0x00,0x00,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7C,0x00,0x00,0x00,
	0x00,0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x18,0x0C,0x0C,0x06,0x06,0x00,
	0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C,0x00,0x00,0x00,
	0x00,0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,
	0x00,0x18,0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x00,0xE0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0xCC,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x1C,0x36,0x30,0x30,0xFC,0x30,0x30,0x30,0x78,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x76,0xCE,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00,
	0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,
	0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,
	0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,
	0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
	0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,
	0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x70,0x1C,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x30,0x30,0x30,0xFC,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xCE,0x76,0x06,0xC6,0x7C,0x00,
	0x00,0x00,0x00,0x00,0x00,0xFE,0x8C,0x18,0x30,0x62,0xFE,0x00,0x00,0x00,
	0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,
	0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
	0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x70,0x00,0x00,0x00,
	0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x6C,0x6C,0xFE,0x00,0x00,0x00,0x00,
	0x00,0x00,0x3C,0x66,0xC0,0xC0,0xC0,0xC6,0x66,0x3C,0x18,0xCC,0x38,0x00,
	0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xCE,0x76,0x00,0x00,0x00,
	0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x30,0x78,0xCC,0x00,0x78,0x0C,0x7C,0xCC,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC6,0x7C,0x18,0x6C,0x38,0x00,
	0x00,0x30,0x78,0xCC,0x00,0x7C,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0xCC,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x30,0x18,0x0C,0x00,0x7C,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0xC6,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,
	0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00,0x00,0x00,
	0x0C,0x18,0x30,0x00,0xFE,0x60,0x60,0x7C,0x60,0x60,0xFE,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x66,0xDB,0x1B,0x7F,0xD8,0xDF,0x76,0x00,0x00,0x00,
	0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xFE,0xD8,0xD8,0xD8,0xDE,0x00,0x00,0x00,
	0x00,0x30,0x78,0xCC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x30,0x18,0x0C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x30,0x78,0xCC,0x00,0xC6,0xC6,0xC6,0xC6,0xCE,0x76,0x00,0x00,0x00,
	0x00,0x60,0x30,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xCE,0x76,0x00,0x00,0x00,
	0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xCE,0x76,0x06,0xC6,0x7C,0x00,
	0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,
	0x00,0x00,0x38,0x6C,0x60,0x60,0xF0,0x60,0x66,0xF6,0x6C,0x00,0x00,0x00,
	0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x3C,0x18,0x18,0x00,0x00,0x00,
	0x00,0xFC,0xC6,0xFC,0xC0,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,
	0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,
	0x00,0x0C,0x18,0x30,0x00,0x78,0x0C,0x7C,0xCC,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,
	0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x00,0x76,0xDC,0x00,0xBC,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,
	0x00,0x76,0xDC,0x00,0xC6,0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0x00,0x00,0x00,
	0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC6,0xC6,0x7C,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x06,0x06,0x00,0x00,0x00,0x00,
	0x00,0x60,0x62,0x66,0x6C,0x18,0x30,0x60,0xDC,0x36,0x0C,0x18,0x3E,0x00,
	0x00,0x60,0x62,0x66,0x6C,0x18,0x36,0x6E,0xDE,0x36,0x7E,0x06,0x06,0x00,
	0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,
	0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
	0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
	0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,
	0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,
	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,
	0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,
	0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,
	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
	0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,
	0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
	0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,
	0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,
	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,
	0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,
	0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,
	0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,
	0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
	0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,
	0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,
	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,
	0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,
	0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,
	0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,
	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
	0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
	0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,
	0x00,0x00,0x00,0x78,0xCC,0xD8,0xFC,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,
	0x00,0x00,0xFE,0x66,0x62,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,
	0x00,0x00,0xFE,0xC6,0x62,0x30,0x18,0x30,0x62,0xC6,0xFE,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x80,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x00,0x00,0x00,
	0x00,0x00,0xFE,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0xFE,0x00,0x00,0x00,
	0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,
	0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,
	0x00,0x00,0x3E,0x60,0x30,0x3C,0x66,0xC6,0xC6,0xCC,0x78,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x06,0x0C,0x7C,0xDE,0xF6,0xE6,0x7C,0x60,0xC0,0x00,0x00,0x00,
	0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,
	0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,
	0x00,0x00,0x00,0x0C,0x1E,0x1A,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
	0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x58,0x78,0x30,0x00,0x00,
	0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,
	0x00,0x00,0x78,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0xD8,0x78,0x38,0x18,0x00,0x00,
	0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x70,0xD8,0x30,0x60,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

	// TAB
	0x00,0x00,0xFF,0xFF,0x3A,0x26,0xFF,0xFF,0x3B,0x26,0xFF,0xFF,0x65,0x26,0xFF,0xFF,0x66,0x26,0xFF,0xFF,0x63,0x26,0xFF,0xFF,0x60,0x26,0xFF,0xFF,0x22,0x20,0xFF,0xFF,
	0xD8,0x25,0xFF,0xFF,0xCB,0x25,0xFF,0xFF,0xD9,0x25,0xFF,0xFF,0x42,0x26,0xFF,0xFF,0x40,0x26,0xFF,0xFF,0x6A,0x26,0xFF,0xFF,0x6B,0x26,0xFF,0xFF,0x3C,0x26,0xFF,0xFF,
	0xBA,0x25,0xFF,0xFF,0xC4,0x25,0xFF,0xFF,0x95,0x21,0xFF,0xFF,0x3C,0x20,0xFF,0xFF,0xB6,0x00,0xFF,0xFF,0xA7,0x00,0xFF,0xFF,0xAC,0x25,0xFF,0xFF,0xA8,0x21,0xFF,0xFF,
	0x91,0x21,0xFF,0xFF,0x93,0x21,0xFF,0xFF,0x92,0x21,0xFF,0xFF,0x90,0x21,0xFF,0xFF,0x1F,0x22,0xFF,0xFF,0x94,0x21,0xFF,0xFF,0xB2,0x25,0xFF,0xFF,0xBC,0x25,0xFF,0xFF,
	0x20,0x00,0xFF,0xFF,0x21,0x00,0xFF,0xFF,0x22,0x00,0xFF,0xFF,0x23,0x00,0xFF,0xFF,0x24,0x00,0xFF,0xFF,0x25,0x00,0xFF,0xFF,0x26,0x00,0xFF,0xFF,0x27,0x00,0xFF,0xFF,
	0x28,0x00,0xFF,0xFF,0x29,0x00,0xFF,0xFF,0x2A,0x00,0xFF,0xFF,0x2B,0x00,0xFF,0xFF,0x2C,0x00,0xFF,0xFF,0x2D,0x00,0xFF,0xFF,0x2E,0x00,0xFF,0xFF,0x2F,0x00,0xFF,0xFF,
	0x30,0x00,0xFF,0xFF,0x31,0x00,0xFF,0xFF,0x32,0x00,0xFF,0xFF,0x33,0x00,0xFF,0xFF,0x34,0x00,0xFF,0xFF,0x35,0x00,0xFF,0xFF,0x36,0x00,0xFF,0xFF,0x37,0x00,0xFF,0xFF,
	0x38,0x00,0xFF,0xFF,0x39,0x00,0xFF,0xFF,0x3A,0x00,0xFF,0xFF,0x3B,0x00,0xFF,0xFF,0x3C,0x00,0xFF,0xFF,0x3D,0x00,0xFF,0xFF,0x3E,0x00,0xFF,0xFF,0x3F,0x00,0xFF,0xFF,
	0x40,0x00,0xFF,0xFF,0x41,0x00,0xFF,0xFF,0x42,0x00,0xFF,0xFF,0x43,0x00,0xFF,0xFF,0x44,0x00,0xFF,0xFF,0x45,0x00,0xFF,0xFF,0x46,0x00,0xFF,0xFF,0x47,0x00,0xFF,0xFF,
	0x48,0x00,0xFF,0xFF,0x49,0x00,0xFF,0xFF,0x4A,0x00,0xFF,0xFF,0x4B,0x00,0xFF,0xFF,0x4C,0x00,0xFF,0xFF,0x4D,0x00,0xFF,0xFF,0x4E,0x00,0xFF,0xFF,0x4F,0x00,0xFF,0xFF,
	0x50,0x00,0xFF,0xFF,0x51,0x00,0xFF,0xFF,0x52,0x00,0xFF,0xFF,0x53,0x00,0xFF,0xFF,0x54,0x00,0xFF,0xFF,0x55,0x00,0xFF,0xFF,0x56,0x00,0xFF,0xFF,0x57,0x00,0xFF,0xFF,
	0x58,0x00,0xFF,0xFF,0x59,0x00,0xFF,0xFF,0x5A,0x00,0xFF,0xFF,0x5B,0x00,0xFF,0xFF,0x5C,0x00,0xFF,0xFF,0x5D,0x00,0xFF,0xFF,0x5E,0x00,0xFF,0xFF,0x5F,0x00,0xFF,0xFF,
	0x60,0x00,0xFF,0xFF,0x61,0x00,0xFF,0xFF,0x62,0x00,0xFF,0xFF,0x63,0x00,0xFF,0xFF,0x64,0x00,0xFF,0xFF,0x65,0x00,0xFF,0xFF,0x66,0x00,0xFF,0xFF,0x67,0x00,0xFF,0xFF,
	0x68,0x00,0xFF,0xFF,0x69,0x00,0xFF,0xFF,0x6A,0x00,0xFF,0xFF,0x6B,0x00,0xFF,0xFF,0x6C,0x00,0xFF,0xFF,0x6D,0x00,0xFF,0xFF,0x6E,0x00,0xFF,0xFF,0x6F,0x00,0xFF,0xFF,
	0x70,0x00,0xFF,0xFF,0x71,0x00,0xFF,0xFF,0x72,0x00,0xFF,0xFF,0x73,0x00,0xFF,0xFF,0x74,0x00,0xFF,0xFF,0x75,0x00,0xFF,0xFF,0x76,0x00,0xFF,0xFF,0x77,0x00,0xFF,0xFF,
	0x78,0x00,0xFF,0xFF,0x79,0x00,0xFF,0xFF,0x7A,0x00,0xFF,0xFF,0x7B,0x00,0xFF,0xFF,0x7C,0x00,0xFF,0xFF,0x7D,0x00,0xFF,0xFF,0x7E,0x00,0xFF,0xFF,0x02,0x23,0xFF,0xFF,
	0xC7,0x00,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xE9,0x00,0xFF,0xFF,0xE2,0x00,0xFF,0xFF,0xE4,0x00,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xE5,0x00,0xFF,0xFF,0xE7,0x00,0xFF,0xFF,
	0xEA,0x00,0xFF,0xFF,0xEB,0x00,0xFF,0xFF,0xE8,0x00,0xFF,0xFF,0xEF,0x00,0xFF,0xFF,0xEE,0x00,0xFF,0xFF,0xEC,0x00,0xFF,0xFF,0xC4,0x00,0xFF,0xFF,0xC5,0x00,0xFF,0xFF,
	0xC9,0x00,0xFF,0xFF,0xE6,0x00,0xFF,0xFF,0xC6,0x00,0xFF,0xFF,0xF4,0x00,0xFF,0xFF,0xF6,0x00,0xFF,0xFF,0xF2,0x00,0xFF,0xFF,0xFB,0x00,0xFF,0xFF,0xF9,0x00,0xFF,0xFF,
	0xFF,0x00,0xFF,0xFF,0xD6,0x00,0xFF,0xFF,0xDC,0x00,0xFF,0xFF,0xA2,0x00,0xFF,0xFF,0xA3,0x00,0xFF,0xFF,0xA5,0x00,0xFF,0xFF,0xA7,0x20,0xFF,0xFF,0x92,0x01,0xFF,0xFF,
	0xE1,0x00,0xFF,0xFF,0xED,0x00,0xFF,0xFF,0xF3,0x00,0xFF,0xFF,0xFA,0x00,0xFF,0xFF,0xF1,0x00,0xFF,0xFF,0xD1,0x00,0xFF,0xFF,0xAA,0x00,0xFF,0xFF,0xBA,0x00,0xFF,0xFF,
	0xBF,0x00,0xFF,0xFF,0x10,0x23,0xFF,0xFF,0xAC,0x00,0xFF,0xFF,0xBD,0x00,0xFF,0xFF,0xBC,0x00,0xFF,0xFF,0xA1,0x00,0xFF,0xFF,0xAB,0x00,0xFF,0xFF,0xBB,0x00,0xFF,0xFF,
	0x91,0x25,0xFF,0xFF,0x92,0x25,0xFF,0xFF,0x93,0x25,0xFF,0xFF,0x02,0x25,0xFF,0xFF,0x24,0x25,0xFF,0xFF,0x61,0x25,0xFF,0xFF,0x62,0x25,0xFF,0xFF,0x56,0x25,0xFF,0xFF,
	0x55,0x25,0xFF,0xFF,0x63,0x25,0xFF,0xFF,0x51,0x25,0xFF,0xFF,0x57,0x25,0xFF,0xFF,0x5D,0x25,0xFF,0xFF,0x5C,0x25,0xFF,0xFF,0x5B,0x25,0xFF,0xFF,0x10,0x25,0xFF,0xFF,
	0x14,0x25,0xFF,0xFF,0x34,0x25,0xFF,0xFF,0x2C,0x25,0xFF,0xFF,0x1C,0x25,0xFF,0xFF,0x00,0x25,0xFF,0xFF,0x3C,0x25,0xFF,0xFF,0x5E,0x25,0xFF,0xFF,0x5F,0x25,0xFF,0xFF,
	0x5A,0x25,0xFF,0xFF,0x54,0x25,0xFF,0xFF,0x69,0x25,0xFF,0xFF,0x66,0x25,0xFF,0xFF,0x60,0x25,0xFF,0xFF,0x50,0x25,0xFF,0xFF,0x6C,0x25,0xFF,0xFF,0x67,0x25,0xFF,0xFF,
	0x68,0x25,0xFF,0xFF,0x64,0x25,0xFF,0xFF,0x65,0x25,0xFF,0xFF,0x59,0x25,0xFF,0xFF,0x58,0x25,0xFF,0xFF,0x52,0x25,0xFF,0xFF,0x53,0x25,0xFF,0xFF,0x6B,0x25,0xFF,0xFF,
	0x6A,0x25,0xFF,0xFF,0x18,0x25,0xFF,0xFF,0x0C,0x25,0xFF,0xFF,0x88,0x25,0xFF,0xFF,0x84,0x25,0xFF,0xFF,0x8C,0x25,0xFF,0xFF,0x90,0x25,0xFF,0xFF,0x80,0x25,0xFF,0xFF,
	0xB1,0x03,0xFF,0xFF,0xDF,0x00,0xFF,0xFF,0x93,0x03,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xA3,0x03,0xFF,0xFF,0xC3,0x03,0xFF,0xFF,0xB5,0x00,0xFF,0xFF,0xC4,0x03,0xFF,0xFF,
	0xA6,0x03,0xFF,0xFF,0x98,0x03,0xFF,0xFF,0xA9,0x03,0xFF,0xFF,0xB4,0x03,0xFF,0xFF,0x1E,0x22,0xFF,0xFF,0xC6,0x03,0xFF,0xFF,0xB5,0x03,0xFF,0xFF,0x29,0x22,0xFF,0xFF,
	0x61,0x22,0xFF,0xFF,0xB1,0x00,0xFF,0xFF,0x65,0x22,0xFF,0xFF,0x64,0x22,0xFF,0xFF,0x20,0x23,0xFF,0xFF,0x21,0x23,0xFF,0xFF,0xF7,0x00,0xFF,0xFF,0x48,0x22,0xFF,0xFF,
	0xB0,0x00,0xFF,0xFF,0x19,0x22,0xFF,0xFF,0xB7,0x00,0xFF,0xFF,0x1A,0x22,0xFF,0xFF,0x7F,0x20,0xFF,0xFF,0xB2,0x00,0xFF,0xFF,0xA0,0x25,0xFF,0xFF,0xA0,0x00,0xFF,0xFF,
};
*/


int main(int argc, char* argv[])
{
	rec_show = 0;

	if (argc>1)
	{
		const char* path = argv[argc-1];

		int show = 0;
		if (argc>2)
			show = atoi(argv[argc-2]);

		if (show<0)
			show=0;
		if (show>2)
			show=2;

		rec_show = show;

		if (show>0)
		{
			//InitMenu();
			GamePreAlloc();

			int cols,rows;
			int prefix_args = terminal_init(0,0,&cols,&rows);
			atexit(terminal_done);
		}
		else
		{
			GamePreAlloc();
		}

		char name[16];
		int avatar;
		int score=validate_score(path,&avatar,name);
		printf("%d %d %s\n", score, avatar, name);
		return 0;
	}


	//MakeTerrain("gen.txt",2500);

	InitMenu();
	GamePreAlloc();

	get_hiscore(0,"");

	atexit(terminal_done);

	init_sound();

	int cols,rows;
	int prefix_args = terminal_init(0,0,&cols,&rows);

	modal = &intro_modal;

	intro_modal.Init(&global_screen);

	terminal_loop();

	return 0;
}


bool make_screen_shot = false;

bool read_input( CON_INPUT* ir, int n, int* r)
{
	int rr=0;
	bool ret = spec_read_input(ir,n,&rr);
	if (r)
		*r=rr;

	if (ret)
	{
		for (int i=0; i<rr; i++)
		{
			if (ir[i].EventType == CON_INPUT_KBD)
			{
				if (ir[i].Event.KeyEvent.bKeyDown && ir[i].Event.KeyEvent.uChar.AsciiChar=='\t')
				{
					make_screen_shot = true;
					//screen_shot(&global_screen);
				}
			}
		}
	}

	return ret;
}

void SetColorMode(SCREEN* s, unsigned char cl)
{
	// free
	if (s->arr)
	{
		free_con_output(s);
		s->arr = 0;
	}

	if (s->buf)
	{
		int size = (s->w+1)*s->h;
		int oldsize = size;
		if (s->color)
			oldsize*=2;
		if (cl)
			size*=2;
		char* buf = new char[size];

		int cpysize = MIN(size,oldsize);
		memcpy(buf,s->buf,cpysize);

		delete [] s->buf;
		s->buf = buf;
		s->color=0;
		s->buf[(s->w+1)*s->h-1]=0;
		if (cl)
		{
			s->color = s->buf+(s->w+1)*s->h;
			memset(s->color, cl, (s->w+1)*s->h);
		}
	}

	s->tcolor = cl;
}

void SetColorMode(unsigned char cl)
{
	cl_transp = cl;
	SetColorMode(&global_screen,cl);

	if (menu_modal.hold_modal)
	{
		CAMPAIGN_MODAL* cm = (CAMPAIGN_MODAL*)menu_modal.hold_modal;

		if (cm->level_modal)
		{
			twister_switch(1);

			LEVEL_MODAL* lm = (LEVEL_MODAL*)cm->level_modal;

			SetColorMode(&lm->b,cl?cm->current_level->sky:0);
			lm->b.scroll -= lm->b.w;
			lm->b.Scroll(lm->b.w);

			SetColorMode(&lm->m,cl);
			lm->m.scroll-=lm->m.w;
			lm->m.Scroll(lm->m.w);

			SetColorMode(&lm->d,cl);
			lm->d.scroll-=lm->d.w;
			lm->d.Scroll(lm->d.w);

			SetColorMode(&lm->t,cl);
			if (cl)
			{
				for (int y=0,i=0; y<lm->t.h; y++,i++)
				{
					for (int x=0; x<lm->t.w; x++,i++)
					{
						if (lm->t.buf[i] == ch_ground)
							lm->t.color[i] = cl_ground;
						else
							lm->t.color[i] = cl;
					}
				}
			}

			twister_switch(0);
		}
	}
}

