[Scummvm-cvs-logs] CVS: scummvm/bs2 .cvsignore,NONE,1.1 anims.cpp,NONE,1.1 anims.h,NONE,1.1 build_display.cpp,NONE,1.1 build_display.h,NONE,1.1 console.cpp,NONE,1.1 console.h,NONE,1.1 controls.cpp,NONE,1.1 controls.h,NONE,1.1 credits.h,NONE,1.1 debug.cpp,NONE,1.1 debug.h,NONE,1.1 defs.h,NONE,1.1 events.cpp,NONE,1.1 events.h,NONE,1.1 function.cpp,NONE,1.1 function.h,NONE,1.1 header.h,NONE,1.1 icons.cpp,NONE,1.1 icons.h,NONE,1.1 interpreter.cpp,NONE,1.1 interpreter.h,NONE,1.1 layers.cpp,NONE,1.1 layers.h,NONE,1.1 logic.cpp,NONE,1.1 logic.h,NONE,1.1 maketext.cpp,NONE,1.1 maketext.h,NONE,1.1 mem_view.cpp,NONE,1.1 mem_view.h,NONE,1.1 memory.cpp,NONE,1.1 memory.h,NONE,1.1 module.mk,NONE,1.1 mouse.cpp,NONE,1.1 mouse.h,NONE,1.1 object.h,NONE,1.1 protocol.cpp,NONE,1.1 protocol.h,NONE,1.1 resman.cpp,NONE,1.1 resman.h,NONE,1.1 router.cpp,NONE,1.1 router.h,NONE,1.1 save_rest.cpp,NONE,1.1 save_rest.h,NONE,1.1 scroll.cpp,NONE,1.1 scroll.h,NONE,1.1 sound.cpp,NONE,1.1 sound.h,NONE,1.1 speech.cpp,NONE,1.1 speech.h,NONE,1.1 startup.cpp,NONE,1.1 startup.h,NONE,1.1 sword2.cpp,NONE,1.1 sword2.h,NONE,1.1 sync.cpp,NONE,1.1 sync.h,NONE,1.1 tony_gsdk.cpp,NONE,1.1 tony_gsdk.h,NONE,1.1 walker.cpp,NONE,1.1 walker.h,NONE,1.1

Jonathan Gray khalek at users.sourceforge.net
Sun Jul 27 18:45:25 CEST 2003


Update of /cvsroot/scummvm/scummvm/bs2
In directory sc8-pr-cvs1:/tmp/cvs-serv2041

Added Files:
	.cvsignore anims.cpp anims.h build_display.cpp build_display.h 
	console.cpp console.h controls.cpp controls.h credits.h 
	debug.cpp debug.h defs.h events.cpp events.h function.cpp 
	function.h header.h icons.cpp icons.h interpreter.cpp 
	interpreter.h layers.cpp layers.h logic.cpp logic.h 
	maketext.cpp maketext.h mem_view.cpp mem_view.h memory.cpp 
	memory.h module.mk mouse.cpp mouse.h object.h protocol.cpp 
	protocol.h resman.cpp resman.h router.cpp router.h 
	save_rest.cpp save_rest.h scroll.cpp scroll.h sound.cpp 
	sound.h speech.cpp speech.h startup.cpp startup.h sword2.cpp 
	sword2.h sync.cpp sync.h tony_gsdk.cpp tony_gsdk.h walker.cpp 
	walker.h 
Log Message:
bs2

--- NEW FILE: .cvsignore ---
.deps

--- NEW FILE: anims.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/anims.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//-------------------------------------------------------------------------------------------------------------
// A more intelligent version of the old ANIMS.C
// All this stuff by James
// DON'T TOUCH!
//-------------------------------------------------------------------------------------------------------------

//#include <io.h>		// for access()
#include <stdio.h>	// for sprintf
#include <string.h>

#include "common/scummsys.h"
#include "driver/driver96.h"
#include "anims.h"
#include "build_display.h"	// for DisplayMsg()
#include "console.h"
#include "controls.h"	// for 'speechSelected' & 'subtitles'
#include "debug.h"
#include "defs.h"
#include "header.h"
#include "interpreter.h"
#include "layers.h"	// for 'this_screen' structure - for restoring palette in FN_play_sequence
#include "maketext.h"	// for MakeTextSprite used by FN_play_sequence ultimately
#include "object.h"
#include "protocol.h"
#include "resman.h"
#include "sword2.h"		// for Close_game()
#include "sync.h"
#include "sound.h"		// for Speech stuff.

//-------------------------------------------------------------------------------------------------------------
uint32 smackerLeadOut=0;	// stores resource id of wav to use as lead-out from smacker

//-------------------------------------------------------------------------------------------------------------
// local function prototypes

int32 Animate(int32 *params, uint8 reverse_flag);
int32 Mega_table_animate(int32 *params, uint8 reverse_flag);

//-------------------------------------------------------------------------------------------------------------
int32 FN_anim(int32 *params)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 resource id of animation file

	return Animate(params,0);	// 0 means normal forward anim
}
//-------------------------------------------------------------------------------------------------------------
int32 FN_reverse_anim(int32 *params)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 resource id of animation file

	return Animate(params,1);	// 1 means reverse anim
}
//-------------------------------------------------------------------------------------------------------------
int32 FN_mega_table_anim(int32 *params)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to animation table

	return Mega_table_animate(params,0);	// 0 means normal forward anim
}
//-------------------------------------------------------------------------------------------------------------
int32 FN_reverse_mega_table_anim(int32 *params)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to animation table

	return Mega_table_animate(params,1);	// 1 means reverse anim
}
//-------------------------------------------------------------------------------------------------------------
int32 Animate(int32 *params, uint8 reverse_flag)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 resource id of animation file

 	Object_logic	*ob_logic;
 	Object_graphic	*ob_graphic;
	uint8			*anim_file;
	_animHeader		*anim_head;
 	int32	res = params[2];

	#ifdef _DEBUG
	_standardHeader	*head;	// for animation testing & checking for correct file type
	#endif

	//----------------------------------------------------------------------------------------
	// read the main parameters

	ob_logic	= (Object_logic *) params[0];	// param 0 is pointer to normal structure
	ob_graphic	= (Object_graphic *) params[1];	// param 1 is pointer to graphic structure
	
	//----------------------------------------------------------------------------------------
	// if this is the start of the anim, set up the first frame

	if (ob_logic->looping==0)
	{
		//-----------------------------------------------------------
		#ifdef _DEBUG
		// For testing all anims!	(James18apr97)
		// A script loop can send every resource number to the anim function
		// & it will only run the valid ones
		// See 'testing_routines' object in George's Player Character section of linc
		if (SYSTEM_TESTING_ANIMS)
		{
			if (res_man.Res_check_valid(res))	// if the resource number is within range & it's not a null resource
			{
				head = (_standardHeader*) res_man.Res_open(res);	// open the resource
				res_man.Res_close(res);								// can close immediately - we've got a pointer to the header

				if (head->fileType!=ANIMATION_FILE)					// if it's not an animation file
				{
					FN_no_sprite(params+1);							// switch off the sprite
					return(IR_STOP);								// don't animate - just continue script next cycle
				}
			}
			else
			{														// not a valid resource number
				FN_no_sprite(params+1);								// switch off the sprite
				return(IR_STOP);									// don't animate - just continue script next cycle
			}

			FN_sort_sprite(params+1);								// switch on the sprite
		}
		#endif
		//-----------------------------------------------------------

		//---------------------
		#ifdef _DEBUG
		// check that we haven't been passed a zero resource number
		if (res==0)
			Con_fatal_error("Animate: %s (id %d) passed zero anim resource (%s line %u)", FetchObjectName(ID), ID, __FILE__, __LINE__);
		#endif
  		//---------------------

		anim_file = res_man.Res_open(res);	// open anim file

		//---------------------
		#ifdef _DEBUG
		// check this this resource is actually an animation file!
		head = (_standardHeader*) anim_file;
		if (head->fileType!=ANIMATION_FILE)	// if it's not an animation file
			Con_fatal_error("Animate: %s (%d) is not an anim! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
		#endif
		//---------------------

		anim_head = FetchAnimHeader( anim_file );					// point to anim header

		//---------------------
		/*
		#ifdef _DEBUG
		// check there's at least one frame
		if (anim_head->noAnimFrames==0)
 			Con_fatal_error("Animate: %s (%d) has zero frame count! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
		#endif
		*/
		//---------------------

		ob_logic->looping		  = 1;			// now running an anim, looping back to this 'FN' call again
		ob_graphic->anim_resource = res;	// param 2 is id of animation resource

		if (reverse_flag)	// if a reverse anim
			ob_graphic->anim_pc = anim_head->noAnimFrames-1;		// start on last frame
		else				// forward anim
			ob_graphic->anim_pc = 0;								// start on first frame
 	}
 	//-------------------------------------------------------------------------------------------------------
	// otherwise, if we've received a sync, return to script immediately

	else if (Get_sync())			// returns sync value if one has been sent to current 'id', otherwise 0
	{
//		Zdebug("**sync stopped %d**", ID);
		ob_logic->looping = 0;		// if sync received, anim finishes right now (remaining on last frame)
		return(IR_CONT);			// quit anim but continue script
	}
 	//-------------------------------------------------------------------------------------------------------
	// otherwise (not first frame & not received a sync), set up the next frame of the anim
	else
	{
		anim_file = res_man.Res_open(ob_graphic->anim_resource);	// open anim file
		anim_head = FetchAnimHeader( anim_file );					// point to anim header

		if (reverse_flag)					// if a reverse anim
			ob_graphic->anim_pc--;			// decrement the anim frame number
		else								// normal forward anim
			ob_graphic->anim_pc++;			// increment the anim frame number
	}
   	//-------------------------------------------------------------------------------------------------------
	// check for end of anim

	if (reverse_flag)					// if a reverse anim
	{
		if (ob_graphic->anim_pc == 0)	// reached the first frame of the anim
			ob_logic->looping = 0;		// anim finishes on this frame
	}
	else								// normal forward anim
	{
		if (ob_graphic->anim_pc == (int32)(anim_head->noAnimFrames-1))	// reached the last frame of the anim
			ob_logic->looping = 0;		// anim finishes on this frame
	}
   	//-------------------------------------------------------------------------------------------------------
	// close the anim file

	res_man.Res_close(ob_graphic->anim_resource);	// close anim file

	//-------------------------------------------------------------------------------------------------------
	// check if we want the script to loop back & call this function again

	if (ob_logic->looping)
		return(IR_REPEAT);	// drop out of script, but call this function again next cycle
	else
		return(IR_STOP);	// drop out of script

	//-------------------------------------------------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------------------
int32 Mega_table_animate(int32 *params, uint8 reverse_flag)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to animation table

 	Object_logic	*ob_logic;
 	Object_mega		*ob_mega;
	uint32			*anim_table;
	int32			pars[5];

	//----------------------------------------------------------------------------------------
	// if this is the start of the anim, read the anim table to get the appropriate anim resource

	ob_logic = (Object_logic *) params[0];			// param 0 is pointer to logic structure

	if (ob_logic->looping==0)
	{
	 	ob_mega = (Object_mega *) params[2];		// param 2 is pointer to mega structure

		anim_table = (uint32*)params[3];
		pars[2] = anim_table[ob_mega->current_dir];	// appropriate anim resource is in 'table[direction]'
	}

	//-------------------------------------------------------------------------------------------------------
	// set up the rest of the parameters for FN_anim()

	pars[0] = params[0];
	pars[1] = params[1];
	// pars[2] only needed setting at the start of the anim

	//-------------------------------------------------------------------------------------------------------

	return Animate(pars, reverse_flag);		// call Animate() with these params
}
//-------------------------------------------------------------------------------------------------------------
int32 FN_set_frame(int32 *params)
{
	// params:	0 pointer to object's graphic structure
	//			1 resource id of animation file
	//			2 frame flag (0=first 1=last)

 	Object_graphic	*ob_graphic;
	uint8			*anim_file;
	_animHeader		*anim_head;
	int32	res = params[1];

	#ifdef _DEBUG
	_standardHeader	*head;	// for checking for correct file type
	#endif

	//---------------------
	#ifdef _DEBUG
	// check that we haven't been passed a zero resource number
	if (res==0)
		Con_fatal_error("FN_set_frame: %s (id %d) passed zero anim resource (%s line %u)", FetchObjectName(ID), ID, __FILE__, __LINE__);
	#endif
	//---------------------

	//----------------------------------------------------------------------------------------
	// open the resource (& check it's valid)

	anim_file = res_man.Res_open(res);	// open anim file

	//---------------------
	#ifdef _DEBUG
	// check this this resource is actually an animation file!
	head = (_standardHeader*) anim_file;
	if (head->fileType!=ANIMATION_FILE)	// if it's not an animation file
		Con_fatal_error("FN_set_frame: %s (%d) is not an anim! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
	#endif
	//---------------------

	anim_head = FetchAnimHeader( anim_file );	// set up pointer to the animation header

	//---------------------
	/*
	#ifdef _DEBUG
	// check there's at least one frame
	if (anim_head->noAnimFrames==0)
		Con_fatal_error("FN_set_frame: %s (%d) has zero frame count! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
	#endif
	*/
	//---------------------

	//----------------------------------------------------------------------------------------
	// set up anim resource in graphic object

	ob_graphic	= (Object_graphic *) params[0];	// param 0 is pointer to the object's graphic structure

	ob_graphic->anim_resource = res;		// param 2 is id of animation resource

	//----------------------------------------------------------------------------------------

	if (params[2])	// frame flag is non-zero
		ob_graphic->anim_pc = anim_head->noAnimFrames-1;	// last frame
	else			// frame flag is 0
		ob_graphic->anim_pc = 0;							// first frame

 	//-------------------------------------------------------------------------------------------------------
	// close the anim file

	res_man.Res_close(ob_graphic->anim_resource);	// close anim file

	//-------------------------------------------------------------------------------------------------------

	return(IR_CONT);	//	drop out of script
}

//---------------------------------------------------------------------------------------------------------------------
int32 FN_no_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

 	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= NO_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_back_par0_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

 	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= BGP0_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_back_par1_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

 	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= BGP1_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_back_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

 	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= BACK_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_sort_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

 	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= SORT_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_fore_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

 	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= FORE_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_fore_par0_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

 	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= FGP0_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_fore_par1_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0xffff0000;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= FGP1_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_shaded_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0x0000ffff;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= SHADED_SPRITE;

	// note that drivers may still shade mega frames automatically, even when not sent 'RDSPR_SHADOW'

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_unshaded_sprite(int32 *params)	
{
	// params	0 pointer to object's graphic structure

	Object_graphic	*ob_graphic = (Object_graphic *) params[0];

	ob_graphic->type &= 0x0000ffff;		// remove previous status (but don't affect the shading upper-word)
	ob_graphic->type |= UNSHADED_SPRITE;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
// Notes on PlaySmacker()

// 1st param is filename of sequence file
// 2nd param is a pointer to a null-terminated array of pointers to _movieTextObject structures


//int32 PlaySmacker(char *filename, _movieTextObject *textObjects[]);

//	typedef struct
//	{
//		uint16 startFrame;
//		uint16 endFrame;
//		_spriteInfo *textSprite;
//		_wavHeader *speech;
//	} _movieTextObject;

//---------------------------------------------------------------------------------------------------------------------
// FOR TEXT LINES IN SEQUENCE PLAYER (James22may97)

#define MAX_SEQUENCE_TEXT_LINES 15

typedef struct
{
	uint32	textNumber;
	uint16	startFrame;
	uint16	endFrame;
	mem		*text_mem;
	mem		*speech_mem;
}	_sequenceTextInfo;

static _sequenceTextInfo sequence_text_list[MAX_SEQUENCE_TEXT_LINES];
uint32 sequenceTextLines=0;		// keeps count of number of text lines to disaply during the sequence

//-------------------------------------------------------------------------------------------------------------

int32 FN_add_sequence_text(int32 *params)	// (James22may97)
{
//	params	0	text number
//			1	frame number to start the text displaying
//			2	frame number to stop the text dispalying

	#ifdef _DEBUG
	if (sequenceTextLines == MAX_SEQUENCE_TEXT_LINES)
		Con_fatal_error("FN_add_sequence_text ran out of lines (%s line %u)",__FILE__,__LINE__);
	#endif

	sequence_text_list[sequenceTextLines].textNumber	= params[0];
	sequence_text_list[sequenceTextLines].startFrame	= params[1];
	sequence_text_list[sequenceTextLines].endFrame		= params[2];
	sequenceTextLines++;

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------

// speech sample code added by James on 16july97
void CreateSequenceSpeech(_movieTextObject *sequenceText[])	// (James23may97)
{
	uint32	line;
 	_frameHeader *frame;
 	uint32	local_text;
	uint32	text_res;
	uint8	*text;
	int16	wavId;	// ie. offical text number (actor text number)
	uint8	speechRunning;
 	char	speechFile[256];
	int32	wavSize;


	for (line=0; line < sequenceTextLines; line++)	// for each sequence text line that's been logged
	{
		sequenceText[line] = new _movieTextObject;	// allocate this structure

		sequenceText[line]->startFrame	= sequence_text_list[line].startFrame;
		sequenceText[line]->endFrame	= sequence_text_list[line].endFrame;

 		//-----------------------------------------------------------
		// pull out the text line to get the official text number (for wav id)

  		text_res	= sequence_text_list[line].textNumber/SIZE;
		local_text	= sequence_text_list[line].textNumber&0xffff;

		text = FetchTextLine( res_man.Res_open(text_res), local_text );	// open text resource & get the line
		memcpy(&wavId, text, 2);	// this works on PSX & PC

		res_man.Res_close(text_res);	// now ok to close the text file

		//--------------------------------------
		// Write to walkthrough file (zebug0.txt)
		#ifdef _DEBUG
		Zdebug(0,"(%d) SEQUENCE TEXT: %s", *(uint16*)text, text+2);	// 1st word of text line is the official line number
		#endif
		//--------------------------------------
		// is it to be speech or subtitles or both?

		speechRunning=0;	// assume not running until know otherwise
		sequence_text_list[line].speech_mem = NULL;
		sequenceText[line]->speech			= NULL;

		if (speechSelected)		// speech is selected, so try that first
		{
			//------------------------------
			// set up path to speech cluster
			// first checking if we have speech1.clu or speech2.clu in current directory (for translators to test)

			#ifdef _WEBDEMO		// (James 03oct97)
				strcpy(speechFile,"SPEECH.CLU");
			#else

				#ifdef _DEBUG
					if ((res_man.WhichCd()==1) && (!access("speech1.clu",0)))	// if 0 ie. if it's there
					{
						strcpy(speechFile,"speech1.clu");
					}
					else if ((res_man.WhichCd()==2) && (!access("speech2.clu",0)))	// if 0 ie. if it's there
					{
						strcpy(speechFile,"speech2.clu");
					}
					else
					#endif	// _DEBUG
					{
						strcpy(speechFile,res_man.GetCdPath());
						strcat(speechFile,"CLUSTERS\\SPEECH.CLU");
					}

			#endif	// _WEBDEMO
			//------------------------------

			wavSize = GetCompSpeechSize(speechFile, wavId);		// returns size of decompressed wav, or 0 if wav not found
			if (wavSize)	// if we've got the wav
			{
				// allocate memory for speech buffer
				sequence_text_list[line].speech_mem = Twalloc( wavSize, MEM_locked, UID_temp );	// last param is an optional id for type of mem block

				if (sequence_text_list[line].speech_mem)	// if mem allocated ok (should be fine, but worth checking)
				{
					if (PreFetchCompSpeech(speechFile, wavId, sequence_text_list[line].speech_mem->ad) == RD_OK)	// Load speech & decompress to our buffer
					{
						Float_mem (sequence_text_list[line].speech_mem);	// now float this buffer so we can make space for the next text sprites and/or speech samples
						speechRunning=1;	// ok, we've got speech!
					}
					else	// whoops, sample didn't load & decompress for some reason...
					{
						Free_mem (sequence_text_list[line].speech_mem);	// may as well free up this speech buffer now, rather than in ClearSequenceSpeech();
						sequence_text_list[line].speech_mem = NULL;		// so we know that it's free'd
					}
				}
			}
		}

		if (subtitles || (speechRunning==0))	// if we want subtitles, or speech failed to load
		{
			text = FetchTextLine( res_man.Res_open(text_res), local_text );	// open text resource & get the line
			// mem* MakeTextSprite( uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes );
			sequence_text_list[line].text_mem = MakeTextSprite( text+2, 600, 255, speech_font_id );	// make the sprite
			// 'text+2' to skip the first 2 bytes which form the line reference number
			// NB. The mem block containing the text sprite is currently FLOATING!

			res_man.Res_close(text_res);	// ok to close the text resource now
		}
		else
		{
			sequence_text_list[line].text_mem	= NULL;
			sequenceText[line]->textSprite		= NULL;
		}
 		//--------------------------------------
	}

	sequenceText[sequenceTextLines] = NULL;	// for drivers: NULL-terminate the array of pointers to _movieTextObject's

	//---------------------------------------
  	// now lock all the memory blocks containing text sprites & speech samples
	// and set up the pointers to them, etc, for the drivers

	for (line=0; line < sequenceTextLines; line++)
	{
		// text sprites:
		if (sequence_text_list[line].text_mem)	// if we've made a text sprite for this line...
		{
			Lock_mem (sequence_text_list[line].text_mem);
			// now fill out the _spriteInfo structure in the _movieTextObjectStructure

			frame = (_frameHeader*) sequence_text_list[line].text_mem->ad;

			sequenceText[line]->textSprite = new _spriteInfo;

			sequenceText[line]->textSprite->x			= 320 - frame->width/2;	// centred
			sequenceText[line]->textSprite->y			= 440 - frame->height;	// at bottom of screen
			sequenceText[line]->textSprite->w			= frame->width;
			sequenceText[line]->textSprite->h			= frame->height;
			sequenceText[line]->textSprite->scale		= 0;
			sequenceText[line]->textSprite->scaledWidth	= 0;
			sequenceText[line]->textSprite->scaledHeight= 0;
			sequenceText[line]->textSprite->type		= RDSPR_DISPLAYALIGN+RDSPR_TRANS+RDSPR_NOCOMPRESSION;
			sequenceText[line]->textSprite->blend		= 0;
			sequenceText[line]->textSprite->data		= sequence_text_list[line].text_mem->ad+sizeof(_frameHeader);
			sequenceText[line]->textSprite->colourTable	= 0;
		}

		// speech samples:
 		if (sequence_text_list[line].speech_mem)	// if we've loaded a speech sample for this line...
		{
			Lock_mem (sequence_text_list[line].speech_mem);
			sequenceText[line]->speech = (_wavHeader *)sequence_text_list[line].speech_mem->ad;	// for drivers: set up pointer to decompressed wav in memory
		}
	}
	//---------------------------------------
}
//---------------------------------------------------------------------------------------------------------------------

// speech sample code added by James on 16july97
void ClearSequenceSpeech(_movieTextObject *textSprites[])	// (James27may97)
{
	uint32	line;

	for (line=0; line < sequenceTextLines; line++)
	{
		delete (textSprites[line]);		// free up the memory used by this _movieTextObject

		if (sequence_text_list[line].text_mem)
			Free_mem (sequence_text_list[line].text_mem);	// free up the mem block containing this text sprite

		if (sequence_text_list[line].speech_mem)
			Free_mem (sequence_text_list[line].speech_mem);	// free up the mem block containing this speech sample
	}

	sequenceTextLines=0;	// IMPORTANT! Reset the line count ready for the next sequence!
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_smacker_lead_in(int32 *params)	// James(21july97)
{
	uint8 *leadIn;
	uint32 rv;
#ifdef _DEBUG
	_standardHeader *header;
#endif


	leadIn = res_man.Res_open(params[0]);

	//-----------------------------------------
	#ifdef _DEBUG
	header = (_standardHeader*)leadIn;
	if (header->fileType != WAV_FILE)
		Con_fatal_error("FN_smacker_lead_in() given invalid resource (%s line %u)",__FILE__,__LINE__);
	#endif
	//-----------------------------------------

	leadIn += sizeof(_standardHeader);
	rv = PlayFx( 0, leadIn, 0, 0, RDSE_FXLEADIN );		// wav data gets copied to sound memory

	//-----------------------------------------
	#ifdef _DEBUG
	if (rv)
		Zdebug("SFX ERROR: PlayFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
	#endif
	//-----------------------------------------

	res_man.Res_close(params[0]);

	FN_stop_music(NULL);	// fade out any music that is currently playing (James22july97)

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_smacker_lead_out(int32 *params)	// James(21july97)
{
	smackerLeadOut = params[0];	// ready for use in FN_play_sequence

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------

int32 FN_play_sequence(int32 *params)	// James(09apr97)
{
	// params	0 pointer to null-terminated ascii filename
	// params	1 number of frames in the sequence, used for PSX.

	char	filename[30];
 	uint32	rv;	// drivers return value
	_movieTextObject *sequenceSpeechArray[MAX_SEQUENCE_TEXT_LINES+1];
	uint8 *leadOut = NULL;
#ifdef _DEBUG
	_standardHeader *header;
#endif

#ifdef _MUTE_SMACKERS
	uint32 musicMuteStatus;
#endif

 	//----------------------------------
	// In the case where smackers are crashing but the rest of the game is fine,
	// the "Skip Smackers" executable will display a message giving the smacker
	// file name rather than actually playing it.
	// Then the user can switch tasks & view the smacker using the stand-alone player!
	// This has got to be the biggest fudge in the history of computer games.

	#ifdef _SKIP_SMACKERS
		uint8	message[30];

		sprintf((char*)message,"SKIPPING SMACKER: \"%s.smk\"", (char *)params[0]);
		DisplayMsg(message, 3);	// 3 is duration in seconds
		RemoveMsg();
		sequenceTextLines=0;	// IMPORTANT - clear this so it doesn't overflow!
		return(IR_CONT);		//	continue script now; don't play smacker!
	#endif
	//----------------------------------
	// Another attempt to prevent the smacker crash
	// This time muting the music during the smacker
	// - in case that's what's causing the crash

	#ifdef _MUTE_SMACKERS
		musicMuteStatus = IsMusicMute();	// keep note of what mute status was to start with
		MuteMusic(1);	// mute the music - we'll set it back to 'musicMuteStatus' later
	#endif
	//----------------------------------

	Zdebug("FN_play_sequence(\"%s\");", params[0]);

	//--------------------------------------------------
	// check that the name paseed from script is 8 chars or less
	#ifdef _DEBUG
	if (strlen((char *)params[0]) > 8)
		Con_fatal_error("Sequence filename too long (%s line %u)",__FILE__,__LINE__);
	#endif
	//--------------------------------------------------
	// add the appropriate file extension & play it

	#ifdef _WEBDEMO		// (James 01oct97)
		sprintf(filename,"%s.smk", (char *)params[0]);
	#else
		sprintf(filename,"%sSMACKS\\%s.smk", res_man.GetCdPath(), (char *)params[0]);
	#endif	// _WEBDEMO

	//--------------------------------------
	// Write to walkthrough file (zebug0.txt)

	#ifdef _DEBUG
 	Zdebug(0,"PLAYING SEQUENCE \"%s\"", filename);
	#endif
   	//--------------------------------------
	// now create the text sprites, if any (James27may97)

	if (sequenceTextLines)	// if we have some text to accompany this sequence
		CreateSequenceSpeech(sequenceSpeechArray);

 	//--------------------------------------
	// open the lead-out music resource, if there is one

	if (smackerLeadOut)
	{
		leadOut = res_man.Res_open(smackerLeadOut);

	 	//---------------------------
		#ifdef _DEBUG
		header = (_standardHeader*)leadOut;
		if (header->fileType != WAV_FILE)
			Con_fatal_error("FN_smacker_lead_out() given invalid resource (%s line %u)",__FILE__,__LINE__);
		#endif
 	 	//---------------------------

		leadOut += sizeof(_standardHeader);
	}

 	//--------------------------------------
	// play the smacker

	FN_stop_music(NULL);	// don't want to carry on streaming game music when smacker starts!
	PauseFxForSequence();	// pause sfx during sequence, except the one used for lead-in music

	if (sequenceTextLines)	// if we have some text to accompany this sequence
		rv = PlaySmacker(filename, sequenceSpeechArray, leadOut);
	else
		rv = PlaySmacker(filename, NULL, leadOut);

/* we don't have this call - khalek
	if (ServiceWindows() == RDERR_APPCLOSED)	// if we pressed Ctrl-Q during the smacker
	{
		Close_game();	//close engine systems down
		RestoreDisplay();
		CloseAppWindow();
		exit(0);	//quit the game
	}
*/

	UnpauseFx();	// unpause sound fx again, in case we're staying in same location

 	//--------------------------------------
	// close the lead-out music resource

 	if (smackerLeadOut)
	{
		res_man.Res_close(smackerLeadOut);
		smackerLeadOut=0;
	}
	//--------------------------
	// check the error return-value
	#ifdef _DEBUG
	if (rv)
		Zdebug("PlaySmacker(\"%s\") returned 0x%.8x", filename, rv);
	#endif
	//--------------------------
	// now clear the text sprites, if any (James27may97)

	if (sequenceTextLines)	// if we have some text/speech to accompany this sequence
		ClearSequenceSpeech(sequenceSpeechArray);

	//--------------------------
	// now clear the screen in case the Sequence was quitted (using ESC) rather than fading down to black

	EraseBackBuffer();				// for hardware rendering
	EraseSoftwareScreenBuffer();	// for software rendering
	FlipScreens();					// to get the new blank screen visible

 	//--------------------------------------------------
	// zero the entire palette in case we're about to fade up!

	_palEntry	 pal[256];

	memset(pal, 0, 256*sizeof(_palEntry));
	SetPalette(0, 256, (uint8 *) pal, RDPAL_INSTANT);
 	//--------------------------------------------------

  	Zdebug("FN_play_sequence FINISHED");

 	//--------------------------------------------------
	#ifdef _MUTE_SMACKERS
		MuteMusic(musicMuteStatus);	// set mute status back to what it was before the sequence
	#endif
	//----------------------------------


	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------

--- NEW FILE: anims.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/anims.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_ANIM_S
#define	_ANIM_S


#include "driver/driver96.h"

int32 FN_anim(int32 *params);
int32 FN_reverse_anim(int32 *params);
int32 FN_mega_table_anim(int32 *params);
int32 FN_reverse_mega_table_anim(int32 *params);
int32 FN_set_frame(int32 *params);
int32 FN_no_sprite(int32 *params);
int32 FN_back_sprite(int32 *params);
int32 FN_sort_sprite(int32 *params);
int32 FN_fore_sprite(int32 *params);

#endif

--- NEW FILE: build_display.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/build_display.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

[...1216 lines suppressed...]
	{
		rv = CloseLightMask();

		if (rv)
			ExitWithReport("Driver Error %.8x [%s line %u]", rv, __FILE__, __LINE__);

		this_screen.mask_flag = 0;
	}

	return (IR_CONT);
}


//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------


--- NEW FILE: build_display.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/build_display.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_BUILD_DISPLAY
#define	_BUILD_DISPLAY

#include "driver/driver96.h"


typedef	struct	//structure filled out by each object to register its graphic printing requrements
{
	int16	x;
	int16	y;
	uint16	scaled_width;
	uint16	scaled_height;
	int16	sort_y;
	uint32	anim_resource;
	uint16	anim_pc;
	uint16	scale;	//denotes a scaling sprite at print time - and holds the scaling value for the shrink routine
	uint16	layer_number;	//non zero means this item is a layer - retrieve from background layer and send to special renderer
	uint8	shadingFlag;	// non zero means we want this frame to be affected by the shading mask

//	uint32	write_mouse_list;	//if none zero the shrinker should write coordinates to this mouse_list number

} buildit;

// declared externally so that debug.cpp can display these in the info
#define	MAX_bgp0_sprites	6
#define	MAX_bgp1_sprites	6
#define	MAX_back_sprites	30
#define	MAX_sort_sprites	30
#define	MAX_fore_sprites	30
#define	MAX_fgp0_sprites	6
#define	MAX_fgp1_sprites	6

// declared externally so that debug.cpp can display these in the info
extern	uint32	cur_bgp0;
extern	uint32	cur_bgp1;
extern	uint32	cur_back;
extern	uint32	cur_sort;
extern	uint32	cur_fore;
extern	uint32	cur_fgp0;
extern	uint32	cur_fgp1;

#ifdef _DEBUG
extern char largest_layer_info[128];
extern char largest_sprite_info[128];
#endif

// the only build list needed externally - by layers.cpp - for adding layers to sort list
extern	buildit	sort_list[];

// function prototypes needed externally
void	Reset_render_lists(void);
void	Build_display(void);	//Tony21Sept96
int32   FN_fade_down(int32 *params);	//Tony5Dec96
int32	FN_fade_up(int32 *params);		// Chris 15May97
void	Process_image(buildit *build_unit);	// (5nov96 JEL)
void	DisplayMsg( uint8 *text, int time ); // (Chris 15May97)
void	RemoveMsg(void);
void	SetFullPalette(int32 palRes);		// James17jun97

extern	uint32	fps;		// needed by debug.cpp for displaying as part of top-screen info

#endif

--- NEW FILE: console.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/console.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

[...1302 lines suppressed...]
			target = event_list[j].id;
			script = event_list[j].interact_id;

			Print_to_console("slot %d: id = %s (%d)", j, FetchObjectName(target), target);
			Print_to_console("         script = %s (%d) pos %d", FetchObjectName(script/65536), script/65536, script%65536);
		}
	}
}
//------------------------------------------------------------------------------------

#else // not debug

void	Print_to_console(char *format,...) {};
void	Temp_print_to_console(char *format,...) {};
void	Clear_console_line(void) {};
void	Scroll_console(void) {};
void	Init_console(void) {};
void	StartConsole(void) {};

#endif	// _DEBUG

--- NEW FILE: console.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/console.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	C_ONSOLE_H
#define	C_ONSOLE_H

#include "driver/driver96.h"
#include "memory.h"

#ifdef _DEBUG

void	Init_console(void);	//Tony9Sept96
uint32	One_console(void);	//Tony12Aug96
void	StartConsole(void);	//Tony12Aug96
void	EndConsole(void);	//Tony9Oct96

void	Con_fatal_error(char *format,...);
void	Print_to_console(char *format,...);	//Tony13Aug96
void	Temp_print_to_console(char *format,...);	//Tony13Aug96
void	Scroll_console(void);	//Tony13Aug96
void	Clear_console_line(void);	//Tony13Aug96

extern	mem	*console_sprite;
extern	uint32	con_y;
extern	uint32	con_depth;
extern	uint32	con_width;

extern uint8 grabbingSequences;
extern uint8 wantSfxDebug;	// sfx debug file enabled/disabled from console


#else	// _DEBUG
/*
#define	Init_console	NULL
#define	One_console		NULL
#define	StartConsole	NULL
#define	EndConsole		NULL
*/

void	Init_console(void);
uint32	One_console(void);	
void	StartConsole(void);
void	EndConsole(void);

// 'Con_fatal_error' commands map to ExitWithReport
// so we show errors in a window rather than our development game console
#define Con_fatal_error		ExitWithReport

//#define	Print_to_console		NULL
//#define	Temp_print_to_console	NULL
//#define	Clear_console_line		NULL
//#define	Scroll_console			NULL
void	Print_to_console(char *format,...);
void	Temp_print_to_console(char *format,...);
void	Clear_console_line(void);
void	Scroll_console(void);
//#define	Var_check			NULL
//#define	Var_set				NULL

#endif	// _DEBUG

extern	uint32	console_status;


#endif

--- NEW FILE: controls.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/controls.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

[...2878 lines suppressed...]

				case 0:
					RenderHard();
					SetUpBackgroundLayers();	// InitialiseBackgroundLayer for each layer! (see layers.cpp)
					break;
			}
			break;
		//-------------------------------
	}

	// update our global variable - which needs to be checked when dimming the palette
	// in PauseGame() in sword2.cpp (since palette-matching cannot be done with dimmed palette
	// so we turn down one notch while dimmed, if at top level)
	current_graphics_level = newLevel;
}
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------


--- NEW FILE: controls.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/controls.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_CONTROL_S
#define	_CONTROL_S

#include "common/scummsys.h"
//#include "src\driver96.h"

uint32	Restore_control(void);	//Tony20Mar97
void	Save_control(void);	//Tony1Apr97
void	Quit_control(void);	//Tony2Apr97
void	Restart_control(void);	//Tony4Apr97
void	Option_control(void);	//Pete5Jun97
int32   ReadOptionSettings(void);	//Pete10Jun97
void	UpdateGraphicsLevel(uint8 oldLevel, uint8 newLevel);	// (James13jun97)

extern uint8 subtitles;		// text selected
extern uint8 speechSelected;
extern uint8 current_graphics_level;

#endif

--- NEW FILE: credits.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/credits.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef _Credits_h_
#define _Credits_h_

#include "driver/driver96.h"

// int32 __declspec( dllexport ) Credits(_drvDrawStatus *pDrawStatus, _drvSoundStatus *pSoundStatus, const char *cdPath, BOOL smoke, BOOL *pAppFocus, _drvKeyStatus *pKeyStatus);
int32 Credits(_drvDrawStatus *pDrawStatus, _drvSoundStatus *pSoundStatus, const char *cdPath, BOOL smoke, BOOL *pAppFocus, _drvKeyStatus *pKeyStatus);

#endif

--- NEW FILE: debug.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/debug.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//--------------------------------------------------------------------------------------
#include <stdarg.h> // for ExitWithReport, which stays in RELEASE version
#include <stdio.h>

#include "driver/driver96.h"
#include "debug.h"
//--------------------------------------------------------------------------------------

#if _DEBUG  // this whole file (except ExitWithReport) only included on debug versions

#include <stdlib.h>

#include "build_display.h"	// for 'fps' (frames-per-second counter)
#include "console.h"
#include "defs.h"
#include "events.h"	// for CountEvents()
#include "layers.h"
#include "logic.h"
#include "maketext.h"
#include "mem_view.h"
#include "mouse.h"
#include "protocol.h"
#include "resman.h"
#include "router.h"	// for PlotWalkGrid()
#include "speech.h"	// for 'officialTextNumber' and 'speechScriptWaiting'

//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// global variables
uint8 displayDebugText		= 0;	// "INFO"		0=off; 1=on
uint8 displayWalkGrid		= 0;	// "WALKGRID"
uint8 displayMouseMarker	= 0;	// "MOUSE"
uint8 displayTime			= 0;	// "TIME"
uint8 displayPlayerMarker	= 0;	// "PLAYER"
uint8 displayTextNumbers	= 0;	// "TEXT"
uint8 renderSkip			= 0;	// Toggled on 'S' key - to render only 1 in 4 frames, to speed up game

uint8 definingRectangles	= 0;	// "RECT"
uint8 draggingRectangle		= 0;	// 0=waiting to start new rect; 1=currently dragging a rectangle
int16 rect_x1	= 0;
int16 rect_y1	= 0;
int16 rect_x2	= 0;
int16 rect_y2	= 0;
uint8 rectFlicker=0;

uint8 testingSnR = 0;				// "SAVEREST" - for system to kill all object resources (except player) in FN_add_human()

int32 startTime = 0;				// "TIMEON" & "TIMEOFF" - system start time.
int32 gameCycle = 0;				// Counter for game clocks.

int32 textNumber = 0;				// current system text line number

int32 showVar[MAX_SHOWVARS];		// "SHOWVAR"

Object_graphic playerGraphic;		// for displaying player object's current graphical info
uint32 player_graphic_no_frames=0;	// no. of frames in currently displayed anim

uint8 debug_text_blocks[MAX_DEBUG_TEXT_BLOCKS];

//--------------------------------------------------------------------------------------
// function prototypes

void Clear_debug_text_blocks( void );
void Make_debug_text_block( char *text, int16 x, int16 y );
void Plot_cross_hair( int16 x, int16 y, uint8 pen );
void DrawRect( int16 x, int16 y, int16 x2, int16 y2, uint8 pen );
//--------------------------------------------------------------------------------------
#endif	// _DEBUG

// THIS FUNCTION STAYS IN THE RELEASE VERSION
// IN FACT, CON_FATAL_ERROR IS MAPPED TO THIS AS WELL, SO WE HAVE A MORE PRESENTABLE ERROR REPORT
void ExitWithReport(char *format,...)	// (6dec96 JEL)
{
	//	Send a printf type string to Paul's windows routine
	char buf[500];
	va_list arg_ptr;	// Variable argument pointer

	va_start(arg_ptr,format);


	vsprintf(buf, format, arg_ptr);
	Zdebug("%s",buf);		// send output to 'debug.txt' as well, just for the record

	while (GetFadeStatus())	// wait for fade to finish before calling RestoreDisplay()
		ServiceWindows();

	RestoreDisplay();
	ReportFatalError((uint8 *)buf);	// display message box
	CloseAppWindow();
	while (ServiceWindows() != RDERR_APPCLOSED);

	exit(0);
}

#if _DEBUG	// all other functions only for _DEBUG version
//--------------------------------------------------------------------------------------
void Zdebug(char *format,...)	//Tony's special debug logging file March96
{
//	Write a printf type string to a debug file

	va_list		arg_ptr;			// Variable argument pointer
	FILE *		debug_filep=0;			// Debug file pointer
	static int	first_debug = 1;		// Flag for first time this is used

	va_start(arg_ptr,format);

	if (first_debug)					//First time round delete any previous debug file
	{
		unlink("debug.txt");
		first_debug = 0;
	}

	debug_filep = fopen("debug.txt","a+t");

	if (debug_filep != NULL)	// if it could be opened
	{
		vfprintf(debug_filep, format, arg_ptr);
		fprintf(debug_filep,"\n");

		fclose(debug_filep);
	}
}

//--------------------------------------------------------------------------------------
void Zdebug(uint32	stream, char *format,...)	//Tony's special debug logging file March96
{
//	Write a printf type string to a debug file

	va_list		arg_ptr;			// Variable argument pointer
	FILE *		debug_filep=0;			// Debug file pointer
	static int	first = 1;		// Flag for first time this is used
	int	j;
	static	int	first_debugs[100];



	if	(first==1)	//first time run then reset the states
	{	for	(j=0;j<100;j++)
			first_debugs[j]=0;

		first=0;
	}




	char	name[20];


	sprintf(name, "debug%d.txt", stream);

	va_start(arg_ptr,format);

	if (!first_debugs[stream])					//First time round delete any previous debug file
	{
		unlink(name);
		first_debugs[stream] = 1;
	}

	debug_filep = fopen(name,"a+t");

	if (debug_filep != NULL)	// if it could be opened
	{
		vfprintf(debug_filep, format, arg_ptr);
		fprintf(debug_filep,"\n");

		fclose(debug_filep);
	}
}
//--------------------------------------------------------------------------------------
void Clear_debug_text_blocks( void )	// JAMES
{
	uint8 blockNo=0;


	while ((blockNo < MAX_DEBUG_TEXT_BLOCKS) && (debug_text_blocks[blockNo] > 0))
	{
		Kill_text_bloc(debug_text_blocks[blockNo]);	// kill the system text block
		debug_text_blocks[blockNo] = 0;				// clear this element of our array of block numbers
		blockNo++;
	}
}
//--------------------------------------------------------------------------------------
void Make_debug_text_block( char *text, int16 x, int16 y)	// JAMES
{
	uint8 blockNo=0;


	while ((blockNo < MAX_DEBUG_TEXT_BLOCKS) && (debug_text_blocks[blockNo] > 0))
		blockNo++;

	if (blockNo == MAX_DEBUG_TEXT_BLOCKS)
		Con_fatal_error("ERROR: debug_text_blocks[] full in Make_debug_text_block() at line %d in file \"%s\"",__LINE__,__FILE__);

	debug_text_blocks[blockNo] = Build_new_block( (uint8 *)text, x, y, 640-x, 0, RDSPR_DISPLAYALIGN, CONSOLE_FONT_ID, NO_JUSTIFICATION);
}

//--------------------------------------------------------------------------------------
//
//
// PC Build_debug_info
//
//
//--------------------------------------------------------------------------------------
void Build_debug_text( void )	// JAMES
{
	char buf[128];

	int32 showVarNo;	// for variable watching
	int32 showVarPos;
	int32 varNo;
	int32 *varTable;


	Clear_debug_text_blocks();	// clear the array of text block numbers for the debug text

	//-------------------------------------------------------------------
	// mouse coords
/*
	if (displayMouseMarker)	// print mouse coords beside mouse-marker, if it's being displayed
	{
		sprintf (buf, "%d,%d", mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y);
		if (mousex>560)
			Make_debug_text_block (buf, mousex-50, mousey-15);
		else
			Make_debug_text_block (buf, mousex+5, mousey-15);
	}
*/
	//-------------------------------------------------------------------
	// mouse area coords

	if (draggingRectangle || SYSTEM_TESTING_ANIMS)	// defining a mouse area the easy way, by creating a box on-screen
	{
		rectFlicker = 1-rectFlicker;	// so we can see what's behind the lines

		sprintf (buf, "x1=%d", rect_x1);
		Make_debug_text_block (buf, 0, 120);

		sprintf (buf, "y1=%d", rect_y1);
		Make_debug_text_block (buf, 0, 135);

		sprintf (buf, "x2=%d", rect_x2);
		Make_debug_text_block (buf, 0, 150);

		sprintf (buf, "y2=%d", rect_y2);
		Make_debug_text_block (buf, 0, 165);
	}
	//-------------------------------------------------------------------
	// testingSnR indicator

	if (testingSnR)		// see FN_add_human()
	{
		sprintf (buf, "TESTING LOGIC STABILITY!");
		Make_debug_text_block (buf, 0, 105);
	}
	//---------------------------------------------
	// speed-up indicator

	if (renderSkip)		// see sword.cpp
	{
		sprintf (buf, "SKIPPING FRAMES FOR SPEED-UP!");
		Make_debug_text_block (buf, 0, 120);
	}
	//---------------------------------------------
	// debug info at top of screen - enabled/disabled as one complete unit

	if (displayTime)
	{
		int32 time = timeGetTime();

		if ((time - startTime) / 1000 >= 10000)
			startTime = time;

		time -= startTime;
		sprintf(buf, "Time %.2d:%.2d:%.2d.%.3d",(time / 3600000) % 60,(time / 60000) % 60, (time / 1000) % 60,time%1000);
		Make_debug_text_block(buf, 500, 360);
		sprintf(buf, "Game %d", gameCycle);
		Make_debug_text_block(buf, 500, 380);
	}
	//---------------------------------------------
   	// current text number & speech-sample resource id

	if (displayTextNumbers)
	{
		if (textNumber)
		{
			if (SYSTEM_TESTING_TEXT)
			{
				if (SYSTEM_WANT_PREVIOUS_LINE)
					sprintf (buf, "backwards");
				else
 					sprintf (buf, "forwards");

				Make_debug_text_block (buf, 0, 340);
			}

			sprintf (buf, "res: %d", textNumber/SIZE);
			Make_debug_text_block (buf, 0, 355);

			sprintf (buf, "pos: %d", textNumber&0xffff);
			Make_debug_text_block (buf, 0, 370);

 			sprintf (buf, "TEXT: %d", officialTextNumber);
			Make_debug_text_block (buf, 0, 385);

		}
	}
	//---------------------------------------------
	// resource number currently being checking for animation

	if (SYSTEM_TESTING_ANIMS)
	{
		sprintf (buf, "trying resource %d", SYSTEM_TESTING_ANIMS);
		Make_debug_text_block (buf, 0, 90);
	}
	//---------------------------------------------

	// general debug info

	if (displayDebugText)
	{
		//---------------------------------------------
/*
		// CD in use
		sprintf (buf, "CD-%d", currentCD);
		Make_debug_text_block (buf, 0, 0);
*/
		//---------------------------------------------
		// mouse coords & object pointed to

		if (CLICKED_ID)
			sprintf (buf, "last click at %d,%d (id %d: %s)", MOUSE_X, MOUSE_Y, CLICKED_ID, FetchObjectName(CLICKED_ID));
		else
			sprintf (buf, "last click at %d,%d (---)", MOUSE_X, MOUSE_Y);

 		Make_debug_text_block (buf, 0, 15);

		if (mouse_touching)
			sprintf (buf, "mouse %d,%d (id %d: %s)", mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y, mouse_touching, FetchObjectName(mouse_touching));
		else
			sprintf (buf, "mouse %d,%d (not touching)", mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y);

		Make_debug_text_block (buf, 0, 30);

		//---------------------------------------------
 		// player coords & graphic info

		if (playerGraphic.anim_resource)	// if player objct has a graphic
			sprintf (buf, "player %d,%d %s (%d) #%d/%d", this_screen.player_feet_x, this_screen.player_feet_y, FetchObjectName(playerGraphic.anim_resource), playerGraphic.anim_resource, playerGraphic.anim_pc, player_graphic_no_frames);
		else
			sprintf (buf, "player %d,%d --- %d", this_screen.player_feet_x, this_screen.player_feet_y, playerGraphic.anim_pc);

		Make_debug_text_block (buf, 0, 45);

		//---------------------------------------------
 		// frames-per-second counter

		sprintf (buf, "fps %d", fps);
		Make_debug_text_block (buf, 440, 0);

		//---------------------------------------------
 		// location number

		sprintf (buf, "location=%d", LOCATION);
		Make_debug_text_block (buf, 440, 15);

		//---------------------------------------------
 		// "result" variable

		sprintf (buf, "result=%d", RESULT);
		Make_debug_text_block (buf, 440, 30);

		//---------------------------------------------
 		// no. of events in event list

		sprintf (buf, "events=%d", CountEvents());
		Make_debug_text_block (buf, 440, 45);

		//---------------------------------------------
		// sprite list usage

		sprintf (buf, "bgp0: %d/%d",cur_bgp0,MAX_bgp0_sprites);
		Make_debug_text_block (buf, 560, 0);

		sprintf (buf, "bgp1: %d/%d",cur_bgp1,MAX_bgp1_sprites);
		Make_debug_text_block (buf, 560, 15);

		sprintf (buf, "back: %d/%d",cur_back,MAX_back_sprites);
		Make_debug_text_block (buf, 560, 30);

		sprintf (buf, "sort: %d/%d",cur_sort,MAX_sort_sprites);
		Make_debug_text_block (buf, 560, 45);

		sprintf (buf, "fore: %d/%d",cur_fore,MAX_fore_sprites);
		Make_debug_text_block (buf, 560, 60);

		sprintf (buf, "fgp0: %d/%d",cur_fgp0,MAX_fgp0_sprites);
		Make_debug_text_block (buf, 560, 75);

		sprintf (buf, "fgp1: %d/%d",cur_fgp1,MAX_fgp1_sprites);
		Make_debug_text_block (buf, 560, 90);

		//---------------------------------------------
		// largest layer & sprite

		// NB. Strings already constructed in Build_display.cpp
		Make_debug_text_block (largest_layer_info, 0, 60);
		Make_debug_text_block (largest_sprite_info, 0, 75);

		//---------------------------------------------
		// "waiting for person" indicator - set form FN_they_do & FN_they_do_we_wait

		if (speechScriptWaiting)
		{
			sprintf (buf, "script waiting for %s (%d)", FetchObjectName(speechScriptWaiting), speechScriptWaiting);
			Make_debug_text_block (buf, 0, 90);
		}
 		//---------------------------------------------
		// variable watch display

		showVarPos = 115;	// y-coord for first showVar

		varTable = (int32*)(res_man.Res_open(1) + sizeof(_standardHeader));	// res 1 is the global variables resource

		for (showVarNo=0; showVarNo < MAX_SHOWVARS; showVarNo++)
		{
			varNo = showVar[showVarNo];	// get variable number

			if (varNo)	// if non-zero ie. cannot watch 'id' but not needed anyway because it changes throughout the logic loop
			{
				sprintf (buf, "var(%d) = %d", varNo, varTable[varNo]);
				Make_debug_text_block (buf, 530, showVarPos);
				showVarPos += 15;	// next line down
			}
		}

		res_man.Res_close(1);	// close global variables resource

		//---------------------------------------------
		// memory indicator - this should come last, to show all the sprite blocks above!

		Create_mem_string (buf);
		Make_debug_text_block (buf, 0, 0);

		//---------------------------------------------
	}
	
	//-------------------------------------------------------------------
	

}

//--------------------------------------------------------------------------------------
void Draw_debug_graphics( void )	// JAMES (08apr97)
{
 	//-------------------------------
	// walk-grid

	if (displayWalkGrid)
		PlotWalkGrid(); 

 	//-------------------------------
	// player feet coord marker

	if (displayPlayerMarker)
		Plot_cross_hair (this_screen.player_feet_x, this_screen.player_feet_y, 215);

	//-------------------------------------------------------------------
	// mouse marker & coords

	if (displayMouseMarker)
		Plot_cross_hair (mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y, 215);

	//-------------------------------------------------------------------
   	// mouse area rectangle / sprite box rectangle when testing anims

	if (SYSTEM_TESTING_ANIMS)
	{
		DrawRect(rect_x1, rect_y1, rect_x2, rect_y2, 184);	// draw box around current frame
	}
	else if (draggingRectangle)		// defining a mouse area the easy way, by creating a box on-screen
	{
		if (rectFlicker)
			DrawRect(rect_x1, rect_y1, rect_x2, rect_y2, 184);
	}
	//-------------------------------------------------------------------
}
//--------------------------------------------------------------------------------------
void Plot_cross_hair( int16 x, int16 y, uint8 pen )
{
	PlotPoint(x,y,pen);			// driver function

	DrawLine(x-2,y,x-5,y,pen);	// driver function
	DrawLine(x+2,y,x+5,y,pen);

	DrawLine(x,y-2,x,y-5,pen);
	DrawLine(x,y+2,x,y+5,pen);
}
//--------------------------------------------------------------------------------------
void DrawRect( int16 x1, int16 y1, int16 x2, int16 y2, uint8 pen )
{
	DrawLine(x1,y1,x2,y1,pen);	// top edge
	DrawLine(x1,y2,x2,y2,pen);	// bottom edge
	DrawLine(x1,y1,x1,y2,pen);	// left edge
	DrawLine(x2,y1,x2,y2,pen);	// right edge
}
//--------------------------------------------------------------------------------------
void Print_current_info(void)	//Tony30Oct96
{
//prints general stuff about the screen, etc.


	if	(this_screen.background_layer_id)
	{	Print_to_console(" background layer id %d", this_screen.background_layer_id);
		Print_to_console(" %d wide, %d high", this_screen.screen_wide, this_screen.screen_deep);
		Print_to_console(" %d normal layers", this_screen.number_of_layers);

		LLogic.Examine_run_list();

	}
	else
		Print_to_console(" no screen");


	Scroll_console();
}
//--------------------------------------------------------------------------------------
#else // not debug

void Draw_debug_graphics(void) {};

#endif	// _DEBUG
//--------------------------------------------------------------------------------------

--- NEW FILE: debug.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/debug.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	D_DEBUG
#define D_DEBUG

//--------------------------------------------------------------------------------------
#ifdef _DEBUG	// this whole file only included on debug versions


//#include "src\driver96.h"
#include "driver.h"
#include "object.h"

#define MAX_DEBUG_TEXT_BLOCKS	50

extern	uint8 displayDebugText;	// 0=off; 1=on
extern	uint8 displayWalkGrid;
extern	uint8 displayMouseMarker;
extern	uint8 displayPlayerMarker;
extern	uint8 displayTime;
extern	uint8 displayTextNumbers;
extern	uint8 definingRectangles;
extern	uint8 draggingRectangle;
extern	uint8 displayTime;
extern	int32 startTime;
extern	int32 gameCycle;
extern	uint8 renderSkip;

extern	int16 rect_x1;
extern	int16 rect_y1;
extern	int16 rect_x2;
extern	int16 rect_y2;

extern	uint8 testingSnR;

extern	int32 textNumber;

extern Object_graphic playerGraphic;
extern uint32 player_graphic_no_frames;



#define MAX_SHOWVARS 15
extern	int32 showVar[MAX_SHOWVARS];


void Zdebug(char * ,...);		// Tony's special debug logging file March96
void Zdebug(uint32	stream, char *format,...);
void Build_debug_text(void);	// James's debug text display
void Draw_debug_graphics(void);	// James's debug graphics display

void Print_current_info(void);	//Tony30Oct96


#else	// ie. not _DEBUG

/* gcc doesn't like this - khalek
#define Zdebug				NULL
#define Build_debug_text	NULL
#define Draw_debug_graphics	NULL
#define Print_current_info	NULL
*/

void Zdebug(char * ,...);		// Tony's special debug logging file March96
void Build_debug_text(void);	// James's debug text display
void Draw_debug_graphics(void);	// James's debug graphics display

#endif	// _DEBUG	// this whole file only included on debug versions
//--------------------------------------------------------------------------------------

void ExitWithReport(char *format,...);	// (6dec96 JEL) IN BOTH DEBUG & RELEASE VERSIONS



#endif	//D_DEBUG

--- NEW FILE: defs.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/defs.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	DEFS
#define	DEFS

#include "header.h"
#include "resman.h"

//--------------------------------------------------------------------------------------
#define	SIZE	0x10000	//65536 items per section
#define	NuSIZE	0xffff	//& with this

//--------------------------------------------------------------------------------------
//global variable references

// NB. 4 * <number from linc's Global Variables list>

#define	ID						*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader))
#define	RESULT					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1)	// 4 * <number from linc's Global Variables list>
#define	PLAYER_ACTION			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 2)
//#define	CUR_PLAYER_ID			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 3)
#define	CUR_PLAYER_ID			8	// always 8 (George object used for Nico player character as well)
#define	PLAYER_ID				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 305)
#define	TALK_FLAG				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 13)

#define	MOUSE_X					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 4)
#define	MOUSE_Y					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 5)
#define	LEFT_BUTTON				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 109)
#define	RIGHT_BUTTON			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 110)
#define	CLICKED_ID				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 178)

#define	IN_SUBJECT				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 6)
#define	COMBINE_BASE			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 7)
#define	OBJECT_HELD				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 14)

#define	SPEECH_ID				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 9)
#define	INS1					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 10)
#define	INS2					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 11)
#define	INS3					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 12)
#define	INS4					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 60)
#define	INS5					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 61)
#define	INS_COMMAND				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 59)

#define	PLAYER_FEET_X			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 141)
#define	PLAYER_FEET_Y			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 142)
#define	PLAYER_CUR_DIR			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 937)

#define	LOCATION				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 62)	// for debug.cpp

#define	SCROLL_X				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 345)	// so scripts can force scroll offsets
#define	SCROLL_Y				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 346)	// so scripts can force scroll offsets

#define	EXIT_CLICK_ID			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 710)
#define	EXIT_FADING				*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 713)

#define	SYSTEM_TESTING_ANIMS	*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 912)
#define	SYSTEM_TESTING_TEXT		*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1230)
#define	SYSTEM_WANT_PREVIOUS_LINE	*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1245)

#define	MOUSE_AVAILABLE			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 686)	// 1=on 0=off (set in FN_add_human & FN_no_human)

#define	AUTO_SELECTED			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1115)	// used in FN_choose

#define	CHOOSER_COUNT_FLAG		*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 15)	// see FN_start_conversation & FN_chooser

#define	DEMO					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1153)	//signifies a demo mode

#define PSXFLAG					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1173) // Indicates to script whether this is the Playstation version.

#define	DEAD					*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1256)	//=1 =dead
#define SPEECHANIMFLAG			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1278) // If set indicates that the speech anim is to run through only once.

#define SCROLL_OFFSET_X			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1314) //for the engine

#define GAME_LANGUAGE			*(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 111)  //for the poor PSX so it knows what language is running.
//--------------------------------------------------------------------------------------
//resource id's of pouse mointers. It's pretty much safe to do it like this

#define	NORMAL_MOUSE_ID				17
#define	SCROLL_LEFT_MOUSE_ID		1440
#define	SCROLL_RIGHT_MOUSE_ID		1441

//--------------------------------------------------------------------------------------
// Console Font - does not use game text - only English required
#define	CONSOLE_FONT_ID				340		// ConsFont

// Speech Font
#define ENGLISH_SPEECH_FONT_ID		341		// SpchFont
#define FINNISH_SPEECH_FONT_ID		956		// FinSpcFn
#define POLISH_SPEECH_FONT_ID		955		// PolSpcFn

// Control Panel Font (and un-selected savegame descriptions)
#define ENGLISH_CONTROLS_FONT_ID	2005	// Sfont
#define FINNISH_CONTROLS_FONT_ID	959		// FinSavFn
#define POLISH_CONTROLS_FONT_ID		3686	// PolSavFn

// Red Font (for selected savegame descriptions)
#define ENGLISH_RED_FONT_ID	2005	//		1998	// Redfont
#define FINNISH_RED_FONT_ID	959	//		960		// FinRedFn
#define POLISH_RED_FONT_ID		3686	//	3688	// PolRedFn

//--------------------------------------------------------------------------------------
// Control panel palette resource id

#define CONTROL_PANEL_PALETTE	261

//--------------------------------------------------------------------------------------
// res id's of the system menu icons
#define	OPTIONS_ICON	344
#define	QUIT_ICON		335
#define	SAVE_ICON		366
#define	RESTORE_ICON	364
#define	RESTART_ICON	342

//--------------------------------------------------------------------------------------
// res id of conversation exit icon

#define	EXIT_ICON	65		// 'EXIT' menu icon (used in FN_choose)

//--------------------------------------------------------------------------------------

#endif

--- NEW FILE: events.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/events.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//------------------------------------------------------------------------------------
#include <stdio.h>

//#include "src\driver96.h"
#include "console.h"
#include "debug.h"
#include "defs.h"
#include "events.h"
#include "interpreter.h"
#include "logic.h"
#include "memory.h"
#include "object.h"
#include "sync.h"
//------------------------------------------------------------------------------------

_event_unit	event_list[MAX_events];

//------------------------------------------------------------------------------------
void	Init_event_system(void)	//Tony4Dec96
{

	uint32	j;


	for	(j=0;j<MAX_events;j++)
		event_list[j].id=0;	//denotes free slot

}
//------------------------------------------------------------------------------------
uint32	CountEvents(void)
{
	uint32	j;
	uint32	count=0;

	for	(j=0; j<MAX_events; j++)
	{
		if (event_list[j].id)
			count++;
	}

	return (count);
}
//------------------------------------------------------------------------------------
int32 FN_request_speech(int32 *params)	//Tony13Nov96
{
//change current script - must be followed by a TERMINATE script directive

//param	0 id of target to catch the event and startup speech servicing

	uint32	j=0;



	while(1)
	{
		if	(event_list[j].id == (uint32)params[0])
			break;
		if	(!event_list[j].id)
			break;

		j++;
	}



	if	(j==MAX_events)
		Con_fatal_error("FN_set_event out of event slots (%s line %u)", __FILE__, __LINE__);

//found that slot

	event_list[j].id=params[0];	//id of person to stop
	event_list[j].interact_id=(params[0]*65536)+6;	//full script id to interact with - megas run their own 7th script



	return(IR_CONT);
}
//------------------------------------------------------------------------------------
void	Set_player_action_event(uint32	id, uint32	interact_id)	//Tony4Dec96
{
	uint32	j=0;




//	if	((event_list[j].id!=id)&&(event_list[j].id))
//		while((event_list[j].id!=id)||(event_list[j].id))	//zip along until we find a free slot
//		{	j++;
//		};

	while(1)
	{
		if	(event_list[j].id==id)
			break;
		if	(!event_list[j].id)
			break;

		j++;
	}


	if	(j==MAX_events)
		Con_fatal_error("Set_event out of event slots");

//found that slot

	event_list[j].id=id;	//id of person to stop
	event_list[j].interact_id=(interact_id*65536)+2;	//full script id of action script number 2

}
//------------------------------------------------------------------------------------
int32	FN_set_player_action_event(int32	*params)	//Tony10Feb97
{
//we want to intercept the player character and have him interact with an object - from script
//this code is the same as the mouse engine calls when you click on an object - here, a third party does the clicking IYSWIM

//note - this routine used CUR_PLAYER_ID as the target

//params	0 id to interact with

	uint32	j=0;




//search for an existing event or a slot

	while(1)
	{
		if	(event_list[j].id==CUR_PLAYER_ID)
			break;
		if	(!event_list[j].id)
			break;

		j++;
	}


	if	(j==MAX_events)
		Con_fatal_error("Set_event out of event slots");

//found that slot

	event_list[j].id=CUR_PLAYER_ID;	//id of person to stop
	event_list[j].interact_id=(params[0]*65536)+2;	//full script id of action script number 2


	return(IR_CONT);
}
//------------------------------------------------------------------------------------
int32	FN_send_event(int32	*params)	//Tony28Feb97
{
//we want to intercept the player character and have him interact with an object - from script

//			0 id to recieve event
//			1 script to run


	uint32	j=0;


//	Zdebug("*+*+* %d %d", params[0], params[1] );


//search for an existing event or a slot

	while(1)
	{
		if	(event_list[j].id==(uint32)params[0])
			break;
		if	(!event_list[j].id)
			break;

		j++;
	}


	if	(j==MAX_events)
		Con_fatal_error("fn_send_event out of event slots");

//found that slot

	event_list[j].id=params[0];	//id of person to stop
	event_list[j].interact_id=params[1];	//full script id


	return(IR_CONT);
}
//------------------------------------------------------------------------------------
int32 FN_check_event_waiting(int32 *params)	//Tony4Dec96
{
// returns yes/no in RESULT

// no params

	uint32	j;



	RESULT=0;


	for	(j=0; j<MAX_events; j++)
	{
		if	(event_list[j].id == ID)	//us?
		{
			RESULT=1;
			break;
		}
	}

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
// like FN_check_event_waiting, but starts the event rather than setting RESULT to 1

int32 FN_check_for_event(int32 *params)	// James (04mar97)
{
	// no params

	uint32	j;


	for	(j=0; j<MAX_events; j++)
	{
		if	(event_list[j].id == ID)	//us?
		{
			// start the event
			LLogic.Logic_one(event_list[j].interact_id);	// run 3rd script of target object on level 1
			event_list[j].id = 0;							// clear the event slot
			return(IR_TERMINATE);
		}
	}

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
// combination of FN_pause & FN_check_for_event
// - ie. does a pause, but also checks for event each cycle

int32 FN_pause_for_event(int32 *params)	// James (04mar97)
{
	// returns yes/no in RESULT

	// params:	0 pointer to object's logic structure
	//			1 number of game-cycles to pause

	Object_logic *ob_logic = (Object_logic *)params[0];
	uint32	j;


	// first, check for an event

	for	(j=0; j<MAX_events; j++)
	{
		if	(event_list[j].id == ID)						// us?
		{
			ob_logic->looping = 0;							// reset the 'looping' flag
			// start the event
			LLogic.Logic_one(event_list[j].interact_id);	// run 3rd script of target object on level 1
			event_list[j].id = 0;							// clear the event slot
			return(IR_TERMINATE);
		}
	}


	// no event, so do the FN_pause bit


	if (ob_logic->looping==0)	// start the pause
	{
		ob_logic->looping = 1;
		ob_logic->pause   = params[1];	// no. of game cycles
	}

	if (ob_logic->pause)	// if non-zero
	{
		ob_logic->pause--;	// decrement the pause count
		return(IR_REPEAT);	// drop out of script, but call this again next cycle
	}
	else					// pause count is zerp
	{
		ob_logic->looping = 0;
		return(IR_CONT);	// continue script
	}
}

//------------------------------------------------------------------------------------
uint32 Check_event_waiting(void)	//Tony4Dec96
{
//returns yes/no


	uint32	j;


	for	(j=0;j<MAX_events;j++)
		if	(event_list[j].id == ID)	//us?
			return(1);	//yes

	return(0);	//no
}
//------------------------------------------------------------------------------------
int32 FN_clear_event(int32 *params)	//Tony11Mar97
{
//	no params
//	no return vaule


	uint32	j;


	for	(j=0;j<MAX_events;j++)
		if	(event_list[j].id == ID)	//us?
		{
			event_list[j].id=0;	//clear the slot
			return(IR_CONT);	//
		}

	return(IR_CONT);	//
}
//------------------------------------------------------------------------------------
void	Start_event(void)	//Tony4Dec96
{
//call this from stuff like fn_walk
//you must follow with a return(IR_TERMINATE)

	uint32	j;


	for	(j=0;j<MAX_events;j++)
		if	(event_list[j].id == ID)	//us?
		{

			LLogic.Logic_one( event_list[j].interact_id);	//run 3rd script of target object on level 1

			event_list[j].id=0;	//clear the slot

			return;
		}

//oh dear - stop the system

	Con_fatal_error("Start_event can't find event for id %d", ID);

}
//------------------------------------------------------------------------------------
int32 FN_start_event(int32 *params)	//Tony4Dec96
{

	uint32	j;


	for	(j=0;j<MAX_events;j++)
		if	(event_list[j].id == ID)	//us?
		{

			LLogic.Logic_one(event_list[j].interact_id);	//run 3rd script of target object on level 1

			event_list[j].id=0;	//clear the slot

			return(IR_TERMINATE);
		}

//oh dear - stop the system

	Con_fatal_error("FN_start_event can't find event for id %d", ID);

	return(0);	//never called - but lets stop them bloody errors
}
//------------------------------------------------------------------------------------
void	Kill_all_ids_events(uint32	id)	//Tony18Dec96
{
	uint32	j;


	for	(j=0;j<MAX_events;j++)
		if	(event_list[j].id == id)	//us?
			event_list[j].id=0;	//clear the slot

	if (id);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------


--- NEW FILE: events.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/events.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_EVENTS
#define	_EVENTS

//#include "src\driver96.h"
#include "object.h"


typedef	struct
{
	uint32	id;
	uint32	interact_id;
}	_event_unit;

#define	MAX_events	10

extern _event_unit	event_list[MAX_events];

void	Init_event_system(void);	//Tony4Dec96
int32	FN_set_event(int32 *params);	//Tony13Nov96
void	Set_player_action_event(uint32	id, uint32	interact_id);	//Tony4Dec96
int32	FN_check_event_waiting(void);	//Tony4Dec96
void	Start_event(void);	//Tony4Dec96
int32	FN_start_event(void);	//Tony4Dec96
uint32	Check_event_waiting(void);	//Tony4Dec96
void	Kill_all_ids_events(uint32	id);	//Tony18Dec96
uint32	CountEvents(void);	// James11july97


#endif

--- NEW FILE: function.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/function.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//------------------------------------------------------------------------------------

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

#include "driver/driver96.h"
#include "build_display.h"
#include "credits.h"
#include "debug.h"
#include "defs.h"
#include "function.h"
#include "interpreter.h"
#include "layers.h"	// for 'this_screen' structure
#include "logic.h"
#include "memory.h"
#include "object.h"
#include "protocol.h"
#include "resman.h"
#include "sword2.h"	// for CloseGame()
//------------------------------------------------------------------------------------
typedef	struct
{
	uint32	a;
	uint32	b;
} test_struct;

//------------------------------------------------------------------------------------

Object_graphic	engine_graph;	// global for engine
Object_mega		engine_mega;	// global for engine

//------------------------------------------------------------------------------------
int32 FN_test_function(int32 *params)
{
//param	0 address of a flag
	Zdebug(" TEST %d %d", *params, RESULT);


	return(IR_CONT);
}
//------------------------------------------------------------------------------------
int32 FN_test_flags(int32 *params)
{
//param	0 value of flag

	test_struct	*tony;


	tony = (test_struct*) *params;	//address of structure



//	Zdebug("\nFN_test_flags %d, %d\n", tony->a, tony->b );

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
int32 FN_gosub(int32 *params)	//Tony23Sept96
{
//hurray, script subroutines
//param	0 id of script


	LLogic.Logic_up(*params);

	return(4);	//logic goes up - pc is saved for current level
}
//------------------------------------------------------------------------------------
int32 FN_new_script(int32 *params)	//Tony13Nov96
{
//change current script - must be followed by a TERMINATE script directive
//param	0 id of script
	Zdebug("FN_new_script %d", *params);

	PLAYER_ACTION=0;	//must clear this

	LLogic.Logic_replace( *params );

	return(IR_TERMINATE);	//drop out no pc save - and around again
}
//------------------------------------------------------------------------------------
int32 FN_interact(int32 *params)	//Tony13Nov96
{
//run targets action on a subroutine
//called by player on his base level 0 idle, for example


//param	0 id of target from which we derive action script reference

	Zdebug("FN_interact %d", *params);
	PLAYER_ACTION=0;	//must clear this

	LLogic.Logic_up( (*params*65536)+2);	//3rd script of clicked on id

	return(IR_GOSUB);	//out, up and around again - pc is saved for current level to be returned to
}
//------------------------------------------------------------------------------------

// Open & close a resource.
// Forces a resource into memory before it's "officially" opened for use.
// eg. if an anim needs to run on smoothly from another, "preloading" gets it into memory in advance
//     to avoid the cacheing delay that normally occurs before the first frame.

int32 FN_preload(int32 *params)	// (1Nov96 JEL)
{
	res_man.Res_open(params[0]);	// open resource
	res_man.Res_close(params[0]);	// close resource

	return(IR_CONT);	// continue script
}


// Go fetch resource in the background.
int32 FN_prefetch(int32 *params)
{
	return(IR_CONT);
}


// Fetches a resource in the background but prevents the script from continuing until the resource is in memory.
int32 FN_fetch_wait(int32 *params)
{
	return (IR_CONT);
}


// Releases a resource from memory. Used for freeing memory for sprites that have just been used
// and will not be used again.
// Sometimes it is better to kick out a sprite straight away so that the memory can be used for
// more frequent animations.
int32 FN_release(int32 *params)
{
	return (IR_CONT);
}


//------------------------------------------------------------------------------------
// Generates a random number between 'min' & 'max' inclusive, and sticks it in the script flag 'result'

int32 FN_random(int32 *params)	// (1nov96 JEL)
{
	uint32 min = params[0];
	uint32 max = params[1];

	RESULT = (rand() % (max-min+1)) + min;	// return_value = random integer between min and max, inclusive
	
	return(IR_CONT);	// continue script
}
//------------------------------------------------------------------------------------
int32 FN_pause(int32 *params)	// (19nov96 JEL)
{
	// params:	0 pointer to object's logic structure
	//			1 number of game-cycles to pause

	//NB. Pause-value of 0 causes script to continue, 1 causes a 1-cycle quit, 2 gives 2 cycles, etc.

	Object_logic *ob_logic = (Object_logic *)params[0];

	if (ob_logic->looping==0)	// start the pause
	{
		ob_logic->looping = 1;
		ob_logic->pause   = params[1];	// no. of game cycles
	}

	if (ob_logic->pause)	// if non-zero
	{
		ob_logic->pause--;	// decrement the pause count
		return(IR_REPEAT);	// drop out of script, but call this again next cycle
	}
	else					// pause count is zerp
	{
		ob_logic->looping = 0;
		return(IR_CONT);	// continue script
	}
}
//------------------------------------------------------------------------------------
int32 FN_random_pause(int32 *params)	// (26nov96 JEL)
{
	// params:	0 pointer to object's logic structure
	//			1 minimum number of game-cycles to pause
	//			2 maximum number of game-cycles to pause

	Object_logic *ob_logic = (Object_logic *)params[0];
	int32 pars[2];


	if (ob_logic->looping==0)
	{
		pars[0] = params[1];	// min
		pars[1] = params[2];	// max

		FN_random(pars);

		pars[1] = RESULT;		// random value between 'min' & 'max' inclusive
	}

	pars[0] = params[0];		// &logic

	return FN_pause(pars);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
int32 FN_pass_graph(int32 *params)	//Tony28Nov96
{
//makes an engine local copy of passed graphic_structure and mega_structure - run script 4 of an object to request this
//used by FN_turn_to(id) etc
//remember, we cannot simply read a compact any longer but instead must request it from the object itself

//params	0 pointer to a graphic structure	*might not need this?


	memcpy( &engine_graph, (uint8*)params[0], sizeof(Object_graphic));

	return(IR_CONT);	//makes no odds
}
//------------------------------------------------------------------------------------
int32 FN_pass_mega(int32 *params)	//Tony28Nov96
{
//makes an engine local copy of passed graphic_structure and mega_structure - run script 4 of an object to request this
//used by FN_turn_to(id) etc
//remember, we cannot simply read a compact any longer but instead must request it from the object itself

//params 0 pointer to a mega structure


	memcpy( &engine_mega, (uint8*)params[0], sizeof(Object_mega));

	return(IR_CONT);	//makes no odds
}
//------------------------------------------------------------------------------------
// temp. function!
// used for setting far-referenced megaset resource field in mega object, from start script

int32 FN_set_value(int32 *params)	// (02jan97 JEL)
{
	// params:	0 pointer to object's mega structure
	//			1 value to set it to

	Object_mega *ob_mega = (Object_mega *)params[0];


	ob_mega->megaset_res = params[1];

	return(IR_CONT);	// continue script
}
//------------------------------------------------------------------------------------
#define BLACK	0
#define WHITE	1
#define RED		2
#define GREEN	3
#define BLUE	4
//------------------------------------------------------------------------------------
uint8 black[4]	= {0,0,0,0};
uint8 white[4]	= {255,255,255,0};
uint8 red[4]	= {255,0,0,0};
uint8 green[4]	= {0,255,0,0};
uint8 blue[4]	= {0,0,255,0};
//------------------------------------------------------------------------------------
// flash colour 0 (ie. border) - useful during script development
// eg. FN_flash(BLUE) where a text line is missed; RED when some code missing, etc

int32 FN_flash(int32 *params)	// (James14feb97)
{
	// params	0: colour to flash

#ifdef _DEBUG

	uint32 count;

	switch (params[0])	// what colour?
	{
		case WHITE:
			SetPalette(0, 1, white, RDPAL_INSTANT);
			break;

		case RED:
			SetPalette(0, 1, red, RDPAL_INSTANT);
			break;

		case GREEN:
			SetPalette(0, 1, green, RDPAL_INSTANT);
			break;

		case BLUE:
			SetPalette(0, 1, blue, RDPAL_INSTANT);
			break;
	}

 	for	(count=0; count<0x80000; count++)
	{
		count++;
		count--;
	}

	SetPalette(0, 1, black, RDPAL_INSTANT);

#endif	// _DEBUG

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
// set border colour - useful during script development
// eg. set to colour during a timer situation, then black when timed out

int32 FN_colour(int32 *params)	// (James14feb97)
{
	// params	0: colour (see defines above)

#ifdef _DEBUG

	switch (params[0])	// what colour?
	{
		case BLACK:
			SetPalette(0, 1, black,	RDPAL_INSTANT);
			break;

		case WHITE:
			SetPalette(0, 1, white,	RDPAL_INSTANT);
			break;

		case RED:
			SetPalette(0, 1, red,	RDPAL_INSTANT);
			break;

		case GREEN:
			SetPalette(0, 1, green,	RDPAL_INSTANT);
			break;

		case BLUE:
			SetPalette(0, 1, blue,	RDPAL_INSTANT);
			break;
	}

#endif	// _DEBUG

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
// Display a message to the user on the screen.
//

int32 FN_display_msg(int32 *params)	// (Chris 15/5/97)
{
	// params	0: Text number of message to be displayed.
	uint32	local_text = params[0]&0xffff;
	uint32	text_res   = params[0]/SIZE;

	// Display message for three seconds.
	DisplayMsg(FetchTextLine( res_man.Res_open(text_res), local_text )+2, 3);	// +2 to skip the encoded text number in the first 2 chars; 3 is duration in seconds
	res_man.Res_close(text_res);
	RemoveMsg();

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
// FN_reset_globals is used by the demo - so it can loop back & restart itself
int32	FN_reset_globals(int32	*params)	//Tony29May97
{
	int32	size;
	uint32	*globals;
	int	j;

	size = res_man.Res_fetch_len(1);

	size-=sizeof(_standardHeader);

	Zdebug("\nglobals size %d", size/4);

	globals = (uint32*) ((uint8 *) res_man.Res_open(1)+sizeof(_standardHeader));

	for	(j=0;j<size/4;j++)
		globals[j]=0;	//blank each global variable

	res_man.Res_close(1);

	res_man.Kill_all_objects(0);	//all objects but george

//	SetGlobalInterpreterVariables((int32*)(res_man.Res_open(1)+sizeof(_standardHeader)));	//reopen global variables resource & send address to interpreter - it won't be moving
//	res_man.Res_close(1);

	//---------------------------------------------------------------
	// FOR THE DEMO - FORCE THE SCROLLING TO BE RESET! (James29may97)
	// - this is taken from FN_init_background
	this_screen.scroll_flag = 2;	// switch on scrolling (2 means first time on screen)
	//---------------------------------------------------------------

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
// FN_play_credits - Plays the credits?
// This function just quits the game if this is the playable demo, ie. credits are NOT played in the demo any more!

extern uint8 quitGame;			// From sword2.cpp
extern void UpdateCompSampleStreaming(void);	// From d_sound.c

int32 FN_play_credits(int32 *params)
{

/*	uint32	rv;	// for Credits() return value

	if (!DEMO)	// this ju
	{
		_drvDrawStatus		ds;
		_drvSoundStatus		ss;
		_drvKeyStatus		ks;

		ClearAllFx();	// Must stop all fx
		CloseFx(-2);	// including leadins
		CloseFx(-1);	// including leadouts
		StopMusic();	// Stop any streaming music
		
		for (int i = 0; i<16; i++)
			UpdateCompSampleStreaming();	// And wait for it to die

		GetDrawStatus (&ds);
		GetSoundStatus(&ss);
		GetKeyStatus  (&ks);

		rv = Credits(&ds, &ss, res_man.GetCdPath(), GetRenderType()==3, &gotTheFocus, &ks);
		SetDrawStatus (&ds);	// (James14aug97) Because game crashing when trying to close down after credits
		SetSoundStatus(&ss);	// -"-
	}

	// returns non-zero if Ctrl-Q was pressed to quit the game during the credits

	if (rv || DEMO)		// if Ctrl-Q pressed during credits, or if this is the playable demo
	{
		Close_game();	//close engine systems down
		RestoreDisplay();
		CloseAppWindow();
		exit(0);		// quit the game
	}

*/
	return (IR_CONT);
}
//------------------------------------------------------------------------------------


--- NEW FILE: function.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/function.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_FUNCTION
#define	_FUNCTION

//#include "src\driver96.h"
#include "object.h"


extern	Object_graphic	engine_graph;	// global for engine
extern	Object_mega		engine_mega;	// global for engine


#endif

--- NEW FILE: header.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/header.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_HEADER
#define	_HEADER

#include "common/scummsys.h"
//#include "src\driver96.h"

//----------------------------------------------------------
// SYSTEM FILE & FRAME HEADERS	(23sep96 JEL)
//----------------------------------------------------------

//#pragma pack( push )
//#pragma pack( 1 )

#if !defined(__GNUC__)
	#pragma START_PACK_STRUCTS
#endif



//----------------------------------------------------------
// ALL FILES
//----------------------------------------------------------
// Standard File Header
#define	NAME_LEN	34

typedef struct
{
	uint8	fileType;	// byte to define file type (see below)
	uint8	compType;	// type of file compression used ie. on whole file (see below)
	uint32	compSize;	// length of compressed file (ie. length on disk)
	uint32	decompSize;	// length of decompressed file held in memory (NB. frames still held compressed)
	uint8	name[NAME_LEN];	//name of object
} GCC_PACK _standardHeader;

//----------------------------------------------------------
// fileType

// 0 something's wrong!
#define ANIMATION_FILE		1	// all normal animations & sprites including mega-sets & font files which are the same format (but all frames always uncompressed)
#define	SCREEN_FILE			2	// each contains background, palette, layer sprites, parallax layers & shading mask
#define	GAME_OBJECT			3	// each contains object hub + structures + script data
#define	WALK_GRID_FILE		4	// walk-grid data
#define	GLOBAL_VAR_FILE		5	// all the global script variables in one file; "there can be only one"
#define PARALLAX_FILE_null	6	// NOT USED
#define	RUN_LIST			7	// each contains a list of object resource id's
#define	TEXT_FILE			8	// each contains all the lines of text for a location or a character's conversation script
#define	SCREEN_MANAGER		9	// one for each location; this contains special startup scripts
#define MOUSE_FILE			10	// mouse pointers and luggage icons (sprites in General \ Mouse pointers & Luggage icons)
#define WAV_FILE			11	// wav file
#define	ICON_FILE			12	// menu icon (sprites in General \ Menu icons
#define PALETTE_FILE		13	// separate palette file (see also _paletteHeader)
//----------------------------------------------------------
// compType

#define NO_COMPRESSION		0
#define FILE_COMPRESSION	1	// standard whole-file compression (not yet devised!)

//----------------------------------------------------------



//----------------------------------------------------------
// (1) ANIMATION FILES
//----------------------------------------------------------
// an animation file consists of:

// standard file header
// animation header
// a string of CDT entries (one per frame of the anim)
// a 16-byte colour table ONLY if (runTimeComp==RLE16)
// a string of groups of (frame header + frame data)

//----------------------------------------------------------
// Animation Header

typedef	struct
{
	uint8	runTimeComp;	// type of runtime compression used for the frame data (see below)
	uint16	noAnimFrames;	// number of frames in the anim (ie. no. of CDT entries)
	uint16	feetStartX;		// start coords for mega to walk to, before running anim
	uint16	feetStartY;
	uint8	feetStartDir;	// direction to start in before running anim
	uint16	feetEndX;		// end coords for mega to stand at after running anim (vital if anim starts from an off-screen position, or ends in a different place from the start)
	uint16	feetEndY;
	uint8	feetEndDir;		// direction to start in after running anim
	uint16	blend;
} GCC_PACK _animHeader;

//----------------------------------------------------------
// runtimeComp - compression used on each frame of the anim

#define NONE	0	// No frame compression
#define RLE256	1	// James's RLE for 256-colour sprites
#define RLE16	2	// James's RLE for 16- or 17-colour sprites
					// (raw blocks have max 16 colours for 2 pixels per byte,
					// so '0's are encoded only as FLAT for 17-colour sprites eg. George's mega-set)
//----------------------------------------------------------
// CDT Entry

typedef struct
{
	int16	x;				// sprite x-coord OR offset to add to mega's feet x-coord to calc sprite y-coord
	int16	y;				// sprite y-coord OR offset to add to mega's feet y-coord to calc sprite y-coord
	uint32	frameOffset;	// points to start of frame header (from start of file header)
	uint8	frameType;		// 0=print sprite normally with top-left corner at (x,y), otherwise see below...
} GCC_PACK _cdtEntry;

// 'frameType' bit values
#define FRAME_OFFSET	1	// print at (feetX+x,feetY+y), with scaling according to feetY
#define FRAME_FLIPPED	2	// print the frame flipped Left->Right
#define FRAME_256_FAST	4	// Frame has been compressed using Pauls fast RLE 256 compression.

//----------------------------------------------------------
//Frame Header

typedef	struct
{
	uint32	compSize;	// compressed size of frame - NB. compression type is now in Anim Header
	uint16	width;		// dimensions of frame
	uint16	height;
} GCC_PACK _frameHeader;

//----------------------------------------------------------
// Frame Data

// uint8 spriteData[width*height];	// one byte per pixel
//----------------------------------------------------------





//----------------------------------------------------------
// (2) SCREEN FILES
//----------------------------------------------------------
// a screen file consists of:

// standard file header
// multi screen header
// 4*256 bytes of palette data
// 256k palette match table
// 2 background parallax layers
// 1 background layer with screen header
// 2 foreground parallax layers
// a string of layer headers
// a string of layer masks

//----------------------------------------------------------
// Multi screen header
// Goes at the beginning of a screen file after the standard
// header.
// Gives offsets from start of table of each of the components

typedef struct
{
	uint32 palette;
	uint32 bg_parallax[2];
	uint32 screen;
	uint32 fg_parallax[2];
	uint32 layers;
	uint32 paletteTable;
	uint32 maskOffset;
} GCC_PACK _multiScreenHeader;

//------------------------------------------------------------
// Palette Data

typedef struct
{
	uint8	red;
	uint8	green;
	uint8	blue;
	uint8	alpha;
} GCC_PACK _palEntry;

#define	NO_COLOURS	256
// _palEntry palette[NO_COLOURS]

//------------------------------------------------------------
// Screen Header

typedef struct
{
	uint16	width;		// dimensions of the background screen
	uint16	height;
	uint16	noLayers;	// number of layer areas
} GCC_PACK _screenHeader;

//------------------------------------------------------------
// Background Raw Bitmap

// uint8 backgroundData[width*height];	// one byte per pixel

//------------------------------------------------------------
// Layer Header

// Note that all the layer headers are kept together,
// rather than being placed before each layer mask,
// in order to simplify the sort routine.

typedef struct
{
	uint16	x;			// coordinates of top-left pixel of area
	uint16	y;
	uint16	width;
	uint16	height;
	uint32  maskSize;
	uint32	offset;		// where to find mask data (from start of standard file header)
} GCC_PACK _layerHeader;

//------------------------------------------------------------
// Layer Mask

// uint8 layerData[width*height/8];	// 8 pixels to a byte

//------------------------------------------------------------



//----------------------------------------------------------
// (3) SCRIPT OBJECT FILES
//----------------------------------------------------------
// a script object file consists of:

// standard file header
// script object header
// script object data

//----------------------------------------------------------
// Script Object Header

// ???????
// ???????
// ???????

//----------------------------------------------------------
// Script Object Data

//----------------------------------------------------------



//----------------------------------------------------------
// (4) WALK-GRID FILES
//----------------------------------------------------------
// a walk-grid file consists of:

// standard file header
// walk-grid file header
// walk-grid data

//----------------------------------------------------------
// Walk-Grid Header - taken directly from old "header.h" in STD_INC

typedef struct
{
	int32	numBars;	// number of bars on the floor
	int32	numNodes;	// number of nodes
} GCC_PACK _walkGridHeader;

//----------------------------------------------------------
// Walk-Grid Data

// ???????

//----------------------------------------------------------



//----------------------------------------------------------
// (5) PALETTE FILES
//----------------------------------------------------------
// a palette file consists of:

// standard file header
// 4*256 bytes of palette data
// 256k palette match table

//----------------------------------------------------------

//--------------------------------------------------------------------------------------------------
// PCX file header
//--------------------------------------------------------------------------------------------------
typedef	struct
{	uint8	manufacturer;
	uint8	version;
	uint8	encoding;
	uint8	bitsPerPixel;
	int16	xmin,ymin;
	int16	xmax,ymax;
	int16	hres;
	int16	vres;
	char	palette[48];
	char	reserved;
	uint8	colourPlanes;
	int16	bytesPerLine;
	int16	paletteType;
	char	filler[58];
} GCC_PACK _PCXHEAD;
//----------------------------------------------------------
#define	TREE_SIZE	3

typedef	struct	// an object hub - which represents all that remains of the compact concept
{
	int32	type;					// type of object
	uint32	logic_level;			// what level?
	uint32	logic[TREE_SIZE];		// NOT USED
	uint32	script_id[TREE_SIZE];	// need this if script
	uint32	script_pc[TREE_SIZE];	// need this also
} GCC_PACK _object_hub;
//----------------------------------------------------------
//----------------------------------------------------------
// (6) text module header	TW

typedef	struct
{
	uint32	noOfLines;	//how many lines of text are there in this module
} GCC_PACK _textHeader;

//a text file has:

//	_standardHeader
//	_textHeader
//	look up table, to
//	line of text,0
//	line of text,0

//----------------------------------------------------------

// #pragma pack( pop )

#if !defined(__GNUC__)
	#pragma END_PACK_STRUCTS
#endif

#endif

--- NEW FILE: icons.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/icons.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

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

#include "driver/driver96.h"
#include "console.h"
#include "icons.h"
#include "interpreter.h"
#include "logic.h"
#include "mouse.h"
#include "object.h"

//------------------------------------------------------------------------------------
menu_object temp_list[TOTAL_engine_pockets];
uint32	total_temp=0;	//tempory list

menu_object master_menu_list[TOTAL_engine_pockets];
uint32	total_masters=0;
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
int32 FN_add_menu_object(int32 *params)	//Tony1Oct96
{
//param	0 pointer to a menu_object structure to copy down

//	Zdebug("FN_add_menu_object icon res");

#ifdef _DEBUG
	if (total_temp == TOTAL_engine_pockets)
		Con_fatal_error("TOTAL_engine_pockets exceeded! (%s line %u)",__FILE__,__LINE__);
#endif

//	copy the structure to our in-the-engine list
	memcpy( &temp_list[total_temp], (uint8*) *params, sizeof(menu_object));	//
	total_temp++;

	return(IR_CONT);	// script continue
}
//------------------------------------------------------------------------------------
int32 FN_refresh_inventory(int32 *params)	// (James28aug97)
{
	// called from 'menu_look_or_combine' script in 'menu_master' object
	// to update the menu to display a combined object while George runs voice-over
	// Note that 'object_held' must be set to the graphic of the combined object

	COMBINE_BASE=0;			// can reset this now

	examining_menu_icon=1;	// so that the icon in 'object_held' is coloured while the rest are grey
	Build_top_menu();
 	examining_menu_icon=0;

	return(IR_CONT);	// script continue
}
//------------------------------------------------------------------------------------
void	Build_top_menu(void)	//Tony19Nov96
{
 // create and start the inventory menu - NOW AT THE BOTTOM OF THE SCREEN!

	uint32	null_pc=0;
	uint32	j,k;
	uint8	icon_coloured;
	uint8	*icon;
	uint8	*head;
	uint32	res;

	total_temp=0;	//reset temp list which will be totally rebuilt



//	Zdebug("\nbuild top menu %d", total_masters);


//clear the temp list before building a new temp list in-case list gets smaller
	for	(j=0;j<TOTAL_engine_pockets;j++)	//check each master
		temp_list[j].icon_resource=0;	//


//call menu builder script which will register all carried menu objects
	head = res_man.Res_open(MENU_MASTER_OBJECT);
	RunScript( (char*)head, (char*)head, &null_pc );	// run the 'build_menu' script in the 'menu_master' object
	res_man.Res_close(MENU_MASTER_OBJECT);

//compare new with old
//anything in master thats not in new gets removed from master - if found in new too, remove from temp

	if	(total_masters)
	{
		for	(j=0;j<total_masters;j++)	//check each master
		{
			for	(k=0;k<TOTAL_engine_pockets;k++)
			{
				res=0;
				if	(master_menu_list[j].icon_resource == temp_list[k].icon_resource)	//if master is in temp
				{
					temp_list[k].icon_resource=0;	//kill it in the temp
					res=1;
					break;
				}
			}
			if	(!res)
			{	master_menu_list[j].icon_resource=0;	//otherwise not in temp so kill in main
//				Zdebug("Killed menu %d",j);
			}
		}
	}

//merge master downwards

	total_masters=0;
	for	(j=0;j<TOTAL_engine_pockets;j++)	//check each master slot
	{
		if	((master_menu_list[j].icon_resource)&&(j!=total_masters))	//not current end - meaning out over the end so move down
		{
			memcpy( &master_menu_list[total_masters++], &master_menu_list[j], sizeof(menu_object));	//
			master_menu_list[j].icon_resource=0;	//moved down now so kill here
		}
		else if (master_menu_list[j].icon_resource)	//skip full slots
			total_masters++;
	}

//add those new to menu still in temp but not yet in master to the end of the master
	for	(j=0;j<TOTAL_engine_pockets;j++)	//check each master slot
		if	(temp_list[j].icon_resource)	//here's a new temp
			memcpy( &master_menu_list[total_masters++], &temp_list[j], sizeof(menu_object));	//


//init top menu from master list
	for	(j=0;j<15;j++)
	{
		if	(master_menu_list[j].icon_resource)
		{
			res = master_menu_list[j].icon_resource;	// 'res' is now the resource id of the icon

			//-----------------------------------------------------------------------------------------------------
			// WHEN AN ICON HAS BEEN RIGHT-CLICKED FOR 'EXAMINE' - SELECTION COLOURED, THE REST GREYED OUT

			if (examining_menu_icon)		// '1' when examining a menu-icon ('OBJECT_HELD' is the resource of the icon being examined)
			{
				if (res == OBJECT_HELD)		// if this is the icon being examined, make it coloured
					icon_coloured=1;
				else						// if not, grey this one out
					icon_coloured=0;
			}
			//-----------------------------------------------------------------------------------------------------
			// WHEN ONE MENU OBJECT IS BEING USED WITH ANOTHER - BOTH TO BE COLOURED, THE REST GREYED OUT

			else if (COMBINE_BASE)	// resource of second icon clicked
			{
				if ((res == OBJECT_HELD)||(res == COMBINE_BASE))	// if this if either of the icons being combined...
					icon_coloured=1;
				else
					icon_coloured=0;
			}
			//-----------------------------------------------------------------------------------------------------
			// NORMAL ICON SELECTION - SELECTION GREYED OUT, THE REST COLOURED

			else
			{
  				if (res == OBJECT_HELD)	// if this is the selction, grey it out
					icon_coloured=0;
				else						// if not, make it coloured
					icon_coloured=1;
			}
		 
 			//-----------------------------------------------------------------------------------------------------


			if (icon_coloured)	// coloured
				icon = res_man.Res_open( master_menu_list[j].icon_resource ) + sizeof(_standardHeader) + RDMENU_ICONWIDE*RDMENU_ICONDEEP;
			else				// greyed out
				icon = res_man.Res_open( master_menu_list[j].icon_resource ) + sizeof(_standardHeader);

			SetMenuIcon(RDMENU_BOTTOM, j, icon);
			res_man.Res_close( res );
		}
		else
		{
			SetMenuIcon(RDMENU_BOTTOM, j, NULL);	//no icon here
			//Zdebug(" NULL for %d", j);
		}
	}

	ShowMenu(RDMENU_BOTTOM);

}



//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
void	Build_system_menu(void)	//Tony19Mar97
{
//start a fresh top system menu

	uint8	*icon;
	int	j;

	uint32	icon_list[5] =
	{
		OPTIONS_ICON,
		QUIT_ICON,
		SAVE_ICON,
		RESTORE_ICON,
		RESTART_ICON
	};


	for	(j=0;j<5;j++)	//build them all high in full colour - when one is clicked on all the rest will grey out
	{
		if	((DEAD)&&(j==2))	//dead then SAVE not available
			icon = res_man.Res_open( icon_list[j] ) + sizeof(_standardHeader);

		else	icon = res_man.Res_open( icon_list[j] ) + sizeof(_standardHeader) + RDMENU_ICONWIDE*RDMENU_ICONDEEP;
		SetMenuIcon(RDMENU_TOP, j, icon);
		res_man.Res_close( icon_list[j] );
	}


	ShowMenu(RDMENU_TOP);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------

--- NEW FILE: icons.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/icons.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_ICONS
#define	_ICONS


//#include	"src\driver96.h"
#include	"object.h"

#define	MENU_MASTER_OBJECT	44
#define	TOTAL_subjects	375-256+1	//the speech subject bar
#define	TOTAL_engine_pockets	15+10	// +10 for overflow

typedef	struct
{
	int32	icon_resource;		// icon graphic graphic
	int32	luggage_resource;	// luggage icon resource (for attaching to mouse pointer)
} menu_object;	//define these in a script and then register them with the system

extern	menu_object master_menu_list[TOTAL_engine_pockets];

void	Build_top_menu(void);	//Tony19Nov96
void	Build_system_menu(void);	//Tony19Mar97

#endif

--- NEW FILE: interpreter.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/interpreter.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef INSIDE_LINC			// Are we running in linc?
#include "console.h"
#endif

#include "driver/driver96.h"
#include "interpreter.h"



//		This file serves two purposes. It is compiled as part of the test functions
//		of Linc, and also as part of the game


//		The machine code table

int32 FN_test_function(int32 *params);
int32 FN_test_flags(int32 *params);
int32 FN_register_start_point(int32 *params);
int32 FN_init_background(int32 *params);
int32 FN_set_session(int32 *params);
int32 FN_back_sprite(int32 *params);	
int32 FN_sort_sprite(int32 *params);	
int32 FN_fore_sprite(int32 *params);	
int32 FN_register_mouse(int32 *params);	
int32 FN_anim(int32 *);
int32 FN_random(int32 *);
int32 FN_preload(int32 *);
int32 FN_add_subject(int32 *);
int32 FN_interact(int32 *);
int32 FN_choose(int32 *);
int32 FN_walk(int32 *);
int32 FN_walk_to_anim(int32 *);					// walk to start position of anim
int32 FN_turn(int32 *);							// turn to (dir)
int32 FN_stand_at(int32 *);						// stand at (x,y,dir)
int32 FN_stand(int32 *);						// stand facing (dir)
int32 FN_stand_after_anim(int32 *);				// stand at end position of anim
int32 FN_pause(int32 *);
int32 FN_mega_table_anim(int32 *);
int32 FN_add_menu_object(int32 *);
int32 FN_start_conversation(int32 *);
int32 FN_end_conversation(int32 *);
int32 FN_set_frame(int32 *);
int32 FN_random_pause(int32 *);
int32 FN_register_frame(int32 *);
int32 FN_no_sprite(int32 *);
int32 FN_send_sync(int32 *);
int32 FN_update_player_stats(int32 *);
int32 FN_pass_graph(int32 *);
int32 FN_init_floor_mouse(int32 *);
int32 FN_pass_mega(int32 *);
int32 FN_face_xy(int32 *);
int32 FN_end_session(int32 *);
int32 FN_no_human(int32 *);
int32 FN_add_human(int32 *);
int32 FN_we_wait(int32 *);
int32 FN_they_do_we_wait(int32 *);
int32 FN_they_do(int32 *);
int32 FN_walk_to_talk_to_mega(int32 *);
int32 FN_fade_down(int32 *);
int32 FN_i_speak(int32 *);
int32 FN_total_restart(int32 *);
int32 FN_set_walkgrid(int32 *);
int32 FN_speech_process(int32 *);
int32 FN_set_scaling(int32 *);
int32 FN_start_event(int32 *);
int32 FN_check_event_waiting(int32 *);
int32 FN_request_speech(int32 *);
int32 FN_gosub(int32 *);
int32 FN_timed_wait(int32 *);
int32 FN_play_fx(int32 *);
int32 FN_stop_fx(int32 *);
int32 FN_play_music(int32 *);
int32 FN_stop_music(int32 *);
int32 FN_set_value(int32 *);
int32 FN_new_script(int32 *);
int32 FN_get_sync(int32 *);
int32 FN_wait_sync(int32 *);
int32 FN_register_walkgrid(int32 *);
int32 FN_reverse_mega_table_anim(int32 *);
int32 FN_reverse_anim(int32 *);
int32 FN_add_to_kill_list(int32 *);
int32 FN_set_standby_coords(int32 *);
int32 FN_back_par0_sprite(int32 *params);
int32 FN_back_par1_sprite(int32 *params);
int32 FN_fore_par0_sprite(int32 *params);
int32 FN_fore_par1_sprite(int32 *params);
int32 FN_fore_par1_sprite(int32 *params);
int32 FN_set_player_action_event(int32 *params);
int32 FN_set_scroll_coordinate(int32 *params);
int32 FN_stand_at_anim(int32 *params);
int32 FN_set_scroll_left_mouse(int32 *params);
int32 FN_set_scroll_right_mouse(int32 *params);
int32 FN_colour(int32 *params);
int32 FN_flash(int32 *params);
int32 FN_prefetch(int32 *params);
int32 FN_get_player_savedata(int32 *params);
int32 FN_pass_player_savedata(int32 *params);
int32 FN_send_event(int32 *params);
int32 FN_add_walkgrid(int32 *params);
int32 FN_remove_walkgrid(int32 *params);
int32 FN_check_for_event(int32 *params);
int32 FN_pause_for_event(int32 *params);
int32 FN_clear_event(int32 *params);
int32 FN_face_mega(int32 *params);
int32 FN_play_sequence(int32 *params);
int32 FN_shaded_sprite(int32 *params);
int32 FN_unshaded_sprite(int32 *params);
int32 FN_fade_up(int32 *params);
int32 FN_display_msg(int32 *params);
int32 FN_set_object_held(int32 *params);
int32 FN_add_sequence_text(int32 *params);
int32 FN_reset_globals(int32 *params);
int32 FN_set_palette(int32 *params);
int32 FN_register_pointer_text(int32 *params);
int32 FN_fetch_wait(int32 *params);
int32 FN_release(int32 *params);
int32 FN_sound_fetch(int32 *params);
int32 FN_prepare_music(int32 *params);
int32 FN_smacker_lead_in(int32 *params);
int32 FN_smacker_lead_out(int32 *params);
int32 FN_stop_all_fx(int32 *params);
int32 FN_check_player_activity(int32 *params);
int32 FN_reset_player_activity_delay(int32 *params);
int32 FN_check_music_playing(int32 *params);
int32 FN_play_credits(int32 *params);
int32 FN_set_scroll_speed_normal(int32 *params);
int32 FN_set_scroll_speed_slow(int32 *params);
int32 FN_remove_chooser(int32 *params);
int32 FN_set_fx_vol_and_pan(int32 *params);
int32 FN_set_fx_vol(int32 *params);
int32 FN_restore_game(int32 *params);
int32 FN_refresh_inventory(int32 *params);
int32 FN_change_shadows(int32 *params);

#define MAX_FN_NUMBER	117

extern int32 (*McodeTable[])(int32 *);

#ifndef INSIDE_LINC
int32 * globalInterpreterVariables2 = NULL;		// Point to the global varibale data
int		g_debugFlag = 0;						// Set this to turn debugging on
#endif


int32 (*McodeTable[MAX_FN_NUMBER+1])(int32 *) =
{	FN_test_function,
	FN_test_flags,
	FN_register_start_point,
	FN_init_background,
	FN_set_session,
	FN_back_sprite,
	FN_sort_sprite,
	FN_fore_sprite,
	FN_register_mouse,
	FN_anim,
	FN_random,
	FN_preload,
	FN_add_subject,
	FN_interact,
	FN_choose,
	FN_walk,
	FN_walk_to_anim,
	FN_turn,
	FN_stand_at,
	FN_stand,
	FN_stand_after_anim,
	FN_pause,
	FN_mega_table_anim,
	FN_add_menu_object,
	FN_start_conversation,
	FN_end_conversation,
	FN_set_frame,
	FN_random_pause,
	FN_register_frame,
	FN_no_sprite,
	FN_send_sync,
	FN_update_player_stats,
	FN_pass_graph,
	FN_init_floor_mouse,
	FN_pass_mega,
	FN_face_xy,
	FN_end_session,
	FN_no_human,
	FN_add_human,
	FN_we_wait,
	FN_they_do_we_wait,
	FN_they_do,
	FN_walk_to_talk_to_mega,
	FN_fade_down,
	FN_i_speak,
	FN_total_restart,
	FN_set_walkgrid,
	FN_speech_process,
	FN_set_scaling,
	FN_start_event,
	FN_check_event_waiting,
	FN_request_speech,
	FN_gosub,
	FN_timed_wait,
	FN_play_fx,
	FN_stop_fx,
	FN_play_music,
	FN_stop_music,
	FN_set_value,
	FN_new_script,
	FN_get_sync,
	FN_wait_sync,
	FN_register_walkgrid,
	FN_reverse_mega_table_anim,
	FN_reverse_anim,
	FN_add_to_kill_list,
	FN_set_standby_coords,
	FN_back_par0_sprite,
	FN_back_par1_sprite,
	FN_fore_par0_sprite,
	FN_fore_par1_sprite,
	FN_set_player_action_event,
	FN_set_scroll_coordinate,
	FN_stand_at_anim,
	FN_set_scroll_left_mouse,
	FN_set_scroll_right_mouse,
	FN_colour,
	FN_flash,
	FN_prefetch,
	FN_get_player_savedata,
	FN_pass_player_savedata,
	FN_send_event,
	FN_add_walkgrid,
	FN_remove_walkgrid,
	FN_check_for_event,
	FN_pause_for_event,
	FN_clear_event,
	FN_face_mega,
	FN_play_sequence,
	FN_shaded_sprite,
	FN_unshaded_sprite,
	FN_fade_up,
	FN_display_msg,
	FN_set_object_held,
	FN_add_sequence_text,
	FN_reset_globals,
	FN_set_palette,
	FN_register_pointer_text,
	FN_fetch_wait,
	FN_release,
	FN_prepare_music,
	FN_sound_fetch,
	FN_prepare_music,
	FN_smacker_lead_in,
	FN_smacker_lead_out,
	FN_stop_all_fx,
	FN_check_player_activity,
	FN_reset_player_activity_delay,
	FN_check_music_playing,
	FN_play_credits,
	FN_set_scroll_speed_normal,
	FN_set_scroll_speed_slow,
	FN_remove_chooser,
	FN_set_fx_vol_and_pan,
	FN_set_fx_vol,
	FN_restore_game,
	FN_refresh_inventory,
	FN_change_shadows,
};

#define CHECKSTACKPOINTER2 ASSERT((stackPointer2>=0)&&(stackPointer2<STACK_SIZE));
#define	PUSHONSTACK(x) {stack2[stackPointer2] = (x);stackPointer2++;CHECKSTACKPOINTER2;}
#define POPOFFSTACK(x) {x=stack2[stackPointer2-1];stackPointer2--;CHECKSTACKPOINTER2;}
#define DOOPERATION(x) {stack2[stackPointer2-2] = (x);stackPointer2--;CHECKSTACKPOINTER2;}

#ifndef INSIDE_LINC
void SetGlobalInterpreterVariables(int32 *vars)
{
	globalInterpreterVariables2 = vars;
}
#endif

#ifdef INSIDE_LINC			// Are we running in linc?
int RunScript ( MCBOVirtualSword &engine , const char * scriptData , char * objectData , uint32 *offset )
#else
int RunScript ( const char * scriptData , char * objectData , uint32 *offset )
#endif
{
	#define STACK_SIZE		10

	_standardHeader *header = (_standardHeader *)scriptData;
	scriptData += sizeof(_standardHeader) + sizeof(_object_hub);

	// The script data format:


	//		int32_TYPE	1									Size of variable space in bytes
	//		...											The variable space
	//		int32_TYPE	1									numberOfScripts
	//		int32_TYPE	numberOfScripts						The offsets for each script


	// Initialise some stuff

	int ip = 0;									// Code pointer
	int curCommand,parameter,value;				// Command and parameter variables
	int32 stack2[STACK_SIZE];						// The current stack
	int32 stackPointer2 = 0;						// Position within stack
	int parameterReturnedFromMcodeFunction=0;	// Allow scripts to return things
	int savedStartOfMcode;						// For saving start of mcode commands

	// Get the start of variables and start of code
	DEBUG3("Enter interpreter data %x, object %x, offset %d",scriptData,objectData,*offset);
	const char *variables = scriptData + sizeof(int);
	const char *code = scriptData + *((int *)scriptData) + sizeof(int);
	uint32 noScripts = *((int32 *)code);
	if ( (*offset) < noScripts)
	{	ip = ((int *)code)[(*offset)+1];
		DEBUG2("Start script %d with offset %d",*offset,ip);
	}
	else
	{	ip = (*offset);
		DEBUG1("Start script with offset %d",ip);
	}

	code += noScripts * sizeof(int) + sizeof(int);

/************************************************************************************************/
#ifdef DONTPROCESSSCRIPTCHECKSUM

	code += sizeof(int) * 3;

#else

	// Code should nopw be pointing at an identifier and a checksum
	int *checksumBlock = (int *)code;
	code += sizeof(int) * 3;

	if (checksumBlock[0] != 12345678)
	{
#ifdef INSIDE_LINC
		AfxMessageBox(CVString("Invalid script in object %s",header->name));
#else
		Con_fatal_error("Invalid script in object %s",header->name);
#endif
		return(0);
	}
	int codeLen = checksumBlock[1];
	int checksum = 0;
	for (int count = 0 ; count < codeLen ; count++)
		checksum += (unsigned char)code[count];
	if ( checksum != checksumBlock[2] )
	{
#ifdef INSIDE_LINC
		AfxMessageBox(CVString("Checksum error in script %s",header->name));
#else
		Con_fatal_error("Checksum error in object %s",header->name);
#endif
		return(0);
	}

#endif //DONTPROCESSSCRIPTCHECKSUM

/************************************************************************************************/

	int runningScript = 1;
	while ( runningScript )
	{	curCommand = code[ip++];
		switch(curCommand)
		{	case CP_END_SCRIPT:			// 0	End the script
				DEBUG1("End script",0);
				runningScript = 0;
#ifdef INSIDE_LINC
				engine.AddTextLine( "End script" , VS_COL_GREY );
				engine.AddTextLine(	"" , VS_COL_GREY );
#endif
				break;

			case CP_PUSH_LOCAL_VAR32:		// 1	Push the contents of a local variable
				Read16ip(parameter)
				DEBUG2("Push local var %d (%d)",parameter,*((int *)(variables+parameter)));
				PUSHONSTACK ( *((int *)(variables+parameter)) );
				break;


			case CP_PUSH_GLOBAL_VAR32:			// 2	Push a global variable
				Read16ip(parameter)
#ifdef INSIDE_LINC
				DEBUG2("Push global var %d (%d)",parameter,g_GlobalVariables.GetLocalByIndex(parameter).GetValue());
				PUSHONSTACK ( g_GlobalVariables.GetLocalByIndex(parameter).GetValue() );
#else
				DEBUG2("Push global var %d (%d)",parameter,globalInterpreterVariables2[parameter]);
				ASSERT(globalInterpreterVariables2);
				PUSHONSTACK ( globalInterpreterVariables2[parameter] );
#endif
				break;

			case CP_POP_LOCAL_VAR32:		// 3	Pop a value into a local word variable
				Read16ip(parameter)
				POPOFFSTACK ( value );
				DEBUG2("Pop %d into var %d",value,parameter);
				*((int *)(variables+parameter)) = value;
				break;

			case CP_CALL_MCODE:			// 4	Call an mcode routine
			{
				Read16ip(parameter)
				ASSERT(parameter <= MAX_FN_NUMBER);
				value = *((int8 *)(code+ip));			// amount to adjust stack by (no of parameters)
				ip ++;
				DEBUG2("Call mcode %d with stack = %x",parameter,stack2+(stackPointer2-value));
#ifdef INSIDE_LINC
				int retVal = engine.McodeTable(parameter , stack2+(stackPointer2-value));
#else
				int retVal = McodeTable[parameter](stack2+(stackPointer2-value));
#endif
				stackPointer2 -= value;
				CHECKSTACKPOINTER2
				switch ( retVal & 7 )
				{	case IR_STOP:	// 0: Quit out for a cycle
						*offset = ip;
						return(0);

					case IR_CONT:	//	1:	// Continue as normal
						break;

					case IR_TERMINATE:	//	2:
						// Return without updating the offset
						return(2);

					case IR_REPEAT:	//	3:
						// Return setting offset to start of this function call
						*offset = savedStartOfMcode;
						return(0);

					case IR_GOSUB:	//	4:	//that's really neat
						*offset = ip;
						return(2);

					default:
						ASSERT(FALSE);
				}
				parameterReturnedFromMcodeFunction = retVal >> 3;
			}
				break;

			case CP_PUSH_LOCAL_ADDR:	// 5	push the address of a local variable
				Read16ip(parameter)
				DEBUG2("Push address of local variable %d (%x)",parameter,(int32)(variables + parameter));
				PUSHONSTACK ( (int32)(variables + parameter) );
				break;

			case CP_PUSH_INT32:			// 6	Push a long word value on to the stack
				Read32ip(parameter)
				DEBUG2("Push int32 %d (%x)",parameter,parameter);
				PUSHONSTACK ( parameter );
				break;


			case CP_SKIPONFALSE:		//	7	Skip if the value on the stack is false
				Read32ipLeaveip(parameter)
				POPOFFSTACK ( value );
				DEBUG2("Skip %d if %d is false",parameter,value);
				if (value)
					ip += sizeof(int32);
				else
					ip += parameter;
				break;

			case CP_SKIPALLWAYS:		// 8 skip a block
				Read32ipLeaveip(parameter)
				DEBUG1("Skip %d",parameter);
				ip += parameter;
				break;

			case CP_SWITCH:				// 9 switch
			{	POPOFFSTACK ( value );
				int caseCount;
				Read32ip(caseCount)
				// Search the cases
				int foundCase = 0;
				for (int count = 0 ; (count < caseCount) && (!foundCase) ; count++)
				{
					if (value == *((int32 *)(code+ip)))
					{	// We have found the case, so lets jump to it
						foundCase = 1;
						ip +=  *((int32 *)(code+ip+sizeof(int32)));
					}
					else
						ip += sizeof(int32) * 2;
				}
				// If we found no matching case then use the default
				if (!foundCase)
				{
					ip += *((int32 *)(code+ip));
				}
			}
				break;

			case CP_ADDNPOP_LOCAL_VAR32:						// 10
				Read16ip(parameter)
				POPOFFSTACK ( value );
				*((int *)(variables+parameter)) += value;
				DEBUG3("+= %d into var %d->%d",value,parameter,*((int *)(variables+parameter)));
				break;

			case CP_SUBNPOP_LOCAL_VAR32:						// 11
				Read16ip(parameter)
				POPOFFSTACK ( value );
				*((int *)(variables+parameter)) -= value;
				DEBUG3("-= %d into var %d->%d",value,parameter,*((int *)(variables+parameter)));
				break;

			case CP_SKIPONTRUE:									//	12	Skip if the value on the stack is TRUE
				Read32ipLeaveip(parameter)
				POPOFFSTACK ( value );
				DEBUG2("Skip %d if %d is false",parameter,value);
				if (!value)
					ip += sizeof(int32);
				else
					ip += parameter;
				break;

			case CP_POP_GLOBAL_VAR32:							// 13				// Pop a global variable
				Read16ip(parameter)
				POPOFFSTACK ( value );
				DEBUG2("Pop %d into global var %d",value,parameter);
#ifdef INSIDE_LINC
				g_GlobalVariables.lclSet(parameter,value);
				engine.AddTextLine(CVString(	"Set variable %s to %d",
													g_GlobalVariables.GetLocalByIndex(parameter).GetName(),
													g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ),
									VS_COL_GREY);
#else //INSIDE_LINC

#ifdef TRACEGLOBALVARIABLESET
				TRACEGLOBALVARIABLESET(parameter,value);
#endif

				globalInterpreterVariables2[parameter] = value;

#endif
				break;

			case CP_ADDNPOP_GLOBAL_VAR32:						// 14			Add and pop a global variable
			{	Read16ip(parameter)
//				parameter = *((int16_TYPE *)(code+ip));
//				ip += 2;
				POPOFFSTACK ( value );
#ifdef INSIDE_LINC
				int newVal = g_GlobalVariables.GetLocalByIndex(parameter).GetValue() + value ;
				g_GlobalVariables.lclSet(parameter, newVal );
				engine.AddTextLine(	CVString(	"Set variable %s to %d",
													g_GlobalVariables.GetLocalByIndex(parameter).GetName(),
													g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ),
										VS_COL_GREY);
#else
				globalInterpreterVariables2[parameter] += value;
				DEBUG3("+= %d into global var %d->%d",value,parameter,*((int *)(variables+parameter)));
#endif
				break;
			}

			case CP_SUBNPOP_GLOBAL_VAR32:						// 15			Sub and pop a global variable
			{	Read16ip(parameter)
//				parameter = *((int16_TYPE *)(code+ip));
//				ip += 2;
				POPOFFSTACK ( value );
#ifdef INSIDE_LINC
				int newVal = g_GlobalVariables.GetLocalByIndex(parameter).GetValue() - value ;
				g_GlobalVariables.lclSet(parameter, newVal );
				engine.AddTextLine(	CVString(	"Set variable %s to %d",
													g_GlobalVariables.GetLocalByIndex(parameter).GetName(),
													g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ),
										VS_COL_GREY);
#else
				globalInterpreterVariables2[parameter] -= value;
				DEBUG3("-= %d into global var %d->%d",value,parameter,*((int *)(variables+parameter)));
#endif
				break;
			}

			case CP_DEBUGON:
				// Turn debugging on
				g_debugFlag = 1;
				break;

			case CP_DEBUGOFF:
				// Turn debugging on
				g_debugFlag = 0;
				break;

			case CP_QUIT:
#ifdef INSIDE_LINC
				break;
#else
				// Quit out for a cycle
				*offset = ip;
				return(0);
#endif

			case CP_TERMINATE:
				// Quit out immediately without affecting the offset pointer
				return(3);

/******************************************************************************************************************
******************************************************************************************************************/

			// Operators

			case OP_ISEQUAL:	//	20				// '=='
				DEBUG3("%d == %d -> %d",	stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] == stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] == stack2[stackPointer2-1]) );
				break;

			case OP_PLUS:		//	21				// '+'
				DEBUG3("%d + %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] + stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] + stack2[stackPointer2-1]) );
				break;

			case OP_MINUS:		//	22				// '+'
				DEBUG3("%d - %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] - stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] - stack2[stackPointer2-1]) );
				break;

			case OP_TIMES:		//	23				// '+'
				DEBUG3("%d * %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] * stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] * stack2[stackPointer2-1]) );
				break;

			case OP_DEVIDE:		//	24				// '+'
				DEBUG3("%d / %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] / stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] / stack2[stackPointer2-1]) );
				break;

			case OP_NOTEQUAL:	//	25				// '!='
				DEBUG3("%d != %d -> %d",	stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] != stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] != stack2[stackPointer2-1]) );
				break;

			case OP_ANDAND:		// 26
				DEBUG3("%d != %d -> %d",	stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] && stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] && stack2[stackPointer2-1]) );
				break;

			case OP_GTTHAN:		// 27 >
				DEBUG3("%d > %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] > stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] > stack2[stackPointer2-1]) );
				break;

			case OP_LSTHAN:		// 28 <
				DEBUG3("%d < %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] < stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] < stack2[stackPointer2-1]) );
				break;

			case CP_JUMP_ON_RETURNED:	// 29
			{	// Jump to a part of the script depending on the return value from an mcode routine
				parameter = *((int8 *)(code+ip));		// Get the maximum value
				ip++;
#ifdef INSIDE_LINC
				TRACE("ip %d: Parameter %d skip %d\r\n",	ip,
															parameterReturnedFromMcodeFunction,
															((int32*)(code+ip))[parameterReturnedFromMcodeFunction] );
#endif

				ip += ((int32 *)(code+ip))[parameterReturnedFromMcodeFunction];
			}
				break;

			case CP_TEMP_TEXT_PROCESS:	// 30
				// Process a text line
				Read32ip(parameter)
//				parameter = *((int32_TYPE *)(code+ip));
//				ip += sizeof(int32_TYPE);;
				DEBUG1("Process text id %d",parameter);
#ifdef INSIDE_LINC
				// Linc only for the moment
				engine.ProcessTextLine(parameter);
#endif //INSIDE_LINC
				break;

			case CP_SAVE_MCODE_START:	// 31
				// Save the start position on an mcode instruction in case we need to restart it again
				savedStartOfMcode = ip-1;
				break;

			case CP_RESTART_SCRIPT:	// 32
			{	// Start the script again
				// Do a ip search to find the script we are running
				const char *tempScrPtr = scriptData + *((int *)scriptData) + sizeof(int);
				int scriptNumber = 0;
				int foundScript = 0;
				uint32 count = 0;
				for (count = 1 ; (count < noScripts) && (!foundScript) ; count++)
				{	if (ip < ((int *)tempScrPtr)[count+1])
					{	scriptNumber = count - 1 ;
						foundScript = 1;
					}
				}
				if (!foundScript)
					scriptNumber = count - 1 ;
				// So we know what script we are running, lets restart it
				ip = ((int *)tempScrPtr)[scriptNumber+1];
				break;
			}

			case CP_PUSH_STRING:	// 33
			{	// Push the address of a string on to the stack
				parameter = *((int8 *)(code+ip));		// Get the string size
				ip += 1;
				// ip points to the string
				PUSHONSTACK( (int)(code+ip) );
				ip += (parameter+1);
				break;
			}

			case CP_PUSH_DEREFERENCED_STRUCTURE:	// 34
			{	// Push the address of a dereferenced structure
				Read32ip(parameter)
				DEBUG1("Push address of far variable (%x)",(int32)(variables + parameter));
				PUSHONSTACK( (int)(objectData + sizeof(int) + sizeof(_standardHeader) + sizeof(_object_hub) + parameter));
				break;
			}

			case OP_GTTHANE:		// 35 >=
				DEBUG3("%d > %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] >= stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] >= stack2[stackPointer2-1]) );
				break;

			case OP_LSTHANE:		// 36 <=
				DEBUG3("%d < %d -> %d",		stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] <= stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] <= stack2[stackPointer2-1]) );
				break;

			case OP_OROR:			// 37
				DEBUG3("%d || %d -> %d",	stack2[stackPointer2-2],
											stack2[stackPointer2-1],
											stack2[stackPointer2-2] || stack2[stackPointer2-1]);
				DOOPERATION ( (stack2[stackPointer2-2] || stack2[stackPointer2-1]) );
				break;


			default:
#ifdef INSIDE_LINC
				AfxMessageBox(CVString("Invalid interpreter token %d",curCommand));
#else
				Con_fatal_error("Interpreter error: Invalid token %d", curCommand);
#endif
				return(3);
		}

	}

	return(1);
}

--- NEW FILE: interpreter.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/interpreter.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

// Interpreter return codes

#define IR_STOP		0
#define IR_CONT		1
#define IR_TERMINATE	2	
#define IR_REPEAT	3
#define IR_GOSUB	4


#ifdef INSIDE_LINC			// Are we running in linc?

extern int g_debugFlag;

#ifdef _DEBUG

#define DEBUG1(x,y)		if(g_debugFlag){engine.AddTextLine(CVString(x,y),VS_COL_DEBUG);}
#define DEBUG2(x,y,z)	if(g_debugFlag){engine.AddTextLine(CVString(x,y,z),VS_COL_DEBUG);}
#define DEBUG3(x,y,z,a)	if(g_debugFlag){engine.AddTextLine(CVString(x,y,z,a),VS_COL_DEBUG);}

#else //_DEBUG

#define DEBUG1
#define DEBUG2
#define DEBUG3

#endif //_DEBUG

#else //INSIDE_LINC

//#include "src\driver96.h"
#include "debug.h"
#include "header.h"

#define DEBUG1				if(g_debugFlag)Zdebug
#define DEBUG2				if(g_debugFlag)Zdebug
#define DEBUG3				if(g_debugFlag)Zdebug

#define ASSERT(x) {if(!(x)){Zdebug("Interpreter ASSERT %s,%d",__FILE__,__LINE__);Con_fatal_error("Assert error in interpreter");}}


#endif


	// Get parameter fix so that the playstation version can handle words not on word boundaries
#define Read16ip(var)			{var = *((int16 *)(code+ip));ip+=sizeof(int16);}
#define Read32ip(var)			{var = *((int32 *)(code+ip));ip+=sizeof(int32);}
#define Read32ipLeaveip(var)		{var = *((int32 *)(code+ip));}

void SetGlobalInterpreterVariables(int32 *vars);

#ifdef INSIDE_LINC			// Are we running in linc?
int RunScript ( MCBOVirtualSword &engine , const char * scriptData , char * /*objectData*/ , uint32 *offset );
#else
int RunScript ( const char * scriptData , char * /*objectData*/ , uint32 *offset );
#endif



//		Command tokens

#define	CT_COMMENT						1				// A program comment
#define	CT_IF							2				// An if statement
#define	CT_OPENBRACKET					3				// (
#define	CT_CLOSEBRACKET					4				// )
#define	CT_VAR							5				// Define a variable
#define	CT_SEMICOLON					6				// ;
#define	CT_COMMA						7				// ,
#define	CT_OPENBRACE					8				// {
#define	CT_CLOSEBRACE					9				// }
#define	CT_STRUCT						10				// Struct
#define	CT_SWITCH						11				// Switch
#define	CT_CASE							12				// Case
#define	CT_BREAK						13				// break
#define	CT_DEFAULT						14				// default
#define	CT_ASSIGN						14				// =
#define	CT_PLUSEQ						15				// '+='
#define	CT_MINUSEQ						16				// '-='
#define	CT_FOR							17				// for
#define	CT_DO							18				// do
#define	CT_WHILE						19				// while
#define	CT_DEBUGON						20				// Turn debugging on
#define	CT_DEBUGOFF						21				// Turn debugging off
#define	CT_QUIT							22				// Quit for a cycle
#define	CT_ENDIF						23				// Endif
#define	CT_TEXTOBJECT					24				// Speaker: text line
#define	CT_ANIM							25				// An animation
#define	CT_ELSE							26				// else to an if
#define	CT_CHOOSE						27				// Start a chooser
#define	CT_END							28				// end, usually followed by something else
#define	CT_END_CHOICE					29				// end choice
#define	CT_TERMINATE					30				// Terminate
#define	CT_PAUSE						31				// Pause
#define	CT_RESTART						32				// Restart script
#define	CT_START						33				// Start conversation
#define	CT_CALL							34				// Call a character
#define	CT_ACTORSCOMMENT				35				// A comment for an actor
#define	CT_TALKER						36				// A set talker command

//		Special functions

#define	SF_RUNLIST						1
#define	SF_DOUBLEQUOTE					2
#define	SF_BACKGROUND					3
#define	SF_SCALEA						4
#define	SF_SCALEB						5
#define	SF_SPEECHSCRIPT					6

//		Compiled tokens

#define	CP_END_SCRIPT					0
#define	CP_PUSH_LOCAL_VAR32				1				// Push a local variable on to the stack
#define	CP_PUSH_GLOBAL_VAR32			2				// Push a global variable
#define	CP_POP_LOCAL_VAR32				3				// Pop a local variable from the stack
#define	CP_CALL_MCODE					4				// Call a machine code function
#define	CP_PUSH_LOCAL_ADDR				5				// Push the address of a local variable
#define	CP_PUSH_INT32					6				// Adjust the stack after calling an fn function
#define	CP_SKIPONFALSE					7				// Skip if the bottom value on the stack is false
#define	CP_SKIPALLWAYS					8				// Skip a block of code
#define	CP_SWITCH						9				// Switch on last stack value
#define	CP_ADDNPOP_LOCAL_VAR32			10				// Add to a local varible
#define	CP_SUBNPOP_LOCAL_VAR32			11				// Subtract to a local variable
#define	CP_SKIPONTRUE					12				// Skip if the bottom value on the stack is true
#define	CP_POP_GLOBAL_VAR32				13				// Pop a global variable
#define	CP_ADDNPOP_GLOBAL_VAR32			14
#define	CP_SUBNPOP_GLOBAL_VAR32			15
#define	CP_DEBUGON						16				// Turn debugging on
#define	CP_DEBUGOFF						17				// Turn debugging off
#define	CP_QUIT							18				// Quit for a cycle
#define	CP_TERMINATE					19				// Quit script completely

//		Operators

#define	OP_ISEQUAL						20				// '=='
#define	OP_PLUS							21				// '+'
#define	OP_MINUS						22				// '-'
#define	OP_TIMES						23				// '*'
#define	OP_DEVIDE						24				// '/'
#define	OP_NOTEQUAL						25				// '=='
#define	OP_ANDAND						26				// &&
#define	OP_GTTHAN						27				// >
#define	OP_LSTHAN						28				// <

//		More tokens, mixed types

#define	CP_JUMP_ON_RETURNED				29				// Use table of jumps with value returned from fn_mcode
#define	CP_TEMP_TEXT_PROCESS			30				// A dummy text process command for me
#define	CP_SAVE_MCODE_START				31				// Save the mcode code start for restarting when necessary
#define	CP_RESTART_SCRIPT				32				// Start the script from the beginning
#define	CP_PUSH_STRING					33				// Push a pointer to a string on the stack
#define	CP_PUSH_DEREFERENCED_STRUCTURE	34				// Push the address of a structure thing

#define	OP_GTTHANE						35				// >=
#define	OP_LSTHANE						36				// <=
#define	OP_OROR							37				// || or OR

--- NEW FILE: layers.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/layers.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//------------------------------------------------------------------------------------
//high level layer initialising

//the system supports:
//		1 optional background parallax layer
//		1 not optional normal backdrop layer
//		3 normal sorted layers
//		up to 2 foreground parallax layers

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

#include "driver/driver96.h"
#include "build_display.h"
#include "console.h"
#include "debug.h"
#include "header.h"
#include "layers.h"
#include "memory.h"
#include "object.h"
#include "protocol.h"
#include "resman.h"
#include "sound.h"	// (James22july97) for Clear_fx_queue() called from FN_init_background()

//------------------------------------------------------------------------------------


screen_info	this_screen;	//this_screen describes the current back buffer and its in-game scroll positions, etc.
//------------------------------------------------------------------------------------
int32 FN_init_background(int32 *params)	//Tony11Sept96
{
//param	0 res id of normal background layer - cannot be 0
//param	1 1 yes 0 no for a new palette
//this screen defines the size of the back buffer

	_multiScreenHeader *screenLayerTable;	// James 06feb97
	_screenHeader	*screen_head;
	_layerHeader	*layer;
 	_spriteInfo		spriteInfo;
	uint32	j;
	uint8	*file;
	uint32	rv;


	//--------------------------------------
	// Write to walkthrough file (zebug0.txt)
	#ifdef _DEBUG
	Zdebug(0,"=====================================");
	Zdebug(0,"CHANGED TO LOCATION \"%s\"", FetchObjectName(*params));
	Zdebug(0,"=====================================");

	// Also write this to system debug file
	Zdebug("=====================================");
	Zdebug("CHANGED TO LOCATION \"%s\"", FetchObjectName(*params));
	Zdebug("=====================================");
	#endif
 	//--------------------------------------

	Clear_fx_queue();		// stops all fx & clears the queue (James22july97)


#ifdef _DEBUG
	Zdebug("FN_init_background(%d)", *params);

	if	(!*params)
	{
		Con_fatal_error("ERROR: FN_set_background cannot have 0 for background layer id! (%s line=%u)",__FILE__,__LINE__);
	}
#endif // _DEBUG


	//-------------------------------------------------------
	// if the screen is still fading down then wait for black
	do
	{
		ServiceWindows();
	}
	while(GetFadeStatus()==RDFADE_DOWN);
	//-------------------------------------------------------

	if (this_screen.mask_flag)	// if last screen was using a shading mask (see below) (James 08apr97)
	{
		rv = CloseLightMask();

		if (rv)
			ExitWithReport("Driver Error %.8x [%s line %u]", rv, __FILE__, __LINE__);
	}
	
	//--------------------------------------------------------
	// New stuff for faster screen drivers (James 06feb97)

	if (this_screen.background_layer_id)	// for drivers: close the previous screen if one is open
		CloseBackgroundLayer();

	//--------------------------------------------------------


	this_screen.background_layer_id=*params;	//set the res id
	this_screen.new_palette = *(params+1);	//yes or no - palette is taken from layer file


//ok, now read the resource and pull out all the normal sort layer info
//and set them up at the beginning of the sort list - why do it each cycle


	file = res_man.Res_open(this_screen.background_layer_id);	//file points to 1st byte in the layer file
	
	screen_head = FetchScreenHeader(file);

	this_screen.number_of_layers= screen_head->noLayers;	//set number of special sort layers
	this_screen.screen_wide = screen_head->width;
	this_screen.screen_deep = screen_head->height;

	Zdebug("res test layers=%d width=%d depth=%d", screen_head->noLayers, screen_head->width, screen_head->height);

	SetLocationMetrics(screen_head->width, screen_head->height);	//initialise the driver back buffer


	if	(screen_head->noLayers)
		for	(j=0;j<screen_head->noLayers;j++)
		{
			layer=FetchLayerHeader(file,j);	//get layer header for layer j

//			add into the sort list

			sort_list[j].sort_y = layer->y+layer->height;	//need this for sorting - but leave the rest blank, we'll take from the header at print time
			sort_list[j].layer_number=j+1;	//signifies a layer

			Zdebug("init layer %d", j);
		}



//using the screen size setup the scrolling variables

	if( ((screen_head->width) > screenWide) || (screen_head->height>screenDeep) )	// if layer is larger than physical screen
	{
		this_screen.scroll_flag = 2;	//switch on scrolling (2 means first time on screen)

//	note, if we've already set the player up then we could do the initial scroll set here

		this_screen.scroll_offset_x = 0;	//reset scroll offsets
		this_screen.scroll_offset_y = 0;

//		calc max allowed offsets (to prevent scrolling off edge) - MOVE TO NEW_SCREEN in GTM_CORE.C !!
		this_screen.max_scroll_offset_x = screen_head->width-screenWide;		// NB. min scroll offsets are both zero
		this_screen.max_scroll_offset_y = screen_head->height-(screenDeep-(RDMENU_MENUDEEP*2));	// 'screenDeep' includes the menu's, so take away 80 pixels
	}
	else	//layer fits on physical screen - scrolling not required
	{
		this_screen.scroll_flag = 0;	//switch off scrolling
		this_screen.scroll_offset_x = 0;	//reset scroll offsets
		this_screen.scroll_offset_y = 0;
	}

	ResetRenderEngine();	//no inter-cycle scrol between new screens (see setScrollTarget in build display)

	// these are the physical screen coords where the system
	// will try to maintain George's actual feet coords
	this_screen.feet_x=320;
	this_screen.feet_y=340;


	//----------------------------------------------------
	// shading mask

	screenLayerTable = (_multiScreenHeader *) ((uint8 *) file + sizeof(_standardHeader));

	if (screenLayerTable->maskOffset)
	{
		spriteInfo.x			= 0;
		spriteInfo.y			= 0;
		spriteInfo.w			= screen_head->width;
		spriteInfo.h			= screen_head->height;
		spriteInfo.scale		= 0;
		spriteInfo.scaledWidth	= 0;
		spriteInfo.scaledHeight	= 0;
		spriteInfo.type			= 0;
		spriteInfo.blend		= 0;
		spriteInfo.data			= FetchShadingMask(file);
		spriteInfo.colourTable	= 0;

		rv = OpenLightMask( &spriteInfo );
		if (rv)
			ExitWithReport("Driver Error %.8x [%s line %u]", rv, __FILE__, __LINE__);

		this_screen.mask_flag=1;	// so we know to close it later! (see above)
	}
	else
		this_screen.mask_flag=0;	// no need to close a mask later

	//----------------------------------------------------

   	res_man.Res_close(this_screen.background_layer_id);	//close the screen file

	SetUpBackgroundLayers();


	Zdebug("end init");
	return(1);
}
//------------------------------------------------------------------------------------
// called from FN_init_background & also from control panel

void SetUpBackgroundLayers(void)	// James(13jun97)
{
	_multiScreenHeader *screenLayerTable;	// James 06feb97
	_screenHeader	*screen_head;
	uint8	*file;


	if (this_screen.background_layer_id)	// if we actually have a screen to initialise (in case called from control panel)
	{
		//------------------------------
		// open resource & set pointers to headers

		file = res_man.Res_open(this_screen.background_layer_id);	//file points to 1st byte in the layer file

		screen_head = FetchScreenHeader(file);

		screenLayerTable = (_multiScreenHeader *) ((uint8 *) file + sizeof(_standardHeader));

		//------------------------------
		// first background parallax

		if (screenLayerTable->bg_parallax[0])
			InitialiseBackgroundLayer(FetchBackgroundParallaxLayer(file,0));
		else
			InitialiseBackgroundLayer(NULL);

		//------------------------------
		// second background parallax

		if (screenLayerTable->bg_parallax[1])
			InitialiseBackgroundLayer(FetchBackgroundParallaxLayer(file,1));
		else
			InitialiseBackgroundLayer(NULL);

		//------------------------------
		// normal backround layer

		InitialiseBackgroundLayer(FetchBackgroundLayer(file));

		//------------------------------
		// first foreground parallax

		if (screenLayerTable->fg_parallax[0])
			InitialiseBackgroundLayer(FetchForegroundParallaxLayer(file,0));
		else
			InitialiseBackgroundLayer(NULL);

		//------------------------------
		// second foreground parallax

		if (screenLayerTable->fg_parallax[1])
			InitialiseBackgroundLayer(FetchForegroundParallaxLayer(file,1));
		else
			InitialiseBackgroundLayer(NULL);

 		//----------------------------------------------------

		res_man.Res_close(this_screen.background_layer_id);	//close the screen file

	 	//----------------------------------------------------
	}
	else	// no current screen to initialise! (In case called from control panel)
	{
	}
}

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------

--- NEW FILE: layers.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/layers.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

#ifndef	_LAYERS
#define	_LAYERS

//#include "src\driver96.h"
#include "memory.h"








typedef	struct
{
	uint16	scroll_offset_x;		// position x
	uint16	scroll_offset_y;		// position y
	uint16	max_scroll_offset_x;	// calc'ed in FN_init_background
	uint16	max_scroll_offset_y;	//
	int16	player_feet_x;			// feet coordinates to use - cant just fetch the player compact anymore
	int16	player_feet_y;
	int16	feet_x;					// special offset-to-player position - tweek as desired - always set in screen manager object startup
	int16	feet_y;
	uint16	screen_wide;			// size of background layer - hense size of back buffer itself (Paul actually malloc's it)
	uint16	screen_deep;
	uint32	background_layer_id;	//id of the normal background layer
	uint16	number_of_layers;		// from the header of the main background layer
	uint8	new_palette;			// set to non zero to start the palette held within layer file fading up after a build_display
	uint8	scroll_flag;			// scroll mode 0 off 1 on
	uint8	mask_flag;				// using shading mask
} screen_info;


extern	screen_info	this_screen;


int32 FN_init_background(int32 *params);	// Tony11Sept96
void SetUpBackgroundLayers(void);			// James(13jun97)	called from control panel (as well as inside FN_init_background)



#endif

--- NEW FILE: logic.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/logic.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//------------------------------------------------------------------------------------
// #include <libsn.h> PSX?
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

//#include "src\driver96.h"
#include "build_display.h"
#include "console.h"
#include "debug.h"
#include "header.h"
#include "interpreter.h"
#include "logic.h"
#include "memory.h"
#include "resman.h"
#include "router.h"	// for ClearWalkGridList()
#include "sound.h"
#include "sword2.h"	// (James19aug97) for CloseGame()
#include "sync.h"

//------------------------------------------------------------------------------------
logic	LLogic;	//declare the object

#define	LEVEL cur_object_hub->logic_level

#define	OBJECT_KILL_LIST_SIZE	50	// this must allow for the largest number of objects in a screen

uint32	object_kill_list[OBJECT_KILL_LIST_SIZE];
uint32	kills=0;	// keeps note of no. of objects in the kill list

//------------------------------------------------------------------------------------
int	logic::Process_session(void)	//Tony6June96 (first run 21Oct96)
{
//do one cycle of the current session



	uint32	run_list;
	uint32	ret,script;
	uint32	*game_object_list;
	char	*raw_script_ad;
	char	*raw_data_ad;
	uint32	null_pc;
	_standardHeader	*head;
	_standardHeader	*far_head;
	uint32	id;

	run_list=current_run_list;	//might change during the session, so take a copy here
	pc=0;	//point to first object in list

	static uint32 cycle=0;


	cycle++;
//	Zdebug("\n CYCLE %d", cycle);

	while(pc!=0xffffffff)	//by minusing the pc we can cause an immediate cessation of logic processing on the current list
	{
		head = (_standardHeader*) res_man.Res_open(run_list);
		if	(head->fileType!=RUN_LIST)
			Con_fatal_error("Logic_engine %d not a run_list", run_list);

		game_object_list = (uint32	*) (head+1);
		ID = game_object_list[pc++];	//read the next id
		id=ID;
		res_man.Res_close(run_list);	//release the list again so it can float in memory - at this point not one thing should be locked


//		Zdebug("%d", ID);

		if	(!ID)	//null terminated
			return(0);	//end the session naturally

		head = (_standardHeader*) res_man.Res_open(ID);
		if	(head->fileType!=GAME_OBJECT)
			Con_fatal_error("Logic_engine %d not an object", ID);

		cur_object_hub = (_object_hub	*) (head+1);

//		Zdebug(" %d id(%d) pc(%d)", cur_object_hub->logic_level, cur_object_hub->script_id[cur_object_hub->logic_level], cur_object_hub->script_pc[cur_object_hub->logic_level]);



//		do the logic for this object
//		we keep going until a function says to stop - remember, system operations are run via function calls to drivers now
		do
		{
			script = cur_object_hub->script_id[LEVEL];	//get the script id as we may be running a script from another object...


//			there is a distinction between running one of our own scripts and that of another object
			if	((script/SIZE)==ID)	//its our script
			{
//				Zdebug("run script %d pc%d", script/SIZE, cur_object_hub->script_pc[LEVEL]);

//				raw_script_ad = (char *) (cur_object_hub+1);	//this is the script data

				raw_script_ad = (char*) head;

				ret=RunScript( raw_script_ad, raw_script_ad, &cur_object_hub->script_pc[LEVEL] );	//script and data object are us/same

			}
			else	//we're running the script of another game object - get our data object address
			{
//				get the foreign objects script data address

				raw_data_ad=(char*)head;

				far_head = (_standardHeader*) res_man.Res_open(script/SIZE);
				if	((far_head->fileType!=GAME_OBJECT)&&((far_head->fileType!=SCREEN_MANAGER)))
					Con_fatal_error("Logic_engine %d not a far object (its a %d)", script/SIZE, far_head->fileType);

//				raw_script_ad = (char*) (head+1) + sizeof(_standardHeader);

//				get our objects data address
//				raw_data_ad = (char*) (cur_object_hub+1);

				raw_script_ad=(char*)far_head;

				ret=RunScript( raw_script_ad, raw_data_ad, &cur_object_hub->script_pc[LEVEL] );

				res_man.Res_close(script/SIZE);	//close foreign object again

				raw_script_ad=raw_data_ad;	//reset to us for service script
			}

			if	(ret==1)	//this script has finished - drop down a level
			{
				if (cur_object_hub->logic_level)	//check that it's not already on level 0 !
					cur_object_hub->logic_level--;
				else	//Hmmm, level 0 terminated :-| Let's be different this time and simply let it restart next go :-)
				{
					cur_object_hub->script_pc[LEVEL]=(cur_object_hub->script_id[LEVEL]&0xffff);	//reset to rerun
//					Zdebug("**WARNING object %d script 0 terminated!", id);
					ret=0;	//cause us to drop out for a cycle
				}
			}
			else	if	(ret>2)
			{
				Con_fatal_error("Process_session: illegal script return type %d (%s line %u)",ret,__FILE__,__LINE__);
			}

//			if ret==2 then we simply go around again - a new script or subroutine will kick in and run

		}
		while(ret);	//keep processing scripts until 0 for quit is returned


//		any post logic system requests to go here

		Clear_syncs(ID);	//clear any syncs that were waiting for this character - it has used them or now looses them

		if	(pc!=0xffffffff)	//the session is still valid so run the service script
		{	null_pc=0;
			RunScript( raw_script_ad, raw_script_ad, &null_pc );	//call the base script - this is the graphic/mouse service call
		}
																				//made for all live objects

//		and that's it so close the object resource
		res_man.Res_close(ID);
	};


	Process_kill_list();	//leaving a room so remove all ids that must reboot correctly

	Zdebug("RESTART the loop");
	

	return(1);	//means restart the loop
}
//------------------------------------------------------------------------------------
void	logic::Express_change_session(uint32	sesh_id)	//Tony6June96
{
//a game-object can bring an immediate halt to the session and cause a new one to start without a screen update

	current_run_list=sesh_id;	//set to new
	pc=0xffffffff;	//causes session to quit

	EXIT_FADING=0;	// reset now in case we double-clicked an exit prior to changing screen

	Init_sync_system();		// we're trashing the list - presumably to change room
							// in theory sync waiting in the list could be left behind and never removed - so we trash the lot

	ClearWalkGridList();	// reset walkgrid list (see FN_register_walkgrid)
	Clear_fx_queue();		// stops all fx & clears the queue
	FreeAllRouteMem();		// free all the route memory blocks from previous game
}
//------------------------------------------------------------------------------------
void	logic::Natural_change_session(uint32	sesh_id)	//Tony7June96
{
//a new session will begin next game cycle.
//the current cycle will conclude and build the screen and flip into view as normal

	current_run_list=sesh_id;	//set to new
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
uint32	logic::Return_run_list(void)	//Tony18Sept96
{
//pass back the private cur_object_list variable - not sure we need this

	return(current_run_list);	//return the id
}
//------------------------------------------------------------------------------------
int32 FN_set_session(int32 *params)	//Tony29Oct96
{
//used by player invoked start scripts

//param	0 id of new run list
	LLogic.Express_change_session(*params);	//now!

	return(IR_CONT);	//cont
}
//------------------------------------------------------------------------------------
int32 FN_end_session(int32 *params)	//Tony21Sept96
{
//causes no more objects in this logic loop to be processed
//the logic engine will restart at the beginning of the new list
// !!the current screen will not be drawn!!

//param	0	id of new run-list

	LLogic.Express_change_session(*params);	//terminate current and change to next run-list

	return(0);	//stop the script - logic engine will now go around and the new screen will begin
}
//------------------------------------------------------------------------------------
void	logic::Logic_up(uint32	new_script)	//Tony23Sept96
{
//move the current object up a level
//called by FN_gosub command - remember, only the logic object has access to cur_object_hub


	cur_object_hub->logic_level++;	//going up a level - and we'll keeping going this cycle

	if	(cur_object_hub->logic_level==3)	//can be 0,1,2
		Con_fatal_error("Logic_up id %d has run off script tree! :-O", ID);

	cur_object_hub->script_id[cur_object_hub->logic_level]=new_script;	//setup new script on next level (not the current level)
	cur_object_hub->script_pc[cur_object_hub->logic_level]=new_script&0xffff;

	//Zdebug("new pc = %d", new_script&0xffff);

}
//------------------------------------------------------------------------------------
void	logic::Logic_one(uint32	new_script)	//Tony4Dec96
{
//force to level one

	cur_object_hub->logic_level=1;

	cur_object_hub->script_id[1]=new_script;	//setup new script on level 1
	cur_object_hub->script_pc[1]=new_script&0xffff;

}
//------------------------------------------------------------------------------------

void	logic::Logic_replace(uint32	new_script)	//Tony13Nov96
{
//change current logic - script must quit with a TERMINATE directive - which does not write to &pc

	cur_object_hub->script_id[cur_object_hub->logic_level]=new_script;	//setup new script on this level
	cur_object_hub->script_pc[cur_object_hub->logic_level]=new_script&0xffff;

}
//------------------------------------------------------------------------------------
uint32	logic::Examine_run_list(void)	//Tony25Oct96
{
	uint32	*game_object_list;
	_standardHeader	*file_header;
	int	scrolls=0;
	char	c;


	if	(current_run_list)
	{
		game_object_list = (uint32	*) (res_man.Res_open(current_run_list)+sizeof(_standardHeader));	//open and lock in place

		Print_to_console("runlist number %d", current_run_list);

		while(*(game_object_list))
		{
			file_header = (_standardHeader*) res_man.Res_open(*(game_object_list));
			Print_to_console(" %d %s",*(game_object_list), file_header->name);
			res_man.Res_close(*(game_object_list++));

			scrolls++;
			Build_display();

			if	(scrolls==18)
			{
				Temp_print_to_console("- Press ESC to stop or any other key to continue");
				Build_display();

				do
				{
			 		//--------------------------------------------------
					// Service windows
					while (!gotTheFocus)
						if (ServiceWindows() == RDERR_APPCLOSED)
							break;

				  	if (ServiceWindows() == RDERR_APPCLOSED)	// if we pressed Ctrl-Q
					{
						Close_game();	//close engine systems down
						RestoreDisplay();
						CloseAppWindow();
						exit(0);	//quit the game
					}
 					//--------------------------------------------------
				}
				while(!KeyWaiting());

				ReadKey(&c);	//kill the key we just pressed
				if	(c==27)	//ESC
					break;

				Clear_console_line();	//clear the Press Esc message ready for the new line
				scrolls=0;
			}


		}




		res_man.Res_close(current_run_list);
	}
	else	Print_to_console("no run list set");


	Scroll_console();
	return(1);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
void	logic::Total_restart(void)	//Tony18Sept96
{
//reset the object restart script 1 on level 0

	cur_object_hub->logic_level=0;

	//cur_object_hub->script_id[0]=1;
	cur_object_hub->script_pc[0]=1;	//reset to rerun

}
//------------------------------------------------------------------------------------
int32 FN_total_restart(int32 *params)	//Tony5Dec96
{
//mega runs this to restart its base logic again - like being cached in again

	LLogic.Total_restart();

	if (params);

	return(IR_TERMINATE);	//drop out without saving pc and go around again
}
//------------------------------------------------------------------------------------
int32 FN_add_to_kill_list(int32 *params)	//James9jan97
{
	// call *once* from object's logic script - ie. in startup code
	// - so not re-called every time script drops off & restarts!

	// mark this object for killing - to be killed when player leaves this screen
	// - so object reloads & script restarts upon re-entry to screen
	// - causes this object's startup logic to be re-run every time we enter the screen
	// - "which is nice"

	// params: none

	uint32 entry;


	if (ID != 8)	// DON'T EVER KILL GEORGE!
	{
		// first, scan list to see if this object is already included (05mar97 James)
		entry=0;
		while ((entry < kills) && (object_kill_list[entry] != ID))
			entry++;

		if (entry == kills)	// if this ID isn't already in the list, then add it, (otherwise finish) (05mar97 James)
		{
			#ifdef _DEBUG
			if (kills == OBJECT_KILL_LIST_SIZE)	// no room at the inn
				Con_fatal_error("List full in FN_add_to_kill_list(%u) (%s line %u)",ID,__FILE__,__LINE__);
			#endif

			object_kill_list[kills] = ID;	// add this 'ID' to the kill list
			kills++;						// "another one bites the dust"

			// when we leave the screen, all these object resources are to be cleaned out of memory
			// and the kill list emptied by doing 'kills=0'
			// - ensuring that all resources are in fact still in memory & more importantly closed
			// before killing!
		}
	}

	return(IR_CONT);	// continue script
}
//------------------------------------------------------------------------------------
void	logic::Process_kill_list(void)	//Tony10Jan97
{

	uint32	j;


	if	(kills)
		for	(j=0;j<kills;j++)
			res_man.Remove_res(object_kill_list[j]);


	kills=0;

}
//------------------------------------------------------------------------------------
void	logic::Reset_kill_list(void)	//James 25mar97
{
	kills=0;
}
//------------------------------------------------------------------------------------


--- NEW FILE: logic.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/logic.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//logic management

#ifndef	_LOGIC
#define	_LOGIC

//#include "src\driver96.h"
#include "defs.h"
#include "header.h"

#define	TREE_SIZE	3



class	logic
{
	public:

	int		Process_session(void);	//do one cycle of the current session
	void	Express_change_session(uint32	sesh_id);	//cause the logic loop to terminate and drop out
	void	Natural_change_session(uint32	sesh_id);	//new logic begins next cycle
	uint32	Return_run_list(void);
	void	Logic_up(uint32	new_script);	//setup script_id and script_pc in cur_object_hub - called by FN_gosub()
	void	Logic_replace(uint32	new_script);
	void	Logic_one(uint32	new_script);
	void	Total_restart(void);
	uint32	Examine_run_list(void);
	void	Reset_kill_list(void);	//James 25mar97


	private:

  	uint32	current_run_list;	//denotes the res id of the game-object-list in current use
	void	Process_kill_list(void);
	uint32	pc;	//pc during logic loop
	_object_hub	*cur_object_hub;	//each object has one of these tacked onto the beginning

};

extern	logic	LLogic;

int32 FN_add_to_kill_list(int32 *params);	//James9jan97

#endif

--- NEW FILE: maketext.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/maketext.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//	MAKETEXT -	Constructs a single-frame text sprite: returns a handle to a
//				FLOATING memory block containing the sprite, given a
//				null-terminated string, max width allowed, pen colour and
//				pointer to required character set.
//
//				NB 1) The routine does not create a standard file header or
//				an anim header for the text sprite - the data simply begins
//				with the frame header.
//
//				NB 2) If pen colour is zero, it copies the characters into the
//				sprite without remapping the colours.
//				ie. It can handle both the standard 2-colour font for speech
//				and any multicoloured fonts for control panels, etc.
//
//	Based on textsprt.c as used for Broken Sword 1, but updated for new system
//	by JEL on 9oct96 and updated again (for font as a resource) on 5dec96.

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define	MAX_LINES		30		// max character lines in output sprite

#define BORDER_COL		200		// source colour for character border (only needed for remapping colours)
#define LETTER_COL		193		// source colour for bulk of character ( " )
#define BORDER_PEN		194		// output colour for character border - should be black ( " ) but note that we have to use a different pen number during sequences

#define NO_COL			0		// sprite background - 0 for transparency!
#define	SPACE			' '
#define	FIRST_CHAR		SPACE	// first character in character set
#define	LAST_CHAR		255		// last character in character set
#define	DUD				64		// the first "chequered flag" (dud) symbol in our character set is in the '@' position
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "driver/driver96.h"
#include "console.h"
#include "debug.h"
#include "defs.h"	// for SPEECH_FONT_ID & CONSOLE_FONT_ID
#include "header.h"
#include "maketext.h"
#include "memory.h"
#include "protocol.h"			// for FetchFrameHeader()
#include "resman.h"

extern uint32 sequenceTextLines;	// see anims.cpp

//-----------------------------------------------------------------------------
typedef struct	// info for each line of words in the output text sprite
{
	uint16	width;	// width of line in pixels
	uint16	length;	// length of line in characters
} _lineInfo;
//-----------------------------------------------------------------------------
// PROTOTYPES
uint16			AnalyseSentence( uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineInfo *line );
mem*			BuildTextSprite( uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line, uint16 noOfLines );
uint16			CharWidth( uint8 ch, uint32 fontRes );
uint16			CharHeight( uint32 fontRes );
_frameHeader*	FindChar( uint8 ch, uint8 *charSet );
void			CopyChar( _frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen );
//-----------------------------------------------------------------------------
// global layout variables - these used to be defines, but now we're dealing with 2 character sets (10dec96 JEL)

int8	line_spacing;	// no. of pixels to separate lines of characters in the output sprite	- negative for overlap
int8	char_spacing;	// no. of pixels to separate characters along each line					- negative for overlap
uint8	border_pen;		// output pen colour of character borders

//-----------------------------------------------------------------------------
// Global font resource id variables, set up in 'SetUpFontResources()' at bottom of this file

uint32 speech_font_id;
uint32 controls_font_id;
uint32 red_font_id;
uint32 death_font_id;

//-----------------------------------------------------------------------------
mem* MakeTextSprite( uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes )
{
	mem		*line;			// handle for the memory block which will contain the array of lineInfo structures
	mem		*textSprite;	// handle for the block to contain the text sprite itself
	uint16	noOfLines;		// no of lines of text required to fit within a sprite of width 'maxWidth' pixels

//	Zdebug("MakeTextSprite( \"%s\", maxWidth=%u )", sentence, maxWidth );

	/////////////////////////////////////////////////////////////////////////////
	// NB. ensure sentence contains no leading/tailing/extra spaces
	// - if necessary, copy to another array first, missing the extra spaces.
	/////////////////////////////////////////////////////////////////////////////

	//----------------------------------------------
	// set the global layout variables (10dec96 JEL)

	if (fontRes == speech_font_id)
	{
		line_spacing	= -6;	// overlap lines by 6 pixels
		char_spacing	= -3;	// overlap characters by 3 pixels
	}
	else if (fontRes == CONSOLE_FONT_ID)
	{
		line_spacing	= 0;	// no space or overlap between lines
		char_spacing	= 1;	// 1 pixel spacing between each character
	}
	else
	{
		line_spacing	= 0;
		char_spacing	= 0;
	}

	if (sequenceTextLines)	// if rendering text over a sequence
		border_pen = 1;		// need a different colour number to BORDER_PEN
	else
		border_pen = BORDER_PEN;

	//----------------------------------------------

	// allocate memory for array of lineInfo structures
	line = Twalloc( MAX_LINES*sizeof(_lineInfo), MEM_locked, UID_temp );	// last param is an optional id for type of mem block

	// get details of sentence breakdown into array of _lineInfo structures
	// and get the no of lines involved
	noOfLines = AnalyseSentence( sentence, maxWidth, fontRes, (_lineInfo *)line->ad );

	// construct the sprite based on the info gathered - returns floating mem block
	textSprite = BuildTextSprite( sentence, fontRes, pen, (_lineInfo *)line->ad, noOfLines );

	// free up the lineInfo array now
	Free_mem( line );

	return( textSprite );
}
//-----------------------------------------------------------------------------
uint16 AnalyseSentence( uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineInfo *line )
{
	uint16 pos=0, wordWidth, wordLength, spaceNeeded, firstWord=TRUE, lineNo=0;
	uint8 ch;
	// joinWidth = how much extra space is needed to append a word to a line
	// NB. SPACE requires TWICE the 'char_spacing' to join a word to line
	uint16 joinWidth = CharWidth( SPACE, fontRes ) + 2*char_spacing;
	

	do
	{
		wordWidth = 0;					// new word
		wordLength = 0;

		ch = sentence[pos++];			// get first char of word (at position 'pos')

		while( (ch != SPACE) && ch )	// while not SPACE or NULL terminator
		{
			// inc wordWidth by (character width + char_spacing) pixels
			wordWidth += CharWidth( ch, fontRes ) + char_spacing;
			wordLength++;
			ch = sentence[pos++];		// get next char
		}

		wordWidth -= char_spacing;		// no char_spacing after final letter of word!

		// 'ch' is now the SPACE or NULL following the word
		// 'pos' indexes to the position following 'ch'


		if( firstWord )		// first word on first line, so no separating SPACE needed
		{
			line[0].width = wordWidth;
			line[0].length = wordLength;
			firstWord = FALSE;
		}
		else
		{
			// see how much extra space this word will need to fit on current line
			// (with a separating space character - also overlapped)
			spaceNeeded = joinWidth + wordWidth;

			if( (line[lineNo].width + spaceNeeded) <= maxWidth )	// fits this line
			{
				line[lineNo].width += spaceNeeded;
				line[lineNo].length += 1+wordLength;	// NB. space+word characters
			}
			else	// put word (without separating SPACE) at start of next line
			{
				lineNo++;							// for next _lineInfo structure in the array
				//debug_only( lineNo < MAX_LINES );	// exception if lineNo >= MAX_LINES
				line[lineNo].width = wordWidth;
				line[lineNo].length = wordLength;
			}
		}
	}
	while( ch );		// while not reached the NULL terminator

	return lineNo+1;	// return no of lines
}

//-----------------------------------------------------------------------------
// Returns a handle to a floating memory block containing a text sprite, given
// a pointer to a null-terminated string, pointer to required character set,
// required text pen colour (or zero to use source colours), pointer to the
// array of linInfo structures created by 'AnalyseSentence()', and the number
// of lines (ie. no. of elements in the 'line' array).

//
//
//	PC Version of BuildTextSprite
//
//

mem* BuildTextSprite( uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line, uint16 noOfLines )
{
	uint8 *linePtr, *spritePtr;
	uint16 lineNo, pos=0, posInLine, spriteWidth=0, spriteHeight, sizeOfSprite;
	uint16 charHeight = CharHeight(fontRes);
	_frameHeader *frameHeadPtr, *charPtr;
	mem *textSprite;
	uint8 *charSet;

	// spriteWidth = width of widest line of output text
	for( lineNo=0; lineNo < noOfLines; lineNo++)
		if( line[lineNo].width > spriteWidth )
			spriteWidth = line[lineNo].width;

	// spriteHeight = tot height of char lines + tot height of separating lines
	spriteHeight = (charHeight*noOfLines + line_spacing*(noOfLines-1));

	// total size (no of pixels)
	sizeOfSprite = spriteWidth * spriteHeight;

	// allocate memory for sprite, and lock it ready for use
	// NB. 'textSprite' is the given pointer to the handle to be used
	textSprite = Twalloc( sizeof(_frameHeader) + sizeOfSprite, MEM_locked, UID_text_sprite );
	// the handle (*textSprite) now points to UNMOVABLE memory block

	// set up the frame header
	frameHeadPtr = (_frameHeader *)textSprite->ad;	// point to the start of our memory block

	frameHeadPtr->compSize	= 0;
	frameHeadPtr->width		= spriteWidth;
	frameHeadPtr->height	= spriteHeight;
	
//	Zdebug("spriteWidth=%u",spriteWidth);
//	Zdebug("spriteHeight=%u",spriteHeight);

	// ok, now point to the start (of the first line) of the sprite data itelf
	linePtr = textSprite->ad + sizeof(_frameHeader);

	// start with transparent sprite (no colour)
	memset( linePtr, NO_COL, sizeOfSprite );


	charSet = res_man.Res_open(fontRes);			// open font file


	// fill sprite with characters, one line at a time
	for( lineNo=0; lineNo < noOfLines; lineNo++ )
	{
		// position the start of the line so that it is centred across the sprite
		spritePtr = linePtr + (spriteWidth - line[lineNo].width) / 2;

		// copy the sprite for each character in this line to the text sprite
		// and inc the sprite ptr by the character's width minus the 'overlap'
		for( posInLine=0; posInLine < line[lineNo].length; posInLine++ )
		{
			charPtr = FindChar( sentence[pos++], charSet );

			#ifdef _DEBUG			
			if ((charPtr->height) != charHeight)
				Con_fatal_error("FONT ERROR: '%c' is not same height as the space (%s line %u)",sentence[pos-1],__FILE__,__LINE__);
			#endif

			CopyChar( charPtr, spritePtr, spriteWidth, pen );
			spritePtr += charPtr->width + char_spacing;
		}

		pos++;	// skip space at end of last word in this line

		// move to start of next character line in text sprite
		linePtr += (charHeight + line_spacing) * spriteWidth;
	}


	res_man.Res_close(fontRes);						// close font file


	// unlock the sprite memory block, so it's movable
	Float_mem( textSprite );

	return( textSprite );
}

//-----------------------------------------------------------------------------
// Returns the width of a character sprite, given the character's ASCII code
// and a pointer to the start of the character set.

uint16 CharWidth( uint8 ch, uint32 fontRes )
{
	_frameHeader *charFrame;
	uint8 *charSet;
	uint16 width;


	charSet = res_man.Res_open(fontRes);	// open font file

	charFrame = FindChar( ch, charSet );	// move to approp. sprite (header)

	width = charFrame->width;

 	res_man.Res_close(fontRes);				// close font file

	return (width);							// return its width
}
//-----------------------------------------------------------------------------
// Returns the height of a character sprite, given the character's ASCII code
// and a pointer to the start of the character set.

uint16 CharHeight( uint32 fontRes )		// assume all chars the same height!
{
	_frameHeader *charFrame;
	uint8 *charSet;
	uint16 height;


	charSet = res_man.Res_open(fontRes);			// open font file

	charFrame = FindChar( FIRST_CHAR, charSet );	// FIRST_CHAR as good as any

	height = charFrame->height;

	res_man.Res_close(fontRes);						// close font file

	return (height);								// return its height
}
//-----------------------------------------------------------------------------
// Returns a pointer to the header of a character sprite, given the character's
// ASCII code and a pointer to the start of the character set.

_frameHeader* FindChar( uint8 ch, uint8 *charSet )
{
	// charSet details:
	// ---------------
	// starts with the standard file header			ie. sizeof(_header) bytes
	// then an int32 giving the no of sprites		ie. 4 bytes
	// then the offset table (an int32 offset for each sprite)
	//  - each offset counting from the start of the file

	if( (ch<FIRST_CHAR) || (ch>LAST_CHAR) )		// if 'ch' out of range
		ch = DUD;								// then print the 'dud' character (chequered flag)

	// address of char = address of charSet + offset to char
	//return (charSet + *(int32 *)(charSet + sizeof(_header) + 4 + 4*(ch - FIRST_CHAR)));
	return (FetchFrameHeader( charSet, ch-FIRST_CHAR ));
}
//-----------------------------------------------------------------------------
// Copies a character sprite from 'charPtr' to the sprite buffer at 'spritePtr'
// of width 'spriteWidth'. If pen is zero, it copies the data across directly,
// otherwise it maps pixels of BORDER_COL to 'border_pen', and LETTER_COL to 'pen'.

void CopyChar( _frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen )
{
	uint8 *rowPtr, *source, *dest;
	uint16 rows, cols;
	

	source = (uint8 *)charPtr + sizeof(_frameHeader);	// now pts to sprite data for char 'ch'
	rowPtr = spritePtr;					// pts to start of first row of char within text sprite

	for( rows=0; rows < charPtr->height; rows++ )
	{
		dest = rowPtr;				// start at beginning of row


		if (pen)	// if required output pen is non-zero
		{
			for( cols=0; cols < charPtr->width; cols++ )
			{
				switch( *source++ )		// inc source ptr along sprite data
				{
					case LETTER_COL:
						*dest = pen;
					break;

					case BORDER_COL:
						if (!(*dest))	// don't do a border pixel if there already a bit of another character underneath (for overlapping!)
							*dest = border_pen;
					break;

					// do nothing if source pixel is zero - ie. transparent
				}
				dest++;			// inc dest ptr to next pixel along row
			}
		}

		else	// pen is zero, so just copy character sprites directly into text sprite without remapping colours
		{
			memcpy( dest, source, charPtr->width );
			source += charPtr->width;
		}			

		rowPtr += spriteWidth;	// next row down (add width of text sprite)
	}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#if _DEBUG
#define	MAX_text_blocs	MAX_DEBUG_TEXT_BLOCKS+1	// allow enough for all the debug text blocks (see debug.cpp)
#else
#define	MAX_text_blocs	2	// only need one for speech, and possibly one for "PAUSED"
#endif	// _DEBUG

typedef	struct
{
	int16	x;
	int16	y;
	uint16	type;	// RDSPR_ status bits - see defintion of _spriteInfo structure for correct size!
	mem	*text_mem;
}	text_bloc;

text_bloc	text_sprite_list[MAX_text_blocs];
//-----------------------------------------------------------------------------
void	Init_text_bloc_system(void)	//Tony16Oct96
{
	uint32	j;

	for	(j=0;j<MAX_text_blocs;j++)
		text_sprite_list[j].text_mem=0;
}
//-----------------------------------------------------------------------------
#define TEXT_MARGIN	12		// distance to keep speech text from edges of screen

uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification)	//Tony31Oct96
{
//creates a text bloc in the list and returns the bloc number
//the list of blocs are read and blitted at render time
//choose alignment type RDSPR_DISPLAYALIGN or 0

	uint32	j=0;
 	_frameHeader *frame_head;
	int16 text_left_margin;
	int16 text_right_margin;
	int16 text_top_margin;
	int16 text_bottom_margin;


//find a free slot
	while((j<MAX_text_blocs)&&(text_sprite_list[j].text_mem))
		j++;

#ifdef _DEBUG
	if	(j==MAX_text_blocs)	//we've run out
		Con_fatal_error("Build_new_block ran out of blocks! (%s line %u)",__FILE__,__LINE__);	//might as well stop the system
#endif


	text_sprite_list[j].text_mem = MakeTextSprite( ascii, width, pen, fontRes );	// make the sprite!


	// speech to be centred above point (x,y), but kept on-screen
	// where (x,y) is a point somewhere just above the talker's head

  	// debug text just to be printed normally from point (x,y)

	//-----------------------------------------------------------
	// JUSTIFICATION & POSITIONING (James updated 20jun97)

	if (justification != NO_JUSTIFICATION)	// 'NO_JUSTIFICATION' means print sprite with top-left at (x,y) without margin checking - used for debug text
	{								
		frame_head = (_frameHeader*) text_sprite_list[j].text_mem->ad;

		switch (justification)
		{
			// this one is always used for SPEECH TEXT; possibly also for pointer text
			case POSITION_AT_CENTRE_OF_BASE:
				x -= (frame_head->width)/2;	// subtract half the sprite-width from the given x-coord
				y -= frame_head->height;	// and the sprite-height from the given y-coord
				break;

 			case POSITION_AT_CENTRE_OF_TOP:
				x -= (frame_head->width)/2;
				break;

   			case POSITION_AT_LEFT_OF_TOP:
				// the given coords are already correct for this!
				break;

   			case POSITION_AT_RIGHT_OF_TOP:
				x -= frame_head->width;
				break;

			case POSITION_AT_LEFT_OF_BASE:
				y -= frame_head->height;
				break;

   			case POSITION_AT_RIGHT_OF_BASE:
				x -= frame_head->width;
				y -= frame_head->height;
				break;

			case POSITION_AT_LEFT_OF_CENTRE:
				y -= (frame_head->height)/2;
   				break;

			case POSITION_AT_RIGHT_OF_CENTRE:
				x -= frame_head->width;
				y -= (frame_head->height)/2;
 				break;
		}

		// ensure text sprite is a few pixels inside the visible screen
		text_left_margin	= TEXT_MARGIN;
		text_right_margin	= 640 - TEXT_MARGIN - frame_head->width;
		text_top_margin		= 0 + TEXT_MARGIN;		// remember - it's RDSPR_DISPLAYALIGN
		text_bottom_margin	= 400 - TEXT_MARGIN - frame_head->height;

		if (x < text_left_margin)	// move if too far left or too far right
			x = text_left_margin;
		else if (x > text_right_margin)
			x = text_right_margin;
			
		if (y < text_top_margin)	// move if too high or too low
			y = text_top_margin;
		else if (y > text_bottom_margin)
			y = text_bottom_margin;
	}
	//-----------------------------------------------------------

	text_sprite_list[j].x = x;
	text_sprite_list[j].y = y;
  	text_sprite_list[j].type = type+RDSPR_NOCOMPRESSION;	// always uncompressed


	return(j+1);
}
//-----------------------------------------------------------------------------

//
//
//	PC Version of Print_text_blocs
//
//

void	Print_text_blocs(void)	//Tony16Oct96
{
//called by build_display

	_frameHeader *frame;
	_spriteInfo		spriteInfo;
	uint32	j;
	uint32	rv;

	for	(j=0;j<MAX_text_blocs;j++)
	{
		if	(text_sprite_list[j].text_mem)
		{
			frame = (_frameHeader*) text_sprite_list[j].text_mem->ad;

			spriteInfo.x			= text_sprite_list[j].x;
			spriteInfo.y			= text_sprite_list[j].y;
			spriteInfo.w			= frame->width;
			spriteInfo.h			= frame->height;
			spriteInfo.scale		= 0;
			spriteInfo.scaledWidth	= 0;
			spriteInfo.scaledHeight	= 0;
			spriteInfo.type			= text_sprite_list[j].type;
			spriteInfo.blend		= 0;
			spriteInfo.data			= text_sprite_list[j].text_mem->ad+sizeof(_frameHeader);
			spriteInfo.colourTable	= 0;

			rv = DrawSprite( &spriteInfo );
			if (rv)
				ExitWithReport("Driver Error %.8x in Print_text_blocs [%s line %u]", rv, __FILE__, __LINE__);
		}
	}
}

//-----------------------------------------------------------------------------
void	Kill_text_bloc(uint32	bloc_number)	//Tony18Oct96
{
	bloc_number--;	//back to real

	if	(text_sprite_list[bloc_number].text_mem)
	{
		Free_mem(text_sprite_list[bloc_number].text_mem);	//release the floating memory
		text_sprite_list[bloc_number].text_mem=0;	//this is how we know the bloc is free
	}
	else
		Con_fatal_error("closing closed text bloc number %d", bloc_number);	//illegal kill - stop the system

}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// called from InitialiseGame() in sword2.cpp
void InitialiseFontResourceFlags(void)	// (James31july97)
{
	uint8 *textFile, *textLine;
	uint8 language;

	#define TEXT_RES		3258	// resource 3258 contains text from location script for 152 (install, save & restore text, etc)
	#define SAVE_LINE_NO	1		// local line number of "save" (actor no. 1826)

#ifndef _DEMO	// normal game
	#define NAME_LINE_NO	54		// local line number of game name (actor no. 3550)
#else
	#define NAME_LINE_NO	451		// local line number of demo game name
#endif	// _DEMO

	//---------------------------------------------------------------------------------
	textFile = res_man.Res_open(TEXT_RES);					// open the text resource
	//---------------------------------------------------------------------------------
	// check if language is Polish or Finnish, and therefore requires alternate fonts

	textLine = FetchTextLine(textFile, SAVE_LINE_NO )+2;	// get the text line (& skip the 2 chars containing the wavId)

	if (strcmp((char*)textLine,"tallenna")==0)		// if this line contains the Finnish for "save"
		language = FINNISH_TEXT;					// - then this version must be Finnish
	else if (strcmp((char*)textLine,"zapisz")==0)	// if this line contains the Polish for "save"
		language = POLISH_TEXT;						// - then this version must be Polish
	else											// neither Finnish nor Polish
		language = DEFAULT_TEXT;					// - use regular fonts

	InitialiseFontResourceFlags(language);			// Set the game to use the appropriate fonts

	//---------------------------------------------------------------------------------
	// Get the game name for the windows application

	textLine = FetchTextLine(textFile, NAME_LINE_NO )+2;	// get the text line (& skip the 2 chars containing the wavId)
	SetWindowName((char*)textLine);							// driver function
	//---------------------------------------------------------------------------------
	res_man.Res_close(TEXT_RES);					// now ok to close the text file
	//---------------------------------------------------------------------------------
}
//------------------------------------------------------------------------------------
// called from the above function, and also from console.cpp
void InitialiseFontResourceFlags(uint8 language)	// (James31july97)
{
	switch (language)
	{
		case FINNISH_TEXT:		// special Finnish fonts
		{
			speech_font_id		= FINNISH_SPEECH_FONT_ID;
			controls_font_id	= FINNISH_CONTROLS_FONT_ID;
			red_font_id			= FINNISH_RED_FONT_ID;
			break;
		}

		case POLISH_TEXT:		// special Polish fonts
		{
			speech_font_id		= POLISH_SPEECH_FONT_ID;
			controls_font_id	= POLISH_CONTROLS_FONT_ID;
			red_font_id			= POLISH_RED_FONT_ID;
			break;
		}

		default:// DEFAULT_TEXT	// regular fonts
		{
			speech_font_id		= ENGLISH_SPEECH_FONT_ID;
			controls_font_id	= ENGLISH_CONTROLS_FONT_ID;
			red_font_id			= ENGLISH_RED_FONT_ID;
			break;
		}
	}
}
//------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------







--- NEW FILE: maketext.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/maketext.h,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

/****************************************************************************
 *	MAKETEXT.H	Function prototype for text sprite builder routine	JEL Oct96
 *
 *	The routine returns a memory handle to a movable memory block containing
 *	the required sprite, which must be locked before use.
 *	ie. lock, draw sprite, unlock/free.
 *	The sprite data contains a frameHeader, but not a standard file header.
 *
 *	Debugger will trap error when word too big for line (maxWidth)
 *	or when more lines needed than max expected (MAX_LINES)
 *
 *	PARAMETERS:
 *
 *	'sentence' points to a NULL-TERMINATED STRING
 *	- string must contain no leading/tailing/extra spaces
 *	- out-of-range characters in the string are forced to the output as a
 *		special error-signal character (chequered flag)
 *
 *	'maxWidth' is the maximum allowed text sprite width, in PIXELS
 *
 *	'pen' is the desired colour (0-255) for the main body of each character
 *	NB. Border colour is #DEFINEd in textsprt.c (to a colour value for BLACK)
 *	if 'pen' is zero, the characters are copied directly and NOT remapped.
 *
 *	'charSet' points to the beginning of the standard file header for the
 *	desired character set
 *	NB. The first and last characters in the set are #DEFINEd in textsprt.c
 *	
 *
 *	RETURNS:
 *
 *	'textSprite' points to the handle to be used for the text sprite
 *
 ****************************************************************************/

#ifndef _MAKETEXT_H
#define _MAKETEXT_H

//#include "src\driver96.h"
#include "memory.h"

#define	NO_JUSTIFICATION			0	// only for debug text, since it doesn't keep text inside the screen margin!
#define POSITION_AT_CENTRE_OF_BASE	1	// these all force text inside the screen edge margin when necessary
#define POSITION_AT_CENTRE_OF_TOP	2
#define POSITION_AT_LEFT_OF_TOP		3
#define POSITION_AT_RIGHT_OF_TOP	4
#define POSITION_AT_LEFT_OF_BASE	5
#define POSITION_AT_RIGHT_OF_BASE	6
#define POSITION_AT_LEFT_OF_CENTRE	7
#define POSITION_AT_RIGHT_OF_CENTRE	8

mem*	MakeTextSprite( uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes );
void	Init_text_bloc_system(void);

void	Kill_text_bloc(uint32 bloc_number);
void	Print_text_blocs(void);	//Tony16Oct96

uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification);

//-----------------------------------------------------------------------------

#define	DEFAULT_TEXT	0
#define FINNISH_TEXT	1
#define POLISH_TEXT		2

void InitialiseFontResourceFlags(void);	// this one works out the language from the text cluster (James31july97)
void InitialiseFontResourceFlags(uint8 language);	// this one allow you to select the fonts yourself (James31july97)

extern uint32 speech_font_id;
extern uint32 controls_font_id;
extern uint32 red_font_id;

//-----------------------------------------------------------------------------

#endif

--- NEW FILE: mem_view.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/mem_view.cpp,v 1.1 2003/07/28 01:44:37 khalek Exp $
 */

//--------------------------------------------------------------------------------------
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
//#include <windows.h>

#include "driver/driver96.h"
#include "build_display.h"
#include "console.h"
#include "debug.h"
#include "defs.h"
#include "header.h"
#include "layers.h"
#include "mem_view.h"
#include "memory.h"
#include "resman.h"
#include "sword2.h"	// (James11aug97) for CloseGame()

//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------

char	buf[50];	//has to be global because a local in Fetch_mem_owner is destroyed on exit
//--------------------------------------------------------------------------------------
void	Console_mem_display(void)	//Tony13Aug96
{
//
	int	pass,found_end,k,j,free=0;
	_standardHeader	*file_header;
	int	scrolls=0;
	char	c;

	char	inf[][20]=
	{
		{"M_null  "},
		{"M_free  "},
		{"M_locked"},
		{"M_float "}
	};


	j=base_mem_block;
	do
	{

		if	(mem_list[j].uid<65536)
		{
			file_header = (_standardHeader*) res_man.Res_open(mem_list[j].uid);
			res_man.Res_close(mem_list[j].uid);	//close immediately so give a true count

			Zdebug("view %d", mem_list[j].uid);


			pass=0;
			found_end=0;

			for	(k=0;k<30;k++)
			{
				if (file_header->name[k]==0)
				{	found_end=1;
					break;
				}

				if ( (file_header->name[k]<32)||(file_header->name[k]>'z'))
					pass=1;

			}

			if	(file_header->name[0]==0)
				pass=1;	//also illegal


			if	((!pass)&&(found_end)) //&&(file_header->fileType<10))
				Print_to_console("%d %s, size 0x%.5x (%dk %d%%), res %d %s %s, A%d, C%d", j, 
					inf[mem_list[j].state],
					mem_list[j].size, mem_list[j].size/1024, (mem_list[j].size*100)/total_free_memory, mem_list[j].uid,

					res_man.Fetch_cluster(mem_list[j].uid),
					file_header->name,
					res_man.Fetch_age(mem_list[j].uid),
					res_man.Fetch_count(mem_list[j].uid));

			else	Print_to_console(" %d is an illegal resource", mem_list[j].uid);

		}
		else
			Print_to_console("%d %s, size 0x%.5x (%dk %d%%), %s", j, 
					inf[mem_list[j].state],
					mem_list[j].size, mem_list[j].size/1024, (mem_list[j].size*100)/total_free_memory,
					Fetch_mem_owner(mem_list[j].uid) );

		if	(mem_list[j].state==MEM_free)
			free+=mem_list[j].size;


		j=mem_list[j].child;

		scrolls++;

		Build_display();


		if	(scrolls==18)
		{
			Temp_print_to_console("- Press ESC to stop or any other key to continue");
			Build_display();

			do
			{
			 	//--------------------------------------------------
				// Service windows
				while (!gotTheFocus)
					if (ServiceWindows() == RDERR_APPCLOSED)
						break;

				if (ServiceWindows() == RDERR_APPCLOSED)	// if we pressed Ctrl-Q
				{
					Close_game();	//close engine systems down
					RestoreDisplay();
					CloseAppWindow();
					exit(0);	//quit the game
				}
 				//--------------------------------------------------
			}
			while(!KeyWaiting());

			ReadKey(&c);	//kill the key we just pressed
			if	(c==27)	//ESC
				break;

			Clear_console_line();	//clear the Press Esc message ready for the new line
			scrolls=0;
		}	
	}
	while	(j!=-1);

	Scroll_console();
	Print_to_console("(total memory block 0x%.8x %dk %dMB) %d / %d%% free", total_free_memory,
				total_free_memory/1024,
				total_free_memory/(1000*1024),
				free,
				(free*100)/total_free_memory);


}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
char	*Fetch_mem_owner(uint32	uid)	//Tony3June96
{

	switch(uid)
	{
		case	UID_memman:
			return("MEMMAN");
			break;

		case	UID_font:
			return("font");
			break;

		case	UID_temp:
			return("temp ram allocation");
			break;

		case	UID_decompression_buffer:
			return("decompression buffer");
			break;

		case	UID_shrink_buffer:
			return("shrink buffer");
			break;

		case	UID_con_sprite:
			return("console sprite buffer");
			break;

		case	UID_text_sprite:
			return("text sprite");
			break;

		case	UID_walk_anim:
			return("walk anim");
			break;

		case	UID_savegame_buffer:
			return("savegame buffer");
			break;

		default:
			sprintf(buf, "<sob> %d?", uid);
			return(buf);
			break;
	}
}

//--------------------------------------------------------------------------------------
void Create_mem_string( char *string )	// James (21oct96 updated 4dec96)
{
	int	blockNo = base_mem_block;
	int blocksUsed=0;
	int	mem_free=0;
	int	mem_locked=0;
	int mem_floating=0;
	int memUsed=0;
	int	percent;



	while (blockNo != -1)
	{
		switch (mem_list[blockNo].state)
		{
			case MEM_free:
				mem_free++;
				break;

			case MEM_locked:
				mem_locked++;
				memUsed += mem_list[blockNo].size;
				break;

			case MEM_float:
				mem_floating++;
				memUsed += mem_list[blockNo].size;
				break;
		}

		blocksUsed++;
		blockNo = mem_list[blockNo].child;
	}

	percent =  (memUsed * 100) / total_free_memory;

	sprintf( string, "locked(%u)+float(%u)+free(%u) = %u/%u blocks (%u%% used)(cur %uk)", mem_locked, mem_floating, mem_free, blocksUsed, MAX_mem_blocks, percent, (res_man.Res_fetch_useage()/1024) );
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------

--- NEW FILE: mem_view.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/mem_view.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	MEMVIEW_H
#define	MEMVIEW_H

//#include	"src\driver96.h"


char	*Fetch_mem_owner(uint32	uid);
void	Console_mem_display(void);					// Tony (13Aug96)
void	Create_mem_string( char *string );			// James (21oct96 updated 4dec96)


#endif

--- NEW FILE: memory.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/memory.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//memory manager -	"remember, it's not good to leave memory locked for a moment longer than necessary" Tony
//					"actually, in a sequential system theoretically you never need to lock any memory!" Chris ;)
//
//					This is a very simple implementation but I see little advantage to being any cleverer
//					with the coding - i could have put the mem blocks before the defined blocks instead
//					of in an array and then used pointers to child/parent blocks. But why bother? I've Kept it simple.
//					When it needs updating or customising it will be accessable to anyone who looks at it.
//					*doesn't have a purgeable/age consituant yet - if anyone wants this then I'll add it in.


//					MemMan v1.1

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

#include "driver/driver96.h"
#include "console.h"
#include "debug.h"
#include "memory.h"
#include "resman.h"


uint32	total_blocks;
uint32	base_mem_block;
uint32	total_free_memory;
uint8	*free_memman;	//address of init malloc to be freed later

//#define	MEMDEBUG	1

mem	mem_list[MAX_mem_blocks];	//list of defined memory handles - each representing a block of memory.

int32 VirtualDefrag( uint32 size );	// Used to determine if the required size can be obtained if the defragger is allowed to run.
int32 suggestedStart = 0;			// Start position of the Defragger as indicated by its sister VirtualDefrag.

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
void	Close_memory_manager(void)	//Tony2Oct96
{

//unlock our supposedly locked in memory
	VirtualUnlock(free_memman, total_free_memory);

	free(free_memman);
}
//------------------------------------------------------------------------------------
void	Init_memory_manager(void)	//Tony9April96
{
	uint32	j;
	uint8	*memory_base;
	//BOOL			res;
	MEMORYSTATUS	memo;

//find out how much actual physical RAM this computer has
	GlobalMemoryStatus(&memo);

//now decide how much to grab - 8MB computer are super critical
	if	(memo.dwTotalPhys<=(8000*1024))	//if 8MB or less :-O
		total_free_memory=4500*1024;	//4.5MB

	else if	(memo.dwTotalPhys<=(12000*1024))	//if 8MB or less :-O
		total_free_memory=8000*1024;	//8MB

	else	if	(memo.dwTotalPhys<=(16000*1024))	//if 16MB or less :-)
		total_free_memory=10000*1024;	//10MB

	else	//:-)) loads of RAM
		total_free_memory=12000*1024;	//12MB



	Zdebug("MEM = %d", memo.dwTotalPhys);
	Zdebug("Sword 2 grabbed %dk", total_free_memory/1024);



//malloc memory and adjust for long boundaries
	memory_base = (uint8	*)	malloc(total_free_memory);

	if	(!memory_base)	//could not grab the memory
	{
		Zdebug("couldn't malloc %d in Init_memory_manager", total_free_memory);
		ExitWithReport("Init_memory_manager() couldn't malloc %d bytes [line=%d file=%s]",total_free_memory,__LINE__,__FILE__);
	}

	free_memman = memory_base;	//the original malloc address

//force to long word boundary
	memory_base+=3;
	memory_base = (uint8 *)((uint32)memory_base & 0xfffffffc);	// ** was (int)memory_base
//	total_free_memory-=3;	//play safe



//set all but first handle to unused
	for	(j=1;j<MAX_mem_blocks;j++)
		mem_list[j].state=MEM_null;


	total_blocks=1;	//total used (free, locked or floating)

	mem_list[0].ad = memory_base;
	mem_list[0].state= MEM_free;
	mem_list[0].age=0;
	mem_list[0].size=total_free_memory;
	mem_list[0].parent=-1;	//we are base - for now
	mem_list[0].child=-1;	//we are the end as well
	mem_list[0].uid=UID_memman;	//init id

	base_mem_block=0;	//for now


//supposedly this will stop the memory swapping out?? Well, as much as we're allowed
//	res=VirtualLock(free_memman, total_free_memory);

//	if	(res!=TRUE)
//		Zdebug(" *VirtualLock failed");
}
//------------------------------------------------------------------------------------
mem	*Talloc(uint32	size,	uint32	type,	uint32	unique_id)	//Tony10Apr96
{
//allocate a block of memory - locked or float

//	returns 0 if fails to allocate the memory
//			or a pointer to a mem structure

	int32	nu_block;
	uint32	spawn=0;
	uint32	slack;





//we must first round the size UP to a dword, so subsequent blocks will start dword alligned
	size+=3;	//move up
	size &= 0xfffffffc;	//and back down to boundary




//find a free block large enough
	if	( (nu_block = Defrag_mem(size))==-1)	//the defragger returns when its made a big enough block. This is a good time to defrag as we're probably not
	{											//doing anything super time-critical at the moment
		return(0);	//error - couldn't find a big enough space
	}



//an exact fit?
	if	(mem_list[nu_block].size==size)	//no new block is required as the fit is perfect
	{
		mem_list[nu_block].state=type;	//locked or float
		mem_list[nu_block].size=size;	//set to the required size
		mem_list[nu_block].uid=unique_id;	//an identifier

#ifdef	MEMDEBUG
		Mem_debug();
#endif	//MEMDEBUG
		return(&mem_list[nu_block]);
	}


//	nu_block is the free block to split, forming our locked/float block with a new free block in any remaining space


//if our child is free then is can expand downwards to eat up our chopped space
//this is good because it doesn't create an extra bloc so keeping the block count down
//why?
//imagine you Talloc 1000k, then free it. Now keep allocating 10 bytes less and freeing again
//you end up with thousands of new free mini blocks. this way avoids that as the free child keeps growing downwards
	if	((mem_list[nu_block].child != -1) && (mem_list[mem_list[nu_block].child].state==MEM_free))	//our child is free
	{
		slack=mem_list[nu_block].size-size;	//the spare memory is the blocks current size minus the amount we're taking

		mem_list[nu_block].state=type;	//locked or float
		mem_list[nu_block].size=size;	//set to the required size
		mem_list[nu_block].uid=unique_id;	//an identifier

		mem_list[mem_list[nu_block].child].ad = mem_list[nu_block].ad+size;	//child starts after us
		mem_list[mem_list[nu_block].child].size += slack;	//childs size increases

		return(&mem_list[nu_block]);
	}


// otherwise we spawn a new block after us and before our child - our child being a proper block that we cannot change

//	we remain a child of our parent
//	we spawn a new child and it inherits our current child

//find a NULL slot for a new block
	while((mem_list[spawn].state!=MEM_null)&&(spawn!=MAX_mem_blocks))
		spawn++;


	if	(spawn==MAX_mem_blocks)	//run out of blocks - stop the program. this is a major blow up and we need to alert the developer
	{
		Mem_debug();	//Lets get a printout of this
		ExitWithReport("ERROR: ran out of mem blocks in Talloc() [file=%s line=%u]",__FILE__,__LINE__);
	}



	mem_list[spawn].state=MEM_free;	//new block is free
	mem_list[spawn].uid=UID_memman;	//a memman created bloc
	mem_list[spawn].size= mem_list[nu_block].size-size;	//size of the existing parent free block minus the size of the new space Talloc'ed.
														//IOW the remaining memory is given to the new free block
	mem_list[spawn].ad = mem_list[nu_block].ad+size;	//we start 1 byte after the newly allocated block
	mem_list[spawn].parent=nu_block;	//the spawned child gets it parent - the newly allocated block

	mem_list[spawn].child=mem_list[nu_block].child;	//the new child inherits the parents old child (we are its new child "Waaaa")



	if	(mem_list[spawn].child!=-1)	//is the spawn the end block?
		mem_list[mem_list[spawn].child].parent= spawn;	//the child of the new free-spawn needs to know its new parent


	mem_list[nu_block].state=type;	//locked or float
	mem_list[nu_block].size=size;	//set to the required size
	mem_list[nu_block].uid=unique_id;	//an identifier
	mem_list[nu_block].child=spawn;	//the new blocks new child is the newly formed free block


	total_blocks++;	//we've brought a new block into the world. Ahhh!


#ifdef	MEMDEBUG
	Mem_debug();
#endif	//MEMDEBUG

	return(&mem_list[nu_block]);
}
//------------------------------------------------------------------------------------
void	Free_mem(mem	*block)	//Tony10Apr96
{
//kill a block of memory - which was presumably floating or locked
//once you've done this the memory may be recycled

	block->state=MEM_free;
	block->uid=UID_memman;	//belongs to the memory manager again

#ifdef	MEMDEBUG
	Mem_debug();
#endif	//MEMDEBUG
}
//------------------------------------------------------------------------------------
void	Float_mem(mem	*block)	//Tony10Apr96
{
//set a block to float
//wont be trashed but will move around in memory

	block->state=MEM_float;

#ifdef	MEMDEBUG
	Mem_debug();
#endif	//MEMDEBUG
}
//------------------------------------------------------------------------------------
void	Lock_mem(mem	*block)	//Tony11Apr96
{
//set a block to lock
//wont be moved - don't lock memory for any longer than necessary unless you know the locked memory is at the bottom of the heap

	block->state=MEM_locked;	//can't move now - this block is now crying out to be floated or free'd again

#ifdef	MEMDEBUG
	Mem_debug();
#endif	//MEMDEBUG
}
//------------------------------------------------------------------------------------
int32	Defrag_mem(uint32	req_size)	//Tony10Apr96
{
//moves floating blocks down and/or merges free blocks until a large enough space is found
//or there is nothing left to do and a big enough block cannot be found
//we stop when we find/create a large enough block - this is enough defragging.

	int32	cur_block;	//block 0 remains the parent block
	int32	original_parent,child, end_child;
	uint32	j;
	uint32	*a;
	uint32	*b;


//	cur_block=base_mem_block;	//the mother of all parents
	cur_block = suggestedStart;


	do
	{
		if	(mem_list[cur_block].state==MEM_free)	//is current block a free block?
		{

			if	(mem_list[cur_block].size>=req_size)
			{
				return(cur_block);	//this block is big enough - return its id
			}


			if	(mem_list[cur_block].child==-1)	//the child is the end block - stop if the next block along is the end block
				return(-1);	//no luck, couldn't find a big enough block


//			current free block is too small, but if its child is *also* free then merge the two together
			if	(mem_list[mem_list[cur_block].child].state==MEM_free)
			{
//				ok, we nuke the child and inherit its child

				child=mem_list[cur_block].child;

				mem_list[cur_block].size+= mem_list[child].size;	//our size grows by the size of our child
				mem_list[cur_block].child = mem_list[child].child;	//our new child is our old childs, child

				if	(mem_list[child].child!=-1)	//not if the chld we're nuking is the end child (it has no child)
					mem_list[mem_list[child].child].parent=cur_block;	//the (nuked) old childs childs parent is now us

				mem_list[child].state=MEM_null;	//clean up the nuked child, so it can be used again

				total_blocks--;
			}


//			current free block is too small, but if its child is a float then we move the floating memory block down and the free up
//			but, parent/child relationships must be such that the memory is all continuous between blocks. ie. a childs memory always
//			begins 1 byte after its parent finishes. However, the positions in the memory list may become truly random, but, any particular
//			block of locked or floating memory must retain its position within the mem_list - the float stays a float because the handle/pointer has been passed back
//			what this means is that when the physical memory of the foat moves down (and the free up) the child becomes the parent and the parent the child
//			but, remember, the parent had a parent and the child another child - these swap over too as the parent/child swap takes place - phew.
			else	if	(mem_list[mem_list[cur_block].child].state==MEM_float)
			{
				child=mem_list[cur_block].child;	//our child is currently floating

			//	memcpy(mem_list[cur_block].ad, mem_list[child].ad, mem_list[child].size);	//move the higher float down over the free block


				a=(uint32*) mem_list[cur_block].ad;
				b=(uint32*) mem_list[child].ad;

				for	(j=0;j<mem_list[child].size/4;j++)
					*(a++)=*(b++);


//				both *ad's change
				mem_list[child].ad = mem_list[cur_block].ad;	//the float is now where the free was
				mem_list[cur_block].ad += mem_list[child].size;	//and the free goes up by the size of the float (which has come down)

//				the status of the mem_list blocks must remain the same, so...
				original_parent= mem_list[cur_block].parent;	//our child gets this when we become its child and it our parent
				mem_list[cur_block].parent=child;	//the free's child becomes its parent
				mem_list[cur_block].child= mem_list[child].child;	//the new child inherits its previous childs child

				end_child=mem_list[child].child;	//save this - see next line

				mem_list[child].child=cur_block;		//the floats parent becomes its child
				mem_list[child].parent= original_parent;

				if	(end_child!=-1)	//if the child had a child
					mem_list[end_child].parent=cur_block;	//then its parent is now the new child

				if	(original_parent==-1)	//the base block was the true base parent
					base_mem_block=child;	//then the child that has moved down becomes the base block as it sits at the lowest possible memory location
				else
					mem_list[original_parent].child=child;	//otherwise the parent of the current free block - that is now the child - gets a new child,
															//that child being previously the child of the child of the original parent
			}
			else	//if	(mem_list[mem_list[cur_block].child].state==MEM_lock)	//the child of current is locked - move to it
				cur_block=mem_list[cur_block].child;	//move to next one along - either locked or END

		}
		else
		{
			cur_block=mem_list[cur_block].child;	//move to next one along, the current must be floating, locked, or a NULL slot
		}

	}
	while(cur_block!=-1);	//while the block we've just done is not the final block

	return(-1);	//no luck, couldn't find a big enough block
}
//------------------------------------------------------------------------------------
void	Mem_debug(void)	//Tony11Apr96
{
//gets called with Talloc, Mem_free, Mem_lock & Mem_float if MEMDEBUG has been #defined
//otherwise can be called at any time anywhere else

	int	j;
	char	inf[][20]=
	{
		{"MEM_null"},
		{"MEM_free"},
		{"MEM_locked"},
		{"MEM_float"}
	};

	Zdebug("\nbase %d total %d", base_mem_block, total_blocks);


//first in mem list order
	for	(j=0;j<MAX_mem_blocks;j++)
	{
		if	(mem_list[j].state==MEM_null)
			Zdebug("%d- NULL", j);
		else
			Zdebug("%d- state %s, ad %d, size %d, p %d, c %d, id %d", j, 
				inf[mem_list[j].state],
				 mem_list[j].ad, mem_list[j].size, mem_list[j].parent, mem_list[j].child, mem_list[j].uid);
	}


//now in child/parent order
	j=base_mem_block;
	do
	{
		Zdebug(" %d- state %s, ad %d, size %d, p %d, c %d", j, 
			inf[mem_list[j].state],
			 mem_list[j].ad, mem_list[j].size, mem_list[j].parent, mem_list[j].child, mem_list[j].uid);

		j=mem_list[j].child;
	}
	while	(j!=-1);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
mem	*Twalloc(uint32	size,	uint32	type,	uint32	unique_id)	//tony12Feb97
{
//the high level Talloc
//can ask the resman to remove old resources to make space - will either do it or halt the system

	mem	*membloc;
	int	j;
	uint32	free=0;

	while( VirtualDefrag(size) )
	{
		if	(!res_man.Help_the_aged_out())	//trash the oldest closed resource
		{
			Zdebug("Twalloc ran out of memory! %d %d %d\n", size, type, unique_id);
			ExitWithReport("Twalloc ran out of memory!");
		}
	}

	membloc = Talloc(size, type, unique_id);

	if (membloc == 0)
	{
		Zdebug("Talloc failed to get memory VirtualDefrag said was there");
		ExitWithReport("Talloc failed to get memory VirtualDefrag said was there");
	}

	j=base_mem_block;
	do
	{

		if	(mem_list[j].state==MEM_free)
			free+=mem_list[j].size;

		j=mem_list[j].child;
	}
	while	(j!=-1);

	return(membloc);	//return the pointer to the memory
}


#define MAX_WASTAGE	51200			// Maximum allowed wasted memory.

int32 VirtualDefrag( uint32 size )	// Chris - 07 April '97
{
	//
	//	Virutually defrags memory...
	//
	//	Used to determine if there is potentially are large enough free block available is the
	//	real defragger was allowed to run.
	//
	//	The idea being that Twalloc will call this and help_the_aged_out until we indicate that
	//	it is possible to obtain a large enough free block. This way the defragger need only 
	//	run once to yield the required block size.
	//
	//	The reason for its current slowness is that the defragger is potentially called several
	//	times, each time shifting upto 20Megs around, to obtain the required free block.
	//
	int32	cur_block;	
	uint32	currentBubbleSize = 0;

	cur_block=base_mem_block;
	suggestedStart = base_mem_block;

	do
	{
		if	(mem_list[cur_block].state == MEM_free)
		{
			// Add a little intelligence. At the start the oldest resources are at the bottom of the
			// tube. However there will be some air at the top. Thus bubbles will be 
			// created at the bottom and float to the top. If we ignore the top gap
			// then a large enough bubble will form lower down the tube. Thus less memory
			// will need to be shifted.

			if (mem_list[cur_block].child != -1)
				currentBubbleSize += mem_list[cur_block].size;
			else if (mem_list[cur_block].size > MAX_WASTAGE)
				currentBubbleSize += mem_list[cur_block].size;

			if (currentBubbleSize >= size)
				return 0;
		}
		else if (mem_list[cur_block].state == MEM_locked)
		{
			currentBubbleSize = 0;
			suggestedStart    = mem_list[cur_block].child;	// Any free block of the correct size will be above this locked block.
		}

		cur_block = mem_list[cur_block].child;
	}
	while(cur_block != -1);	

	return(1);
}

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------

--- NEW FILE: memory.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/memory.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	MEMORY_H
#define	MEMORY_H

#include "common/scummsys.h"
//#include "src\driver96.h"


typedef	struct
{
	uint32	state;
	uint32	age;	// *not used*
	uint32	size;
	int32	parent;	//who is before us
	int32	child;	//who is after us
	uint32	uid;	//id of a position in the resList or some other unique id - for the visual display only
	uint8	*ad;
} mem;


#define	MEM_null	0	//null
#define	MEM_free	1
#define	MEM_locked	2
#define	MEM_float	3

//---------------------------------------
// MEMORY BLOCKS

#define	MAX_mem_blocks	999

// maintain at a good 50% higher than the
// highest recorded value from the on-screen info
//---------------------------------------

#define	UID_memman					0xffffffff
#define	UID_NULL					0xfffffffe			//FREE
#define	UID_font					0xfffffffd
#define	UID_temp					0xfffffffc
#define	UID_decompression_buffer	0xfffffffb
#define	UID_shrink_buffer			0xfffffffa
#define	UID_con_sprite				0xfffffff9
#define	UID_text_sprite				0xfffffff8
#define	UID_walk_anim				0xfffffff7
#define	UID_savegame_buffer			0xfffffff6
#define UID_restoregame_buffer		0xfffffff5

void	Init_memory_manager(void);
void	Close_memory_manager(void);	//Tony2Oct96
//mem	*Talloc(uint32	size,	uint32	type,	uint32	unique_id);	//low level
mem	*Twalloc(uint32	size,	uint32	type,	uint32	unique_id);	//high level
void	Free_mem(mem	*block);
void	Float_mem(mem	*block);
void	Lock_mem(mem	*block);
void	Mem_debug(void);
void	Visual_mem_display(void);
int32	Defrag_mem(uint32	req_size);	//Tony10Apr96


extern	uint32	total_blocks;
extern	uint32	base_mem_block;
extern	mem	mem_list[MAX_mem_blocks];
extern	uint32	total_free_memory;

#endif

--- NEW FILE: module.mk ---
MODULE := bs2

MODULE_OBJS = \
	bs2/anims.o \
	bs2/build_display.o \
	bs2/console.o \
	bs2/controls.o \
	bs2/debug.o \
	bs2/events.o \
	bs2/function.o \
	bs2/icons.o \
	bs2/interpreter.o \
	bs2/layers.o \
	bs2/logic.o \
	bs2/maketext.o \
	bs2/memory.o \
	bs2/mem_view.o \
	bs2/mouse.o \
	bs2/protocol.o \
	bs2/resman.o \
	bs2/router.o \
	bs2/save_rest.o \
	bs2/scroll.o \
	bs2/sound.o \
	bs2/speech.o \
	bs2/startup.o \
	bs2/sword2.o \
	bs2/sync.o \
	bs2/tony_gsdk.o \
	bs2/walker.o \
	bs2/driver/_console.o \
	bs2/driver/d_draw.o \
	bs2/driver/d_sound.o \
	bs2/driver/keyboard.o \
	bs2/driver/language.o \
	bs2/driver/menu.o \
	bs2/driver/misc.o \
	bs2/driver/_mouse.o \
	bs2/driver/palette.o \
	bs2/driver/rdwin.o \
	bs2/driver/render.o \
	bs2/driver/sprite.o
	

# Include common rules 
include common.rules

--- NEW FILE: mouse.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/mouse.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

[...1427 lines suppressed...]
int32 FN_reset_player_activity_delay(int32 *params)	// James23july97
{
// Use if you want to deliberately reset the "no player activity" counter for any reason

//	no params

	player_activity_delay=0;	// reset activity delay counter

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
void Monitor_player_activity(void)	// James23july97
{
	if (CheckForMouseEvents())	// if there is at least one mouse event outstanding
		player_activity_delay=0;	// reset activity delay counter
	else
		player_activity_delay++;	// no. of game cycles since mouse event queue last empty
}
//---------------------------------------------------------------------------------------------------------------------


--- NEW FILE: mouse.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/mouse.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//mouse stuff

#ifndef MOUSE_H
#define MOUSE_H

//#include	"src\driver96.h"
#include	"object.h"

//---------------------------------------------------------------------------------
#define	TOTAL_mouse_list	50

#define	MOUSE_normal		0
#define	MOUSE_top			1
#define	MOUSE_drag			2
#define	MOUSE_system_menu	3
#define	MOUSE_holding		4
//---------------------------------------------------------------------------------
// mouse unit - like Object_mouse, but with anim resource & pc (needed if sprite is to act as mouse detection mask)
typedef	struct
{
	int32	x1;				// top-left of mouse area is (x1,y1)
	int32	y1;
	int32	x2;				// bottom-right of area is (x2,y2)	(these coords are inclusive)
	int32	y2;
	int32	priority;
	int32	pointer;		// type (or resource id?) of pointer used over this area
	// up to here, this is basically a copy of the Object_mouse structure, but then we have...
	int32	id;				// object id, used when checking mouse list
	int32	anim_resource;	// resource id of animation file (if sprite to be used as mask) - otherwise 0
	int32	anim_pc;		// current frame number of animation
	int32	pointer_text;	// local id of text line to print when pointer highlights an object
} Mouse_unit;
//---------------------------------------------------------------------------------
extern	uint32	cur_mouse;
extern	Mouse_unit mouse_list[TOTAL_mouse_list];
extern	uint32	mouse_touching;
extern	uint32	mouse_mode;
extern	uint8	examining_menu_icon;

extern	uint32	mouse_status;	//human 0 on/1 off
extern	uint32	mouse_mode_locked;	//0 not !0 mode cannot be changed from normal mouse to top menu (i.e. when carrying big objects)

extern	uint32	real_luggage_item;	//last minute for pause mode

extern	uint32	pointerTextSelected;

//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
void	Reset_mouse_list(void);	//Tony26Sept96

void	Normal_mouse(void);	//Tony30Sept96
void	Top_menu_mouse(void);	//Tony3Oct96
void	Drag_mouse(void);	//Tony21Nov96
void	System_menu(void);	//Tony19Mar97

void	Mouse_on_off(void);	//Tony30Sept96
uint32	Check_mouse_list(void);	//Tony30Sept96
void	Mouse_engine(void);	//Tony30Sept96

void	Set_mouse(uint32 res);
void	Set_luggage(uint32	res);	//Tony26Nov96

int32 FN_no_human(int32 *params);	//Tony30Sept96
int32 FN_add_human(int32 *params);	//Tony30Sept96

void ClearPointerText(void);		// James16jun97
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
#endif

--- NEW FILE: object.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/object.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	_SCRIPT_STRUCTURES
#define	_SCRIPT_STRUCTURES

#include "driver/driver96.h"

// these structures represent the broken up compact components
// these here declared to the system must be the same as those declared to LINC (or it wont work)


// mouse structure - defines mouse detection area, detection priority & 'type' flag
typedef	struct
{
	int32	x1;				// top-left of mouse area is (x1,y1)
	int32	y1;
	int32	x2;				// bottom-right of area is (x2,y2)	(these coords are inclusive)
	int32	y2;
	int32	priority;
	int32	pointer;		// type (or resource id?) of pointer used over this area
} Object_mouse;


// logic structure - contains fields used in logic script processing
typedef	struct
{
	int32	looping;		// 0 when first calling FN_<function>;  1 when calling subsequent times in same loop
	int32	pause;			// pause count, used by FN_pause()
} Object_logic;

//------------------------------------------------
// status bits for 'type' field of Object_graphic)
// in low word:
#define	NO_SPRITE		0x00000000	// don't print
#define	BGP0_SPRITE		0x00000001	// fixed to background parallax[0]
#define	BGP1_SPRITE		0x00000002	// fixed to background parallax[1]
#define	BACK_SPRITE		0x00000004	// 'background' sprite, fixed to main background
#define	SORT_SPRITE		0x00000008	// 'sorted' sprite, fixed to main background
#define	FORE_SPRITE		0x00000010	// 'foreground' sprite, fixed to main background
#define	FGP0_SPRITE		0x00000020	// fixed to foreground parallax[0]
#define	FGP1_SPRITE		0x00000040	// fixed to foreground parallax[0]

// in high word:
#define UNSHADED_SPRITE	0x00000000	// not to be shaded
#define SHADED_SPRITE	0x00010000	// to be shaded, based on shading mask
//------------------------------------------------

// graphic structure - contains fields appropriate to sprite output
typedef	struct
{
	int32	type;			// see above
	int32	anim_resource;	// resource id of animation file
	int32	anim_pc;		// current frame number of animation
} Object_graphic;


// speech structure - contains fields used by speech scripts & text output
typedef	struct
{
	int32	pen;			// colour to use for body of characters
	int32	width;			// max width of text sprite
	int32	command;		// speech script command id
	int32	ins1;			// speech script instruction parameters (may need more now?)
	int32	ins2;
	int32	ins3;
	int32	ins4;
	int32	ins5;
	int32	wait_state;	//0 not waiting	1 waiting for next speech command
} Object_speech;


// mega structure - contains fields used for mega-character & mega-set processing
typedef	struct
{
	int32	NOT_USED_1;			// only free roaming megas need to check this before registering their graphics for drawing
	int32	NOT_USED_2;			// id of floor on which we are standing
	int32	NOT_USED_3;			// id of object which we are getting to
	int32	NOT_USED_4;			// pixel distance to stand from player character when in conversation
	int32	currently_walking;	// number given us by the auto router
	int32	walk_pc;			// current frame number of walk-anim
	int32	scale_a;			// current scale factors, taken from floor data
	int32	scale_b;
	int32	feet_x;				// mega feet coords - frame-offsets are added to these position mega frames
	int32	feet_y;
	int32	current_dir;		// current dirction faced by mega; used by autorouter to determine turns required
	int32	colliding;			// means were currently avoiding a collision (see FN_walk)
	int32	megaset_res;		// resource id of mega-set file
	int32	NOT_USED_5;			// NOT USED
} Object_mega;


// walk-data structure - contains details of layout of frames in the mega-set, and how they are to be used
typedef struct
{
	int32	nWalkFrames;				// no. of frames per walk-cycle
	int32	usingStandingTurnFrames;	// 0=no  1=yes
	int32	usingWalkingTurnFrames;		// 0=no  1=yes
	int32	usingSlowInFrames;			// 0=no  1=yes
	int32	usingSlowOutFrames;			// 0=no  !0=number of slow-out frames in each direction
	int32	nSlowInFrames[8];			// no. of slow-in frames in each direction
	int32	leadingLeg[8];				// leading leg for walk	in each direction  (0=left  1=right)
	int32	dx[8*(12+1)];				// walk step distances in x direction
	int32	dy[8*(12+1)];				// walk step distances in y direction
} Object_walkdata;


#endif

--- NEW FILE: protocol.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/protocol.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#include <stdio.h>
//#include <windows.h>

//#include "src\driver96.h"
#include "console.h"
#include "debug.h"
#include "defs.h"
#include "header.h"
#include "logic.h"
#include "memory.h"
#include "protocol.h"
#include "resman.h"

//-----------------------------------------------------------------------------------------------------------------------
// returns a pointer to the first palette entry, given the pointer to the start of the screen file
// assumes it has been passed a pointer to a valid screen file
uint8 *FetchPalette(uint8 *screenFile)	// Chris 04Oct96
{
	uint8 *palette;

	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

	palette = (uint8 *)mscreenHeader + mscreenHeader->palette;

	palette[0] = 0;	// always set colour 0 to black
	palette[1] = 0;	// because most background screen palettes have a bright colour 0
	palette[2] = 0;	// although it should come out as black in the game!
	palette[3] = 0;
   
	return palette;
}
//-----------------------------------------------------------------------------------------------------------------------
// returns a pointer to the start of the palette match table, given the pointer to the start of the screen file
// assumes it has been passed a pointer to a valid screen file

uint8 *FetchPaletteMatchTable(uint8 *screenFile)	// James 09dec96
{
	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

	return (uint8 *) mscreenHeader + mscreenHeader->paletteTable;
}

//-----------------------------------------------------------------------------------------------------------------------
// returns a pointer to the screen header, given the pointer to the start of the screen file
// assumes it has been passed a pointer to a valid screen file
_screenHeader *FetchScreenHeader(uint8 *screenFile)	//Chris 04Oct96
{
	// Get the table
	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

	return (_screenHeader*) ((uint8 *) mscreenHeader + mscreenHeader->screen);

}
//-----------------------------------------------------------------------------------------------------------------------
// returns a pointer to the requested layer header, given the pointer to the start of the screen file
// drops out if the requested layer number exceeds the number of layers on this screen
// assumes it has been passed a pointer to a valid screen file
_layerHeader *FetchLayerHeader(uint8 *screenFile, uint16 layerNo)	//Chris 04Oct96
{
	_screenHeader *screenHead;


	screenHead = FetchScreenHeader(screenFile);

#ifdef _DEBUG
	if (layerNo > (screenHead->noLayers-1))	// layer number too large!
		Con_fatal_error("FetchLayerHeader(%d) invalid layer number! (%s line %u)",layerNo,__FILE__,__LINE__);
#endif

	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

	return (_layerHeader *) ((uint8 *) mscreenHeader + mscreenHeader->layers + (layerNo * sizeof(_layerHeader)));
}

//---------------------------------------------------------------
// returns a pointer to the start of the shading mask, given the pointer to the start of the screen file
// assumes it has been passed a pointer to a valid screen file

uint8 *FetchShadingMask(uint8 *screenFile)	// James 08apr97
{
	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

	return (uint8 *) mscreenHeader + mscreenHeader->maskOffset;
}

//-----------------------------------------------------------------------------------------------------------------------
// returns a pointer to the anim header, given the pointer to the start of the anim file
// assumes it has been passed a pointer to a valid anim file

_animHeader *FetchAnimHeader(uint8 *animFile)	// (25sep96JEL)
{
	return (_animHeader *) (animFile + sizeof(_standardHeader));
}

//---------------------------------------------------------------
// returns a pointer to the requested frame number's cdtEntry, given the pointer to the start of the anim file
// drops out if the requested frame number exceeds the number of frames in this anim
// assumes it has been passed a pointer to a valid anim file

_cdtEntry *FetchCdtEntry(uint8 *animFile, uint16 frameNo)	// Chris 09Oct96
{
	_animHeader *animHead;

	animHead = FetchAnimHeader(animFile);

#ifdef _DEBUG
	if (frameNo > (animHead->noAnimFrames-1))	// frame number too large!
		Con_fatal_error("FetchCdtEntry(animFile,%d) - anim only %d frames (%s line %u)",frameNo,animHead->noAnimFrames,__FILE__,__LINE__);
#endif

	return (_cdtEntry *) ( (uint8 *)animHead + sizeof(_animHeader) + frameNo * sizeof(_cdtEntry) );
}
//---------------------------------------------------------------
// returns a pointer to the requested frame number's header, given the pointer to the start of the anim file
// drops out if the requested frame number exceeds the number of frames in this anim
// assumes it has been passed a pointer to a valid anim file

_frameHeader *FetchFrameHeader(uint8 *animFile, uint16 frameNo)	// James 31oct96
{
	// required address = (address of the start of the anim header) + frameOffset
	return (_frameHeader *) (animFile + sizeof(_standardHeader) + (FetchCdtEntry(animFile,frameNo)->frameOffset) );
}
//---------------------------------------------------------------
// Returns a pointer to the requested parallax layer data.
// Assumes it has been passed a pointer to a valid screen file.
_parallax *FetchBackgroundParallaxLayer(uint8 *screenFile, int layer) // Chris 04Oct96
{
	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

#ifdef _DEBUG
	if (mscreenHeader->bg_parallax[layer] == 0)
		Con_fatal_error("FetchBackgroundParallaxLayer(%d) - No parallax layer exists (%s line %u)",layer,__FILE__,__LINE__);
#endif

	return (_parallax *) ((uint8 *) mscreenHeader + mscreenHeader->bg_parallax[layer]);
}
//---------------------------------------------------------------
_parallax *FetchBackgroundLayer(uint8 *screenFile) // Chris 04Oct96
{
	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

#ifdef _DEBUG
	if (mscreenHeader->screen == 0)
		Con_fatal_error("FetchBackgroundLayer (%d) - No background layer exists (%s line %u)",__FILE__,__LINE__);
#endif

	return (_parallax *) ((uint8 *) mscreenHeader + mscreenHeader->screen + sizeof(_screenHeader));
}
//---------------------------------------------------------------
_parallax *FetchForegroundParallaxLayer(uint8 *screenFile, int layer) // Chris 04Oct96
{
	_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));

#ifdef _DEBUG
	if (mscreenHeader->fg_parallax[layer] == 0)
		Con_fatal_error("FetchForegroundParallaxLayer(%d) - No parallax layer exists (%s line %u)",layer,__FILE__,__LINE__);
#endif

	return (_parallax *) ((uint8 *) mscreenHeader + mscreenHeader->fg_parallax[layer]);
}
//---------------------------------------------------------------
uint8 errorLine[128];
//---------------------------------------------------------------
uint8 *FetchTextLine(uint8 *file, uint32	text_line)	//Tony24Oct96
{
	// Get the table
	_standardHeader *fileHeader;
	uint32	*point;


	_textHeader *text_header = (_textHeader *) (file + sizeof(_standardHeader));


	if	(text_line>=text_header->noOfLines)		// (James08aug97)
	{
		fileHeader = (_standardHeader*)file;
		sprintf ((char*)errorLine, "xxMissing line %d of %s (only 0..%d)", text_line, fileHeader->name, text_header->noOfLines-1);
		errorLine[0]=0;	// first 2 chars are NULL so that actor-number comes out as '0'
		errorLine[1]=0;
		return(errorLine);

//		GOT RID OF CON_FATAL_ERROR HERE BECAUSE WE DON'T WANT IT TO CRASH OUT ANY MORE!
//		Con_fatal_error("FetchTextLine cannot get %d, only 0..%d avail (%s line %u)", text_line, text_header->noOfLines-1,__FILE__,__LINE__);
	}


	point=(uint32*) text_header+1;	//point to the lookup table

	return( (uint8*) (file+ *(point+text_line)) );
}
//---------------------------------------------------------------
// Used for testing text & speech (see FN_I_speak in speech.cpp)
uint8 CheckTextLine(uint8 *file, uint32	text_line)	// (James26jun97)
{
	_textHeader *text_header = (_textHeader *) (file + sizeof(_standardHeader));

	if (text_line>=text_header->noOfLines)
		return(0);	// out of range => invalid
	else
		return(1);	// valid
}
//---------------------------------------------------------------
uint8 *FetchObjectName(int32 resourceId)	// James15jan97
{
	_standardHeader *header;
	
	header = (_standardHeader*) res_man.Res_open(resourceId);

	res_man.Res_close(resourceId);

	return (header->name);	// note this pointer is no longer valid, but it should be ok until another resource is opened!
}
//---------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------

--- NEW FILE: protocol.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/protocol.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//the usual suspects (the usual suspicions)

#ifndef	_PROTOCOL
#define	_PROTOCOL

#include "driver/driver96.h"
#include "header.h"

uint8			*FetchPalette(uint8 *screenFile);	// Chris 04Oct96
_screenHeader	*FetchScreenHeader(uint8 *screenFile);	//Chris 04Oct96
_layerHeader	*FetchLayerHeader(uint8 *screenFile, uint16 layerNo);	//Chris 04Oct96
uint8			 *FetchShadingMask(uint8 *screenFile);	// James 08apr97

_animHeader		*FetchAnimHeader(uint8 *animFile);	// (25sep96JEL)
_cdtEntry		*FetchCdtEntry(uint8 *animFile, uint16 frameNo);	// (31oct96 JEL)
_frameHeader	*FetchFrameHeader(uint8 *animFile, uint16 frameNo);	// (25sep96JEL)
_parallax		*FetchBackgroundParallaxLayer(uint8 *screenFile, int layer); // Chris 04Oct96
_parallax		*FetchBackgroundLayer(uint8 *screenFile); // Chris 04Oct96
_parallax		*FetchForegroundParallaxLayer(uint8 *screenFile, int layer); // Chris 04Oct96
uint8			*FetchTextLine(uint8 *file, uint32	text_line);	//Tony24Oct96
uint8			CheckTextLine(uint8 *file, uint32	text_line);	// (James26jun97)
uint8			*FetchPaletteMatchTable(uint8 *screenFile);	// James 09dec96
uint8			*FetchObjectName(int32 resourceId);	// James15jan97

#endif

--- NEW FILE: resman.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/resman.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

[...1500 lines suppressed...]
			spriteInfo.x = oldX;
			CopyScreenBuffer();
			FlipScreens();
		}

	} while (!done);

	Free_mem(text_spr);
	RemoveMsg();
}
//------------------------------------------------------------------------------------



//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------



--- NEW FILE: resman.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/resman.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	RESMAN_H
#define	RESMAN_H

//#include "src\driver96.h"
#include "memory.h"

#define	MAX_res_files	20

#define	RES_locked	1
#define	RES_perm	2


class	resMan
{
	public:

		void	InitResMan(void);				//read in the config file
		void	Close_ResMan(void);				//Tony29May96
//----
		uint8	*Res_open(uint32 res);			//returns ad of resource. Loads if not in memory
												//retains a count
												//resource can be aged out of memory if count=0
												//the resource is locked while count!=0

		void	Res_close(uint32 res);			//decrements the count

//----

		uint8	Res_check_valid( uint32 res );	// returns '0' if resource out of range or null, otherwise '1' for ok

												//resource floats when count=0
//----
		char	*Fetch_cluster(uint32 res);		//for mem_view to query the owners of mem blocs
		uint32	Fetch_age(uint32 res);			//
		uint32	Fetch_count(uint32 count);		//

		uint32	Help_the_aged_out(void);		//Tony10Oct96

		uint32	Res_fetch_len( uint32 res );	//Tony27Jan96

		void	Res_next_cycle( void );
		uint32	Res_fetch_useage( void );

		void	GetCd(int cd);				// Prompts the user for the specified CD.
		int		WhichCd() {return curCd;}

//----console commands
		void	Print_console_clusters(void);	//Tony10Oct96
		void	Examine_res(uint8 *input);		//Tony23Oct96
		void	Kill_all_res(uint8 wantInfo);	//Tony29Nov96
		void	Kill_all_objects(uint8 wantInfo);	// James17jan97
		void	Remove_res(uint32	res);		//Tony10Jan97
		void	Remove_all_res(void);			// James24mar97
		void	Kill_res(uint8 *res);			//Tony23Oct96
		char	*GetCdPath( void );				// Chris 9Apr97


		mem	**resList;	//pointer to a pointer (or list of pointers in-fact)

	private:

		int		curCd;
		uint32	total_res_files;
		uint32	total_clusters;
		uint32	current_memory_useage;
		uint32	resTime;	//inc's each time Res_open is called and is given to resource as its age
							//cannot be allowed to start at 0! (a pint if you can tell me why)
		uint32	*age;
		uint16	*res_conv_table;	//Gode generated res-id to res number/rel number conversion table
		uint16	*count;
		char	resource_files[MAX_res_files][20];
		uint8	cdTab[MAX_res_files];		// Location of each cluster.
		char	cdPath[256];				// Drive letter of the CD-ROM drive or false CD path.
		void	CacheNewCluster(uint32 newCluster);
		char	cdDrives[24];
};							



extern	resMan	res_man;	//declare the object global

#endif

--- NEW FILE: router.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/router.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

[...3050 lines suppressed...]
		else
			Con_fatal_error("ERROR: walkGridList[] full in %s line %d",__FILE__,__LINE__);
	}
}
//--------------------------------------------------------------------------------------
// called from FN_remove_walkgrid
void RemoveWalkGrid(int32 gridResource)
{
	int entry;

	// first, scan list to see if this grid is actually there
	entry=0;
	while ((entry < MAX_WALKGRIDS) && (walkGridList[entry] != gridResource))
		entry++;

	if (entry < MAX_WALKGRIDS)	// if we've found it in the list, reset entry to zero (otherwise just ignore the request)
		walkGridList[entry] = 0;
}
//--------------------------------------------------------------------------------------


--- NEW FILE: router.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/router.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef _ROUTER_H
#define _ROUTER_H

//#include "src\driver96.h"
#include "memory.h"
#include "object.h"


typedef	struct _walkData
{
	uint16	frame;
	int16	x;
	int16	y;
	uint8	step;
	uint8	dir;
} _walkData;




int32 RouteFinder(Object_mega *ob_mega, Object_walkdata *ob_walkdata, int32 x, int32 y, int32 dir);

void EarlySlowOut(Object_mega *ob_mega, Object_walkdata *ob_walkdata);

void AllocateRouteMem(void);
_walkData* LockRouteMem(void);
void FloatRouteMem(void);
void FreeRouteMem(void);
void FreeAllRouteMem(void);
void PlotWalkGrid(void);
void AddWalkGrid(int32 gridResource);
void RemoveWalkGrid(int32 gridResource);
void ClearWalkGridList(void);
uint8 CheckForCollision(void);

//--------------------------------------------------------------------------------------


#endif

--- NEW FILE: save_rest.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/save_rest.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
// SAVE_REST.CPP	save, restore & restart functions
//
// James 05feb97
//
// "Jesus Saves", but could he Restore or Restart? He can now...
//
//------------------------------------------------------------------------------------

//#include <direct.h> directx?
#include <stdio.h>
#include <stdlib.h>

#include "driver/driver96.h"
#include "console.h"
#include "defs.h"
#include "function.h"		// for engine_logic, engine_graph, etc
#include "interpreter.h"	// for IR_CONT, etc
#include "layers.h"
#include "logic.h"
#include "memory.h"
#include "object.h"
#include "protocol.h"
#include "resman.h"
#include "router.h"
#include "save_rest.h"
#include "scroll.h"			// for Set_scrolling()
#include "sound.h"
#include "walker.h"

//------------------------------------------------------------------------------------
#define	MAX_FILENAME_LEN	128		// max length of a savegame filename, including full path

//------------------------------------------------------------------------------------
// local function prototypes

void GetPlayerStructures(void);		// James27feb97
void PutPlayerStructures(void);		// James27feb97

uint32 SaveData(uint16 slotNo, uint8 *buffer, uint32 bufferSize);
uint32 RestoreData(uint16 slotNo, uint8 *buffer, uint32 bufferSize);

uint32 CalcChecksum(uint8 *buffer, uint32 size);	// James04aug97

//------------------------------------------------------------------------------------

typedef	struct		// savegame file header		(James06feb97)
{
	uint32			checksum;							// sum of all bytes in file, excluding this uint32
	char			description[SAVE_DESCRIPTION_LEN];	// player's description of savegame
	uint32			varLength;							// length of global variables resource
	uint32			screenId;							// resource id of screen file
	uint32			runListId;							// resource id of run list
	uint32			feet_x;								// copy of this_screen.feet_x
	uint32			feet_y;								// copy of this_screen.feet_y
	uint32			music_id;							// copy of 'looping_music_id'
	_object_hub		player_hub;							// copy of player object's object_hub structure
	Object_logic	logic;								// copy of player character logic structure
	Object_graphic	graphic;							// copy of player character graphic structure
	Object_mega		mega;								// copy of player character mega structure
}
_savegameHeader;

// savegame consists of header & global variables resource

_savegameHeader header;		// global because easier to copy to/from player object structures

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
// SAVE GAME
//------------------------------------------------------------------------------------

uint32 SaveGame(uint16 slotNo, uint8 *desc)		// (James05feb97)
{
	mem		*saveBufferMem;
	uint32	bufferSize;
	uint32	errorCode;

	//------------------------------------------------------
	// allocate the savegame buffer

	bufferSize = FindBufferSize();
	saveBufferMem = Twalloc( bufferSize, MEM_locked, UID_savegame_buffer );

	FillSaveBuffer(saveBufferMem, bufferSize, desc);

	//------------------------------------------------------
	// save it (platform-specific)

	errorCode = SaveData( slotNo, saveBufferMem->ad, bufferSize );	// save the buffer

 	//------------------------------------------------------
	// free the buffer

	Free_mem( saveBufferMem );

 	//------------------------------------------------------

	return(errorCode);
}

//------------------------------------------------------------------------------------
// calculate size of required savegame buffer

uint32 FindBufferSize( void )
{
	return (sizeof(header) + res_man.Res_fetch_len(1));	// size of savegame header + size of global variables
}

//------------------------------------------------------------------------------------

void FillSaveBuffer(mem *buffer, uint32 size, uint8 *desc)
{
	uint8	*varsRes;

	//------------------------------------------------------
	// set up the header

	// 'checksum' gets filled in last of all
	sprintf(header.description, "%s", (char*)desc);					// player's description of savegame
	header.varLength	= res_man.Res_fetch_len(1);					// length of global variables resource
	header.screenId		= this_screen.background_layer_id;			// resource id of current screen file
	header.runListId	= LLogic.Return_run_list();					// resource id of current run-list
	header.feet_x		= this_screen.feet_x;						// those scroll position control things
	header.feet_y		= this_screen.feet_y;						//
	header.music_id		= looping_music_id;							// id of currently looping music (or zero)

	// object hub
	memcpy (&header.player_hub, res_man.Res_open(CUR_PLAYER_ID) + sizeof(_standardHeader), sizeof(_object_hub));
	res_man.Res_close(CUR_PLAYER_ID);

	// logic, graphic & mega structures
	GetPlayerStructures();											// copy the 4 essential player object structures into the header

	//------------------------------------------------------
	// copy the header to the buffer

	memcpy( buffer->ad, &header, sizeof(header) );					// copy the header to the savegame buffer

	//------------------------------------------------------
	// copy the global variables to the buffer

	varsRes = res_man.Res_open(1);									// open variables resource
	memcpy( buffer->ad + sizeof(header), varsRes, header.varLength );	// copy that to the buffer, following the header
 	res_man.Res_close(1);											// close variables resource

	//------------------------------------------------------
	// set the checksum & copy that to the buffer (James05aug97)

	header.checksum = CalcChecksum((buffer->ad)+sizeof(header.checksum), size-sizeof(header.checksum));
 	memcpy( buffer->ad, &header.checksum, sizeof(header.checksum) );					// copy the header to the savegame buffer

	//------------------------------------------------------
}

//------------------------------------------------------------------------------------

uint32 SaveData(uint16 slotNo, uint8 *buffer, uint32 bufferSize)
{
	char saveFileName[MAX_FILENAME_LEN];
	FILE *fp;
	uint32	itemsWritten;


//create saves directory just in case not there
	_mkdir("saves");


	sprintf(saveFileName, "saves\\savegame.%.3d", slotNo);	// construct filename

	fp = fopen(saveFileName, "wb");					// attempt to open file for writing

	if (fp==NULL)
	{
		return(SR_ERR_FILEOPEN);					// error: couldn't open file
	}
	else
	{
//		itemsWritten = fwrite(sourceAddress, size, count, fp);
		itemsWritten = fwrite(buffer, 1, bufferSize, fp);			// write the buffer
 		fclose(fp);									// close savegame file

		if (itemsWritten == bufferSize)		// if we successfully wrote it all
			return(SR_OK);					// buffer saved ok
		else
			return(SR_ERR_WRITEFAIL);		// write failed for some reason (could be hard drive full)
	}
}

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
// RESTORE GAME
//------------------------------------------------------------------------------------

uint32 RestoreGame(uint16 slotNo)		// (James05feb97)
{
	mem		*saveBufferMem;
	uint32	bufferSize;
	uint32	errorCode;

	//------------------------------------------------------
	// allocate the savegame buffer

	bufferSize = FindBufferSize();
	saveBufferMem = Twalloc( bufferSize, MEM_locked, UID_savegame_buffer );

	//------------------------------------------------------
	// read the savegame file into our buffer

	errorCode = RestoreData( slotNo, saveBufferMem->ad, bufferSize );	// load savegame into buffer

	//------------------------------------------------------
	// if it was read in successfully, then restore the game from the buffer & free the buffer

	if (errorCode == SR_OK)
	{
		errorCode = RestoreFromBuffer(saveBufferMem, bufferSize);

		// Note that the buffer has been freed inside RestoreFromBuffer,
		// in order to clear it from memory before loading in the new screen & runlist
	}
	else
		Free_mem( saveBufferMem );	// because RestoreFromBuffer would have freed it

	//------------------------------------------------------

	return(errorCode);												// game restored ok
}

//------------------------------------------------------------------------------------

uint32 RestoreData(uint16 slotNo, uint8 *buffer, uint32 bufferSize)
{
	char saveFileName[MAX_FILENAME_LEN];
	FILE *fp;
 	uint32	itemsRead;

  
	sprintf(saveFileName, "saves\\savegame.%.3d", slotNo);	// construct filename

	fp = fopen(saveFileName, "rb");					// attempt to open file for reading

	if (fp==NULL)
	{
		return(SR_ERR_FILEOPEN);					// error: couldn't open file
	}
	else
	{
//		itemsRead = fread(destAddress, size, count, fp);
		itemsRead = fread(buffer, 1, bufferSize, fp);	// read savegame into the buffer

		if (itemsRead == bufferSize)	// if we successfully read it all
		{
	 		fclose(fp);										// close savegame file
			return(SR_OK);				// file read ok
		}
		else	// didn't read the expected amount of data for some reason
		{
			if (ferror(fp))	// if it was a genuine read error, before reaching the end of the file
			{
	 			fclose(fp);					// close savegame file
   				return(SR_ERR_READFAIL);	// error: read failed
			}
			else	// we reached the end of the file before we filled the savegame buffer (ie. incompatible savegame file!)
 			{
	 			fclose(fp);						// close savegame file
				return(SR_ERR_INCOMPATIBLE);	// error: incompatible save-data - can't use!
			}
		}
	}
}

//------------------------------------------------------------------------------------
uint32	RestoreFromBuffer(mem *buffer, uint32 size)
{
	uint8	*varsRes;
	int32	pars[2];

	memcpy( &header, buffer->ad, sizeof(header) );		// get a copy of the header from the savegame buffer

  	//------------------------------------------------------
	// Calc checksum & check that aginst the value stored in the header (James05aug97)

	if (header.checksum != CalcChecksum((buffer->ad)+sizeof(header.checksum), size-sizeof(header.checksum)))
	{
		Free_mem( buffer );
		return(SR_ERR_INCOMPATIBLE);	// error: incompatible save-data - can't use!
	}
	//------------------------------------------------------
	// check savegame against length of current global variables resource
	// This would most probably be trapped by the checksum test anyway, but it doesn't do any harm to check this as well

	// Note that during development, earlier savegames will often be shorter than the current expected length

	if (header.varLength != res_man.Res_fetch_len(1))	// if header contradicts actual current size of global variables
	{
		Free_mem( buffer );
		return(SR_ERR_INCOMPATIBLE);	// error: incompatible save-data - can't use!
	}
	//----------------------------------
	// clean out system
	res_man.Kill_all_res(0);	// trash all resources from memory except player object & global variables
	LLogic.Reset_kill_list();	// clean out the system kill list (no more objects to kill)
	
	//----------------------------------
	// get player character data from savegame buffer

	// object hub is just after the standard header 
	memcpy (res_man.Res_open(CUR_PLAYER_ID) + sizeof(_standardHeader), &header.player_hub, sizeof(_object_hub));
	res_man.Res_close(CUR_PLAYER_ID);
	PutPlayerStructures();										// fill in the 4 essential player object structures from the header

	//----------------------------------
	// get variables resource from the savegame buffer	

	varsRes = res_man.Res_open(1);								// open variables resource
	memcpy( varsRes, buffer->ad + sizeof(header), header.varLength );// copy that to the buffer, following the header
 	res_man.Res_close(1);										// close variables resource

	Free_mem( buffer );		// free it now, rather than in RestoreGame, to unblock memory before new screen & runlist loaded
	pars[0] = header.screenId;
	pars[1] = 1;
	FN_init_background(pars);
	this_screen.new_palette=99;	// (JEL08oct97) so palette not restored immediately after control panel - we want to fade up instead!

	this_screen.feet_x = header.feet_x;	// these need setting after the defaults get set in FN_init_background
	this_screen.feet_y = header.feet_y;	// remember that these can change through the game, so need saving & restoring too
	LLogic.Express_change_session(header.runListId);			// start the new run list

	//----------------------------------------------------------------------------
	// (James01aug97)
	// Force in the new scroll position, so unsightly scroll-catch-up does not occur
	// when screen first draws after returning from restore panel

	this_screen.player_feet_x = header.mega.feet_x;	// set 'this_screen's record of player position
	this_screen.player_feet_y = header.mega.feet_y;	// - ready for Set_scrolling()

	if (this_screen.scroll_flag)	// if this screen is wide
		Set_scrolling();			// recompute the scroll offsets now, 

	//----------------------------------------------------------------------------
	// Any music required will be started after we've returned from Restore_control()
	// - see System_menu() in mouse.cpp!
	looping_music_id = header.music_id;
 	//------------------------------------------------------

	//--------------------------------------
	// Write to walkthrough file (zebug0.txt)
	#ifdef _DEBUG
	Zdebug(0,"*************************************");
	Zdebug(0,"RESTORED GAME \"%s\"", header.description);
	Zdebug(0,"*************************************");

	// Also write this to system debug file
 	Zdebug("*************************************");
	Zdebug("RESTORED GAME \"%s\"", header.description);
	Zdebug("*************************************");
 	#endif
	//--------------------------------------


	return(SR_OK);												// game restored ok

}

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
// GetSaveDescription - PC version...
//------------------------------------------------------------------------------------

uint32 GetSaveDescription(uint16 slotNo, uint8 *description)		// (James05feb97)
{
	char saveFileName[MAX_FILENAME_LEN];
	_savegameHeader header;
	FILE *fp;

	sprintf(saveFileName, "saves\\savegame.%.3d", slotNo);			// construct filename

	fp = fopen(saveFileName, "rb");							// attempt to open file for reading

	if (fp==NULL)
	{
		return(SR_ERR_FILEOPEN);							// error: couldn't open file
	}
	else
	{
//		fread(destAddress, size, count, fp);
		fread(&header, sizeof(header), 1, fp);				// read header
		fclose(fp);
		sprintf((char*)description, header.description);
		return(SR_OK);
	}
}

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
void GetPlayerStructures(void)		// James27feb97
{
	 // request the player object structures which need saving

	uint32	null_pc=7;	// script no. 7 - 'george_savedata_request' calls FN_pass_player_savedata
 	char	*raw_script_ad;
	_standardHeader	*head;


	head = (_standardHeader*) res_man.Res_open(CUR_PLAYER_ID);

	if	(head->fileType!=GAME_OBJECT)
		Con_fatal_error("incorrect CUR_PLAYER_ID=%d (%s line %u)",CUR_PLAYER_ID,__FILE__,__LINE__);

	raw_script_ad = (char *)head;	// (head+1) + sizeof(_object_hub);	//get to raw script data
	RunScript( raw_script_ad, raw_script_ad, &null_pc );
	res_man.Res_close(CUR_PLAYER_ID);
}
//------------------------------------------------------------------------------------
void PutPlayerStructures(void)		// James27feb97 (updated by James on 29july97)
{
	// fill out the player object structures from the savegame structures
	// also run the appropriate scripts to set up george's anim tables & walkdata, and nico's anim tables

	uint32	null_pc=8;	// script no. 8 - 'george_savedata_return' calls FN_get_player_savedata
 	char	*raw_script_ad;
	_standardHeader	*head;


	head = (_standardHeader*) res_man.Res_open(CUR_PLAYER_ID);

	if	(head->fileType!=GAME_OBJECT)
		Con_fatal_error("incorrect CUR_PLAYER_ID=%d (%s line %u)",CUR_PLAYER_ID,__FILE__,__LINE__);

	raw_script_ad = (char *)head;	// (head+1) + sizeof(_object_hub);	//get to raw script data
	
	null_pc=8;	// script no. 8 - 'george_savedata_return' calls FN_get_player_savedata
	RunScript( raw_script_ad, raw_script_ad, &null_pc );

	null_pc=14;	// script no. 14 - 'set_up_nico_anim_tables'
	RunScript( raw_script_ad, raw_script_ad, &null_pc );

	switch (header.mega.megaset_res)	// which megaset was the player at the time of saving?
	{
		case 36:		// GeoMega:
			null_pc=9;	// script no.9	- 'player_is_george'
			break;

		case 2003:		// GeoMegaB:
			null_pc=13;	// script no.13 - 'player_is_georgeB'
			break;

		case 1366:		// NicMegaA:
			null_pc=11;	// script no.11 - 'player_is_nicoA'
			break;

 		case 1437:		// NicMegaB:
			null_pc=12;	// script no.12 - 'player_is_nicoB'
			break;

 		case 1575:		// NicMegaC:
			null_pc=10;	// script no.10 - 'player_is_nicoC'
			break;
	}
	RunScript( raw_script_ad, raw_script_ad, &null_pc );

	res_man.Res_close(CUR_PLAYER_ID);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
int32 FN_pass_player_savedata(int32 *params)	// James27feb97
{
	// copies the 4 essential player structures into the savegame header
	// - run script 7 of player object to request this

	// remember, we cannot simply read a compact any longer but instead must request it from the object itself

	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure

	// copy from player object to savegame header
	memcpy( &header.logic,		(uint8*)params[0], sizeof(Object_logic)		);
	memcpy( &header.graphic,	(uint8*)params[1], sizeof(Object_graphic)	);
	memcpy( &header.mega,		(uint8*)params[2], sizeof(Object_mega)		);

	return(IR_CONT);	//makes no odds
}
//------------------------------------------------------------------------------------
int32 FN_get_player_savedata(int32 *params)	// James27feb97
{
	// reverse of FN_pass_player_savedata
	// - run script 8 of player object

	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure

	Object_logic	*ob_logic		= (Object_logic*)	params[0];
	Object_graphic	*ob_graphic		= (Object_graphic*)	params[1];
	Object_mega		*ob_mega		= (Object_mega*)	params[2];

	int32	pars[3];


	// copy from savegame header to player object
	memcpy( (uint8*)ob_logic,	&header.logic,		sizeof(Object_logic)	);
	memcpy( (uint8*)ob_graphic,	&header.graphic,	sizeof(Object_graphic)	);
	memcpy( (uint8*)ob_mega,	&header.mega,		sizeof(Object_mega)		);


 	// any walk-data must be cleared - the player will be set to stand if he was walking when saved

	if (ob_mega->currently_walking)		// if the player was walking when game was saved
	{
		ob_mega->currently_walking = 0;	// clear the flag
		ob_mega->colliding = 0;			// reset this just in case

		pars[0] = (int32)ob_graphic;	// pointer to object's graphic structure
		pars[1] = (int32)ob_mega;		// pointer to object's mega structure
		pars[2] = ob_mega->current_dir;	// target direction
		FN_stand(pars);					// set player to stand

		ob_logic->looping = 0;			// reset looping flag (which would have been '1' during FN_walk)
	}


	return(IR_CONT);	//makes no odds
}
//------------------------------------------------------------------------------------
uint32 CalcChecksum(uint8 *buffer, uint32 size)		// (James05aug97)
{
	uint32 total=0;
	uint32 pos;

	for (pos=0; pos<size; pos++)
		total += buffer[pos];

	return(total);
}

--- NEW FILE: save_rest.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/save_rest.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	SAVE_REST_H
#define	SAVE_REST_H


//#include "src\driver96.h"
#include "memory.h"

#define	SAVE_DESCRIPTION_LEN	64

uint32	SaveGame(uint16 slotNo, uint8 *description);
uint32	RestoreGame(uint16 slotNo);
uint32	GetSaveDescription(uint16 slotNo, uint8 *description);
void	FillSaveBuffer(mem *buffer, uint32 size, uint8 *desc);
uint32	RestoreFromBuffer(mem *buffer, uint32 size);
uint32	FindBufferSize( void );


// Save & Restore error codes

//		ERROR CODE			VALUE		MEANING													REASON
//		==========			=====		=======													======
#define SR_OK				0x00000000	// ok													No worries
#define SR_ERR_FILEOPEN		0x00000001	// can't open file										Could create file for saving, or couldn't find file for loading
#define SR_ERR_INCOMPATIBLE	0x00000002	// (RestoreGame only) incompatible savegame data		Savegame file is obsolete. (Won't happen after development stops)
#define	SR_ERR_READFAIL		0x00000003	// (RestoreGame only) failed on reading savegame file	Something screwed up during the fread()
#define SR_ERR_WRITEFAIL	0x00000004	// (SaveGame only) failed on writing savegame file		Something screwed up during the fwrite() - could be hard-drive full..?

#endif

--- NEW FILE: scroll.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/scroll.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//------------------------------------------------------------------------------------
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

//#include "src\driver96.h"
#include "build_display.h"
#include "debug.h"
#include "defs.h"
#include "header.h"
#include "interpreter.h"
#include "layers.h"
#include "memory.h"
#include "object.h"
#include "protocol.h"
#include "resman.h"
#include "scroll.h"

//------------------------------------------------------------------------------------
#define MAX_SCROLL_DISTANCE 8	// max no of pixel allowed to scroll per cycle

//------------------------------------------------------------------------------------
uint8 scroll_fraction=16;	// used to be a define, but now it's flexible (see new functions below)
//------------------------------------------------------------------------------------
void	Set_scrolling(void)		//S2.1(2Mar94jel) refurnished Tony25Sept96 :-)
{
	// feet_x = 128+320	// normally we aim to get George's feet at (320,250) from top left of screen window
	// feet_y = 128+250

	// set scroll offsets according to the player's coords

	int16	offset_x;
	int16	offset_y;
	int16	dx, dy;
	uint16	scroll_distance_x;	// how much we want to scroll
	uint16	scroll_distance_y;


	if (SCROLL_X || SCROLL_Y)	// if the scroll offsets are being forced in script (05feb97 JAMES)
	{
		// ensure not too far right
		if (SCROLL_X < this_screen.max_scroll_offset_x)
			this_screen.scroll_offset_x = SCROLL_X;
		else
 			this_screen.scroll_offset_x = this_screen.max_scroll_offset_x;

		// ensure not too far down
		if (SCROLL_Y < this_screen.max_scroll_offset_y)
			this_screen.scroll_offset_y = SCROLL_Y;
		else
 			this_screen.scroll_offset_y = this_screen.max_scroll_offset_y;
	}
	else
	{
		offset_x = this_screen.player_feet_x-this_screen.feet_x;	// George's offset from the centre - the desired position for him
		offset_y = this_screen.player_feet_y-this_screen.feet_y;


		// prevent scrolling too far left/right/up/down
		offset_x = offset_x < 0 ? 0 : ( (uint32)offset_x > this_screen.max_scroll_offset_x ? this_screen.max_scroll_offset_x : offset_x );
		offset_y = offset_y < 0 ? 0 : ( (uint32)offset_y > this_screen.max_scroll_offset_y ? this_screen.max_scroll_offset_y : offset_y );

		if (this_screen.scroll_flag==2)	// first time on this screen - need absolute scroll immediately!
		{
			//Zdebug(42,"init scroll");
			this_screen.scroll_offset_x = offset_x;
			this_screen.scroll_offset_y = offset_y;
			this_screen.scroll_flag=1;
		}
		else	// catch up with required scroll offsets - speed depending on distance to catch up (dx and dy) & 'SCROLL_FRACTION' used
		{		// but limit to certain number of pixels per cycle (MAX_SCROLL_DISTANCE)

			dx = this_screen.scroll_offset_x - offset_x;
			dy = this_screen.scroll_offset_y - offset_y;

			if (dx < 0)				// current scroll_offset_x is less than the required value
			{
				scroll_distance_x = (1+(-dx)/scroll_fraction);	// => inc by (fraction of the differnce) NB. dx is -ve, so we subtract dx/SCROLL_FRACTION
				this_screen.scroll_offset_x += scroll_distance_x < MAX_SCROLL_DISTANCE ? scroll_distance_x : MAX_SCROLL_DISTANCE;
			}
			else if (dx > 0)	// current scroll_offset_x is greater than the required value
			{
				scroll_distance_x = (1+dx/scroll_fraction);		// => dec by (fraction of the differnce)
				this_screen.scroll_offset_x -= scroll_distance_x < MAX_SCROLL_DISTANCE ? scroll_distance_x : MAX_SCROLL_DISTANCE;
			}											// NB. I'm adding 1 to the result of dx/SCROLL_FRACTION, because it would otherwise
													//			not scroll at all when dx < SCROLL_FRACTION
			if (dy < 0)
			{
				scroll_distance_y = (1+(-dy)/scroll_fraction);
				this_screen.scroll_offset_y += scroll_distance_y < MAX_SCROLL_DISTANCE ? scroll_distance_y : MAX_SCROLL_DISTANCE;
			}
			else if (dy > 0)
			{
				scroll_distance_y = (1+dy/scroll_fraction);
				this_screen.scroll_offset_y -= scroll_distance_y < MAX_SCROLL_DISTANCE ? scroll_distance_y : MAX_SCROLL_DISTANCE;
			}
		}
	}
}
//------------------------------------------------------------------------------------
int32 FN_set_scroll_coordinate(int32 *params)	//Tony25Sept96
{
	// set the special scroll offset variables
	// call when starting screens and to change the camera within screens
	// call AFTER FN_init_background() to override the defaults
	// called feet_x and feet_y to retain intelectual compatibility with Sword1 !
	// feet_x & feet_y refer to the physical screen coords where the system will try to maintain George's feet

	// param	0 feet_x value
	// param	1 feet_y value


	this_screen.feet_x = params[0];
	this_screen.feet_y = params[1];


	return(IR_CONT);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
int32 FN_set_scroll_speed_normal(int32 *params)		// James08aug97
{
	scroll_fraction=16;

	return(IR_CONT);
}
//------------------------------------------------------------------------------------
int32 FN_set_scroll_speed_slow(int32 *params)		// James08aug97
{
	scroll_fraction=32;

	return(IR_CONT);
}
//------------------------------------------------------------------------------------


--- NEW FILE: scroll.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/scroll.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//the usual suspects

#ifndef	_SCROLL
#define	_SCROLL

//#include "src\driver96.h"

void	Set_scrolling(void);

#endif

--- NEW FILE: sound.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/sound.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//--------------------------------------------------------------------------------------
//								BROKEN SWORD 2
//
//	SOUND.CPP		Contains the sound engine, fx & music functions
//					Some very 'sound' code in here ;)
//
//	(16Dec96 JEL)
//
//--------------------------------------------------------------------------------------

#include <stdio.h>

//#include "src\driver96.h"
#include "console.h"
#include "defs.h"	// for RESULT
#include "interpreter.h"
#include "protocol.h"	// for FetchObjectName() for debugging FN_play_fx
#include "resman.h"
#include "sound.h"

//--------------------------------------------------------------------------------------
typedef struct
{
	uint32	resource;		// resource id of sample
	uint32	fetchId;		// Id of resource in PSX CD queue. :)
	uint16	delay;			// cycles to wait before playing (or 'random chance' if FX_RANDOM)
	uint8	volume;			// 0..16
	int8	pan;			// -16..16
	uint8	type;			// FX_SPOT, FX_RANDOM or FX_LOOP
} _fxq_entry;

#define FXQ_LENGTH 32		// max number of fx in queue at once [DO NOT EXCEED 255]

_fxq_entry fxq[FXQ_LENGTH];

//--------------------------------------------------------------------------------------

uint32 looping_music_id=0;	// used to store id of tunes that loop, for save & restore
char musicDirectory[120];

//--------------------------------------------------------------------------------------
// local function prototypes

void Trigger_fx (uint8 j);

//--------------------------------------------------------------------------------------
// initialise the fxq by clearing all the entries

void Init_fx_queue(void)
{
	uint8 j;


	for (j=0; j < FXQ_LENGTH; j++)	// scan the queue
	{
		fxq[j].resource = 0;		// 0 resource means 'empty' slot
		fxq[j].fetchId	= 0;		// Not being fetched.
	}
}

//--------------------------------------------------------------------------------------
// process the fxq once every game cycle

void Process_fx_queue(void)
{
	uint8 j;	// assuming FXQ_LENGTH is 255 or less


	for (j=0; j < FXQ_LENGTH; j++)				// scan the queue
	{
		if (fxq[j].resource)					// if this entry isn't empty
		{
			if (fxq[j].type == FX_RANDOM)		// if it's type FX_RANDOM
			{
				if (rand()%(fxq[j].delay)==0)	// 1 in 'delay' chance of this fx occurring
				{	
					Trigger_fx(j);				// play it
				}

			}
			else if(fxq[j].type == FX_SPOT)
			{
				if (fxq[j].delay)				// if delay is above 0
					fxq[j].delay--;				// decrement delay countdown
				else							// if zero delay remaining
				{
					Trigger_fx(j);				// play it
					fxq[j].type = FX_SPOT2;
				}
			}
			else if (fxq[j].type == FX_SPOT2)
			{
				if (IsFxOpen(j+1))
					fxq[j].resource = 0;		// Once the Fx has finished remove it from the queue.
			}
		}
	}
}

//--------------------------------------------------------------------------------------
void Trigger_fx(uint8 j)	// called from Process_fx_queue only
{
	uint8 *data;
	int32 id;
	uint32 rv;

	id = (uint32)j+1;	// because 0 is not a valid id

	if (fxq[j].type == FX_SPOT)
	{
		data = res_man.Res_open(fxq[j].resource);						// load in the sample
		data += sizeof(_standardHeader);
		rv = PlayFx( id, data, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT );		// wav data gets copied to sound memory
		res_man.Res_close(fxq[j].resource);								// release the sample
//		fxq[j].resource = 0;											// clear spot fx from queue
	}
	else	// random & looped fx are already loaded into sound memory by FN_play_fx()
	{		// - to be referenced by 'j', so pass NULL data

		if (fxq[j].type == FX_RANDOM)
			rv = PlayFx( id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT );	// not looped
		else			// FX_LOOP
			rv = PlayFx( id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXLOOP );	// looped
	}

	#ifdef _DEBUG
	if (rv)
		Zdebug("SFX ERROR: PlayFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
	#endif
}

//--------------------------------------------------------------------------------------
int32 FN_play_fx(int32 *params)		// called from script only
{
	// params:	0 sample resource id
	//			1 type		(FX_SPOT, FX_RANDOM, FX_LOOP)
	//			2 delay		(0..65535)
	//			3 volume	(0..16)
	//			4 pan		(-16..16)

	// example script:	FN_play_fx (FXWATER, FX_LOOP, 0, 10, 15);
	//					fx_water = result;	// fx_water is just a local script flag
	//					.
	//					.
	//					.
	//					FN_stop_fx (fx_water);

	uint8	j=0;
	uint8	*data;
	uint32	id;
	uint32 rv;

	//----------------------------------
	#ifdef _DEBUG

	_standardHeader *header;
	char type[10];


	if (wantSfxDebug)
	{
		switch (params[1])	// 'type'
		{
			case FX_SPOT:
				strcpy(type,"SPOT");
				break;

			case FX_LOOP:
				strcpy(type,"LOOPED");
				break;

			case FX_RANDOM:
				strcpy(type,"RANDOM");
				break;

			default:
				strcpy(type,"INVALID");
		}

		Zdebug("SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", FetchObjectName(params[0]), params[3], params[4], params[2], type);
	}

	#endif	_DEBUG
	//----------------------------------

	while ((j < FXQ_LENGTH) && (fxq[j].resource != 0))
		j++;

	if (j==FXQ_LENGTH)
	{
		return (IR_CONT);
//		Con_fatal_error("ERROR: Sound queue overflow in FN_play_fx() (%s line %u)",__FILE__,__LINE__);
	}
	else
	{
		fxq[j].resource	= params[0];			// wav resource id
		fxq[j].type		= params[1];			// FX_SPOT, FX_LOOP or FX_RANDOM

		if (fxq[j].type == FX_RANDOM)			// FX_RANDOM:
			fxq[j].delay = params[2] * 12 + 1;	//  'delay' param is the intended average no. seconds between playing this effect (+1 to avoid divide-by-zero in Process_fx_queue)
		else									// FX_SPOT or FX_LOOP:
 			fxq[j].delay = params[2];			//  'delay' is no. frames to wait before playing

		fxq[j].volume	= params[3];			// 0..16
		fxq[j].pan		= params[4];			// -16..16


		if (fxq[j].type == FX_SPOT)						// spot fx
		{
			#ifdef _DEBUG
 			data = res_man.Res_open(fxq[j].resource);	// "pre-load" the sample; this gets it into memory
			header = (_standardHeader*)data;
			if (header->fileType != WAV_FILE)
				Con_fatal_error("FN_play_fx given invalid resource (%s line %u)",__FILE__,__LINE__);
			#else
			res_man.Res_open(fxq[j].resource);			// "pre-load" the sample; this gets it into memory
			#endif
			res_man.Res_close(fxq[j].resource);			// but then releases it to "age" out if the space is needed
		}
		else											// random & looped fx
		{
			id = (uint32)j+1;							// because 0 is not a valid id

			data = res_man.Res_open(fxq[j].resource);	// load in the sample

			#ifdef _DEBUG
			header = (_standardHeader*)data;
			if (header->fileType != WAV_FILE)
				Con_fatal_error("FN_play_fx given invalid resource (%s line %u)",__FILE__,__LINE__);
			#endif

			data += sizeof(_standardHeader);
			rv = OpenFx(id,data);							// copy it to sound memory, using position in queue as 'id'

			#ifdef _DEBUG
			if (rv)
				Zdebug("SFX ERROR: OpenFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
			#endif

			res_man.Res_close(fxq[j].resource);			// release the sample
		}
	}


	//---------------------------------------------
	// (James07uag97)
	if (fxq[j].type == FX_LOOP)		// looped fx
		Trigger_fx(j);				// play now, rather than in Process_fx_queue where it was getting played again & again!
 	//---------------------------------------------


	RESULT = j;	// in case we want to call FN_stop_fx() later, to kill this fx (mainly for FX_LOOP & FX_RANDOM)

	return(IR_CONT);	//	continue script
}

//--------------------------------------------------------------------------------------
int32 FN_sound_fetch(int32 *params)
{
	return (IR_CONT);
}
//--------------------------------------------------------------------------------------
// to alter the volume and pan of a currently playing fx
int32 FN_set_fx_vol_and_pan(int32 *params)
{
//	params	0	id of fx (ie. the id returned in 'result' from FN_play_fx
//			1	new volume (0..16)
//			2	new pan (-16..16)

//	SetFxVolumePan(int32 id, uint8 vol, uint8 pan);
	SetFxVolumePan(1+params[0], params[1], params[2]);	// driver fx_id is 1+<pos in queue>
//	Zdebug("%d",params[2]);

	return (IR_CONT);
}
//--------------------------------------------------------------------------------------
// to alter the volume  of a currently playing fx
int32 FN_set_fx_vol(int32 *params)
{
//	params	0	id of fx (ie. the id returned in 'result' from FN_play_fx
//			1	new volume (0..16)

//	SetFxIdVolume(int32 id, uint8 vol);
	SetFxIdVolume(1+params[0], params[1]);

	return (IR_CONT);
}
//--------------------------------------------------------------------------------------
int32 FN_stop_fx(int32 *params)		// called from script only
{
	// params:	0 position in queue

	// This will stop looped & random fx instantly, and remove the fx from the queue.
	// So although it doesn't stop spot fx, it will remove them from the queue if they haven't yet played

	uint8	j = (uint8) params[0];
	uint32	id;
	uint32	rv;

	if ((fxq[j].type == FX_RANDOM) || (fxq[j].type == FX_LOOP))
	{
		id = (uint32)j+1;	// because 0 is not a valid id
		rv = CloseFx(id);		// stop fx & remove sample from sound memory

		#ifdef _DEBUG
		if (rv)
			Zdebug("SFX ERROR: CloseFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
		#endif
	}

	fxq[j].resource = 0;	// remove from queue


	return(IR_CONT);		//	continue script
}

//--------------------------------------------------------------------------------------
int32 FN_stop_all_fx(int32 *params)		// called from script only
{
	// Stops all looped & random fx and clears the entire queue
	// NO PARAMS

	Clear_fx_queue();

	return(IR_CONT);		//	continue script
}
//--------------------------------------------------------------------------------------
// Stops all looped & random fx and clears the entire queue

void Clear_fx_queue(void)
{
	ClearAllFx();			// stop all fx & remove the samples from sound memory
	Init_fx_queue();		// clean out the queue
}

//--------------------------------------------------------------------------------------

//=============================================================================
//	int32 StreamMusic(uint8 *filename, int32 loopFlag)
//
//	Streams music from the file defined by filename.  The loopFlag should
//	be set to RDSE_FXLOOP if the music is to loop back to the start.
//	Otherwise, it should be RDSE_FXSPOT.
//	The return value must be checked for any problems.
//
//	--------------------------------------------------------------------------
//
//	int32 PauseMusic(void)
//
//	Stops the music dead in it's tracks.
//
//	--------------------------------------------------------------------------
//
//	int32 UnpauseMusic(void)
//
//	Re-starts the music from where it was stopped.
//
//=============================================================================
int32 FN_prepare_music(int32 *params)
{
	return (IR_CONT);
}

//--------------------------------------------------------------------------------------
// Start a tune playing, to play once or to loop until stopped or next one played
int32 FN_play_music(int32 *params)		// updated by James on 10apr97
{
	// params	0 tune id
	//			1 loop flag (0 or 1)

	char	filename[128];
	uint32	loopFlag;
	uint32	rv;	// drivers return value


//	Zdebug("FN_play_music(%d)", params[0]);

	if (params[1]==FX_LOOP)				// if it is to loop
	{
		loopFlag = RDSE_FXLOOP;
		looping_music_id = params[0];	// keep a note of the id, for restarting after an interruption to gameplay
	}
	else								// just play once
	{
 		loopFlag = RDSE_FXSPOT;
		looping_music_id = 0;			// don't need to restart this tune after control panel or restore
	}


	// add the appropriate file extension & play it

	#ifdef _WEBDEMO		// (James 01oct97)
		sprintf(filename,"MUSIC.CLU");
	#else
		sprintf(filename,"%sCLUSTERS\\MUSIC.CLU", res_man.GetCdPath());
	#endif	// _WEBDEMO

	rv = StreamCompMusic(filename, params[0], loopFlag);

	#ifdef _DEBUG
		if (rv)
	 		Zdebug("ERROR: StreamCompMusic(%s, %d, %d) returned error 0x%.8x", filename, params[0], loopFlag, rv);
	#endif

//	Zdebug("FN_play_music(%d) returning", params[0]);

	return(IR_CONT);	//	continue script
}

//--------------------------------------------------------------------------------------
int32 FN_stop_music(int32 *params)		// called from script only
{
	// params:	none


	looping_music_id=0;		// clear the 'looping' flag

	StopMusic();

	if (params);

	return(IR_CONT);	//	continue script
}
//--------------------------------------------------------------------------------------
extern void UpdateCompSampleStreaming(void);	// used in Kill_music()
//--------------------------------------------------------------------------------------
void Kill_music(void)	// James22aug97
{
	uint8 count;

	looping_music_id=0;		// clear the 'looping' flag
	StopMusic();

	// THIS BIT CAUSES THE MUSIC TO STOP INSTANTLY!
	for(count=0; count<16; count++)
		UpdateCompSampleStreaming();
}
//--------------------------------------------------------------------------------------
int32 FN_check_music_playing(int32 *params)		// James (30july97)
{

	// params: none
	// sets result to no. of seconds of current tune remaining
	// or 0 if no music playing

	RESULT = MusicTimeRemaining();	// in seconds, rounded up to the nearest second

	return(IR_CONT);	//	continue script
}
//--------------------------------------------------------------------------------------
void PauseAllSound(void)	// James25july97
{
	uint32	rv;	// for drivers return value

	rv = PauseMusic();
	if (rv != RD_OK)
		Zdebug("ERROR: PauseMusic() returned %.8x in PauseAllSound()", rv);

	rv = PauseSpeech();
	if (rv != RD_OK)
		Zdebug("ERROR: PauseSpeech() returned %.8x in PauseAllSound()", rv);

	rv = PauseFx();
	if (rv != RD_OK)
		Zdebug("ERROR: PauseFx() returned %.8x in PauseAllSound()", rv);
}
//--------------------------------------------------------------------------------------
void UnpauseAllSound(void)	// James25july97
{
	uint32	rv;	// for drivers return value

	rv = UnpauseMusic();
	if (rv != RD_OK)
		Zdebug("ERROR: UnpauseMusic() returned %.8x in UnpauseAllSound()", rv);

	rv = UnpauseSpeech();
	if (rv != RD_OK)
		Zdebug("ERROR: UnpauseSpeech() returned %.8x in UnpauseAllSound()", rv);

	rv = UnpauseFx();
 	if (rv != RD_OK)
		Zdebug("ERROR: UnpauseFx() returned %.8x in UnpauseAllSound()", rv);
}
//--------------------------------------------------------------------------------------


--- NEW FILE: sound.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/sound.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

/*****************************************************************************
 *		SOUND.H		Sound engine
 *
 *		SOUND.CPP Contains the sound engine, fx & music functions
 *		Some very 'sound' code in here ;)
 *
 *		(16Dec96 JEL)
 *
 ****************************************************************************/

#ifndef SOUND_H
#define SOUND_H

#include "scummsys.h"

// fx types
#define FX_SPOT		0
#define FX_LOOP		1
#define FX_RANDOM	2
#define FX_SPOT2	3

void Init_fx_queue(void);		// to be called during system initialisation
void Process_fx_queue(void);	// to be called from the main loop, once per cycle
void Clear_fx_queue(void);		// stops all fx & clears the queue - eg. when leaving a location
void PauseAllSound(void);		// James25july97
void UnpauseAllSound(void);		// James25july97

void Kill_music(void);			// James22aug97


int32 FN_play_music(int32 *params);		// for save_Rest.cpp
int32 FN_stop_music(int32 *params);

extern uint32 looping_music_id;		// used to store id of tunes that loop, for save & restore

#endif

--- NEW FILE: speech.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/speech.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

[...1955 lines suppressed...]
		case 528:	// PresidentaSpeech
					//		SFX (528);
					//		FX <Nearby Crash of Collapsing Masonry>

		case 920:	// location 62

		case 923:	// location 62

		case 926:	// location 62

		{
			return 0;	// don't want speech for these lines!
			break;
		}

		default:
			return 1;	// ok for all other lines
	}
}
//------------------------------------------------------------------------------------

--- NEW FILE: speech.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/speech.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	_SPEECH
#define	_SPEECH

//#include "src\driver96.h"
#include "header.h"


#define	MAX_SUBJECT_LIST	30	//is that enough?



typedef	struct	//array of these for subject menu build up
{
	uint32	res;
	uint32	ref;
} _subject_unit;

extern uint32	speech_text_bloc_no;	// so speech text cleared when running a new start-script
extern int16	officialTextNumber;

extern int32	speechScriptWaiting;

extern	int	choosing;	//could alternately use logic->looping of course
extern	uint32	unpause_zone;
#endif

--- NEW FILE: startup.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/startup.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//------------------------------------------------------------------------------------
#include <stdio.h>

//#include "src\driver96.h"
#include "build_display.h"
#include "console.h"
#include "debug.h"
#include "defs.h"
#include "header.h"
#include "interpreter.h"
#include "maketext.h"	// for Kill_text_bloc()
#include "memory.h"
#include "mouse.h"		// for FN_add_human()
#include "object.h"
#include "resman.h"
#include "router.h"
#include "sound.h"
#include "speech.h"		// for 'speech_text_bloc_no' - so that speech text can be cleared when running a new start-script
#include "startup.h"
#include "sword2.h"	// (James11aug97) for CloseGame()
#include "sync.h"
#include "tony_gsdk.h"

//------------------------------------------------------------------------------------
uint32	total_startups=0;
uint32	total_screen_managers=0;
uint32	res;

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
_startup	start_list[MAX_starts];
//------------------------------------------------------------------------------------
uint32	Init_start_menu(void)	//Tony13Aug96
{
//print out a list of all the start points available
//there should be a linc produced file called startup.txt
//this file should contain ascii numbers of all the resource game objects that are screen managers
//we query each in turn and setup an array of start structures
//if the file doesn't exist then we say so and return a 0


	uint32	end;
	mem	*temp;
	uint32	pos=0;
	uint32	j=0;
	char	*raw_script;
	uint32	null_pc;


	char	ascii_start_ids[MAX_starts][7];


//ok, load in the master screen manager file




	total_startups=0;	//no starts



	Zdebug("initialising start menu");


	if	(!(end=Read_file("STARTUP.INF", &temp, UID_temp)))
	{
		Zdebug("Init_start_menu cannot open startup.inf");
		return(0);	//meaning no start menu available
	}



//ok, we've loaded in the resource.inf file which contains a list of all the files
//now extract the filenames
	do
	{
		while(((char)*(temp->ad+j))!=13)	//item must have an #0d0a
		{
			ascii_start_ids[total_screen_managers][pos]=*(temp->ad+j);
			j++;
			pos++;

		};

		ascii_start_ids[total_screen_managers][pos]=0;	//NULL terminate our extracted string

		pos=0;	//reset position in current slot between entries
		j+=2;	//past the 0a
		total_screen_managers++;	//done another

		if	(total_screen_managers==MAX_starts)
		{	Zdebug("WARNING MAX_starts exceeded!");
			break;
		}
	}
	while(j<end);	//using this method the Gode generated resource.inf must have #0d0a on the last entry



	Zdebug("%d screen manager objects", total_screen_managers);

//open each object and make a query call. the object must fill in a startup structure
//it may fill in several if it wishes - for instance a startup could be set for later in the game where specific vars are set
	for	(j=0;j<total_screen_managers;j++)
	{
		res=atoi(ascii_start_ids[j]);

		Zdebug("+querying screen manager %d", res);


//		resopen each one and run through the interpretter
//		script 0 is the query request script


		if (res_man.Res_check_valid(res))	// if the resource number is within range & it's not a null resource (James 12mar97)
		{									// - need to check in case un-built sections included in start list
			Zdebug("- resource %d ok",res);
			raw_script= (char*) (res_man.Res_open(res));	//+sizeof(_standardHeader)+sizeof(_object_hub));
			null_pc=0;	//
			RunScript ( raw_script, raw_script, &null_pc );
			res_man.Res_close(res);
		}
		else
		{
			Zdebug("- resource %d invalid",res);
		}
	}


	Zdebug("");	//line feed


	Free_mem(temp);	//release the Talloc

	return(1);
}
//------------------------------------------------------------------------------------
int32 FN_register_start_point(int32 *params)	//Tony14Oct96
{
	// param	0 id of startup script to call - key
	// param	1 pointer to ascii message


//	Zdebug(" FN_register_start_point %d %s", params[0], params[1]);

	#ifdef _DEBUG
	if (total_startups==MAX_starts)
		Con_fatal_error("ERROR: start_list full [%s line %u]",__FILE__,__LINE__);

	if (strlen((char*)params[1])+1 > MAX_description)	// +1 to allow for NULL terminator
		Con_fatal_error("ERROR: startup description too long [%s line %u]",__FILE__,__LINE__);
	#endif

	start_list[total_startups].start_res_id	= res;			// this objects id
	start_list[total_startups].key			= params[0];	// a key code to be passed to a script via a script var to SWITCH in the correct start
	strcpy(start_list[total_startups].description, (char*)params[1]);

	total_startups++;	//point to next

	return(1);
}
//------------------------------------------------------------------------------------
uint32	Con_print_start_menu(void)	//Tony14Oct96
{
	//the console 'starts' (or 's') command which lists out all the registered start points in the game
	uint32	j;
	int		scrolls=0;
	char	c;


	if	(!total_startups)
	{	Print_to_console("Sorry - no startup positions registered?");

		if	(!total_screen_managers)
			Print_to_console("There is a problem with startup.inf");
		else
			Print_to_console(" (%d screen managers found in startup.inf)", total_screen_managers);

	}
	else
	{
		for(j=0;j<total_startups;j++)
		{
			Print_to_console("%d  (%s)", j, start_list[j].description);
			Build_display();
			scrolls++;


			if	(scrolls==18)
			{
				Temp_print_to_console("- Press ESC to stop or any other key to continue");
				Build_display();

				do
				{
			 		//--------------------------------------------------
					// Service windows
					while (!gotTheFocus)
						if (ServiceWindows() == RDERR_APPCLOSED)
							break;

					if (ServiceWindows() == RDERR_APPCLOSED)	// if we pressed Ctrl-Q
					{
						Close_game();	//close engine systems down
						RestoreDisplay();
						CloseAppWindow();
						exit(0);	//quit the game
					}
 					//--------------------------------------------------
				}
				while(!KeyWaiting());

				ReadKey(&c);	//kill the key we just pressed
				if	(c==27)	//ESC
					break;

				Clear_console_line();	//clear the Press Esc message ready for the new line
				scrolls=0;
			}	


		}
	}
	return(1);
}
//------------------------------------------------------------------------------------
uint32	Con_start(uint8 *input)	//Tony15Oct96
{
//if the second word id is a numeric that can be applied to a genuine startup then do it
	uint32	j=0;
	uint32	start;
	char	*raw_script;
	char	*raw_data_ad;
	uint32	null_pc;



	if (*input == NULL)		// so that typing 'S' then <enter> works on NT (James26feb97)
	{
		Con_print_start_menu();
		return(1);
	}


	while(*(input+j))
	{
		if ( (*(input+j)>='0') && (*(input+j)<='9') )
			j++;
		else
			break;
	}


	if	(!*(input+j))	//didn't quit out of loop on a non numeric chr$
	{
		start = atoi((char*)input);

		if	(!total_startups)
			Print_to_console("Sorry - there are no startups!");

		else	if	(start<total_startups)	//a legal start
		{
//			do the startup as we've specified a legal start

			//--------------------------------------------------------------
			// restarting - stop sfx, music & speech!

			Clear_fx_queue();
			//---------------------------------------------
			FN_stop_music(NULL);	// fade out any music that is currently playing
			//---------------------------------------------

			UnpauseSpeech();
			StopSpeech();							// halt the sample prematurely

			//--------------------------------------------------------------
			// clean out all resources & flags, ready for a total restart (James24mar97)

			res_man.Remove_all_res();	// remove all resources from memory, including player object & global variables
			SetGlobalInterpreterVariables((int32*)(res_man.Res_open(1)+sizeof(_standardHeader)));	// reopen global variables resource & send address to interpreter - it won't be moving
			res_man.Res_close(1);

			FreeAllRouteMem();	// free all the route memory blocks from previous game

			if (speech_text_bloc_no)					// if there was speech text
			{
				Kill_text_bloc(speech_text_bloc_no);	// kill the text block
				speech_text_bloc_no=0;
			}

			//--------------------------------------------------------------

//			set the key
			raw_data_ad= (char*) (res_man.Res_open(8));	//+sizeof(_standardHeader)+sizeof(_object_hub));	//open george
			raw_script= (char*) (res_man.Res_open(start_list[start].start_res_id));	//+sizeof(_standardHeader)+sizeof(_object_hub));
			null_pc=start_list[start].key&0xffff;	//denotes script to run
			Print_to_console("running start %d", start);
			RunScript ( raw_script, raw_data_ad, &null_pc );

			res_man.Res_close(start_list[start].start_res_id);
			res_man.Res_close(8);	//close george

			FN_add_human(NULL);	// make sure thre's a mouse, in case restarting while mouse not available
		}
		else
			Print_to_console("not a legal start position");
	}
	else
	{
		Con_print_start_menu();		// so that typing 'S' then <enter> works under Win95
	}
	return(1);
}

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------



--- NEW FILE: startup.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/startup.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	_STARTUP
#define	_STARTUP

//#include "src\driver96.h"


#define	MAX_starts		100
#define	MAX_description	100


typedef	struct
{
	char	description[MAX_description];
	uint32	start_res_id;	//id of screen manager object
	uint32	key;			//tell the manager which startup you want (if there are more than 1) (i.e more than 1 entrance to a screen and/or seperate game boots)

} _startup;


extern	_startup	start_list[MAX_starts];

uint32	Init_start_menu(void);	//Tony13Aug96
uint32	Con_print_start_menu(void);	//Tony13Aug96
uint32	Con_start(uint8 *input);	//Tony15Oct96

#endif

--- NEW FILE: sword2.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/sword2.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//------------------------------------------------------------------------------------
#include <ctype.h>
#include <stdio.h>
//#include <windows.h>

#include "driver/driver96.h"
#include "common/gameDetector.h"
#include "build_display.h"
#include "console.h"
#include "controls.h"
#include "debug.h"
#include "events.h"
#include "header.h"
#include "interpreter.h"
#include "layers.h"
#include "logic.h"
#include "maketext.h"
#include "memory.h"
#include "mouse.h"
#include "protocol.h"
#include "resman.h"
#include "scroll.h"
#include "sound.h"
#include "speech.h"
#include "startup.h"
#include "sword2.h"
#include "sync.h"

#define MAX_PATH 260

void Start_game(void);

int  RunningFromCd();

uint8 quitGame = 0;

//------------------------------------------------------------------------------------
// version & owner details

//So version string is 18 bytes long :
//Version String =  <8 byte header,5 character version, \0, INT32 time>

uint8 version_string[HEAD_LEN+10]	=	{1, 255, 37, 22, 45, 128, 34, 67};

uint8 unencoded_name[HEAD_LEN+48]	=	{76, 185, 205, 23, 44, 34, 24, 34,
										'R','e','v','o','l','u','t','i','o','n',' ',
										'S','o','f','t','w','a','r','e',' ','L','t','d',
										0};

uint8 encoded_name[HEAD_LEN+48]		=	{44, 32, 190, 222, 123, 65, 233, 99,
										179, 209, 225, 157, 222, 238, 219, 209, 143, 224, 133, 190,
										232, 209, 162, 177, 198, 228, 202, 146, 180, 232, 214, 65,
										65, 65, 116, 104, 116, 114, 107, 104, 32, 49, 64, 35, 123,
										125, 61, 45, 41, 40, 163, 36, 49, 123, 125, 10};

//------------------------------------------------------------------------------------

uint8 gamePaused=0;			// James17jun97
//uint32 pause_text_bloc_no=0;	// James17jun97
uint8 graphics_level_fudged=0;	// James10july97
uint8 stepOneCycle=0;	// for use while game paused

//------------------------------------------------------------------------------------
void PauseGame(void);			// James17jun97
void UnpauseGame(void);			// James17jun97
//------------------------------------------------------------------------------------

static const VersionSettings bs2_settings[] = {
	/* Broken Sword 2 */
	{"bs2", "Broken Sword II", GID_BS2_FIRST, 99, VersionSettings::ADLIB_DONT_CARE, GF_DEFAULT_TO_1X_SCALER, "players.clu" },
	{NULL, NULL, 0, 0, VersionSettings::ADLIB_DONT_CARE, 0, NULL}
};

BS2State *g_bs2 = NULL;

const VersionSettings *Engine_BS2_targetList() {
	return bs2_settings;
}

Engine *Engine_BS2_create(GameDetector *detector, OSystem *syst) {
	return new BS2State(detector, syst);
}

BS2State::BS2State(GameDetector *detector, OSystem *syst)
	: Engine(detector, syst) {
	
	_detector = detector;
	_syst = syst;
	g_bs2 = this;
}


void BS2State::errorString(const char *buf1, char *buf2) {
	strcpy(buf2, buf1);
}

int32 InitialiseGame(void)
{
//init engine drivers

	uint8	*file;

	Zdebug("CALLING: Init_memory_manager");
	Init_memory_manager();		// get some falling RAM and put it in your pocket, never let it slip away
	Zdebug("RETURNED.");

	Zdebug("CALLING: res_man.InitResMan");
	res_man.InitResMan();		// initialise the resource manager
	Zdebug("RETURNED from res_man.InitResMan");

								// initialise global script variables
	file=res_man.Res_open(1);	// res 1 is the globals list
	Zdebug("CALLING: SetGlobalInterpreterVariables");
	SetGlobalInterpreterVariables((int32*)(file+sizeof(_standardHeader)));
	Zdebug("RETURNED.");
//	res_man.Res_close(1);		// DON'T CLOSE VARIABLES RESOURCE - KEEP IT OPEN AT VERY START OF MEMORY SO IT CAN'T MOVE!

	file=res_man.Res_open(8);	// DON'T CLOSE PLAYER OBJECT RESOURCE - KEEP IT OPEN IN MEMORY SO IT CAN'T MOVE!

	//----------------------------------------
	Zdebug("CALLING: InitialiseFontResourceFlags");
	InitialiseFontResourceFlags();	// Set up font resource variables for this language version (James31july97)
									// Also set the windows application name to the proper game name
	Zdebug("RETURNED.");
	//----------------------------------------

	Zdebug("CALLING: Init_console");
	Init_console();				// set up the console system
	Zdebug("RETURNED.");

	#ifdef _DEBUG
		Zdebug("CALLING: Init_start_menu");
		Init_start_menu();			// read in all the startup information
		Zdebug("RETURNED from Init_start_menu");
	#endif	// _DEBUG



	Zdebug("CALLING: Init_text_bloc_system");
	Init_text_bloc_system();	// no blocs live
	Zdebug("RETURNED.");

	Zdebug("CALLING: Init_sync_system");
	Init_sync_system();
	Zdebug("RETURNED.");

	Zdebug("CALLING: Init_event_system");
	Init_event_system();
	Zdebug("RETURNED.");

	Zdebug("CALLING: Init_fx_queue");
	Init_fx_queue();			// initialise the sound fx queue
	Zdebug("RETURNED.");

#ifdef _DEMO	// demo only
	DEMO=1;		// set script variable
#endif

	return(0);
}
//------------------------------------------------------------------------------------
void	Close_game()	//Tony11Oct96
{
	Zdebug("Close_game() STARTING:");
//avoid corruption when windows kicks back in
	EraseBackBuffer();
	FlipScreens();
	EraseBackBuffer();
	FlipScreens();

	Kill_music();			// Stop music instantly! (James22aug97)
	Close_memory_manager();	// free the memory again
	res_man.Close_ResMan();

	Zdebug("Close_game() DONE.");
}
//------------------------------------------------------------------------------------
int32 GameCycle(void)
{
//do one game cycle


	{
		if	(LLogic.Return_run_list())	//got a screen to run?
		{
			do	//run the logic session UNTIL a full loop has been performed
			{
				Reset_render_lists();	// reset the graphic 'buildit' list before a new logic list (see FN_register_frame)
				Reset_mouse_list();		// reset the mouse hot-spot list (see FN_register_mouse & FN_register_frame)
			}
			while(LLogic.Process_session());	//keep going as long as new lists keep getting put in - i.e. screen changes
		}
		else	//start the console and print the start options perhaps?
		{
			StartConsole();
			Print_to_console("AWAITING START COMMAND: (Enter 's 1' then 'q' to start from beginning)");
		}
	}

	if (this_screen.scroll_flag)	// if this screen is wide
		Set_scrolling();			// recompute the scroll offsets every game-cycle

	Mouse_engine();	//check the mouse

	Process_fx_queue();

	res_man.Res_next_cycle();	// update age and calculate previous cycle memory usage

	if (quitGame)
		return(1);
	else
		return(0);
}
//------------------------------------------------------------------------------------
// int main(int argc, char *argv[])
// int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
void BS2State::go()
{
	uint32 rv;
	uint8  breakOut = 0;
	char	c;
	int	j=100;
	uint32	pc=0;

//	Zdebug("[%s]", lpCmdLine);


	#ifndef _DEBUG
	DisableQuitKey();	// so cannot use Ctrl-Q from the release versions (full game or demo)
	#endif


	if	(RunningFromCd())	//stop this game being run from CD
		exit(-1);



	// Call the application "Revolution" until the resource manager is ready to dig the name out of a text file
	// See InitialiseGame() which calls InitialiseFontResourceFlags() in maketext.cpp
	// Have to do it like this since we cannot really fire up the resource manager until a window
	// has been created as any errors are displayed via a window, thus time becomes a loop.

	Zdebug("CALLING: InitialiseWindow");
	// rv = InitialiseWindow(hInstance, hPrevInstance, lpCmdLine, nCmdShow, "Revolution");
	rv = RD_OK;
 	Zdebug("RETURNED with rv = %.8x", rv);
	if (rv != RD_OK)
	{
		// ReportDriverError(rv);
		return;
	}

	Zdebug("CALLING: InitialiseDisplay");
	// rv = InitialiseDisplay(640, 480, 8, RD_FULLSCREEN);
	_syst->init_size(640, 480);
	rv = RD_OK;
		
	Zdebug("RETURNED with rv = %.8x", rv);
	if (rv != RD_OK)
	{
		// ReportDriverError(rv);
		CloseAppWindow();
		return;
	}

	Zdebug("CALLING: ReadOptionSettings");
	ReadOptionSettings();	//restore the menu settings
  	Zdebug("RETURNED.");

	Zdebug("CALLING: InitialiseSound");
	rv = InitialiseSound(22050, 2, 16);
 	Zdebug("RETURNED with rv = %.8x", rv);
	// don't care if this fails, because it should still work without sound cards
	// but it should set a global system flag so that we can avoid loading sound fx & streaming music
	// because they won't be heard anyway
/*
	if (rv != RD_OK)
	{
		ReportDriverError(rv);
		CloseAppWindow();
		return(0);
	}
*/

	Zdebug("CALLING: InitialiseGame");
	if (InitialiseGame())
	{
	  	Zdebug("RETURNED from InitialiseGame - closing game");
		RestoreDisplay();
		CloseAppWindow();
		return;
	}
   	Zdebug("RETURNED from InitialiseGame - ok");



//check for restore game on startup - at the mo any passed argument is good enough to trigger this
	// if	(lpCmdLine[0])	//non zero
	if (0)
	{
		Set_mouse(NORMAL_MOUSE_ID);

		if	(!Restore_control())	// restore a game
			Start_game();
	}
	//-------------------------------------------------------------
	// release versions only (full-game and demo)
//	#if NDEBUG	// comment this out for debug versions to start game automatically!
	else
		Start_game();
//	#endif		// comment this out for debug versions to start game automatically!
	//-------------------------------------------------------------


	Zdebug("CALLING: InitialiseRenderCycle");
	InitialiseRenderCycle();
  	Zdebug("RETURNED.");

	while (TRUE)
	{
		if (ServiceWindows() == RDERR_APPCLOSED)
		{
			break;		// break out of main game loop
		}

		
		// check for events
		parseEvents();
#ifdef _DEBUG
		if (grabbingSequences && (!console_status))
			GrabScreenShot();
#endif

		while (!gotTheFocus)
		{
			if (ServiceWindows() == RDERR_APPCLOSED)
			{
				breakOut = 1;
				break;	// break out of this while-loop
			}
		}

		if (breakOut)	// if we are closing down the game
			break;		// break out of main game loop

//-----

#ifdef _DEBUG
		if	(console_status)
		{
			if	(One_console())
			{
				EndConsole();
				UnpauseAllSound();	// see sound.cpp
			}
		}
#endif

		if	(!console_status)	//not in console mode - if the console is quit we want to get a logic cycle in before
		{							//the screen is build. Mostly because of first scroll cycle stuff
#ifdef _DEBUG
			if (stepOneCycle)	// if we've just stepped forward one cycle while the game was paused
			{
				PauseGame();
				stepOneCycle=0;
			}
#endif
			if (KeyWaiting())
			{
				ReadKey(&c);
#ifdef _DEBUG
				if (c==27)					// ESC whether paused or not
				{
					PauseAllSound();					// see sound.cpp
					StartConsole();						// start the console
				}
				else
#endif
					if (gamePaused)					// if currently paused
					{
						if (toupper(c)=='P')				// 'P' while paused = unpause!
						{
							UnpauseGame();
						}
#ifdef _DEBUG
						else if (toupper(c)==' ')			// SPACE bar while paused = step one frame!
						{
							stepOneCycle=1;					// step through one game cycle
							UnpauseGame();
						}
#endif	// _DEBUG
					}
				else if (toupper(c)=='P')	// 'P' while not paused = pause!
				{
					PauseGame();
				}
#ifdef _DEBUG	// frame-skipping only allowed on debug version
				else if (toupper(c)=='S')	// 'S' toggles speed up (by skipping display rendering)
				{
					renderSkip = 1 - renderSkip;
				}
#endif	// _DEBUG
			}

			if (gamePaused==0)	// skip GameCycle if we're paused
			{
#ifdef _DEBUG
				gameCycle += 1;
#endif

				if (GameCycle())
					break;		// break out of main game loop
			}

#ifdef _DEBUG
			Build_debug_text();			// creates the debug text blocks
#endif	// _DEBUG
		}
//-----

		// James (24mar97)

#ifdef _DEBUG
		if ((console_status)||(renderSkip==0)||(gameCycle%4 == 0))	// if not in console & 'renderSkip' is set, only render display once every 4 game-cycles
			Build_display();	// create and flip the screen
#else
		Build_display();	// create and flip the screen
#endif	// _DEBUG

	}

	Close_game();	//close engine systems down
	RestoreDisplay();
	CloseAppWindow();

	return;	//quit the game
}
//------------------------------------------------------------------------------------
int RunningFromCd()
{
   char  sCDName[MAX_PATH];
   char  sRoot[MAX_PATH];
   DWORD dwMaxCompLength, dwFSFlags;
/*
   GetModuleFileName(NULL , sRoot, _MAX_PATH);
   *(strchr(sRoot,'\\')+1) = '\0';

   if (!GetVolumeInformation(sRoot, sCDName,_MAX_PATH, NULL, &dwMaxCompLength, &dwFSFlags, NULL, 0))
      return -1;
   if (!scumm_strnicmp(sCDName,CD1_LABEL,6))
      return 1;
   if (!scumm_strnicmp(sCDName,CD2_LABEL,6))
      return 2;
*/
   return 0;
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------


//------------------------------------------------------------------------------------
void	Start_game(void)	//Tony29May97
{
//boot the game straight into a start script

	Zdebug("Start_game() STARTING:");

#ifdef _DEMO
	#define SCREEN_MANAGER_ID	19	// DOCKS SECTION START
#else
	#define SCREEN_MANAGER_ID	949	// INTRO & PARIS START
#endif

	char	*raw_script;
	char	*raw_data_ad;
	uint32	null_pc=1;	// the required start-scripts are both script #1 in the respective ScreenManager objects

	raw_data_ad	= (char*) (res_man.Res_open(8));					// open george object, ready for start script to reference
	raw_script	= (char*) (res_man.Res_open(SCREEN_MANAGER_ID));	// open the ScreenManager object

	RunScript ( raw_script, raw_data_ad, &null_pc );			// run the start script now (because no console)

	res_man.Res_close(SCREEN_MANAGER_ID);						// close the ScreenManager object
	res_man.Res_close(8);										// close george

	Zdebug("Start_game() DONE.");
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
void PauseGame(void)		// James17jun97
{
//	uint8	*text;

//	text = FetchTextLine( res_man.Res_open(3258), 449 );	// open text file & get the line "PAUSED"
//	pause_text_bloc_no = Build_new_block(text+2, 320, 210, 640, 184, RDSPR_TRANS+RDSPR_DISPLAYALIGN, SPEECH_FONT_ID, POSITION_AT_CENTRE_OF_BASE);
//	res_man.Res_close(3258);	// now ok to close the text file

	//---------------------------
	// don't allow Pause while screen fading or while black (James 03sep97)
	if(GetFadeStatus()!=RDFADE_NONE)
		return;
	//---------------------------
	
  	PauseAllSound();

//make a normal mouse
	ClearPointerText();
//	mouse_mode=MOUSE_normal;
	SetLuggageAnim(NULL, NULL);	//this is the only place allowed to do it this way
	Set_mouse(NULL);			// blank cursor
	mouse_touching=1;	//forces engine to choose a cursor

	if (current_graphics_level==3)	// if level at max
	{
		UpdateGraphicsLevel(3,2);	// turn down because palette-matching won't work when dimmed
		graphics_level_fudged=1;
	}

	if (stepOneCycle==0)	// don't dim it if we're single-stepping through frames
	{
  		DimPalette();				// dim the palette during the pause (James26jun97)
	}

	gamePaused=1;
}
//------------------------------------------------------------------------------------
void UnpauseGame(void)		// James17jun97
{
//	Kill_text_bloc(pause_text_bloc_no);	// removed "PAUSED" from screen

	if	((OBJECT_HELD)&&(real_luggage_item))
		Set_luggage(real_luggage_item);

	UnpauseAllSound();

	SetFullPalette(0xffffffff);	// put back game screen palette; see Build_display.cpp (James26jun97)

 	if (graphics_level_fudged)	// if level at max
	{
		UpdateGraphicsLevel(2,3);	// turn up again
		graphics_level_fudged=0;
	}

	gamePaused=0;
	unpause_zone=2;

	if	((!mouse_status)||(choosing))	//if mouse is about or we're in a chooser menu
		Set_mouse(NORMAL_MOUSE_ID);
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------


--- NEW FILE: sword2.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/sword2.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	_SWORD2
#define	_SWORD2

//#include "src\driver96.h"


#ifdef _PCF76	// Bodge for PCF76 version so that their demo CD can be labelled "PCF76" rather than "RBSII1"
	#define CD1_LABEL	"PCF76"
#else
	#define CD1_LABEL	"RBSII1"
#endif


#define	CD2_LABEL	"RBSII2"

void	Close_game();	//Tony11Oct96

void PauseGame(void);		// James17jun97
void UnpauseGame(void);		// James17jun97
void Start_game(void);		// James13aug97

#define HEAD_LEN 8

extern uint8 version_string[];		// for displaying from the console
extern uint8 unencoded_name[];


// TODO move stuff into class
class BS2State : public Engine {
		void errorString(const char *buf_input, char *buf_output);
	public:
		BS2State(GameDetector *detector, OSystem *syst);
		void go();
		void parseEvents();
		OSystem *_syst;
		GameDetector *_detector;
	private:
		bool _quit;
};

extern BS2State *g_bs2;

#endif

--- NEW FILE: sync.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/sync.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//------------------------------------------------------------------------------------
#include <stdio.h>

//#include "src\driver96.h"
#include "console.h"
#include "debug.h"
#include "defs.h"
#include "interpreter.h"
#include "memory.h"
#include "object.h"
#include "sync.h"
//------------------------------------------------------------------------------------
typedef	struct
{
	uint32	id;
	uint32	sync;
}	_sync_unit;	//haaaaaaaa

#define	MAX_syncs	10	//there wont be many will there. probably 2 at most i reckon


_sync_unit	sync_list[MAX_syncs];

//------------------------------------------------------------------------------------
void	Init_sync_system(void)	//Tony27Nov96
{
//set list to 0's

	uint32	j;



	for	(j=0;j<MAX_syncs;j++)
		sync_list[j].id=0;


}
//------------------------------------------------------------------------------------
int32	FN_send_sync(int32 *params)	//Tony27Nov96
{
//param	0 sync's recipient
//param	1 sync value


	uint32	current_sync=0;


	if	(sync_list[current_sync].id)
	{
		do
			current_sync++;
		while(sync_list[current_sync].id);	//zip along until we find a free slot
		
	}

//	Zdebug(" %d sending sync %d to %d", ID, params[1], params[0]);


	sync_list[current_sync].id=params[0];
	sync_list[current_sync].sync=params[1];



	return(IR_CONT);
}
//------------------------------------------------------------------------------------
void	Clear_syncs(uint32	id)	//Tony27Nov96
{
//clear any syncs registered for this id
//call this just after the id has been processed

	uint32	j;


//there could in theory be more than one sync waiting for us so clear the lot

	for	(j=0;j<MAX_syncs;j++)
		if	(sync_list[j].id==id)
		{	//Zdebug("removing sync %d for %d", j, id);
			sync_list[j].id=0;
		}


}
//------------------------------------------------------------------------------------
uint32	Get_sync(void)	//Tony27Nov96
{
	// check for a sync waiting for this character
	// - called from system code eg. from inside FN_anim(), to see if animation to be quit

	uint32	j;


	for	(j=0;j<MAX_syncs;j++)
		if	(sync_list[j].id == ID)
			return(1);	//means sync found	Tony12July97

//			return(sync_list[j].sync);	//return sync value waiting



	return(0);	//no sync found

}
//------------------------------------------------------------------------------------
int32	FN_get_sync(int32	*params)	//Tony27Nov96
{
// check for a sync waiting for this character
// - called from script

//params	none


	uint32	j;


	for	(j=0;j<MAX_syncs;j++)
		if	(sync_list[j].id == ID)
		{	RESULT=sync_list[j].sync;
			return(IR_CONT);	//return sync value waiting
		}

	RESULT=0;

	if (params);

	return(IR_CONT);	//no sync found

}
//------------------------------------------------------------------------------------
int32	FN_wait_sync(int32	*params)	//Tony27Nov96
{
//keep calling until a sync recieved

//params	none


	uint32	j;

	j=ID;


//	Zdebug("%d waits", ID);

	
	for	(j=0;j<MAX_syncs;j++)
		if	(sync_list[j].id == ID)
		{	RESULT=sync_list[j].sync;
			//Zdebug(" go");
			return(IR_CONT);	//return sync value waiting
		}

	if (params);

	return(IR_REPEAT);	//back again next cycle

}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------


--- NEW FILE: sync.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/sync.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	_SYNC
#define	_SYNC

//#include "src\driver96.h"
#include "object.h"


void	Init_sync_system(void);	//Tony27Nov96
void	Clear_syncs(uint32	id);	//Tony27Nov96
uint32	Get_sync(void);	//Tony27Nov96


#endif

--- NEW FILE: tony_gsdk.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/tony_gsdk.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//===================================================================================================================
//
// File - tony_gsdk.cpp
//
//===================================================================================================================


//general odds and ends

#include <sys/type.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <io.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

//#include "src\driver96.h"
#include "debug.h"
#include "header.h"
#include "layers.h"
#include "memory.h"
#include "protocol.h"
#include "resman.h"
#include "tony_gsdk.h"

// TODO replace with file class

//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
uint32	Read_file(char	*name,	mem	**membloc, uint32	uid)	//Tony25Apr96
{
//read the file in and place into an allocated MEM_float block
//used for non resources manager files - stuff like fonts, etc.
//returns bytes read or 0 for error

	FILE	*fh=0;	//file pointer
	uint32	end;



	fh = fopen(name, "rb");	//open for binary reading

	if	(fh==NULL)
	{	Zdebug("Read_file cannot open %s", name);
		return(0);
	}

//ok, find the length and read the file in
	fseek(fh, 0, SEEK_END);	//get size of file
   end = ftell(fh);	//finally got the end

	*membloc= Twalloc(end, MEM_float, uid);	//reserve enough floating memory for the file
	
	fseek( fh, 0, SEEK_SET );	//back to beginning of file

	if	(fread( (*membloc)->ad, sizeof(char), end,fh)==-1)
	{	Zdebug("Read_file read fail %d", name);
		return(0);
	}

	fclose(fh);

	return(end);	//ok, done it - return bytes read
}
//-----------------------------------------------------------------------------------------------------------------------
int32	Direct_read_file(char	*name,	char	*ad)	//Tony1May96
{
//load the file directly into the memory location passed
//memory must be pre-allocated

	FILE	*fh=0;	//file pointer
	uint32	end;


	fh = fopen(name, "rb");	//open for binary reading

	if	(fh==NULL)
	{	Zdebug("Direct_read_file cannot open %s", name);
		return(0);
	}

//ok, find the length and read the file in
	fseek(fh, 0, SEEK_END);	//get size of file
   end = ftell(fh);	//finally got the end
	fseek( fh, 0, SEEK_SET );	//back to beginning of file

	if	(fread( ad, sizeof(char), end,fh)==-1)
	{	Zdebug("Direct_read_file read fail %d", name);
		return(0);
	}

	fclose(fh);


	return(end);	//ok, done it - return bytes read
}
//-----------------------------------------------------------------------------------------------------------------------
int32	Direct_write_file(char	*name,	char	*ad, uint32 total_bytes)	//Tony1May96
{
//load the file directly into the memory location passed
	int	fh;

	//fh = open(name, _O_RDWR | _O_CREAT);	//open for reading
	fh = open(name, O_RDWR | O_CREAT);	//open for reading

	if	(fh==-1)
	{	Zdebug("Direct_write_file open fail %d", name);
		return(-1);
	}

	if	(write( fh, ad, total_bytes)==-1)
	{	Zdebug("Direct_write_file write fail %d", name);
		return(-1);
	}

	close(fh);

	return(0);	//ok, done it
}

//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------


--- NEW FILE: tony_gsdk.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/tony_gsdk.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	TONY_GSDK
#define	TONY_GSDK

//#include "src\driver96.h"
#include "memory.h"



uint32	Read_file(char	*name,	mem	**membloc, uint32 uid);
int32	Direct_read_file(char	*name,	char	*ad);
int32	Direct_write_file(char	*name,	char	*ad, uint32 total_bytes);


#endif

--- NEW FILE: walker.cpp ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/walker.cpp,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

//--------------------------------------------------------------------------------------
// WALKER.CPP by James (14nov96)

// script functions for moving megas about the place & also for keeping tabs on them

// FN_walk()				// walk to (x,y,dir)
// FN_walk_to_anim()		// walk to start position of anim
// FN_turn()				// turn to (dir)
// FN_stand_at()			// stand at (x,y,dir)
// FN_stand()				// stand facing (dir)
// FN_stand_after_anim()	// stand at end position of anim
// FN_face_id()				// turn to face object (id)
// FN_face_xy()				// turn to face point (x,y)
// FN_is_facing()			// is mega (id) facing us?
// FN_get_pos()				// get details of another mega's position

//--------------------------------------------------------------------------------------

//#include "src\driver96.h"
#include "console.h"
#include "defs.h"
#include "events.h"
#include "function.h"
#include "interpreter.h"
#include "logic.h"	// for FN_add_to_kill_list
#include "object.h"
#include "protocol.h"
#include "router.h"
#include "sync.h"

//--------------------------------------------------------------------------------------

int16	standby_x;			// see FN_set_standby_coords
int16	standby_y;
uint8	standby_dir;

//--------------------------------------------------------------------------------------
/*
uint8 Check_walk_anim_ok( Object_mega *ob_mega, Object_walkdata *ob_walkdata );
//--------------------------------------------------------------------------------------
// NEW CODE TO VERIFY THAT THE WALK-ANIM CONTAINS NO INVALID FRAMES!
// (James 15sep97)
uint8 Check_walk_anim_ok( Object_mega *ob_mega, Object_walkdata *ob_walkdata )
{
	int32		walk_pc=0;
	_walkData	*walkAnim;
	uint8		*anim_file;
	_animHeader	*anim_head;
	uint32		lastValidFrameNo;
	uint8		ok=1;


	anim_file = res_man.Res_open(ob_mega->megaset_res);	// open mega-set file
	anim_head = FetchAnimHeader( anim_file );			// set up pointer to the animation header
 	lastValidFrameNo = anim_head->noAnimFrames-1;		// get last valid frame number
	res_man.Res_close(ob_mega->megaset_res);			// close file

   	walkAnim = LockRouteMem();	// lock the _walkData array

	while (ok && (walkAnim[walk_pc].frame != 512))	// '512' id end-marker
	{
		if (walkAnim[walk_pc].frame > lastValidFrameNo)	// if frame exceeds the allowed range
			ok=0;

		walk_pc++;
	}

	FloatRouteMem();	// allow _walkData array to float about memory again

	return(ok);
}
*/
//--------------------------------------------------------------------------------------
// walk mega to (x,y,dir)

int32 FN_walk(int32 *params)	// James (14nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target x-coord
	//			5 target y-coord
	//			6 target direction

	Object_logic	*ob_logic;
	Object_graphic	*ob_graph;
	Object_mega		*ob_mega;
	Object_walkdata	*ob_walkdata;
	int16			target_x;
	int16			target_y;
	uint8			target_dir;
	int8			route;
	int32			walk_pc;
	_walkData		*walkAnim;
	uint8			colliding=0;	// set to 1 when collision avoided

	//----------------------------------------------------------------------------------------
	// get the parameters

	ob_logic	= (Object_logic *)params[0];
	ob_graph	= (Object_graphic *)params[1];
	ob_mega		= (Object_mega *)params[2];

	target_x	= params[4];
	target_y	= params[5];
	target_dir	= params[6];

	//----------------------------------------------------------------------------------------
	// if this is the start of the walk, calculate route

	if (ob_logic->looping==0)
	{
		//---------------------------
		// If we're already there, don't even bother allocating memory and calling the router,
		// just quit back & continue the script!
		// This avoids an embarassing mega stand frame appearing for one cycle when we're already
		// in position for an anim eg. repeatedly clicking on same object to repeat an anim
		// - no mega frame will appear in between runs of the anim.
		
		if ((ob_mega->feet_x == target_x) && (ob_mega->feet_y == target_y)
			&& (ob_mega->current_dir == target_dir))
		{
			RESULT = 0;				// 0 means ok - finished walk
			return(IR_CONT);			// may as well continue the script
		}

		//---------------------------
		if ((params[6] < 0) || (params[6] > 8))	// invalid direction (NB. '8' means end walk on ANY direction)
			Con_fatal_error("Invalid direction (%d) in FN_walk (%s line %u)",params[6],__FILE__,__LINE__);
		//---------------------------

		ob_walkdata	= (Object_walkdata *)params[3];

		ob_mega->walk_pc=0;			//always

		AllocateRouteMem();	// set up mem for _walkData in route_slots[] & set mega's 'route_slot_id' accordingly
		route = RouteFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);

		/*
		if (id == PLAYER)
		{
			nExtraBars = 0;
			nExtraNodes = 0;
			if	((route == 1) || (route == 2))
			{
				megaOnGrid = 0;	// if we have just checked a grid with the mega on the grid take the mega off
				reRouteGeorge = 0;
			}
		}
		*/

		if	((route == 1) || (route == 2))	// 1=created route	2=zero route but may need to turn
		{
			//-------------------------------------------
			ob_logic->looping	= 1;		// so script FN_walk loop continues until end of walk-anim
											// need to animate the route now, so don't set result or return yet!

			ob_mega->currently_walking=1;	// started walk(James23jun97)
											// (see FN_get_player_savedata() in save_rest.cpp
			//-------------------------------------------
		}
		else							// 0=can't make route to target
		{
			FreeRouteMem();		// free up the walkdata mem block
			RESULT = 1;					// 1 means error, no walk created
			return(IR_CONT);			// may as well continue the script
		}

		// ok, walk is about to start, so set the mega's graphic resource
		ob_graph->anim_resource = ob_mega->megaset_res;
	}
	//----------------------------------------------------------------------------------------
	// double clicked an exit so quit the walk when screen is black

 	else if ((EXIT_FADING) && (GetFadeStatus()==RDFADE_BLACK))
	{
//		ok, thats it - back to script and change screen

		ob_logic->looping=0;	// so script loop stops
		FreeRouteMem();			// free up the walkdata mem block

		EXIT_CLICK_ID=0;		// must clear in-case on the new screen there's a walk instruction (which would get cut short)
//		EXIT_FADING=0;	// this will be reset when we change screens, so we can use it in script to check if a 2nd-click came along


		ob_mega->currently_walking=0;	// finished walk (James23jun97)
										// (see FN_get_player_savedata() in save_rest.cpp

		ob_mega->colliding=0;

		RESULT = 0;				// 0 means ok
		return(IR_CONT);		// continue the script so that RESULT can be checked!
	}
	//----------------------------------------------------------------------------------------
	// get pointer to walkanim & current frame position

	walkAnim	= LockRouteMem();	// lock the _walkData array
	walk_pc		= ob_mega->walk_pc;

	//----------------------------------------------------------------------------------------
	// if stopping the walk early, overwrite the next step with a slow-out, then finish

	if (Check_event_waiting())
	{
		if ((walkAnim[walk_pc].step == 0) && (walkAnim[walk_pc+1].step == 1))	// at the beginning of a step
		{
			ob_walkdata	= (Object_walkdata *)params[3];
			EarlySlowOut(ob_mega,ob_walkdata);
		}
	}
/*
	else if (CheckForCollision())
	{
		if ((walkAnim[walk_pc].step == 0) && (walkAnim[walk_pc+1].step == 1))	// at the beginning of a step
		{
			ob_walkdata	= (Object_walkdata *)params[3];
			EarlySlowOut(ob_mega,ob_walkdata);

			ob_mega->colliding=1;
		}
	}
*/
	//------------------------------------------------------------------
	// get new frame of walk

	ob_graph->anim_pc		= walkAnim[walk_pc].frame;
	ob_mega->current_dir	= walkAnim[walk_pc].dir;
	ob_mega->feet_x			= walkAnim[walk_pc].x;
	ob_mega->feet_y			= walkAnim[walk_pc].y;

	//------------------------------------------------------------------
	// check if NEXT frame is in fact the end-marker of the walk sequence
	// so we can return to script just as the final (stand) frame of the walk is set
	// - so that if followed by an anim, the anim's first frame replaces the final stand-frame
	// of the walk (see below)

	if (walkAnim[walk_pc+1].frame==512)	// '512' is end-marker
	{
		ob_logic->looping=0;	// so script loop stops
		FreeRouteMem();	// free up the walkdata mem block

		ob_mega->currently_walking=0;	// finished walk(James23jun97)
										// (see FN_get_player_savedata() in save_rest.cpp
/*
		if (ID==CUR_PLAYER_ID)
		{
			george_walking = 0;

			if (megaOnGrid == 2)
				megaOnGrid = 0;
		}
*/

		if (Check_event_waiting())	// if George's walk has been interrupted to run a new action script for instance
		{							// or Nico's walk has been interrupted by player clicking on her to talk
			ob_mega->colliding=0;	// Don't care about collision now we've got an event
			Start_event();
			RESULT = 1;				// 1 means didn't finish walk
			return(IR_TERMINATE);
		}
		else if (ob_mega->colliding)	// If we almost collided with another mega,
		{								// then we want to re-route from scratch.
			ob_mega->colliding=0;		// reset the flag now we've acknowledged the collision
			return(IR_REPEAT);			// Stop the script, but repeat this call next cycle
		}
		else
		{
			RESULT = 0;				// 0 means ok - finished walk
			return(IR_CONT);		// CONTINUE the script so that RESULT can be checked!
									// Also, if an anim command follows the FN_walk command,
									// the 1st frame of the anim (which is always a stand frame itself)
									// can replace the final stand frame of the walk, to hide the
									// slight difference between the shrinking on the mega frames
									// and the pre-shrunk anim start-frame.
		}
	}
	//----------------------------------------------------------------------------------------
	// increment the walkanim frame number, float the walkanim & come back next cycle

	ob_mega->walk_pc++;

	FloatRouteMem();	// allow _walkData array to float about memory again
	return(IR_REPEAT);	// stop the script, but repeat this call next cycle

	//------------------------------------------------------------------
}
//--------------------------------------------------------------------------------------
// walk mega to start position of anim

int32 FN_walk_to_anim(int32 *params)	// James (14nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 anim resource id

	Object_logic	*ob_logic;
	uint8			*anim_file;
	_animHeader		*anim_head;
	int32			pars[7];

	//----------------------------------------------------------------------------------------
	// if this is the start of the walk, read anim file to get start coords

	ob_logic = (Object_logic *)params[0];

	if (ob_logic->looping==0)
	{
		anim_file = res_man.Res_open(params[4]);		// open anim file
		anim_head = FetchAnimHeader( anim_file );		// point to animation header

		pars[4] = anim_head->feetStartX;				// target_x
		pars[5] = anim_head->feetStartY;				// target_y
		pars[6] = anim_head->feetStartDir;				// target_dir

		res_man.Res_close(params[4]);					// close anim file

		//------------------------------------------
		if ((pars[4]==0)&&(pars[5]==0))					// if start coords not yet set in anim header
		{
			pars[4] = standby_x;						// use the standby coords
			pars[5] = standby_y;						// (which should be set beforehand in the script)
			pars[6] = standby_dir;

			Zdebug("WARNING: FN_walk_to_anim(%s) used standby coords", FetchObjectName(params[4]));
		}

		if ((pars[6] < 0) || (pars[6] > 7))				// check for invalid direction
			Con_fatal_error("Invalid direction (%d) in FN_walk_to_anim (%s line %u)", pars[6],__FILE__,__LINE__);

		//------------------------------------------
	}
	//----------------------------------------------------------------------------------------
	// set up the rest of the parameters for FN_walk()

	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];	// walkdata - needed for EarlySlowOut if player clicks elsewhere during the walk

	//-------------------------------------------------------------------------------------------------------

	return FN_walk(pars);	// call FN_walk() with target coords set to anim start position
}

//--------------------------------------------------------------------------------------
// turn mega to <direction>
// just needs to call FN_walk() with current feet coords, so router can produce anim of turn frames

int32 FN_turn(int32 *params)	// James (15nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target direction

	Object_logic	*ob_logic;
	Object_mega		*ob_mega;
	int32			pars[7];

	// if this is the start of the turn, get the mega's current feet coords + the required direction

	ob_logic = (Object_logic *)params[0];

	if (ob_logic->looping==0)
	{
	 	//--------------------------------------------
		if ((params[4] < 0) || (params[4] > 7))	// invalid direction
			Con_fatal_error("Invalid direction (%d) in FN_turn (%s line %u)",params[4],__FILE__,__LINE__);
		//--------------------------------------------

	 	ob_mega = (Object_mega *)params[2];
	
		pars[4] = ob_mega->feet_x;
		pars[5] = ob_mega->feet_y;
		pars[6] = params[4];	// DIRECTION to turn to
	}

	//----------------------------------------------------------------------------------------
	// set up the rest of the parameters for FN_walk()

	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];

	//----------------------------------------------------------------------------------------

	return FN_walk(pars);	// call FN_walk() with target coords set to feet coords
}
//--------------------------------------------------------------------------------------
// stand mega at (x,y,dir)
// sets up the graphic object, but also needs to set the new 'current_dir' in the mega object, so the router knows in future

int32 FN_stand_at(int32 *params)	// James
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 target x-coord
	//			3 target y-coord
	//			4 target direction

	Object_mega		*ob_mega;
	Object_graphic	*ob_graph;

	//----------------------------------------------------------------------------------------
	// check for invalid direction

	if ((params[4] < 0) || (params[4] > 7))	// invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_stand_at (%s line %u)",params[4],__FILE__,__LINE__);

	//----------------------------------------------------------------------------------------
	// set up pointers to the graphic & mega structure

	ob_graph	= (Object_graphic *)params[0];
	ob_mega		= (Object_mega *)params[1];

	//----------------------------------------------------------------------------------------
	// set up the stand frame & set the mega's new direction

	ob_graph->anim_resource	= ob_mega->megaset_res;	// mega-set animation file
	ob_mega->feet_x			= params[2];			// x
	ob_mega->feet_y			= params[3];			// y
	ob_graph->anim_pc		= params[4]+96;			// dir + first stand frame (always frame 96)
	ob_mega->current_dir	= params[4];			// dir

 	//----------------------------------------------------------------------------------------

	return(IR_CONT);	// continue the script
}

//--------------------------------------------------------------------------------------
// stand mega in <direction> at current feet coords
// just needs to call FN_stand_at() with current feet coords

int32 FN_stand(int32 *params)	// James (15nov96)
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 target direction

	Object_mega *ob_mega = (Object_mega *)params[1];
	int32 pars[5];

	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = ob_mega->feet_x;
	pars[3] = ob_mega->feet_y;
	pars[4] = params[2];	// DIRECTION to stand in

	return FN_stand_at(pars);	// call FN_stand_at() with target coords set to feet coords
}
//--------------------------------------------------------------------------------------
// stand mega at end position of anim

int32 FN_stand_after_anim(int32 *params)	// James (14nov96)
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 anim resource id

	uint8 *anim_file;
	_animHeader *anim_head;
	int32 pars[5];

	//----------------------------------------------------------------------------------------
	// open the anim file & set up a pointer to the animation header

	anim_file = res_man.Res_open(params[2]);	// open anim file
	anim_head = FetchAnimHeader( anim_file );

	//----------------------------------------------------------------------------------------
	// set up the parameter list for FN_walk_to()

	pars[0] = params[0];
	pars[1] = params[1];

	pars[2] = anim_head->feetEndX;					// x
	pars[3] = anim_head->feetEndY;					// y
	pars[4] = anim_head->feetEndDir;				// dir

	//----------------------------------------------------------------------------------------

	if ((pars[2]==0)&&(pars[3]==0))					// if start coords not available either
	{
		pars[2] = standby_x;						// use the standby coords
		pars[3] = standby_y;						// (which should be set beforehand in the script)
		pars[4] = standby_dir;

		Zdebug("WARNING: FN_stand_after_anim(%s) used standby coords", FetchObjectName(params[2]));
	}

	if ((pars[4] < 0) || (pars[4] > 7))				// check for invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_stand_after_anim (%s line %u)", pars[4],__FILE__,__LINE__);

	//----------------------------------------------------------------------------------------
	// close the anim file

	res_man.Res_close(params[2]);		// close anim file

	//----------------------------------------------------------------------------------------

	return FN_stand_at(pars);			// call FN_stand_at() with target coords set to anim end position
}

//--------------------------------------------------------------------------------------
// stand mega at start position of anim

int32 FN_stand_at_anim(int32 *params)	// James (07feb97)
{
	// params:	0 pointer to object's graphic structure
	//			1 pointer to object's mega structure
	//			2 anim resource id

	uint8 *anim_file;
	_animHeader *anim_head;
	int32 pars[5];

	//----------------------------------------------------------------------------------------
	// open the anim file & set up a pointer to the animation header

	anim_file = res_man.Res_open(params[2]);	// open anim file
	anim_head = FetchAnimHeader( anim_file );

	//----------------------------------------------------------------------------------------
	// set up the parameter list for FN_walk_to()

	pars[0] = params[0];
	pars[1] = params[1];

	pars[2] = anim_head->feetStartX;				// x
	pars[3] = anim_head->feetStartY;				// y
	pars[4] = anim_head->feetStartDir;				// dir

	if ((pars[2]==0)&&(pars[3]==0))					// if start coords not available
	{
		pars[2] = standby_x;						// use the standby coords
		pars[3] = standby_y;						// (which should be set beforehand in the script)
		pars[4] = standby_dir;

		Zdebug("WARNING: FN_stand_at_anim(%s) used standby coords", FetchObjectName(params[2]));
	}

	if ((pars[4] < 0) || (pars[4] > 7))				// check for invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_stand_after_anim (%s line %u)", pars[4],__FILE__,__LINE__);

	//-------------------------------------------------------------------------------------------------------
	// close the anim file

	res_man.Res_close(params[2]);		// close anim file

	//-------------------------------------------------------------------------------------------------------

	return FN_stand_at(pars);			// call FN_stand_at() with target coords set to anim end position
}

//--------------------------------------------------------------------------------------
// Code to workout direction from start to dest

#define	diagonalx 36	// used in what_target not valid for all megas	jps 17mar95
#define	diagonaly 8


int What_target(int startX,	int	startY, int	destX, int	destY)		//S2.1(20Jul95JPS)
{
	int tar_dir;
//setting up
	int deltaX = destX-startX;
	int deltaY = destY-startY;
	int signX = (deltaX > 0);
	int signY = (deltaY > 0);
	int	slope;

	if ( (abs(deltaY) * diagonalx ) < (abs(deltaX) * diagonaly / 2))
	{
		slope = 0;// its flat
	}
	else if ( (abs(deltaY) * diagonalx / 2) > (abs(deltaX) * diagonaly ) )
	{
		slope = 2;// its vertical
	}
	else
	{
		slope = 1;// its diagonal
	}

	if (slope == 0) //flat
	{
		if (signX == 1)	// going right
		{
			tar_dir = 2;
		}
		else
		{
			tar_dir = 6;
		}
	}
	else if (slope == 2) //vertical
	{
		if (signY == 1)	// going down
		{
			tar_dir = 4;
		}
		else
		{
			tar_dir = 0;
		}
	}
	else if (signX == 1) //right diagonal
	{
		if (signY == 1)	// going down
		{
			tar_dir = 3;
		}
		else
		{
			tar_dir = 1;
		}
	}
 	else //left diagonal
	{
		if (signY == 1)	// going down
		{
			tar_dir = 5;
		}
		else
		{
			tar_dir = 7;
		}
	}
	return tar_dir;
}

//--------------------------------------------------------------------------------------
// turn mega to face point (x,y) on the floor
// just needs to call FN_walk() with current feet coords & direction computed by What_target()

int32 FN_face_xy(int32 *params)	// James (29nov96)
{
	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target x-coord
	//			5 target y-coord

	Object_logic	*ob_logic;
	Object_mega		*ob_mega;
 	int32			pars[7];

	//----------------------------------------------------------------------------------------
	// if this is the start of the turn, get the mega's current feet coords + the required direction

	ob_logic = (Object_logic *)params[0];

	if (ob_logic->looping==0)
	{
	 	ob_mega = (Object_mega *)params[2];
	
		pars[4] = ob_mega->feet_x;
		pars[5] = ob_mega->feet_y;
		pars[6] = What_target( ob_mega->feet_x, ob_mega->feet_y, params[4], params[5] );	// set target direction
	}

	//----------------------------------------------------------------------------------------
	// set up the rest of the parameters for FN_walk()

	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];

	//----------------------------------------------------------------------------------------

	return FN_walk(pars);	// call FN_walk() with target coords set to feet coords
}
//--------------------------------------------------------------------------------------
int32	FN_face_mega(int32	*params) 	//S2.1(3mar95jps)	Tony29Nov96
{
//params	0 pointer to object's logic structure
//			1 pointer to object's graphic structure
//			2 pointer to object's mega structure
//			3 pointer to object's walkdata structure

//			4 id of target mega to face

	uint32	null_pc=3;	//get ob_mega
	char	*raw_script_ad;
	int32	pars[7];
	Object_logic	*ob_logic;
	Object_mega		*ob_mega;
	_standardHeader	*head;


	ob_mega = (Object_mega *)params[2];
	ob_logic = (Object_logic *)params[0];


	if (ob_logic->looping==0)
	{

//		get targets info
		head = (_standardHeader*) res_man.Res_open(params[4]);
		if	(head->fileType!=GAME_OBJECT)
			Con_fatal_error("FN_face_mega %d not an object", params[4]);

		raw_script_ad = (char *)head;	// (head+1) + sizeof(_object_hub);	//get to raw script data

		RunScript( raw_script_ad, raw_script_ad, &null_pc );	//call the base script - this is the graphic/mouse service call
		res_man.Res_close(params[4]);

//		engine_mega is now the Object_mega of mega we want to turn to face

		pars[3] = params[3];
		pars[4] = ob_mega->feet_x;
		pars[5] = ob_mega->feet_y;
		pars[6] = What_target( ob_mega->feet_x, ob_mega->feet_y, engine_mega.feet_x, engine_mega.feet_y );
	}



	pars[0] = params[0];
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];

	return FN_walk(pars);	// call FN_walk() with target coords set to feet coords

}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//	FN_walk		(here for reference instead of splitting a window)

	// params:	0 pointer to object's logic structure
	//			1 pointer to object's graphic structure
	//			2 pointer to object's mega structure
	//			3 pointer to object's walkdata structure
	//			4 target x-coord
	//			5 target y-coord
	//			6 target direction
//------------------------------------------------------------------------------------
int32	FN_walk_to_talk_to_mega(int32	*params)	//Tony2Dec96
{
//we route to left or right hand side of target id if possible
//target is a shrinking mega

	Object_mega		*ob_mega;
	Object_logic	*ob_logic;

	uint32	null_pc=3;	//4th script - get mega
	char	*raw_script_ad;
	int32	pars[7];
	int	scale;
	int	mega_seperation=params[5];
	_standardHeader	*head;


//params	0 pointer to object's logic structure
//			1 pointer to object's graphic structure
//			2 pointer to object's mega structure
//			3 pointer to object's walkdata structure

//			4 id of target mega to face
//			5 distance


	ob_logic = (Object_logic*) params[0];
	ob_mega = (Object_mega*) params[2];

	pars[0] = params[0];	// standard stuff
	pars[1] = params[1];
	pars[2] = params[2];
	pars[3] = params[3];			// walkdata



	if	(!ob_logic->looping)	//not been here before so decide where to walk-to
	{
//		first request the targets info
		head = (_standardHeader*) res_man.Res_open(params[4]);
		if	(head->fileType!=GAME_OBJECT)
			Con_fatal_error("FN_walk_to_talk_to_mega %d not an object", params[4]);

		raw_script_ad = (char *)head;	// (head+1) + sizeof(_object_hub);	//get to raw script data
		RunScript( raw_script_ad, raw_script_ad, &null_pc );	//call the base script - this is the graphic/mouse service call
		res_man.Res_close(params[4]);

//		engine_mega is now the Object_mega of mega we want to route to


		pars[5] = engine_mega.feet_y;	// stand exactly beside the mega, ie. at same y-coord


//		apply scale factor to walk distance
		scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b)/256;	// Ay+B gives 256*scale ie. 256*256*true_scale for even better accuracy, ie. scale = (Ay+B)/256

		mega_seperation= (mega_seperation*scale)/256;

//		Zdebug("seperation %d", mega_seperation);
//		Zdebug(" target x %d, y %d", engine_mega.feet_x, engine_mega.feet_y);

		if	(engine_mega.feet_x < ob_mega->feet_x)	// target is left of us
		{
			pars[4] = engine_mega.feet_x+mega_seperation;	// so aim to stand to their right
			pars[6] = 5;	// face down_left
		}
		else										// ok, must be right of us
		{
			pars[4] = engine_mega.feet_x-mega_seperation;	// so aim to stand to their left
			pars[6] = 3;	// face down_right
		}
	}

  	//first cycle builds the route - thereafter merely follows it

	return FN_walk(pars);	//call FN_walk() with target coords set to feet coords
							//RESULT will be 1 when it finishes or 0 if it failed to build route
}
//------------------------------------------------------------------------------------
int32 FN_set_walkgrid(int32 *params)	// (6dec96 JEL)
{
	Con_fatal_error("FN_set_walkgrid no longer valid");
	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
// add this walkgrid resource to the list of those used for routing in this location
// - note this is ignored in the resource is already in the list

int32 FN_add_walkgrid(int32 *params)	// (03mar97 JEL)
{
	// params	0 id of walkgrid resource

	// all objects that add walkgrids must be restarted whenever we reneter a location

	if (ID != 8)	// DON'T EVER KILL GEORGE!
		FN_add_to_kill_list(params);// need to call this in case it wasn't called in script! ('params' just used as dummy param)

	AddWalkGrid(params[0]);

	res_man.Res_open(params[0]);	// Touch the grid, getting it into memory.
	res_man.Res_close(params[0]);

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
// remove this walkgrid resource from the list of those used for routing in this location
// - note that this is ignored if the resource isn't actually in the list

int32 FN_remove_walkgrid(int32 *params)	// (03mar97 JEL)
{
	// params	0 id of walkgrid resource

	RemoveWalkGrid(params[0]);

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_register_walkgrid(int32 *params)
{
	Con_fatal_error("FN_register_walkgrid no longer valid");
	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_set_scaling(int32 *params)	// (6dec96 JEL)
{
	// params	0 pointer to object's mega structure
	//				1 scale constant A
	//				2 scale constant B

	// 256*s = A*y + B

	// where s is system scale, which itself is (256 * actual_scale) ie. s==128 is half size

 	Object_mega *ob_mega = (Object_mega *) params[0];

	ob_mega->scale_a = params[1];
	ob_mega->scale_b = params[2];

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------
int32 FN_set_standby_coords(int32 *params)	// (10dec97 JEL)
{
	// set the standby walk coords to be used by FN_walk_to_anim & FN_stand_after_anim
	// when the anim header's start/end coords are zero

	// useful during development; can stay in final game anyway

	// params	0 x-coord
	//			1 y-coord
	//			2 direction (0..7)

	//----------------------------------------------------------------------------------------
	// check for invalid direction

	if ((params[2] < 0) || (params[2] > 7))	// invalid direction
		Con_fatal_error("Invalid direction (%d) in FN_set_standby_coords (%s line %u)",params[2],__FILE__,__LINE__);

	//----------------------------------------------------------------------------------------

	standby_x	= params[0];
	standby_y	= params[1];
	standby_dir	= params[2];

	return(IR_CONT);	//	continue script
}
//---------------------------------------------------------------------------------------------------------------------

--- NEW FILE: walker.h ---
/* Copyright (C) 1994-2003 Revolution Software Ltd
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/bs2/walker.h,v 1.1 2003/07/28 01:44:38 khalek Exp $
 */

#ifndef	_WALKER
#define	_WALKER

//#include "src\driver96.h"



int32 FN_face_mega(int32 *params);
int32 FN_turn(int32 *params);
int32 FN_walk(int32 *params);				// James (14nov96)
int32 FN_walk_to_anim(int32 *params);		// James (14nov96)
int32 FN_stand_after_anim(int32 *params);	// James (18jun97)
int32 FN_stand(int32 *params);				// James

#endif





More information about the Scummvm-git-logs mailing list