/****************************************************************************\
*
* Magnetic Scrolls Interpreter by Niclas Karlsson 1997
*
* BeOS interface beosmain.c by Tinic Uro
*
\****************************************************************************/
#include <AppKit.h>
#include <InterfaceKit.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include "defs.h"

#define width   70	// Window width in characters
#define height  33	// Window height in characters

extern type32 	i_count;
type32			more_counter=0;
type8			buffer[80],xpos=0,bufpos=0,log_on=0,ms_gfx_enabled,filename[128];
FILE				*log1=0,*log2=0;
char 			app_path[1024]="/boot/home";

// -------------------------------------------------
// Misc stuff
// -------------------------------------------------

static bool floyd_32_8(ulong *in_data, int in_width, int in_height, BBitmap *dest_bitmap)
/*
 *	Does a floyd alike dithering to a BBitmap
 * 
 *	in_data		= input data in RGBA format
 *	in_width	= width of the picture (== bytes per row!)
 *	in_height	= height of the picture
 *	dest_bitmap	= pointer to a BBitmap with COLOR_8_BIT colorspace
 *  			  Make sure that the BBitmap is big enough...
 *
 *  corrections are done this way:
 *
 *	+-----+-----+- -
 *  |     | 0.5 |
 *  +-----+-----+- -
 *  | 0.5 | 0.0 |
 *  +-----+-----+- -
 *  |     |     |
 *
 *  This allows to use only shifting and avoiding real divisions.
 *  You will note a slight diagonal dithering, but this is no
 *  real disadvantage.
 *
 */
{
	if(dest_bitmap->ColorSpace()!=B_COLOR_8_BIT)	return FALSE;

	char 	*delta	= new char[(in_width+1)*2*4];
	uchar	*dst		= (uchar *)dest_bitmap->Bits();
	uchar	*xpal	= (uchar *)system_colors()->index_map;
	ulong	*cpal	= (ulong *)system_colors()->color_list;
	char		*fcwrite	= delta+((in_width+1));
	char		*cread	= delta;
	char		*cwrite	= fcwrite;
	ulong	xmod		= dest_bitmap->BytesPerRow();
	long		switcher	= 0;

	memset(delta,0,(in_width+1)*2*4);
	
	for(int y=0;y<in_height;y++)
	{
		long rdlast	= 0;
		long gdlast	= 0;
		long bdlast	= 0;
		
		for(int x=0;x<in_width;x++)
		{
			// get 1 pixel from the input buffer

			ulong 	p  = *in_data++;			

			// add corrections from previous pixels.

			ulong	cread_data=*cread++;
			
			long	b  = ((p>>24)&0xFF) + ((*cread++ + bdlast)/2);
			long	g  = ((p>>16)&0xFF) + ((*cread++ + gdlast)/2);
			long	r  = ((p>> 8)&0xFF) + ((*cread++ + rdlast)/2);

			// fix high and low values

			r = r > 255 ? 255 : r;
			r = r <   0 ?   0 : r;
			g = g > 255 ? 255 : g;
			g = g <   0 ?   0 : g;
			b = b > 255 ? 255 : b;
			b = b <   0 ?   0 : b;

			// lets see which color we get from the BeOS palette.
			
			uchar 	q = xpal[((r<<7)&0x7C00)|((g<<2)&0x03E0)|((b>>3)&0x001F)];
			ulong 	s = cpal[q];

			// output the pixel

			dst[x] = q;

			// save the differences to the requested color

			*cwrite++ = rdlast = r - ((s>>24)&0xFF);
			*cwrite++ = gdlast = g - ((s>>16)&0xFF);
			*cwrite++ = bdlast = b - ((s>> 8)&0xFF);
		}

		if(switcher)
		{
			cwrite	= delta;
			cread	= fcwrite;
			switcher= 0;
		}
		else
		{
			cread	= delta;
			cwrite	= fcwrite;
			switcher= 1;
		}				
		dst+=xmod;
	}
	delete [] delta;
	
	return TRUE;
}

type8 ms_load_file(type8 *name, type8 *ptr, type16 size) {
	FILE *fh;
	type8 *realname;

	if (name) realname=name;
	else {
		do {
			printf("Filename: ");
		}	while (!gets((char *)filename));
		realname=filename;
	}

	char fname[1024];
	strcpy(fname,app_path);
	strcat(fname,"/");
	strcat(fname,(char *)realname);

	if (!(fh=fopen((char *)fname,"rb"))) return 1;
	if (fread(ptr,1,size,fh)!=size) return 1;
	fclose(fh);
	return 0;
}

type8 ms_save_file(type8 *name, type8 *ptr, type16 size) {
	FILE *fh;
	type8 *realname;

	if (name) realname=name;
	else {
		do {
			printf("Filename: ");
		}	while (!gets((char *)filename));
		realname=filename;
	}

	char fname[1024];
	strcpy(fname,app_path);
	strcat(fname,"/");
	strcat(fname,(char *)realname);

	if (!(fh=fopen((char *)fname,"wb"))) return 1;
	if (fwrite(ptr,1,size,fh)!=size) return 1;
	fclose(fh);
	return 0;
}

static void script_write(type8 c) {
	if (log_on==2 && fputc(c,log1)==EOF) {
		printf("[Problem with script file - closing]\n");
		fclose(log1);
		log_on=0;
	}
}

static void transcript_write(type8 c) {
	if (log2 && c==0x08 && ftell(log2)>0) fseek(log2,-1,SEEK_CUR);
	else if (log2 && fputc(c,log2)==EOF) {
		printf("[Problem with transcript file - closing]\n");
		fclose(log2);
		log2=0;
	}
}

// -------------------------------------------------
// TextView stuff
// -------------------------------------------------

class MagneticView;
class MagneticWindow;

MagneticView		*view;
MagneticWindow 	*win;
int32			ActKey=0;

class MagneticView : public BView
{
	BBitmap		*bmp;
	BView		*bmp_view;
	float		xpos;
	float		ypos;	
	float		xsiz;
	float		ysiz;
	float		cwidths[256];
	float		cheight;
	float		fwidth;
	float		fheight;
	char			linebuffer[1024];
	char			tmpbuffer[1024];
	int32		linex;
	font_height	fontheight;
	uint8		bg_color;
	bool			cursor;
	int32		cursor_pos;
	int32		xoff;

	public:
				MagneticView(BRect frame):BView(frame,"MagneticView",B_FOLLOW_ALL,B_WILL_DRAW)
				{
					BScreen screen;
					bg_color=screen.IndexForColor(200,200,200);
					cursor=false;
				};

		void		AttachedToWindow()
				{
					SetFont(be_plain_font);
					SetFontSize(be_fixed_font->Size());

					char s[2];
					for(int32 c=0;c<256;c++)
					{
						s[0]=c;
						s[1]=0;
						cwidths[c]=StringWidth(s);
					}

					s[0]='W';
					s[1]=0;
					fwidth = be_fixed_font->StringWidth(s);
					fheight = be_fixed_font->Size();

					be_plain_font->GetHeight(&fontheight);

					cheight = be_fixed_font->Size();
					cheight += 1.0;

					xsiz=width*fwidth;
					ysiz=height*cheight;
					
					Window()->ResizeTo(xsiz+2,ysiz+2);

					xpos=0;
					ypos=0;
					linex=0;
					linebuffer[0]=0;

					bmp = new BBitmap(Bounds(),B_COLOR_8_BIT,true);
					bmp_view = new BView(Bounds(),"MagneticBmpView",NULL,NULL);
					bmp->Lock();
					bmp->AddChild(bmp_view);
					bmp_view->SetViewColor(200,200,200);
					bmp_view->SetLowColor(200,200,200);
					bmp_view->SetHighColor(200,200,200);
					bmp_view->FillRect(Bounds());
					bmp_view->SetHighColor(0,0,0);
					bmp_view->SetFont(be_plain_font);
					bmp_view->SetFontSize(be_fixed_font->Size());
					bmp_view->Sync();
					bmp->Unlock();					

					MakeFocus();
				};
				
		void		Draw(BRect udp)
				{
					DrawBitmapAsync(bmp,udp,udp);
					Sync();
				};
		
		void		KeyDown(const char *bytes, int32 numBytes)
				{
					if(numBytes>0)
					{
						ActKey=bytes[0];
					}
				};
				
		// Quite a hack, but it works fine 8-)...
		type8 	GetKey()
				{
					type8 key;
					while(ActKey==0) snooze(10000);
					key=ActKey;
					ActKey=0;
					return key;
				};

		void		FlushStatus(char *line)
				{
					bmp->Lock();
					bmp_view->Sync();
					bmp_view->SetFont(be_fixed_font);
					bmp_view->SetHighColor(128,0,0);
					bmp_view->FillRect(BRect(1,1,xsiz,cheight));
					bmp_view->SetHighColor(255,255,255);
					bmp_view->SetLowColor(128,0,0);
					bmp_view->DrawString(line,BPoint(1,(cheight-fontheight.descent)+1));
					bmp_view->SetHighColor(0,0,0);
					bmp_view->SetLowColor(200,200,200);
					bmp_view->Sync();
					bmp_view->SetFont(be_plain_font);
					bmp_view->SetFontSize(be_fixed_font->Size());
					bmp->Unlock();

					int8 *bits = (int8 *)bmp->Bits();
					memset(bits,bg_color,bmp->BytesPerRow());
					
					Window()->Lock();
					Draw(BRect(0,0,xsiz-1,cheight));
					Window()->Unlock();
				};
				
		void		SetCursor(bool onoff)
				{
					cursor=onoff;
					xoff=linex;
				};
				
		void		FlushReadLine()
				{
					bmp->Lock();
					bmp_view->SetHighColor(200,200,200);
					bmp_view->FillRect(BRect(1,ypos+1,xsiz+1,ypos+cheight+1));
					bmp_view->SetHighColor(0,0,0);
					bmp_view->DrawString(linebuffer,BPoint(1,ypos+(cheight-fontheight.descent)+1));
					float sw=bmp_view->StringWidth(linebuffer,cursor_pos+xoff);
					if(cursor)
						bmp_view->StrokeLine(BPoint(sw,ypos+1),BPoint(sw,ypos+cheight+1));
					bmp_view->Sync();
					bmp->Unlock();
					
					Window()->Lock();
					Draw(BRect(0,ypos,xsiz+1,ypos+cheight+1));
					Window()->Unlock();
				};
		
		void		Flush()
				{
					bmp->Lock();
					bmp_view->DrawString(linebuffer,BPoint(1,ypos+(cheight-fontheight.descent)+1));
					float sw=bmp_view->StringWidth(linebuffer,cursor_pos+xoff);
					if(cursor)
						bmp_view->StrokeLine(BPoint(sw,ypos+1),BPoint(sw,ypos+cheight+1));
					bmp_view->Sync();
					bmp->Unlock();
					
					Window()->Lock();
					Draw(BRect(0,ypos,xsiz+1,ypos+cheight+1));
					Window()->Unlock();
				};
		
		void		NewReadLine(int32 cpos, type8 *b)
				{
					cursor_pos = cpos;
					if(b)
					{
						strcpy(&linebuffer[xoff],(char *)b);
					}	
					FlushReadLine();
				};
				
		void		PutChar(type8 c)
				{
					if(c==0x0a)
					{
						more_counter++;
						Flush();
						if(ypos>=(ysiz-cheight))
						{
							int8 *bits = (int8 *)bmp->Bits();
							memcpy(bits+(int32)(bmp->BytesPerRow()*(cheight+1)),bits+(int32)(bmp->BytesPerRow()*((cheight*2)+1)),bmp->BytesPerRow()*(ysiz-cheight));
							memset(bits+(int32)(bmp->BytesPerRow()*(ysiz-cheight+1)),bg_color,bmp->BytesPerRow()*cheight);
							if(more_counter>=(height-1))
							{
								strcpy(linebuffer,"[MORE]");
								FlushReadLine();
								Window()->Lock();
								Draw(BRect(0,0,xsiz+1,ysiz+1));
								Window()->Unlock();
								GetKey();
								strcpy(linebuffer,"");
								FlushReadLine();
								more_counter=0;
							}
							Window()->Lock();
							Draw(BRect(0,0,xsiz+1,ysiz+1));
							Window()->Unlock();
						}
						else 
						{
							ypos+=cheight;
						}
						xpos=0;
						linex=0;
						
					}
					else
					{
						linebuffer[linex]=c;
						linebuffer[linex+1]=0;
						linex++;
						xpos+=cwidths[c];
						
						// Wrap line
						if(xpos>xsiz)
						{
							int32 x=linex;
							for(;(linebuffer[x]!=0x20) && (x>0);x--){}
							int32 i=x+1;
							int32 d=0;
							for(;i<linex;i++,d++)tmpbuffer[d]=linebuffer[i];
							linebuffer[x]=0;
							PutChar(0x0a);
							i=0;
							linex=0;
							memset(linebuffer,0,1024);
							for(;i<d;i++)
							{
								linebuffer[i]=tmpbuffer[i];
								linex++;
								xpos+=cwidths[linebuffer[i]];
							}
						}
					}
				};
};

class MagneticWindow : public BWindow
{
	public:
				MagneticWindow(BRect frame):BWindow(frame,"Magnetic by Tinic",B_TITLED_WINDOW,B_NOT_RESIZABLE)
				{
					frame.OffsetTo(0,0);
					view = new MagneticView(frame);
					Lock();
					AddChild(view);
					Unlock();
					Show();					
				};
				
		bool		QuitRequested(void)
				{
					be_app->PostMessage(B_QUIT_REQUESTED);
					return true;
				};
};

void ms_statuschar(type8 c) {
	static type8 x=0;
	static char status_bar[1024];

	if (c==0x09) {
		while (x+11<width) {
			status_bar[x]=0x20;
			x++;
		}
		return;
	}
	if (c==0x0a) {
		x=0;
		view->FlushStatus(status_bar);
		return;
	}
	status_bar[x]=c;
	x++;
}

void ms_flush(void) {
	type8 j;

	if (!bufpos) return;
	for (j=0;j<bufpos;j++) {
		if (buffer[j]==0x0a) xpos=0;
		if (buffer[j]==0x08) xpos-=2;
		view->PutChar(buffer[j]);
		transcript_write(buffer[j]);
		xpos++;
	}
	bufpos=0;
}

void ms_putchar(type8 c) {
	if((c!=0x08))
		buffer[bufpos++]=c;
	else if(bufpos>0)
		bufpos--;
	if ((c==0x20) || (c==0x0a) || (bufpos>=80)) ms_flush();
}

type8 ms_getchar(void) {
	static type8  buf[256];
	static type16 pos=0;
	static BList backbuf;
	static int32 backpos=0;
	int c;
	type8  i;
	
	if (!pos) {				/* Read new line? */
		i=0;
		
		more_counter=0;

		view->SetCursor(true);
		view->FlushReadLine();

		while (1) 
		{
			if (log_on==1) 
			{								/* Reading from logfile */
				if ((c=fgetc(log1))==EOF) 
				{				/* End of log? - turn off */
					log_on=0;
					fclose(log1);
					c=view->GetKey();
				} 
				else printf("%c",c);					/* print the char as well */
			} 
			else 
			{
				c=view->GetKey();
				if (c=='#' && !i) /* Interpreter command? */
				{				
					buf[i++]=c;
					view->NewReadLine(i,buf);

					while((c=view->GetKey())!='\n' && c!=EOF && i<255)
					{
						if( c==B_LEFT_ARROW)
						{
							if(i>0)
							{
								i--;
								view->NewReadLine(i,buf);
							}				
						}
						else if(c==B_RIGHT_ARROW)
						{
							
							if(buf[i]!=0)
							{
								i++;
								view->NewReadLine(i,buf);
							}				
						}
						else if(c==B_UP_ARROW)
						{
							if(backbuf.CountItems()>0)
							{
								strcpy((char *)buf,(char *)backbuf.ItemAt(backpos));
								if(backpos<(backbuf.CountItems()-1))
								{
									backpos++;
								}
								i=strlen((char *)buf);
								view->NewReadLine(i,buf);
							}
						}
						else if(c==B_DOWN_ARROW)
						{
							if(backbuf.CountItems()>0)
							{
								strcpy((char *)buf,(char *)backbuf.ItemAt(backpos));
								if(backpos>0)
								{
									backpos--;
								}
								i=strlen((char *)buf);
								view->NewReadLine(i,buf);
							}
						}
						else if(c==B_INSERT)
						{
						}
						else if(c==B_BACKSPACE)
						{
							if(i>0)
							{
								i--;
								for(int h=i;buf[h]!=0;h++)buf[h]=buf[h+1];
								view->NewReadLine(i,buf);
							}
						}
						else if(c==B_DELETE)
						{
							if(i>0 && buf[i]!=0)
							{
								for(int h=i;buf[h]!=0;h++)buf[h]=buf[h+1];
								view->NewReadLine(i,buf);
							}
						}
						else
						{
							if(c!=0xa)
							{
								for(int h=strlen((char *)buf);h>=i;h--)buf[h+1]=buf[h];
								buf[i++]=c;
								view->NewReadLine(i,buf);
							}
						}
					}
					buf[i]=0;
					c='\n';									/* => Prints new prompt */
					i=0;
					if (!strcmp((char *)buf,"#logoff") && log_on==2) 
					{
						printf("[Closing script file]\n");
						log_on=0;
						fclose(log1);
					} 
					else if (!strcmp((char *)buf,"#undo")) 
					{
						c=0;
						memset(buf,0,256);
						view->SetCursor(false);
						view->FlushReadLine();
						return c;
					} 
					else 
					{
						printf("[Nothing done]\n");
					}
				}
			}
			if( c==B_LEFT_ARROW)
			{
				if(i>0)
				{
					i--;
					view->NewReadLine(i,buf);
				}				
			}
			else if(c==B_RIGHT_ARROW)
			{
				
				if(buf[i]!=0)
				{
					i++;
					view->NewReadLine(i,buf);
				}				
			}
			else if(c==B_UP_ARROW)
			{
				if(backbuf.CountItems()>0)
				{
					strcpy((char *)buf,(char *)backbuf.ItemAt(backpos));
					if(backpos<(backbuf.CountItems()-1))
					{
						backpos++;
					}
					i=strlen((char *)buf);
					view->NewReadLine(i,buf);
				}
			}
			else if(c==B_DOWN_ARROW)
			{
				if(backbuf.CountItems()>0)
				{
					strcpy((char *)buf,(char *)backbuf.ItemAt(backpos));
					if(backpos>0)
					{
						backpos--;
					}
					i=strlen((char *)buf);
					view->NewReadLine(i,buf);
				}
			}
			else if(c==B_INSERT)
			{
			}
			else if(c==B_BACKSPACE)
			{
				if(i>0)
				{
					i--;
					for(int h=i;buf[h]!=0;h++)buf[h]=buf[h+1];
					view->NewReadLine(i,buf);
				}
			}
			else if(c==B_DELETE)
			{
				if(i>0 && buf[i]!=0)
				{
					for(int h=i;buf[h]!=0;h++)buf[h]=buf[h+1];
					view->NewReadLine(i,buf);
				}
			}
			else
			{
				if(c!=0xa)
				{
					for(int h=strlen((char *)buf);h>=i;h--)buf[h+1]=buf[h];
					buf[i++]=c;
					view->NewReadLine(i,buf);
				}
				script_write(c);
				if (c!='\n') transcript_write(c);
				if (c=='\n' || c==EOF || i==255) break;
				if (!c) break;
			}
		}
		
		int j=strlen((char *)buf);
		
		backbuf.AddItem(strdup((char *)buf),0);
		backpos=0;
		
		buf[j]='\n';
		buf[j+1]=0;
		
		view->SetCursor(false);
		view->FlushReadLine();
	}
	

	if ((c=buf[pos++])=='\n' || !c) 
	{
		memset(buf,0,256);
		pos=0;
	}
	return (type8)c;
}

// -------------------------------------------------
// GFX stff
// -------------------------------------------------

class GFXWindow;

GFXWindow *gfxwindow=0;

class GFXWindow : public BWindow
{	
	class GFXView : public BView
	{
		BBitmap	*bmp;
		BBitmap	*bmp8;
		bool		color_8_bit;
		
		public:
		
				GFXView():BView(BRect(0,0,0,0),"",B_FOLLOW_ALL,B_WILL_DRAW)
				{
					bmp=0;
					bmp8=0;					
				};
				
				~GFXView()
				{
					if(bmp) delete bmp;
					if(bmp8) delete bmp8;
				};
	
		void		AttachedToWindow(void)
				{
					BRect rect=Window()->Bounds();
					ResizeTo(rect.Width(),rect.Height());
				};
				
		void		SetBitmap(uint32 w, uint32 h, uint16 *pal, uint8 *data)
				{
					Window()->Lock();
					if(bmp) delete bmp;
					bmp=0;
					if(bmp8) delete bmp8;
					bmp8=0;
					Window()->ResizeTo(w-1,h-1);
					ResizeTo(w-1,h-1);
					Window()->Unlock();

					bmp = new BBitmap(BRect(0,0,w-1,h-1),B_RGB_32_BIT);
					
					uint32 rpal[16];
					
					for(int i=0;i<16;i++)
					{
						int r,g,b;
						
						b = ((pal[i]>>8)&7);
						g = ((pal[i]>>4)&7);
						r = ((pal[i]>>0)&7);


						rpal[i] =	r<<29 |
									g<<21 |
									b<<13;
					}
					uint32 *bits = (uint32 *)bmp->Bits();
					
					for(int y=0;y<h;y++)
					{
						for(int i=0;i<w;i++)
						{
							bits[i]=rpal[data[i]&0xF];
						}
						data+=w;
						bits+=bmp->BytesPerRow()/sizeof(uint32);
					}
					
					bmp8 = new BBitmap(BRect(0,0,w-1,h-1),B_COLOR_8_BIT);
					floyd_32_8((ulong *)bmp->Bits(),w,h,bmp8);
													
					Window()->Lock();
					SetDrawingMode(B_OP_COPY);
					Draw(Bounds());
					Window()->Unlock();
				};
		
		void		Draw(BRect udp)
				{
					BScreen screen;					
					if(screen.ColorSpace()==B_COLOR_8_BIT)
					{ 
						if(bmp8) DrawBitmap(bmp8,udp,udp); 
					}
					else 
					{
						if(bmp) DrawBitmap(bmp,udp,udp);
					}
				};
	};

	GFXView		*view;
	
	public:

			GFXWindow(BRect frame):BWindow(frame,"MagneticGFX",B_TITLED_WINDOW,B_NOT_RESIZABLE|B_NOT_CLOSABLE)
			{
				view = new GFXView();
				AddChild(view);				

				BRect rect=win->Frame();
				MoveTo(rect.RightTop()+BPoint(12,0));

				Show();
			};
			
	void		SetBitmap(uint32 w, uint32 h, uint16 *pal, uint8 *data)
			{
				view->SetBitmap(w,h,pal,data);
			};
			
	bool		QuitRequested(void)
			{
				return false;
			};
};

void ms_showpic(type8 c,type8 mode) {

	type16 w,h,pal[16];
	type8 *raw=0,i;

	if(mode==2 && ms_gfx_enabled)
	{
		raw=ms_extract(c,&w,&h,pal);	
		if(!gfxwindow)
		{
			gfxwindow = new GFXWindow(BRect(0,0,w-1,h-1));
			win->Activate();
		}
		gfxwindow->SetBitmap(w,h,pal,raw);
	}

}

// -------------------------------------------------
// Main Application
// -------------------------------------------------

class MagneticApp;

class MagneticApp : public BApplication
{
	type8 		running;
	type8		*gamename;
	type8		*gfxname;	
	type32 		dlimit;
	type32		slimit;
	thread_id	game_thread;
	BFilePanel	*filepanel;

	public:
				MagneticApp():BApplication("application/x-Tinic.Magnetic")
				{
					gamename=0;
					gfxname=0;
					game_thread=0;
					filepanel=0;
					dlimit=slimit=0xffffffff;
				};
				
		void 	RefsReceived(BMessage *message)
				{
					entry_ref ref;
					if(message->FindRef("refs",&ref)==B_NO_ERROR)
					{
						BEntry entry(&ref);
						BPath path;
						entry.GetPath(&path);
						gamename=(type8 *)strdup(path.Path());
						if(!game_thread)	RunGame();
					}
				};

		void 	ArgvReceived(int32 argc, char **argv)
				{
					for (int i=1;i<argc;i++) 
					{
						if (argv[i][0]=='-') 
						{
							switch (tolower(argv[i][1])) 
							{
								case 'd':	if (strlen(argv[i])>2) dlimit=atoi(&argv[i][2]);
												else dlimit=0;
												break;
								case 's':	if (strlen(argv[i])>2) slimit=atoi(&argv[i][2]);
												else slimit=655360;
												break;
								case 't':	if (!(log2=fopen(&argv[i][2],"w"))) {
												printf("Failed to open \"%s\" for writing.\n",&argv[i][2]);
										}
												break; 
								case 'r':	if (log1=fopen(&argv[i][2],"r")) log_on=1;
												else printf("Failed to open \"%s\" for reading.\n",&argv[i][2]);
												break;
								case 'w':	if (log1=fopen(&argv[i][2],"w")) log_on=2;
												else printf("Failed to open \"%s\" for writing.\n",&argv[i][2]);
												break;
								default:		printf("Unknown option -%c, ignoring.\n",argv[i][1]);
							}
						} 
						else if (!gamename) gamename=(type8 *)strdup(argv[i]);
						else gfxname=(type8 *)strdup(argv[i]);
					}
				};

		bool		QuitRequested(void)
				{
					kill_thread(game_thread);

					if(filepanel) delete filepanel;
					if(gamename) free(gamename);
					if(gfxname) free(gfxname);

					return true;
				};


		void		ReadyToRun()
				{
					app_info the_info;	
					BDirectory app_dir=BDirectory();
					
					if (GetAppInfo(&the_info) == B_NO_ERROR) 
					{
						BEntry file = BEntry(&the_info.ref);
						BPath path = BPath();
						
						if(file.GetParent(&app_dir)==B_NO_ERROR)
						{	
							app_dir.GetEntry(&file);
							file.GetPath(&path);
							strcpy(app_path,path.Path());
							chdir(app_path);
						}
					} 

					if(!gamename)
					{
						BMessenger messenger(this);
						filepanel = new BFilePanel();		
						filepanel->SetTarget(messenger);	
						filepanel->Window()->SetTitle("Open game file...");
						filepanel->Show();
					}
					else
					{
						if(!game_thread)	RunGame();
					}
				};
	
		void		RunGame()
				{
					resume_thread(game_thread=spawn_thread((thread_entry)LaunchGame,"Game",B_NORMAL_PRIORITY,this));
				};
		
	static void	LaunchGame(MagneticApp *obj)
				{
					obj->Game();
				};
				
		void 	Game()
				{				
					if (!gamename) 
					{
						printf("\nMS-Interpreter - Magnetic Scrolls interpreter V1.0\n\n");
						printf("Usage: Magnetic [options] game [gfxfile]\n\n"
								 "Where the options are:\n"
								 " -d[n]    activate registerdump (after n instructions)\n"
								 " -r[name] read script file\n"
								 " -s[n]    safety mode, exits automatically (after n instructions)\n"
								 " -t[name] write transcript file\n"
								 " -w[name] write script file\n\n"
								 "The interpreter commands are:\n"
								 " #undo   obvious - don't use it near are_you_sure prompts\n"
								 " #logoff to turn off script writing\n\n");
					} 
					else 
					{
						if (!gfxname)
						{
							gfxname = (type8 *)malloc(64);
							strcpy((char *)gfxname,(char *)gamename);
							int32 i;
							for(i=strlen((char *)gfxname);i>=0 && gfxname[i]!='.';i--){}
							if(i>=0)
							{
								strcpy((char *)&gfxname[i],".gfx");
							}
							else
							{
								strcat((char *)gfxname,".gfx");
							}
							BEntry entry((char *)gfxname);
							if(!entry.Exists())
							{
								free(gfxname);
								gfxname=0;
							}
						}
						if (!(ms_gfx_enabled=ms_init(gamename,gfxname))) 
						{
							printf("Couldn't start up game \"%s\".\n",gamename);	
						} 
						else 
						{
							BRect rect(0,0,639,479);
							rect.OffsetTo(8,28);				
							win = new MagneticWindow(rect);	
	
							ms_gfx_enabled--;
							running=1;
		
							while ((i_count<slimit) && running) 
							{
								if (i_count>=dlimit) status();
								running=ms_rungame();
							}
		
							if (i_count==slimit) 
							{
								printf("\n\nSafety limit (%d) reached.\n",slimit);
								status();
							}
		
							ms_freemem();
							if (log_on) fclose(log1);
							if (log2) fclose(log2);
							log2=0;
							
							printf("\nExiting.\n");
							
						}
					}
					be_app->PostMessage(B_QUIT_REQUESTED);
				};				
}

main(int argc, char **argv) 
{
	be_app = (BApplication *)new MagneticApp();
	be_app->Run();
	delete be_app;
}
