////////////////////////////////////////////////////////////////////
// MIDP wrapper
// (c) 2007 Peter "ph0x" Moraliyski (ppm@freemail.hu)
////////////////////////////////////////////////////////////////////

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

#include "SDL.h"
#include "SDL_image.h" 
#include "SDL_audio.h" 
#include "SDL_config.h" 

#include  "common.h"

extern int _getticks();
extern void _repaint();
extern void _servicerepaints();
extern void _sleep(int n);
extern void _quit(int rc);
extern void _playmusic();
extern void _stopmusic();
extern void _drawimage(SDL_Surface &img, int x, int y, int anc, SDL_Surface *screen); //fixme
extern void _drawline(int x0, int y0, int x1, int y1, int col, SDL_Surface *screen);
extern void _setclip(int x, int y, int w, int h, SDL_Surface *screen);
extern void _fillrect(int x0, int y0, int x1, int y1, int col, SDL_Surface *screen);
extern void _fillArc(int x, int y, int w, int h, int af, int at, int col, SDL_Surface *screen);
extern SDL_Surface *_createsurface(int w, int h);
extern void _processinput();
extern void _processinputend();


extern bool paused;
extern int popupidx;

extern int cnt;
/*extern touchPosition touch, oldtouch, newtouch, prevtouch;
extern bool touched, clicked, untouched;
extern int lasttouch;*/

String SINT(int n) { //fixme
	/*char s[16];
	memset(s, 0, sizeof(s));	
	sprintf(s, "%d", n);
	String ss= s;	
	return s;*/
	
	return NULL;
}

String substring(String s, int a, int b) {
	//return s.substr(a, b-a); //fixme
}

// System /////////////////////////////////////////////////////////////////////////////

int System::currentTimeMillis() {
	return _getticks();
} 
	
// System end /////////////////////////////////////////////////////////////////////////

// Math /////////////////////////////////////////////////////////////////////////////

int Math::abs(int n) {
	return n<0?-n:n;
}

int Math::max(int a, int b) {
	return a>b?a:b;
}

// Math end /////////////////////////////////////////////////////////////////////////

// Integer //////////////////////////////////////////////////////////////////////////

String Integer::toString(int n) {
	return NULL; //fixme
}

// Integer end //////////////////////////////////////////////////////////////////////

// Graphics /////////////////////////////////////////////////////////////////////////////

void Graphics::drawImage(Image img, int x, int y, int anc) { //fixme
	_drawimage(img.surf, x, y, anc, surf);
}

Graphics::Graphics() {
	LEFT= 4;
	RIGHT= 8;
	HCENTER= 1;
	TOP= 16;
	BOTTOM= 32;
	VCENTER= 2;		
}

void Graphics::setClip(int x, int y, int w, int h) {
	_setclip(x, y, w, h, surf);
}

void Graphics::clipRect(int x, int y, int w, int h) {}

void Graphics::setColor(int n) {
	b= (n>>0)&0xff;
	g= (n>>8)&0xff;
	r= (n>>16)&0xff;
	col= SDL_MapRGB(screen->format, r, g, b);
}	

void Graphics::setColor256(int n) {
	col= n; //SDL_MapRGB(screen->format, r, g, b);
}	

void Graphics::setColor(int r, int g, int b) {
	col= SDL_MapRGB(screen->format, r, g, b);
}	

void Graphics::drawString(String s, int x, int y, int anc) {
}

void Graphics::fillRoundRect(int x, int y, int w, int h, int a, int b) {
	_fillrect(x, y, w, h, col, surf);
}

void Graphics::drawRoundRect(int x, int y, int w, int h, int a, int b) {
	//wrk TEMP HACK!
	if (y < 0) {h+= y; y= 0;} 
	if (y + h >= SH) {	
		h-= y-SH;		
		if (h<0) h=0;		
	}

	drawLine(x, y, x+w, y);
	drawLine(x+w, y, x+w, y+h);
	drawLine(x+w, y+h, x, y+h);
	drawLine(x, y+h, x, y);
}

void Graphics::fillRect(int x, int y, int w, int h) {
	_fillrect(x, y, w, h, col, surf);
}

void Graphics::drawLine(int x1, int y1, int x2, int y2) {
	_drawline(x1, y1, x2, y2, col, surf);
}

void Graphics::drawRect(int x, int y, int w, int h) {
	drawLine(x, y, x+w, y);
	drawLine(x+w, y, x+w, y+h);
	drawLine(x+w, y+h, x, y+h);
	drawLine(x, y+h, x, y);
}

void Graphics::drawArc(int a0, int a1, int a2, int a3, int a4, int a5) {
}
	
void Graphics::fillArc(int x, int y, int a2, int a3, int a4, int a5) {
	//fillRect(x, y, a2, a3);
	_fillArc(x, y, a2, a3, a4, a5, col, surf);
}


// Graphics end /////////////////////////////////////////////////////////////////////////////

// Image /////////////////////////////////////////////////////////////////////////////

int Image::getWidth() {
	return surf.w;
}

int Image::getHeight() {
	return surf.h;
}

void Image::postcreate() {
	///if (surf == NULL) return; //fixme
	//w= surf->w;
	//h= surf->h;
	gg.surf= &surf;
	
}

/*void Image::createImage(String s) {
	surf= IMG_Load(s.c_str());
	postcreate();
}*/

void Image::createImage(const void *p) {
	if (p==NULL) return;
	
	IMG_Load(p, &surf);
	postcreate();
}

void Image::createImage(int w, int h) { //fixme
	/*surf= _createsurface(w, h);
	postcreate();*/
}

Graphics Image::getGraphics() {
	return gg;
}

// Image end /////////////////////////////////////////////////////////////////////////////

	Image noimg;	//wrk was in gamemidlet
	bool OFFSCREEN= false;
	Image Ioffscreen;
	int scene= SCENE_VOID;
	Graphics g2;
	int frame;
	int SLEEP= 30;
	
	byte keypressed[MY_KEY_SZAM];	//1 lenyomtak 2 epp le van nyomva
	byte key_was_pressed=3;
	byte key_is__pressed=1;

//-------------------SZOGFUGGVENYEK------------------------------------
	
//a CORE tombok, ezekbe szamolom elore a fugvenyekhez kello adatokat.. ezeket mar csak interpolalni kell, es a megfelelo tartomanyba tukrozve kapjuk majd a fuggveny erteket
	signed short *SINCORE, *ATANCORE, *ACOSCORE; //todo

	int sqrt(int i) {
		int x,newx;
		if (i<=0) return 0;
		x=i;
		while (true) {
			newx=(x+i/x)>>1;
			if(newx>=x) return newx;
			x=newx;
	}	}

//a szogfuggvenyek tombjeit kiszamito algoritmus.. a parametert kivettem, helyette vannak a konstansok efolott
	void szogf_core_kiszamito() {
		signed int i,j,k,hossz;
		signed int cj1,cj2;
		signed int szog_s=1<<SIN_DB_B,szog_at=1<<ATAN_DB_B,szog_ac=1<<ACOS_DB_B;	//a 2 hatvanyokat kiszamolom

//----sinus-cosinus-----------						//ez kell a masik ket szogfuggvenyhez!!!
		SINCORE = (signed short*)malloc((szog_s +1)*sizeof(signed short));
		memset(SINCORE, 0, (szog_s +1)*sizeof(signed short));
		
		signed int *sincore1= (signed int*)malloc((szog_s +1)*sizeof(signed int)); //a pontosabb szamitas erdekeben ideiglenesen kiszamolom a sin/cos-t 16 fixpontal [azaz ez mar nem fer bele short-ba]
		signed int *coscore1= (signed int*)malloc((szog_s +1)*sizeof(signed int)); //ezekbol szamolom majd a CORE tomboket.
		sincore1[0]=0;										//eloszor a sin/cos-t szamolom
		coscore1[0]=65536;
		sincore1[szog_s]=65536;
		coscore1[szog_s]=0;
		i=szog_s>>1;
		while (i>0) {										//eloszor szamolom 45 fokban, aztan 45*1/2 es 45*3/2-ed ponton, vagyis minden i alkalmaval egy ugy szinust szamolok meglevo 2 koze
			for (j=i;j<szog_s;j+=i+i){
				sincore1[j]=(sincore1[j+i]+sincore1[j-i]);	//kiszamolja a ket korpont atlagat majd lenormalizalja
				coscore1[j]=(coscore1[j+i]+coscore1[j-i]);
				sincore1[j]+=(sincore1[j]&2);				//de elotte meg kerekitjuk :)
				coscore1[j]+=(coscore1[j]&2);
				sincore1[j]>>=2;							//azert kell osztani hogy az sqrt-ben levo ertek biztosan ne csorduljon tul... [meg egy /2 jon az atlagolasbol]
				coscore1[j]>>=2;							//igy 0-32k kozott van
				hossz =sqrt(sincore1[j]*sincore1[j]+coscore1[j]*coscore1[j]);	//a parameter max erteke: 2*(23k^2)==2^30.. vagyis a 2szerese mar nem ferne bele :)
				sincore1[j]=(sincore1[j]<<16)/hossz;		//es a pont x,y koordinataja lesz a sin, cos erteke az aktualis szognek
				coscore1[j]=(coscore1[j]<<16)/hossz;		//a sin/cos max erteke ugyan lehetne 2^15-en de ezt csak a szelso pontokon veszi fel [amennyiben sincore tomb nem kib.nagy:)], szoval ez itt egy hajszal hijjan nem csordul tul.. :)
				k=sincore1[j]<<14;							//csak hogy ha legalabb 16 a fixpont akkor is mukodjon
				k=k>>(15+14-SIN_FIXP_B);					//eltoljuk a sinust hogy a sinus fixpontjanak megfelelo meretu legyen
				SINCORE[j]=(signed  short)((k+(k&1))>>1);			//kerekites
			}
			i/=2;											//feleakkora lepeskozzel megyek vegig a tombon
		}
		SINCORE[szog_s]=1<<SIN_FIXP_B;
//----arcustangens------------
		ATANCORE= (signed short*)malloc((szog_at +1)*sizeof(signed short));
		memset(ATANCORE, 0, (szog_at +1)*sizeof(signed short));
		j=0;
		for (i=0;i<=szog_at;i++) {							//arctan	0, es 1 kozotti tortek eseten szamolja a tangens inverzet [tan=sin/cos]
			while (szog_at*sincore1[j]<i*coscore1[j]) j++;	//megkeresi a legkozelebbi szoget aminek a sin/cos-ja nem kisebb mint az aktualis hanyados.. mert ha megvan akkor kb ez a szog lesz az inverz.
															//a sin/cos monoton, ezert eleg az elso ilyet megtalalni, es mivel az i/szog is monoton :) ezert eleg az elozo hanyadosnal megtalalttol keresni...
			if (j>0) {										//megnezzuk mennyire esik tavol ez a szog sin/cos-jatol, es az elozo sin/cos-jatol az aktualis hanyados, mert az alapjan sulyozott atlagot szamolunk
				k= ((sincore1[j]>>1)*(coscore1[j-1]>>1)-  (sincore1[j-1]>>1)*(coscore1[j]>>1));								//max 2^30 -t szamol reszeremenykent
				k=(((sincore1[j]>>1)*(coscore1[j-1]>>1)-(((coscore1[j-1]>>1)*(coscore1[j]>>1))>>ATAN_DB_B)*i)<<6)/(k>>10);	//mivel a tangens eleg pontatlan ezert a (k>>16)-bol 6-ot attetem a kitevobe igy meg nem csordul tul
				k=(j-1)*k+(65536-k)*(j);
			} else k=0;
			k>>=SIN_DB_B+15-ATAN_FIXP_B;					//mivel a kiszamolt szog fugg a sincore felbontasatol, ezert kell azt beleszamitani hogy mennyivel toljuk el, hogy az ertek az atan fixpontjanak megfeleljen
			ATANCORE[i]=(signed short)((k+(k&1))>>1);				//az elobb 1-el kevesebbnyit toltuk jobbra, mert meg kerekiteni akarunk.. [es kozben osztunk 2-vel]
		}
//----arcuscosinus------------
		ACOSCORE= (signed short*)malloc((szog_ac +1)*sizeof(signed short));
		memset(ACOSCORE, 0, (szog_ac +1)*sizeof(signed short));
		j=0;
		for (i=szog_ac;i>=0;i--) {							//arccos szamitasa	hasonloan szamitjuk mint az atan-t
			if (i>(szog_ac>>2)) {							//csak mivel tul nagy ertekek eseten az acos eleg pontattlan ezert pitagoresz alapjan kiszamitjuk a masik befogot.. ami ekkor kicsi lesz..ezzel szamitva asin-t pontosabb acost kapunk..
				k=sqrt((65536-i*i)<<14)<<1;					//0-64k.. kiszamoljuk a masik befogot.. az sqrt-ben max 2^30 lehet.. vagyis annal kicsit kissebb
				while (sincore1[j]<k) j++;					//elokeritjuk a ket legkozelebbi szoget.. ezek kozott lesz a megoldas amit e ket ertek sulyozott atlagaval szamolunk
				cj1=sincore1[j];							//beallitjuk a 2 erteket ami kozott van a keresett ertek
				cj2=sincore1[(j+SIN_DB_M)&(SIN_DB_M>>2)];	//j lehet 0... ilyenkor a -1. helyett a legutolsot adja.. ami nem baj, mert ekkor biztos hogy 0 sullyal fog szerepelni az.. :) ..de legalabb nem akad ki, es megsporoltam egy feltetelt
				hossz=k;									//es keresett.. vagyis az alapjan fugunk sulyzoni a szogeket hogy ez mennyire van tavol az elozo ket ponttol
			} else {										//kis ertekek eseten egyszerunek csak a cos-al szamolunk
				while (coscore1[j]>(i<<8)) j++;				//j==0-64		2^6 -> 2^14
				cj1=coscore1[j];
				cj2=coscore1[j-1];							//j mar biztos tobb mint 0 :))
				hossz=i<<8;
			}
			if (cj1!=hossz) {								//ha van mit atlagolni
				k=((cj2-hossz)<<16)/(cj2-cj1);					//akkor szamoljuk ki a sulyt
				k=k*(j)+(65536-k)*(j-1);						//es sulyozzuk be vele a j, es a j-1 szogeket
			} else k=j<<16;									//kulonben az aktualis szog lesz az acos.. 
			k>>=SIN_DB_B+15-ACOS_FIXP_B;					//itt is beleszamit az eltolasba hogy hany elemu a sinus tomb
			ACOSCORE[i]=(signed short)((k+(k&1))>>1);				//kerekites
		}
	//----------------------------
	}
//eredmenyek, hibak:
//sin:
//eredeti 0, 101, 201, 301, 401, 501, 601, 700, 799, 897, 995, 1092, 1189, 1285, 1380, 1474, 1567, 1660, 1751, 1842, 1931, 2019, 2106, 2191, 2276, 2359, 2440, 2520, 2598, 2675, 2751, 2824, 2896, 2967, 3035, 3102, 3166, 3229, 3290, 3349, 3406, 3461, 3513, 3564, 3612, 3659, 3703, 3745, 3784, 3822, 3857, 3889, 3920, 3948, 3973, 3996, 4017, 4036, 4052, 4065, 4076, 4085, 4091, 4095, 4096
//szamolt 0, 101, 201, 301, 401, 501, 601, 700, 799, 897, 995, 1092, 1189, 1285, 1380, 1474, 1567, 1660, 1751, 1842, 1931, 2019, 2106, 2191, 2276, 2359, 2440, 2520, 2599, 2675, 2751, 2824, 2896, 2967, 3035, 3102, 3166, 3229, 3290, 3349, 3406, 3461, 3513, 3564, 3612, 3659, 3703, 3745, 3784, 3822, 3857, 3889, 3920, 3948, 3973, 3997, 4017, 4036, 4052, 4065, 4076, 4085, 4091, 4095, 4096
//vagyis mar csak 2 helyen ter el -1 -el
//atan:
//eredeti 0,    325,  651,  975,  1297, 1616, 1933,  2246,  2555, 2859,  3159,  3453,  3742,  4025,  4301,  4572,  4836,  5094,  5344,  5589,  5826,  6058,  6282,  6500,  6711,  6917,  7116,  7310,  7498,  7679, 7855,  8026,  8192
//szamolt 0,    326,  651,  975,  1297, 1617, 1933,  2246,  2555, 2860,  3159,  3453,  3742,  4025,  4301,  4572,  4836,  5093,  5344,  5588,  5826,  6056,  6281,  6499,  6711,  6917,  7116,  7309,  7497,  7679, 7855,  8025,  8192
//elteres 0.00, 0.07, 0.12, 0.18, 0.00, 0.10,-0.04, -0.05,  0.28,-0.04, -0.16, -0.43, -0.31, -0.21, -0.37, -0.06, -0.06, -0.07, -0.03, -0.44, -0.77, -1.03, -1.18, -1.18, -0.94, -0.23, -0.88, -1.33, -1.12,  0.04,-1.13, -1.29,  0.00
//11 helyen ter el, 1 helyen 2-vel is elter. ez a leginstabilabb, de ennel a legkevesbe fontos a pontossag... anno meg a konstans tomb is pontatlanabb volt ennel, mert csak 0-45 kozottiek voltak az ertekek ..:)
//arccos:
//63 helyen ter el +-1 -el   ..ezeket az ertekeket inkabb nem irtam be, mert tul sok lett volna ..:), de 16k-tol tart 0 fele

	signed short sin(signed int i) {		//360 fok==256 [=2^(SIN_DB_B+2)] egyseg
		i&=SIN_DB_M;				//igy mindig 0 es 255 kozott lesz
		if (i<SIN_90) return SINCORE[i];
		if (i<=SIN_180) return SINCORE[SIN_180-i];
		if (i<SIN_270) return (signed short) -SINCORE[i-SIN_180];
		return (signed short) -SINCORE[SIN_360-i];
	}
	
	signed short cos(signed int i) {
		return sin(i+SIN_90);
	}
	
/*	
//"high quality" ugyanaz mint a sima, de itt nemcsak egesz szognek lehet lekerni a szinuszat [lassabb, de pontos ha az kell]
	public short sin_hq(int j) {	//+8 bit parameternek
		int i=j>>8;
		i&=SIN_DB_M;				//igy mindig 0 es 255 kozott lesz
		int maradek=j&255;
		return (short) (((256-maradek)*sin(i)+maradek*sin(i+1))>>8);
	}
	public short cos_hq(int i) {
		return sin_hq(i+HSIN_90);
	}

//tangens=sin/cos.. ahol sin,cos=a kor x,y koordinataja. vagyis az inverze eseten az x/y-bol kell szoget szamolni
//tehat a tombben letaroljuk az 0/32 es 32/32 kozotti aranyokra mekkora szog tartozik... ez 0-45 fok ..a tobbit, tukrozgetessel ki lehet szamolni mar ebbol
//majd lehet kicsivel nagyobb szamokat kene az ATANCORE-ba irni
//min(|x|,|y|)<2^(31-ATAN_DB_B) kell hogy legyen.. a nagyobbik barmekkora lehet azzal ugyis csak osztunk:)
//olyan mertekegysegben adja vissza amit a sin-nek at lehet adni [0-360fok azaz jelenleg:0-256 altalanosan:0 - 2^(SIN_DB_B+2)]
	public short atan(int a, int b) {	//x,y koordinata-bol szamolja ki hogy milyen szogben all.. mert ugye ez az arcus tangens
		if (a==0 && b==0) return 0;	//ha x es y ==0 akkor nem lehet aranyt szamolni
		short arctan;
		int a2,b2,a3,b3,pa=Math.abs(a),pb=Math.abs(b);
		if (pa<pb) {a2=a;b2=b;a3=pa;b3=pb;} else {a2=b;b2=a;a3=pb;b3=pa;}	//ha y/x>1 akkor az x/y-al szamol... vagyis 45 fokra valo tukrozes
		arctan=(short)(ATANCORE[(a3<<ATAN_DB_B)/b3]>>(ATAN_FIXP_B-SIN_DB_B));
		if (pa>=pb) arctan=(short) (-arctan);	//+90				//az x,y elojelei alapjan donti el melyik ternegyedben van a szog
		if (a2<0) arctan=(short) (-arctan);
		if (b2<0) { arctan=(short) (SIN_180-arctan); } //+180
		if (pa>=pb) arctan+=SIN_90;
		if (arctan<0) arctan+=SIN_360;
		return arctan;
	}
//ez ugyanaz mint az elozo, csak ha 2 elore letarolt ertek koze esik akkor ezen 2 ertek sulyozott aranyat adja vissza
//vagyis linearisan interpolal ket ertek kozott, ES az atan fixpontja szerint adja vissza az erteket [jelenleg: 0-64k altalanosan: 0-2^(ATAN_FIXP_B+2)]
	public int atan_hq(int a, int b) {	//high quality	+8 bit blend	
		if (a==0 && b==0) return 0;		
		int arctan;				
		int a2,b2,a3,b3,pa=Math.abs(a),pb=Math.abs(b);
		if (pa<pb) {a2=a;b2=b;a3=pa;b3=pb;} else {a2=b;b2=a;a3=pb;b3=pa;}
		arctan=ATANCORE[(a3<<ATAN_DB_B)/b3];		
		int maradek=(a3<<ATAN_DB_B)%b3*256/b3;
		if (maradek>0) arctan=(arctan*(256-maradek)+ATANCORE[(a3<<ATAN_DB_B)/b3+1]*maradek)>>8;	//ha nem pont egy pontra esik akkor kell interpolaciot szamolni
		if (pa>=pb) arctan=-arctan;	//+90
		if (a2<0) arctan=-arctan;
		if (b2<0) { arctan=(ATAN_90<<1)-arctan; } //+180
		if (pa>=pb) arctan+=ATAN_90;
		if (arctan<0) arctan+=ATAN_90<<2;
		return arctan;
	}

//Az arcus cosinus eseten az egyseg kor-on levo pont x koordinatajabol szamol szoget [ahol i jelenleg: -64-64k lehet, altalanosan: -2^(ACOS_DB_B+8)-2^(ACOS_DB_B+8)]
//ez a fuggveny is ket legkozelebbi pontbol inetpolalja ki az eredmenyt
//a visszateresi ereteke egy szog ami 0-180fok azaz jelenleg: 0-32k, altalanosan 0-ACOS_180
	public int acos_hq(int i) {		//vagyis eleg egy 0-65536 kozotti szambol kiindulni [16 bit eltolas]
		int j=Math.abs(i),arccos,k,maradek;
		if (j>1<<(ACOS_DB_B+8)) return -1;	//ha veletlen kisebb/nagyobb szamot adunk meg akkor hibaval ter vissza
		k=j>>8;
		maradek=j&255;
 		arccos=ACOSCORE[k];
		if (maradek==0) {					//ha netan pont egy megadott pontra [azaz egesz szam jelenleg] a pont, akkor nem kell interpolalni..
			if (i>=0) return arccos;
			return ACOS_180-arccos;			//ha netan negativ lenne az i akkor tukrozzuk a 90 fokra
		}//else
		arccos=(arccos*(256-maradek)+ACOSCORE[k+1]*maradek)>>8;		//kulonben interpolalunk
		if (i>=0) return arccos;
		return ACOS_180-arccos;				//else
	}
*/

//-------------------SZOGFUGGVENYEK-vege-------------------------------

//wrk move up
MultiImage *mm; //wrk
MetaImage mi[0]; //wrk

	const String mmfiles[0]; //wrk keep same in header

int mapKey(int keyCode) {

	switch (keyCode) {
		default: return keyCode;
		case KEY_START: return KEY_RSOFT;
		case KEY_SELECT: return KEY_RSOFT;
		case KEY_A: return KEY_LSOFT;
		case KEY_B: return KEY_LSOFT;
		case KEY_L: return KEY_LSOFT;
		case KEY_R: return KEY_LSOFT;
	}

	
}

void keyPressed(int keyCode) {
		keyCode= mapKey(keyCode);

		switch (keyCode) {
			case KEY_NUM0:	keypressed[MY_KEY_NUM0 ]=3; break;
			case KEY_NUM1:	keypressed[MY_KEY_NUM1 ]=3; break;
			case KEY_NUM2:	keypressed[MY_KEY_NUM2 ]=3; keypressed[MY_KEY_UP   ]=3; break;
			case KEY_NUM3:	keypressed[MY_KEY_NUM3 ]=3; break;						
			case KEY_NUM4:	keypressed[MY_KEY_NUM4 ]=3; keypressed[MY_KEY_LEFT ]=3; break;
			case KEY_NUM5:	keypressed[MY_KEY_NUM5 ]=3; keypressed[MY_KEY_FIRE ]=3; break;
			case KEY_NUM6:	keypressed[MY_KEY_NUM6 ]=3; keypressed[MY_KEY_RIGHT]=3; break;
			case KEY_NUM7:	keypressed[MY_KEY_NUM7 ]=3; break;
			case KEY_NUM8:	keypressed[MY_KEY_NUM8 ]=3; keypressed[MY_KEY_DOWN ]=3; break;			
			case KEY_NUM9:	keypressed[MY_KEY_NUM9 ]=3; break;
			case KEY_UP:	/*case KEY_NUM2:*/ keypressed[MY_KEY_UP   ]=3; break;			
			case KEY_DOWN:	/*case KEY_NUM8:*/ keypressed[MY_KEY_DOWN ]=3; break;
			case KEY_LEFT:	/*case KEY_NUM4:*/ keypressed[MY_KEY_LEFT ]=3; break;
			case KEY_RIGHT:	/*case KEY_NUM6:*/ keypressed[MY_KEY_RIGHT]=3; break;
			case KEY_FIRE:	/*case KEY_NUM5:*/ keypressed[MY_KEY_FIRE ]=3; break;
			case KEY_RSOFT: keypressed[MY_KEY_RSOFT]=3; break;
			case KEY_LSOFT:	keypressed[MY_KEY_LSOFT]=3; keypressed[MY_KEY_FIRE ]=3; break;
			case KEY_STAR: keypressed[MY_KEY_STAR]=3; break;
			case KEY_POUND: keypressed[MY_KEY_POUND]=3; break;
	}	
}

void keyReleased(int keyCode) {
		keyCode= mapKey(keyCode);		
		
		switch (keyCode) {
			case KEY_NUM0:	keypressed[MY_KEY_NUM0 ]&=-3; break;
			case KEY_NUM1:	keypressed[MY_KEY_NUM1 ]&=-3; break;
			case KEY_NUM2:	keypressed[MY_KEY_NUM2 ]&=-3; keypressed[MY_KEY_UP   ]&=-3; break;
			case KEY_NUM3:	keypressed[MY_KEY_NUM3 ]&=-3; break;						
			case KEY_NUM4:	keypressed[MY_KEY_NUM4 ]&=-3; keypressed[MY_KEY_LEFT ]&=-3; break;
			case KEY_NUM5:	keypressed[MY_KEY_NUM5 ]&=-3; keypressed[MY_KEY_FIRE ]&=-3; break;
			case KEY_NUM6:	keypressed[MY_KEY_NUM6 ]&=-3; keypressed[MY_KEY_RIGHT]&=-3; break;
			case KEY_NUM7:	keypressed[MY_KEY_NUM7 ]&=-3; break;
			case KEY_NUM8:	keypressed[MY_KEY_NUM8 ]&=-3; keypressed[MY_KEY_DOWN ]&=-3; break;			
			case KEY_NUM9:	keypressed[MY_KEY_NUM9 ]&=-3; break;
			case KEY_UP:	/*case KEY_NUM2:*/ keypressed[MY_KEY_UP   ]&=-3; break;			
			case KEY_DOWN:	/*case KEY_NUM8:*/ keypressed[MY_KEY_DOWN ]&=-3; break;
			case KEY_LEFT:	/*case KEY_NUM4:*/ keypressed[MY_KEY_LEFT ]&=-3; break;
			case KEY_RIGHT:	/*case KEY_NUM6:*/ keypressed[MY_KEY_RIGHT]&=-3; break;
			case KEY_FIRE:	/*case KEY_NUM5:*/ keypressed[MY_KEY_FIRE ]&=-3; break;
			case KEY_RSOFT: keypressed[MY_KEY_RSOFT]&=-3; break;
			case KEY_LSOFT:	keypressed[MY_KEY_LSOFT]&=-3; keypressed[MY_KEY_FIRE ]&=-3;  break;
			case KEY_STAR: keypressed[MY_KEY_STAR]&=-3; break;
			case KEY_POUND: keypressed[MY_KEY_POUND]&=-3; break;
	}	
}

bool joehack;
void processinput() {
	_processinput();
		
	/*if (!touched)
	if (joehack) {
		joehack= false;
		keyReleased(KEY_A);		
	}*/
	
	/*if (scene==SCENE_GAME)
	if (touched) {
		joehack= true;
		keyPressed(KEY_A);
	}*/ 	
	
	/*if (scene==SCENE_MENU)
	if (clicked) {
		joehack= true;
		keyPressed(KEY_A);
	}*/
	
	_processinputend();
}

void destroyApp(boolean con) {}

void notifyDestroyed() {
	_quit(0);
}

void sleep(int n) { 
	_sleep(n);
} 

Graphics g;
void init() {
	g.surf= screen;
	//HACK!
	g.LEFT= 4;
	g.RIGHT= 8;
	g.HCENTER= 1;
	g.TOP= 16;
	g.BOTTOM= 32;
	g.VCENTER= 2;		


	//fixme
	/*noimg.createImage(4,4);
	mm= (MultiImage*) malloc(50*sizeof(MultiImage));
	memset(mm, 0, 50*sizeof(MultiImage));*/
}


void paint(Graphics g);

void repaint() {	
	paint(g);	
	_repaint();
}

void serviceRepaints() {
	_servicerepaints();
}


// PortSound //////////////////////////////////////////////////////////////////////////

PortSound::PortSound() {				
	vol= 50;
    //setVol(50);
			
	playing= false;
	looped= false;
	sound= null;
	size= 0;	
}
	
void PortSound::setVol(int v) {	    
}


void PortSound::load(String s) { 	
	/*extern const void *loadfile(const char *s, int &size);	
	char *buf= (char*)loadfile(s.c_str(), size);	

	if (buf) {		
		sound= (char*)malloc(size); 
		memcpy(sound, buf, size);	
	}*/
}

void PortSound::play() {	
	if (sound==null) return;	
	playing= true;
	///playGenericSound(sound, size);
}

void PortSound::stop() {	
	if (sound==null) return;		
	///playGenericSound(sound, 0); //hack stop all channels
	playing= false;
}

void PortSound::setLoop(boolean lp) {
    looped= lp;
}
   
void PortSound::destroy() {
}

void PortSound::vibrate(int ms) {
}

// PortSound end //////////////////////////////////////////////////////////////////////	

// MetaImage //////////////////////////////////////////////////////////////////////////

void MetaImage::paint(Graphics g, int x, int y, int anc, int tran, int frame) {
		if (ismeta) 
		{
			if ((anc & g.VCENTER)!=0) y-= getHeight(frame)>>1; else
			if ((anc & g.BOTTOM)!=0) y-= getHeight(frame);
			if ((anc & g.HCENTER)!=0) x-= getWidth(frame)>>1; else
			if ((anc & g.RIGHT)!=0) x-= getWidth(frame);
//#ifdef DEBUG
//# 			if (meta[frame][0]+getWidth(frame) > img.getWidth()) System.out.println("!W: "+ img);
//# 			if (meta[frame][1]+getHeight(frame)> img.getHeight()) System.out.println("!H: "+ img);
//#endif			
			g.setClip(x, y, getWidth(frame), getHeight(frame));
			g.drawImage(img, x-meta[frame][0], y-meta[frame][1], g.LEFT|g.TOP);			
			g.setClip(0,0,SW,SH);							
		} else	g.drawImage(img, x, y, anc);
}

void MetaImage::create(String s) { //fixme
	/*s= RESPATH+s;
	s+= ".raw";
	img.createImage(s);*/
}

void MetaImage::makemeta() {	
	ismeta= true;
}

int MetaImage::getWidth() {
	return img.getWidth();
}

int MetaImage::getHeight() {
	return img.getHeight(); 
}

int MetaImage::getWidth(int f) {
	return 8; //wrk
}

int MetaImage::getHeight(int f) {
	return 8; //wrk
}

// MetaImage end //////////////////////////////////////////////////////////////////////

// MultiImage /////////////////////////////////////////////////////////////////////////

void MultiImage::loadMm(int n) { //fixme
		/*Image *tmp= (Image*)malloc(50*sizeof(Image));
		
		if (mm[n].loaded) return;
//printf("%s %d\n", __FUNCTION__, n);		
		for (int i=0; i<100; i++) {						
			string s= RESPATH+mmfiles[n];
			s+= i<10? "0":"";
			s+= SINT(i);
			s+= ".raw";
			
			tmp[i].createImage(s);			
			if (tmp[i].surf == null) {				
				mm[n].img= (Image*)malloc(i*sizeof(Image));
				memcpy(mm[n].img, tmp, i*sizeof(Image));			
				free(tmp);				
				mm[n].numframes= i;
				mm[n].loaded= true;
				break;			
			}
		}*/
		
//printf("%s %d\n", mm[n], mmfiles[n].numframes);
}
	
void MultiImage::unload() {
		/*img= new Image[1];	
		img[0]= noimg;*/
		
		//img= null; //wrk
		loaded= false;
	}
	
int MultiImage::getHeight(int f) {
		//if (!loaded) for (int i=0; i<SIZEOF(mm); i++) if (mm[i]==this) {img= loadMm(i); break;} //wrk
		
		if (img==null || f >= numframes) {
			return noimg.getHeight(); //debug
		}
		
		return img[f].getHeight(); 
	}

int MultiImage::getWidth(int f) {		
		//if (!loaded) for (i=0; i<mm.length; i++) if (mm[i]==this) {img= loadMm(i); break;} //wrk
		
		if (img==null || f >= numframes) {
			return noimg.getWidth(); //debug
		}

		return img[f].getWidth();
	}

Image MultiImage::getImage(int f) {
		//if (!loaded) for (int i=0; i<mm.length; i++) if (mm[i]==this) {img= loadMm(i); break;} //wrk

		if (img==null || f >= numframes) {
			return noimg; //debug
		}
		
		return img[f]; 
	}

void MultiImage::paint(Graphics g, int x, int y, int anc, int tran, int f) {

	    /*if (!loaded) for (int i=0; i<PortCanvas.mm.length; i++) if (PortCanvas.mm[i]==this) {
			img= loadMm(i);
			break;
	    }*/

	    if (img==null || f >= numframes) {
			return; //debug
	    }
	    
		//if (img[f]==GameMidlet.noimg) return; //wrk

		if (tran==0)
		g.drawImage(img[f], x, y, anc);	
		else
		g.drawImage(img[f+((numframes+1)>>1)], x, y, anc);	
}

void Thread::sleep(int ms) {
		_sleep(ms);
}


// MultiImage end /////////////////////////////////////////////////////////////////////
