[Scummvm-cvs-logs] CVS: scummvm/saga actionmap.cpp,NONE,1.1 actionmap.h,NONE,1.1 actionmap_mod.h,NONE,1.1 actor.cpp,NONE,1.1 actor.h,NONE,1.1 actor_mod.h,NONE,1.1 actordata.cpp,NONE,1.1 actordata.h,NONE,1.1 animation.cpp,NONE,1.1 animation.h,NONE,1.1 animation_mod.h,NONE,1.1 cmdline.cpp,NONE,1.1 console.cpp,NONE,1.1 console.h,NONE,1.1 console_mod.h,NONE,1.1 cvar.cpp,NONE,1.1 cvar.h,NONE,1.1 cvar_mod.h,NONE,1.1 events.cpp,NONE,1.1 events.h,NONE,1.1 events_mod.h,NONE,1.1 expr.cpp,NONE,1.1 expr.h,NONE,1.1 font.cpp,NONE,1.1 font.h,NONE,1.1 font_map.cpp,NONE,1.1 font_mod.h,NONE,1.1 game.cpp,NONE,1.1 game.h,NONE,1.1 game_mod.h,NONE,1.1 gfx.cpp,NONE,1.1 gfx.h,NONE,1.1 gfx_mod.h,NONE,1.1 ihnm_introproc.cpp,NONE,1.1 ihnm_introproc.h,NONE,1.1 image.cpp,NONE,1.1 image.h,NONE,1.1 image_mod.h,NONE,1.1 interface.cpp,NONE,1.1 interface.h,NONE,1.1 interface_mod.h,NONE,1.1 isomap.cpp,NONE,1.1 isomap.h,NONE,1.1 isomap_mod.h,NONE,1.1 ite_introproc.cpp,NONE,1.1 ite_introproc.h,NONE,1.1 ite_introproc_mod.h,NONE,1.1 math.cpp,NONE,1.1 math.h,NONE,1.1 math_mod.h,NONE,1.1 misc.cpp,NONE,1.1 objectmap.cpp,NONE,1.1 objectmap.h,NONE,1.1 objectmap_mod.h,NONE,1.1 palanim.cpp,NONE,1.1 palanim.h,NONE,1.1 palanim_mod.h,NONE,1.1 reinherit.h,NONE,1.1 render.cpp,NONE,1.1 render.h,NONE,1.1 render_mod.h,NONE,1.1 rscfile.cpp,NONE,1.1 rscfile.h,NONE,1.1 rscfile_mod.h,NONE,1.1 scene.cpp,NONE,1.1 scene.h,NONE,1.1 scene_mod.h,NONE,1.1 sceneproc.cpp,NONE,1.1 sceneproc.h,NONE,1.1 script.cpp,NONE,1.1 script.h,NONE,1.1 script_mod.h,NONE,1.1 sdata.cpp,NONE,1.1 sdata.h,NONE,1.1 sdebug.cpp,NONE,1.1 sfuncs.cpp,NONE,1.1 sfuncs.h,NONE,1.1 sndres.cpp,NONE,1.1 sndres.h,NONE,1.1 sndres_mod.h,NONE,1.1 sprite.cpp,NONE,1.1 sprite.h,NONE,1.1 sprite_mod.h,NONE,1.1 sstack.cpp,NONE,1.1 sstack.h,NONE,1.1 stack.cpp,NONE,1.1 stack.h,NONE,1.1 stack_mod.h,NONE,1.1 sthread.cpp,NONE,1.1 sthread.h,NONE,1.1 sys_fs.cpp,NONE,1.1 sys_interface.h,NONE,1.1 sysgfx.cpp,NONE,1.1 sysgfx.h,NONE,1.1 sysinput.cpp,NONE,1.1 sysio.cpp,NONE,1.1 sysmusic.cpp,NONE,1.1 syssound.cpp,NONE,1.1 systimer.cpp,NONE,1.1 systimer.h,NONE,1.1 text.cpp,NONE,1.1 text.h,NONE,1.1 text_mod.h,NONE,1.1 transitions.cpp,NONE,1.1 x86_32.h,NONE,1.1 xmidi.cpp,NONE,1.1 xmidi.h,NONE,1.1 xmidi_mod.h,NONE,1.1 ys_binread.cpp,NONE,1.1 ys_binwrite.cpp,NONE,1.1 ys_dl_list.cpp,NONE,1.1 ys_file.cpp,NONE,1.1 yslib.h,NONE,1.1 gamedesc_priv.h,1.3,1.4 module.mk,1.1,1.2 saga.cpp,1.3,1.4 saga.h,1.3,1.4 binread.cpp,1.4,NONE binread.h,1.2,NONE gamedesc.cpp,1.6,NONE gamedesc.h,1.4,NONE resfile.cpp,1.5,NONE resfile.h,1.3,NONE resnames.h,1.2,NONE

Eugene Sandulenko sev at users.sourceforge.net
Mon Apr 12 14:56:01 CEST 2004


Update of /cvsroot/scummvm/scummvm/saga
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25930

Modified Files:
	gamedesc_priv.h module.mk saga.cpp saga.h 
Added Files:
	actionmap.cpp actionmap.h actionmap_mod.h actor.cpp actor.h 
	actor_mod.h actordata.cpp actordata.h animation.cpp 
	animation.h animation_mod.h cmdline.cpp console.cpp console.h 
	console_mod.h cvar.cpp cvar.h cvar_mod.h events.cpp events.h 
	events_mod.h expr.cpp expr.h font.cpp font.h font_map.cpp 
	font_mod.h game.cpp game.h game_mod.h gfx.cpp gfx.h gfx_mod.h 
	ihnm_introproc.cpp ihnm_introproc.h image.cpp image.h 
	image_mod.h interface.cpp interface.h interface_mod.h 
	isomap.cpp isomap.h isomap_mod.h ite_introproc.cpp 
	ite_introproc.h ite_introproc_mod.h math.cpp math.h math_mod.h 
	misc.cpp objectmap.cpp objectmap.h objectmap_mod.h palanim.cpp 
	palanim.h palanim_mod.h reinherit.h render.cpp render.h 
	render_mod.h rscfile.cpp rscfile.h rscfile_mod.h scene.cpp 
	scene.h scene_mod.h sceneproc.cpp sceneproc.h script.cpp 
	script.h script_mod.h sdata.cpp sdata.h sdebug.cpp sfuncs.cpp 
	sfuncs.h sndres.cpp sndres.h sndres_mod.h sprite.cpp sprite.h 
	sprite_mod.h sstack.cpp sstack.h stack.cpp stack.h stack_mod.h 
	sthread.cpp sthread.h sys_fs.cpp sys_interface.h sysgfx.cpp 
	sysgfx.h sysinput.cpp sysio.cpp sysmusic.cpp syssound.cpp 
	systimer.cpp systimer.h text.cpp text.h text_mod.h 
	transitions.cpp x86_32.h xmidi.cpp xmidi.h xmidi_mod.h 
	ys_binread.cpp ys_binwrite.cpp ys_dl_list.cpp ys_file.cpp 
	yslib.h 
Removed Files:
	binread.cpp binread.h gamedesc.cpp gamedesc.h resfile.cpp 
	resfile.h resnames.h 
Log Message:
WIP for SAGA engine.

 o text formatting is not consistent with rules, just indent utility is too
   dumb for that
 o it does not use OSystem, i.e. it runs on direct SDL calls
 o it may not even compile on your box
 o if you enable it, expect zillions of warnings
 o no sound

Now it runs ITE intro as reinherit did


--- NEW FILE: actionmap.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/actionmap.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Action map module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"


/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "cvar_mod.h"
#include "console_mod.h"
#include "gfx_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "actionmap_mod.h"
#include "actionmap.h"

namespace Saga {

static R_ACTIONMAP_INFO ActmapModule;

int ACTIONMAP_Register(void)
{

	CVAR_RegisterFunc(CF_action_info,
	    "action_info", NULL, R_CVAR_NONE, 0, 0);

	return R_SUCCESS;
}

int ACTIONMAP_Init(void)
{
	R_printf(R_STDOUT, "ACTIONMAP Module: Initializing...\n");

	ActmapModule.init = 1;
	return R_SUCCESS;
}

int ACTIONMAP_Load(const uchar * exmap_res, size_t exmap_res_len)
/*--------------------------------------------------------------------------*\
 * Loads exit map data from specified exit map resource
\*--------------------------------------------------------------------------*/
{

	R_ACTIONMAP_ENTRY *exmap_entry;
	R_POINT *exmap_pt_tbl;

	int exit_ct;
	int i, pt;

	const uchar *read_p = exmap_res;
	size_t read_len = exmap_res_len;

	assert(ActmapModule.init);
	assert(exmap_res != NULL);

	(void)read_len;

	/* Load exits
	 * \*------------------------------------------------------------- */
	exit_ct = ys_read_s16_le(read_p, &read_p);
	if (exit_ct < 0) {
		return R_FAILURE;
	}

	exmap_entry = (R_ACTIONMAP_ENTRY *)malloc(exit_ct * sizeof *exmap_entry);
	if (exmap_entry == NULL) {

		R_printf(R_STDERR, "Memory allocation failure.\n");
		return R_MEM;
	}

	for (i = 0; i < exit_ct; i++) {

		exmap_entry[i].unknown00 = ys_read_s16_le(read_p, &read_p);
		exmap_entry[i].unknown02 = ys_read_s16_le(read_p, &read_p);
		exmap_entry[i].exit_scene = ys_read_s16_le(read_p, &read_p);
		exmap_entry[i].unknown06 = ys_read_s16_le(read_p, &read_p);

		exmap_entry[i].pt_count = ys_read_s16_le(read_p, &read_p);
		if (exmap_entry[i].pt_count < 0) {

			free(exmap_entry);
			return R_FAILURE;
		}

		exmap_pt_tbl =
		    (R_POINT *)malloc(exmap_entry[i].pt_count * sizeof *exmap_pt_tbl);
		if (exmap_pt_tbl == NULL) {

			R_printf(R_STDERR, "Memory allocation failure.\n");
			return R_MEM;
		}

		for (pt = 0; pt < exmap_entry[i].pt_count; pt++) {

			exmap_pt_tbl[pt].x = ys_read_s16_le(read_p, &read_p);
			exmap_pt_tbl[pt].y = ys_read_s16_le(read_p, &read_p);
		}

		exmap_entry[i].pt_tbl = exmap_pt_tbl;
	}

	ActmapModule.exits_loaded = 1;
	ActmapModule.n_exits = exit_ct;
	ActmapModule.exits_tbl = exmap_entry;

	ActmapModule.exmap_res = exmap_res;
	ActmapModule.exmap_res_len = exmap_res_len;

	return R_SUCCESS;
}

int ACTIONMAP_Free(void)
/*--------------------------------------------------------------------------*\
 * Frees the currently loaded exit map data
\*--------------------------------------------------------------------------*/
{

	R_ACTIONMAP_ENTRY *exmap_entry;
	int i;

	if (!ActmapModule.exits_loaded) {
		return R_SUCCESS;
	}

	for (i = 0; i < ActmapModule.n_exits; i++) {

		exmap_entry = &ActmapModule.exits_tbl[i];

		free(exmap_entry->pt_tbl);
	}

	free(ActmapModule.exits_tbl);

	ActmapModule.exits_loaded = 0;
	ActmapModule.exits_tbl = NULL;
	ActmapModule.n_exits = 0;

	return R_SUCCESS;
}

int ACTIONMAP_Shutdown(void)
/*--------------------------------------------------------------------------*\
\*--------------------------------------------------------------------------*/
{

	return R_SUCCESS;
}

int ACTIONMAP_Draw(R_SURFACE * ds, int color)
{

	int i;

	assert(ActmapModule.init);

	if (!ActmapModule.exits_loaded) {
		return R_FAILURE;
	}

	for (i = 0; i < ActmapModule.n_exits; i++) {

		if (ActmapModule.exits_tbl[i].pt_count == 2) {

			GFX_DrawFrame(ds,
			    &ActmapModule.exits_tbl[i].pt_tbl[0],
			    &ActmapModule.exits_tbl[i].pt_tbl[1], color);

		} else if (ActmapModule.exits_tbl[i].pt_count > 2) {

			GFX_DrawPolyLine(ds,
			    ActmapModule.exits_tbl[i].pt_tbl,
			    ActmapModule.exits_tbl[i].pt_count, color);

		}
	}

	return R_SUCCESS;
}

void CF_action_info(int argc, char *argv[])
{
	R_POINT *pt;

	int i;
	int pt_i;

	YS_IGNORE_PARAM(argc);
	YS_IGNORE_PARAM(argv);

	if (!ActmapModule.exits_loaded) {
		return;
	}

	CON_Print("%d exits loaded.\n", ActmapModule.n_exits);

	for (i = 0; i < ActmapModule.n_exits; i++) {

		CON_Print
		    ("Action %d: Exit to: %d; Pts: %d; Unk0: %d Unk2: %d Scr_N: %d",
		    i, ActmapModule.exits_tbl[i].exit_scene,
		    ActmapModule.exits_tbl[i].pt_count,
		    ActmapModule.exits_tbl[i].unknown00,
		    ActmapModule.exits_tbl[i].unknown02,
		    ActmapModule.exits_tbl[i].unknown06);

		for (pt_i = 0; pt_i < ActmapModule.exits_tbl[i].pt_count;
		    pt_i++) {

			pt = &ActmapModule.exits_tbl[i].pt_tbl[pt_i];

			CON_Print("   pt: %d (%d, %d)", pt_i, pt->x, pt->y);
		}
	}

	return;
}

} // End of namespace Saga

--- NEW FILE: actionmap.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/actionmap.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Action map module - private header

 Notes: 
*/

#ifndef SAGA_ACTIONMAP_H_
#define SAGA_ACTIONMAP_H_

namespace Saga {

typedef struct R_ACTIONMAP_ENTRY_tag {

	int unknown00;
	int unknown02;
	int exit_scene;
	int unknown06;

	int pt_count;
	R_POINT *pt_tbl;

} R_ACTIONMAP_ENTRY;

typedef struct R_ACTIONMAP_INFO_tag {

	int init;

	int exits_loaded;
	int n_exits;
	R_ACTIONMAP_ENTRY *exits_tbl;

	const uchar *exmap_res;
	size_t exmap_res_len;

} R_ACTIONMAP_INFO;

void CF_action_info(int argc, char *argv[]);

} // End of namespace Saga

#endif				/* R_ACTIONMAP_H_ */
/* end "r_actionmap.h" */

--- NEW FILE: actionmap_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/actionmap_mod.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Action map module - public module header

 Notes: 
*/

#ifndef SAGA_ACTIONMAP_MOD_H_
#define SAGA_ACTIONMAP_MOD_H_

namespace Saga {

int ACTIONMAP_Register(void);
int ACTIONMAP_Init(void);

int ACTIONMAP_Load(const uchar * exmap_res, size_t exmap_res_len);
int ACTIONMAP_Draw(R_SURFACE * ds, int color);

int ACTIONMAP_Free(void);
int ACTIONMAP_Shutdown(void);

} // End of namespace Saga

#endif				/* R_ACTIONMAP_MOD_H_ */
/* end "r_actionmap_mod.h" */

--- NEW FILE: actor.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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.
 *
[...1417 lines suppressed...]
	}

	if ((action_n < 0) || (action_n >= actor->action_ct)) {
		CON_Print("Invalid action number.");

		return;
	}

	CON_Print("Action frame counts: %d %d %d %d.",
	    actor->act_tbl[action_n].dir[0].frame_count,
	    actor->act_tbl[action_n].dir[1].frame_count,
	    actor->act_tbl[action_n].dir[2].frame_count,
	    actor->act_tbl[action_n].dir[3].frame_count);

	ACTOR_SetAction(index, action_n, ACTION_LOOP);

	return;
}

} // End of namespace Saga

--- NEW FILE: actor.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/actor.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Actor management module header file

 Notes: 
 
	Hardcoded actor table present in r_actordata.c
*/

#ifndef SAGA_ACTOR_H__
#define SAGA_ACTOR_H__

namespace Saga {

#define ACTOR_BASE_SPEED 0.25
#define ACTOR_BASE_ZMOD 0.5

#define ACTOR_DEFAULT_ORIENT 2
#define ACTOR_ORIENTMAX 7

#define ACTOR_ACTIONTIME 80

#define ACTOR_DIALOGUE_LETTERTIME 50
#define ACTOR_DIALOGUE_HEIGHT 100

#define R_ACTOR_LMULT 4

enum R_ACTOR_INTENTS {

	INTENT_NONE = 0,
	INTENT_PATH = 1,
	INTENT_SPEAK = 2
};

typedef struct R_ACTORACTIONITEM_tag {

	int frame_index;
	int frame_count;

} R_ACTORACTIONITEM;

typedef struct R_ACTORACTION_tag {

	R_ACTORACTIONITEM dir[4];

} R_ACTORACTION;

typedef struct R_WALKINTENT_tag {

	int wi_active;
	uint wi_flags;
	int wi_init;

	int time;
	float slope;
	int x_dir;
	R_POINT org;
	R_POINT cur;

	R_POINT dst_pt;
	YS_DL_LIST *nodelist;

	int sem_held;
	R_SEMAPHORE *sem;

} R_WALKINTENT;

typedef struct R_WALKNODE_tag {

	int calc_flag;
	R_POINT node_pt;

} R_WALKNODE;

typedef struct R_SPEAKINTENT_tag {

	int si_init;
	uint si_flags;
	int si_last_action;

	YS_DL_LIST *si_diaglist;	/* Actor dialogue list */

} R_SPEAKINTENT;

typedef struct R_ACTORINTENT_tag {

	int a_itype;
	uint a_iflags;
	int a_idone;

	void *a_data;

} R_ACTORINTENT;

typedef struct R_ACTOR_tag {

	int id;			/* Actor id */
	int name_i;		/* Actor's index in actor name string list */
	uint flags;

	R_POINT a_pt;		/* Actor's logical coordinates */
	R_POINT s_pt;		/* Actor's screen coordinates */

	int sl_rn;		/* Actor's sprite list res # */
	int si_rn;		/* Actor's sprite index res # */
	R_SPRITELIST *sl_p;	/* Actor's sprite list data */

	int idle_time;
	int orient;
	int speaking;

	int a_dcolor;		/* Actor dialogue color */

	/* The actor intent list describes what the actor intends to do;
	 * multiple intents can be queued. The actor must complete an 
	 * intent before moving on to the next; thus actor movements, esp
	 * as described from scripts, can be serialized */

	YS_DL_LIST *a_intentlist;
/*	
    R_WALKPATH path;
*/

	int def_action;
	uint def_action_flags;

	int action;
	uint action_flags;

	int action_frame;
	int action_time;

	R_ACTORACTION *act_tbl;	/* Action lookup table */
	int action_ct;		/* Number of actions in the action LUT */

	YS_DL_NODE *node;	/* Actor's node in the actor list */

} R_ACTOR;

typedef struct R_ACTORDIALOGUE_tag {

	int d_playing;
	char *d_string;
	uint d_voice_rn;

	long d_time;
	int d_sem_held;
	R_SEMAPHORE *d_sem;

} R_ACTORDIALOGUE;

typedef struct R_ACTIONTIMES_tag {

	int action;
	int time;

} R_ACTIONTIMES;

typedef struct R_ACTOR_MODULE_tag {

	int init;

	R_RSCFILE_CONTEXT *actor_ctxt;

	uint count;

	int *alias_tbl;
	YS_DL_NODE **tbl;
	YS_DL_LIST *list;

	int err_n;
	const char *err_str;

} R_ACTOR_MODULE;

R_ACTOR *LookupActor(int index);

int AddActor(R_ACTOR * actor);

int Z_Compare(const void *elem1, const void *elem2);

int
HandleWalkIntent(R_ACTOR * actor,
    R_WALKINTENT * a_walk_int, int *complete_p, int msec);

int
HandleSpeakIntent(R_ACTOR * actor,
    R_SPEAKINTENT * a_speakint, int *complete_p, int msec);

int
ACTOR_SetPathNode(R_WALKINTENT * walk_int,
    R_POINT * src_pt, R_POINT * dst_pt, R_SEMAPHORE * sem);

int LoadActorSpriteIndex(R_ACTOR * actor, int si_rn, int *last_frame_p);

static void CF_actor_add(int argc, char *argv[]);

static void CF_actor_del(int argc, char *argv[]);

static void CF_actor_move(int argc, char *argv[]);

static void CF_actor_moverel(int argc, char *argv[]);

static void CF_actor_seto(int argc, char *argv[]);

static void CF_actor_setact(int argc, char *argv[]);

} // End of namespace Saga

#endif				/* R_ACTOR_H__ */
/* end "r_actor.h" */

--- NEW FILE: actor_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/actor_mod.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Actor management module public header file

 Notes: 
*/

#ifndef SAGA_ACTOR_MOD_H
#define SAGA_ACTOR_MOD_H

namespace Saga {

enum R_ACTOR_WALKFLAGS {

	WALK_NONE = 0x00,
	WALK_NOREORIENT = 0x01
};

enum R_ACTOR_ORIENTATIONS {

	ORIENT_N = 0,
	ORIENT_NE = 1,
	ORIENT_E = 2,
	ORIENT_SE = 3,
	ORIENT_S = 4,
	ORIENT_SW = 5,
	ORIENT_W = 6,
	ORIENT_NW = 7
};

enum R_ACTOR_ACTIONS {

	ACTION_IDLE = 0,
	ACTION_WALK = 1,
	ACTION_SPEAK = 2,
	ACTION_COUNT
};

enum R_ACTOR_ACTIONFLAGS {

	ACTION_NONE = 0x00,
	ACTION_LOOP = 0x01
};

int ACTOR_Register(void);
int ACTOR_Init(void);
int ACTOR_Shutdown(void);

int ACTOR_Direct(int msec);

int ACTOR_Create(int actor_id, int x, int y);
int ACTOR_ActorExists(uint actor_id);

int ACTOR_DrawList(void);
int ACTOR_AtoS(R_POINT * logical, const R_POINT * actor);
int ACTOR_StoA(R_POINT * actor, const R_POINT * screen);

int ACTOR_Move(int index, R_POINT * move_pt);
int ACTOR_MoveRelative(int index, R_POINT * move_pt);

int ACTOR_WalkTo(int index, R_POINT * walk_pt, uint flags, R_SEMAPHORE * sem);

int ACTOR_GetActorIndex(uint actor_id);

int ACTOR_Speak(int index, char *d_string, uint d_voice_rn, R_SEMAPHORE * sem);

int ACTOR_SkipDialogue(void);

int ACTOR_GetSpeechTime(const char *d_string, uint d_voice_rn);
int ACTOR_SetOrientation(int index, int orient);
int ACTOR_SetAction(int index, int action_n, uint action_flags);
int ACTOR_SetDefaultAction(int index, int action_n, uint action_flags);

} // End of namespace Saga

#endif				/* R_ACTOR_MOD_H */
/* end "r_actor_mod.h" */

--- NEW FILE: actordata.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/actordata.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Actor data table

 Notes: 
*/

#include "actordata.h"

namespace Saga {

/* Lookup table to convert 8 cardinal directions to 4 */
int ActorOrientationLUT[] = { 2, 0, 0, 0, 3, 1, 1, 1 };

R_ACTORTABLE ActorTable[R_ACTORCOUNT] = {

/*   namei                         sl_rn si_rn        col
     -----                         ----- -----        ---              */
	{0, 1, 0, 0, 0, 37, 135, 0, 1, 0, 0, 0},
	/* original okk entry
	 * { 1,    0,    0,    0,    0,    0,    0,    1,    132, 0,   0,   0 }, */
	{1, 0, 0, 0, 0, 45, 144, 1, 132, 0, 0, 0},
	{2, 0, 0, 0, 0, 48, 143, 2, 161, 0, 0, 0},
	{3, 0, 240, 480, 0, 115, 206, 0, 25, 0, 0, 0},
	{4, 17, 368, 400, 0, 115, 206, 4, 49, 0, 0, 0},
	{5, 11, 552, 412, 0, 54, 152, 1, 171, 0, 0, 0},
	{17, 2, 1192, 888, 0, 57, 153, 17, 49, 0, 0, 0},
	{17, 2, 816, 1052, 0, 57, 153, 18, 49, 0, 0, 0},
	{17, 2, 928, 932, 0, 58, 153, 19, 49, 0, 0, 0},
	{17, 2, 1416, 1160, 0, 58, 153, 20, 49, 0, 0, 0},
	{19, 49, 1592, 1336, 0, 92, 175, 15, 162, 0, 0, 0},
	{20, 49, 744, 824, 0, 63, 156, 19, 112, 0, 4, 4},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{9, 49, 1560, 1624, 0, 94, 147, 18, 132, 0, 4, 4},
	{56, 49, 1384, 792, 0, 95, 193, 20, 72, 0, 0, 0},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{19, 0, 1592, 1336, 0, 92, 175, 0, 171, 0, 0, 0},
	{18, 32, 764, 448, 0, 55, 150, 0, 48, 10, 4, 4},
	{35, 32, 0, 0, 0, 56, 151, 0, 112, 0, 0, 0},
	{36, 32, 0, 0, 0, 105, 142, 0, 155, 0, 0, 0},
	{32, 32, 0, 0, 0, 91, 190, 0, 98, 0, 0, 0},
	{31, 32, 0, 0, 0, 90, 189, 0, 171, 0, 0, 0},
	{31, 32, 0, 0, 0, 90, 189, 0, 171, 0, 0, 0},
	{31, 32, 0, 0, 0, 90, 189, 0, 171, 0, 0, 0},
	{31, 32, 0, 0, 0, 79, 172, 0, 18, 0, 0, 0},
	{21, 50, 664, 400, 0, 76, 171, 2, 74, 0, 4, 4},
	{21, 50, 892, 428, 0, 76, 171, 2, 74, 0, 4, 4},
	{9, 51, 904, 936, 0, 51, 145, 35, 5, 0, 0, 0},
	{9, 51, 872, 840, 0, 51, 145, 36, 5, 0, 0, 0},
	{9, 51, 1432, 344, 0, 51, 145, 37, 5, 0, 0, 0},
	{9, 51, 664, 472, 0, 51, 145, 38, 5, 0, 0, 0},
	{10, 51, 1368, 1464, 0, 80, 146, 39, 147, 0, 0, 0},
	{10, 51, 1416, 1624, 0, 80, 146, 40, 147, 0, 0, 0},
	{10, 51, 1752, 120, 0, 80, 146, 41, 147, 0, 0, 0},
	{10, 51, 984, 408, 0, 80, 146, 42, 147, 0, 0, 0},
	{14, 52, 856, 376, 0, 82, 174, 8, 73, 0, 0, 0},
	{14, 52, 808, 664, 0, 82, 174, 9, 73, 0, 0, 0},
	{14, 52, 440, 568, 0, 82, 174, 10, 73, 0, 0, 0},
	{14, 52, 392, 776, 0, 82, 174, 11, 73, 0, 0, 0},
	{21, 4, 240, 384, 0, 79, 172, 0, 18, 0, 2, 2},
	{23, 4, 636, 268, 0, 77, 173, 0, 74, 0, 4, 4},
	{22, 4, 900, 320, 0, 78, 179, 0, 60, 0, 4, 4},
	{14, 4, 788, 264, 0, 75, 170, 0, 171, 0, 2, 2},
	{14, 4, 1088, 264, 0, 75, 170, 0, 171, 0, 6, 6},
	{24, 19, 728, 396, 0, 65, 181, 47, 146, 0, 6, 6},
	{24, 21, -20, -20, 0, 66, 182, 0, 146, 0, 4, 4},
	{25, 19, 372, 464, 0, 67, 183, 73, 146, 0, 2, 2},
	{26, 5, 564, 476, 27, 53, 149, 1, 5, 0, 4, 4},
	{27, 31, 868, 344, 0, 81, 180, 0, 171, 0, 4, 4},
	{28, 73, 568, 380, 0, 83, 176, 30, 120, 0, 4, 4},
	{14, 7, 808, 480, 0, 82, 174, 9, 73, 0, 0, 0},
	{29, 10, 508, 432, 0, 84, 186, 6, 112, 0, 4, 4},
	{33, 10, 676, 420, 0, 86, 184, 6, 171, 0, 4, 4},
	{30, 10, 388, 452, 0, 88, 185, 6, 171, 0, 4, 4},
	{30, 10, 608, 444, 0, 89, 185, 6, 171, 0, 4, 4},
	{31, 10, 192, 468, 0, 90, 189, 6, 171, 0, 4, 4},
	{31, 10, 772, 432, 0, 90, 189, 6, 171, 0, 4, 4},
	{14, 10, 1340, 444, 0, 87, 188, 6, 171, 0, 4, 4},
	{20, 18, 808, 360, 7, 60, 154, 64, 88, 0, 4, 4},
	{34, 49, 1128, 1256, 0, 96, 191, 16, 35, 0, 4, 4},
	{34, 49, 1384, 792, 0, 93, 192, 17, 66, 0, 4, 4},
	{24, 21, 0, -40, 0, 65, 181, 50, 146, 0, 6, 6},
	{3, 21, 0, -40, 0, 64, 158, 49, 112, 0, 0, 0},
	{17, 21, 0, -40, 0, 62, 157, 74, 48, 0, 0, 0},
	{17, 21, 0, -40, 0, 62, 157, 74, 49, 0, 0, 0},
	{17, 21, 0, -40, 0, 62, 157, 74, 50, 0, 0, 0},
	{12, 244, 1056, 504, 0, 107, 167, 21, 124, 0, 6, 6},
	{8, 33, 248, 440, 0, 68, 169, 14, 112, 0, 0, 0},
	{11, 23, 308, 424, 0, 106, 166, 6, 48, 0, 2, 2},
	{17, 2, 1864, 1336, 0, 58, 153, 21, 49, 0, 0, 0},
	{17, 2, 760, 216, 0, 58, 153, 22, 49, 0, 0, 0},
	{44, 29, 0, 0, 0, 72, 159, 0, 112, 0, 0, 0},
	{45, 29, 0, 0, 0, 71, 163, 0, 146, 0, 6, 6},
	{45, 29, 0, 0, 0, 71, 163, 0, 124, 0, 2, 2},
	{45, 29, 0, 0, 0, 71, 163, 0, 169, 0, 0, 0},
	{7, 29, 0, 0, 0, 69, 164, 0, 4, 0, 0, 0},
	{7, 29, 0, 0, 0, 70, 165, 0, 4, 0, 0, 0},
	{7, 257, 552, 408, 0, 70, 165, 0, 4, 0, 2, 2},
	{7, 29, 0, 0, 0, 70, 165, 0, 4, 0, 0, 0},
	{7, 29, 0, 0, 0, 70, 165, 0, 4, 0, 0, 0},
	{7, 257, 712, 380, 0, 69, 164, 0, 4, 0, 4, 4},
	{7, 29, 0, 0, 0, 69, 164, 0, 4, 0, 0, 0},
	{7, 29, 0, 0, 0, 69, 164, 0, 4, 0, 0, 0},
	{7, 29, 0, 0, 0, 69, 164, 0, 4, 0, 0, 0},
	{7, 29, 0, 0, 0, 69, 164, 0, 4, 0, 0, 0},
	{7, 0, 0, 0, 0, 69, 164, 0, 4, 0, 0, 0},
	{7, 29, 0, 0, 0, 70, 165, 0, 4, 0, 0, 0},
	{47, 30, 0, 0, 0, 102, 199, 1, 186, 0, 0, 0},
	{48, 69, 0, 0, 0, 109, 202, 35, 26, 0, 0, 0},
	{49, 69, 0, 0, 0, 109, 202, 35, 26, 0, 0, 0},
	{50, 69, 0, 0, 0, 111, 203, 16, 67, 0, 0, 0},
	{51, 20, 0, 0, 0, 112, 204, 15, 26, 0, 0, 0},
	{50, 20, 0, 0, 0, 111, 203, 14, 67, 0, 0, 0},
	{49, 20, 0, 0, 0, 109, 202, 35, 26, 0, 0, 0},
	{48, 256, 0, 0, 0, 109, 202, 35, 26, 0, 0, 0},
	{21, 32, 0, 0, 0, 76, 171, 0, 171, 0, 0, 0},
	{21, 32, 0, 0, 0, 76, 171, 0, 171, 0, 0, 0},
	{21, 32, 0, 0, 0, 76, 171, 0, 171, 0, 0, 0},
	{52, 15, 152, 400, 0, 108, 168, 19, 48, 10, 2, 2},
	{47, 251, 640, 360, 0, 113, 205, 5, 186, 10, 2, 2},
	{41, 75, 152, 400, 0, 100, 197, 5, 81, 0, 0, 0},
	{44, 9, 0, 0, 0, 73, 160, 54, 112, 0, 0, 0},
	{0, 22, -20, -20, 0, 118, 209, 0, 171, 0, 0, 0},
	{1, 22, 0, 0, 0, 119, 210, 0, 171, 0, 0, 0},
	{0, 22, -20, -20, 0, 118, 209, 0, 171, 0, 0, 0},
	{1, 22, 0, 0, 0, 119, 210, 0, 171, 0, 0, 0},
	{53, 42, 640, 400, 0, 104, 201, 8, 141, 0, 0, 0},
	{54, 21, -20, -20, 0, 120, 211, 48, 238, 0, 0, 0},
	{0, 4, -20, -20, 0, 42, 140, 0, 1, 0, 0, 0},
	{26, 5, -20, -20, 27, 52, 148, 1, 5, 0, 4, 4},
	{36, 4, -20, -20, 0, 116, 207, 0, 155, 0, 0, 0},
	{36, 0, -20, -20, 0, 117, 208, 0, 155, 0, 0, 0},
	{46, 252, -20, -20, 0, 74, 162, 29, 34, 0, 0, 0},
	{0, 32, -20, -20, 0, 41, 137, 0, 1, 0, 0, 0},
	{0, 259, -20, -20, 0, 44, 138, 0, 1, 0, 0, 0},
	{0, 5, -20, -20, 0, 43, 139, 0, 1, 0, 0, 0},
	{0, 31, -20, -20, 0, 39, 136, 0, 1, 0, 0, 0},
	{0, 252, -20, -20, 0, 39, 136, 0, 1, 0, 0, 0},
	{0, 15, -20, -20, 0, 39, 136, 0, 1, 0, 0, 0},
	{0, 20, -20, -20, 0, 39, 136, 0, 1, 0, 0, 0},
	{0, 25, -20, -20, 0, 39, 136, 0, 1, 0, 0, 0},
	{0, 272, -20, -20, 0, 40, 141, 0, 1, 0, 0, 0},
	{0, 50, -20, -20, 0, 39, 136, 0, 1, 0, 0, 0},
	{50, 71, -20, -20, 0, 111, 203, 0, 67, 0, 0, 0},
	{50, 274, -20, -20, 0, 111, 203, 0, 67, 0, 0, 0},
	{50, 274, -20, -20, 0, 110, 212, 0, 171, 0, 0, 0},
	{50, 274, -20, -20, 0, 110, 212, 0, 171, 0, 0, 0},
	{50, 274, -20, -20, 0, 110, 212, 0, 171, 0, 0, 0},
	{57, 272, 909, 909, 48, 121, 213, 0, 171, 0, 0, 0},
	{58, 15, -20, -20, 0, 122, 214, 0, 171, 0, 0, 0},
	{37, 246, -20, -20, 0, 97, 194, 0, 141, 0, 0, 0},
	{38, 246, -20, -20, 0, 98, 195, 0, 27, 0, 0, 0},
	{59, 246, -20, -20, 0, 103, 200, 0, 26, 0, 0, 0},
	{41, 245, -20, -20, 0, 100, 197, 0, 81, 0, 0, 0},
	{47, 250, 640, 360, 0, 114, 205, 0, 186, 10, 2, 2},
	{0, 278, -20, -20, 0, 40, 141, 0, 1, 0, 0, 0},
	{0, 272, -20, -20, 0, 40, 141, 0, 1, 0, 0, 0},
	{41, 77, -20, -20, 0, 100, 197, 24, 81, 0, 0, 0},
	{37, 261, -20, -20, 0, 97, 194, 0, 141, 0, 0, 0},
	{38, 261, -20, -20, 0, 98, 195, 0, 27, 0, 0, 0},
	{39, 261, -20, -20, 0, 99, 196, 0, 5, 0, 0, 0},
	{39, 261, -20, -20, 0, 99, 196, 0, 5, 0, 0, 0},
	{39, 261, -20, -20, 0, 99, 196, 0, 5, 0, 0, 0},
	{39, 261, -20, -20, 0, 99, 196, 0, 5, 0, 0, 0},
	{59, 279, -20, -20, 0, 103, 200, 0, 26, 0, 0, 0},
	{38, 279, -20, -20, 0, 98, 195, 0, 27, 0, 0, 0},
	{42, 77, -20, -20, 0, 101, 198, 25, 171, 0, 0, 0},
	{59, 281, -20, -20, 0, 103, 200, 26, 26, 0, 0, 0},
	{59, 279, -20, -20, 0, 123, 215, 0, 1, 0, 0, 0},
	{59, 279, -20, -20, 0, 123, 215, 0, 132, 0, 0, 0},
	{59, 279, -20, -20, 0, 123, 215, 0, 161, 0, 0, 0},
	{54, 279, -20, -20, 0, 120, 211, 0, 133, 0, 6, 6},
	{44, 9, -20, -20, 0, 124, 161, 0, 171, 0, 6, 6},
	{7, 255, 588, 252, 0, 70, 165, 0, 3, 0, 2, 2},
	{7, 255, 696, 252, 0, 70, 165, 0, 5, 0, 6, 6},
	{36, 4, 0, 0, 0, 105, 142, 0, 155, 0, 0, 0},
	{44, 272, 1124, 1124, 120, 72, 159, 0, 112, 0, 0, 0},
	{7, 272, 1124, 1108, 120, 70, 165, 0, 4, 0, 0, 0},
	{7, 272, 1108, 1124, 120, 70, 165, 0, 4, 0, 0, 0},
	{29, 288, 508, 432, 0, 85, 187, 0, 112, 0, 4, 4},
	{29, 0, 508, 432, 0, 84, 186, 0, 99, 0, 4, 4},
	{29, 0, 508, 432, 0, 84, 186, 0, 98, 0, 4, 4},
	{29, 0, 508, 432, 0, 84, 186, 0, 104, 0, 4, 4},
	{29, 0, 508, 432, 0, 84, 186, 0, 99, 0, 4, 4},
	{36, 288, 0, 0, 0, 105, 142, 0, 155, 0, 0, 0},
	{1, 27, -20, -20, 0, 47, 178, 0, 132, 0, 0, 0},
	{1, 252, -20, -20, 0, 47, 178, 0, 132, 0, 0, 0},
	{1, 25, -20, -20, 0, 47, 178, 0, 132, 0, 0, 0},
	{1, 259, -20, -20, 0, 47, 178, 0, 132, 0, 0, 0},
	{1, 279, -20, -20, 0, 47, 178, 0, 132, 0, 0, 0},
	{1, 273, -20, -20, 0, 47, 178, 0, 132, 0, 0, 0},
	{1, 26, -20, -20, 0, 8, 178, 0, 171, 0, 0, 0},
	{1, 0, -20, -20, 0, 0, 0, 0, 50, 0, 0, 0},
	{1, 0, -20, -20, 0, 0, 0, 0, 82, 0, 0, 0},
	{1, 0, -20, -20, 0, 0, 0, 0, 35, 0, 0, 0},
	{9, 74, -20, -20, 0, 51, 145, 0, 5, 0, 0, 0}
};

} // End of namespace Saga

--- NEW FILE: actordata.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/actordata.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Actor data table header file

 Notes: 
*/

#ifndef SAGA_ACTORDATA_H
#define SAGA_ACTORDATA_H

namespace Saga {

typedef struct R_ACTORTABLE_tag {

	int name_index;
	int unknown1;
	int unknown2;
	int unknown3;
	int unknown4;
	int spritelist_rn;
	int spriteindex_rn;
	int unknown5;
	unsigned char color;
	unsigned char unknown6;
	unsigned char unknown7;
	unsigned char unknown8;

} R_ACTORTABLE;

#define R_ACTORCOUNT 181

extern int ActorOrientationLUT[];
extern R_ACTORTABLE ActorTable[R_ACTORCOUNT];

} // End of namespace Saga

#endif				/* R_ACTORDATA_H */

/* end "r_actordata.h" */

--- NEW FILE: animation.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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.
 *
[...1153 lines suppressed...]
	anim_ct = AnimInfo.anim_count;

	CON_Print("There are %d animations loaded:", anim_ct);

	for (idx = 0, i = 0; i < anim_ct; idx++, i++) {

		while (AnimInfo.anim_tbl[idx] == NULL) {
			idx++;
		}

		CON_Print("%02d: Frames: %u Flags: %u",
		    i,
		    AnimInfo.anim_tbl[idx]->n_frames,
		    AnimInfo.anim_tbl[idx]->flags);
	}

	return;
}

} // End of namespace Saga

--- NEW FILE: animation.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/animation.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:   
 
    Background animation management module private header

 Notes: 
*/

#ifndef SAGA_ANIMATION_H_
#define SAGA_ANIMATION_H_

namespace Saga {

#define R_MAX_ANIMATIONS 7
#define R_DEFAULT_FRAME_TIME 140

#define SAGA_FRAME_HEADER_MAGIC 15
#define SAGA_FRAME_HEADER_LEN 12

/* All animation resources begin with an ANIMATION_HEADER
 * at 0x00, followed by a RLE code stream
\*--------------------------------------------------------------------------*/

typedef struct R_ANIMATION_HEADER_tag {

	uint magic;

	uint screen_w;
	uint screen_h;

	uint unknown06;
	uint unknown07;

	uint nframes;
	uint flags;

	uint unknown10;
	uint unknown11;

} R_ANIMATION_HEADER;

/* A byte from the code stream of FRAME_HEADER_MAGIC signifies that a
 * FRAME_HEADER structure follows
\*--------------------------------------------------------------------------*/

typedef struct R_FRAME_HEADER_tag {

	int x_start;
	int y_start;

	int x_pos;
	int y_pos;

	int width;
	int height;

} R_FRAME_HEADER;

/* Animation info array member */
typedef struct R_ANIMATION_tag {

	const uchar *resdata;
	size_t resdata_len;

	uint n_frames;
	size_t *frame_offsets;

	uint current_frame;
	uint end_frame;
	uint stop_frame;

	const uchar *cur_frame_p;
	size_t cur_frame_len;

	int frame_time;

	uint play_flag;
	int link_flag;
	uint link_id;

	uint flags;

} R_ANIMATION;

typedef struct R_ANIMINFO_tag {

	int initialized;

	uint anim_count;
	uint anim_limit;

	R_ANIMATION *anim_tbl[R_MAX_ANIMATIONS];

} R_ANIMINFO;

int ANIM_GetNumFrames(const uchar * anim_resource, uint * n_frames);

int
ITE_DecodeFrame(const uchar * anim_resource,
    size_t frame_offset, uchar * buf, size_t buf_len);

int
IHNM_DecodeFrame(uchar * decode_buf,
    size_t decode_buf_len,
    const uchar * thisf_p,
    size_t thisf_len, const uchar ** nextf_p, size_t * nextf_len);

int
ANIM_GetFrameOffset(const uchar * anim_resource,
    uint find_frame, size_t * frame_offset);

static void CF_anim_info(int argc, char *argv[]);

} // End of namespace Saga

#endif				/* R_ANIMATION_H_ */
/* end "r_animation.h" */

--- NEW FILE: animation_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/animation_mod.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Background animation management module public header

 Notes: 
*/

#ifndef SAGA_ANIMATION_MOD_H__
#define SAGA_ANIMATION_MOD_H__

namespace Saga {

enum ANIM_FLAGS {

	ANIM_LOOP = 0x01,
	ANIM_ENDSCENE = 0x80	/* When animation ends, dispatch scene end event */
};

int ANIM_Register(void);

int ANIM_Init(void);

int ANIM_Shutdown(void);

int
ANIM_Load(const uchar * anim_resdata,
    size_t anim_resdata_len, uint * anim_id_p);

int ANIM_Free(uint anim_id);

int ANIM_Play(uint anim_id, int vector_time);

int ANIM_Link(uint anim_id1, uint anim_id2);

int ANIM_SetFlag(uint anim_id, uint flag);

int ANIM_SetFrameTime(uint anim_id, int time);

int ANIM_Reset(void);

} // End of namespace Saga

#endif				/* R_ANIMATION_MOD_H__ */
/* end "r_animation_mod.h__ */

--- NEW FILE: cmdline.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/cmdline.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Command line parser

 Notes: 

*/

#include "reinherit.h"

namespace Saga {

int R_ReadCommandLine(int argc, char **argv, R_EXECINFO * execinfo)
{

	int arg;
	int intparam;

	for (arg = 1; arg < argc; arg++) {

		if (strcmp(argv[arg], "-scene") == 0) {
			arg++;
			if (arg <= argc) {
				intparam = atoi(argv[arg]);
				execinfo->start_scene = intparam;
				if (intparam == 0) {
					R_printf(R_STDERR,
					    "Error: Invalid parameter to '-scene'.\n");
					return -1;
				}
			} else {
				R_printf(R_STDERR,
				    "Error: '-scene' requires a parameter.\n");
				return -1;
			}
		}

		if (strcmp(argv[arg], "-gamedir") == 0) {
			arg++;
			if (arg <= argc) {

				execinfo->game_dir = argv[arg];
			} else {
				R_printf(R_STDERR,
				    "Error: '-gamedir' requires a parameter.\n");
				return -1;
			}
		}

		if (strcmp(argv[arg], "-noverify") == 0) {
			execinfo->no_verify = 1;
		}

		if (strcmp(argv[arg], "-nosound") == 0) {
			execinfo->no_sound = 1;
		}

		if (strcmp(argv[arg], "-nomusic") == 0) {
			execinfo->no_music = 1;
		}

		if (strcmp(argv[arg], "-windowed") == 0) {
			execinfo->windowed = 1;
		}

	}

	return 0;

}

} // End of namespace Saga

--- NEW FILE: console.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/console.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:   
 
    Console module

 Notes: 
*/

#include "reinherit.h"

/*
   Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "font_mod.h"
#include "cvar_mod.h"
#include "events_mod.h"
#include "gfx_mod.h"

/*
   Begin module
\*--------------------------------------------------------------------------*/
#include "console_mod.h"
#include "console.h"

namespace Saga {

static R_CONSOLEINFO ConInfo = {

	0,
	R_CON_DEFAULTPOS,
	R_CON_DEFAULTLINES,
	R_CON_DEFAULTCMDS
};

static char InputBuf[R_CON_INPUTBUF_LEN];

static R_CON_SCROLLBACK ConScrollback;
static R_CON_SCROLLBACK ConHistory;

static int CV_ConResize = R_CON_DEFAULTPOS;
static int CV_ConDroptime = R_CON_DROPTIME;

int CON_Register(void)
{

	CVAR_Register_I(&CV_ConResize, "con_h",
	    NULL, R_CVAR_NONE, 12, R_CON_DEFAULTPOS);

	CVAR_Register_I(&CV_ConDroptime, "con_droptime",
	    NULL, R_CVAR_NONE, 0, 5000);

	CVAR_Register_I(&ConInfo.line_max, "con_lines",
	    NULL, R_CVAR_NONE, 5, 5000);

	return R_SUCCESS;
}

int CON_Init(void)
{
	return R_SUCCESS;
}

int CON_Shutdown(void)
{

	R_printf(R_STDOUT,
	    "CON_Shutdown(): Deleting console scrollback and command history.\n");

	CON_DeleteScroll(&ConScrollback);
	CON_DeleteScroll(&ConHistory);

	return R_SUCCESS;
}

int CON_Activate(void)
{
	R_EVENT con_event;

	if (ConInfo.active) {
		return R_FAILURE;
	}

	con_event.type = R_CONTINUOUS_EVENT;
	con_event.code = R_CONSOLE_EVENT | R_NODESTROY;
	con_event.op = EVENT_ACTIVATE;
	con_event.time = 0;
	con_event.duration = CV_ConDroptime;

	EVENT_Queue(&con_event);

	ConInfo.active = 1;

	return R_SUCCESS;
}

int CON_Deactivate(void)
{
	R_EVENT con_event;

	if (!ConInfo.active) {
		return R_FAILURE;
	}

	con_event.type = R_CONTINUOUS_EVENT;
	con_event.code = R_CONSOLE_EVENT | R_NODESTROY;
	con_event.op = EVENT_DEACTIVATE;
	con_event.time = 0;
	con_event.duration = CV_ConDroptime;

	EVENT_Queue(&con_event);

	return R_SUCCESS;
}

int CON_IsActive(void)
{

	return ConInfo.active;
}

int CON_Type(int in_char)
/****************************************************************************\
 Responsible for processing character input to the console and maintaining
 the console input buffer.
 Input buffer is processed by EXPR_Parse on enter.
 High ASCII characters are ignored.
\****************************************************************************/
{

	int input_pos = ConInfo.input_pos;
	const char *expr;
	int expr_len;
	int result;
	/*char *lvalue; */

	char *rvalue = NULL;
	R_CVAR_P con_cvar = NULL;

	char *expr_err;
	char *err_str;

	if (ConInfo.y_pos != ConInfo.y_max) {
		/* Ignore keypress until console fully down */
		return R_SUCCESS;
	}

	if ((in_char > 127) || (!in_char)) {
		/* Ignore non-ascii codes */
		return R_SUCCESS;
	}

	switch (in_char) {

	case '\r':

		expr = ConInfo.input_buf;
		CON_Print("> %s", ConInfo.input_buf);

		expr_len = strlen(ConInfo.input_buf);
		result = EXPR_Parse(&expr, &expr_len, &con_cvar, &rvalue);

		CON_AddLine(&ConHistory, ConInfo.hist_max, ConInfo.input_buf);

		memset(ConInfo.input_buf, 0, R_CON_INPUTBUF_LEN);
		ConInfo.input_pos = 0;
		ConInfo.hist_pos = 0;
		if (result != R_SUCCESS) {
			EXPR_GetError(&expr_err);
			CON_Print("Parse error: %s", expr_err);
			break;
		}

		if (rvalue == NULL) {
			CVAR_Print(con_cvar);
			break;
		}

		if (CVAR_IsFunc(con_cvar)) {
			CVAR_Exec(con_cvar, rvalue);
		} else if (CVAR_SetValue(con_cvar, rvalue) != R_SUCCESS) {
			CVAR_GetError(&err_str);
			CON_Print("Illegal assignment: %s.", err_str);
		}

		break;

	case '\b':
		ConInfo.input_buf[input_pos] = 0;

		if (input_pos > 0) {
			ConInfo.input_pos--;
			ConInfo.input_buf[ConInfo.input_pos] = 0;
		}
		break;

	default:
		if (input_pos < R_CON_INPUTBUF_LEN) {
			ConInfo.input_buf[input_pos] = (char)in_char;
			ConInfo.input_pos++;
		}
		break;
	}

	if (rvalue)
		free(rvalue);

	return R_SUCCESS;
}

int CON_Draw(R_SURFACE * ds)
{

	int line_y;

	R_CONSOLE_LINE *walk_ptr;
	R_CONSOLE_LINE *start_ptr;

	int txt_fgcolor;
	int txt_shcolor;

	R_RECT fill_rect;

	int i;

	if (!ConInfo.active) {
		return R_FAILURE;
	}

	if (CV_ConResize != ConInfo.y_max) {
		ConInfo.y_max = CV_ConResize;
		ConInfo.y_pos = CV_ConResize;
	}

	fill_rect.x1 = 0;
	fill_rect.y1 = 0;

	fill_rect.x2 = ds->buf_w - 1;
	fill_rect.y2 = ConInfo.y_pos;

	GFX_DrawRect(ds, &fill_rect, SYSGFX_MatchColor(R_CONSOLE_BGCOLOR));

	txt_fgcolor = SYSGFX_MatchColor(R_CONSOLE_TXTCOLOR);
	txt_shcolor = SYSGFX_MatchColor(R_CONSOLE_TXTSHADOW);

	FONT_Draw(SMALL_FONT_ID,
	    ds,
	    ">", 1,
	    2, ConInfo.y_pos - 10, txt_fgcolor, txt_shcolor, FONT_SHADOW);

	FONT_Draw(SMALL_FONT_ID,
	    ds,
	    ConInfo.input_buf, strlen(ConInfo.input_buf),
	    10, ConInfo.y_pos - 10, txt_fgcolor, txt_shcolor, FONT_SHADOW);

	line_y = ConInfo.y_pos - (R_CON_INPUT_H + R_CON_LINE_H);

	start_ptr = ConScrollback.head;

	for (i = 0; i < ConInfo.line_pos; i++) {
		if (start_ptr->next) {
			start_ptr = start_ptr->next;
		} else {
			break;
		}
	}

	for (walk_ptr = start_ptr; walk_ptr; walk_ptr = walk_ptr->next) {

		FONT_Draw(SMALL_FONT_ID,
		    ds,
		    walk_ptr->str_p,
		    walk_ptr->str_len,
		    2, line_y, txt_fgcolor, txt_shcolor, FONT_SHADOW);

		line_y -= R_CON_LINE_H;

		if (line_y < -R_CON_LINE_H)
			break;
	}

	return R_SUCCESS;
}

int CON_Print(const char *fmt_str, ...)
{

	char vsstr_p[R_CON_PRINTFLIMIT + 1];
	va_list argptr;
	int ret_val;

	va_start(argptr, fmt_str);

	ret_val = vsprintf(vsstr_p, fmt_str, argptr);

	CON_AddLine(&ConScrollback, ConInfo.line_max, vsstr_p);

	va_end(argptr);

	ConInfo.line_pos = 0;

	return ret_val;
}

int CON_CmdUp(void)
{

	R_CONSOLE_LINE *start_ptr = ConHistory.head;
	int i;

	if (!start_ptr) {
		return R_SUCCESS;
	}

	if (ConInfo.hist_pos < ConHistory.lines) {
		ConInfo.hist_pos++;
	}

	for (i = 1; (i < ConInfo.hist_pos); i++) {
		if (start_ptr->next) {
			start_ptr = start_ptr->next;
		} else {
			break;
		}
	}

	memset(ConInfo.input_buf, 0, R_CON_INPUTBUF_LEN);
	strcpy(ConInfo.input_buf, start_ptr->str_p);
	ConInfo.input_pos = start_ptr->str_len - 1;

	R_printf(R_STDOUT, "History pos: %d/%d", ConInfo.hist_pos,
	    ConHistory.lines);

	return R_SUCCESS;
}

int CON_CmdDown(void)
{

	R_CONSOLE_LINE *start_ptr = ConHistory.head;
	int i;

	if (ConInfo.hist_pos == 1) {
		R_printf(R_STDOUT, "Erased input buffer.");
		memset(ConInfo.input_buf, 0, R_CON_INPUTBUF_LEN);
		ConInfo.input_pos = 0;
		ConInfo.hist_pos--;
		return R_SUCCESS;
	} else if (ConInfo.hist_pos) {
		ConInfo.hist_pos--;
	} else {
		return R_SUCCESS;
	}

	for (i = 1; i < ConInfo.hist_pos; i++) {
		if (start_ptr->next) {
			start_ptr = start_ptr->next;
		} else {
			break;
		}
	}

	memset(ConInfo.input_buf, 0, R_CON_INPUTBUF_LEN);
	strcpy(ConInfo.input_buf, start_ptr->str_p);
	ConInfo.input_pos = start_ptr->str_len - 1;

	R_printf(R_STDOUT, "History pos: %d/%d", ConInfo.hist_pos,
	    ConHistory.lines);

	return R_SUCCESS;
}

int CON_PageUp(void)
{

	int n_lines;

	n_lines = (ConInfo.y_max - R_CON_INPUT_H) / R_CON_LINE_H;

	if (ConInfo.line_pos < (ConScrollback.lines - n_lines)) {
		ConInfo.line_pos += n_lines;
	}

	R_printf(R_STDOUT, "Line pos: %d", ConInfo.line_pos);

	return R_SUCCESS;
}

int CON_PageDown(void)
{

	int n_lines;

	n_lines = (ConInfo.y_max - R_CON_INPUT_H) / R_CON_LINE_H;

	if (ConInfo.line_pos > n_lines) {
		ConInfo.line_pos -= n_lines;
	} else {
		ConInfo.line_pos = 0;
	}

	return R_SUCCESS;
}

int CON_DropConsole(double percent)
{

	R_SURFACE *back_buf;

	if (percent > 1.0) {
		percent = 1.0;
	}

	back_buf = SYSGFX_GetBackBuffer();
	CON_SetDropPos(percent);

	CON_Draw(back_buf);

	return R_SUCCESS;
}

int CON_RaiseConsole(double percent)
{

	R_SURFACE *back_buf;

	if (percent >= 1.0) {
		percent = 1.0;
		ConInfo.active = 0;
	}

	back_buf = SYSGFX_GetBackBuffer();

	CON_SetDropPos(1.0 - percent);

	CON_Draw(back_buf);

	return R_SUCCESS;
}

static int CON_SetDropPos(double percent)
{

	double exp_percent;

	if (percent > 1.0)
		percent = 1.0;
	if (percent < 0.0)
		percent = 0.0;

	exp_percent = percent * percent;

	ConInfo.y_pos = (int)(ConInfo.y_max * exp_percent);

	return R_SUCCESS;
}

static int
CON_AddLine(R_CON_SCROLLBACK * scroll, int line_max, const char *constr_p)
{

	int constr_len;
	char *newstr_p;
	R_CONSOLE_LINE *newline_p;
	int del_lines;
	int i;

	constr_len = strlen(constr_p) + 1;

	newstr_p = (char *)malloc(constr_len);
	if (newstr_p == NULL) {
		return R_MEM;
	}

	newline_p = (R_CONSOLE_LINE *)malloc(sizeof(R_CONSOLE_LINE));
	if (newline_p == NULL) {
		return R_MEM;
	}
	newline_p->next = NULL;
	newline_p->prev = NULL;

	strcpy(newstr_p, constr_p);
	newline_p->str_p = newstr_p;
	newline_p->str_len = constr_len;

	if (scroll->head == NULL) {
		scroll->head = newline_p;
		scroll->tail = newline_p;
	} else {
		scroll->head->prev = newline_p;
		newline_p->next = scroll->head;
		scroll->head = newline_p;
	}

	scroll->lines++;

	if (scroll->lines > line_max) {
		del_lines = scroll->lines - line_max;

		for (i = 0; i < del_lines; i++) {
			CON_DeleteLine(scroll);
		}
	}

	return R_SUCCESS;
}

static int CON_DeleteLine(R_CON_SCROLLBACK * scroll)
{

	R_CONSOLE_LINE *temp_p = scroll->tail;

	if (temp_p->prev == NULL) {
		scroll->head = NULL;
		scroll->tail = NULL;
	} else {
		temp_p->prev->next = NULL;
		scroll->tail = temp_p->prev;
	}

	if (temp_p->str_p)
		free(temp_p->str_p);
	free(temp_p);
	scroll->lines--;

	return R_SUCCESS;
}

static int CON_DeleteScroll(R_CON_SCROLLBACK * scroll)
{

	R_CONSOLE_LINE *walk_ptr;
	R_CONSOLE_LINE *temp_ptr;

	for (walk_ptr = scroll->head; walk_ptr; walk_ptr = temp_ptr) {

		if (walk_ptr->str_p)
			free(walk_ptr->str_p);
		temp_ptr = walk_ptr->next;
		free(walk_ptr);
	}

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: console.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/console.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Console module header file

 Notes: 
*/

#ifndef SAGA_CONSOLE_H_
#define SAGA_CONSOLE_H_

namespace Saga {

#define R_CON_INPUTBUF_LEN 80

#define R_CONSOLE_BGCOLOR   0x00A0A0A0UL
#define R_CONSOLE_TXTCOLOR  0x00FFFFFFUL
#define R_CONSOLE_TXTSHADOW 0x00202020UL

typedef struct R_CONSOLEINFO_tag {

	int active;
	int y_max;
	int line_max;
	int hist_max;
	int hist_pos;
	int line_pos;
	int y_pos;
	char *prompt;
	int prompt_w;
	char input_buf[R_CON_INPUTBUF_LEN + 1];
	int input_pos;

} R_CONSOLEINFO;

typedef struct R_CONSOLE_LINE_tag {

	struct R_CONSOLE_LINE_tag *next;
	struct R_CONSOLE_LINE_tag *prev;
	char *str_p;
	int str_len;

} R_CONSOLE_LINE;

typedef struct R_CON_SCROLLBACK_tag {

	struct R_CONSOLE_LINE_tag *head;
	struct R_CONSOLE_LINE_tag *tail;
	int lines;

} R_CON_SCROLLBACK;

static int
CON_AddLine(R_CON_SCROLLBACK * scroll, int line_max, const char *constr_p);

static int CON_DeleteLine(R_CON_SCROLLBACK * scroll);

static int CON_DeleteScroll(R_CON_SCROLLBACK * scroll);

static int CON_SetDropPos(double percent);

#define R_CON_DEFAULTPOS 136
#define R_CON_DEFAULTLINES 100
#define R_CON_DEFAULTCMDS 10
#define R_CON_DROPTIME 400
#define R_CON_PRINTFLIMIT 1024
#define R_CON_LINE_H 10
#define R_CON_INPUT_H 10

} // End of namespace Saga

#endif				/* R_CONSOLE_H_ */

/* end "r_console.h" */

--- NEW FILE: console_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/console_mod.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:	
 
	Console module public header file

 Notes: 
*/

#ifndef SAGA_CONSOLE_MOD_H_
#define SAGA_CONSOLE_MOD_H_

namespace Saga {

int CON_Register(void);
int CON_Init(void);
int CON_Shutdown(void);

int CON_Activate(void);
int CON_Deactivate(void);
int CON_IsActive(void);

int CON_Type(int in_char);
int CON_Draw(R_SURFACE * ds);
int CON_Print(const char *fmt_str, ...);

int CON_CmdUp(void);
int CON_CmdDown(void);
int CON_PageUp(void);
int CON_PageDown(void);

int CON_DropConsole(double percent);
int CON_RaiseConsole(double percent);

} // End of namespace Saga

#endif				/* R_CONSOLE_MOD_H_ */
/* end "r_console_mod.h" */

--- NEW FILE: cvar.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/cvar.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:   
 
    Configuration Variable Module

 Notes: 
*/

#include "reinherit.h"

#include <limits.h>
#include <stddef.h>

/*
   Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "console_mod.h"

/*
   Begin module
\*--------------------------------------------------------------------------*/
#include "cvar_mod.h"
#include "cvar.h"

namespace Saga {

R_CVAR *CVHashTbl[R_CVAR_HASHLEN];

char *CVAR_ErrMsg[] = {

	"No Error",
	"Not implememented.",
	"Memory allocation failed",
	"Value overflowed while parsing",
	"Invalid numeric constant",
	"Value overflows destination type",
	"Assignment of negative value to unsigned variable",
	"Value outside of specified bounds",
	"Invalid string literal",
	"Invalid type for assignment",
	"Variable is read-only",
	"Not a valid function"
};

enum CVAR_Errors {

	CVERR_NONE,
	CVERR_NOTIMPL,
	CVERR_MEM,
	CVERR_PARSEOVERFLOW,
	CVERR_INVALID,
	CVERR_DESTOVERFLOW,
	CVERR_SIGN,
	CVERR_BOUND,
	CVERR_STRING,
	CVERR_TYPE,
	CVERR_READONLY,
	CVERR_NOTFUNC
};

static enum CVAR_Errors CVAR_ErrorState;

int CVAR_GetError(char **err_str)
/****************************************************************************\
 Returns the appropriate cvar error string
\****************************************************************************/
{

	*err_str = CVAR_ErrMsg[CVAR_ErrorState];

	return CVAR_ErrorState;
}

int CVAR_Shutdown(void)
/****************************************************************************\
 Frees the cvar hash table
\****************************************************************************/
{

	R_CVAR *walk_ptr;
	R_CVAR *temp_ptr;
	int i;

	R_printf(R_STDOUT, "CVAR_Shutdown(): Deleting cvar hash table.\n");

	for (i = 0; i < R_CVAR_HASHLEN; i++) {

		for (walk_ptr = CVHashTbl[i]; walk_ptr; walk_ptr = temp_ptr) {

			temp_ptr = walk_ptr->next;
			free(walk_ptr);
		}
	}

	return R_SUCCESS;
}

unsigned int CVAR_HashString(const char *str)
/****************************************************************************\
 Returns hash index for string 'str'.
 Cannot fail.
\****************************************************************************/
{

	unsigned int index;

	for (index = 0; *str != '\0'; str++) {
		index = *str + 31 * index;
	}

	return index % R_CVAR_HASHLEN;
}

int CVAR_Add(int index, R_CVAR * cvar)
/****************************************************************************\
 Adds a copy of the given cvar into the hash table.
 Returns R_SUCCESS if cvar was added, R_MEM if allocation failed.
\****************************************************************************/
{

	R_CVAR *new_cvar;
	R_CVAR *temp_ptr;

	new_cvar = (R_CVAR *)malloc(sizeof(R_CVAR));

	if (new_cvar == NULL) {
		CVAR_ErrorState = CVERR_MEM;
		return R_MEM;
	}

	memcpy(new_cvar, cvar, sizeof(R_CVAR));

	if (CVHashTbl[index] == NULL) {
		CVHashTbl[index] = new_cvar;
		new_cvar->next = NULL;
	} else {
		temp_ptr = CVHashTbl[index];
		CVHashTbl[index] = new_cvar;
		new_cvar->next = temp_ptr;
	}

	CVAR_ErrorState = CVERR_NONE;
	return R_SUCCESS;
}

int CVAR_Exec(R_CVAR_P cvar_func, char *r_value)
/****************************************************************************\
 Attempts to execute the specified console function with the given argument
 string.
 Returns R_FAILURE if cvar_func is not a valid console function
\****************************************************************************/
{

	int cf_argc = 0;
	char **cf_argv = NULL;
	int max_args;

	if (cvar_func->type != R_CVAR_FUNC) {
		CVAR_ErrorState = CVERR_NOTFUNC;
		return R_FAILURE;
	}

	cf_argc = EXPR_GetArgs(r_value, &cf_argv);

	if (cf_argc < cvar_func->t.func.min_args) {
		CON_Print("Too few arguments to function.");
		if (cf_argv)
			free(cf_argv);
		return R_FAILURE;
	}

	max_args = cvar_func->t.func.max_args;
	if ((max_args > -1) && (cf_argc > max_args)) {
		CON_Print("Too many arguments to function.");
		if (cf_argv)
			free(cf_argv);
		return R_FAILURE;
	}

	/* Call function */
	(cvar_func->t.func.func_p) (cf_argc, cf_argv);

	if (cf_argv)
		free(cf_argv);

	return R_SUCCESS;
}

int CVAR_SetValue(R_CVAR_P cvar, char *r_value)
/****************************************************************************\
 Attempts to assign the value contained in the string 'r_value' to cvar.
 Returns R_FAILURE if there was an error parsing 'r_value'
\****************************************************************************/
{

	long int int_param;
	unsigned long uint_param;

	char *end_p;
	ptrdiff_t scan_len;
	int r_value_len;

	r_value_len = strlen(r_value);

	if (cvar->flags & R_CVAR_READONLY) {
		CVAR_ErrorState = CVERR_READONLY;
		return R_FAILURE;
	}

	switch (cvar->type) {

	case R_CVAR_INT:

		int_param = strtol(r_value, &end_p, 10);

		if ((int_param == LONG_MIN) || (int_param == LONG_MAX)) {
			CVAR_ErrorState = CVERR_PARSEOVERFLOW;
			return R_FAILURE;
		}

		scan_len = end_p - r_value;

		if (int_param == 0) {
			if (!scan_len || r_value[scan_len - 1] != '0') {
				/* strtol() returned 0, but string isn't "0". Invalid. */
				CVAR_ErrorState = CVERR_INVALID;
				return R_FAILURE;
			}
		}

		if (scan_len != r_value_len) {
			/* Entire string wasn't converted...Invalid */
			CVAR_ErrorState = CVERR_INVALID;
			return R_FAILURE;
		}

		if ((int_param < CV_INTMIN) || (int_param > CV_INTMAX)) {
			/* Overflows destination type */
			CVAR_ErrorState = CVERR_DESTOVERFLOW;
			return R_FAILURE;
		}

		/* Ignore bounds if equal */
		if (cvar->t.i.lbound != cvar->t.i.ubound) {

			if ((int_param < cvar->t.i.lbound) ||
			    (int_param > cvar->t.i.ubound)) {
				/* Value is outside of cvar bounds */
				CVAR_ErrorState = CVERR_BOUND;
				return R_FAILURE;
			}
		}

		*(cvar->t.i.var_p) = (cv_int_t) int_param;

#ifdef R_CVAR_TRACE
		printf("Set cvar to value %ld.\n", int_param);
#endif

		break;

	case R_CVAR_UINT:

		if (*r_value == '-') {
			CVAR_ErrorState = CVERR_SIGN;
			return R_FAILURE;
		}

		uint_param = strtoul(r_value, &end_p, 10);

		if (uint_param == ULONG_MAX) {
			CVAR_ErrorState = CVERR_PARSEOVERFLOW;
			return R_FAILURE;
		}

		scan_len = end_p - r_value;

		if (uint_param == 0) {

			if (!scan_len || r_value[scan_len - 1] != '0') {
				/* strtol() returned 0, but string isn't "0". Invalid. */
				CVAR_ErrorState = CVERR_INVALID;
				return R_FAILURE;
			}
		}

		if (scan_len != r_value_len) {
			/* Entire string wasn't converted...Invalid */
			CVAR_ErrorState = CVERR_INVALID;
			return R_FAILURE;
		}

		if (uint_param > CV_UINTMAX) {
			/* Overflows destination type */
			CVAR_ErrorState = CVERR_DESTOVERFLOW;
			return R_FAILURE;
		}

		/* Ignore bounds if equal */
		if (cvar->t.ui.lbound != cvar->t.ui.ubound) {

			if ((uint_param < cvar->t.ui.lbound) ||
			    (uint_param > cvar->t.ui.ubound)) {
				/* Value is outside cvar bounds */
				CVAR_ErrorState = CVERR_BOUND;
				return R_FAILURE;
			}
		}

		*(cvar->t.ui.var_p) = (cv_uint_t) uint_param;

#ifdef R_CVAR_TRACE
		printf("Set cvar to value %lu.\n", uint_param);
#endif

		break;

	case R_CVAR_FLOAT:

		CVAR_ErrorState = CVERR_NOTIMPL;
		return R_FAILURE;
		break;

	case R_CVAR_STRING:

		if (strrchr(r_value, '\"') != NULL) {
			CVAR_ErrorState = CVERR_STRING;
			return R_FAILURE;
		}

		strncpy(cvar->t.s.var_str, r_value, cvar->t.s.ubound);
		if (cvar->t.s.ubound < r_value_len) {
			cvar->t.s.var_str[cvar->t.s.ubound] = 0;
		}
#ifdef R_CVAR_TRACE
		printf("Set cvar to value \"%s\".\n", cvar->t.s.var_str);
#endif

		break;

	default:

		CVAR_ErrorState = CVERR_TYPE;
		return R_FAILURE;
		break;
	}

	CVAR_ErrorState = CVERR_NONE;
	return R_SUCCESS;
}

R_CVAR_P CVAR_Find(const char *var_str)
/****************************************************************************\
 Given a cvar name this function returns a pointer to the appropriate 
 cvar structure or NULL if no match was found.
\****************************************************************************/
{

	R_CVAR *walk_ptr;
	int hash;

	hash = CVAR_HashString(var_str);

#ifdef R_CVAR_TRACE
	printf("Performing lookup on hash bucket %d.\n", hash);
#endif

	walk_ptr = CVHashTbl[hash];

	while (walk_ptr != NULL) {

		if (strcmp(var_str, walk_ptr->name) == 0) {
			return walk_ptr;
		}

		walk_ptr = walk_ptr->next;
	}

	return NULL;
}

int CVAR_IsFunc(R_CVAR_P cvar_func)
{

	if (cvar_func->type == R_CVAR_FUNC)
		return 1;
	else
		return 0;
}

int
CVAR_RegisterFunc(cv_func_t func,
    const char *func_name,
    const char *func_argstr, uint flags, int min_args, int max_args)
/****************************************************************************\
 Registers a console function 'cvar' 
 (could think of a better place to put these...?)
\****************************************************************************/
{

	R_CVAR new_cvar;
	int hash;

	new_cvar.name = func_name;
	new_cvar.type = R_CVAR_FUNC;
	new_cvar.section = NULL;
	new_cvar.flags = flags;

	new_cvar.t.func.func_p = func;
	new_cvar.t.func.func_argstr = func_argstr;
	new_cvar.t.func.min_args = min_args;
	new_cvar.t.func.max_args = max_args;
	hash = CVAR_HashString(func_name);

#ifdef R_CVAR_TRACE
	printf("Added FUNC cvar to hash bucket %d.\n", hash);
#endif

	return CVAR_Add(hash, &new_cvar);
}

int
CVAR_Register_I(cv_int_t * var_p,
    const char *var_name,
    const char *section, uint flags, cv_int_t lbound, cv_int_t ubound)
/****************************************************************************\
 Registers an integer type cvar.
\****************************************************************************/
{

	R_CVAR new_cvar;
	int hash;

	new_cvar.name = var_name;
	new_cvar.type = R_CVAR_INT;
	new_cvar.section = section;
	new_cvar.flags = flags;

	new_cvar.t.i.var_p = var_p;

	new_cvar.t.i.lbound = lbound;
	new_cvar.t.i.ubound = ubound;

	hash = CVAR_HashString(var_name);

#ifdef R_CVAR_TRACE
	printf("Added INT cvar to hash bucket %d.\n", hash);
#endif

	return CVAR_Add(hash, &new_cvar);
}

int
CVAR_Register_UI(cv_uint_t * var_p,
    const char *var_name,
    const char *section, uint flags, cv_uint_t lbound, cv_uint_t ubound)
/****************************************************************************\ 
 Registers an unsigned integer type cvar.
\****************************************************************************/
{

	R_CVAR new_cvar;
	int hash;

	new_cvar.name = var_name;
	new_cvar.type = R_CVAR_UINT;
	new_cvar.section = section;
	new_cvar.flags = flags;

	new_cvar.t.ui.var_p = var_p;

	new_cvar.t.ui.lbound = lbound;
	new_cvar.t.ui.ubound = ubound;

	hash = CVAR_HashString(var_name);

#ifdef R_CVAR_TRACE
	printf("Added UNSIGNED INT ccvar to hash bucket %d.\n", hash);
#endif

	return CVAR_Add(hash, &new_cvar);
}

int
CVAR_Register_F(cv_float_t * var_p,
    const char *var_name,
    const char *section, uint flags, cv_float_t lbound, cv_float_t ubound)
/****************************************************************************\
 Registers a floating point type cvar.
\****************************************************************************/
{

	R_CVAR new_cvar;
	int hash;

	new_cvar.name = var_name;
	new_cvar.type = R_CVAR_FLOAT;
	new_cvar.section = section;
	new_cvar.flags = flags;

	new_cvar.t.f.var_p = var_p;

	new_cvar.t.f.lbound = lbound;
	new_cvar.t.f.ubound = ubound;

	hash = CVAR_HashString(var_name);

#ifdef R_CVAR_TRACE
	printf("Added FLOAT cvar to hash bucket %d.\n", hash);
#endif

	return CVAR_Add(hash, &new_cvar);
}

int
CVAR_Register_S(cv_char_t * var_str,
    const char *var_name, const char *section, uint flags, int ubound)
/****************************************************************************\
 Registers a string type cvar. Storage must be provided in var_p for 'ubound'
 characters plus 1 for NUL char. 
\****************************************************************************/
{

	R_CVAR new_cvar;
	int hash;

	new_cvar.name = var_name;
	new_cvar.type = R_CVAR_STRING;
	new_cvar.section = section;
	new_cvar.flags = flags;

	new_cvar.t.s.var_str = var_str;
	new_cvar.t.s.ubound = ubound;

	hash = CVAR_HashString(var_name);

#ifdef R_CVAR_TRACE
	printf("Added UNSIGNED INT var to hash bucket %d.\n", hash);
#endif

	return CVAR_Add(hash, &new_cvar);
}

int CVAR_Print(R_CVAR_P con_cvar)
/****************************************************************************\
 Displays the value and type of the given cvar to the console.
\****************************************************************************/
{

	switch (con_cvar->type) {

	case R_CVAR_INT:
		CON_Print("\"%s\"(i) = %d",
		    con_cvar->name, *(con_cvar->t.i.var_p));
		break;

	case R_CVAR_UINT:
		CON_Print("\"%s\"(ui) = %u",
		    con_cvar->name, *(con_cvar->t.ui.var_p));
		break;

	case R_CVAR_FLOAT:
		CON_Print("\"%s\"(ui) = %f",
		    con_cvar->name, *(con_cvar->t.f.var_p));
		break;

	case R_CVAR_STRING:
		CON_Print("\"%s\"(s) = \"%s\"", con_cvar->name,
		    con_cvar->t.s.var_str);
		break;

	case R_CVAR_FUNC:
		if (con_cvar->t.func.func_argstr) {
			CON_Print("\"%s\"(func) Args: %s", con_cvar->name,
			    con_cvar->t.func.func_argstr);
		} else {
			CON_Print("\"%s\"(func) No arguments.",
			    con_cvar->name);
		}
		break;

	default:
		CON_Print("Invalid variable type.\n");
		break;
	}

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: cvar.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/cvar.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:   
 
    Configuration Variable Module

 Notes: 
*/

#ifndef SAGA_CVAR_H_
#define SAGA_CVAR_H_

namespace Saga {

#define R_CVAR_HASHLEN 32

typedef struct R_SUBCVAR_INT_tag {

	cv_int_t *var_p;
	cv_int_t ubound;
	cv_int_t lbound;

} R_SUBCVAR_INT;

typedef struct R_SUBCVAR_UINT_tag {

	cv_uint_t *var_p;
	cv_uint_t ubound;
	cv_uint_t lbound;

} R_SUBCVAR_UINT;

typedef struct R_SUBCVAR_FLOAT_tag {

	cv_float_t *var_p;
	cv_float_t ubound;
	cv_float_t lbound;

} R_SUBCVAR_FLOAT;

typedef struct R_SUBCVAR_STRING_tag {

	cv_char_t *var_str;
	int ubound;

} R_SUBCVAR_STRING;

typedef struct R_SUBCVAR_FUNC_tag {

	cv_func_t func_p;
	const char *func_argstr;
	int min_args;
	int max_args;

} R_SUBCVAR_FUNC;

typedef struct R_CVAR_tag {

	int type;
	const char *name;
	const char *section;
	uint flags;

	union {
		R_SUBCVAR_INT i;
		R_SUBCVAR_UINT ui;
		R_SUBCVAR_FLOAT f;
		R_SUBCVAR_STRING s;
		R_SUBCVAR_FUNC func;
	} t;

	struct R_CVAR_tag *next;

} R_CVAR;

} // End of namespace Saga

#endif				/* R_CVAR_H_ */
/* end "r_cvar.h" */

--- NEW FILE: cvar_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/cvar_mod.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:   
 
    Configuration variable module public header file

 Notes: 
*/

#ifndef SAGA_CVAR_MOD_H_
#define SAGA_CVAR_MOD_H_

namespace Saga {

/* Modify these to change base cvar types */
#define CV_INTMAX INT_MAX
#define CV_INTMIN INT_MIN

#define CV_UINTMAX UINT_MAX
typedef int cv_int_t;
typedef unsigned int cv_uint_t;
typedef float cv_float_t;
typedef char cv_char_t;
typedef void (*cv_func_t) (int cv_argc, char *cv_argv[]);
/******************************************/

typedef struct R_CVAR_tag *R_CVAR_P;	/* opaque typedef */

typedef enum R_CVAR_TYPES_tag {

	R_CVAR_INVALID,
	R_CVAR_INT,
	R_CVAR_UINT,
	R_CVAR_FLOAT,
	R_CVAR_STRING,
	R_CVAR_FUNC
} R_CVAR_TYPES;

typedef enum R_CVAR_FLAGS_tag {

	R_CVAR_NONE,
	R_CVAR_READONLY,
	R_CVAR_LBOUND,
	R_CVAR_UBOUND,
	R_CVAR_CFG,
	R_CVAR_SECTION
} R_CVAR_FLAGS;

#define R_CVAR_BOUNDED ( R_CVAR_LBOUND | R_CVAR_UBOUND )

int CVAR_Shutdown(void);
R_CVAR_P CVAR_Find(const char *var_str);
int CVAR_SetValue(R_CVAR_P cvar, char *r_value);
int CVAR_Print(R_CVAR_P con_cvar);
int CVAR_GetError(char **err_str);
int CVAR_IsFunc(R_CVAR_P cvar_func);
int CVAR_Exec(R_CVAR_P cvar_func, char *r_value);

int
CVAR_RegisterFunc(cv_func_t func,
    const char *func_name,
    const char *func_argstr, uint flags, int min_args, int max_args);

int CVAR_Register_I(cv_int_t * var_p,
    const char *var_name,
    const char *section, uint flags, cv_int_t lbound, cv_int_t ubound);

int CVAR_Register_UI(cv_uint_t * var_p,
    const char *var_name,
    const char *section, uint flags, cv_uint_t lbound, cv_uint_t ubound);

int CVAR_Register_F(cv_float_t * var_p,
    const char *var_name,
    const char *section, uint flags, cv_float_t lbound, cv_float_t ubound);

int CVAR_Register_S(cv_char_t * var_str,
    const char *var_name, const char *section, uint flags, int ubound);

int EXPR_Parse(const char **exp_pp, int *len, R_CVAR_P * expr_cvar,
    char **rvalue);

char *EXPR_ReadString(const char **string_p, int *len, int term_char);

int EXPR_GetError(char **err_str);

int EXPR_GetArgs(char *cmd_str, char ***expr_argv);

} // End of namespace Saga

#endif				/* R_CVAR_MOD_H_ */
/* end r_cvar_mod.h_ */

--- NEW FILE: events.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/events.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Event management module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "animation_mod.h"
#include "console_mod.h"
#include "scene_mod.h"
#include "gfx_mod.h"
#include "interface_mod.h"
#include "text_mod.h"
#include "palanim_mod.h"
#include "render_mod.h"
#include "sndres_mod.h"

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "events_mod.h"
#include "events.h"

namespace Saga {

static YS_DL_LIST *EventList;

int EVENT_Init(void)
{
	R_printf(R_STDOUT, "Initializing event subsystem...\n");

	EventList = ys_dll_create();

	return (EventList != NULL) ? R_SUCCESS : R_FAILURE;
}

int EVENT_Shutdown(void)
{
	R_printf(R_STDOUT, "Shutting down event subsystem...\n");

	EVENT_FreeList();

	return R_SUCCESS;
}

int EVENT_HandleEvents(long msec)
/*--------------------------------------------------------------------------*\
 * Function to process event list once per frame. 
 * First advances event times, then processes each event with the appropriate
 *  handler depending on the type of event.
\*--------------------------------------------------------------------------*/
{
	YS_DL_NODE *walk_node;
	YS_DL_NODE *next_node;

	R_EVENT *event_p;

	long delta_time;
	int result;

	/* Advance event times
	 * \*------------------------------------------------------------- */
	ProcessEventTime(msec);

	/* Process each event in list
	 * \*------------------------------------------------------------- */
	for (walk_node = ys_dll_head(EventList);
	    walk_node != NULL; walk_node = next_node) {

		event_p = (R_EVENT *)ys_dll_get_data(walk_node);

		/* Save next event in case current event is handled and removed */
		next_node = ys_dll_next(walk_node);

		/* Call the appropriate event handler for the specific event type */
		switch (event_p->type) {

		case R_ONESHOT_EVENT:
			result = HandleOneShot(event_p);
			break;

		case R_CONTINUOUS_EVENT:
			result = HandleContinuous(event_p);
			break;

		case R_INTERVAL_EVENT:
			result = HandleInterval(event_p);
			break;

		default:
			result = R_EVENT_INVALIDCODE;
			R_printf(R_STDERR,
			    "Invalid event code encountered.\n");
			break;
		}

		/* Process the event appropriately based on result code from 
		 * handler */
		if ((result == R_EVENT_DELETE) ||
		    (result == R_EVENT_INVALIDCODE)) {

			/* If there is no event chain, delete the base event. */
			if (event_p->chain == NULL) {
				ys_dll_delete(walk_node);
			} else {
				/* If there is an event chain present, move the next event 
				 * in the chain up, adjust it by the previous delta time, 
				 * and reprocess the event by adjusting next_node. */
				delta_time = event_p->time;

				ys_dll_replace(walk_node, event_p->chain,
				    sizeof *event_p);

				event_p = (R_EVENT *)ys_dll_get_data(walk_node);
				event_p->time += delta_time;

				next_node = walk_node;
			}
		} else if (result == R_EVENT_BREAK) {

			break;
		}

	}			/* end for () */

	return R_SUCCESS;
}

int HandleContinuous(R_EVENT * event)
{

	double event_pc = 0.0;	/* Event completion percentage */
	int event_done = 0;

	R_BUFFER_INFO buf_info;
	SCENE_BGINFO bg_info;
	R_SURFACE *back_buf;

	event_pc = ((double)event->duration - event->time) / event->duration;

	if (event_pc >= 1.0) {
		/* Cap percentage to 100 */
		event_pc = 1.0;
		event_done = 1;
	}

	if (event_pc < 0.0) {
		/* Event not signaled, skip it */
		return R_EVENT_CONTINUE;
	} else if (!(event->code & R_SIGNALED)) {
		/* Signal event */
		event->code |= R_SIGNALED;
		event_pc = 0.0;
	}

	switch (event->code & R_EVENT_MASK) {

	case R_PAL_EVENT:

		switch (event->op) {

		case EVENT_BLACKTOPAL:

			back_buf = SYSGFX_GetBackBuffer();

			SYSGFX_BlackToPal(back_buf, (PALENTRY *)event->data, event_pc);
			break;

		case EVENT_PALTOBLACK:

			back_buf = SYSGFX_GetBackBuffer();

			SYSGFX_PalToBlack(back_buf, (PALENTRY *)event->data, event_pc);
			break;

		default:
			break;
		}		/* end switch() */

		break;

	case R_TRANSITION_EVENT:

		switch (event->op) {

		case EVENT_DISSOLVE:

			RENDER_GetBufferInfo(&buf_info);
			SCENE_GetBGInfo(&bg_info);

			TRANSITION_Dissolve(buf_info.r_bg_buf,
			    buf_info.r_bg_buf_w,
			    buf_info.r_bg_buf_h,
			    buf_info.r_bg_buf_w,
			    bg_info.bg_buf, bg_info.bg_p, 0, event_pc);

			break;

		default:
			break;
		}

		break;

	case R_CONSOLE_EVENT:

		switch (event->op) {

		case EVENT_ACTIVATE:

			CON_DropConsole(event_pc);
			break;

		case EVENT_DEACTIVATE:

			CON_RaiseConsole(event_pc);
			break;

		default:
			break;
		}

		break;

	default:
		break;

	}			/* end switch( event->event_code ) */

	if (event_done) {
		return R_EVENT_DELETE;
	}

	return R_EVENT_CONTINUE;
}

static int HandleOneShot(R_EVENT * event)
{

	R_SURFACE *back_buf;

	static SCENE_BGINFO bginfo;

	if (event->time > 0) {
		return R_EVENT_CONTINUE;
	}

	/* Event has been signaled */

	switch (event->code & R_EVENT_MASK) {

	case R_TEXT_EVENT:

		switch (event->op) {

		case EVENT_DISPLAY:

			TEXT_SetDisplay((R_TEXTLIST_ENTRY *)event->data, 1);
			break;

		case EVENT_REMOVE:
			{
				R_SCENE_INFO scene_info;

				SCENE_GetInfo(&scene_info);

				TEXT_DeleteEntry(scene_info.text_list,
								 (R_TEXTLIST_ENTRY *)event->data);
			}
			break;

		default:
			break;
		}

		break;

	case R_VOICE_EVENT:

		SND_PlayVoice(event->param);
		break;

	case R_MUSIC_EVENT:

		SYSMUSIC_Play(event->param, event->param2);
		break;

	case R_BG_EVENT:
		{
			R_BUFFER_INFO rbuf_info;
			R_POINT bg_pt;

			if (SCENE_GetMode() == R_SCENE_MODE_NORMAL) {

				back_buf = SYSGFX_GetBackBuffer();

				RENDER_GetBufferInfo(&rbuf_info);
				SCENE_GetBGInfo(&bginfo);

				bg_pt.x = bginfo.bg_x;
				bg_pt.y = bginfo.bg_y;

				GFX_BufToBuffer(rbuf_info.r_bg_buf,
				    rbuf_info.r_bg_buf_w,
				    rbuf_info.r_bg_buf_h,
				    bginfo.bg_buf,
				    bginfo.bg_w, bginfo.bg_h, NULL, &bg_pt);

				if (event->param == SET_PALETTE) {

					PALENTRY *pal_p;

					SCENE_GetBGPal(&pal_p);
					SYSGFX_SetPalette(back_buf, pal_p);
				}
			}
		}
		break;

	case R_ANIM_EVENT:

		switch (event->op) {

		case EVENT_FRAME:

			ANIM_Play(event->param, event->time);
			break;

		default:
			break;
		}

		break;

	case R_SCENE_EVENT:

		switch (event->op) {

		case EVENT_END:

			SCENE_Next();

			return R_EVENT_BREAK;
			break;

		default:
			break;
		}

		break;

	case R_PALANIM_EVENT:

		switch (event->op) {

		case EVENT_CYCLESTART:

			PALANIM_CycleStart();
			break;

		case EVENT_CYCLESTEP:

			PALANIM_CycleStep(event->time);
			break;

		default:
			break;
		}
		break;

	case R_INTERFACE_EVENT:

		switch (event->op) {

		case EVENT_ACTIVATE:

			INTERFACE_Activate();
			break;

		default:
			break;
		}

		break;

	default:
		break;

	}			/* end switch( event->code ) */

	return R_EVENT_DELETE;
}

static int HandleInterval(R_EVENT * event)
{
	YS_IGNORE_PARAM(event);

	return R_EVENT_DELETE;
}

R_EVENT *EVENT_Queue(R_EVENT * event)
/*--------------------------------------------------------------------------*\
 * Schedules an event in the event list; returns a pointer to the scheduled
 * event suitable for chaining if desired.
\*--------------------------------------------------------------------------*/
{
	YS_DL_NODE *new_node;
	R_EVENT *queued_event;

	event->chain = NULL;

	new_node = ys_dll_add_tail(EventList, event, sizeof *event);

	if (new_node == NULL) {
		return NULL;
	}

	queued_event = (R_EVENT *)ys_dll_get_data(new_node);

	InitializeEvent(queued_event);

	return queued_event;
}

R_EVENT *EVENT_Chain(R_EVENT * head_event, R_EVENT * add_event)
/*--------------------------------------------------------------------------*\
 * Places a 'add_event' on the end of an event chain given by 'head_event'
 * (head_event may be in any position in the event chain)
\*--------------------------------------------------------------------------*/
{
	R_EVENT *walk_event;
	R_EVENT *new_event;

	/* Allocate space for new event */
	new_event = (R_EVENT *)malloc(sizeof *new_event);
	if (new_event == NULL) {
		return NULL;
	}

	/* Copy event data to new event */
	*new_event = *add_event;

	/* Walk to end of chain */
	for (walk_event = head_event;
	    walk_event->chain != NULL; walk_event = walk_event->chain) {

		continue;
	}

	/* Place new event */
	walk_event->chain = new_event;
	new_event->chain = NULL;

	InitializeEvent(new_event);

	return new_event;
}

static int InitializeEvent(R_EVENT * event)
{

	switch (event->type) {

	case R_ONESHOT_EVENT:
		break;

	case R_CONTINUOUS_EVENT:
		event->time += event->duration;
		break;

	case R_INTERVAL_EVENT:
		break;

	default:
		return R_FAILURE;
		break;
	}

	return R_SUCCESS;
}

int EVENT_ClearList(void)
/*--------------------------------------------------------------------------*\
 * Removes all events from the list except NODESTROY (engine) events
\*--------------------------------------------------------------------------*/
{
	YS_DL_NODE *walk_node;
	YS_DL_NODE *next_node;

	struct R_EVENT_tag *chain_walk;
	struct R_EVENT_tag *next_chain;

	R_EVENT *event_p;

	/* Walk down event list */
	for (walk_node = ys_dll_head(EventList);
	    walk_node != NULL; walk_node = next_node) {

		next_node = ys_dll_next(walk_node);
		event_p = (R_EVENT *)ys_dll_get_data(walk_node);

		/* Only remove events not marked R_NODESTROY (engine events) */
		if (!(event_p->code & R_NODESTROY)) {

			/* Remove any events chained off this one */
			for (chain_walk = event_p->chain;
			    chain_walk != NULL; chain_walk = next_chain) {

				next_chain = chain_walk->chain;
				free(chain_walk);
			}

			ys_dll_delete(walk_node);
		}
	}

	return R_SUCCESS;
}

int EVENT_FreeList(void)
/*--------------------------------------------------------------------------*\
 * Removes all events from the list (even R_NODESTROY)
\*--------------------------------------------------------------------------*/
{
	YS_DL_NODE *walk_node;
	YS_DL_NODE *next_node;

	struct R_EVENT_tag *chain_walk;
	struct R_EVENT_tag *next_chain;

	R_EVENT *event_p;

	/* Walk down event list */
	for (walk_node = ys_dll_head(EventList);
	    walk_node != NULL; walk_node = next_node) {

		event_p = (R_EVENT *)ys_dll_get_data(walk_node);

		/* Remove any events chained off current node */
		for (chain_walk = event_p->chain;
		    chain_walk != NULL; chain_walk = next_chain) {

			next_chain = chain_walk->chain;
			free(chain_walk);
		}

		/* Delete current node */
		next_node = ys_dll_next(walk_node);
		ys_dll_delete(walk_node);
	}

	return R_SUCCESS;
}

static int ProcessEventTime(long msec)
/*--------------------------------------------------------------------------*\
 * Walks down the event list, updating event times by 'msec'.
\*--------------------------------------------------------------------------*/
{
	YS_DL_NODE *walk_node;
	R_EVENT *event_p;

	uint event_count = 0;

	for (walk_node = ys_dll_head(EventList);
	    walk_node != NULL; walk_node = ys_dll_next(walk_node)) {

		event_p = (R_EVENT *)ys_dll_get_data(walk_node);
		event_p->time -= msec;

		event_count++;

		if (event_count > R_EVENT_WARNINGCOUNT) {
			R_printf(R_STDERR,
			    "WARNING: Event list exceeds %u.\n");
		}
	}

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: events.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/events.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Event management module header file

 Notes: 
*/

#ifndef SAGA_EVENT_H
#define SAGA_EVENT_H

namespace Saga {

#define R_EVENT_DBGLVL R_DEBUG_NONE

#define R_EVENT_WARNINGCOUNT 1000

#define R_EVENT_MASK 0x00FF

enum R_EVENT_STATUSCODE {

	R_EVENT_INVALIDCODE = 0,
	R_EVENT_DELETE,
	R_EVENT_CONTINUE,
	R_EVENT_BREAK
};

static int HandleContinuous(R_EVENT * event);

static int HandleOneShot(R_EVENT * event);

static int HandleInterval(R_EVENT * event);

static int ProcessEventTime(long msec);

static int InitializeEvent(R_EVENT * event);

} // End of namespace Saga

#endif				/* R_EVENT_H */

--- NEW FILE: events_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/events_mod.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Event module public header

 Notes: 
*/

#ifndef SAGA_EVENTS_MOD_H
#define SAGA_EVENTS_MOD_H

namespace Saga {

enum R_EVENT_TYPES {

	R_ONESHOT_EVENT,
	R_CONTINUOUS_EVENT,
	R_INTERVAL_EVENT
};

enum R_EVENT_FLAGS {

	R_SIGNALED = 0x8000,
	R_NODESTROY = 0x4000
};

enum R_EVENT_CODES {

	R_BG_EVENT = 1,
	R_ANIM_EVENT,
	R_MUSIC_EVENT,
	R_VOICE_EVENT,
	R_SOUND_EVENT,
	R_SCENE_EVENT,
	R_TEXT_EVENT,
	R_PAL_EVENT,
	R_PALANIM_EVENT,
	R_TRANSITION_EVENT,
	R_INTERFACE_EVENT,
	R_CONSOLE_EVENT,
	R_ACTOR_EVENT
};

enum R_EVENT_OPS {

	/* INSTANTANEOUS events
	 * \*------------------------------------------------------------- */
	/* BG events */
	EVENT_DISPLAY = 1,
	/* ANIM events */
	EVENT_FRAME = 1,
	/* MUISC & SOUND events */
	EVENT_PLAY = 1,
	EVENT_STOP = 2,
	/* SCENE events */
	EVENT_END = 2,
	/* TEXT events */
	EVENT_HIDE = 2,
	EVENT_REMOVE = 3,
	/* PALANIM events */
	EVENT_CYCLESTART = 1,
	EVENT_CYCLESTEP = 2,
	/* INTERFACE events */
	EVENT_ACTIVATE = 1,
	EVENT_DEACTIVATE,
	/* ACTOR events */
	EVENT_MOVE = 1,

	/* CONTINUOUS events
	 * \*------------------------------------------------------------- */
	/* PALETTE events */
	EVENT_PALTOBLACK = 1,
	EVENT_BLACKTOPAL = 2,
	/* TRANSITION events */
	EVENT_DISSOLVE = 1
};

enum R_EVENT_PARAMS {

	NO_SET_PALETTE,
	SET_PALETTE
};

typedef struct R_EVENT_tag {

	unsigned int type;
	unsigned int code;	/* Event operation category & flags */
	int op;			/* Event operation */

	long param;		/* Optional event parameter */
	long param2;

	void *data;		/* Optional event data */

	long time;		/* Elapsed time until event */
	long duration;		/* Duration of event */
	long d_reserved;

	struct R_EVENT_tag *chain;	/* Event chain 
					 * (For consecutive events) */

} R_EVENT;

int EVENT_Init(void);

int EVENT_Shutdown(void);

int EVENT_HandleEvents(long msec);

int EVENT_ClearList(void);

int EVENT_FreeList(void);

R_EVENT *EVENT_Queue(R_EVENT * event);

R_EVENT *EVENT_Chain(R_EVENT * head_event, R_EVENT * add_event);

} // End of namespace Saga

#endif				/* R_EVENTS_MOD_H */

--- NEW FILE: expr.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/expr.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:   
 
    Expression parsing module, and string handling functions

 Notes: 

    EXPR_ParseArgs() lifted wholesale from SDL win32 initialization code by
    Sam Lantinga
*/

#include "reinherit.h"

/*
   Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "cvar_mod.h"

/*
   Begin module
\*--------------------------------------------------------------------------*/
#include "expr.h"

namespace Saga {

char *EXPR_ErrMsg[] = {

	"Invalid error state.",
	"No Error",
	"Memory allocation failed",
	"Illegal variable name",
	"Expected \'=\' or \'(\' in expression",
	"Expected \'(\' in function call",
	"Illegal \'(\', identifier is not function",
	"Expected a value to assign",
	"Unterminated string literal",
	"Unmatched parenthesis in function call",
	"Error reading value string",
	"Expected a number or boolean",
	"Unknown variable or function"
};

enum EXPR_Errors {

	EXERR_ASSERT,
	EXERR_NONE,
	EXERR_MEM,
	EXERR_ILLEGAL,
	EXERR_EXPR,
	EXERR_FUNC,
	EXERR_NOTFUNC,
	EXERR_RVALUE,
	EXERR_LITERAL,
	EXERR_PAREN,
	EXERR_STRING,
	EXERR_NUMBER,
	EXERR_NOTFOUND
};

static enum EXPR_Errors EXPR_ErrorState;

int EXPR_GetError(char **err_str)
/*--------------------------------------------------------------------------*\
 Returns the appropriate expression parser error string given an error code.
\*--------------------------------------------------------------------------*/
{

	*err_str = EXPR_ErrMsg[EXPR_ErrorState];

	return EXPR_ErrorState;
}

int
EXPR_Parse(const char **exp_pp, int *len, R_CVAR_P * expr_cvar, char **rvalue)
/*--------------------------------------------------------------------------*\
 Parses an interactive expression.
 Sets 'expr_cvar' to the cvar/cfunction identifier input by the user, and
 'rvalue' to the corresponding rvalue ( in an expression ) or argument string
 ( in a function call ).

 Memory pointed to by rvalue after return must be explicitly freed by the
 caller.
\*--------------------------------------------------------------------------*/
{

	int i;
	int in_char;
	int equ_offset;
	int rvalue_offset;

	char *lvalue_str;
	int lvalue_len;

	char *rvalue_str;
	int rvalue_len;

	const char *scan_p;
	int scan_len;

	const char *expr_p;
	int expr_len;
	int test_char = '\0';
	int have_func = 0;

	R_CVAR_P lvalue_cvar;

	expr_p = *exp_pp;
	expr_len = strlen(*exp_pp);

	scan_p = *exp_pp;
	scan_len = expr_len;

    /**lvalue = NULL;*/
	*rvalue = NULL;

	EXPR_ErrorState = EXERR_ASSERT;

	for (i = 0; i <= scan_len; i++, scan_p++) {

		in_char = *scan_p;

		if ((i == 0) && isdigit(in_char)) {
			/* First character of a valid identifier cannot be a digit */
			EXPR_ErrorState = EXERR_ILLEGAL;
			return R_FAILURE;
		}

		/* If we reach a character that isn't valid in an identifier... */
		if ((!isalnum(in_char)) && ((in_char != '_'))) {

			/* then eat remaining whitespace, if any */
			equ_offset = strspn(scan_p, R_EXPR_WHITESPACE);

			test_char = scan_p[equ_offset];
			/* and test for the only valid characters after an identifier */
			if ((test_char != '=') &&
			    (test_char != '\0') && (test_char != '(')) {

				if ((equ_offset == 0)
				    && ((scan_p - expr_p) != expr_len)) {
					EXPR_ErrorState = EXERR_ILLEGAL;
				} else {
					EXPR_ErrorState = EXERR_EXPR;
				}
				return R_FAILURE;
			}

			break;
		}
	}

	lvalue_len = (scan_p - expr_p);
	lvalue_str = (char *)malloc(lvalue_len + 1);

	if (lvalue_str == NULL) {
		EXPR_ErrorState = EXERR_MEM;
		return R_FAILURE;
	}

	strncpy(lvalue_str, expr_p, lvalue_len);
	lvalue_str[lvalue_len] = 0;

	/* We now have the lvalue, so attempt to find it */
	lvalue_cvar = CVAR_Find(lvalue_str);
	if (lvalue_cvar == NULL) {
		EXPR_ErrorState = EXERR_NOTFOUND;
		return R_FAILURE;
	}
	if (lvalue_str) {
		free(lvalue_str);
		lvalue_str = NULL;
	}

	/* Skip parsed character, if any */
	scan_p += equ_offset + 1;
	scan_len = (scan_p - expr_p);

	/* Check if the 'cvar' is really a function */
	have_func = CVAR_IsFunc(lvalue_cvar);

	if (test_char == '(') {

		if (have_func) {

			rvalue_str =
			    EXPR_ReadString(&scan_p, &rvalue_len, ')');
			if (rvalue_str != NULL) {
				/* Successfully read string */
				/*CON_Print( "Read function parameters \"%s\".", rvalue_str ); */
				*expr_cvar = lvalue_cvar;
				*rvalue = rvalue_str;

				scan_len = (scan_p - expr_p);

				*exp_pp = scan_p;
				*len -= scan_len;

				EXPR_ErrorState = EXERR_NONE;
				return R_SUCCESS;
			} else {
				EXPR_ErrorState = EXERR_PAREN;
				return R_FAILURE;
			}
		} else {
			EXPR_ErrorState = EXERR_NOTFUNC;
			return R_FAILURE;
		}

	}

	/* Eat more whitespace */
	rvalue_offset = strspn(scan_p, R_EXPR_WHITESPACE);

	if (rvalue_offset + i == expr_len) {
		/* Only found single lvalue */
		*expr_cvar = lvalue_cvar;
		*exp_pp = scan_p;
		*len -= scan_len;
		return R_SUCCESS;
	}

	scan_p += rvalue_offset;
	scan_len = (scan_p - expr_p) + 1;

	in_char = *scan_p;

	in_char = toupper(in_char);

	switch (in_char) {

	case '\"':
		scan_p++;
		scan_len--;
		rvalue_str = EXPR_ReadString(&scan_p, &rvalue_len, '\"');

		if (rvalue_str != NULL) {
			/* Successfully read string */
			break;
		} else {
			EXPR_ErrorState = EXERR_LITERAL;
			return R_FAILURE;
		}
		break;

#if 0
	case 'Y':		/* Y[es] */
	case 'T':		/* T[rue] */

		break;

	case 'N':		/* N[o] */
	case 'F':		/* F[alse] */

		break;
#endif

	default:

		if (isdigit(in_char) || (in_char == '-') || (in_char == '+')) {

			rvalue_str = EXPR_ReadString(&scan_p, &rvalue_len, 0);

			if (rvalue_str != NULL) {
				/* Successfully read string */
				break;
			} else {
				EXPR_ErrorState = EXERR_STRING;
				return R_FAILURE;
			}
		} else {
			EXPR_ErrorState = EXERR_NUMBER;
			return R_FAILURE;
		}

		break;

	}

	*expr_cvar = lvalue_cvar;
	*rvalue = rvalue_str;

	scan_len = (scan_p - expr_p);

	*exp_pp = scan_p;
	*len -= scan_len;

	EXPR_ErrorState = EXERR_NONE;
	return R_SUCCESS;

}

char *EXPR_ReadString(const char **string_p, int *len, int term_char)
/****************************************************************************\
 Reads in a string of characters from '*string_p' until 'term_char' is 
 encountered. If 'term_char' == 0, the function reads characters until
 whitespace is encountered. 
 Upon reading a string, the function modifies *string_p and len based on 
 the number of characters read.
\****************************************************************************/
{

	int string_len;
	char *str_p;
	char *term_p;

	const char *scan_p;
	int in_char;

	if (term_char > 0) {

		term_p = strchr(*string_p, term_char);

		if (term_p == NULL) {
			return NULL;
		}

		string_len = (int)(term_p - *string_p);

		str_p = (char *)malloc(string_len + 1);

		if (str_p == NULL) {
			return NULL;
		}

		strncpy(str_p, *string_p, string_len);
		str_p[string_len] = 0;

		*string_p += (string_len + 1);	/* Add 1 for terminating char */
		*len -= (string_len + 1);

	} else {

		scan_p = *string_p;
		string_len = 0;

		while (scan_p) {

			in_char = *scan_p++;

			if (!isspace(in_char)) {
				string_len++;
			} else if (string_len) {

			  str_p = (char *)malloc(string_len + 1);

				if (str_p == NULL) {
					return NULL;
				}

				strncpy(str_p, *string_p, string_len);
				str_p[string_len] = 0;

				*string_p += string_len;
				*len -= string_len;
				break;

			} else {
				return NULL;
			}
		}

	}

	return str_p;
}

int EXPR_GetArgs(char *cmd_str, char ***expr_argv)
/****************************************************************************\
 Parses the string 'cmd_str' into argc/argv format, returning argc.
 The resulting argv pointers point into the 'cmd_str' string, so any argv
 entries should not be used after cmd_str is deallocated.

 Memory pointed to by expr_argv must be explicitly freed by the caller.
\****************************************************************************/
{

	int expr_argc;

	expr_argc = EXPR_ParseArgs(cmd_str, NULL);
	*expr_argv = (char **)malloc((expr_argc + 1) * sizeof(**expr_argv));

	if (expr_argv == NULL) {
		return R_FAILURE;
	}

	EXPR_ParseArgs(cmd_str, *expr_argv);

	return expr_argc;

}

int EXPR_ParseArgs(char *cmd_str, char **argv)
{

	char *bufp;
	int argc;

	argc = 0;
	for (bufp = cmd_str; *bufp;) {
		/* Skip leading whitespace */
		while (isspace(*bufp)) {
			++bufp;
		}
		/* Skip over argument */
		if (*bufp == '"') {
			++bufp;
			if (*bufp) {
				if (argv) {
					argv[argc] = bufp;
				}
				++argc;
			}
			/* Skip over word */
			while (*bufp && (*bufp != '"')) {
				++bufp;
			}
		} else {
			if (*bufp) {
				if (argv) {
					argv[argc] = bufp;
				}
				++argc;
			}
			/* Skip over word */
			while (*bufp && !isspace(*bufp)) {
				++bufp;
			}
		}
		if (*bufp) {
			if (argv) {
				*bufp = '\0';
			}
			++bufp;
		}
	}
	if (argv) {
		argv[argc] = NULL;
	}
	return (argc);
}

} // End of namespace Saga

--- NEW FILE: expr.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/expr.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*
 Description:   
 
    Expression parsing module header file

 Notes: 
*/

#ifndef SAGA_EXPR_H_
#define SAGA_EXPR_H_

namespace Saga {

#define R_EXPR_WHITESPACE "\t\n "

int EXPR_ParseArgs(char *cmd_str, char **argv);

} // End of namespace Saga

#endif				/* R_EXPR_H_ */
/* end "r_expr.h" */

--- NEW FILE: font.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/font.cpp,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Font management and font drawing module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "rscfile_mod.h"
#include "game_mod.h"

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "font_mod.h"
#include "font.h"

namespace Saga {

static R_FONT_MODULE FontModule;

int FONT_Init(void)
{

	R_GAME_FONTDESC *gamefonts;
	int i;

	if (FontModule.init) {

		FontModule.err_str = "Font module already initialized.";

		return R_FAILURE;
	}

	/* Load font module resource context 
	 * \*------------------------------------------------------------ */
	if (GAME_GetFileContext(&FontModule.font_ctxt,
		R_GAME_RESOURCEFILE, 0) != R_SUCCESS) {

		FontModule.err_str = "Couldn't get resource context.";

		return R_FAILURE;
	}

	/* Allocate font table
	 * \*------------------------------------------------------------ */
	GAME_GetFontInfo(&gamefonts, &FontModule.n_fonts);

	assert(FontModule.n_fonts > 0);

	FontModule.fonts = (R_FONT **)malloc(FontModule.n_fonts *
	    sizeof *FontModule.fonts);
	if (FontModule.fonts == NULL) {

		FontModule.err_str = "Memory allocation failure.";

		return R_MEM;
	}

	for (i = 0; i < FontModule.n_fonts; i++) {

		FONT_Load(gamefonts[i].font_rn, gamefonts[i].font_id);
	}

	FontModule.init = 1;

	return R_SUCCESS;
}

int FONT_Shutdown(void)
{

	int i;

	R_printf(R_STDOUT, "FONT_Shutdown(): Freeing fonts.\n");
/*
    for ( i = 0 ; i < R_FONT_COUNT ; i ++ ) {

        if ( FontModule.fonts[i] != NULL ) {

            if ( FontModule.fonts[i]->normal_loaded ) {
                free( FontModule.fonts[i]->normal->font_free_p );
                free( FontModule.fonts[i]->normal );
            }

            if ( FontModule.fonts[i]->outline_loaded ) {
                free( FontModule.fonts[i]->outline->font_free_p );
                free( FontModule.fonts[i]->outline );
            }
        }

        free( FontModule.fonts[i] );
    }
*/
	return R_SUCCESS;
}

int FONT_Load(ulong font_rn, int font_id)
{

	R_FONT_HEADER fh;
	R_FONT *font;
	R_FONT_STYLE *normal_font;

	uchar *fontres_p;
	size_t fontres_len;
	size_t remain;

	const uchar *read_p;

	int nbits;
	int c;

	if ((font_id < 0) || (font_id >= FontModule.n_fonts)) {
		return R_FAILURE;
	}

	/* Load font resource
	 * \*------------------------------------------------------------- */
	if (RSC_LoadResource(FontModule.font_ctxt,
		font_rn, &fontres_p, &fontres_len) != R_SUCCESS) {

		FontModule.err_str = "Couldn't load font resource.";

		return R_FAILURE;
	}

	if (fontres_len < R_FONT_DESCSIZE) {

		FontModule.err_str = "Invalid font length.";
	}

	read_p = fontres_p;
	remain = fontres_len;

	/* Create new font structure
	 * \*------------------------------------------------------------- */
	font = (R_FONT *)malloc(sizeof *font);
	if (font == NULL) {
		FontModule.err_str = "Memory allocation error.";

		return R_MEM;
	}

	/* Read font header
	 * \*------------------------------------------------------------- */
	fh.c_height = ys_read_u16_le(read_p, &read_p);
	fh.c_width = ys_read_u16_le(read_p, &read_p);
	fh.row_length = ys_read_u16_le(read_p, &read_p);

#if R_FONT_DBGLVL >= R_DEBUG_INFO
	R_printf(R_STDOUT, "FONT_Load(): Reading font resource...\n");
#endif

#if R_FONT_DBGLVL >= R_DEBUG_VERBOSE
	R_printf(R_STDOUT, "Character width:\t%d\n", fh.c_width);
	R_printf(R_STDOUT, "Character height:\t%d\n", fh.c_height);
	R_printf(R_STDOUT, "Row padding:\t%d\n", fh.row_length);
#endif

	/* Create normal font style
	 * \*------------------------------------------------------------- */
	normal_font = (R_FONT_STYLE *)malloc(sizeof *normal_font);
	if (normal_font == NULL) {

		FontModule.err_str = "Memory allocation error.";
		free(font);

		return R_MEM;
	}

	normal_font->font_free_p = fontres_p;
	normal_font->hdr.c_height = fh.c_height;
	normal_font->hdr.c_width = fh.c_width;
	normal_font->hdr.row_length = fh.row_length;

	for (c = 0; c < R_FONT_CHARCOUNT; c++) {
		normal_font->fce[c].index = ys_read_u16_le(read_p, &read_p);
	}

	for (c = 0; c < R_FONT_CHARCOUNT; c++) {
		nbits = normal_font->fce[c].width =
		    ys_read_u8(read_p, &read_p);
		normal_font->fce[c].byte_width = GetByteLen(nbits);
	}

	for (c = 0; c < R_FONT_CHARCOUNT; c++) {
		normal_font->fce[c].flag = ys_read_u8(read_p, &read_p);
	}

	for (c = 0; c < R_FONT_CHARCOUNT; c++) {
		normal_font->fce[c].tracking = ys_read_u8(read_p, &read_p);
	}

	if ((read_p - fontres_p) != R_FONT_DESCSIZE) {

		R_printf(R_STDERR, "Invalid font resource size.\n");
		return R_FAILURE;
	}

	normal_font->font_p = (uchar *) read_p;

	font->normal = normal_font;
	font->normal_loaded = 1;

	/* Create outline font style
	 * \*------------------------------------------------------------- */
	font->outline = FONT_CreateOutline(normal_font);
	font->outline_loaded = 1;

	/* Set font data 
	 * \*------------------------------------------------------------- */

	FontModule.fonts[font_id] = font;

	return R_SUCCESS;
}

int FONT_GetHeight(int font_id)
{

	R_FONT *font;

	if (!FontModule.init) {
		return R_FAILURE;
	}

	if ((font_id < 0) ||
	    (font_id >= FontModule.n_fonts) ||
	    (FontModule.fonts[font_id] == NULL)) {

		FontModule.err_str = "Invalid font id.";

		return R_FAILURE;
	}

	font = FontModule.fonts[font_id];

	return font->normal->hdr.c_height;
}

static R_FONT_STYLE *FONT_CreateOutline(R_FONT_STYLE * src_font)
{

	R_FONT_STYLE *new_font;
	unsigned char *new_font_data;
	size_t new_font_data_len;

	int s_width = src_font->hdr.c_width;
	int s_height = src_font->hdr.c_height;

	int new_row_len = 0;
	int row;
	int i;

	int index;
	size_t index_offset = 0;

	int new_byte_width;
	int old_byte_width;

	int current_byte;

	unsigned char *base_ptr;
	unsigned char *src_ptr;
	unsigned char *dest_ptr1;
	unsigned char *dest_ptr2;
	unsigned char *dest_ptr3;

	unsigned char c_rep;

	/* Create new font style structure
	 * \*------------------------------------------------------------- */
	new_font = (R_FONT_STYLE *)malloc(sizeof *new_font);

	if (new_font == NULL) {
		FontModule.err_str = "Memory allocation error.";

		return NULL;
	}

	memset(new_font, 0, sizeof *new_font);

	/* Populate new font style character data 
	 * \*------------------------------------------------------------- */
	for (i = 0; i < R_FONT_CHARCOUNT; i++) {

		new_byte_width = 0;
		old_byte_width = 0;

		index = src_font->fce[i].index;
		if ((index > 0) || (i == R_FONT_FIRSTCHAR)) {
			index += index_offset;
		}

		new_font->fce[i].index = index;
		new_font->fce[i].tracking = src_font->fce[i].tracking;
		new_font->fce[i].flag = src_font->fce[i].flag;

		if (src_font->fce[i].width != 0) {

			new_byte_width =
			    GetByteLen(src_font->fce[i].width + 2);
			old_byte_width = GetByteLen(src_font->fce[i].width);

			if (new_byte_width > old_byte_width) {
				index_offset++;
			}
		}

		new_font->fce[i].width = src_font->fce[i].width + 2;
		new_font->fce[i].byte_width = new_byte_width;
		new_row_len += new_byte_width;
	}

#if R_FONT_DBGLVL >= R_DEBUG_VERBOSE
	R_printf(R_STDOUT, "New row length: %d\n", new_row_len);
#endif

	new_font->hdr.c_width = s_width + 2;
	new_font->hdr.c_height = s_height + 2;
	new_font->hdr.row_length = new_row_len;

	/* Allocate new font representation storage 
	 * \*------------------------------------------------------------- */
	new_font_data_len = new_row_len * (s_height + 2);
	new_font_data = (unsigned char *)malloc(new_font_data_len);

	if (new_font_data == NULL) {
		FontModule.err_str = "Memory allocation error.";

		return NULL;
	}

	memset(new_font_data, 0, new_font_data_len);

	new_font->font_free_p = new_font_data;
	new_font->font_p = new_font_data;

	/* Generate outline font representation
	 * \*------------------------------------------------------------- */
	for (i = 0; i < R_FONT_CHARCOUNT; i++) {

		for (row = 0; row < s_height; row++) {

			for (current_byte = 0;
			    current_byte < new_font->fce[i].byte_width;
			    current_byte++) {

				base_ptr =
				    new_font->font_p + new_font->fce[i].index +
				    current_byte;

				dest_ptr1 =
				    base_ptr + new_font->hdr.row_length * row;
				dest_ptr2 =
				    base_ptr +
				    new_font->hdr.row_length * (row + 1);
				dest_ptr3 =
				    base_ptr +
				    new_font->hdr.row_length * (row + 2);

				if (current_byte > 0) {

					/* Get last two columns from previous byte */
					src_ptr = src_font->font_p +
					    src_font->hdr.row_length * row +
					    src_font->fce[i].index +
					    (current_byte - 1);

					c_rep = *src_ptr;
					*dest_ptr1 |=
					    ((c_rep << 6) | (c_rep << 7));
					*dest_ptr2 |=
					    ((c_rep << 6) | (c_rep << 7));
					*dest_ptr3 |=
					    ((c_rep << 6) | (c_rep << 7));
				}

				if (current_byte < src_font->fce[i].byte_width) {

					src_ptr = src_font->font_p +
					    src_font->hdr.row_length * row +
					    src_font->fce[i].index +
					    current_byte;

					c_rep = *src_ptr;
					*dest_ptr1 |=
					    c_rep | (c_rep >> 1) | (c_rep >>
					    2);
					*dest_ptr2 |=
					    c_rep | (c_rep >> 1) | (c_rep >>
					    2);
					*dest_ptr3 |=
					    c_rep | (c_rep >> 1) | (c_rep >>
					    2);
				}
			}
		}

		/* "Hollow out" character to prevent overdraw */
		for (row = 0; row < s_height; row++) {

			for (current_byte = 0;
			    current_byte < new_font->fce[i].byte_width;
			    current_byte++) {

				dest_ptr2 = new_font->font_p +
				    new_font->hdr.row_length * (row + 1) +
				    new_font->fce[i].index + current_byte;

				if (current_byte > 0) {

					/* Get last two columns from previous byte */
					src_ptr = src_font->font_p +
					    src_font->hdr.row_length * row +
					    src_font->fce[i].index +
					    (current_byte - 1);

					*dest_ptr2 &=
					    ((*src_ptr << 7) ^ 0xFFU);
				}

				if (current_byte < src_font->fce[i].byte_width) {

					src_ptr = src_font->font_p +
					    src_font->hdr.row_length * row +
					    src_font->fce[i].index +
					    current_byte;

					*dest_ptr2 &=
					    ((*src_ptr >> 1) ^ 0xFFU);
				}
			}
		}
	}

	return new_font;

}

static int GetByteLen(int num_bits)
{

	int byte_len;

	byte_len = num_bits / 8;

	if (num_bits % 8) {
		byte_len++;
	}

	return byte_len;
}

int
FONT_GetStringWidth(int font_id,
    const char *test_str, size_t test_str_ct, int flags)
/*--------------------------------------------------------------------------*\
 * Returns the horizontal length in pixels of the graphical representation
 *  of at most 'test_str_ct' characters of the string 'test_str', taking
 *  into account any formatting options specified by 'flags'.
 * If 'test_str_ct' is 0, all characters of 'test_str' are counted.
\*--------------------------------------------------------------------------*/
{

	R_FONT *font;
	size_t ct;
	int width = 0;
	int ch;
	uchar *txt_p;

	if (!FontModule.init) {
		return R_FAILURE;
	}

	if ((font_id < 0) ||
	    (font_id >= FontModule.n_fonts) ||
	    (FontModule.fonts[font_id] == NULL)) {

		FontModule.err_str = "Invalid font id.";

		return R_FAILURE;
	}

	font = FontModule.fonts[font_id];
	assert(font != NULL);

	txt_p = (uchar *) test_str;

	for (ct = test_str_ct;
	    *txt_p && (!test_str_ct || ct > 0); txt_p++, ct--) {

		ch = *txt_p & 0xFFU;

		/* Translate character */
		ch = CharMap[ch];
		assert(ch < R_FONT_CHARCOUNT);

		width += font->normal->fce[ch].tracking;
	}

	if ((flags & FONT_BOLD) || (flags & FONT_OUTLINE)) {
		width += 1;
	}

	return width;
}

int
FONT_Draw(int font_id,
    R_SURFACE * ds,
    const char *draw_str,
    size_t draw_str_ct,
    int text_x, int text_y, int color, int effect_color, int flags)
{

	R_FONT *font;

	if (!FontModule.init) {
		FontModule.err_str = "Font Module not initialized.";

		return R_FAILURE;
	}

	if ((font_id < 0) ||
	    (font_id >= FontModule.n_fonts) ||
	    (FontModule.fonts[font_id] == NULL)) {

		FontModule.err_str = "Invalid font id.";

		return R_FAILURE;
	}

	font = FontModule.fonts[font_id];

	if (flags & FONT_OUTLINE) {

		FONT_Out(font->outline,
		    ds,
		    draw_str,
		    draw_str_ct, text_x - 1, text_y - 1, effect_color);

		FONT_Out(font->normal,
		    ds, draw_str, draw_str_ct, text_x, text_y, color);
	} else if (flags & FONT_SHADOW) {

		FONT_Out(font->normal,
		    ds,
		    draw_str,
		    draw_str_ct, text_x - 1, text_y + 1, effect_color);

		FONT_Out(font->normal,
		    ds, draw_str, draw_str_ct, text_x, text_y, color);
	} else {		/* FONT_NORMAL */

		FONT_Out(font->normal,
		    ds, draw_str, draw_str_ct, text_x, text_y, color);
	}

	return R_SUCCESS;
}

int
FONT_Out(R_FONT_STYLE * draw_font,
    R_SURFACE * ds,
    const char *draw_str,
    size_t draw_str_ct, int text_x, int text_y, int color)
{

	const uchar *draw_str_p;

	uchar *c_data_ptr;
	int c_code;

	int char_row;

	uchar *output_ptr;
	uchar *output_ptr_min;
	uchar *output_ptr_max;

	int row;
	int row_limit;

	int c_byte_len;
	int c_byte;
	int c_bit;

	int ct;

	if ((text_x > ds->buf_w) || (text_y > ds->buf_h)) {
		/* Output string can't be visible */
		return R_SUCCESS;
	}

	draw_str_p = (uchar *) draw_str;
	ct = draw_str_ct;

	/* Draw string one character at a time, maximum of 'draw_str'_ct 
	 * characters, or no limit if 'draw_str_ct' is 0 */
	for (; *draw_str_p && (!draw_str_ct || ct); draw_str_p++, ct--) {

		c_code = *draw_str_p & 0xFFU;

		/* Translate character */
		c_code = CharMap[c_code];
		assert(c_code < R_FONT_CHARCOUNT);

		/* Check if character is defined */
		if ((draw_font->fce[c_code].index == 0) &&
		    (c_code != R_FONT_FIRSTCHAR)) {

#           if R_FONT_SHOWUNDEFINED

			if (c_code == R_FONT_CH_SPACE) {
				text_x += draw_font->fce[c_code].tracking;
				continue;
			}
			c_code = R_FONT_CH_QMARK;

#           else

			/* Character code is not defined, but advance tracking
			 * ( Not defined if offset is 0, except for 33 ('!') which
			 *   is defined ) */
			text_x += draw_font->fce[c_code].tracking;
			continue;

#endif
		}

		/* Get length of character in bytes */
		c_byte_len = ((draw_font->fce[c_code].width - 1) / 8) + 1;

		row_limit = (ds->buf_h < (text_y + draw_font->hdr.c_height))
		    ? ds->buf_h : text_y + draw_font->hdr.c_height;

		char_row = 0;

		for (row = text_y; row < row_limit; row++, char_row++) {

			/* Clip negative rows */
			if (row < 0) {
				continue;
			}

			output_ptr = ds->buf + (ds->buf_pitch * row) + text_x;

			output_ptr_min = ds->buf + (ds->buf_pitch * row) +
			    (text_x > 0 ? text_x : 0);

			output_ptr_max = output_ptr + (ds->buf_pitch - text_x);

			/* If character starts off the screen, jump to next character */
			if (output_ptr < output_ptr_min) {
				break;
			}

			c_data_ptr = draw_font->font_p +
			    char_row * draw_font->hdr.row_length +
			    draw_font->fce[c_code].index;

			for (c_byte = 0; c_byte < c_byte_len;
			    c_byte++, c_data_ptr++) {

				/* Check each bit, draw pixel if bit is set */
				for (c_bit = 7;
				    c_bit >= 0
				    && (output_ptr < output_ptr_max);
				    c_bit--) {

					if ((*c_data_ptr >> c_bit) & 0x01) {
						*output_ptr = (uchar) color;
					}
					output_ptr++;

				}	/* end per-bit processing */

			}	/* end per-byte processing */

		}		/* end per-row processing */

		/* Advance tracking position */
		text_x += draw_font->fce[c_code].tracking;

	}			/* end per-character processing */

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: font.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/font.h,v 1.1 2004/04/12 21:40:46 sev Exp $
 *
 */
/*

 Description:   
 
    Font management and font drawing header file

 Notes: 
*/

#ifndef SAGA_FONT_H__
#define SAGA_FONT_H__

namespace Saga {

#define R_FONT_DBGLVL R_DEBUG_NONE

#define R_FONT_SHOWUNDEFINED 1	/* Define to draw undefined characters 
				 * as ?'s */

/* The first defined character (!) is the only one that may 
   have a valid offset of '0' */
#define R_FONT_FIRSTCHAR 33

#define R_FONT_CH_SPACE 32
#define R_FONT_CH_QMARK 63

/* Minimum font header size without font data 
   (6 + 512 + 256 + 256 + 256 ) */
#define R_FONT_DESCSIZE 1286

#define R_FONT_CHARCOUNT 256
#define R_FONT_CHARMASK 0xFFU

#define SAGA_FONT_HEADER_LEN 6

typedef struct R_FONT_HEADER_tag {

	int c_height;
	int c_width;
	int row_length;

} R_FONT_HEADER;

typedef struct FONT_CHAR_ENTRY_TAG {

	int index;
	int byte_width;
	int width;
	int flag;
	int tracking;

} FONT_CHAR_ENTRY;

typedef struct R_FONT_STYLE_tag {

	R_FONT_HEADER hdr;
	FONT_CHAR_ENTRY fce[256];

	uchar *font_free_p;
	uchar *font_p;

} R_FONT_STYLE;

typedef struct R_FONT_tag {

	ulong font_rn;
	int font_id;

	int normal_loaded;
	R_FONT_STYLE *normal;
	int outline_loaded;
	R_FONT_STYLE *outline;

	uchar *res_data;
	size_t res_len;

} R_FONT;

typedef struct R_FONT_MODULE_tag {

	int init;

	R_RSCFILE_CONTEXT *font_ctxt;

	int n_fonts;
	R_FONT **fonts;

	int err_n;
	const char *err_str;

} R_FONT_MODULE;

int FONT_Load(ulong font_rn, int font_id);

static R_FONT_STYLE *FONT_CreateOutline(R_FONT_STYLE * src_font);

int
FONT_Out(R_FONT_STYLE * font,
    R_SURFACE * ds,
    const char *draw_str,
    size_t draw_str_ct, int text_x, int text_y, int color);

static int GetByteLen(int num_bits);

extern int CharMap[];

} // End of namespace Saga

#endif				/* R_FONT_H__ */
/* end "r_font.h" */

--- NEW FILE: font_map.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/font_map.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Font module character mapping table ( MS CP-850 to ISO 8859-1 )

 Notes: 

    Translation table derived from http://www.kostis.net/charsets/
*/

namespace Saga {

int CharMap[] = {
	0,			/*   0 */
	1,			/*   1 */
	2,			/*   2 */
	3,			/*   3 */
	4,			/*   4 */
	5,			/*   5 */
	6,			/*   6 */
	7,			/*   7 */
	8,			/*   8 */
	9,			/*   9 */
	10,			/*  10 */
	11,			/*  11 */
	12,			/*  12 */
	13,			/*  13 */
	14,			/*  14 */
	15,			/*  15 */
	16,			/*  16 */
	17,			/*  17 */
	18,			/*  18 */
	19,			/*  19 */
	20,			/*  20 */
	21,			/*  21 */
	22,			/*  22 */
	23,			/*  23 */
	24,			/*  24 */
	25,			/*  25 */
	26,			/*  26 */
	27,			/*  27 */
	28,			/*  28 */
	29,			/*  29 */
	30,			/*  30 */
	31,			/*  31 */
	32,			/*  32 */
	33,			/*  33 */
	34,			/*  34 */
	35,			/*  35 */
	36,			/*  36 */
	37,			/*  37 */
	38,			/*  38 */
	39,			/*  39 */
	40,			/*  40 */
	41,			/*  41 */
	42,			/*  42 */
	43,			/*  43 */
	44,			/*  44 */
	45,			/*  45 */
	46,			/*  46 */
	47,			/*  47 */
	48,			/*  48 */
	49,			/*  49 */
	50,			/*  50 */
	51,			/*  51 */
	52,			/*  52 */
	53,			/*  53 */
	54,			/*  54 */
	55,			/*  55 */
	56,			/*  56 */
	57,			/*  57 */
	58,			/*  58 */
	59,			/*  59 */
	60,			/*  60 */
	61,			/*  61 */
	62,			/*  62 */
	63,			/*  63 */
	64,			/*  64 */
	65,			/*  65 */
	66,			/*  66 */
	67,			/*  67 */
	68,			/*  68 */
	69,			/*  69 */
	70,			/*  70 */
	71,			/*  71 */
	72,			/*  72 */
	73,			/*  73 */
	74,			/*  74 */
	75,			/*  75 */
	76,			/*  76 */
	77,			/*  77 */
	78,			/*  78 */
	79,			/*  79 */
	80,			/*  80 */
	81,			/*  81 */
	82,			/*  82 */
	83,			/*  83 */
	84,			/*  84 */
	85,			/*  85 */
	86,			/*  86 */
	87,			/*  87 */
	88,			/*  88 */
	89,			/*  89 */
	90,			/*  90 */
	91,			/*  91 */
	92,			/*  92 */
	93,			/*  93 */
	94,			/*  94 */
	95,			/*  95 */
	96,			/*  96 */
	97,			/*  97 */
	98,			/*  98 */
	99,			/*  99 */
	100,			/* 100 */
	101,			/* 101 */
	102,			/* 102 */
	103,			/* 103 */
	104,			/* 104 */
	105,			/* 105 */
	106,			/* 106 */
	107,			/* 107 */
	108,			/* 108 */
	109,			/* 109 */
	110,			/* 110 */
	111,			/* 111 */
	112,			/* 112 */
	113,			/* 113 */
	114,			/* 114 */
	115,			/* 115 */
	116,			/* 116 */
	117,			/* 117 */
	118,			/* 118 */
	119,			/* 119 */
	120,			/* 120 */
	121,			/* 121 */
	122,			/* 122 */
	123,			/* 123 */
	124,			/* 124 */
	125,			/* 125 */
	126,			/* 126 */
	127,			/* 127 */
	199,			/* 128 LATIN CAPITAL LETTER C WITH CEDILLA */
	252,			/* 129 LATIN SMALL LETTER U WITH DIAERESIS */
	233,			/* 130 LATIN SMALL LETTER E WITH ACUTE */
	226,			/* 131 LATIN SMALL LETTER A WITH CIRCUMFLEX */
	228,			/* 132 LATIN SMALL LETTER A WITH DIAERESIS */
	224,			/* 133 LATIN SMALL LETTER A WITH GRAVE */
	229,			/* 134 LATIN SMALL LETTER A WITH RING ABOVE */
	231,			/* 135 LATIN SMALL LETTER C WITH CEDILLA */
	234,			/* 136 LATIN SMALL LETTER E WITH CIRCUMFLEX */
	235,			/* 137 LATIN SMALL LETTER E WITH DIAERESIS */
	232,			/* 138 LATIN SMALL LETTER E WITH GRAVE */
	239,			/* 139 LATIN SMALL LETTER I WITH DIAERESIS */
	238,			/* 140 LATIN SMALL LETTER I WITH CIRCUMFLEX */
	236,			/* 141 LATIN SMALL LETTER I WITH GRAVE */
	196,			/* 142 LATIN CAPITAL LETTER A WITH DIAERESIS */
	197,			/* 143 LATIN CAPITAL LETTER A WITH RING ABOVE */
	201,			/* 144 LATIN CAPITAL LETTER E WITH ACUTE */
	230,			/* 145 LATIN SMALL LETTER AE */
	198,			/* 146 LATIN CAPITAL LETTER AE */
	244,			/* 147 LATIN SMALL LETTER O WITH CIRCUMFLEX */
	246,			/* 148 LATIN SMALL LETTER O WITH DIAERESIS */
	242,			/* 149 LATIN SMALL LETTER O WITH GRAVE */
	251,			/* 150 LATIN SMALL LETTER U WITH CIRCUMFLEX */
	249,			/* 151 LATIN SMALL LETTER U WITH GRAVE */
	255,			/* 152 LATIN SMALL LETTER Y WITH DIAERESIS */
	214,			/* 153 LATIN CAPITAL LETTER O WITH DIAERESIS */
	220,			/* 154 LATIN CAPITAL LETTER U WITH DIAERESIS */
	248,			/* 155 LATIN SMALL LETTER O WITH STROKE */
	163,			/* 156 POUND SIGN */
	216,			/* 157 LATIN CAPITAL LETTER O WITH STROKE */
	215,			/* 158 MULTIPLICATION SIGN */
	0,			/* 159 LATIN SMALL LETTER F WITH HOOK */
	225,			/* 160 LATIN SMALL LETTER A WITH ACUTE */
	237,			/* 161 LATIN SMALL LETTER I WITH ACUTE */
	243,			/* 162 LATIN SMALL LETTER O WITH ACUTE */
	250,			/* 163 LATIN SMALL LETTER U WITH ACUTE */
	241,			/* 164 LATIN SMALL LETTER N WITH TILDE */
	209,			/* 165 LATIN CAPITAL LETTER N WITH TILDE */
	170,			/* 166 FEMININE ORDINAL INDICATOR */
	186,			/* 167 MASCULINE ORDINAL INDICATOR */
	191,			/* 168 INVERTED QUESTION MARK */
	174,			/* 169 REGISTERED SIGN */
	172,			/* 170 NOT SIGN */
	189,			/* 171 VULGAR FRACTION ONE HALF */
	188,			/* 172 VULGAR FRACTION ONE QUARTER */
	161,			/* 173 INVERTED EXCLAMATION MARK */
	171,			/* 174 LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
	187,			/* 175 RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
	0,			/* 176 LIGHT SHADE */
	0,			/* 177 MEDIUM SHADE */
	0,			/* 178 DARK SHADE */
	0,			/* 179 BOX DRAWINGS LIGHT VERTICAL */
	0,			/* 180 BOX DRAWINGS LIGHT VERTICAL AND LEFT */
	193,			/* 181 LATIN CAPITAL LETTER A WITH ACUTE */
	194,			/* 182 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
	192,			/* 183 LATIN CAPITAL LETTER A WITH GRAVE */
	169,			/* 184 COPYRIGHT SIGN */
	0,			/* 185 BOX DRAWINGS DOUBLE VERTICAL AND LEFT */
	0,			/* 186 BOX DRAWINGS DOUBLE VERTICAL */
	0,			/* 187 BOX DRAWINGS DOUBLE DOWN AND LEFT */
	0,			/* 188 BOX DRAWINGS DOUBLE UP AND LEFT */
	162,			/* 189 CENT SIGN */
	165,			/* 190 YEN SIGN */
	0,			/* 191 BOX DRAWINGS LIGHT DOWN AND LEFT */
	0,			/* 192 BOX DRAWINGS LIGHT UP AND RIGHT */
	0,			/* 193 BOX DRAWINGS LIGHT UP AND HORIZONTAL */
	0,			/* 194 BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
	0,			/* 195 BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
	0,			/* 196 BOX DRAWINGS LIGHT HORIZONTAL */
	0,			/* 197 BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
	227,			/* 198 LATIN SMALL LETTER A WITH TILDE */
	195,			/* 199 LATIN CAPITAL LETTER A WITH TILDE */
	0,			/* 200 BOX DRAWINGS DOUBLE UP AND RIGHT */
	0,			/* 201 BOX DRAWINGS DOUBLE DOWN AND RIGHT */
	0,			/* 202 BOX DRAWINGS DOUBLE UP AND HORIZONTAL */
	0,			/* 203 BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL */
	0,			/* 204 BOX DRAWINGS DOUBLE VERTICAL AND RIGHT */
	0,			/* 205 BOX DRAWINGS DOUBLE HORIZONTAL */
	0,			/* 206 BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL */
	164,			/* 207 CURRENCY SIGN */
	240,			/* 208 LATIN SMALL LETTER ETH */
	208,			/* 209 LATIN CAPITAL LETTER ETH */
	202,			/* 210 LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
	203,			/* 211 LATIN CAPITAL LETTER E WITH DIAERESIS */
	200,			/* 212 LATIN CAPITAL LETTER E WITH GRAVE */
	305,			/* 213 LATIN SMALL LETTER DOTLESS I */
	205,			/* 214 LATIN CAPITAL LETTER I WITH ACUTE */
	206,			/* 215 LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
	207,			/* 216 LATIN CAPITAL LETTER I WITH DIAERESIS */
	0,			/* 217 BOX DRAWINGS LIGHT UP AND LEFT */
	0,			/* 218 BOX DRAWINGS LIGHT DOWN AND RIGHT */
	0,			/* 219 FULL BLOCK */
	0,			/* 220 LOWER HALF BLOCK */
	166,			/* 221 BROKEN BAR */
	204,			/* 222 LATIN CAPITAL LETTER I WITH GRAVE */
	0,			/* 223 UPPER HALF BLOCK */
	211,			/* 224 LATIN CAPITAL LETTER O WITH ACUTE */
	223,			/* 225 LATIN SMALL LETTER SHARP S */
	212,			/* 226 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
	210,			/* 227 LATIN CAPITAL LETTER O WITH GRAVE */
	245,			/* 228 LATIN SMALL LETTER O WITH TILDE */
	213,			/* 229 LATIN CAPITAL LETTER O WITH TILDE */
	181,			/* 230 MICRO SIGN */
	254,			/* 231 LATIN SMALL LETTER THORN */
	222,			/* 232 LATIN CAPITAL LETTER THORN */
	218,			/* 233 LATIN CAPITAL LETTER U WITH ACUTE */
	219,			/* 234 LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
	217,			/* 235 LATIN CAPITAL LETTER U WITH GRAVE */
	253,			/* 236 LATIN SMALL LETTER Y WITH ACUTE */
	221,			/* 237 LATIN CAPITAL LETTER Y WITH ACUTE */
	175,			/* 238 MACRON */
	180,			/* 239 ACUTE ACCENT */
	173,			/* 240 SOFT HYPHEN */
	177,			/* 241 PLUS-MINUS SIGN */
	0,			/* 242 DOUBLE LOW LINE */
	190,			/* 243 VULGAR FRACTION THREE QUARTERS */
	182,			/* 244 PILCROW SIGN */
	167,			/* 245 SECTION SIGN */
	247,			/* 246 DIVISION SIGN */
	184,			/* 247 CEDILLA */
	176,			/* 248 DEGREE SIGN */
	168,			/* 249 DIAERESIS */
	183,			/* 250 MIDDLE DOT */
	185,			/* 251 SUPERSCRIPT ONE */
	179,			/* 252 SUPERSCRIPT THREE */
	178,			/* 253 SUPERSCRIPT TWO */
	0,			/* 254 BLACK SQUARE */
	160			/* 255 NO-BREAK SPACE */
};

} // End of namespace Saga

--- NEW FILE: font_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/font_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Font management and font drawing module public header

 Notes: 
*/

#ifndef SAGA_FONT_MOD_H_
#define SAGA_FONT_MOD_H_

namespace Saga {

enum FONT_ID {

	SMALL_FONT_ID,
	MEDIUM_FONT_ID,
	BIG_FONT_ID
};

enum FONT_EFFECT_FLAGS {

	FONT_NORMAL = 0x00,
	FONT_OUTLINE = 0x01,
	FONT_SHADOW = 0x02,
	FONT_BOLD = 0x04,
	FONT_CENTERED = 0x08
};

int FONT_Init(void);

int FONT_Shutdown(void);

int FONT_Draw(int font_id,
    R_SURFACE * ds,
    const char *draw_str,
    size_t draw_str_len,
    int text_x, int text_y, int color, int effect_color, int flags);

int FONT_GetStringWidth(int font_id,
    const char *test_str, size_t test_str_ct, int flags);

int FONT_GetHeight(int font_id);

} // End of namespace Saga

#endif				/* R_FONT_MOD_H_ */
/* end "r_font_mod.h" */

--- NEW FILE: game.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/game.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Game detection, general game parameters

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "rscfile_mod.h"
#include "cvar_mod.h"
#include "ite_introproc_mod.h"
#include "interface_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "game_mod.h"
#include "game.h"

namespace Saga {

/*--------------------------------------------------------------------------*\
 * Inherit the Earth - Demo version
\*--------------------------------------------------------------------------*/

R_GAME_FILEDESC ITEDEMO_GameFiles[] = {

	{"ITE.RSC", R_GAME_RESOURCEFILE}
	,
	{"ITE.DMO", R_GAME_DEMOFILE}
	,
	{"SCRIPTS.RSC", R_GAME_SCRIPTFILE}
	,
	{"VOICES.RSC", R_GAME_SOUNDFILE | R_GAME_VOICEFILE}
};

R_GAME_FONTDESC ITEDEMO_GameFonts[] = {

	{R_GAME_FONT_SMALL, 0}
	,
	{R_GAME_FONT_MEDIUM, 1}
};

R_GAME_SOUNDINFO ITEDEMO_GameSound = {

	R_GAME_SOUND_VOC
};

/*--------------------------------------------------------------------------*\
 * Inherit the Earth - Diskette version
\*--------------------------------------------------------------------------*/

R_GAME_FILEDESC ITEDISK_GameFiles[] = {

	{"ITE.RSC", R_GAME_RESOURCEFILE}
	,
	{"SCRIPTS.RSC", R_GAME_SCRIPTFILE}
	,
	{"VOICES.RSC", R_GAME_SOUNDFILE | R_GAME_VOICEFILE}
};

R_GAME_FONTDESC ITEDISK_GameFonts[] = {

	{R_GAME_FONT_MEDIUM, 0}
	,
	{R_GAME_FONT_LARGE, 1}
	,
	{R_GAME_FONT_SMALL, 2}
};

R_GAME_RESOURCEDESC ITE_Resources = {
	ITE_SCENE_LUT,		/* Scene lookup table RN */
	ITE_SCRIPT_LUT,		/* Script lookup table RN */

	ITE_COMMAND_PANEL,
	ITE_DIALOGUE_PANEL
};

R_GAME_SOUNDINFO ITE_GameSound = {

	R_GAME_SOUND_VOC
};

/*--------------------------------------------------------------------------*\
 * Inherit the Earth - CD Enhanced version
\*--------------------------------------------------------------------------*/

R_GAME_FILEDESC ITECD_GameFiles[] = {

	{"ITE.RSC", R_GAME_RESOURCEFILE}
	,
	{"SCRIPTS.RSC", R_GAME_SCRIPTFILE}
	,
	{"SOUNDS.RSC", R_GAME_SOUNDFILE}
	,
	{"VOICES.RSC", R_GAME_VOICEFILE}
};

R_GAME_FONTDESC ITECD_GameFonts[] = {

	{R_GAME_FONT_MEDIUM, 0}
	,
	{R_GAME_FONT_LARGE, 1}
	,
	{R_GAME_FONT_SMALL, 2}
};

R_GAME_SOUNDINFO ITECD_GameSound = {

	R_GAME_SOUND_PCM,
	22050,
	16,
	0
};

/*--------------------------------------------------------------------------*\
 * I Have No Mouth and I Must Scream - Demo version
\*--------------------------------------------------------------------------*/

R_GAME_FILEDESC IHNMDEMO_GameFiles[] = {

	{"SCREAM.RES", R_GAME_RESOURCEFILE}
	,
	{"SCRIPTS.RES", R_GAME_SCRIPTFILE}
	,
	{"SFX.RES", R_GAME_SOUNDFILE}
	,
	{"VOICESD.RES", R_GAME_VOICEFILE}
};

/*--------------------------------------------------------------------------*\
 * I Have No Mouth and I Must Scream - Retail CD version
\*--------------------------------------------------------------------------*/

R_GAME_FILEDESC IHNMCD_GameFiles[] = {

	{"MUSICFM.RES", R_GAME_MUSICFILE}
	,
	{"MUSICGM.RES", R_GAME_MUSICFILE}
	,
	{"SCREAM.RES", R_GAME_RESOURCEFILE}
	,
	{"SCRIPTS.RES", R_GAME_SCRIPTFILE}
	,
	{"SFX.RES", R_GAME_SOUNDFILE}
	,
	{"VOICES1.RES", R_GAME_VOICEFILE}
	,
	{"VOICES2.RES", R_GAME_VOICEFILE}
	,
	{"VOICES3.RES", R_GAME_VOICEFILE}
	,
	{"VOICES4.RES", R_GAME_VOICEFILE}
	,
	{"VOICES5.RES", R_GAME_VOICEFILE}
	,
	{"VOICES6.RES", R_GAME_VOICEFILE}
	,
	{"VOICESS.RES", R_GAME_VOICEFILE}
};

R_GAME_FONTDESC IHNMCD_GameFonts[] = {

	{R_GAME_FONT_MEDIUM, 2}
	,
	{R_GAME_FONT_LARGE, 3}
	,
	{R_GAME_FONT_SMALL, 4}
	,
	{R_GAME_FONT_SMALL2, 5}
	,
	{R_GAME_FONT_MEDIUM2, 6}
	,
	{R_GAME_FONT_LARGE2, 7}
	,
	{R_GAME_FONT_LARGE3, 8}
};

R_GAME_RESOURCEDESC IHNM_Resources[] = {
	IHNM_SCENE_LUT,		/* Scene lookup table RN */
	IHNM_SCRIPT_LUT,	/* Script lookup table RN */

	IHNM_COMMAND_PANEL,
	IHNM_DIALOGUE_PANEL
};

R_GAME_SOUNDINFO IHNM_GameSound = {

	R_GAME_SOUND_WAV
};

R_GAMEDESC GameDescs[] = {

	/* Inherit the earth - Demo version
	 * \*------------------------------------------------------------- */
	{
		    R_GAMETYPE_ITE,
		    R_GAME_ITE_DEMO,	/* Game id */
		    "Inherit the Earth - Demo version",	/* Game title */
		    320, 200,	/* Logical resolution */
		    137,	/* Scene viewport height */

		    ITE_DEFAULT_SCENE,	/* Starting scene number */

		    &ITE_Resources,

		    YS_NELEMS(ITEDEMO_GameFiles),	/* Game datafiles */
		    ITEDEMO_GameFiles,

		    YS_NELEMS(ITEDEMO_GameFonts),
		    ITEDEMO_GameFonts,

		    &ITEDEMO_GameSound,

		    Verify_ITEDEMO,	/* Game verification func */
		    0		/* Game supported flag */
	    }
	,

	/* Inherit the earth - Disk version
	 * \*------------------------------------------------------------- */
	{
		    R_GAMETYPE_ITE,
		    R_GAME_ITE_DISK,
		    "Inherit the Earth - Disk version",
		    320, 200,
		    137,

		    ITE_DEFAULT_SCENE,

		    &ITE_Resources,

		    YS_NELEMS(ITEDISK_GameFiles),
		    ITEDISK_GameFiles,

		    YS_NELEMS(ITEDISK_GameFonts),
		    ITEDISK_GameFonts,

		    &ITE_GameSound,

		    Verify_ITEDISK,
	    1}
	,

	/* Inherit the earth - CD version
	 * \*------------------------------------------------------------- */
	{
		    R_GAMETYPE_ITE,
		    R_GAME_ITE_CD,
		    "Inherit the Earth - CD version",
		    320, 200,
		    137,

		    ITE_DEFAULT_SCENE,

		    &ITE_Resources,

		    YS_NELEMS(ITECD_GameFiles),
		    ITECD_GameFiles,

		    YS_NELEMS(ITECD_GameFonts),
		    ITECD_GameFonts,

		    &ITECD_GameSound,

		    NULL,
	    1}
	,

	/* I Have No Mouth And I Must Scream - Demo version
	 * \*------------------------------------------------------------- */
	{
		    R_GAMETYPE_IHNM,
		    R_GAME_IHNM_DEMO,
		    "I Have No Mouth - Demo version",
		    640, 480,
		    304,

		    0,

		    IHNM_Resources,

		    YS_NELEMS(IHNMDEMO_GameFiles),
		    IHNMDEMO_GameFiles,

		    0,
		    NULL,

		    &IHNM_GameSound,

		    NULL,
	    0}
	,

	/* I Have No Mouth And I Must Scream - CD version
	 * \*------------------------------------------------------------- */
	{
		    R_GAMETYPE_IHNM,
		    R_GAME_IHNM_CD,
		    "I Have No Mouth - CD version",
		    640, 480,
		    304,

		    1,

		    IHNM_Resources,

		    YS_NELEMS(IHNMCD_GameFiles),
		    IHNMCD_GameFiles,

		    YS_NELEMS(IHNMCD_GameFonts),
		    IHNMCD_GameFonts,

		    &IHNM_GameSound,

		    NULL,
	    1}
};

static R_GAMEMODULE GameModule;

void GAME_setGameDirectory(const char *gamedir) {
	assert(gamedir != NULL);

	debug(0, "Using game data path: %s", gamedir);

	strcpy(GameModule.game_dir, gamedir);
	strcpy(GameModule.data_dir, ".");
}

int GAME_Register(void)
{

	return R_SUCCESS;

	/* Register "gamedir" cfg cvar
	 * \*----------------------------------------- */
	strncpy(GameModule.game_dir, "./", R_MAXPATH);

	if (CVAR_Register_S(GameModule.game_dir,
		"gamedir", NULL, R_CVAR_CFG, R_MAXPATH) != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Register "datadir" cfg cvar
	 * \*----------------------------------------- */
	strncpy(GameModule.data_dir, "./", R_MAXPATH);

	if (CVAR_Register_S(GameModule.data_dir,
		"datadir", NULL, R_CVAR_CFG, R_MAXPATH) != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Register "g_language" cfg cvar
	 * \*----------------------------------------- */
	strncpy(GameModule.game_dir, "us", R_MAXPATH);

	if (CVAR_Register_S(GameModule.game_language,
		"g_language",
		NULL, R_CVAR_CFG, R_GAME_LANGSTR_LIMIT) != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Register "g_skipintro" cfg cvar
	 * \*----------------------------------------- */
	if (CVAR_Register_I(&GameModule.g_skipintro,
		"g_skipintro", NULL, R_CVAR_CFG, 0, 1) != R_SUCCESS) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int GAME_Init(void)
{
	uint game_n;
	char *game_dir;

	game_dir = GameModule.game_dir;

	if (DetectGame(game_dir, &game_n) != R_SUCCESS) {

		GameModule.err_str = "No valid games were found in the "
		    "specified directory.";

		return R_FAILURE;
	}

	if (!GameDescs[game_n].gd_supported) {

		GameModule.err_str = "This game is not currently supported.";

		return R_FAILURE;
	}

	if (LoadGame(game_dir, game_n) != R_SUCCESS) {

		GameModule.err_str = "Error loading game resource files.";

		return R_FAILURE;
	}

	/* Load dialogue file 
	 * \*------------------------------------------------------------- */
	LoadLanguage();

	return R_SUCCESS;
}

int LoadLanguage(void)
{

	char lang_file[R_MAXPATH];
	char lang_path[R_MAXPATH];
	uint game_n;

	FILE *test_fp;

	game_n = GameModule.game_number;

	if (GameDescs[game_n].gd_game_type == R_GAMETYPE_ITE) {

		snprintf(lang_file, R_MAXPATH,
		    "%s%s.%s",
		    R_GAME_ITE_LANG_PREFIX,
		    GameModule.game_language, R_GAME_LANG_EXT);

		SYSFS_GetFQFN(GameModule.data_dir,
		    lang_file, lang_path, R_MAXPATH);

		test_fp = fopen(lang_path, "r");
		if (test_fp == NULL) {

			R_printf(R_STDOUT,
			    "Couldn't open language file %s. "
			    "Using default (US English)\n", lang_path);

			return R_SUCCESS;
		}

		fclose(test_fp);

		if (INTERFACE_RegisterLang() != R_SUCCESS) {
			R_printf(R_STDERR,
			    "Error registering interface language cvars.");

			return R_FAILURE;
		}

		if (ITE_IntroRegisterLang() != R_SUCCESS) {

			R_printf(R_STDERR,
			    "Error registering intro sequence language cvars.");

			return R_FAILURE;
		}

		R_printf(R_STDOUT, "Using language file %s.\n", lang_path);

		// FIXME
		//CFG_Read(lang_path);
	} else {

		R_printf(R_STDOUT,
		    "Language support for this game not implemented.\n");
	}

	return R_SUCCESS;
}

int GAME_GetErrN(void)
{
	return 0;
}

const char *GAME_GetErrS(void)
{

	return GameModule.err_str == NULL
	    ? "No error description." : GameModule.err_str;
}

int GAME_GetFileContext(R_RSCFILE_CONTEXT ** ctxt_p, uint r_type, int param)
{

	R_RSCFILE_CONTEXT *found_ctxt = NULL;
	uint i;

	YS_IGNORE_PARAM(param);

	if (ctxt_p == NULL) {

		return R_FAILURE;
	}

	for (i = 0; i < GameModule.gfile_n; i++) {

		if (GameModule.gfile_data[i].file_types & r_type) {

			found_ctxt = GameModule.gfile_data[i].file_ctxt;
		}
	}

	if (found_ctxt != NULL) {

		*ctxt_p = found_ctxt;
	} else {

		*ctxt_p = NULL;
	}

	return R_SUCCESS;
}

int DetectGame(const char *game_dir, uint * game_n_p)
{
	char game_fpath[R_GAME_PATH_LIMIT] = { 0 };

	uint game_count = YS_NELEMS(GameDescs);
	uint game_n;

	uint file_count;
	uint file_n;

	FILE *test_fp;

	int file_missing = 0;
	int found_game = 0;
	int error;

	if ((game_dir == NULL) || (game_n_p == NULL)) {

		return R_FAILURE;
	}

	for (game_n = 0; (game_n < game_count) && !found_game; game_n++) {

		file_count = GameDescs[game_n].gd_filect;

		file_missing = 0;

		/* Try to open all files for this game */
		for (file_n = 0; file_n < file_count; file_n++) {

			SYSFS_GetFQFN(game_dir,
			    GameDescs[game_n].gd_filedescs[file_n].gf_fname,
			    game_fpath, R_GAME_PATH_LIMIT);
			test_fp = fopen(game_fpath, "rb");
			if (test_fp == NULL) {

				file_missing = 1;

				break;
			}

			fclose(test_fp);
		}

		/* Try the next game, couldn't find all files for the current 
		 * game */
		if (file_missing) {
			continue;
		}

		/* If there's a verification function for this game, use it, 
		 * otherwise assume we've found the game if all files are found. */
		found_game = 1;

		if (GameDescs[game_n].gd_verifyf != NULL &&
		    GameDescs[game_n].gd_verifyf(game_dir) != R_SUCCESS) {

			found_game = 0;
		}

		if (found_game) {
			R_printf(R_STDOUT,
			    "Found game: %s\n", GameDescs[game_n].gd_title);

			*game_n_p = game_n;

			return R_SUCCESS;
		}
	}

	return R_FAILURE;
}

int LoadGame(const char *game_dir, uint game_n)
{

	R_RSCFILE_CONTEXT *load_ctxt;

	uint game_count = YS_NELEMS(GameDescs);

	char game_fpath[R_GAME_PATH_LIMIT] = { 0 };
	const char *game_fname;
	uint game_filect;

	uint i;

	if ((game_dir == NULL) || (game_n >= game_count)) {

		return R_FAILURE;
	}

	game_filect = GameDescs[game_n].gd_filect;

	GameModule.gfile_data = (R_GAME_FILEDATA *)malloc(game_filect *
	    sizeof *GameModule.gfile_data);
	if (GameModule.gfile_data == NULL) {

		return R_MEM;
	}

	GameModule.gfile_n = game_filect;

	/* Load game resource files
	 * \*------------------------------------------------------------- */
	for (i = 0; i < game_filect; i++) {

		load_ctxt = RSC_CreateContext();

		game_fname = GameDescs[game_n].gd_filedescs[i].gf_fname;

		SYSFS_GetFQFN(game_dir,
		    game_fname, game_fpath, R_GAME_PATH_LIMIT);

		if (RSC_OpenContext(load_ctxt, game_fpath) != R_SUCCESS) {

			return R_FAILURE;
		}

		R_printf(R_STDOUT, "Opened resource file: %s\n", game_fname);

		GameModule.gfile_data[i].file_ctxt = load_ctxt;
		GameModule.gfile_data[i].file_types =
		    GameDescs[game_n].gd_filedescs[i].gf_type;

		GameModule.gfile_data[i].file_flags = 0;
	}

	/* Load game font data
	 * \*------------------------------------------------------------- */
	GameModule.gd_fontct = GameDescs[game_n].gd_fontct;
	GameModule.gd_fontdescs = GameDescs[game_n].gd_fontdescs;

	/* Finish initialization
	 * \*------------------------------------------------------------- */
	GameModule.game_number = game_n;
	GameModule.gamedesc = &GameDescs[game_n];

	GameModule.game_init = 1;

	return R_SUCCESS;
}

int GAME_GetResourceInfo(R_GAME_RESOURCEDESC * rsc_desc)
{
	assert(rsc_desc != NULL);

	*rsc_desc = *GameModule.gamedesc->gd_resource_desc;

	return R_SUCCESS;
}

int GAME_GetSoundInfo(R_GAME_SOUNDINFO * snd_info)
{
	assert(snd_info != NULL);

	*snd_info = *GameModule.gamedesc->gd_soundinfo;

	return R_SUCCESS;
}

int GAME_GetDisplayInfo(R_GAME_DISPLAYINFO * disp_info)
{

	int game_n;

	assert(disp_info != NULL);

	if (!GameModule.game_init) {
		return R_FAILURE;
	}

	game_n = GameModule.game_number;

	disp_info->logical_w = GameDescs[game_n].gd_logical_w;
	disp_info->logical_h = GameDescs[game_n].gd_logical_h;
	disp_info->scene_h = GameDescs[game_n].gd_scene_h;

	return R_SUCCESS;
}

int GAME_GetFontInfo(R_GAME_FONTDESC ** gf_desc, int *font_n)
{

	assert((gf_desc != NULL) && (font_n != NULL));

	*gf_desc = GameModule.gd_fontdescs;
	*font_n = GameModule.gd_fontct;

	return R_SUCCESS;
}

int GAME_GetSceneInfo(R_GAME_SCENEDESC * gs_desc)
{

	assert(gs_desc != NULL);

	gs_desc->first_scene = GameModule.gamedesc->gd_startscene;
	gs_desc->scene_lut_rn =
	    GameModule.gamedesc->gd_resource_desc->scene_lut_rn;

	return R_SUCCESS;
}

int GAME_GetGame(void)
{

	return GameModule.gamedesc->gd_game_id;
}

int GAME_GetGameType(void)
{

	return GameModule.gamedesc->gd_game_type;
}

int Verify_ITEDEMO(const char *game_dir)
{

	YS_IGNORE_PARAM(game_dir);

	return R_SUCCESS;
}

int Verify_ITEDISK(const char *game_dir)
{

	R_RSCFILE_CONTEXT *test_ctx;

	char fpath[R_GAME_PATH_LIMIT] = { 0 };

	ulong script_lut_len;
	ulong script_lut_rn;

	int verified = 0;

	test_ctx = RSC_CreateContext();

	SYSFS_GetFQFN(game_dir, "ITE.RSC", fpath, R_GAME_PATH_LIMIT);

	if (RSC_OpenContext(test_ctx, fpath) != R_SUCCESS) {
		return R_FAILURE;
	}

	script_lut_rn =
	    GameDescs[R_GAME_ITE_DISK].gd_resource_desc->script_lut_rn;

	if (RSC_GetResourceSize(test_ctx,
		script_lut_rn, &script_lut_len) != R_SUCCESS) {

		RSC_DestroyContext(test_ctx);

		return R_FAILURE;
	}

	RSC_DestroyContext(test_ctx);

	if (script_lut_len % R_SCR_LUT_ENTRYLEN_ITEDISK == 0) {

		verified = 1;
	}

	if (!verified) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int Verify_ITECD(const char *game_dir)
{

	YS_IGNORE_PARAM(game_dir);

	return R_SUCCESS;
}

int Verify_IHNMDEMO(const char *game_dir)
{

	YS_IGNORE_PARAM(game_dir);

	return R_SUCCESS;
}

int Verify_IHNMCD(const char *game_dir)
{

	YS_IGNORE_PARAM(game_dir);

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: game.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/game.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Game detection, general game parameters

 Notes: 
*/

#ifndef SAGA_GAME_H_
#define SAGA_GAME_H_

namespace Saga {

#define R_GAME_LANGSTR_LIMIT 3
#define R_GAME_PATH_LIMIT 512

#define R_GAME_ITE_LANG_PREFIX "ite_"
#define R_GAME_LANG_EXT "lng"

/* Script lookup table entry sizes for game verification */
#define R_SCR_LUT_ENTRYLEN_ITECD 22
#define R_SCR_LUT_ENTRYLEN_ITEDISK 16

typedef int (*R_GAME_VERIFYFUNC) (const char *);

typedef struct R_GAME_FILEDESC_tag {

	const char *gf_fname;
	uint gf_type;

} R_GAME_FILEDESC;

typedef struct R_GAMEDESC_tag {

	int gd_game_type;
	int gd_game_id;

	const char *gd_title;

	int gd_logical_w;
	int gd_logical_h;
	int gd_scene_h;

	int gd_startscene;

	R_GAME_RESOURCEDESC *gd_resource_desc;

	int gd_filect;
	R_GAME_FILEDESC *gd_filedescs;

	int gd_fontct;
	R_GAME_FONTDESC *gd_fontdescs;

	R_GAME_SOUNDINFO *gd_soundinfo;

	R_GAME_VERIFYFUNC gd_verifyf;

	int gd_supported;

} R_GAMEDESC;

typedef struct R_GAME_FILEDATA_tag {

	R_RSCFILE_CONTEXT *file_ctxt;

	uint file_types;
	uint file_flags;

} R_GAME_FILEDATA;

typedef struct R_GAMEMODULE_tag {

	int game_init;
	int game_number;

	R_GAMEDESC *gamedesc;

	int g_skipintro;

	char game_dir[R_MAXPATH];
	char data_dir[R_MAXPATH];

	char game_language[R_GAME_LANGSTR_LIMIT];

	uint gfile_n;
	R_GAME_FILEDATA *gfile_data;

	uint gd_fontct;
	R_GAME_FONTDESC *gd_fontdescs;

	int err_n;
	const char *err_str;

} R_GAMEMODULE;

int LoadLanguage(void);

int DetectGame(const char *game_dir, uint * game_n_p);

int LoadGame(const char *game_dir, uint game_n_p);

int Verify_ITEDEMO(const char *game_dir);
int Verify_ITEDISK(const char *game_dir);
int Verify_ITECD(const char *game_dir);
int Verify_IHNMDEMO(const char *game_dir);
int Verify_IHNMCD(const char *game_dit);

} // End of namespace Saga

#endif				/* R_GAME_H_ */
/* end "r_game.h" */

--- NEW FILE: game_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/game_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Game detection, general game parameters - module header

 Notes: 
*/

#ifndef SAGA_GAME_MOD_H__
#define SAGA_GAME_MOD_H__

namespace Saga {

enum R_GAME_BASETYPES {

	R_GAMETYPE_ITE,
	R_GAMETYPE_IHNM
};

enum R_GAME_IDS {

	R_GAME_ITE_DEMO = 0,
	R_GAME_ITE_DISK = 1,
	R_GAME_ITE_CD = 2,
	R_GAME_IHNM_DEMO = 3,
	R_GAME_IHNM_CD = 4
};

enum R_GAME_FILETYPES {

	R_GAME_RESOURCEFILE = 0x01,
	R_GAME_SCRIPTFILE = 0x02,
	R_GAME_SOUNDFILE = 0x04,
	R_GAME_VOICEFILE = 0x08,
	R_GAME_DEMOFILE = 0x10,
	R_GAME_MUSICFILE = 0x20
};

enum R_GAME_SOUNDINFO_TYPES {

	R_GAME_SOUND_PCM = 0,
	R_GAME_SOUND_VOC,
	R_GAME_SOUND_WAV
};

enum R_GAME_FONT_IDS {

	R_GAME_FONT_SMALL = 0,
	R_GAME_FONT_MEDIUM,
	R_GAME_FONT_LARGE,
	R_GAME_FONT_SMALL2,
	R_GAME_FONT_MEDIUM2,
	R_GAME_FONT_LARGE2,
	R_GAME_FONT_LARGE3
};

typedef struct R_GAME_DISPLAYINFO_tag {

	int logical_w;
	int logical_h;
	int scene_h;

} R_GAME_DISPLAYINFO;

typedef struct R_GAMESOUND_INFO_tag {

	int res_type;
	long freq;
	int sample_size;
	int stereo;

} R_GAME_SOUNDINFO;

typedef struct R_GAMEFONT_DESC_tag {

	uint font_id;
	ulong font_rn;

} R_GAME_FONTDESC;

typedef struct R_GAMESCENE_DESC_tag {

	ulong scene_lut_rn;
	ulong first_scene;

} R_GAME_SCENEDESC;

typedef struct R_GAMERESOURCE_DESC_tag {

	ulong scene_lut_rn;
	ulong script_lut_rn;
	ulong command_panel_rn;
	ulong dialogue_panel_rn;

} R_GAME_RESOURCEDESC;

int GAME_Register(void);

int GAME_Init(void);

int GAME_GetFileContext(R_RSCFILE_CONTEXT ** ctxt_p, uint r_type, int param);

int GAME_GetFontInfo(R_GAME_FONTDESC **, int *);

int GAME_GetResourceInfo(R_GAME_RESOURCEDESC *);

int GAME_GetSoundInfo(R_GAME_SOUNDINFO *);

int GAME_GetDisplayInfo(R_GAME_DISPLAYINFO *);

int GAME_GetSceneInfo(R_GAME_SCENEDESC *);

int GAME_GetGame(void);

int GAME_GetGameType(void);

int GAME_GetErrN(void);

void GAME_setGameDirectory(const char *gamedir);

const char *GAME_GetErrS(void);

} // End of namespace Saga

#endif				/* R_GAME_MOD_H__ */
/* end "r_game_mod.h" */

--- NEW FILE: gfx.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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.
 *
[...1059 lines suppressed...]
				write_p += ds->buf_pitch;
			}
			write_p += x_vector;
	    /***********/
		}

		/* Vertical seg */
		for (k = 0; k < end_run; k++) {
			*write_p = (uchar) color;
			write_p += ds->buf_pitch;
		}
		write_p += x_vector;
	/***********/
		return;
	}

	return;
}

} // End of namespace Saga

--- NEW FILE: gfx.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/gfx.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Graphics maniuplation routines - private header file

 Notes: 
*/

#ifndef SAGA_GFX_H_
#define SAGA_GFX_H_

namespace Saga {

#define R_CURSOR_W 7
#define R_CURSOR_H 7

#define R_CURSOR_ORIGIN_X 4
#define R_CURSOR_ORIGIN_Y 4

#define R_CLAMP(a, min, max) \
    (a = (a < (min)) ? (min) : ((a > max) ? (max) : a ))

#define R_CLAMP_RECT( rect, xmin, xmax, ymin, ymax ) \
            R_CLAMP( rect->x1, xmin, xmax ); \
            R_CLAMP( rect->x2, xmin, xmax ); \
            R_CLAMP( rect->y1, ymin, ymax ); \
            R_CLAMP( rect->y2, ymin, ymax )

} // End of namespace Saga

#endif				/* R_GFX_H_ */
/* end "r_gfx_h_ */

--- NEW FILE: gfx_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/gfx_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Graphics manipulation routines - module header file

 Notes: 
*/

#ifndef SAGA_GFX_MOD_H_
#define SAGA_GFX_MOD_H_

namespace Saga {

typedef struct R_CLIPINFO_tag {

	/* input members */
	const R_RECT *src_rect;
	const R_RECT *dst_rect;
	const R_POINT *dst_pt;

	/* output members */
	int nodraw;
	int src_draw_x;
	int src_draw_y;
	int dst_draw_x;
	int dst_draw_y;
	int draw_w;
	int draw_h;

} R_CLIPINFO;

int GFX_SimpleBlit(R_SURFACE * dst_s, R_SURFACE * src_s);

int GFX_Scale2x(R_SURFACE * dst_s, R_SURFACE * src_s);

int GFX_Scale2x8(R_SURFACE * dst_s, R_SURFACE * src_s);

int GFX_Scale2x16(R_SURFACE * dst_s, R_SURFACE * src_s);

int GFX_SLScale2x16(char *dest_buf,
    int dest_w,
    int dest_p, int dst_h, char *src_buf, int src_w, int src_p, int src_h);

int GFX_ClearSurface(char *buf, int w, int h, int p);
int GFX_ClearSurface16(char *buf, int w, int h, int p);

int GFX_DrawPalette(R_SURFACE * dst_s);

int GFX_BufToSurface(R_SURFACE * ds,
    const uchar * src,
    int src_w, int src_h, R_RECT * src_rect, R_POINT * dst_pt);

int
GFX_BufToBuffer(uchar * dst_buf,
    int dst_w,
    int dst_h,
    const uchar * src,
    int src_w, int src_h, R_RECT * src_rect, R_POINT * dst_pt);

int GFX_DrawCursor(R_SURFACE * ds, R_POINT * p1);
int GFX_DrawRect(R_SURFACE * ds, R_RECT * dst_rect, int color);
int GFX_DrawFrame(R_SURFACE * ds, R_POINT * p1, R_POINT * p2, int color);
int GFX_DrawPolyLine(R_SURFACE * ds, R_POINT * pts, int pt_ct, int draw_color);

int GFX_GetClipInfo(R_CLIPINFO * clipinfo);

int
GFX_ClipLine(R_SURFACE * ds,
    const R_POINT * src_p1,
    const R_POINT * src_p2, R_POINT * dst_p1, R_POINT * dst_p2);

void GFX_DrawLine(R_SURFACE * ds, R_POINT * p1, R_POINT * p2, int color);

} // End of namespace Saga

#endif				/* R_GFX_MOD_H_ */
/* end "r_gfx_mod.h" */

--- NEW FILE: ihnm_introproc.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ihnm_introproc.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    "I Have No Mouth" Intro sequence scene procedures

 Notes: 
*/

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

#include "yslib.h"

#include "reinherit.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "animation_mod.h"
#include "cvar_mod.h"
#include "events_mod.h"
#include "font_mod.h"
#include "rscfile_mod.h"
#include "scene_mod.h"
#include "text_mod.h"
#include "palanim_mod.h"

/*
 * Begin module:
\*--------------------------------------------------------------------------*/
#include "scene.h"
#include "ihnm_introproc.h"

namespace Saga {

R_SCENE_RESLIST IHNM_IntroMovie1RL[] = {

	{30, SAGA_BG_IMAGE}
	,
	{31, SAGA_ANIM_1}
};

R_SCENE_DESC IHNM_IntroMovie1Desc = {

	0, 0, 0, 0, 0, 0, 0, 0,
	IHNM_IntroMovie1RL,
	YS_NELEMS(IHNM_IntroMovie1RL)

};

R_SCENE_RESLIST IHNM_IntroMovie2RL[] = {

	{32, SAGA_BG_IMAGE}
	,
	{33, SAGA_ANIM_1}
};

R_SCENE_DESC IHNM_IntroMovie2Desc = {

	0, 0, 0, 0, 0, 0, 0, 0,
	IHNM_IntroMovie2RL,
	YS_NELEMS(IHNM_IntroMovie2RL)

};

R_SCENE_RESLIST IHNM_IntroMovie3RL[] = {

	{34, SAGA_BG_IMAGE}
	,
	{35, SAGA_ANIM_1}
};

R_SCENE_DESC IHNM_IntroMovie3Desc = {

	0, 0, 0, 0, 0, 0, 0, 0,
	IHNM_IntroMovie3RL,
	YS_NELEMS(IHNM_IntroMovie3RL)

};

R_SCENE_RESLIST IHNM_IntroMovie4RL[] = {

	{1227, SAGA_BG_IMAGE}
	,
	{1226, SAGA_ANIM_1}
};

R_SCENE_DESC IHNM_IntroMovie4Desc = {

	0, 0, 0, 0, 0, 0, 0, 0,
	IHNM_IntroMovie4RL,
	YS_NELEMS(IHNM_IntroMovie4RL)

};

R_SCENE_QUEUE IHNM_IntroList[] = {
	{0, &IHNM_IntroMovie1Desc, BY_DESC, IHNM_IntroMovieProc1, 0}
	,
	{0, &IHNM_IntroMovie2Desc, BY_DESC, IHNM_IntroMovieProc2, 0}
	,
	{0, &IHNM_IntroMovie3Desc, BY_DESC, IHNM_IntroMovieProc3, 0}
	,
	{0, &IHNM_IntroMovie4Desc, BY_DESC, IHNM_HateProc, 0}
};

int IHNM_StartProc(void)
{
	size_t n_introscenes;
	size_t i;

	n_introscenes = YS_NELEMS(IHNM_IntroList);

	for (i = 0; i < n_introscenes; i++) {

		SCENE_Queue(&IHNM_IntroList[i]);
	}

	return R_SUCCESS;
}

int IHNM_IntroMovieProc1(int param, R_SCENE_INFO * scene_info)
{

	R_EVENT event = { 0 };

	YS_IGNORE_PARAM(scene_info);

	switch (param) {

	case SCENE_BEGIN:

		/* Background for intro scene is the first frame of the
		 * intro animation; display it and set the palette
		 \*-----------------------------------------------------*/
		event.type = R_ONESHOT_EVENT;
		event.code = R_BG_EVENT;
		event.op = EVENT_DISPLAY;
		event.param = SET_PALETTE;
		event.time = 0;

		EVENT_Queue(&event);

		ANIM_SetFrameTime(0, R_IHNM_INTRO_FRAMETIME);
		ANIM_SetFlag(0, ANIM_ENDSCENE);
		ANIM_Play(0, 0);
		break;

	default:
		break;
	}

	return 0;
}

int IHNM_IntroMovieProc2(int param, R_SCENE_INFO * scene_info)
{

	R_EVENT event = { 0 };
	R_EVENT *q_event;

	PALENTRY *pal;

	static PALENTRY current_pal[R_PAL_ENTRIES];

	YS_IGNORE_PARAM(scene_info);

	switch (param) {

	case SCENE_BEGIN:

		/* Fade to black out of the intro CyberDreams logo anim
		 * \*----------------------------------------------------- */
		SYSGFX_GetCurrentPal(current_pal);

		event.type = R_CONTINUOUS_EVENT;
		event.code = R_PAL_EVENT;
		event.op = EVENT_PALTOBLACK;
		event.time = 0;
		event.duration = R_IHNM_PALFADE_TIME;
		event.data = current_pal;

		q_event = EVENT_Queue(&event);

		/* Background for intro scene is the first frame of the
		 * intro animation; display it but don't set palette
		 \*-----------------------------------------------------*/
		event.type = R_ONESHOT_EVENT;
		event.code = R_BG_EVENT;
		event.op = EVENT_DISPLAY;
		event.param = NO_SET_PALETTE;
		event.time = 0;

		q_event = EVENT_Chain(q_event, &event);

		/* Fade in from black to the scene background palette
		 * \*----------------------------------------------------- */
		SCENE_GetBGPal(&pal);

		event.type = R_CONTINUOUS_EVENT;
		event.code = R_PAL_EVENT;
		event.op = EVENT_BLACKTOPAL;
		event.time = 0;
		event.duration = R_IHNM_PALFADE_TIME;
		event.data = pal;

		q_event = EVENT_Chain(q_event, &event);

		ANIM_SetFlag(0, ANIM_LOOP);
		ANIM_Play(0, R_IHNM_PALFADE_TIME * 2);

		/* Queue end of scene after looping animation for a while
		 * \*----------------------------------------------------- */
		event.type = R_ONESHOT_EVENT;
		event.code = R_SCENE_EVENT;
		event.op = EVENT_END;
		event.time = R_IHNM_DGLOGO_TIME;

		q_event = EVENT_Chain(q_event, &event);

		break;

	default:
		break;
	}

	return 0;
}

int IHNM_IntroMovieProc3(int param, R_SCENE_INFO * scene_info)
{

	R_EVENT event = { 0 };
	R_EVENT *q_event;

	PALENTRY *pal;

	static PALENTRY current_pal[R_PAL_ENTRIES];

	YS_IGNORE_PARAM(scene_info);

	switch (param) {

	case SCENE_BEGIN:

		/* Fade to black out of the intro DG logo anim
		 * \*----------------------------------------------------- */
		SYSGFX_GetCurrentPal(current_pal);

		event.type = R_CONTINUOUS_EVENT;
		event.code = R_PAL_EVENT;
		event.op = EVENT_PALTOBLACK;
		event.time = 0;
		event.duration = R_IHNM_PALFADE_TIME;
		event.data = current_pal;

		q_event = EVENT_Queue(&event);

		/* Background for intro scene is the first frame of the
		 * intro animation; display it but don't set palette
		 \*-----------------------------------------------------*/
		event.type = R_ONESHOT_EVENT;
		event.code = R_BG_EVENT;
		event.op = EVENT_DISPLAY;
		event.param = NO_SET_PALETTE;
		event.time = 0;

		q_event = EVENT_Chain(q_event, &event);

		/* Fade in from black to the scene background palette
		 * \*----------------------------------------------------- */
		SCENE_GetBGPal(&pal);

		event.type = R_CONTINUOUS_EVENT;
		event.code = R_PAL_EVENT;
		event.op = EVENT_BLACKTOPAL;
		event.time = 0;
		event.duration = R_IHNM_PALFADE_TIME;
		event.data = pal;

		q_event = EVENT_Chain(q_event, &event);

		ANIM_Play(0, 0);

		/* Queue end of scene after a while
		 * \*----------------------------------------------------- */
		event.type = R_ONESHOT_EVENT;
		event.code = R_SCENE_EVENT;
		event.op = EVENT_END;
		event.time = R_IHNM_TITLE_TIME;

		q_event = EVENT_Chain(q_event, &event);

		break;

	default:
		break;
	}

	return 0;
}

int IHNM_HateProc(int param, R_SCENE_INFO * scene_info)
{

	R_EVENT event = { 0 };
	R_EVENT *q_event;

	YS_IGNORE_PARAM(scene_info);

	switch (param) {

	case SCENE_BEGIN:

		/* Background for intro scene is the first frame of the
		 * intro animation; display it and set the palette
		 \*-----------------------------------------------------*/
		event.type = R_ONESHOT_EVENT;
		event.code = R_BG_EVENT;
		event.op = EVENT_DISPLAY;
		event.param = SET_PALETTE;
		event.time = 0;

		q_event = EVENT_Queue(&event);

		ANIM_SetFlag(0, ANIM_LOOP);
		ANIM_Play(0, 0);

		break;

	default:
		break;
	}

	return 0;
}

} // End of namespace Saga

--- NEW FILE: ihnm_introproc.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ihnm_introproc.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Intro sequence scene procedures header file

 Notes: 
*/

#ifndef SAGA_ITE_INTRO_H_
#define SAGA_ITE_INTRO_H_

namespace Saga {

#define R_IHNM_PALFADE_TIME    1000
#define R_IHNM_INTRO_FRAMETIME 80
#define R_IHNM_DGLOGO_TIME     8000
#define R_IHNM_TITLE_TIME      16000

} // End of namespace Saga

#endif				/* R_IHNM_INTRO_H_ */
/* end "r_ihnm_introproc.h */

--- NEW FILE: image.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/image.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    SAGA Image resource management routines

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "game_mod.h"

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "image_mod.h"
#include "image.h"

namespace Saga {

int
IMG_DecodeBGImage(const uchar * image_data,
    size_t image_size,
    uchar ** output_buf, size_t * output_buf_len, int *w, int *h)
{

	R_IMAGE_HEADER hdr;
	int modex_height;

	const uchar *RLE_data_ptr;
	size_t RLE_data_len;

	uchar *decode_buf;
	size_t decode_buf_len;

	uchar *out_buf;
	size_t out_buf_len;

	const uchar *read_p = image_data;

	if (image_size <= SAGA_IMAGE_DATA_OFFSET) {
		/* Image size is way too small */
		return R_FAILURE;
	}

	hdr.width = ys_read_u16_le(read_p, &read_p);
	hdr.height = ys_read_u16_le(read_p, &read_p);
	hdr.unknown4 = ys_read_u16_le(read_p, &read_p);
	hdr.unknown6 = ys_read_u16_le(read_p, &read_p);

	RLE_data_ptr = image_data + SAGA_IMAGE_DATA_OFFSET;
	RLE_data_len = image_size - SAGA_IMAGE_DATA_OFFSET;

	modex_height = Granulate(hdr.height, 4);

	decode_buf_len = hdr.width * modex_height;
	decode_buf = (uchar *)malloc(decode_buf_len);

	out_buf_len = hdr.width * hdr.height;
	out_buf = (uchar *)malloc(out_buf_len);

	if (DecodeBGImageRLE(RLE_data_ptr,
		RLE_data_len, decode_buf, decode_buf_len) != R_SUCCESS) {

		free(decode_buf);
		free(out_buf);

		return R_FAILURE;
	}

	UnbankBGImage(out_buf, decode_buf, hdr.width, hdr.height);

	/* For some reason bg images in IHNM are upside down
	 * \*------------------------------------------------------------- */
	if (GAME_GetGameType() == R_GAMETYPE_IHNM) {

		FlipImage(out_buf, hdr.width, hdr.height);
	}

	free(decode_buf);

	*output_buf_len = out_buf_len;
	*output_buf = out_buf;

	*w = hdr.width;
	*h = hdr.height;

	return R_SUCCESS;
}

int
DecodeBGImageRLE(const uchar * inbuf,
    size_t inbuf_len, uchar * outbuf, size_t outbuf_len)
{

	const uchar *inbuf_ptr;
	uchar *outbuf_ptr;
	size_t inbuf_remain;

	const uchar *inbuf_end;
	uchar *outbuf_end;
	size_t outbuf_remain;

	uchar mark_byte;
	int test_byte;

	uint runcount;

	uchar bitfield;
	uchar bitfield_byte1;
	uchar bitfield_byte2;

	uchar *backtrack_ptr;
	int backtrack_amount;

	uint c, b;

	int decode_err = 0;

	inbuf_ptr = inbuf;
	inbuf_remain = inbuf_len;

	outbuf_ptr = outbuf;
	outbuf_remain = outbuf_len;

	inbuf_end = (inbuf + inbuf_len) - 1;
	outbuf_end = (outbuf + outbuf_len) - 1;

	memset(outbuf, 0, outbuf_len);

	while ((inbuf_remain > 1) && (outbuf_remain > 0) && !decode_err) {

		if ((inbuf_ptr > inbuf_end) || (outbuf_ptr > outbuf_end)) {
			return R_FAILURE;
		}

		mark_byte = *inbuf_ptr++;
		inbuf_remain--;

		test_byte = mark_byte & 0xC0;	/* Mask all but two high order bits */

		switch (test_byte) {

		case 0xC0:	/* 1100 0000 */

			/* Uncompressed run follows: Max runlength 63 */
			runcount = mark_byte & 0x3f;

			if ((inbuf_remain < runcount) ||
			    (outbuf_remain < runcount)) {
				return R_FAILURE;
			}

			for (c = 0; c < runcount; c++) {
				*outbuf_ptr++ = *inbuf_ptr++;
			}

			inbuf_remain -= runcount;
			outbuf_remain -= runcount;
			continue;

			break;

		case 0x80:	/* 1000 0000 */

			/* Compressed run follows: Max runlength 63 */
			runcount = (mark_byte & 0x3f) + 3;

			if (!inbuf_remain || (outbuf_remain < runcount)) {
				return R_FAILURE;
			}

			for (c = 0; c < runcount; c++) {
				*outbuf_ptr++ = *inbuf_ptr;
			}

			inbuf_ptr++;
			inbuf_remain--;
			outbuf_remain -= runcount;
			continue;

			break;

		case 0x40:	/* 0100 0000 */

			/* Repeat decoded sequence from output stream: 
			 * Max runlength 10 */

			runcount = ((mark_byte >> 3) & 0x07U) + 3;

			backtrack_amount = *inbuf_ptr;

			if (!inbuf_remain ||
			    (backtrack_amount > (outbuf_ptr - outbuf)) ||
			    (runcount > outbuf_remain)) {
				return R_FAILURE;
			}

			inbuf_ptr++;
			inbuf_remain--;

			backtrack_ptr = outbuf_ptr - backtrack_amount;

			for (c = 0; c < runcount; c++) {
				*outbuf_ptr++ = *backtrack_ptr++;
			}

			outbuf_remain -= runcount;
			continue;

			break;

		default:	/* 0000 0000 */
			break;
		}

		/* Mask all but the third and fourth highest order bits */
		test_byte = mark_byte & 0x30;

		switch (test_byte) {

		case 0x30:	/* 0011 0000 */
			/* Bitfield compression */

			runcount = (mark_byte & 0x0F) + 1;

			if ((inbuf_remain < (runcount + 2)) ||
			    (outbuf_remain < (runcount * 8))) {
				return R_FAILURE;
			}

			bitfield_byte1 = *inbuf_ptr++;
			bitfield_byte2 = *inbuf_ptr++;

			for (c = 0; c < runcount; c++) {

				bitfield = *inbuf_ptr;

				for (b = 0; b < 8; b++) {

					if (bitfield & 0x80) {
						*outbuf_ptr = bitfield_byte2;
					} else {
						*outbuf_ptr = bitfield_byte1;
					}

					bitfield <<= 1;

					outbuf_ptr++;
				}
				inbuf_ptr++;
			}

			inbuf_remain -= (runcount + 2);
			outbuf_remain -= (runcount * 8);
			continue;

			break;

		case 0x20:	/* 0010 0000 */
			/* Uncompressed run follows */

			runcount = ((mark_byte & 0x0F) << 8) + *inbuf_ptr;

			if ((inbuf_remain < (runcount + 1)) ||
			    (outbuf_remain < runcount)) {
				return R_FAILURE;
			}

			inbuf_ptr++;

			for (c = 0; c < runcount; c++) {
				*outbuf_ptr++ = *inbuf_ptr++;
			}

			inbuf_remain -= (runcount + 1);
			outbuf_remain -= runcount;
			continue;

			break;

		case 0x10:	/* 0001 0000 */
			/* Repeat decoded sequence from output stream */

			backtrack_amount =
			    ((mark_byte & 0x0F) << 8) + *inbuf_ptr;

			if (inbuf_remain < 2) {
				return R_FAILURE;
			}

			inbuf_ptr++;
			runcount = *inbuf_ptr++;

			if ((backtrack_amount > (outbuf_ptr - outbuf)) ||
			    (outbuf_remain < runcount)) {
				return R_FAILURE;
			}

			backtrack_ptr = outbuf_ptr - backtrack_amount;

			for (c = 0; c < runcount; c++) {
				*outbuf_ptr++ = *backtrack_ptr++;
			}

			inbuf_remain -= 2;
			outbuf_remain -= runcount;
			continue;

			break;

		default:
			return R_FAILURE;
			break;

		}

	}			/* end while */

	return R_SUCCESS;
}

int FlipImage(uchar * img_buf, int columns, int scanlines)
{

	int line;
	uchar *tmp_scan;

	uchar *flip_p1;
	uchar *flip_p2;

	int flipcount = scanlines / 2;

	tmp_scan = (uchar *)malloc(columns);
	if (tmp_scan == NULL) {
		return R_FAILURE;
	}

	flip_p1 = img_buf;
	flip_p2 = img_buf + (columns * (scanlines - 1));

	for (line = 0; line < flipcount; line++) {

		memcpy(tmp_scan, flip_p1, columns);
		memcpy(flip_p1, flip_p2, columns);
		memcpy(flip_p2, tmp_scan, columns);

		flip_p1 += columns;
		flip_p2 -= columns;
	}

	free(tmp_scan);

	return R_SUCCESS;
}

int
UnbankBGImage(uchar * dst_buf,
    const uchar * src_buf, int columns, int scanlines)
{

	int x, y;
	int temp;

	int quadruple_rows;
	int remain_rows;

	int rowjump_src;
	int rowjump_dest;

	const uchar *src_p;
	uchar *dst_p;

	const uchar *srcptr1, *srcptr2, *srcptr3, *srcptr4;
	uchar *dstptr1, *dstptr2, *dstptr3, *dstptr4;

	quadruple_rows = scanlines - (scanlines % 4);
	remain_rows = scanlines - quadruple_rows;

	assert(scanlines > 0);

	src_p = src_buf;
	dst_p = dst_buf + columns;

	srcptr1 = src_p;
	srcptr2 = src_p + 1;
	srcptr3 = src_p + 2;
	srcptr4 = src_p + 3;

	dstptr1 = dst_buf;
	dstptr2 = dst_buf + columns;
	dstptr3 = dst_buf + columns * 2;
	dstptr4 = dst_buf + columns * 3;

	rowjump_src = columns * 4;
	rowjump_dest = columns * 4;

	/* Unbank groups of 4 first */
	for (y = 0; y < quadruple_rows; y += 4) {

		for (x = 0; x < columns; x++) {
			temp = x * 4;
			dstptr1[x] = srcptr1[temp];
			dstptr2[x] = srcptr2[temp];
			dstptr3[x] = srcptr3[temp];
			dstptr4[x] = srcptr4[temp];
		}

		/* This is to avoid generating invalid pointers - 
		 * usually innocuous, but undefined */
		if (y < quadruple_rows - 4) {

			dstptr1 += rowjump_dest;
			dstptr2 += rowjump_dest;
			dstptr3 += rowjump_dest;
			dstptr4 += rowjump_dest;
			srcptr1 += rowjump_src;
			srcptr2 += rowjump_src;
			srcptr3 += rowjump_src;
			srcptr4 += rowjump_src;
		}

	}

	/* Unbank rows remaining */
	switch (remain_rows) {

	case 1:
		dstptr1 += rowjump_dest;
		srcptr1 += rowjump_src;

		for (x = 0; x < columns; x++) {
			temp = x * 4;
			dstptr1[x] = srcptr1[temp];
		}
		break;

	case 2:
		dstptr1 += rowjump_dest;
		dstptr2 += rowjump_dest;
		srcptr1 += rowjump_src;
		srcptr2 += rowjump_src;

		for (x = 0; x < columns; x++) {
			temp = x * 4;
			dstptr1[x] = srcptr1[temp];
			dstptr2[x] = srcptr2[temp];
		}
		break;

	case 3:
		dstptr1 += rowjump_dest;
		dstptr2 += rowjump_dest;
		dstptr3 += rowjump_dest;
		srcptr1 += rowjump_src;
		srcptr2 += rowjump_src;
		srcptr3 += rowjump_src;

		for (x = 0; x < columns; x++) {
			temp = x * 4;
			dstptr1[x] = srcptr1[temp];
			dstptr2[x] = srcptr2[temp];
			dstptr3[x] = srcptr3[temp];
		}
		break;

	default:
		break;
	}

	return R_SUCCESS;
}

const uchar *IMG_GetImagePal(const uchar * image_data, size_t image_size)
{
	if (image_size <= SAGA_IMAGE_HEADER_LEN) {
		return NULL;
	}

	return image_data + SAGA_IMAGE_HEADER_LEN;
}

} // End of namespace Saga

--- NEW FILE: image.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/image.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    SAGA Image resource management header file

 Notes: 
*/

#ifndef SAGA_IMAGE_H__
#define SAGA_IMAGE_H__

namespace Saga {

#define R_MIN_IMG_RLECODE    3
#define MODEX_SCANLINE_LIMIT 200

#define SAGA_IMAGE_DATA_OFFSET 776
#define SAGA_IMAGE_HEADER_LEN  8

typedef struct R_IMAGE_HEADER_tag {

	int width;
	int height;
	int unknown4;
	int unknown6;

} R_IMAGE_HEADER;

int
DecodeBGImageRLE(const uchar * inbuf,
    size_t inbuf_len, uchar * outbuf, size_t outbuf_len);

int FlipImage(uchar * img_buf, int columns, int scanlines);

int
UnbankBGImage(uchar * dest_buf,
    const uchar * src_buf, int columns, int scanlines);

} // End of namespace Saga

#endif				/* R_IMAGE_H__ */
/* end "r_image.h" */

--- NEW FILE: image_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/image_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    SAGA Image resource management routines

 Notes: 
*/

#ifndef SAGA_IMAGE_MOD_H_
#define SAGA_IMAGE_MOD_H_

namespace Saga {

int
IMG_DecodeBGImage(const uchar * image_data,
    size_t image_size,
    uchar ** output_buf, size_t * output_buf_len, int *w, int *h);

const uchar *IMG_GetImagePal(const uchar * image_data, size_t image_size);

} // End of namespace Saga

#endif				/* R_IMAGE_MOD_H_ */
/* end "r_image_mod.h" */

--- NEW FILE: interface.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/interface.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Game interface module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "game_mod.h"
#include "cvar_mod.h"
#include "actor_mod.h"
#include "console_mod.h"
#include "font_mod.h"
#include "gfx_mod.h"
#include "image_mod.h"
#include "objectmap_mod.h"
#include "rscfile_mod.h"
#include "script_mod.h"
#include "sprite_mod.h"

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "interface_mod.h"
#include "interface.h"

namespace Saga {

static R_INTERFACE_MODULE IfModule;

static R_VERB_DATA I_VerbData[] = {

	{I_VERB_WALKTO, "verb_walkto", "Walk to", S_VERB_WALKTO},
	{I_VERB_LOOKAT, "verb_lookat", "Look at", S_VERB_LOOKAT},
	{I_VERB_PICKUP, "verb_pickup", "Pick up", S_VERB_PICKUP},
	{I_VERB_TALKTO, "verb_talkto", "Talk to", S_VERB_TALKTO},
	{I_VERB_OPEN, "verb_open", "Open", S_VERB_OPEN},
	{I_VERB_CLOSE, "verb_close", "Close", S_VERB_CLOSE},
	{I_VERB_USE, "verb_use", "Use", S_VERB_USE},
	{I_VERB_GIVE, "verb_give", "Give", S_VERB_GIVE}
};

static R_INTERFACE_DESC ITE_interface = {

	ITE_STATUS_Y,
	ITE_STATUS_W,
	ITE_STATUS_H,
	ITE_STATUS_TEXT_Y,
	ITE_STATUS_TXTCOL,
	ITE_STATUS_BGCOL,

	ITE_CMD_TEXT_COL,
	ITE_CMD_TEXT_SHADOWCOL,
	ITE_CMD_TEXT_HILITECOL,

	COMMAND_DEFAULT_BUTTON,

	ITE_LPORTRAIT_X,
	ITE_LPORTRAIT_Y
};

static R_INTERFACE_BUTTON ITE_c_buttons[] = {

	{5, 4, 46, 47, "Portrait", 0, 0, BUTTON_NONE, 0},
	/* "Walk To" and "Talk To" share button sprites */
	{52, 4, 109, 14, "Walk To", 1, 2, BUTTON_VERB, I_VERB_WALKTO},
	{52, 15, 109, 25, "Look At", 3, 4, BUTTON_VERB, I_VERB_LOOKAT},
	{52, 26, 109, 36, "Pick Up", 5, 6, BUTTON_VERB, I_VERB_PICKUP},
	{52, 37, 109, 47, "Talk To", 1, 2, BUTTON_VERB, I_VERB_TALKTO},
	{110, 4, 166, 14, "Open", 7, 8, BUTTON_VERB, I_VERB_OPEN},
	{110, 15, 166, 25, "Close", 9, 10, BUTTON_VERB, I_VERB_CLOSE},
	{110, 26, 166, 36, "Use", 11, 12, BUTTON_VERB, I_VERB_USE},
	{110, 37, 166, 47, "Give", 13, 14, BUTTON_VERB, I_VERB_GIVE},

	{181, 6, 206, 24, "Inv1", 0, 0, BUTTON_NONE, 0},
	{213, 6, 240, 24, "Inv2", 0, 0, BUTTON_NONE, 0},
	{245, 6, 272, 24, "Inv3", 0, 0, BUTTON_NONE, 0},
	{277, 6, 304, 24, "Inv4", 0, 0, BUTTON_NONE, 0},
	{181, 27, 208, 45, "Inv5", 0, 0, BUTTON_NONE, 0},
	{213, 27, 240, 45, "Inv6", 0, 0, BUTTON_NONE, 0},
	{245, 27, 272, 45, "Inv7", 0, 0, BUTTON_NONE, 0},
	{277, 27, 304, 45, "Inv8", 0, 0, BUTTON_NONE, 0},
	{306, 6, 314, 11, "InvUp", 0, 0, BUTTON_NONE, 0},
	{306, 41, 314, 45, "InvDown", 0, 0, BUTTON_NONE, 0}
};

static R_INTERFACE_DESC IHNM_interface = {

	IHNM_STATUS_Y,
	IHNM_STATUS_W,
	IHNM_STATUS_H,
	IHNM_STATUS_TEXT_Y,
	IHNM_STATUS_TXTCOL,
	IHNM_STATUS_BGCOL,

	IHNM_CMD_TEXT_COL,
	IHNM_CMD_TEXT_SHADOWCOL,
	IHNM_CMD_TEXT_HILITECOL,

	COMMAND_DEFAULT_BUTTON,

	IHNM_LPORTRAIT_X,
	IHNM_LPORTRAIT_Y
};

static R_INTERFACE_BUTTON IHNM_c_buttons[] = {

	{5, 4, 46, 47, "Portrait", 0, 0, 0, 0}
};

int INTERFACE_RegisterLang(void)
{
	size_t i;

	for (i = 0; i < YS_NELEMS(I_VerbData); i++) {

		if (CVAR_Register_S(I_VerbData[i].verb_str,
			I_VerbData[i].verb_cvar,
			NULL, R_CVAR_CFG, R_VERB_STRLIMIT) != R_SUCCESS) {

			return R_FAILURE;
		}

		assert(CVAR_Find(I_VerbData[i].verb_cvar) != NULL);
	}

	return R_SUCCESS;
}

int INTERFACE_Init(void)
{

	R_GAME_RESOURCEDESC g_resdesc;

	int game_type;
	int result;

	if (IfModule.init) {
		return R_FAILURE;
	}

	IfModule.i_thread = STHREAD_Create();
	if (IfModule.i_thread == NULL) {

		R_printf(R_STDERR,
		    "Error creating script thread for game interface "
		    "module.\n");

		return R_FAILURE;
	}

	/* Load interface module resource file context
	 * \*------------------------------------------------------------- */
	result = GAME_GetFileContext(&IfModule.i_file_ctxt,
	    R_GAME_RESOURCEFILE, 0);
	if (result != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Initialize interface data by game type
	 * \*------------------------------------------------------------- */
	game_type = GAME_GetGameType();

	if (game_type == R_GAMETYPE_ITE) {

		/* Load Inherit the Earth interface desc */

		IfModule.c_panel.buttons = ITE_c_buttons;
		IfModule.c_panel.nbuttons = YS_NELEMS(ITE_c_buttons);

		IfModule.i_desc = ITE_interface;
	} else if (game_type == R_GAMETYPE_IHNM) {

		/* Load I Have No Mouth interface desc */
		IfModule.c_panel.buttons = IHNM_c_buttons;
		IfModule.c_panel.nbuttons = YS_NELEMS(IHNM_c_buttons);

		IfModule.i_desc = IHNM_interface;
	} else {
		return R_FAILURE;
	}

	/* Load interface resources
	 * \*------------------------------------------------------------- */
	GAME_GetResourceInfo(&g_resdesc);

	/* Load command panel resource */
	result = RSC_LoadResource(IfModule.i_file_ctxt,
	    g_resdesc.command_panel_rn,
	    &IfModule.c_panel.res, &IfModule.c_panel.res_len);
	if (result != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Load dialogue panel resource */
	result = RSC_LoadResource(IfModule.i_file_ctxt,
	    g_resdesc.dialogue_panel_rn,
	    &IfModule.d_panel.res, &IfModule.d_panel.res_len);
	if (result != R_SUCCESS) {

		return R_FAILURE;
	}

	SPRITE_LoadList(ITE_COMMAND_BUTTONSPRITES, &IfModule.c_panel.sprites);

	SPRITE_LoadList(ITE_DEFAULT_PORTRAITS, &IfModule.def_portraits);

	IMG_DecodeBGImage(IfModule.c_panel.res,
	    IfModule.c_panel.res_len,
	    &IfModule.c_panel.img,
	    &IfModule.c_panel.img_len,
	    &IfModule.c_panel.img_w, &IfModule.c_panel.img_h);

	IMG_DecodeBGImage(IfModule.d_panel.res,
	    IfModule.d_panel.res_len,
	    &IfModule.d_panel.img,
	    &IfModule.d_panel.img_len,
	    &IfModule.d_panel.img_w, &IfModule.d_panel.img_h);

	IfModule.c_panel.x = 0;
	IfModule.c_panel.y = 149;

	IfModule.d_panel.x = 0;
	IfModule.d_panel.y = 149;

	IfModule.c_panel.set_button = COMMAND_DEFAULT_BUTTON;
	IfModule.active_portrait = 0;

	IfModule.active_verb = I_VERB_WALKTO;

	IfModule.init = 1;

	return R_SUCCESS;
}

int INTERFACE_Activate(void)
{

	IfModule.active = 1;
	INTERFACE_Draw();

	return R_SUCCESS;
}

int INTERFACE_Deactivate(void)
{

	IfModule.active = 0;

	return R_SUCCESS;
}

int INTERFACE_SetStatusText(const char *new_txt)
{

	assert(new_txt != NULL);

	strncpy(IfModule.status_txt, new_txt, R_STATUS_TEXT_LEN);

	return R_SUCCESS;
}

int INTERFACE_Draw(void)
{

	R_GAME_DISPLAYINFO g_di;

	R_SURFACE *back_buf;

	int xbase;
	int ybase;
	int lportrait_x;
	int lportrait_y;

	R_RECT rect;
	R_POINT origin;

	back_buf = SYSGFX_GetBackBuffer();

	if (!IfModule.active) {
		return R_SUCCESS;
	}

	/* Get game display info
	 * \*------------------------------------------------------------- */
	GAME_GetDisplayInfo(&g_di);

	/* Erase background of status bar
	 * \*------------------------------------------------------------- */
	rect.x1 = 0;
	rect.y1 = IfModule.i_desc.status_y;

	rect.x2 = g_di.logical_w - 1;
	rect.y2 = IfModule.i_desc.status_h - 1;

	GFX_DrawRect(back_buf, &rect, IfModule.i_desc.status_bgcol);

	/* Draw command panel background
	 * \*------------------------------------------------------------- */
	if (IfModule.panel_mode == PANEL_COMMAND) {

		xbase = IfModule.c_panel.x;
		ybase = IfModule.c_panel.y;

		origin.x = 0;
		origin.y = g_di.logical_h - IfModule.c_panel.img_h;

		GFX_BufToSurface(back_buf,
		    IfModule.c_panel.img,
		    IfModule.c_panel.img_w,
		    IfModule.c_panel.img_h, NULL, &origin);
	} else {

		xbase = IfModule.d_panel.x;
		ybase = IfModule.d_panel.y;

		origin.x = 0;
		origin.y = g_di.logical_h - IfModule.c_panel.img_h;

		GFX_BufToSurface(back_buf,
		    IfModule.d_panel.img,
		    IfModule.d_panel.img_w,
		    IfModule.d_panel.img_h, NULL, &origin);
	}

	/* Draw character portrait
	 * \*------------------------------------------------------------- */
	lportrait_x = xbase + IfModule.i_desc.lportrait_x;
	lportrait_y = ybase + IfModule.i_desc.lportrait_y;

	SPRITE_Draw(back_buf,
	    IfModule.def_portraits,
	    IfModule.active_portrait, lportrait_x, lportrait_y);

	return R_SUCCESS;
}

int INTERFACE_Update(R_POINT * imouse_pt, int update_flag)
{

	R_GAME_DISPLAYINFO g_di;

	R_SURFACE *back_buf;

	int imouse_x, imouse_y;

	assert(imouse_pt != NULL);

	if (!IfModule.active) {
		return R_SUCCESS;
	}

	imouse_x = imouse_pt->x;
	imouse_y = imouse_pt->y;

	back_buf = SYSGFX_GetBackBuffer();

	/* Get game display info
	 * \*------------------------------------------------------------- */
	GAME_GetDisplayInfo(&g_di);

	/* Update playfield space ( only if cursor is inside )
	 * \*------------------------------------------------------------- */
	if (imouse_y < g_di.scene_h) {

		/* Mouse is in playfield space */

		if (update_flag == UPDATE_MOUSEMOVE) {

			HandlePlayfieldUpdate(back_buf, imouse_pt);
		} else if (update_flag == UPDATE_MOUSECLICK) {

			HandlePlayfieldClick(back_buf, imouse_pt);
		}
	}

	/* Update command space
	 * \*------------------------------------------------------------- */

	if (update_flag == UPDATE_MOUSEMOVE) {

		HandleCommandUpdate(back_buf, imouse_pt);
	} else if (update_flag == UPDATE_MOUSECLICK) {

		HandleCommandClick(back_buf, imouse_pt);
	}

	DrawStatusBar(back_buf);

	return R_SUCCESS;
}

int DrawStatusBar(R_SURFACE * ds)
{

	R_GAME_DISPLAYINFO g_di;
	R_RECT rect;

	int string_w;

	/* Get game display info
	 * \*------------------------------------------------------------- */
	GAME_GetDisplayInfo(&g_di);

	/* Erase background of status bar
	 * \*------------------------------------------------------------- */
	rect.x1 = 0;
	rect.y1 = IfModule.i_desc.status_y;
	rect.x2 = g_di.logical_w - 1;
	rect.y2 = IfModule.i_desc.status_y + IfModule.i_desc.status_h - 1;

	GFX_DrawRect(ds, &rect, IfModule.i_desc.status_bgcol);

	string_w = FONT_GetStringWidth(SMALL_FONT_ID,
	    IfModule.status_txt, 0, 0);

	FONT_Draw(SMALL_FONT_ID,
	    ds,
	    IfModule.status_txt,
	    0,
	    (IfModule.i_desc.status_w / 2) - (string_w / 2),
	    IfModule.i_desc.status_y + IfModule.i_desc.status_txt_y,
	    IfModule.i_desc.status_txt_col, 0, 0);

	return R_SUCCESS;

}

int HandleCommandClick(R_SURFACE * ds, R_POINT * imouse_pt)
{

	int hit_button;
	int ibutton_num;

	int x_base;
	int y_base;

	int button_x = 0;
	int button_y = 0;

	int old_set_button;
	int set_button;

	hit_button = INTERFACE_HitTest(imouse_pt, &ibutton_num);
	if (hit_button != R_SUCCESS) {

		/* Clicking somewhere other than a button doesn't do anything */
		return R_SUCCESS;
	}

	x_base = IfModule.c_panel.x;
	y_base = IfModule.c_panel.y;

	if (IfModule.c_panel.buttons[ibutton_num].flags & BUTTON_SET) {

		old_set_button = IfModule.c_panel.set_button;
		set_button = ibutton_num;
		IfModule.c_panel.set_button = set_button;

		if (IfModule.c_panel.buttons[set_button].flags & BUTTON_VERB) {

			IfModule.active_verb =
			    IfModule.c_panel.buttons[ibutton_num].data;
		}

		if (IfModule.c_panel.buttons[set_button].flags & BUTTON_BITMAP) {

			button_x =
			    x_base + IfModule.c_panel.buttons[set_button].x1;
			button_y =
			    y_base + IfModule.c_panel.buttons[set_button].y1;

			SPRITE_Draw(ds,
			    IfModule.c_panel.sprites,
			    IfModule.c_panel.buttons[set_button].
			    active_sprite - 1, button_x, button_y);
		}

		if (IfModule.c_panel.buttons[old_set_button].
		    flags & BUTTON_BITMAP) {

			button_x =
			    x_base +
			    IfModule.c_panel.buttons[old_set_button].x1;
			button_y =
			    y_base +
			    IfModule.c_panel.buttons[old_set_button].y1;

			SPRITE_Draw(ds,
			    IfModule.c_panel.sprites,
			    IfModule.c_panel.buttons[old_set_button].
			    inactive_sprite - 1, button_x, button_y);
		}
	}

	return R_SUCCESS;
}

int HandleCommandUpdate(R_SURFACE * ds, R_POINT * imouse_pt)
{

	int hit_button;
	int ibutton_num;

	int button_x = 0;
	int button_y = 0;
	int button_w = 0;

	int verb_idx = 0;
	int string_w = 0;

	int color;

	int i;

	hit_button = INTERFACE_HitTest(imouse_pt, &ibutton_num);
	if (hit_button == R_SUCCESS) {

		/* Hovering over a command panel button */
		INTERFACE_SetStatusText(I_VerbData[IfModule.active_verb].
		    verb_str);
	}

	for (i = 0; i < IfModule.c_panel.nbuttons; i++) {

		if (!(IfModule.c_panel.buttons[i].flags & BUTTON_LABEL)) {
			continue;
		}

		button_w = IfModule.c_panel.buttons[i].x2 -
		    IfModule.c_panel.buttons[i].x1;

		verb_idx = IfModule.c_panel.buttons[i].data;

		string_w = FONT_GetStringWidth(SMALL_FONT_ID,
		    I_VerbData[verb_idx].verb_str, 0, 0);

		if (i == hit_button) {
			color = IfModule.i_desc.cmd_txt_hilitecol;
		} else {
			color = IfModule.i_desc.cmd_txt_col;
		}

		button_x = IfModule.c_panel.x + IfModule.c_panel.buttons[i].x1;
		button_y = IfModule.c_panel.y + IfModule.c_panel.buttons[i].y1;

		FONT_Draw(SMALL_FONT_ID,
		    ds,
		    I_VerbData[verb_idx].verb_str,
		    0,
		    button_x + ((button_w / 2) - (string_w / 2)),
		    button_y + 1,
		    color, IfModule.i_desc.cmd_txt_shadowcol, FONT_SHADOW);

		if ((i == IfModule.c_panel.set_button) &&
		    (IfModule.c_panel.buttons[i].flags & BUTTON_BITMAP)) {

			SPRITE_Draw(ds,
			    IfModule.c_panel.sprites,
			    IfModule.c_panel.buttons[i].active_sprite - 1,
			    button_x, button_y);
		}
	}

	return R_SUCCESS;
}

int HandlePlayfieldClick(R_SURFACE * ds, R_POINT * imouse_pt)
{

	int hit_object;
	int object_num;
	uint object_flags = 0;

	int script_num;
	R_POINT iactor_pt;

	hit_object = OBJECTMAP_HitTest(imouse_pt, &object_num);

	if (hit_object != R_SUCCESS) {

		/* Player clicked on empty spot - walk here regardless of verb */

		ACTOR_StoA(&iactor_pt, imouse_pt);
		ACTOR_WalkTo(0, &iactor_pt, 0, NULL);

		return R_SUCCESS;
	}

	if (OBJECTMAP_GetFlags(object_num, &object_flags) != R_SUCCESS) {

		CON_Print("Invalid object number: %d\n", object_num);

		return R_FAILURE;
	}

	if (object_flags & R_OBJECT_NORMAL) {

		if (OBJECTMAP_GetEPNum(object_num, &script_num) == R_SUCCESS) {

			/* Set active verb in script module */
			SDATA_PutWord(4, 4,
			    I_VerbData[IfModule.active_verb].s_verb);

			/* Execute object script if present */
			if (script_num != 0) {
				STHREAD_Execute(IfModule.i_thread, script_num);
			}
		}
	} else {

		/* Not a normal scene object - walk to it as if it weren't there */

		ACTOR_StoA(&iactor_pt, imouse_pt);
		ACTOR_WalkTo(0, &iactor_pt, 0, NULL);

	}

	return R_SUCCESS;
}

int HandlePlayfieldUpdate(R_SURFACE * ds, R_POINT * imouse_pt)
{

	const char *object_name;
	int object_num;
	uint object_flags = 0;

	char new_status[R_STATUS_TEXT_LEN];

	int hit_object;

	new_status[0] = 0;

	hit_object = OBJECTMAP_HitTest(imouse_pt, &object_num);

	if (hit_object != R_SUCCESS) {

		/* Cursor over nothing - just display current verb */
		INTERFACE_SetStatusText(I_VerbData[IfModule.active_verb].
		    verb_str);

		return R_SUCCESS;
	}

	if (OBJECTMAP_GetFlags(object_num, &object_flags) != R_SUCCESS) {

		CON_Print("Invalid object number: %d\n", object_num);

		return R_FAILURE;
	}

	OBJECTMAP_GetName(object_num, &object_name);

	if (object_flags & R_OBJECT_NORMAL) {

		/* Normal scene object - display as subject of verb */

		snprintf(new_status,
		    R_STATUS_TEXT_LEN,
		    "%s %s",
		    I_VerbData[IfModule.active_verb].verb_str, object_name);
	} else {

		/* Not normal scene object - override verb as we can only
		 * walk to this object */

		snprintf(new_status,
		    R_STATUS_TEXT_LEN,
		    "%s %s", I_VerbData[I_VERB_WALKTO].verb_str, object_name);
	}

	INTERFACE_SetStatusText(new_status);

	return R_SUCCESS;
}

int INTERFACE_HitTest(R_POINT * imouse_pt, int *ibutton)
{

	R_INTERFACE_BUTTON *buttons;

	int nbuttons;
	int xbase;
	int ybase;

	int i;

	buttons = IfModule.c_panel.buttons;
	nbuttons = IfModule.c_panel.nbuttons;

	xbase = IfModule.c_panel.x;
	ybase = IfModule.c_panel.y;

	for (i = 0; i < nbuttons; i++) {

		if ((imouse_pt->x >= (xbase + buttons[i].x1)) &&
		    (imouse_pt->x < (xbase + buttons[i].x2)) &&
		    (imouse_pt->y >= (ybase + buttons[i].y1)) &&
		    (imouse_pt->y < (ybase + buttons[i].y2))) {

			*ibutton = i;

			return R_SUCCESS;
		}
	}

	*ibutton = -1;
	return R_FAILURE;
}

int INTERFACE_Shutdown(void)
{

	if (!IfModule.init) {

		return R_FAILURE;
	}

	IfModule.init = 0;

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: interface.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/interface.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Game interface module private header file

 Notes: 

    Module dependencies:
    - r_script_mod
    - r_sprite_mod
*/

#ifndef SAGA_INTERFACE_H__
#define SAGA_INTERFACE_H__

namespace Saga {

#define R_VERB_STRLIMIT 32

#define R_STATUS_TEXT_LEN 128

#define COMMAND_DEFAULT_BUTTON 1

/* Inherit the Earth interface values */
#define ITE_STATUS_Y      137
#define ITE_STATUS_W      320
#define ITE_STATUS_H      12
#define ITE_STATUS_TEXT_Y 2
#define ITE_STATUS_TXTCOL 186
#define ITE_STATUS_BGCOL  15

#define ITE_CMD_TEXT_COL       147
#define ITE_CMD_TEXT_SHADOWCOL 15
#define ITE_CMD_TEXT_HILITECOL 96

#define ITE_LPORTRAIT_X 5
#define ITE_LPORTRAIT_Y 4

/* IHNMAIMS interface values */
#define IHNM_STATUS_Y      304
#define IHNM_STATUS_W      640
#define IHNM_STATUS_H      24
#define IHNM_STATUS_TEXT_Y 8
#define IHNM_STATUS_TXTCOL 186
#define IHNM_STATUS_BGCOL  0

#define IHNM_CMD_TEXT_COL       147
#define IHNM_CMD_TEXT_SHADOWCOL 15
#define IHNM_CMD_TEXT_HILITECOL 96

#define IHNM_LPORTRAIT_X 5
#define IHNM_LPORTRAIT_Y 4

typedef enum R_PANEL_MODES_tag {

	PANEL_COMMAND,
	PANEL_DIALOGUE
} R_PANEL_MODES;

typedef enum R_BUTTON_FLAGS_tag {

	BUTTON_NONE = 0x0,
	BUTTON_LABEL = 0x01,
	BUTTON_BITMAP = 0x02,
	BUTTON_SET = 0x04

} R_BUTTON_FLAGS;

#define BUTTON_VERB ( BUTTON_LABEL | BUTTON_BITMAP | BUTTON_SET )

typedef struct R_INTERFACE_BUTTON_tag {

	int x1;
	int y1;
	int x2;
	int y2;
	char *label;
	int inactive_sprite;
	int active_sprite;
	int flags;
	int data;

} R_INTERFACE_BUTTON;

typedef struct R_INTERFACE_PANEL_tag {

	uchar *res;
	size_t res_len;
	int x;
	int y;
	uchar *img;
	size_t img_len;
	int img_w;
	int img_h;
	int set_button;
	int nbuttons;
	R_INTERFACE_BUTTON *buttons;
	R_SPRITELIST *sprites;

} R_INTERFACE_PANEL;

typedef struct R_INTERFACE_DESC_tag {

	int status_y;
	int status_w;
	int status_h;
	int status_txt_y;
	int status_txt_col;
	int status_bgcol;

	int cmd_txt_col;
	int cmd_txt_shadowcol;
	int cmd_txt_hilitecol;
	int cmd_defaultbutton;

	int lportrait_x;
	int lportrait_y;

} R_INTERFACE_DESC;

typedef struct R_INTERFACE_MODULE_tag {

	int init;
	int active;

	R_RSCFILE_CONTEXT *i_file_ctxt;

	R_INTERFACE_DESC i_desc;

	R_PANEL_MODES panel_mode;
	R_INTERFACE_PANEL c_panel;
	R_INTERFACE_PANEL d_panel;

	char status_txt[R_STATUS_TEXT_LEN];

	int active_portrait;
	R_SPRITELIST *def_portraits;
	int active_verb;

	R_SCRIPT_THREAD *i_thread;

} R_INTERFACE_MODULE;

enum INTERFACE_VERBS {

	I_VERB_WALKTO,
	I_VERB_LOOKAT,
	I_VERB_PICKUP,
	I_VERB_TALKTO,
	I_VERB_OPEN,
	I_VERB_CLOSE,
	I_VERB_USE,
	I_VERB_GIVE
};

typedef struct R_VERB_DATA_tag {

	int i_verb;
	const char *verb_cvar;
	char verb_str[R_VERB_STRLIMIT];
	int s_verb;

} R_VERB_DATA;

int INTERFACE_HitTest(R_POINT * imouse_pt, int *ibutton);

int DrawStatusBar(R_SURFACE * ds);
int HandleCommandUpdate(R_SURFACE * ds, R_POINT * imouse_pt);
int HandleCommandClick(R_SURFACE * ds, R_POINT * imouse_pt);
int HandlePlayfieldUpdate(R_SURFACE * ds, R_POINT * imouse_pt);
int HandlePlayfieldClick(R_SURFACE * ds, R_POINT * imouse_pt);

} // End of namespace Saga

#endif				/* R_INTERFACE_H__ */
/* end "r_interface.h" */

--- NEW FILE: interface_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/interface_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Game interface module public header file

 Notes: 
*/

#ifndef SAGA_INTERFACE_MOD_H
#define SAGA_INTERFACE_MOD_H

namespace Saga {

typedef enum INTERFACE_UPDATE_FLAGS_tag {

	UPDATE_MOUSEMOVE = 1,
	UPDATE_MOUSECLICK

} INTERFACE_UPDATE_FLAGS;

int INTERFACE_RegisterLang(void);

int INTERFACE_Init(void);
int INTERFACE_Shutdown(void);

int INTERFACE_Activate(void);
int INTERFACE_Deactivate(void);

int INTERFACE_SetStatusText(const char *new_txt);
int INTERFACE_Draw(void);
int INTERFACE_Update(R_POINT * imouse_pt, int update_flag);

} // End of namespace Saga

#endif				/* SAGA_INTERFACE_MOD_H */

--- NEW FILE: isomap.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/isomap.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Isometric level module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "game_mod.h"
#include "gfx_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "isomap_mod.h"
#include "isomap.h"

namespace Saga {

static R_ISOMAP_MODULE IsoModule;

int ISOMAP_Init(void)
{
	IsoModule.init = 1;

	return R_SUCCESS;
}

int ISOMAP_LoadTileset(const uchar * tileres_p, size_t tileres_len)
{

	R_ISOTILE_ENTRY first_entry;
	R_ISOTILE_ENTRY *tile_tbl;

	uint i;

	const uchar *read_p = tileres_p;
	size_t read_len = tileres_len;

	assert((IsoModule.init) && (!IsoModule.tiles_loaded));
	assert((tileres_p != NULL) && (tileres_len > 0));

	read_p += 2;
	first_entry.tile_offset = ys_read_u16_le(read_p, &read_p);

	IsoModule.tile_ct = first_entry.tile_offset / SAGA_ISOTILE_ENTRY_LEN;

	read_p = tileres_p;
	read_len = tileres_len;

	tile_tbl = (R_ISOTILE_ENTRY *)malloc(IsoModule.tile_ct * sizeof *tile_tbl);
	if (tile_tbl == NULL) {
		return R_MEM;
	}

	for (i = 0; i < IsoModule.tile_ct; i++) {

		tile_tbl[i].tile_h = ys_read_u8(read_p, &read_p);
		tile_tbl[i].unknown01 = ys_read_u8(read_p, &read_p);

		tile_tbl[i].tile_offset = ys_read_u16_le(read_p, &read_p);
		tile_tbl[i].unknown04 = ys_read_s16_le(read_p, &read_p);
		tile_tbl[i].unknown06 = ys_read_s16_le(read_p, &read_p);
	}

	IsoModule.tiles_loaded = 1;
	IsoModule.tile_tbl = tile_tbl;
	IsoModule.tileres_p = tileres_p;
	IsoModule.tileres_len = tileres_len;

	return R_SUCCESS;
}

int ISOMAP_LoadMetaTileset(const uchar * mtileres_p, size_t mtileres_len)
{

	R_ISO_METATILE_ENTRY *mtile_tbl;

	const uchar *read_p = mtileres_p;
	size_t read_len = mtileres_len;

	uint mtile_ct;
	uint ct;

	int i;

	assert(IsoModule.init);
	assert((mtileres_p != NULL) && (mtileres_len > 0));

	(void)read_len;

	mtile_ct = mtileres_len / SAGA_METATILE_ENTRY_LEN;

	mtile_tbl = (R_ISO_METATILE_ENTRY *)malloc(mtile_ct * sizeof *mtile_tbl);
	if (mtile_tbl == NULL) {
		return R_MEM;
	}

	for (ct = 0; ct < mtile_ct; ct++) {

		mtile_tbl[ct].mtile_n = ys_read_u16_le(read_p, &read_p);
		mtile_tbl[ct].unknown02 = ys_read_s16_le(read_p, &read_p);
		mtile_tbl[ct].unknown04 = ys_read_s16_le(read_p, &read_p);
		mtile_tbl[ct].unknown06 = ys_read_s16_le(read_p, &read_p);

		for (i = 0; i < SAGA_METATILE_SIZE; i++) {
			mtile_tbl[ct].tile_tbl[i] =
			    ys_read_u16_le(read_p, &read_p);
		}
	}

	IsoModule.mtile_ct = mtile_ct;
	IsoModule.mtile_tbl = mtile_tbl;
	IsoModule.mtileres_p = mtileres_p;
	IsoModule.mtileres_len = mtileres_len;

	IsoModule.mtiles_loaded = 1;

	return R_SUCCESS;
}

int ISOMAP_LoadMetamap(const uchar * mm_res_p, size_t mm_res_len)
{

	const uchar *read_p = mm_res_p;
	size_t read_len = mm_res_len;

	int i;

	(void)read_len;

	IsoModule.metamap_n = ys_read_s16_le(read_p, &read_p);

	for (i = 0; i < SAGA_METAMAP_SIZE; i++) {

		IsoModule.metamap_tbl[i] = ys_read_u16_le(read_p, &read_p);
	}

	IsoModule.mm_res_p = mm_res_p;
	IsoModule.mm_res_len = mm_res_len;
	IsoModule.metamap_loaded = 1;

	return R_SUCCESS;
}

int ISOMAP_Draw(R_SURFACE * dst_s)
{

	R_GAME_DISPLAYINFO disp_info;
	R_RECT iso_rect;

	GAME_GetDisplayInfo(&disp_info);

	iso_rect.x1 = 0;
	iso_rect.y1 = 0;
	iso_rect.x2 = disp_info.logical_w - 1;
	iso_rect.y2 = disp_info.scene_h - 1;

	GFX_DrawRect(dst_s, &iso_rect, 0);

	ISOMAP_DrawMetamap(dst_s, -1000, -500);

	return R_SUCCESS;
}

int ISOMAP_DrawMetamap(R_SURFACE * dst_s, int map_x, int map_y)
{
	int meta_base_x = map_x;
	int meta_base_y = map_y;

	int meta_xi;
	int meta_yi;

	int meta_x;
	int meta_y;

	int meta_idx;

	for (meta_yi = SAGA_METAMAP_H - 1; meta_yi >= 0; meta_yi--) {

		meta_x = meta_base_x;
		meta_y = meta_base_y;

		for (meta_xi = SAGA_METAMAP_W - 1; meta_xi >= 0; meta_xi--) {

			meta_idx = meta_xi + (meta_yi * 16);

			ISOMAP_DrawMetaTile(dst_s,
			    IsoModule.metamap_tbl[meta_idx], meta_x, meta_y);

			meta_x += 128;
			meta_y += 64;
		}

		meta_base_x -= 128;
		meta_base_y += 64;
	}

	return R_SUCCESS;
}

int
ISOMAP_DrawMetaTile(R_SURFACE * dst_s, uint mtile_i, int mtile_x, int mtile_y)
{

	int tile_xi;
	int tile_yi;

	int tile_x;
	int tile_y;

	int tile_base_x;
	int tile_base_y;

	int tile_i;

	R_ISO_METATILE_ENTRY *mtile_p;
	assert(IsoModule.init && IsoModule.mtiles_loaded);

	if (mtile_i >= IsoModule.mtile_ct) {
		return R_FAILURE;
	}

	mtile_p = &IsoModule.mtile_tbl[mtile_i];

	tile_base_x = mtile_x;
	tile_base_y = mtile_y;

	for (tile_yi = SAGA_METATILE_H - 1; tile_yi >= 0; tile_yi--) {

		tile_y = tile_base_y;
		tile_x = tile_base_x;

		for (tile_xi = SAGA_METATILE_W - 1; tile_xi >= 0; tile_xi--) {

			tile_i = tile_xi + (tile_yi * SAGA_METATILE_W);

			ISOMAP_DrawTile(dst_s,
			    mtile_p->tile_tbl[tile_i], tile_x, tile_y);

			tile_x += SAGA_ISOTILE_WIDTH / 2;
			tile_y += SAGA_ISOTILE_BASEHEIGHT / 2 + 1;

		}

		tile_base_x -= SAGA_ISOTILE_WIDTH / 2;
		tile_base_y += SAGA_ISOTILE_BASEHEIGHT / 2 + 1;

	}

	return R_SUCCESS;
}

int ISOMAP_DrawTile(R_SURFACE * dst_s, uint tile_i, int tile_x, int tile_y)
{

	const uchar *tile_p;
	const uchar *read_p;

	uchar *draw_p;

	int draw_x;
	int draw_y;

	int tile_h;
	int w_count = 0;
	int row;

	int bg_runct;
	int fg_runct;
	int ct;

	assert(IsoModule.init && IsoModule.tiles_loaded);

	if (tile_i >= IsoModule.tile_ct) {
		return R_FAILURE;
	}

	/* temporary x clip */
	if (tile_x < 0) {
		return R_SUCCESS;
	}

	/* temporary x clip */
	if (tile_x >= 320 - 32) {
		return R_SUCCESS;
	}

	tile_p = IsoModule.tileres_p + IsoModule.tile_tbl[tile_i].tile_offset;
	tile_h = IsoModule.tile_tbl[tile_i].tile_h;

	read_p = tile_p;
	draw_p = dst_s->buf + tile_x + (tile_y * dst_s->buf_pitch);

	draw_x = tile_x;
	draw_y = tile_y;

	if (tile_h > SAGA_ISOTILE_BASEHEIGHT) {
		draw_y = tile_y - (tile_h - SAGA_ISOTILE_BASEHEIGHT);
	}

	/* temporary y clip */
	if (draw_y < 0) {
		return R_SUCCESS;
	}

	for (row = 0; row < tile_h; row++) {

		draw_p =
		    dst_s->buf + draw_x + ((draw_y + row) * dst_s->buf_pitch);
		w_count = 0;

		/* temporary y clip */
		if ((draw_y + row) >= 137) {
			return R_SUCCESS;
		}

		for (;;) {

			bg_runct = *read_p++;
			w_count += bg_runct;

			if (w_count >= SAGA_ISOTILE_WIDTH) {
				break;
			}

			draw_p += bg_runct;

			fg_runct = *read_p++;
			w_count += fg_runct;

			for (ct = 0; ct < fg_runct; ct++) {

				*draw_p++ = *read_p++;
			}
		}
	}

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: isomap.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/isomap.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Isometric level module - private header

 Notes: 
*/

#ifndef SAGA_ISOMAP_H_
#define SAGA_ISOMAP_H_

namespace Saga {

typedef struct R_ISOTILE_ENTRY_tag {

	int tile_h;
	int unknown01;
	size_t tile_offset;
	int unknown04;
	int unknown06;

} R_ISOTILE_ENTRY;

#define SAGA_ISOTILE_ENTRY_LEN 8
#define SAGA_ISOTILE_WIDTH 32
#define SAGA_ISOTILE_BASEHEIGHT 15

#define SAGA_METATILE_W 8
#define SAGA_METATILE_H 8
#define SAGA_METATILE_SIZE 64

#define SAGA_METAMAP_W 16
#define SAGA_METAMAP_H 16
#define SAGA_METAMAP_SIZE 256

typedef struct R_ISO_METATILE_ENTRY_tag {

	int mtile_n;
	int unknown02;
	int unknown04;
	int unknown06;

	int tile_tbl[SAGA_METATILE_SIZE];

} R_ISO_METATILE_ENTRY;

#define SAGA_METATILE_ENTRY_LEN 136

typedef struct R_ISOMAP_MODULE_tag {

	int init;

	int tiles_loaded;
	const uchar *tileres_p;
	size_t tileres_len;
	uint tile_ct;
	R_ISOTILE_ENTRY *tile_tbl;

	int mtiles_loaded;
	const uchar *mtileres_p;
	size_t mtileres_len;
	uint mtile_ct;
	R_ISO_METATILE_ENTRY *mtile_tbl;

	int metamap_loaded;
	int metamap_n;
	uint metamap_tbl[SAGA_METAMAP_SIZE];
	const uchar *mm_res_p;
	size_t mm_res_len;

} R_ISOMAP_MODULE;

int ISOMAP_DrawTile(R_SURFACE * dst_s, uint tile_i, int tile_x, int tile_y);

int
ISOMAP_DrawMetaTile(R_SURFACE * dst_s, uint mtile_i, int mtile_x, int mtile_y);

int ISOMAP_DrawMetamap(R_SURFACE * dst_s, int map_x, int map_y);

} // End of namespace Saga

#endif				/* SAGA_ISOMAP_H_ */

--- NEW FILE: isomap_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/isomap_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Isometric level module - public module header

 Notes: 
*/

#ifndef SAGA_ISOMAP_MOD_H_
#define SAGA_ISOMAP_MOD_H_

namespace Saga {

int ISOMAP_Init(void);

int ISOMAP_LoadTileset(const uchar *, size_t);

int ISOMAP_LoadMetaTileset(const uchar *, size_t);

int ISOMAP_LoadMetamap(const uchar * mm_res_p, size_t mm_res_len);

int ISOMAP_Draw(R_SURFACE * dst_s);

} // End of namespace Saga

#endif				/* SAGA_ISOMAP_MOD_H_ */

--- NEW FILE: ite_introproc.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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.
 *
[...1138 lines suppressed...]
		event.time = 5000;

		q_event = EVENT_Chain(q_event_start, &event);

		break;

	case SCENE_END:

		break;

	default:
		R_printf(R_STDERR, "Illegal scene procedure parameter.\n");
		break;

	}

	return 0;
}

} // End of namespace Saga

--- NEW FILE: ite_introproc.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ite_introproc.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Intro sequence scene procedures header file

 Notes: 
*/

#ifndef SAGA_ITE_INTRO_H_
#define SAGA_ITE_INTRO_H_

namespace Saga {

#define R_INTRO_STRMAX 256

#define ITE_INTRO_FRAMETIME 90

#define INTRO_CAPTION_Y 170
#define VOICE_PAD 50
#define VOICE_LETTERLEN 90

#define PALETTE_FADE_DURATION 1000
#define DISSOLVE_DURATION 3000

#define CREDIT_DURATION1 4000

enum R_INTRO_SCENE_DIALOGUE_INFO {

	INTRO_CAVE1_START = 0,
	INTRO_CAVE1_END = 4,

	INTRO_CAVE2_START = 4,
	INTRO_CAVE2_END = 7,

	INTRO_CAVE3_START = 7,
	INTRO_CAVE3_END = 10,

	INTRO_CAVE4_START = 10,
	INTRO_CAVE4_END = 14
};

typedef struct R_INTRO_DIALOGUE_tag {

	ulong i_voice_rn;
	char *i_cvar_name;
	char i_str[R_INTRO_STRMAX];

} R_INTRO_DIALOGUE;

typedef struct INTRO_CAPTION_tag {

	int res_n;
	char *caption;

} INTRO_CAPTION;

typedef struct INTRO_CREDIT_tag {

	int text_x;
	int text_y;
	int delta_time;
	int duration;
	char *string;
	int font_id;

} INTRO_CREDIT;

} // End of namespace Saga

#endif				/* SAGA_ITE_INTRO_H_ */

--- NEW FILE: ite_introproc_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ite_introproc_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Intro sequence scene procedures - public header file

 Notes: 
*/

#ifndef SAGA_ITE_INTROPROC_MOD_H_
#define SAGA_ITE_INTROPROC_MOD_H_

namespace Saga {

int ITE_IntroRegisterLang(void);

} // End of namespace Saga

#endif				/* SAGA_ITE_INTROPROC_MOD_H_ */

--- NEW FILE: math.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/math.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Math routines

 Notes: 
*/

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

#include "reinherit.h"

namespace Saga {

int
MATH_HitTestPoly(R_POINT * points, unsigned int npoints, R_POINT test_point)
{
	int yflag0;
	int yflag1;
	int inside_flag = 0;
	unsigned int pt;

	R_POINT *vtx0 = &points[npoints - 1];
	R_POINT *vtx1 = &points[0];

	yflag0 = (vtx0->y >= test_point.y);

	for (pt = 0; pt < npoints; pt++, vtx1++) {

		yflag1 = (vtx1->y >= test_point.y);

		if (yflag0 != yflag1) {

			if (((vtx1->y - test_point.y) * (vtx0->x - vtx1->x) >=
				(vtx1->x - test_point.x) * (vtx0->y -
				    vtx1->y)) == yflag1) {

				inside_flag = !inside_flag;
			}
		}
		yflag0 = yflag1;
		vtx0 = vtx1;
	}

	return inside_flag;
}

} // End of namespace Saga

--- NEW FILE: math.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/math.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Math routines implementation header

 Notes: 
*/

#ifndef SAGA_MATH_H__
#define  SAGA_MATH_H__

#endif				/* SAGA_MATH_H__ */

--- NEW FILE: math_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/math_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Math routines public header

 Notes: 
*/

#ifndef SAGA_MATH_MOD_H__
#define SAGA_MATH_MOD_H__

namespace Saga {

int
MATH_HitTestPoly(R_POINT * points, unsigned int npoints, R_POINT test_point);

} // End of namespace Saga

#endif				/* SAGA_MATH_MOD_H__ */

--- NEW FILE: misc.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/misc.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Misc. routines

 Notes: 
*/

namespace Saga {

int Granulate(int value, int granularity)
{

	int remainder;

	if (value == 0)
		return 0;

	if (granularity == 0)
		return 0;

	remainder = value % granularity;

	if (remainder == 0) {
		return value;
	} else {
		return (granularity - remainder + value);
	}

}

} // End of namespace Saga

--- NEW FILE: objectmap.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/objectmap.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Object map / Object click-area module 

 Notes: 

    Polygon Hit Test code ( HitTestPoly() ) adapted from code (C) Eric Haines
     appearing in Graphics Gems IV, "Point in Polygon Strategies."
     p. 24-46, code: p. 34-45
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "cvar_mod.h"
#include "console_mod.h"
#include "gfx_mod.h"
#include "math_mod.h"
#include "font_mod.h"

/*
 * Module options
\*--------------------------------------------------------------------------*/

#define R_OBJECTMAP_DEBUG R_DEBUG_INFO

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "objectmap_mod.h"
#include "objectmap.h"

namespace Saga {

static R_OBJECTMAP_INFO OMInfo;

int OBJECTMAP_Register(void)
{

	CVAR_RegisterFunc(CF_object_info,
	    "object_info", NULL, R_CVAR_NONE, 0, 0);

	return R_SUCCESS;
}

int OBJECTMAP_Init(void)
/*--------------------------------------------------------------------------*\
 * Initializes the object map module, creates module allocation context
\*--------------------------------------------------------------------------*/
{
	R_printf(R_STDOUT, "OBJECTMAP Module: Initializing...\n");

	OMInfo.initialized = 1;
	return R_SUCCESS;
}

int OBJECTMAP_Shutdown(void)
/*--------------------------------------------------------------------------*\
 * Shuts down the object map module, destroys module allocation context
\*--------------------------------------------------------------------------*/
{
	if (!OMInfo.initialized) {
		return R_FAILURE;
	}

	R_printf(R_STDOUT, "OBJECTMAP Module: Shutting down...\n");

	OBJECTMAP_Free();
	OBJECTMAP_FreeNames();

	R_printf(R_STDOUT, "OBJECTMAP Module: Shutdown AOK.\n");

	OMInfo.initialized = 0;
	return R_SUCCESS;
}

int OBJECTMAP_Load(const uchar * om_res, size_t om_res_len)
/*--------------------------------------------------------------------------*\
 * Loads an object map resource ( objects ( clickareas ( points ) ) ) 
\*--------------------------------------------------------------------------*/
{
	const unsigned char *read_p = om_res;

	R_OBJECTMAP_ENTRY *object_map;
	R_CLICKAREA *clickarea;
	R_POINT *point;

	int i, k, m;

	YS_IGNORE_PARAM(om_res_len);

	if (!OMInfo.initialized) {
		R_printf(R_STDERR,
		    "Error: Object map module not initialized!\n");
		return R_FAILURE;
	}

	if (OMInfo.objects_loaded) {
		OBJECTMAP_Free();
	}

	/* Obtain object count N and allocate space for N objects
	 * \*------------------------------------------------------------- */
	OMInfo.n_objects = ys_read_u16_le(read_p, &read_p);

	OMInfo.object_maps =
	  (R_OBJECTMAP_ENTRY *)malloc(OMInfo.n_objects * sizeof *OMInfo.object_maps);

	if (OMInfo.object_maps == NULL) {
		R_printf(R_STDERR, "Error: Memory allocation failed.\n");
		return R_MEM;
	}

	/* Load all N objects
	 * \*------------------------------------------------------------- */
	for (i = 0; i < OMInfo.n_objects; i++) {

		object_map = &OMInfo.object_maps[i];
		object_map->unknown0 = ys_read_u8(read_p, &read_p);
		object_map->n_clickareas = ys_read_u8(read_p, &read_p);
		object_map->flags = ys_read_u16_le(read_p, &read_p);
		object_map->object_num = ys_read_u16_le(read_p, &read_p);
		object_map->script_num = ys_read_u16_le(read_p, &read_p);

		object_map->clickareas =
			(R_CLICKAREA *)malloc(object_map->n_clickareas *
		    sizeof *(object_map->clickareas));

		if (object_map->clickareas == NULL) {
			R_printf(R_STDERR,
			    "Error: Memory allocation failed.\n");
			return R_MEM;
		}

		/* Load all clickareas for this object */
		for (k = 0; k < object_map->n_clickareas; k++) {

			clickarea = &object_map->clickareas[k];
			clickarea->n_points = ys_read_u16_le(read_p, &read_p);
			assert(clickarea->n_points != 0);

			clickarea->points =
			    (R_POINT *)malloc(clickarea->n_points * sizeof *(clickarea->points));

			if (clickarea->points == NULL) {
				R_printf(R_STDERR,
				    "Error: Memory allocation failed.\n");
				return R_MEM;
			}

			/* Load all points for this clickarea */
			for (m = 0; m < clickarea->n_points; m++) {

				point = &clickarea->points[m];
				point->x = ys_read_s16_le(read_p, &read_p);
				point->y = ys_read_s16_le(read_p, &read_p);
			}

#           if R_OBJECTMAP_DEBUG >= R_DEBUG_PARANOID
			R_printf(R_STDOUT,
			    "OBJECTMAP_Load(): "
			    "Read %d points for clickarea %d in object %d.\n",
			    clickarea->n_points, k, object_map->object_num);
#           endif
		}		/* End load all clickareas */
	}			/* End load all objects */

    /*-------------------------------------------------------------*/
	OMInfo.objects_loaded = 1;

	return R_SUCCESS;
}

int OBJECTMAP_Free(void)
/*--------------------------------------------------------------------------*\
 * Frees all storage allocated for the current object map data
\*--------------------------------------------------------------------------*/
{
	R_OBJECTMAP_ENTRY *object_map;
	R_CLICKAREA *clickarea;

	int i, k;

	if (!OMInfo.objects_loaded) {
		return R_FAILURE;
	}

	for (i = 0; i < OMInfo.n_objects; i++) {
		object_map = &OMInfo.object_maps[i];

		for (k = 0; k < object_map->n_clickareas; k++) {
			clickarea = &object_map->clickareas[k];
			free(clickarea->points);
		}
		free(object_map->clickareas);
	}

	if (OMInfo.n_objects) {
		free(OMInfo.object_maps);
	}

	OMInfo.objects_loaded = 0;

	return R_SUCCESS;
}

int OBJECTMAP_LoadNames(const unsigned char *onl_res, size_t onl_res_len)
/*--------------------------------------------------------------------------*\
 * Loads an object name list resource
\*--------------------------------------------------------------------------*/
{
	YS_REG_FUNC(OBJECTMAP_LoadNames);
	const unsigned char *read_p = onl_res;

	int table_len;
	int n_names;
	size_t name_offset;

	int i;

	YS_IGNORE_PARAM(onl_res_len);

	if (OMInfo.names_loaded) {
		OBJECTMAP_FreeNames();
	}

	table_len = ys_read_u16_le(read_p, &read_p);

	n_names = table_len / 2 - 2;
	OMInfo.n_names = n_names;

#if 0
#   if R_OBJECTMAP_DEBUG >= R_DEBUG_INFO
	R_printf(R_STDOUT, "%s: Loading %d object names.\n", YS_FUNC, n_names);
#   endif
#endif
	OMInfo.names = (char **)malloc(n_names * sizeof *OMInfo.names);

	if (OMInfo.names == NULL) {
		R_printf(R_STDERR, "Error: Memory allocation failed.\n");
		return R_MEM;
	}

	for (i = 0; i < n_names; i++) {
		name_offset = ys_read_u16_le(read_p, &read_p);
		OMInfo.names[i] = (char *)(onl_res + name_offset);

#       if R_OBJECTMAP_DEBUG >= R_DEBUG_VERBOSE
		R_printf(R_STDOUT,
		    "Loaded object name string: %s\n", OMInfo.names[i]);
#       endif
	}

	OMInfo.names_loaded = 1;

	return R_SUCCESS;
}

int OBJECTMAP_FreeNames(void)
/*--------------------------------------------------------------------------*\
 * Frees all storage allocated for the current object name list data
\*--------------------------------------------------------------------------*/
{
	if (!OMInfo.names_loaded) {
		return R_FAILURE;
	}

	if (OMInfo.n_names) {
		free(OMInfo.names);
	}

	OMInfo.names_loaded = 0;
	return R_SUCCESS;
}

int OBJECTMAP_GetName(int object, const char **name)
/*--------------------------------------------------------------------------*\
 * If 'object' is a valid object number in the currently loaded object 
 *  name list resource, the funciton sets '*name' to the descriptive string
 *  corresponding to 'object' and returns R_SUCCESS. Otherwise it returns
 *  R_FAILURE.
\*--------------------------------------------------------------------------*/
{
	if (!OMInfo.names_loaded) {
		return R_FAILURE;
	}

	if ((object <= 0) || (object > OMInfo.n_names)) {
		return R_FAILURE;
	}

	*name = OMInfo.names[object - 1];

	return R_SUCCESS;
}

int OBJECTMAP_GetFlags(int object, uint * flags)
{
	int i;

	if (!OMInfo.names_loaded) {
		return R_FAILURE;
	}

	if ((object <= 0) || (object > OMInfo.n_names)) {
		return R_FAILURE;
	}

	for (i = 0; i < OMInfo.n_objects; i++) {

		if (OMInfo.object_maps[i].object_num == object) {

			*flags = OMInfo.object_maps[i].flags;
			return R_SUCCESS;
		}
	}

	return R_FAILURE;
}

int OBJECTMAP_GetEPNum(int object, int *ep_num)
/*--------------------------------------------------------------------------*\
 * If 'object' is a valid object number in the currently loaded object 
 *  name list resource, the funciton sets '*ep_num' to the entrypoint number
 *  corresponding to 'object' and returns R_SUCCESS. Otherwise, it returns
 *  R_FAILURE.
\*--------------------------------------------------------------------------*/
{
	int i;

	if (!OMInfo.names_loaded) {
		return R_FAILURE;
	}

	if ((object < 0) || (object > (OMInfo.n_objects + 1))) {
		return R_FAILURE;
	}

	for (i = 0; i < OMInfo.n_objects; i++) {

		if (OMInfo.object_maps[i].object_num == object) {

			*ep_num = OMInfo.object_maps[i].script_num;
			return R_SUCCESS;
		}
	}

	return R_FAILURE;
}

int OBJECTMAP_Draw(R_SURFACE * ds, R_POINT * imouse_pt, int color, int color2)
/*--------------------------------------------------------------------------*\
 * Uses GFX_DrawLine to display all clickareas for each object in the 
 *  currently loaded object map resource.
\*--------------------------------------------------------------------------*/
{

	R_OBJECTMAP_ENTRY *object_map;
	R_CLICKAREA *clickarea;

	char txt_buf[32];

	int draw_color = color;
	int draw_txt = 0;

	int hit_object = 0;
	int object_num = 0;

	int pointcount = 0;
	int i, k;

	assert(OMInfo.initialized);

	if (!OMInfo.objects_loaded) {
		return R_FAILURE;
	}

	if (imouse_pt != NULL) {

		if (OBJECTMAP_HitTest(imouse_pt, &object_num) == R_SUCCESS) {
			hit_object = 1;
		}
	}

	for (i = 0; i < OMInfo.n_objects; i++) {

		draw_color = color;

		if (hit_object &&
		    (object_num == OMInfo.object_maps[i].object_num)) {

			snprintf(txt_buf,
			    sizeof txt_buf,
			    "obj %d: ? %d, f %X",
			    OMInfo.object_maps[i].object_num,
			    OMInfo.object_maps[i].unknown0,
			    OMInfo.object_maps[i].flags);

			draw_txt = 1;
			draw_color = color2;
		}

		object_map = &OMInfo.object_maps[i];

		for (k = 0; k < object_map->n_clickareas; k++) {

			clickarea = &object_map->clickareas[k];
			pointcount = 0;

			if (clickarea->n_points == 2) {

				/* 2 points represent a box */
				GFX_DrawFrame(ds,
				    &clickarea->points[0],
				    &clickarea->points[1], draw_color);
			} else if (clickarea->n_points > 2) {

				/* Otherwise draw a polyline */

				GFX_DrawPolyLine(ds,
				    clickarea->points,
				    clickarea->n_points, draw_color);

			}

		}		/* end for() clickareas */
	}			/* end for() objects */

	if (draw_txt) {

		FONT_Draw(SMALL_FONT_ID,
		    ds,
		    txt_buf,
		    0,
		    2, 2, SYSGFX_GetWhite(), SYSGFX_GetBlack(), FONT_OUTLINE);
	}

	return R_SUCCESS;
}

int OBJECTMAP_HitTest(R_POINT * imouse_pt, int *object_num)
{

	R_POINT imouse;
	R_OBJECTMAP_ENTRY *object_map;
	R_CLICKAREA *clickarea;
	R_POINT *points;
	int n_points;

	int i, k;

	assert((imouse_pt != NULL) && (object_num != NULL));

	imouse.x = imouse_pt->x;
	imouse.y = imouse_pt->y;

	/* Loop through all scene objects */
	for (i = 0; i < OMInfo.n_objects; i++) {

		object_map = &OMInfo.object_maps[i];

		/* Hit-test all clickareas for this object */
		for (k = 0; k < object_map->n_clickareas; k++) {

			clickarea = &object_map->clickareas[k];

			n_points = clickarea->n_points;
			points = clickarea->points;

			if (n_points == 2) {
				/* Hit-test a box region */
				if ((imouse.x > points[0].x) &&
				    (imouse.x <= points[1].x) &&
				    (imouse.y > points[0].y) &&
				    (imouse.y <= points[1].y)) {

					*object_num = object_map->object_num;

					return R_SUCCESS;
				}
			} else if (n_points > 2) {
				/* Hit-test a polygon */
				if (MATH_HitTestPoly(points, n_points, imouse)) {

					*object_num = object_map->object_num;

					return R_SUCCESS;
				}
			}

		}		/* end for() clickareas */
	}			/* end for() objects */

	*object_num = 0;

	return R_FAILURE;
}

static void CF_object_info(int argc, char *argv[])
{
	int i;

	YS_IGNORE_PARAM(argc);
	YS_IGNORE_PARAM(argv);

	if (!OMInfo.initialized) {
		return;
	}

	CON_Print("%d objects loaded.", OMInfo.n_objects);

	for (i = 0; i < OMInfo.n_objects; i++) {

		CON_Print("%s:", OMInfo.names[i]);
		CON_Print
		    ("%d. Unk1: %d, flags: %X, name_i: %d, scr_n: %d, ca_ct: %d",
		    i, OMInfo.object_maps[i].unknown0,
		    OMInfo.object_maps[i].flags,
		    OMInfo.object_maps[i].object_num,
		    OMInfo.object_maps[i].script_num,
		    OMInfo.object_maps[i].n_clickareas);

	}

	return;
}

} // End of namespace Saga

--- NEW FILE: objectmap.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/objectmap.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Object map / Object click-area module header file

 Notes: 
*/

#ifndef SAGA_OBJECTMAP_H_
#define SAGA_OBJECTMAP_H_

namespace Saga {

typedef struct R_CLICKAREA_tag {

	int n_points;
	R_POINT *points;

} R_CLICKAREA;

typedef struct R_OBJECTMAP_ENTRY_tag {

	int unknown0;
	uint flags;

	int object_num;
	int script_num;

	int n_clickareas;
	R_CLICKAREA *clickareas;

} R_OBJECTMAP_ENTRY;

typedef struct R_OBJECTMAP_INFO_tag {

	int initialized;

	int objects_loaded;
	int n_objects;
	R_OBJECTMAP_ENTRY *object_maps;

	int names_loaded;
	int n_names;
	char **names;

} R_OBJECTMAP_INFO;

static void CF_object_info(int argc, char *argv[]);

} // End of namespace Saga

#endif				/* SAGA_OBJECTMAP_H_ */

--- NEW FILE: objectmap_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/objectmap_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Object map module public header file

 Notes: 
*/

#ifndef SAGA_OBJECTMAP_MOD_H__
#define SAGA_OBJECTMAP_MOD_H__

namespace Saga {

enum R_OBJECT_FLAGS {

	R_OBJECT_NORMAL = 0x02
};

int OBJECTMAP_Register(void);

int OBJECTMAP_Init(void);

int OBJECTMAP_Shutdown(void);

int OBJECTMAP_Load(const uchar * om_res, size_t om_res_len);

int OBJECTMAP_Free(void);

int OBJECTMAP_LoadNames(const uchar * onl_res, size_t onl_res_len);

int OBJECTMAP_FreeNames(void);

int OBJECTMAP_GetName(int object, const char **name);

int OBJECTMAP_GetFlags(int object, uint * flags);

int OBJECTMAP_GetEPNum(int object, int *ep_num);

int
OBJECTMAP_Draw(R_SURFACE * draw_surface,
    R_POINT * imouse_pt, int color, int color2);

int OBJECTMAP_HitTest(R_POINT * imouse_pt, int *object_num);

} // End of namespace Saga

#endif				/* SAGA_OBJECTMAP_MOD_H__ */

--- NEW FILE: palanim.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/palanim.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Palette animation module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "events_mod.h"
#include "game_mod.h"

/*
 * Begin module:
\*--------------------------------------------------------------------------*/
#include "palanim_mod.h"
#include "palanim.h"

namespace Saga {

static PALANIM_DATA PAnimData;

int PALANIM_Load(const uchar * resdata, size_t resdata_len)
{
	const uchar *read_p = resdata;
	void *test_p;

	uint i;

	YS_IGNORE_PARAM(resdata_len);

	if (PAnimData.loaded) {
		PALANIM_Free();
	}

	if (resdata == NULL) {
		return R_FAILURE;
	}

	if (GAME_GetGameType() == R_GAMETYPE_IHNM) {
		return R_SUCCESS;
	}

	PAnimData.entry_count = ys_read_u16_le(read_p, &read_p);

	R_printf(R_STDOUT,
	    "PALANIM_Load(): Loading %d PALANIM entries.\n",
	    PAnimData.entry_count);

	test_p = calloc(PAnimData.entry_count, sizeof(PALANIM_ENTRY));
	if (test_p == NULL) {
		R_printf(R_STDERR, "PALANIM_Load(): Allocation failure.\n");
		return R_MEM;
	}

	PAnimData.entries = (PALANIM_ENTRY *)test_p;

	for (i = 0; i < PAnimData.entry_count; i++) {

		int color_count;
		int pal_count;
		int p, c;

		color_count = ys_read_u16_le(read_p, &read_p);
		pal_count = ys_read_u16_le(read_p, &read_p);

		PAnimData.entries[i].pal_count = pal_count;
		PAnimData.entries[i].color_count = color_count;

#       if 0
		R_printf(R_STDOUT,
		    "PALANIM_Load(): Entry %d: Loading %d palette indices.\n",
		    i, pal_count);
#endif

		test_p = calloc(1, sizeof(char) * pal_count);
		if (test_p == NULL) {
			R_printf(R_STDERR,
			    "PALANIM_Load(): Allocation failure.\n");
			return R_MEM;
		}

		PAnimData.entries[i].pal_index = (uchar *)test_p;

#       if 0
		R_printf(R_STDOUT,
		    "PALANIM_Load(): Entry %d: Loading %d SAGA_COLOR "
		    "structures.\n", i, color_count);
#       endif

		test_p = calloc(1, sizeof(R_COLOR) * color_count);
		if (test_p == NULL) {
			R_printf(R_STDERR,
			    "PALANIM_Load(): Allocation failure.\n");
			return R_MEM;
		}

		PAnimData.entries[i].colors = (R_COLOR *)test_p;

		for (p = 0; p < pal_count; p++) {
			PAnimData.entries[i].pal_index[p] =
			    (uchar) ys_read_u8(read_p, &read_p);
		}

		for (c = 0; c < color_count; c++) {
			PAnimData.entries[i].colors[c].red =
			    (uchar) ys_read_u8(read_p, &read_p);

			PAnimData.entries[i].colors[c].green =
			    (uchar) ys_read_u8(read_p, &read_p);

			PAnimData.entries[i].colors[c].blue =
			    (uchar) ys_read_u8(read_p, &read_p);
		}
	}

	PAnimData.loaded = 1;
	return R_SUCCESS;

}

int PALANIM_CycleStart(void)
{

	R_EVENT event;

	if (!PAnimData.loaded) {
		return R_FAILURE;
	}

	event.type = R_ONESHOT_EVENT;
	event.code = R_PALANIM_EVENT;
	event.op = EVENT_CYCLESTEP;
	event.time = PALANIM_CYCLETIME;

	EVENT_Queue(&event);

	return R_SUCCESS;

}

int PALANIM_CycleStep(int vectortime)
{
	R_SURFACE *back_buf;

	static PALENTRY pal[256];
	uint pal_index;
	uint col_index;

	uint i, j;
	uint cycle;
	uint cycle_limit;

	R_EVENT event;

	if (!PAnimData.loaded) {
		return R_FAILURE;
	}

	SYSGFX_GetCurrentPal(pal);
	back_buf = SYSGFX_GetBackBuffer();

	for (i = 0; i < PAnimData.entry_count; i++) {

		cycle = PAnimData.entries[i].cycle;
		cycle_limit = PAnimData.entries[i].color_count;

		for (j = 0; j < PAnimData.entries[i].pal_count; j++) {

			pal_index =
			    (unsigned char)PAnimData.entries[i].pal_index[j];
			col_index = (cycle + j) % cycle_limit;

			pal[pal_index].red =
			    (uchar) PAnimData.entries[i].colors[col_index].red;

			pal[pal_index].green =
			    (uchar) PAnimData.entries[i].colors[col_index].
			    green;

			pal[pal_index].blue =
			    (uchar) PAnimData.entries[i].colors[col_index].
			    blue;
		}

		PAnimData.entries[i].cycle++;

		if (PAnimData.entries[i].cycle == cycle_limit) {
			PAnimData.entries[i].cycle = 0;
		}
	}

	SYSGFX_SetPalette(back_buf, pal);

	event.type = R_ONESHOT_EVENT;
	event.code = R_PALANIM_EVENT;
	event.op = EVENT_CYCLESTEP;
	event.time = vectortime + PALANIM_CYCLETIME;

	EVENT_Queue(&event);

	return R_SUCCESS;

}

int PALANIM_Free(void)
{

	uint i;

	if (!PAnimData.loaded) {
		return R_FAILURE;
	}

	for (i = 0; i < PAnimData.entry_count; i++) {
#if 0
		R_printf(R_STDOUT,
		    "PALANIM_Free(): Entry %d: Freeing colors.\n", i);
#endif
		free(PAnimData.entries[i].colors);
#if 0
		R_printf(R_STDOUT,
		    "PALANIM_Free(): Entry %d: Freeing indices.\n", i);
#endif
		free(PAnimData.entries[i].pal_index);

	}

	R_printf(R_STDOUT, "PALANIM_Free(): Freeing entries.\n", i);

	free(PAnimData.entries);

	PAnimData.loaded = 0;

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: palanim.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/palanim.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Palette animation module header file

 Notes: 
*/

#ifndef SAGA_PALANIM_H
#define SAGA_PALANIM_H

#include "reinherit.h"

namespace Saga {

#define PALANIM_CYCLETIME 100

typedef struct PALANIM_ENTRY_tag {

	uint pal_count;
	uint color_count;
	uint cycle;

	uchar *pal_index;
	R_COLOR *colors;

} PALANIM_ENTRY;

typedef struct PALANIM_DATA_tag {

	int loaded;
	uint entry_count;

	PALANIM_ENTRY *entries;

} PALANIM_DATA;

} // End of namespace Saga

#endif


--- NEW FILE: palanim_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/palanim_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Palette animation module public header file

 Notes: 
*/

#ifndef SAGA_PALANIM_MOD_H__
#define SAGA_PALANIM_MOD_H__

namespace Saga {

int PALANIM_Load(const uchar *, size_t);

int PALANIM_CycleStart(void);

int PALANIM_CycleStep(int vectortime);

int PALANIM_Free(void);

} // End of namespace Saga

#endif				/* SAGA_PALANIM_MOD_H__ */

--- NEW FILE: reinherit.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/reinherit.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Main Header File

 Notes: 
*/

#ifndef SAGA_REINHERIT_H_
#define SAGA_REINHERIT_H_

#include "stdafx.h"

#include "base/engine.h"

/*
 * Architecture conditionals
\*--------------------------------------------------------------------------*/
#include "x86_32.h"

/*
 * Implementation conditionals
\*--------------------------------------------------------------------------*/
#define R_ENV_LINUX
#include "sys_interface.h"

namespace Saga {

#define R_MAXPATH 512

/* For debug message processing */
#define R_DEBUG_NONE 0
#define R_DEBUG_INFO 1
#define R_DEBUG_VERBOSE 2
#define R_DEBUG_PARANOID 3

#define R_MEMFAIL_MSG "Memory allocation error."

/*
 * Define opaque types
\*--------------------------------------------------------------------------*/

/* r_rscfile */
typedef struct R_RSCFILE_CONTEXT_tag R_RSCFILE_CONTEXT;

/* r_script */
typedef struct R_SEMAPHORE_tag R_SEMAPHORE;

/*
 * Define common data types
\*--------------------------------------------------------------------------*/

#ifndef HAVE_UCHAR
typedef unsigned char uchar;
#endif
#ifndef HAVE_ULONG
typedef unsigned long ulong;
#endif
#ifndef HAVE_UINT
typedef unsigned int uint;
#endif

typedef struct R_POINT_tag {

	int x;
	int y;

} R_POINT;

typedef struct R_RECT_tag {

	int x1;
	int y1;
	int x2;
	int y2;

} R_RECT;

#define R_MAKERECT( rect, x1, y1, x2, y2 ) \
    ( rect.x1 = x1, rect.y1 = y1, rect.x2 = x2, rect.y2 = y2, &rect )

typedef struct R_COLOR_tag {

	int red;
	int green;
	int blue;
	int alpha;

} R_COLOR;

typedef struct R_SURFACE_tag {

	uchar *buf;
	int buf_w;
	int buf_h;
	int buf_pitch;

	int bpp;

	R_RECT clip_rect;

	void *impl_src;

} R_SURFACE;

typedef struct R_SOUNDBUFFER_tag {

	uchar *res_data;
	size_t res_len;

	long s_freq;
	int s_samplebits;
	int s_stereo;
	int s_signed;

	uchar *s_buf;
	size_t s_buf_len;

} R_SOUNDBUFFER;

#define R_RGB_RED   0x00FF0000UL
#define R_RGB_GREEN 0x0000FF00UL
#define R_RGB_BLUE  0x000000FFUL

typedef struct SAGA_COLOR_tag {

	R_UINT8 r;
	R_UINT8 g;
	R_UINT8 b;

} SAGA_COLOR;

#define SAGA_COLOR_LEN 3

typedef struct PALENTRY_TAG {

	R_UINT8 red;
	R_UINT8 green;
	R_UINT8 blue;

} PALENTRY;

enum R_ERRORCODE {

	R_STOP = -3,
	R_MEM = -2,
	R_FAILURE = -1,
	R_SUCCESS = 0

};


/*
 * r_cmdline.c
\*--------------------------------------------------------------------------*/
typedef struct R_EXECINFO_tag {

	int start_scene;
	int no_verify;
	int no_sound;
	int no_music;
	int windowed;
	char *game_dir;

} R_EXECINFO;

int R_ReadCommandLine(int argc, char **argv, R_EXECINFO * execinfo);

/*
 * r_main.c
\*--------------------------------------------------------------------------*/
int main(int argc, char *argv[]);

void R_Shutdown(int param);

/*
 * r_misc.c
\*--------------------------------------------------------------------------*/
int Granulate(int value, int granularity);

/*
 * r_transitions.c
\*--------------------------------------------------------------------------*/
int TRANSITION_Dissolve(uchar * dst_img,
    int dst_w,
    int dst_h,
    int dst_p, const uchar * src_img, int src_p, int flags, double percent);

/*--------------------------------------------------------------------------*\
 * System specific routines
\*--------------------------------------------------------------------------*/

/*
 * System : IO
\*--------------------------------------------------------------------------*/

int SYSIO_Init(void);
int SYSIO_Shutdown(void);

/*
 * System : Filesystem
\*--------------------------------------------------------------------------*/

int SYSFS_GetFileLen(FILE * file_p, ulong * len);
int SYSFS_GetFQFN(const char *f_dir,
    const char *f_name, char *buf, size_t buf_len);

/*
 * System : Sound
\*--------------------------------------------------------------------------*/
int SYSSOUND_Init(int enabled);
int SYSSOUND_Shutdown(void);

int SYSSOUND_Play(int sound_rn, int channel);
int SYSSOUND_Pause(int channel);
int SYSSOUND_Resume(int channel);
int SYSSOUND_Stop(int channel);

int SYSSOUND_PlayVoice(R_SOUNDBUFFER *);
int SYSSOUND_PauseVoice(void);
int SYSSOUND_ResumeVoice(void);
int SYSSOUND_StopVoice(void);

/*
 * System : Music
\*--------------------------------------------------------------------------*/
enum SYSMUSIC_FLAGS {

	R_MUSIC_LOOP = 0x01
};

int SYSMUSIC_Init(int enabled);
int SYSMUSIC_Shutdown(void);

int SYSMUSIC_Play(ulong music_rn, uint flags);
int SYSMUSIC_Pause(void);
int SYSMUSIC_Resume(void);
int SYSMUSIC_Stop(void);

/*
 * System : Graphics
\*--------------------------------------------------------------------------*/
#define R_PAL_ENTRIES 256

typedef struct R_SYSGFX_INIT_tag {

	int backbuf_w;
	int backbuf_h;
	int backbuf_bpp;

	int screen_w;
	int screen_h;
	int screen_bpp;

	int fullscreen;

} R_SYSGFX_INIT;

int SYSGFX_Init(R_SYSGFX_INIT *);

R_SURFACE *SYSGFX_GetScreenSurface(void);
R_SURFACE *SYSGFX_GetBackBuffer(void);

int SYSGFX_LockSurface(R_SURFACE * surface);
int SYSGFX_UnlockSurface(R_SURFACE * surface);

R_SURFACE *SYSGFX_CreateSurface(int w, int h, int bpp);
R_SURFACE *SYSGFX_FormatToDisplay(R_SURFACE * surface);
int SYSGFX_DestroySurface(R_SURFACE * surface);

int SYSGFX_GetWhite(void);
int SYSGFX_GetBlack(void);
int SYSGFX_MatchColor(unsigned long colormask);
int SYSGFX_SetPalette(R_SURFACE * surface, PALENTRY * pal);
int SYSGFX_GetCurrentPal(PALENTRY * src_pal);

int SYSGFX_PalToBlack(R_SURFACE * surface, PALENTRY * src_pal, double percent);

int SYSGFX_BlackToPal(R_SURFACE * surface, PALENTRY * src_pal, double percent);

/*
 * System : Timer 
\*--------------------------------------------------------------------------*/
typedef struct R_SYSTIMER_tag R_SYSTIMER;

typedef void (*R_SYSTIMER_CALLBACK) (unsigned long, void *);

int SYSTIMER_InitMSCounter(void);
unsigned long SYSTIMER_ReadMSCounter(void);

int SYSTIMER_ResetMSCounter(void);
int SYSTIMER_Sleep(uint msec);
int SYSTIMER_CreateTimer(R_SYSTIMER **,
    unsigned long, void *, R_SYSTIMER_CALLBACK);
int SYSTIMER_DestroyTimer(R_SYSTIMER *);

/*
 * System : Input 
\*--------------------------------------------------------------------------*/
int SYSINPUT_Init(void);
int SYSINPUT_ProcessInput(void);
int SYSINPUT_GetMousePos(int *mouse_x, int *mouse_y);
int SYSINPUT_HideMouse(void);
int SYSINPUT_ShowMouse(void);

/*** sys_signal.c ***/
int ITESYS_CheckSignal(void);

} // End of namespace Saga

#endif				/* SAGA_REINHERIT_H_ */

--- NEW FILE: render.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/render.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Main rendering loop

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

#include <SDL.h>

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "actor_mod.h"
#include "console_mod.h"
#include "cvar_mod.h"
#include "font_mod.h"
#include "game_mod.h"
#include "gfx_mod.h"
#include "interface_mod.h"
#include "scene_mod.h"
#include "sprite_mod.h"
#include "text_mod.h"

#include "actionmap_mod.h"
#include "objectmap_mod.h"

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "render_mod.h"
#include "render.h"

namespace Saga {

static R_RENDER_MODULE RenderModule;

const char *test_txt = "The quick brown fox jumped over the lazy dog. "
    "She sells sea shells down by the sea shore.";

int RENDER_Register(void)
{

	/* Register "r_fullscreen" cfg cvar
	 * \*----------------------------------------- */
	RenderModule.r_fullscreen = R_FULLSCREEN_DEFAULT;

	if (CVAR_Register_I(&RenderModule.r_fullscreen,
		"r_fullscreen", NULL, R_CVAR_CFG, 0, 1) != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Register "r_doubleres" cfg cvar
	 * \*----------------------------------------- */
	RenderModule.r_doubleres = R_DOUBLERES_DEFAULT;

	if (CVAR_Register_I(&RenderModule.r_doubleres,
		"r_doubleres", NULL, R_CVAR_CFG, 0, 1) != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Register "r_hicolor" cfg cvar
	 * \*----------------------------------------- */
	RenderModule.r_hicolor = R_HICOLOR_DEFAULT;

	if (CVAR_Register_I(&RenderModule.r_hicolor,
		"r_hicolor", NULL, R_CVAR_CFG, 0, 1) != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Register "r_softcursor" cfg cvar
	 * \*----------------------------------------- */
	RenderModule.r_softcursor = R_SOFTCURSOR_DEFAULT;

	if (CVAR_Register_I(&RenderModule.r_softcursor,
		"r_softcursor", NULL, R_CVAR_CFG, 0, 1) != R_SUCCESS) {

		return R_FAILURE;
	}

	return R_SUCCESS;
}

int RENDER_Init(void)
{

	R_GAME_DISPLAYINFO disp_info = { 0 };
	R_SYSGFX_INIT gfx_init = { 0 };

	int result;

	int tmp_w, tmp_h, tmp_bytepp;

	/* Initialize system graphics
	 * \*------------------------------------------------------------- */
	GAME_GetDisplayInfo(&disp_info);

	gfx_init.backbuf_bpp = 8;	/* all games are 8 bpp so far */
	gfx_init.backbuf_w = disp_info.logical_w;
	gfx_init.backbuf_h = disp_info.logical_h;

	if (RenderModule.r_hicolor) {
		gfx_init.screen_bpp = 16;
	} else {
		gfx_init.screen_bpp = 8;
	}

	gfx_init.screen_w = disp_info.logical_w;
	gfx_init.screen_h = disp_info.logical_h;

	/* Don't try to double a game exceeding the resolution limit
	 * (640x480 would get doubled to 1280 x 960!) */
	if (disp_info.logical_w > R_DOUBLE_RESLIMIT) {
		RenderModule.r_doubleres = 0;
	}

	if (RenderModule.r_doubleres) {

		gfx_init.screen_w *= 2;
		gfx_init.screen_h *= 2;
	}

	gfx_init.fullscreen = RenderModule.r_fullscreen;

	if (SYSGFX_Init(&gfx_init) != R_SUCCESS) {

		return R_FAILURE;
	}

	/* Initialize FPS timer callback
	 * \*------------------------------------------------------------- */
	result = SYSTIMER_CreateTimer(&RenderModule.r_fps_timer,
	    1000, NULL, RENDER_FpsTimer);
	if (result != R_SUCCESS) {
		return R_FAILURE;
	}

	/* Create background buffer 
	 * \*------------------------------------------------------------- */
	RenderModule.r_bg_buf_w = disp_info.logical_w;
	RenderModule.r_bg_buf_h = disp_info.logical_h;

	RenderModule.r_bg_buf = (uchar *)calloc(disp_info.logical_w,
	    disp_info.logical_h);

	if (RenderModule.r_bg_buf == NULL) {
		return R_MEM;
	}

	/* Allocate temp buffer for animation decoding, 
	 * graphics scalers (2xSaI), etc.
	 \*-------------------------------------------------------------*/
	tmp_w = disp_info.logical_w;
	tmp_h = disp_info.logical_h + 4;	/* BG unbanking requres extra rows */
	tmp_bytepp = 1;

	if (RenderModule.r_doubleres) {
		tmp_w *= 2;
		tmp_h *= 2;
	}

	if (RenderModule.r_hicolor) {
		tmp_bytepp = 2;
	}

	RenderModule.r_tmp_buf = (uchar *)calloc(1, tmp_w * tmp_h * tmp_bytepp);
	if (RenderModule.r_tmp_buf == NULL) {

		free(RenderModule.r_bg_buf);
		return R_MEM;
	}

	RenderModule.r_tmp_buf_w = tmp_w;
	RenderModule.r_tmp_buf_h = tmp_h;

	RenderModule.r_screen_surface = SYSGFX_GetScreenSurface();
	RenderModule.r_backbuf_surface = SYSGFX_GetBackBuffer();

	/* Initialize cursor state
	 * \*------------------------------------------------------------- */
	if (RenderModule.r_softcursor) {
		SYSINPUT_HideMouse();
	}

	RenderModule.initialized = 1;

	return R_SUCCESS;
}

int RENDER_DrawScene(void)
{

	R_SURFACE *screen_surface;
	R_SURFACE *backbuf_surface;
	R_SURFACE *display_surface;

	R_GAME_DISPLAYINFO disp_info = { 0 };
	R_SCENE_INFO scene_info;
	SCENE_BGINFO bg_info;

	R_POINT bg_pt;

	char txt_buf[20];
	int fps_width;

	R_POINT mouse_pt;
	int mouse_x, mouse_y;

	int surface_converted = 0;

	if (!RenderModule.initialized) {
		return R_FAILURE;
	}

	RenderModule.r_framecount++;

	screen_surface = RenderModule.r_screen_surface;
	backbuf_surface = RenderModule.r_backbuf_surface;

	/* Get mouse coordinates
	 * \*------------------------------------------------------------- */
	SYSINPUT_GetMousePos(&mouse_x, &mouse_y);

	mouse_pt.x = mouse_x;
	mouse_pt.y = mouse_y;

	if (RenderModule.r_doubleres) {
		mouse_pt.x /= 2;
		mouse_pt.y /= 2;
	}

	SCENE_GetBGInfo(&bg_info);
	GAME_GetDisplayInfo(&disp_info);
	bg_pt.x = 0;
	bg_pt.y = 0;

	/* Display scene background
	 * \*--------------------------------------------------------- */
	SCENE_Draw(backbuf_surface);

	/* Display scene maps, if applicable
	 * \*--------------------------------------------------------- */
	if (RENDER_GetFlags() & RF_OBJECTMAP_TEST) {

		OBJECTMAP_Draw(backbuf_surface,
		    &mouse_pt, SYSGFX_GetWhite(), SYSGFX_GetBlack());

		ACTIONMAP_Draw(backbuf_surface, SYSGFX_MatchColor(R_RGB_RED));
	}

	/* Draw queued actors
	 * \*--------------------------------------------------------- */
	ACTOR_DrawList();

	/* Draw queued text strings
	 * \*--------------------------------------------------------- */
	SCENE_GetInfo(&scene_info);

	TEXT_DrawList(scene_info.text_list, backbuf_surface);

	/* Handle user input
	 * \*--------------------------------------------------------- */
	SYSINPUT_ProcessInput();

	/* Display rendering information
	 * \*--------------------------------------------------------- */
	if (RenderModule.r_flags & RF_SHOW_FPS) {

		sprintf(txt_buf, "%d", RenderModule.r_fps);

		fps_width = FONT_GetStringWidth(SMALL_FONT_ID,
		    txt_buf, 0, FONT_NORMAL);

		FONT_Draw(SMALL_FONT_ID,
		    backbuf_surface,
		    txt_buf,
		    0,
		    backbuf_surface->buf_w - fps_width, 2,
		    SYSGFX_GetWhite(), SYSGFX_GetBlack(), FONT_OUTLINE);

		switch (RenderModule.r_mode) {

		case RM_SCANLINES:
			FONT_Draw(SMALL_FONT_ID,
			    backbuf_surface,
			    "Scanlines",
			    0,
			    2, 2,
			    SYSGFX_GetWhite(),
			    SYSGFX_GetBlack(), FONT_OUTLINE);
			break;

		case RM_2XSAI:
			FONT_Draw(SMALL_FONT_ID,
			    backbuf_surface,
			    "2xSaI",
			    0,
			    2, 2,
			    SYSGFX_GetWhite(),
			    SYSGFX_GetBlack(), FONT_OUTLINE);
			break;

		case RM_SUPER2XSAI:
			FONT_Draw(SMALL_FONT_ID,
			    backbuf_surface,
			    "Super2xSaI",
			    0,
			    2, 2,
			    SYSGFX_GetWhite(),
			    SYSGFX_GetBlack(), FONT_OUTLINE);
			break;

		case RM_SUPEREAGLE:
			FONT_Draw(SMALL_FONT_ID,
			    backbuf_surface,
			    "SuperEagle",
			    0,
			    2, 2,
			    SYSGFX_GetWhite(),
			    SYSGFX_GetBlack(), FONT_OUTLINE);
			break;
		}

	}

	/* Display "paused game" message, if applicable
	 * \*--------------------------------------------------------- */
	if (RenderModule.r_flags & RF_RENDERPAUSE) {

		int msg_len = strlen(R_PAUSEGAME_MSG);
		int msg_w = FONT_GetStringWidth(BIG_FONT_ID,
		    R_PAUSEGAME_MSG,
		    msg_len,
		    FONT_OUTLINE);

		FONT_Draw(BIG_FONT_ID,
		    backbuf_surface,
		    R_PAUSEGAME_MSG,
		    msg_len,
		    (backbuf_surface->buf_w - msg_w) / 2, 90,
		    SYSGFX_GetWhite(), SYSGFX_GetBlack(), FONT_OUTLINE);
	}

	/* Update user interface
	 * \*--------------------------------------------------------- */

	INTERFACE_Update(&mouse_pt, UPDATE_MOUSEMOVE);

	if (RenderModule.r_softcursor) {
		GFX_DrawCursor(backbuf_surface, &mouse_pt);
	}

	/* Display text formatting test, if applicable
	 * \*--------------------------------------------------------- */
	if (RenderModule.r_flags & RF_TEXT_TEST) {

		TEXT_Draw(MEDIUM_FONT_ID,
		    backbuf_surface,
		    test_txt,
		    mouse_pt.x, mouse_pt.y,
		    SYSGFX_GetWhite(),
		    SYSGFX_GetBlack(), FONT_OUTLINE | FONT_CENTERED);
	}

	/* Display palette test, if applicable
	 * \*--------------------------------------------------------- */
	if (RenderModule.r_flags & RF_PALETTE_TEST) {

		GFX_DrawPalette(backbuf_surface);
	}

	/* Draw console
	 * \*--------------------------------------------------------- */
	CON_Draw(backbuf_surface);

	/* Display the current frame
	 * \*--------------------------------------------------------- */

	if (RenderModule.r_hicolor) {

		display_surface = SYSGFX_FormatToDisplay(backbuf_surface);

		if (display_surface == NULL) {
			R_printf(R_STDERR,
			    "Error: Back buffer conversion failed!\n");

			return R_FAILURE;
		}

		surface_converted = 1;
	} else {

		display_surface = backbuf_surface;
	}

	SYSGFX_LockSurface(screen_surface);
	SYSGFX_LockSurface(display_surface);

	switch (RenderModule.r_mode) {

	case RM_SCANLINES:

		break;

	default:

		if (RenderModule.r_doubleres) {

			GFX_Scale2x(screen_surface, display_surface);
		} else {

			GFX_SimpleBlit(screen_surface, display_surface);
		}

		break;
	}

	SYSGFX_UnlockSurface(display_surface);
	SYSGFX_UnlockSurface(screen_surface);

	if (surface_converted) {

		SYSGFX_DestroySurface(display_surface);
	}

	// FIXME
	SDL_UpdateRect((SDL_Surface *)screen_surface->impl_src, 0, 0, 0, 0);

	return R_SUCCESS;
}

unsigned int RENDER_GetFrameCount(void)
{

	return RenderModule.r_framecount;
}

unsigned int RENDER_ResetFrameCount(void)
{
	unsigned int framecount = RenderModule.r_framecount;

	RenderModule.r_framecount = 0;

	return framecount;
}

void RENDER_FpsTimer(unsigned long interval, void *param)
{
	YS_IGNORE_PARAM(interval);
	YS_IGNORE_PARAM(param);

	RenderModule.r_fps = RenderModule.r_framecount;
	RenderModule.r_framecount = 0;

	return;
}

void RENDER_ConvertMousePt(R_POINT * mouse_pt)
{
	assert(mouse_pt != NULL);

	if (RenderModule.r_doubleres) {

		mouse_pt->x /= 2;
		mouse_pt->y /= 2;
	}

	return;
}

unsigned int RENDER_GetFlags(void)
{
	return RenderModule.r_flags;
}

void RENDER_SetFlag(unsigned int flag)
{

	RenderModule.r_flags |= flag;

	return;
}

void RENDER_ToggleFlag(unsigned int flag)
{

	RenderModule.r_flags ^= flag;

	return;
}

int RENDER_SetMode(int mode)
{

	switch (mode) {

	case RM_SCANLINES:

		if (!RenderModule.r_doubleres) {

			return R_FAILURE;
		}

		break;

	case RM_2XSAI:

		if (!RenderModule.r_doubleres || !RenderModule.r_hicolor) {

			return R_FAILURE;
		}

		break;

	case RM_SUPER2XSAI:

		if (!RenderModule.r_doubleres || !RenderModule.r_hicolor) {

			return R_FAILURE;
		}

		break;

	case RM_SUPEREAGLE:

		if (!RenderModule.r_doubleres || !RenderModule.r_hicolor) {

			return R_FAILURE;
		}

		break;

	default:
		break;

	}

	RenderModule.r_mode = mode;

	return R_SUCCESS;
}

int RENDER_GetBufferInfo(R_BUFFER_INFO * r_bufinfo)
{

	assert(r_bufinfo != NULL);

	r_bufinfo->r_bg_buf = RenderModule.r_bg_buf;
	r_bufinfo->r_bg_buf_w = RenderModule.r_bg_buf_w;
	r_bufinfo->r_bg_buf_h = RenderModule.r_bg_buf_h;

	r_bufinfo->r_tmp_buf = RenderModule.r_tmp_buf;
	r_bufinfo->r_tmp_buf_w = RenderModule.r_tmp_buf_w;
	r_bufinfo->r_tmp_buf_h = RenderModule.r_tmp_buf_h;

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: render.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/render.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Main rendering loop - private header

 Notes: 
*/

#ifndef SAGA_RENDER_H_
#define SAGA_RENDER_H_

namespace Saga {

/* Render module CVAR defaults */
#define R_FULLSCREEN_DEFAULT 0
#define R_DOUBLERES_DEFAULT  1
#define R_HICOLOR_DEFAULT    1
#define R_SOFTCURSOR_DEFAULT 1

#define R_DOUBLE_RESLIMIT 320

#define R_PAUSEGAME_MSG "PAWS GAME"

typedef struct R_RENDER_MODULE_tag {

	int initialized;

	/* Init cvars */
	int r_fullscreen;
	int r_doubleres;
	int r_hicolor;
	int r_softcursor;

	/* Module data */
	R_SURFACE *r_screen_surface;
	R_SURFACE *r_display_surface;
	R_SURFACE *r_backbuf_surface;

	uchar *r_bg_buf;
	int r_bg_buf_w;
	int r_bg_buf_h;

	uchar *r_tmp_buf;
	int r_tmp_buf_w;
	int r_tmp_buf_h;

	R_SYSTIMER *r_fps_timer;
	R_SPRITELIST *r_test_sprite;

	unsigned int r_fps;
	unsigned int r_framecount;

	unsigned int r_flags;
	int r_mode;

} R_RENDER_MODULE;

void RENDER_FpsTimer(unsigned long interval, void *param);

} // End of namespace Saga

#endif				/* SAGA_RENDER_H_ */

--- NEW FILE: render_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/render_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Main rendering loop - public header

 Notes: 
*/

#ifndef SAGA_RENDER_MOD_H__
#define SAGA_RENDER_MOD_H__

namespace Saga {

enum RENDER_FLAGS {

	RF_SHOW_FPS = 0x01,
	RF_PALETTE_TEST = 0x02,
	RF_TEXT_TEST = 0x04,
	RF_OBJECTMAP_TEST = 0x08,
	RF_RENDERPAUSE = 0x10,
	RF_GAMEPAUSE = 0x20
};

enum RENDER_MODES {
	RM_NORMAL,
	RM_SCANLINES,
	RM_SCANLINES50,
	RM_2XSAI,
	RM_SUPER2XSAI,
	RM_SUPEREAGLE,
	RM_BILINEAR
};

typedef struct R_BUFFER_INFO_tag {

	uchar *r_bg_buf;
	int r_bg_buf_w;
	int r_bg_buf_h;

	uchar *r_tmp_buf;
	int r_tmp_buf_w;
	int r_tmp_buf_h;

} R_BUFFER_INFO;

int RENDER_Register(void);

int RENDER_Init(void);

int RENDER_DrawScene(void);

void RENDER_ConvertMousePt(R_POINT *);

unsigned int RENDER_GetFlags(void);

void RENDER_SetFlag(unsigned int);

void RENDER_ToggleFlag(unsigned int);

int RENDER_SetMode(int);

unsigned int RENDER_GetFrameCount(void);

unsigned int RENDER_ResetFrameCount(void);

int RENDER_GetBufferInfo(R_BUFFER_INFO *);

} // End of namespace Saga

#endif				/* SAGA_RENDER_MOD_H__ */

--- NEW FILE: rscfile.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/rscfile.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    RSC Resource file management module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "rscfile_mod.h"
#include "rscfile.h"

namespace Saga {

R_RSCFILE_CONTEXT *RSC_CreateContext(void)
{
	R_RSCFILE_CONTEXT empty_context = { 0 };
	R_RSCFILE_CONTEXT *new_context;

	new_context = (R_RSCFILE_CONTEXT *)malloc(sizeof *new_context);
	if (new_context == NULL) {
		return NULL;
	}

	*new_context = empty_context;

	return new_context;
}

int RSC_OpenContext(R_RSCFILE_CONTEXT * rsc_context, const char *fspec)
{
	FILE *rsc_fp;
	int result;

	rsc_fp = fopen(fspec, "rb");
	if (rsc_fp == NULL) {
		return R_FAILURE;
	}

	if (rsc_context->rc_file_open) {
		return R_FAILURE;
	}

	rsc_context->rc_file_fspec = fspec;
	rsc_context->rc_file_p = rsc_fp;

	result = ys_get_filesize(rsc_fp, &rsc_context->rc_file_size, NULL);
	if (result != YS_E_SUCCESS) {
		fclose(rsc_fp);
		return R_FAILURE;
	}

	if (RSC_LoadRSC(rsc_context) != R_SUCCESS) {
		return R_FAILURE;
	}

	rsc_context->rc_file_open = 1;
	rsc_context->rc_file_loaded = 1;

	return R_SUCCESS;
}

int RSC_CloseContext(R_RSCFILE_CONTEXT * rsc_context)
{
	if (rsc_context->rc_file_open) {
		fclose(rsc_context->rc_file_p);
	}

	rsc_context->rc_file_open = 0;

	RSC_FreeRSC(rsc_context);

	rsc_context->rc_file_loaded = 0;

	return R_SUCCESS;
}

int RSC_DestroyContext(R_RSCFILE_CONTEXT * rsc_context)
{
	RSC_CloseContext(rsc_context);

	if (rsc_context->rc_file_loaded) {
		free(rsc_context->rc_res_table);
	}

	free(rsc_context);

	return R_SUCCESS;
}

int RSC_LoadRSC(R_RSCFILE_CONTEXT * rsc)
{
	ulong res_tbl_ct;
	ulong res_tbl_offset;

	uchar tblinfo_buf[RSC_TABLEINFO_SIZE];
	uchar *tbl_buf;
	size_t tbl_len;
	ulong i;

	R_RSCFILE_RESOURCE *rsc_restbl;

	const uchar *read_p;

	read_p = tblinfo_buf;

	if (rsc->rc_file_size < RSC_MIN_FILESIZE) {
		return R_FAILURE;
	}

	/* Read resource table info from the rear end of file
	 * \*------------------------------------------------------------- */
	fseek(rsc->rc_file_p, (long)(rsc->rc_file_size - 8), SEEK_SET);

	if (fread(tblinfo_buf,
		1, RSC_TABLEINFO_SIZE, rsc->rc_file_p) != RSC_TABLEINFO_SIZE) {

		return R_FAILURE;
	}

	res_tbl_offset = ys_read_u32_le(read_p, &read_p);
	res_tbl_ct = ys_read_u32_le(read_p, NULL);

	/* Check for sane table offset
	 * \*------------------------------------------------------------- */
	if (res_tbl_offset != rsc->rc_file_size - RSC_TABLEINFO_SIZE -
	    RSC_TABLEENTRY_SIZE * res_tbl_ct) {

		return R_FAILURE;
	}

	/* Load resource table
	 * \*------------------------------------------------------------- */
	tbl_len = RSC_TABLEENTRY_SIZE * res_tbl_ct;

	tbl_buf = (uchar *)malloc(tbl_len);
	if (tbl_buf == NULL) {
		return R_FAILURE;
	}

	fseek(rsc->rc_file_p, (long)res_tbl_offset, SEEK_SET);

	if (fread(tbl_buf, 1, tbl_len, rsc->rc_file_p) != tbl_len) {
		free(tbl_buf);
		return R_FAILURE;
	}

	rsc_restbl = (R_RSCFILE_RESOURCE *)malloc(res_tbl_ct * sizeof *rsc_restbl);
	if (rsc_restbl == NULL) {
		free(tbl_buf);
		return R_FAILURE;
	}

	read_p = tbl_buf;

	for (i = 0; i < res_tbl_ct; i++) {

		rsc_restbl[i].res_offset = ys_read_u32_le(read_p, &read_p);
		rsc_restbl[i].res_size = ys_read_u32_le(read_p, &read_p);

		if ((rsc_restbl[i].res_offset > rsc->rc_file_size) ||
		    (rsc_restbl[i].res_size > rsc->rc_file_size)) {

			free(tbl_buf);
			free(rsc_restbl);
			return R_FAILURE;
		}
	}

	rsc->rc_res_table = rsc_restbl;
	rsc->rc_res_ct = res_tbl_ct;

	free(tbl_buf);

	return R_SUCCESS;
}

int RSC_FreeRSC(R_RSCFILE_CONTEXT * rsc)
{
	if (!rsc->rc_file_loaded) {
		return R_FAILURE;
	}

	free(rsc->rc_res_table);

	return R_SUCCESS;
}

ulong RSC_GetResourceCount(R_RSCFILE_CONTEXT * rsc)
{
	return (rsc == NULL) ? 0 : rsc->rc_res_ct;
}

int
RSC_GetResourceSize(R_RSCFILE_CONTEXT * rsc, ulong res_num, ulong * res_size)
{
	if ((rsc == NULL) || (res_size == NULL)) {
		return R_FAILURE;
	}

	if (res_num > (rsc->rc_res_ct - 1)) {
		return R_FAILURE;
	}

	*res_size = rsc->rc_res_table[res_num].res_size;

	return R_SUCCESS;
}

int
RSC_GetResourceOffset(R_RSCFILE_CONTEXT * rsc,
    ulong res_num, ulong * res_offset)
{
	if ((rsc == NULL) || (res_offset == NULL)) {
		return R_FAILURE;
	}

	if (res_num > (rsc->rc_res_ct - 1)) {
		return R_FAILURE;
	}

	*res_offset = rsc->rc_res_table[res_num].res_offset;

	return R_SUCCESS;
}

int
RSC_LoadResource(R_RSCFILE_CONTEXT * rsc,
    ulong res_num, uchar ** res_p, size_t * res_size_p)
{
	ulong res_offset;
	size_t res_size;
	uchar *res_buf;

	if ((rsc == NULL) || (res_p == NULL)) {
		return R_FAILURE;
	}

	if (res_num > (rsc->rc_res_ct - 1)) {
		return R_FAILURE;
	}

	res_offset = rsc->rc_res_table[res_num].res_offset;
	res_size = rsc->rc_res_table[res_num].res_size;

	if (fseek(rsc->rc_file_p, (long)res_offset, SEEK_SET) != 0) {
		return R_FAILURE;
	}

	res_buf = (uchar *)malloc(res_size);
	if (res_buf == NULL) {
		return R_MEM;
	}

	if (fread(res_buf, 1, res_size, rsc->rc_file_p) != res_size) {
		free(res_buf);
		return R_FAILURE;
	}

	*res_p = res_buf;

	if (res_size_p != NULL) {
		*res_size_p = res_size;
	}

	return R_SUCCESS;
}

int RSC_FreeResource(uchar * resource_ptr)
{

	free(resource_ptr);

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: rscfile.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/rscfile.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    RSC Resource file management header file

 Notes: 
*/

#ifndef SAGA_RSCFILE_H__
#define SAGA_RSCFILE_H__

namespace Saga {

#define RSC_TABLEINFO_SIZE 8
#define RSC_TABLEENTRY_SIZE 8

#define RSC_MIN_FILESIZE (RSC_TABLEINFO_SIZE + RSC_TABLEENTRY_SIZE + 1)

typedef struct R_RSCFILE_RESOURCE_tag {

	int res_type;

	size_t res_offset;
	size_t res_size;

} R_RSCFILE_RESOURCE;

struct R_RSCFILE_CONTEXT_tag {

	const char *rc_file_fspec;
	FILE *rc_file_p;
	int rc_file_open;
	unsigned long rc_file_size;

	int rc_file_loaded;
	R_RSCFILE_RESOURCE *rc_res_table;
	size_t rc_res_ct;

};

int RSC_LoadRSC(R_RSCFILE_CONTEXT * rsc_context);

int RSC_FreeRSC(R_RSCFILE_CONTEXT * rsc);

} // End of namespace Saga

#endif				/* SAGA_RSCFILE_H__ */

--- NEW FILE: rscfile_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/rscfile_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    RSC Resource file management module public header file

 Notes: 
*/

#ifndef SAGA_RSCFILE_MOD_H__
#define SAGA_RSCFILE_MOD_H__

#include "resnames.h"

namespace Saga {

R_RSCFILE_CONTEXT *RSC_CreateContext(void);

int RSC_DestroyContext(R_RSCFILE_CONTEXT *);

int RSC_OpenContext(R_RSCFILE_CONTEXT *, const char *);

int RSC_CloseContext(R_RSCFILE_CONTEXT *);

ulong RSC_GetResourceCount(R_RSCFILE_CONTEXT *);

int RSC_GetResourceSize(R_RSCFILE_CONTEXT *, ulong, ulong *);

int RSC_GetResourceOffset(R_RSCFILE_CONTEXT *, ulong, ulong *);

int RSC_LoadResource(R_RSCFILE_CONTEXT *, ulong, uchar **, size_t *);

int RSC_FreeResource(uchar *);

} // End of namespace Saga

#endif				/* SAGA_RSCFILE_MOD_H__ */

--- NEW FILE: scene.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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.
 *
[...1120 lines suppressed...]

	YS_IGNORE_PARAM(argc);
	YS_IGNORE_PARAM(argv);

	CON_Print(fmt, "Scene number:", SceneModule.scene_number);
	CON_Print(fmt, "Descriptor R#:", SceneModule.scene_rn);
	CON_Print("-------------------------");
	CON_Print(fmt, "Unknown:", SceneModule.desc.unknown0);
	CON_Print(fmt, "Resource list R#:", SceneModule.desc.res_list_rn);
	CON_Print(fmt, "End slope:", SceneModule.desc.end_slope);
	CON_Print(fmt, "Begin slope:", SceneModule.desc.begin_slope);
	CON_Print(fmt, "Script resource:", SceneModule.desc.script_num);
	CON_Print(fmt, "Scene script:", SceneModule.desc.scene_scriptnum);
	CON_Print(fmt, "Start script:", SceneModule.desc.start_scriptnum);
	CON_Print(fmt, "Music R#", SceneModule.desc.music_rn);

	return;
}

} // End of namespace Saga

--- NEW FILE: scene.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/scene.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Scene management module private header file

 Notes: 
*/

#ifndef SAGA_SCENE_H
#define SAGA_SCENE_H

namespace Saga {

enum SCENE_LOAD_FLAGS {

	BY_RESOURCE = 0,
	BY_SCENE,
	BY_DESC
};

enum SCENE_PROC_PARAMS {

	SCENE_BEGIN = 0,
	SCENE_END
};

/* Resource type numbers */
enum SAGA_RESOURCE_TYPES {

	SAGA_BG_IMAGE = 2,
	SAGA_BG_MASK = 3,
	SAGA_OBJECT_NAME_LIST = 5,
	SAGA_OBJECT_MAP = 6,
	SAGA_ACTION_MAP = 7,
	SAGA_ISO_TILESET = 8,
	SAGA_ISO_METAMAP = 9,
	SAGA_ISO_METATILESET = 10,
	SAGA_ANIM_1 = 14,
	SAGA_ANIM_2,
	SAGA_ANIM_3,
	SAGA_ANIM_4,
	SAGA_ANIM_5,
	SAGA_ANIM_6,
	SAGA_ANIM_7,
	SAGA_PAL_ANIM = 23
};

#define SAGA_SCENE_DESC_LEN 16

typedef struct R_SCENE_DESC_tag {

	int unknown0;
	int res_list_rn;
	int end_slope;
	int begin_slope;
	int script_num;
	int scene_scriptnum;
	int start_scriptnum;
	int music_rn;

	struct R_SCENE_RESLIST_tag *res_list;
	size_t res_list_ct;

} R_SCENE_DESC;

#define SAGA_RESLIST_ENTRY_LEN 4

typedef struct R_SCENE_RESLIST_tag {

	ulong res_number;
	int res_type;

	uchar *res_data;
	size_t res_data_len;

} R_SCENE_RESLIST;

typedef struct SCENE_IMAGE_tag {

	int loaded;

	int w;
	int h;
	int p;

	uchar *buf;
	size_t buf_len;

	uchar *res_buf;
	size_t res_len;

	PALENTRY pal[256];

} SCENE_IMAGE;

typedef struct SCENE_ANIMINFO_tag {

	int anim_res_number;
	int anim_handle;

	struct SCENE_ANIMINFO_tag *next;

} SCENE_ANIMINFO;

typedef struct R_SCENE_QUEUE_tag {

	ulong scene_n;
	R_SCENE_DESC *scene_desc;
	int load_flag;

	R_SCENE_PROC *scene_proc;
	int scene_skiptarget;

} R_SCENE_QUEUE;

typedef struct R_SCENE_MODULE_tag {

	int init;

	R_RSCFILE_CONTEXT *scene_ctxt;

	int *scene_lut;
	int scene_count;
	int scene_max;

	YS_DL_LIST *scene_queue;

	int first_scene;

	int scene_loaded;
	int scene_mode;
	int scene_number;
	int scene_rn;
	int in_game;

	int load_desc;
	R_SCENE_DESC desc;

	int reslist_loaded;
	int reslist_entries;
	R_SCENE_RESLIST *reslist;

	int anim_entries;
	YS_DL_LIST *anim_list;

	R_SCENE_PROC *scene_proc;

	R_TEXTLIST *text_list;

	SCENE_IMAGE bg;
	SCENE_IMAGE bg_mask;

} R_SCENE_MODULE;

int SCENE_Queue(R_SCENE_QUEUE * scene_queue);
int SCENE_ClearQueue(void);

int
SCENE_Load(int scene,
    int load_flag, R_SCENE_PROC scene_proc, struct R_SCENE_DESC_tag *);

int LoadSceneDescriptor(ulong res_number);

int LoadSceneResourceList(ulong res_number);

int ProcessSceneResources(void);

void CF_scenechange(int argc, char *argv[]);

void CF_sceneinfo(int argc, char *argv[]);

/*
 * r_sceneproc.c                                                
\*--------------------------------------------------------------------------*/

int IHNM_StartProc(void);

int InitialSceneProc(int param, R_SCENE_INFO * scene_info);
int DefaultSceneProc(int param, R_SCENE_INFO * scene_info);

/*
 * r_ite_introproc.c                                             
\*--------------------------------------------------------------------------*/

int ITE_StartProc(void);
int ITE_IntroAnimProc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroCave1Proc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroCave2Proc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroCave3Proc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroCave4Proc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroValleyProc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroTreeHouseProc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroFairePathProc(int param, R_SCENE_INFO * scene_info);
int ITE_IntroFaireTentProc(int param, R_SCENE_INFO * scene_info);

/*
 * r_ihnm_introproc.c                                             
\*--------------------------------------------------------------------------*/
int IHNM_StartProc(void);
int IHNM_IntroMovieProc1(int param, R_SCENE_INFO * scene_info);
int IHNM_IntroMovieProc2(int param, R_SCENE_INFO * scene_info);
int IHNM_IntroMovieProc3(int param, R_SCENE_INFO * scene_info);
int IHNM_HateProc(int param, R_SCENE_INFO * scene_info);

} // End of namespace Saga

#endif				/* SAGA_SCENE_H_ */

--- NEW FILE: scene_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/scene_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Scene management module public header file

 Notes: 
*/

#ifndef SAGA_SCENE_MOD_H__
#define SAGA_SCENE_MOD_H__

#include "text_mod.h"

namespace Saga {

/*
 * r_scene.c                                                
\*--------------------------------------------------------------------------*/
enum R_SCENE_MODES {

	R_SCENE_MODE_INVALID,
	R_SCENE_MODE_NORMAL,
	R_SCENE_MODE_ISO
};

typedef struct SCENE_ZINFO_tag {

	int begin_slope;
	int end_slope;

} SCENE_ZINFO;

typedef struct SCENE_BGINFO_tag {

	int bg_x;
	int bg_y;

	int bg_w;
	int bg_h;
	int bg_p;

	uchar *bg_buf;
	size_t bg_buflen;

} SCENE_BGINFO;

typedef struct R_SCENE_INFO_tag {

	SCENE_ZINFO z_info;
	SCENE_BGINFO bg_info;

	R_TEXTLIST *text_list;

} R_SCENE_INFO;

typedef int (R_SCENE_PROC) (int, R_SCENE_INFO *);

int SCENE_Register(void);
int SCENE_Init(void);
int SCENE_Shutdown(void);

int SCENE_Start(void);
int SCENE_Next(void);
int SCENE_Skip(void);
int SCENE_End(void);

int SCENE_Draw(R_SURFACE *);

int SCENE_GetMode(void);
int SCENE_GetBGMaskInfo(int *w, int *h, uchar ** buf, size_t * buf_len);

int SCENE_IsBGMaskPresent(void);
int SCENE_GetBGInfo(SCENE_BGINFO * bginfo);
int SCENE_GetZInfo(SCENE_ZINFO * zinfo);
int SCENE_GetBGPal(PALENTRY ** pal);

int SCENE_GetInfo(R_SCENE_INFO * si);

} // End of namespace Saga

#endif				/* SAGA_SCENE_MOD_H__ */

--- NEW FILE: sceneproc.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sceneproc.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:   
 
    Initial and default scene procedures

 Notes: 
*/

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

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "animation_mod.h"
#include "events_mod.h"
#include "scene_mod.h"
#include "palanim_mod.h"

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "scene.h"
#include "sceneproc.h"

namespace Saga {

int InitialSceneProc(int param, R_SCENE_INFO * scene_info)
{
	R_EVENT event = { 0 };
	R_EVENT *q_event;

	int delay_time = 0;

	static PALENTRY current_pal[R_PAL_ENTRIES];
	PALENTRY *pal;

	YS_IGNORE_PARAM(scene_info);

	switch (param) {

	case SCENE_BEGIN:

		SYSMUSIC_Stop();
		SYSSOUND_StopVoice();

		/* Fade palette to black from intro scene
		 * \*----------------------------------------------------- */
		SYSGFX_GetCurrentPal(current_pal);

		event.type = R_CONTINUOUS_EVENT;
		event.code = R_PAL_EVENT;
		event.op = EVENT_PALTOBLACK;
		event.time = 0;
		event.duration = PALETTE_FADE_DURATION;
		event.data = current_pal;

		delay_time += PALETTE_FADE_DURATION;

		q_event = EVENT_Queue(&event);

		/* Activate user interface
		 * \*----------------------------------------------------- */
		event.type = R_ONESHOT_EVENT;
		event.code = R_INTERFACE_EVENT;
		event.op = EVENT_ACTIVATE;
		event.time = 0;

		q_event = EVENT_Chain(q_event, &event);

		/* Set first scene background w/o changing palette
		 * \*----------------------------------------------------- */
		event.type = R_ONESHOT_EVENT;
		event.code = R_BG_EVENT;
		event.op = EVENT_DISPLAY;
		event.param = NO_SET_PALETTE;
		event.time = 0;

		q_event = EVENT_Chain(q_event, &event);

		/* Fade in to first scene background palette
		 * \*----------------------------------------------------- */
		SCENE_GetBGPal(&pal);

		event.type = R_CONTINUOUS_EVENT;
		event.code = R_PAL_EVENT;
		event.op = EVENT_BLACKTOPAL;
		event.time = delay_time;
		event.duration = PALETTE_FADE_DURATION;
		event.data = pal;

		q_event = EVENT_Chain(q_event, &event);

		event.code = R_PALANIM_EVENT;
		event.op = EVENT_CYCLESTART;
		event.time = 0;

		q_event = EVENT_Chain(q_event, &event);

		ANIM_SetFlag(0, ANIM_LOOP);
		ANIM_Play(0, delay_time);

		break;

	case SCENE_END:

		break;

	default:
		R_printf(R_STDERR, "Illegal scene procedure parameter.\n");
		break;

	}

	return 0;
}

int DefaultSceneProc(int param, R_SCENE_INFO * scene_info)
{

	R_EVENT event;

	YS_IGNORE_PARAM(scene_info);

	switch (param) {

	case SCENE_BEGIN:

		/* Set scene background
		 * \*----------------------------------------------------- */
		event.type = R_ONESHOT_EVENT;
		event.code = R_BG_EVENT;
		event.op = EVENT_DISPLAY;
		event.param = SET_PALETTE;
		event.time = 0;

		EVENT_Queue(&event);

		/* Activate user interface
		 * \*----------------------------------------------------- */
		event.type = R_ONESHOT_EVENT;
		event.code = R_INTERFACE_EVENT;
		event.op = EVENT_ACTIVATE;
		event.time = 0;

		EVENT_Queue(&event);

		/* Begin palette cycle animation if present
		 * \*----------------------------------------------------- */
		event.type = R_ONESHOT_EVENT;
		event.code = R_PALANIM_EVENT;
		event.op = EVENT_CYCLESTART;
		event.time = 0;

		EVENT_Queue(&event);

		break;

	case SCENE_END:

		break;

	default:
		R_printf(R_STDERR, "Illegal scene procedure parameter.\n");
		break;

	}

	return 0;
}

} // End of namespace Saga


--- NEW FILE: sceneproc.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sceneproc.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*
 Description:	
 
	Initial and default scene procedures header file

 Notes: 
*/

#ifndef SAGA_SCENEPROC_H
#define SAGA_SCENEPROC_H

namespace Saga {

#define PALETTE_FADE_DURATION 1000

} // End of namespace Saga

#endif

--- NEW FILE: script.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/script.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module: Script resource handling functions

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "rscfile_mod.h"
#include "game_mod.h"
#include "text_mod.h"
#include "console_mod.h"
#include "cvar_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "script_mod.h"
#include "script.h"
#include "sstack.h"
#include "sthread.h"

namespace Saga {

R_SCRIPT_MODULE ScriptModule;

int SCRIPT_Register(void)
{

	CVAR_RegisterFunc(CF_script_info,
	    "script_info", NULL, R_CVAR_NONE, 0, 0);

	CVAR_RegisterFunc(CF_script_exec,
	    "script_exec", "<Script number>", R_CVAR_NONE, 1, 1);

	CVAR_RegisterFunc(CF_script_togglestep,
	    "script_togglestep", NULL, R_CVAR_NONE, 0, 0);

	return R_SUCCESS;
}

int SCRIPT_Init(void)
/*--------------------------------------------------------------------------*\
 * Initializes the scripting module.
 * Loads script resource look-up table, initializes script data system
\*--------------------------------------------------------------------------*/
{
	R_RSCFILE_CONTEXT *s_lut_ctxt;

	uchar *rsc_ptr;
	size_t rsc_len;

	const uchar *read_ptr;
	const uchar *read_ptr2;

	int result;
	int i;

	R_printf(R_STDOUT, "Initializing scripting subsystem.\n");

	/* Load script resource file context
	 * \*---------------------------------------------------------------------- */
	result = GAME_GetFileContext(&ScriptModule.script_ctxt,
	    R_GAME_SCRIPTFILE, 0);
	if (result != R_SUCCESS) {

		R_printf(R_STDERR, "Couldn't get script file context.\n");

		return R_FAILURE;
	}

	/* Load script LUT resource
	 * \*---------------------------------------------------------------------- */
	result = GAME_GetFileContext(&s_lut_ctxt, R_GAME_RESOURCEFILE, 0);
	if (result != R_SUCCESS) {

		R_printf(R_STDERR, "Couldn't get resource file context.\n");

		return R_FAILURE;
	}

	result = RSC_LoadResource(s_lut_ctxt,
	    ITE_SCRIPT_LUT, &rsc_ptr, &rsc_len);
	if (result != R_SUCCESS) {

		R_printf(R_STDERR,
		    "Error: Couldn't load script resource look-up table.\n");

		return R_FAILURE;
	}

	/* Create logical script LUT from resource
	 * \*---------------------------------------------------------------------- */
	if (rsc_len % R_S_LUT_ENTRYLEN_ITECD == 0) {

		ScriptModule.script_lut_entrylen = R_S_LUT_ENTRYLEN_ITECD;
	} else if (rsc_len % R_S_LUT_ENTRYLEN_ITEDISK == 0) {

		ScriptModule.script_lut_entrylen = R_S_LUT_ENTRYLEN_ITEDISK;
	} else {
		R_printf(R_STDERR,
		    "Error: Invalid script lookup table length.\n");
		return R_FAILURE;
	}

	/* Calculate number of entries */
	ScriptModule.script_lut_max =
	    rsc_len / ScriptModule.script_lut_entrylen;

	/* Allocate space for logical LUT */
	ScriptModule.script_lut = (R_SCRIPT_LUT_ENTRY *)malloc(ScriptModule.script_lut_max *
	    sizeof(R_SCRIPT_LUT_ENTRY));
	if (ScriptModule.script_lut == NULL) {
		R_printf(R_STDERR,
		    "Error: Couldn't allocate memory for script resource "
		    "look-up table.\n");
		return R_MEM;
	}

	/* Convert LUT resource to logical LUT */
	read_ptr = rsc_ptr;
	for (i = 0; i < ScriptModule.script_lut_max; i++) {

		read_ptr2 = read_ptr;

		ScriptModule.script_lut[i].script_rn =
		    ys_read_u16_le(read_ptr2, &read_ptr2);

		ScriptModule.script_lut[i].diag_list_rn =
		    ys_read_u16_le(read_ptr2, &read_ptr2);

		ScriptModule.script_lut[i].voice_lut_rn =
		    ys_read_u16_le(read_ptr2, &read_ptr2);

		/* Skip the unused portion of the structure */
		read_ptr += ScriptModule.script_lut_entrylen;
	}

	RSC_FreeResource(rsc_ptr);

	/* Any voice lookup table resources present? */
	for (i = 0; i < ScriptModule.script_lut_max; i++) {

		if (ScriptModule.script_lut[i].voice_lut_rn) {

			ScriptModule.voice_lut_present = 1;
			break;
		}
	}

	/* Initialize script submodules
	 * \*---------------------------------------------------------------------- */
	ScriptModule.thread_list = ys_dll_create();

	if (SDATA_Init() != R_SUCCESS) {
		free(ScriptModule.script_lut);
		return R_FAILURE;
	}

	ScriptModule.initialized = 1;
	return R_SUCCESS;
}

int SCRIPT_Shutdown(void)
/*--------------------------------------------------------------------------*\
 * Shut down script module gracefully; free all allocated module resources
\*--------------------------------------------------------------------------*/
{
	YS_DL_NODE *thread_node;
	R_SCRIPT_THREAD *thread;

	if (!ScriptModule.initialized) {

		return R_FAILURE;
	}

	R_printf(R_STDOUT, "Shutting down scripting subsystem.\n");

	/* Free script lookup table */
	free(ScriptModule.script_lut);

	/* Stop all threads and destroy them */

	for (thread_node = ys_dll_head(ScriptModule.thread_list);
	    thread_node != NULL; thread_node = ys_dll_next(thread_node)) {

		thread = (R_SCRIPT_THREAD *)ys_dll_get_data(thread_node);

		STHREAD_Destroy(thread);
	}

	ScriptModule.initialized = 0;

	return R_SUCCESS;
}

int SCRIPT_Load(int script_num)
/*--------------------------------------------------------------------------*\
 * Loads a script; including script bytecode and dialogue list 
\*--------------------------------------------------------------------------*/
{

	R_SCRIPTDATA *script_data;

	uchar *bytecode_p;
	size_t bytecode_len;
	ulong scriptl_rn;

	uchar *diagl_p;
	size_t diagl_len;
	ulong diagl_rn;

	uchar *voicelut_p;
	size_t voicelut_len;
	ulong voicelut_rn;

	int result;

	if (GAME_GetGameType() == R_GAMETYPE_IHNM) {
		return R_SUCCESS;
	}

	/* Validate script number */
	if ((script_num < 0) || (script_num > ScriptModule.script_lut_max)) {
		R_printf(R_STDERR, "SCRIPT_Load(): Invalid script number!\n");
		return R_FAILURE;
	}

	/* Release old script data if present */
	SCRIPT_Free();

	/* Initialize script data structure
	 * \*---------------------------------------------------------------------- */
	R_printf(R_STDOUT, "Loading script data for script #%d.\n",
	    script_num);

	script_data = (R_SCRIPTDATA *)malloc(sizeof *script_data);
	if (script_data == NULL) {
		R_printf(R_STDERR, "Memory allocation failed.\n");
		return R_MEM;
	}

	script_data->loaded = 0;

	/* Initialize script pointers */
	script_data->diag = NULL;
	script_data->bytecode = NULL;
	script_data->voice = NULL;

	/* Load script bytecode
	 * \*---------------------------------------------------------------------- */
	scriptl_rn = ScriptModule.script_lut[script_num].script_rn;

	result = RSC_LoadResource(ScriptModule.script_ctxt,
	    scriptl_rn, &bytecode_p, &bytecode_len);
	if (result != R_SUCCESS) {
		R_printf(R_STDERR,
		    "Error loading script bytecode resource.\n");
		free(script_data);
		return R_FAILURE;
	}

	script_data->bytecode = SCRIPT_LoadBytecode(bytecode_p, bytecode_len);

	if (script_data->bytecode == NULL) {
		R_printf(R_STDERR,
		    "Error interpreting script bytecode resource.\n");
		free(script_data);
		RSC_FreeResource(bytecode_p);
		return R_FAILURE;
	}

	/* Load script dialogue list
	 * \*---------------------------------------------------------------------- */
	diagl_rn = ScriptModule.script_lut[script_num].diag_list_rn;

	/* Load dialogue list resource */
	result = RSC_LoadResource(ScriptModule.script_ctxt,
	    diagl_rn, &diagl_p, &diagl_len);
	if (result != R_SUCCESS) {
		R_printf(R_STDERR, "Error loading dialogue list resource.\n");
		free(script_data);
		RSC_FreeResource(bytecode_p);
		return R_FAILURE;
	}

	/* Convert dialogue list resource to logical dialogue list */
	script_data->diag = SCRIPT_LoadDialogue(diagl_p, diagl_len);
	if (script_data->diag == NULL) {
		R_printf(R_STDERR,
		    "Error interpreting dialogue list resource.\n");
		free(script_data);
		RSC_FreeResource(bytecode_p);
		RSC_FreeResource(diagl_p);
		return R_FAILURE;
	}

	/* Load voice resource lookup table
	 * \*---------------------------------------------------------------------- */
	if (ScriptModule.voice_lut_present) {

		voicelut_rn = ScriptModule.script_lut[script_num].voice_lut_rn;

		/* Load voice LUT resource */
		result = RSC_LoadResource(ScriptModule.script_ctxt,
		    voicelut_rn, &voicelut_p, &voicelut_len);
		if (result != R_SUCCESS) {

			R_printf(R_STDERR,
			    "Error loading voice LUT resource.\n");

			free(script_data);
			RSC_FreeResource(bytecode_p);
			RSC_FreeResource(diagl_p);

			return R_FAILURE;
		}

		/* Convert voice LUT resource to logical voice LUT */
		script_data->voice = SCRIPT_LoadVoiceLUT(voicelut_p,
		    voicelut_len, script_data);
		if (script_data->voice == NULL) {
			R_printf(R_STDERR,
			    "Error interpreting voice LUT resource.\n");

			free(script_data);
			RSC_FreeResource(bytecode_p);
			RSC_FreeResource(diagl_p);
			RSC_FreeResource(voicelut_p);

			return R_FAILURE;
		}

	}

	/* Finish initialization
	 * \*---------------------------------------------------------------------- */
	script_data->loaded = 1;
	ScriptModule.current_script = script_data;

	return R_SUCCESS;
}

int SCRIPT_Free(void)
/*--------------------------------------------------------------------------*\
 * Frees all resources associated with current script.
\*--------------------------------------------------------------------------*/
{

	if (ScriptModule.current_script == NULL) {
		return R_FAILURE;
	}

	if (!ScriptModule.current_script->loaded) {
		return R_FAILURE;
	}

	R_printf(R_STDOUT, "Releasing script data.\n");

	/* Finish initialization
	 * \*---------------------------------------------------------------------- */
	if (ScriptModule.current_script->diag != NULL) {
		free(ScriptModule.current_script->diag->str);
		free(ScriptModule.current_script->diag->str_off);
	}
	free(ScriptModule.current_script->diag);

	if (ScriptModule.current_script->bytecode != NULL) {
		free(ScriptModule.current_script->bytecode->entrypoints);
		RSC_FreeResource(ScriptModule.current_script->bytecode->
		    bytecode_p);
	}

	free(ScriptModule.current_script->bytecode);

	if (ScriptModule.voice_lut_present) {
		free(ScriptModule.current_script->voice->voices);
		free(ScriptModule.current_script->voice);
	}

	free(ScriptModule.current_script);

	ScriptModule.current_script = NULL;

	return R_SUCCESS;
}

R_SCRIPT_BYTECODE *SCRIPT_LoadBytecode(const uchar * bytecode_p,
    size_t bytecode_len)
/*--------------------------------------------------------------------------*\
 * Reads the entrypoint table from a script bytecode resource in memory. 
 * Returns NULL on failure.
\*--------------------------------------------------------------------------*/
{

	const uchar *read_p = bytecode_p;
	R_PROC_TBLENTRY *bc_ep_tbl = NULL;
	R_SCRIPT_BYTECODE *bc_new_data = NULL;

	unsigned long n_entrypoints;	/* Number of entrypoints */
	size_t ep_tbl_offset;	/* Offset of bytecode entrypoint table */

	unsigned long i;

	R_printf(R_STDOUT, "Loading script bytecode...\n");

	/* The first two uint32 values are the number of entrypoints, and the
	 * offset to the entrypoint table, respectively. */

	n_entrypoints = ys_read_u32_le(read_p, &read_p);
	ep_tbl_offset = ys_read_u32_le(read_p, &read_p);

	/* Check that the entrypoint table offset is valid. */
	if ((bytecode_len - ep_tbl_offset) <
	    (n_entrypoints * R_SCRIPT_TBLENTRY_LEN)) {

		R_printf(R_STDERR, "Invalid table offset.\n");
		return NULL;
	}

	if (n_entrypoints > R_SCRIPT_MAX) {
		R_printf(R_STDERR, "Script limit exceeded.\n");
		return NULL;
	}

	/* Allocate a new bytecode resource information structure and table of
	 * entrypoints */

	bc_new_data = (R_SCRIPT_BYTECODE *)malloc(sizeof *bc_new_data);
	if (bc_new_data == NULL) {
		R_printf(R_STDERR,
		    "Memory allocation failure loading script bytecode.\n");
		return NULL;
	}

	bc_ep_tbl = (R_PROC_TBLENTRY *)malloc(n_entrypoints * sizeof *bc_ep_tbl);
	if (bc_ep_tbl == NULL) {
		R_printf(R_STDERR,
		    "Memory allocation failure creating script entrypoint table.\n");
		free(bc_new_data);
		return NULL;
	}

	/* Read in the entrypoint table */

	read_p = bytecode_p + ep_tbl_offset;

	for (i = 0; i < n_entrypoints; i++) {
		/* First uint16 is the offset of the entrypoint name from the start
		 * of the bytecode resource, second uint16 is the offset of the 
		 * bytecode itself for said entrypoint */
		bc_ep_tbl[i].name_offset = ys_read_u16_le(read_p, &read_p);
		bc_ep_tbl[i].offset = ys_read_u16_le(read_p, &read_p);

		/* Perform a simple range check on offset values */
		if ((bc_ep_tbl[i].name_offset > bytecode_len) ||
		    (bc_ep_tbl[i].offset > bytecode_len)) {

			R_printf(R_STDERR,
			    "Invalid offset encountered in script entrypoint table.\n");
			free(bc_new_data);
			free(bc_ep_tbl);
			return NULL;
		}
	}

	bc_new_data->bytecode_p = (uchar *) bytecode_p;
	bc_new_data->bytecode_len = bytecode_len;

	bc_new_data->n_entrypoints = n_entrypoints;
	bc_new_data->entrypoints = bc_ep_tbl;
	bc_new_data->ep_tbl_offset = ep_tbl_offset;

	return bc_new_data;
}

R_DIALOGUE_LIST *SCRIPT_LoadDialogue(const uchar * dialogue_p,
    size_t dialogue_len)
/*--------------------------------------------------------------------------*\
 * Reads a logical dialogue list from a dialogue list resource in memory.
 * Returns NULL on failure.
\*--------------------------------------------------------------------------*/
{
	const uchar *read_p = dialogue_p;

	R_DIALOGUE_LIST *dialogue_list;
	uint n_dialogue;

	uint i;
	size_t offset;

	R_printf(R_STDOUT, "Loading dialogue list...\n");

	/* Allocate dialogue list structure */
	dialogue_list = (R_DIALOGUE_LIST *)malloc(sizeof *dialogue_list);
	if (dialogue_list == NULL) {
		return NULL;
	}

	/* First uint16 is the offset of the first string */
	offset = ys_read_u16_le(read_p, &read_p);
	if (offset > dialogue_len) {
		R_printf(R_STDERR, "Error, invalid string offset.\n");
		return NULL;
	}

	/* Calculate table length */
	n_dialogue = offset / 2;
	dialogue_list->n_dialogue = n_dialogue;

	/* Allocate table of string pointers */
	dialogue_list->str = (char **)malloc(n_dialogue * sizeof(char *));
	if (dialogue_list->str == NULL) {
		free(dialogue_list);
		return NULL;
	}

	/* Allocate table of string offsets */
	dialogue_list->str_off = (size_t *)malloc(n_dialogue * sizeof(size_t));
	if (dialogue_list->str_off == NULL) {
		free(dialogue_list->str);
		free(dialogue_list);
		return NULL;
	}

	/* Read in tables from dialogue list resource */
	read_p = dialogue_p;
	for (i = 0; i < n_dialogue; i++) {
		offset = ys_read_u16_le(read_p, &read_p);

		if (offset > dialogue_len) {
			R_printf(R_STDERR, "Error, invalid string offset.\n");
			free(dialogue_list->str);
			free(dialogue_list->str_off);
			free(dialogue_list);
			return NULL;
		}
		dialogue_list->str[i] = (char *)dialogue_p + offset;
		dialogue_list->str_off[i] = offset;
	}

	return dialogue_list;
}

R_VOICE_LUT *SCRIPT_LoadVoiceLUT(const uchar * voicelut_p,
    size_t voicelut_len, R_SCRIPTDATA * script)
/*--------------------------------------------------------------------------*\
 * Reads a logical voice LUT from a voice LUT resource in memory.
 * Returns NULL on failure.
\*--------------------------------------------------------------------------*/
{
	const uchar *read_p = voicelut_p;

	R_VOICE_LUT *voice_lut;

	uint n_voices;
	uint i;

	voice_lut = (R_VOICE_LUT *)malloc(sizeof *voice_lut);
	if (voice_lut == NULL) {
		return NULL;
	}

	n_voices = voicelut_len / 2;
	if (n_voices != script->diag->n_dialogue) {
		R_printf(R_STDERR, "Error: Voice LUT entries do not match "
		    "dialogue entries.\n");
		return NULL;
	}

	voice_lut->voices = (int *)malloc(n_voices * sizeof *voice_lut->voices);
	if (voice_lut->voices == NULL) {

		return NULL;
	}

	for (i = 0; i < n_voices; i++) {

		voice_lut->voices[i] = ys_read_u16_le(read_p, &read_p);
	}

	return voice_lut;
}

void CF_script_info(int argc, char *argv[])
{

	ulong n_entrypoints;
	ulong i;
	char *name_ptr;

	if (ScriptModule.current_script == NULL) {
		return;
	}

	if (!ScriptModule.current_script->loaded) {
		return;
	}

	n_entrypoints = ScriptModule.current_script->bytecode->n_entrypoints;

	CON_Print("Current script contains %d entrypoints:", n_entrypoints);

	for (i = 0; i < n_entrypoints; i++) {
		name_ptr = (char *)
		    ScriptModule.current_script->bytecode->bytecode_p +
		    ScriptModule.current_script->bytecode->entrypoints[i].
		    name_offset;

		CON_Print("%lu: %s", i, name_ptr);
	}

	return;
}

void CF_script_exec(int argc, char *argv[])
{
	uint ep_num;

	if (argc < 1) {
		return;
	}

	ep_num = atoi(argv[0]);

	if (ScriptModule.dbg_thread == NULL) {

		CON_Print("Creating debug thread...");
		ScriptModule.dbg_thread = STHREAD_Create();

		if (ScriptModule.dbg_thread == NULL) {
			CON_Print("Thread creation failed.");
			return;
		}
	}

	if (ep_num >= ScriptModule.current_script->bytecode->n_entrypoints) {
		CON_Print("Invalid entrypoint.");
		return;
	}

	STHREAD_Execute(ScriptModule.dbg_thread, ep_num);

	return;
}

void CF_script_togglestep(int argc, char *argv[])
{
	ScriptModule.dbg_singlestep = !ScriptModule.dbg_singlestep;

	return;
}

} // End of namespace Saga

--- NEW FILE: script.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/script.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module private header

 Notes: 
*/

#ifndef SAGA_SCRIPT_H
#define SAGA_SCRIPT_H

#include "sstack.h"
#include "sdata.h"

namespace Saga {

#define R_S_LUT_ENTRYLEN_ITECD 22
#define R_S_LUT_ENTRYLEN_ITEDISK 16

#define R_SCRIPT_TBLENTRY_LEN 4

#define R_SCRIPT_MAX 5000
#define R_SCRIPTLIST_HDR 12
#define R_SCRIPT_STRINGLIMIT 255
#define R_TAB "    "

#define R_DEF_THREAD_STACKSIZE 16

#define S_ERROR_PREFIX "SError: "
#define S_WARN_PREFIX "SWarning: "

typedef struct R_PROC_TBLENTRY_tag {

	size_t name_offset;
	size_t offset;

} R_PROC_TBLENTRY;

typedef struct R_SCRIPT_BYTECODE_tag {

	unsigned char *bytecode_p;
	size_t bytecode_len;

	size_t ep_tbl_offset;
	unsigned long n_entrypoints;
	R_PROC_TBLENTRY *entrypoints;

} R_SCRIPT_BYTECODE;

typedef struct R_DIALOGUE_LIST_tag {

	unsigned int n_dialogue;
	char **str;
	size_t *str_off;

} R_DIALOGUE_LIST;

typedef struct R_VOICE_LUT_tag {

	int n_voices;
	int *voices;

} R_VOICE_LUT;

typedef struct R_SCRIPTDATA_tag {

	int loaded;
	R_SCRIPT_BYTECODE *bytecode;
	R_DIALOGUE_LIST *diag;
	R_VOICE_LUT *voice;

} R_SCRIPTDATA;

typedef struct R_SCRIPT_LUT_ENTRY_tag {

	int script_rn;
	int diag_list_rn;
	int voice_lut_rn;

} R_SCRIPT_LUT_ENTRY;

typedef struct R_SCRIPT_DATABUF_tag {

	SDataWord_T *data;
	int len;

} R_SCRIPT_DATABUF;

typedef struct R_SCRIPT_MODULE_tag {

	int initialized;

	R_RSCFILE_CONTEXT *script_ctxt;

	int voice_lut_present;
	R_SCRIPT_LUT_ENTRY *script_lut;
	int script_lut_max;
	uint script_lut_entrylen;

	R_SCRIPTDATA *current_script;
	YS_DL_LIST *thread_list;
	R_SCRIPT_DATABUF *data_buf[R_SCRIPT_DATABUF_NUM];

	int dbg_singlestep;
	int dbg_dostep;
	R_SCRIPT_THREAD *dbg_thread;
	R_TEXTLIST_ENTRY *dbg_txtentry;

} R_SCRIPT_MODULE;

extern R_SCRIPT_MODULE ScriptModule;

R_SCRIPT_BYTECODE *SCRIPT_LoadBytecode(const uchar * bytecode_p,
    size_t bytecode_len);

R_DIALOGUE_LIST *SCRIPT_LoadDialogue(const uchar * dialogue_p,
    size_t dialogue_len);

R_VOICE_LUT *SCRIPT_LoadVoiceLUT(const uchar * voicelut_p,
    size_t voicelut_len, R_SCRIPTDATA * script);

int
SCRIPT_Disassemble(R_SCRIPT_BYTECODE * script_list,
    R_DIALOGUE_LIST * diag_list);

void CF_script_info(int argc, char *argv[]);

void CF_script_exec(int argc, char *argv[]);

void CF_script_togglestep(int argc, char *argv[]);

} // End of namespace Saga

#endif

--- NEW FILE: script_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/script_mod.h,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module public header

 Notes: 
*/

#ifndef SAGA_SCRIPT_MOD_H
#define SAGA_SCRIPT_MOD_H

namespace Saga {

typedef unsigned int SDataWord_T;

typedef struct R_SCRIPT_THREAD_tag R_SCRIPT_THREAD;

enum R_SCRIPT_VERBS {

	S_VERB_WALKTO = 0,
	S_VERB_LOOKAT = 2,
	S_VERB_PICKUP = 1,
	S_VERB_TALKTO,
	S_VERB_OPEN = 5,
	S_VERB_CLOSE = 6,
	S_VERB_USE = 8,
	S_VERB_GIVE
};

int SCRIPT_Register(void);

int SCRIPT_Init(void);

int SCRIPT_Shutdown(void);

int SCRIPT_Load(int script_num);

int SCRIPT_Free(void);

int SDATA_GetWord(int n_buf, int n_word, SDataWord_T * data);

int SDATA_PutWord(int n_buf, int n_word, SDataWord_T data);

int SDATA_SetBit(int n_buf, SDataWord_T n_bit, int bitstate);

int SDATA_GetBit(int n_buf, SDataWord_T n_bit, int *bitstate);

int SDATA_ReadWordS(SDataWord_T word);

uint SDATA_ReadWordU(SDataWord_T word);

R_SCRIPT_THREAD *STHREAD_Create(void);

int STHREAD_Execute(R_SCRIPT_THREAD * thread, int ep_num);

int STHREAD_ExecThreads(int msec);

int STHREAD_HoldSem(R_SEMAPHORE * sem);

int STHREAD_ReleaseSem(R_SEMAPHORE * sem);

int STHREAD_DebugStep(void);

} // End of namespace Saga

#endif				/* SAGA_SCRIPT_MOD_H */

--- NEW FILE: sdata.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sdata.cpp,v 1.1 2004/04/12 21:40:47 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module data management component

 Notes: 
 
    Type SDataWord_T must be unpadded
*/

#include "reinherit.h"

#include "yslib.h"

#include <limits.h>

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "text_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "script_mod.h"
#include "script.h"
#include "sdata.h"

namespace Saga {

int SDATA_Init(void)
{

	unsigned int i;
	void *alloc_ptr;

	R_printf(R_STDOUT, "Initializing script data buffers.\n");

	for (i = 0; i < R_SCRIPT_DATABUF_NUM; i++) {

		alloc_ptr = malloc(sizeof *ScriptModule.data_buf[0]);

		if (alloc_ptr == NULL) {
			R_printf(R_STDERR,
			    "Error allocating memory for script data buffer %d.\n",
			    i);
			return R_MEM;
		}

		ScriptModule.data_buf[i] = (R_SCRIPT_DATABUF *)alloc_ptr;

		alloc_ptr = calloc(R_SCRIPT_DATABUF_LEN, sizeof(SDataWord_T));

		if (alloc_ptr == NULL) {
			R_printf(R_STDERR,
			    "Error allocating memory for script data buffer %d.\n",
			    i);
			return R_MEM;
		}

		ScriptModule.data_buf[i]->len = R_SCRIPT_DATABUF_LEN;
		ScriptModule.data_buf[i]->data = (SDataWord_T *)alloc_ptr;
	}

	return R_SUCCESS;
}

int SDATA_GetWord(int n_buf, int n_word, SDataWord_T * data)
{

	if ((n_buf < 0) || (n_buf >= R_SCRIPT_DATABUF_NUM)) {
		return R_FAILURE;
	}

	if ((n_word < 0) || (n_word >= ScriptModule.data_buf[n_buf]->len)) {
		return R_FAILURE;
	}

	if (data == NULL) {
		return R_FAILURE;
	}

	*data = ScriptModule.data_buf[n_buf]->data[n_word];

	return R_SUCCESS;
}

int SDATA_PutWord(int n_buf, int n_word, SDataWord_T data)
{

	if ((n_buf < 0) || (n_buf >= R_SCRIPT_DATABUF_NUM)) {
		return R_FAILURE;
	}

	if ((n_word < 0) || (n_word >= ScriptModule.data_buf[n_buf]->len)) {
		return R_FAILURE;
	}

	ScriptModule.data_buf[n_buf]->data[n_word] = data;

	return R_SUCCESS;
}

int SDATA_SetBit(int n_buf, SDataWord_T n_bit, int bitstate)
{

	int n_word;
	int n_bitpos;

	SDataWord_T bit_pattern = 0x01;

	if ((n_buf < 0) || (n_buf >= R_SCRIPT_DATABUF_NUM)) {
		return R_FAILURE;
	}

	if (n_bit >= (unsigned long)ScriptModule.data_buf[n_buf]->len *
	    (sizeof(SDataWord_T) * CHAR_BIT)) {

		return R_FAILURE;
	}

	n_word = n_bit / (sizeof(SDataWord_T) * CHAR_BIT);
	n_bitpos = n_bit % (sizeof(SDataWord_T) * CHAR_BIT);

	bit_pattern <<= ((sizeof(SDataWord_T) * CHAR_BIT) - (n_bitpos + 1));

	if (bitstate) {
		ScriptModule.data_buf[n_buf]->data[n_word] |= bit_pattern;
	} else {
		ScriptModule.data_buf[n_buf]->data[n_word] &= ~bit_pattern;
	}

	return R_SUCCESS;
}

int SDATA_GetBit(int n_buf, SDataWord_T n_bit, int *bitstate)
{

	int n_word;
	int n_bitpos;

	SDataWord_T bit_pattern = 0x01;

	if ((n_buf < 0) || (n_buf >= R_SCRIPT_DATABUF_NUM)) {

		return R_FAILURE;
	}

	if (n_bit >= (SDataWord_T) ScriptModule.data_buf[n_buf]->len *
	    (sizeof(SDataWord_T) * CHAR_BIT)) {

		return R_FAILURE;
	}

	n_word = n_bit / (sizeof(SDataWord_T) * CHAR_BIT);
	n_bitpos = n_bit % (sizeof(SDataWord_T) * CHAR_BIT);

	bit_pattern <<= ((sizeof(SDataWord_T) * CHAR_BIT) - (n_bitpos + 1));

	*bitstate = (ScriptModule.data_buf[n_buf]->data[n_word] &
	    bit_pattern) ? 1 : 0;

	return R_SUCCESS;
}

int SDATA_ReadWordS(SDataWord_T word)
{
	uint u_int = word;
	int s_int;

	if (u_int & 0x8000U) {
		s_int = (int)(u_int - 0x8000U) - 0x7FFF - 1;
	} else {
		s_int = u_int;
	}

	return s_int;
}

uint SDATA_ReadWordU(SDataWord_T word)
{
	uint u_int = (uint) word;

	return u_int;
}

} // End of namespace Saga

--- NEW FILE: sdata.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sdata.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module data management component header file

 Notes: 
*/

#ifndef SAGA_SDATA_H
#define SAGA_SDATA_H

namespace Saga {

#define R_SCRIPT_DATABUF_NUM 5U
#define R_SCRIPT_DATABUF_LEN 1024U

int SDATA_Init(void);

} // End of namespace Saga

#endif				/* SAGA_SDATA_H */

--- NEW FILE: sdebug.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sdebug.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module simple thread debugging support

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "actor_mod.h"
#include "console_mod.h"
#include "text_mod.h"
#include "scene_mod.h"
#include "font_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "script.h"
#include "sthread.h"

namespace Saga {

#define SD_DISPLAY_LEN 128

#define SD_ADDTXT( x ) strncat( disp_buf, x, SD_DISPLAY_LEN );

int SDEBUG_PrintInstr(R_SCRIPT_THREAD * thread)
{

	R_TEXTLIST_ENTRY tl_e;

	const uchar *start_p;
	const uchar *read_p;

	char tmp_buf[80] = { 0 };
	static char disp_buf[SD_DISPLAY_LEN] = { 0 };

	int in_char;
	/*int op_offset; */

	int n_switch;
	int i;

	R_SCENE_INFO si;

	SCENE_GetInfo(&si);

	disp_buf[0] = 0;

	if (ScriptModule.dbg_txtentry != NULL) {

		TEXT_DeleteEntry(si.text_list, ScriptModule.dbg_txtentry);
		ScriptModule.dbg_txtentry = NULL;
	}

	tl_e.color = 1;
	tl_e.effect_color = 0;
	tl_e.text_x = 2;
	tl_e.text_y = 20;
	tl_e.font_id = SMALL_FONT_ID;
	tl_e.flags = FONT_OUTLINE;
	tl_e.string = disp_buf;
	tl_e.display = 1;

	read_p = ScriptModule.current_script->bytecode->bytecode_p +
	    thread->i_offset;

	start_p = read_p;

	in_char = ys_read_u8(read_p, &read_p);

	sprintf(tmp_buf, "%04lX | %02X | ", thread->i_offset, in_char);
	strncat(disp_buf, tmp_buf, SD_DISPLAY_LEN);

	switch (in_char) {

		/* Align */
	case 0x01:

		SD_ADDTXT("ALGN |");
		break;

		/* Push nothing */
	case 0x02:

		SD_ADDTXT("PSHN |");
		break;

		/* Pop nothing */
	case 0x03:

		SD_ADDTXT("POPN |");
		break;

		/* Push false (0) */
	case 0x04:

		SD_ADDTXT("PSHF |");
		break;

		/* Push true (1) */
	case 0x05:

		SD_ADDTXT("PSHT |");
		break;

		/* Push word (dialogue string index) */
	case 0x08:
		{
			int param;

			SD_ADDTXT("PSHD | ");

			param = ys_read_u16_le(read_p, &read_p);
			sprintf(tmp_buf, "%02X", param);
			SD_ADDTXT(tmp_buf);
/*
				if(( param >= 0 ) && ( param < diag_list->n_dialogue )) {
					printf(" ; \"%.*s\"", R_SCRIPT_STRINGLIMIT, diag_list->str[param] );
				}
				else {
					printf(" ; Invalid dialogue string.\n" );
				}
*/
		}
		break;

		/* Push word */
	case 0x06:
		{
			int param;

			SD_ADDTXT("PUSH | ");
			param = ys_read_u16_le(read_p, &read_p);
			sprintf(tmp_buf, "%04X", param);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Test flag */
	case 0x0B:
		{
			int param1;
			int param2;

			SD_ADDTXT("TSTF | ");
			param1 = *read_p++;
			param2 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %04X", param1, param2);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Get word */
	case 0x0C:
		{
			int param1;
			int param2;

			SD_ADDTXT("GETW | ");
			param1 = *read_p++;
			param2 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %04X", param1, param2);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Modify flag */
	case 0x0F:
		{
			int param1;
			int param2;

			SD_ADDTXT("MODF | ");
			param1 = *read_p++;
			param2 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %04X", param1, param2);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Put word */
	case 0x10:
		{
			int param1;
			int param2;

			SD_ADDTXT("PUTW | ");
			param1 = *read_p++;
			param2 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %04X", param1, param2);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Modify flag and pop */
	case 0x13:
		{
			int param1;
			int param2;

			SD_ADDTXT("MDFP | ");
			param1 = *read_p++;
			param2 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %04X", param1, param2);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Put word and pop */
	case 0x14:
		{
			int param1;
			int param2;

			SD_ADDTXT("PTWP | ");
			param1 = *read_p++;
			param2 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %04X", param1, param2);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Call subscript ? */
	case 0x17:
		{
			int param1;
			int param2;
			int param3;

			SD_ADDTXT("GOSB | ");
			param1 = *read_p++;
			param2 = *read_p++;
			param3 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %02X %04X", param1, param2,
			    param3);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Call function */
	case 0x19:
	case 0x18:
		{
			int func_num;
			int param;

			SD_ADDTXT("CALL | ");

			func_num = *read_p++;
			sprintf(tmp_buf, "%02X ", func_num);
			SD_ADDTXT(tmp_buf);

			param = ys_read_u16_le(read_p, &read_p);
			sprintf(tmp_buf, "%04X ", param);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Begin subscript */
	case 0x1A:
		{
			int param;

			SD_ADDTXT("ENTR | ");
			param = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%04X ", param);
			SD_ADDTXT(tmp_buf);
/*
				for( i = 0 ; i < script_list->n_scripts ; i++ ) {
					if( op_offset == script_list->scripts[i].offset ) {
						printf("; Entrypoint \"%s\".", script_list->scriptl_p +
							script_list->scripts[i].name_offset );
								
						break;
					}
				}
*/
		}
		break;

	case 0x1B:
		SD_ADDTXT("??? ");
		break;

		/* End subscript */
	case 0x1C:
		SD_ADDTXT("EXIT |");
		break;

		/* Unconditional jump */
	case 0x1D:
		{
			int param1;

			SD_ADDTXT("JMP  | ");
			param1 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%04X", param1);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Jump if nonzero + POP */
	case 0x1E:
		{
			int param1;

			SD_ADDTXT("JNZP | ");
			param1 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%04X", param1);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Jump if zero + POP */
	case 0x1F:
		{
			int param1;

			SD_ADDTXT("JZP  | ");
			param1 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%04X", param1);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Jump if nonzero */
	case 0x20:
		{
			int param1;

			SD_ADDTXT("JNZ  | ");
			param1 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%04X", param1);
			SD_ADDTXT(tmp_buf);
		}
		break;

		/* Jump if zero */
	case 0x21:
		{
			int param1;

			SD_ADDTXT("JZ   | ");
			param1 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%04X", param1);
			SD_ADDTXT(tmp_buf);

		}
		break;

		/* Switch */
	case 0x22:
		{
			int switch_num;
			int switch_jmp;
			int default_jmp;

			SD_ADDTXT("SWCH | ");
			n_switch = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X\n", n_switch);
			SD_ADDTXT(tmp_buf);

			for (i = 0; i < n_switch; i++) {
				switch_num = ys_read_u16_le(read_p, &read_p);
				switch_jmp = ys_read_u16_le(read_p, &read_p);

				/*
				 * printf( R_TAB "CASE %04X, %04X\n", switch_num, switch_jmp );
				 */
			}

			default_jmp = ys_read_u16_le(read_p, &read_p);

			/*
			 * printf( R_TAB "DEF %04X", default_jmp );
			 */
		}
		break;

		/* Random branch */
	case 0x24:
		{
			int n_switch2;
			int switch_num;
			int switch_jmp;

			SD_ADDTXT("RJMP | ");

			/* Ignored? */
			ys_read_u16_le(read_p, &read_p);

			n_switch2 = ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%04X", n_switch2);
			SD_ADDTXT(tmp_buf);

			for (i = 0; i < n_switch2; i++) {
				/*printf("\n"); */
				switch_num = ys_read_u16_le(read_p, &read_p);
				switch_jmp = ys_read_u16_le(read_p, &read_p);
				/*
				 * printf( R_TAB "WEIGHT %04X, %04X", switch_num, switch_jmp );
				 */
			}
		}
		break;

	case 0x25:
		SD_ADDTXT("NEG  |");
		break;

	case 0x26:
		SD_ADDTXT("TSTZ |");
		break;

	case 0x27:
		SD_ADDTXT("NOT  |");
		break;

	case 0x28:
		SD_ADDTXT("??? ");
		read_p++;
		ys_read_u16_le(read_p, &read_p);
		break;

	case 0x29:
		SD_ADDTXT("??? ");
		read_p++;
		ys_read_u16_le(read_p, &read_p);
		break;

	case 0x2A:
		SD_ADDTXT("??? ");
		read_p++;
		ys_read_u16_le(read_p, &read_p);
		break;

	case 0x2B:
		SD_ADDTXT("??? ");
		read_p++;
		ys_read_u16_le(read_p, &read_p);
		break;

		/* Addition */
	case 0x2C:
		SD_ADDTXT("ADD  |");
		break;

		/* Subtraction */
	case 0x2D:
		SD_ADDTXT("SUB  |");
		break;

		/* Integer multiplication */
	case 0x2E:
		SD_ADDTXT("MULT |");
		break;

		/* Integer division */
	case 0x2F:
		SD_ADDTXT("DIV |");
		break;

		/* Modulus */
	case 0x30:
		SD_ADDTXT("MOD  |");
		break;

		/* Test equality */
	case 0x33:
		SD_ADDTXT("EQU  |");
		break;

		/* Test inequality */
	case 0x34:
		SD_ADDTXT("NEQU |");
		break;

		/* Test Greater-than */
	case 0x35:
		SD_ADDTXT("GRT  |");
		break;

		/* Test Less-than */
	case 0x36:
		SD_ADDTXT("LST  |");
		break;

		/* Test Greater-than or Equal to */
	case 0x37:
		SD_ADDTXT("GRTE |");
		break;

		/* Test Less-than or Equal to */
	case 0x38:
		SD_ADDTXT("LSTE |");
		break;

	case 0x3F:
		SD_ADDTXT("SHR  |");
		break;

	case 0x40:
		SD_ADDTXT("SHL  |");
		break;

	case 0x41:
		SD_ADDTXT("AND  |");
		break;

	case 0x42:
		SD_ADDTXT("OR   |");
		break;

	case 0x43:
		SD_ADDTXT("XOR  |");
		break;

	case 0x44:
		SD_ADDTXT("LAND |");
		break;

	case 0x45:
		SD_ADDTXT("LOR  |");
		break;

	case 0x46:
		SD_ADDTXT("LXOR |");
		break;

	case 0x53:
		{
			int n_voices;
			int param1;
			int param2;

			SD_ADDTXT("DLGP | ");

			n_voices = *read_p++;
			param1 = ys_read_u16_le(read_p, &read_p);
			param2 = *read_p++;

			/* ignored ? */
			ys_read_u16_le(read_p, &read_p);

			sprintf(tmp_buf, "%02X %04X %02X", n_voices, param1,
			    param2);
			SD_ADDTXT(tmp_buf);
		}
		break;

	case 0x54:
		SD_ADDTXT("DLGS |");
		break;

	case 0x55:
		SD_ADDTXT("DLGX |");
		break;

	case 0x56:
		{
			int param1;
			int param2;
			int param3;

			SD_ADDTXT("DLGO | ");
			param1 = *read_p++;
			param2 = *read_p++;

			sprintf(tmp_buf, "%02X %02X ", param1, param2);
			SD_ADDTXT(tmp_buf);

			if (param2 > 0) {
				param3 = ys_read_u16_le(read_p, &read_p);

				sprintf(tmp_buf, "%04X", param3);
				SD_ADDTXT(tmp_buf);
			}
		}
		break;

	case 0x57:
		{
			int param1;
			int param2;
			int param3;

			SD_ADDTXT("JMPS | ");

			param1 = ys_read_u16_le(read_p, &read_p);
			param2 = ys_read_u16_le(read_p, &read_p);
			param3 = *read_p++;

			sprintf(tmp_buf, "%04X %04X %02X", param1, param2,
			    param3);
			SD_ADDTXT(tmp_buf);
		}
		break;

	default:
		sprintf(tmp_buf, "Invalid opcode.\n");
		SD_ADDTXT(tmp_buf);
		break;

	}			/* end switch( in_char ) */

	ScriptModule.dbg_txtentry = TEXT_AddEntry(si.text_list, &tl_e);
	TEXT_SetDisplay(ScriptModule.dbg_txtentry, 1);

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: sfuncs.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sfuncs.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module script function component

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "actor_mod.h"
#include "animation_mod.h"
#include "console_mod.h"
#include "interface_mod.h"
#include "text_mod.h"

/*
\*--------------------------------------------------------------------------*/
#include "script.h"
#include "sfuncs.h"

namespace Saga {

R_SFUNC_ENTRY SFuncList[R_SFUNC_NUM] = {

	{0, 0, NULL}
	,
	{1, 1, SF_Sleep}
	,
	{2, 0, NULL}
	,
	{3, 1, SF_3}
	,
	{4, 1, SF_SetCommandText}
	,
	{5, 0, NULL}
	,
	{6, 3, SF_ActorWalkTo}
	,
	{7, 0, NULL}
	,
	{8, 2, SF_SetActorOrient}
	,
	{9, 0, NULL}
	,
	{10, 0, NULL}
	,
	{11, 1, SF_FreezeInterface}
	,
	{12, 0, NULL}
	,
	{13, 0, NULL}
	,
	{14, 0, NULL}
	,
	{15, 0, NULL}
	,
	{16, 0, NULL}
	,
	{17, 0, NULL}
	,
	{18, 0, NULL}
	,
	{19, 0, NULL}
	,
	{20, 0, NULL}
	,
	{21, 0, NULL}
	,
	{22, 0, NULL}
	,
	{23, 0, NULL}
	,
	{24, 0, NULL}
	,
	{25, 0, NULL}
	,
	{26, 3, SF_StartAnim}
	,
	{27, 3, SF_ActorWalkToAsync}
	,
	{28, 0, NULL}
	,
	{29, 0, NULL}
	,
	{30, 3, SF_PlaceActor}
	,
	{31, 0, NULL}
	,
	{32, 0, NULL}
	,
	{33, 0, NULL}
	,
	{34, 0, NULL}
	,
	{35, 0, NULL}
	,
	{36, 4, SF_ActorWalkTo2}
	,
	{37, 4, SF_SetActorAct}
	,
	{38, 3, SF_SetActorAct2}
	,
	{39, 0, NULL}
	,
	{40, 0, NULL}
	,
	{41, 4, SF_LinkAnim}
	,
	{42, 0, NULL}
	,
	{43, 6, SF_PlaceActorEx}
	,
	{44, 0, SF_CheckUserInterrupt}
	,
	{45, 0, NULL}
	,
	{46, 0, NULL}
	,
	{47, 0, NULL}
	,
	{48, 0, NULL}
	,
	{49, 0, NULL}
	,
	{50, 0, NULL}
	,
	{51, 0, NULL}
	,
	{52, 0, NULL}
	,
	{53, 0, NULL}
	,
	{54, 0, NULL}
	,
	{55, 0, NULL}
	,
	{56, 0, NULL}
	,
	{57, 0, NULL}
	,
	{58, 0, NULL}
	,
	{59, 0, NULL}
	,
	{60, 0, NULL}
	,
	{61, 0, NULL}
	,
	{62, 0, NULL}
	,
	{63, 0, NULL}
	,
	{64, 0, NULL}
	,
	{65, 0, NULL}
	,
	{66, 0, NULL}
	,
	{67, 0, NULL}
	,
	{68, 0, NULL}
	,
	{69, 0, NULL}
	,
	{70, 0, NULL}
	,
	{71, 0, NULL}
	,
	{72, 0, NULL}
	,
	{73, 0, NULL}
	,
	{74, 0, NULL}
	,
	{75, 0, NULL}
	,
	{76, 0, NULL}
	,
	{77, 0, NULL}
};

int SF_Sleep(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #1 (0x01) blocking
 *
 * Suspends thread execution for the specified time period
 *
 * Param1: time to suspend ( units? )
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T time_param;

	int time;

	SSTACK_Pop(thread->stack, &time_param);

	time = SDATA_ReadWordU(time_param);

	thread->sleep_time = time * 10;

	return R_SUCCESS;
}

int SF_3(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #3 (0x03)
 *
 * Unknown function; pops a parameter and pushes a return value
 *
 * Param1: unknown
 *
\*--------------------------------------------------------------------------*/
{
	/* INCOMPLETE */

	SDataWord_T param1;

	SSTACK_Pop(thread->stack, &param1);

	SSTACK_Push(thread->stack, 0);	/* push for now to allow intro faire 
					 * setup to run completely */

	return R_SUCCESS;
}

int SF_SetCommandText(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #4 (0x04) nonblocking
 *
 * Set the command display to the specified text string
 *
 * Param1: dialogue index of string
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T s_idx_parm;

	SSTACK_Pop(thread->stack, &s_idx_parm);

	/* INCOMPLETE */

	return R_SUCCESS;
}

int SF_ActorWalkTo(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #6 (0x06) blocking
 *
 * Commands the specified actor to walk to the given position
 *
 * Param1: actor id
 * Param2: actor destination x
 * Param3: actor destination y
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T actor_parm;

	SDataWord_T x_parm;
	SDataWord_T y_parm;

	int actor_id;
	int actor_idx;

	R_POINT pt;

	SSTACK_Pop(thread->stack, &actor_parm);

	SSTACK_Pop(thread->stack, &x_parm);
	SSTACK_Pop(thread->stack, &y_parm);

	actor_id = SDATA_ReadWordS(actor_parm);

	actor_idx = ACTOR_GetActorIndex(actor_id);
	if (actor_idx < 0) {
		CON_Print(S_WARN_PREFIX "SF.08: Actor id 0x%X not found.",
		    actor_id);
		return R_FAILURE;
	}

	pt.x = SDATA_ReadWordS(x_parm);
	pt.y = SDATA_ReadWordS(y_parm);

	ACTOR_WalkTo(actor_idx, &pt, 0, &thread->sem);

	return R_SUCCESS;
}

int SF_SetActorOrient(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #8 (0x08) nonblocking
 *
 * Sets the orientation of the specified actor.
 *
 * Param1: actor id
 * Param2: actor orientation
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T actor_parm;
	SDataWord_T orient_parm;

	int actor_id;
	int actor_idx;
	int orientation;

	SSTACK_Pop(thread->stack, &actor_parm);
	SSTACK_Pop(thread->stack, &orient_parm);

	actor_id = SDATA_ReadWordS(actor_parm);
	orientation = SDATA_ReadWordS(orient_parm);

	actor_idx = ACTOR_GetActorIndex(actor_id);
	if (actor_idx < 0) {
		CON_Print(S_WARN_PREFIX "SF.08: Actor id 0x%X not found.",
		    actor_id);

		return R_FAILURE;
	}

	ACTOR_SetOrientation(actor_idx, orientation);
	return R_SUCCESS;
}

int SF_FreezeInterface(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #11 (0x0B) nonblocking
 *
 * If the parameter is true, the user interface is disabled while script 
 * continues to run. If the parameter is false, the user interface is 
 * reenabled.
 *
 * Param1: boolean
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T b_param;

	SSTACK_Pop(thread->stack, &b_param);

	if (b_param) {
		INTERFACE_Deactivate();
	} else {
		INTERFACE_Activate();
	}

	return R_SUCCESS;
}

int SF_StartAnim(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #26 (0x1A) nonblocking
 *
 * Starts the specified animation 
 *
 * Param1: ?
 * Param2: frames of animation to play or -1 to loop
 * Param3: animation id
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T unk_parm;
	SDataWord_T frame_parm;
	SDataWord_T anim_id_parm;

	int frame_count;
	int anim_id;

	SSTACK_Pop(thread->stack, &anim_id_parm);
	SSTACK_Pop(thread->stack, &frame_parm);
	SSTACK_Pop(thread->stack, &unk_parm);

	frame_count = SDATA_ReadWordS(frame_parm);
	anim_id = SDATA_ReadWordS(anim_id_parm);

	if (ANIM_Play(anim_id, 0) != R_SUCCESS) {

		CON_Print(S_WARN_PREFIX
		    "SF.26: ANIM_Play() failed. Anim id: %u\n", anim_id);

		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SF_ActorWalkToAsync(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #27 (0x1B) nonblocking
 *
 * Commands the specified actor to walk to the given position
 *
 * Param1: actor id
 * Param2: actor destination x
 * Param3: actor destination y
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T actor_parm;

	SDataWord_T x_parm;
	SDataWord_T y_parm;

	int actor_id;
	int actor_idx;

	R_POINT pt;

	SSTACK_Pop(thread->stack, &actor_parm);

	SSTACK_Pop(thread->stack, &x_parm);
	SSTACK_Pop(thread->stack, &y_parm);

	actor_id = SDATA_ReadWordS(actor_parm);

	actor_idx = ACTOR_GetActorIndex(actor_id);
	if (actor_idx < 0) {
		CON_Print(S_WARN_PREFIX "SF.08: Actor id 0x%X not found.",
		    actor_id);
		return R_FAILURE;
	}

	pt.x = SDATA_ReadWordS(x_parm);
	pt.y = SDATA_ReadWordS(y_parm);

	ACTOR_WalkTo(actor_idx, &pt, 0, NULL);

	return R_SUCCESS;
}

int SF_PlaceActor(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #30 (0x1E) nonblocking
 *
 * Positions an actor at the specified location; actor is created if the 
 *  actor does not already exist.
 *
 * Param1: actor id
 * Param2: actor pos x
 * Param3: actor pos y
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T actor_parm;

	SDataWord_T x_parm;
	SDataWord_T y_parm;

	int actor_id;
	int actor_idx;
	int result;

	R_POINT pt;

	SSTACK_Pop(thread->stack, &actor_parm);

	SSTACK_Pop(thread->stack, &x_parm);
	SSTACK_Pop(thread->stack, &y_parm);

	actor_id = SDATA_ReadWordS(actor_parm);

	pt.x = SDATA_ReadWordS(x_parm);
	pt.y = SDATA_ReadWordS(y_parm);

	if (!ACTOR_ActorExists(actor_id)) {

		result = ACTOR_Create(actor_id, pt.x, pt.y);

		if (result != R_SUCCESS) {

			CON_Print(S_WARN_PREFIX
			    "SF.30: Couldn't create actor 0x%X.", actor_id);
			return R_FAILURE;
		}
	} else {

		actor_idx = ACTOR_GetActorIndex(actor_id);

		ACTOR_Move(actor_idx, &pt);
	}

	return R_SUCCESS;
}

int SF_ActorWalkTo2(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #36 (0x24) ?
 *
 * Commands the specified actor to walk to the given position
 *
 * Param1: actor id
 * Param2: actor destination x
 * Param3: actor destination y
 * Param4: unknown
 *
\*--------------------------------------------------------------------------*/
{
	/* INCOMPLETE */

	SDataWord_T actor_parm;

	SDataWord_T x_parm;
	SDataWord_T y_parm;
	SDataWord_T unk_parm;

	int actor_idx;

	R_POINT pt;

	SSTACK_Pop(thread->stack, &actor_parm);

	SSTACK_Pop(thread->stack, &x_parm);
	SSTACK_Pop(thread->stack, &y_parm);
	SSTACK_Pop(thread->stack, &unk_parm);

	actor_idx = ACTOR_GetActorIndex(SDATA_ReadWordS(actor_parm));
	if (actor_idx < 0) {
		CON_Print(S_WARN_PREFIX "SF.36: Actor id 0x%X not found.",
		    (int)actor_parm);
		return R_FAILURE;
	}

	pt.x = SDATA_ReadWordS(x_parm);
	pt.y = SDATA_ReadWordS(y_parm);

#if 1
	ACTOR_WalkTo(actor_idx, &pt, 0, NULL);
#else
	ACTOR_WalkTo(actor_idx, &pt, 0, &thread->sem);
#endif

	return R_SUCCESS;
}

int SF_SetActorAct(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #37 (0x25) nonblocking
 *
 * Sets an actor to the specified action state
 *
 * Param1: actor id
 * Param2: unknown
 * Param3: actor action state
 * Param4: unknown
 *
\*--------------------------------------------------------------------------*/
{
	/* INCOMPLETE */

	SDataWord_T actor_parm;

	SDataWord_T unk1_parm;
	SDataWord_T unk2_parm;
	SDataWord_T action_parm;

	int actor_id;
	int actor_idx;

	int action;
	/*uint flags; */

	SSTACK_Pop(thread->stack, &actor_parm);

	SSTACK_Pop(thread->stack, &unk1_parm);
	SSTACK_Pop(thread->stack, &action_parm);
	SSTACK_Pop(thread->stack, &unk2_parm);

	actor_id = SDATA_ReadWordS(actor_parm);
	action = SDATA_ReadWordS(action_parm);

	actor_idx = ACTOR_GetActorIndex(actor_id);

	if (ACTOR_SetAction(actor_idx, action, ACTION_NONE) != R_SUCCESS) {
		CON_Print(S_WARN_PREFIX "SF.37: ACTOR_SetAction() failed.");

		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SF_SetActorAct2(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #38 (0x26) nonblocking
 *
 * Sets an actor to the specified action state
 *
 * Param1: actor id
 * Param2: actor action state
 * Param3: unknown
 *
\*--------------------------------------------------------------------------*/
{
	/* INCOMPLETE */

	SDataWord_T actor_parm;

	SDataWord_T unk1_parm;
	SDataWord_T action_parm;

	int actor_id;
	int actor_idx;

	int action;
	/*uint flags; */

	SSTACK_Pop(thread->stack, &actor_parm);

	SSTACK_Pop(thread->stack, &action_parm);
	SSTACK_Pop(thread->stack, &unk1_parm);

	actor_id = SDATA_ReadWordS(actor_parm);
	action = SDATA_ReadWordS(action_parm);

	actor_idx = ACTOR_GetActorIndex(actor_id);

	if (ACTOR_SetAction(actor_idx, action, ACTION_NONE) != R_SUCCESS) {
		CON_Print(S_WARN_PREFIX "SF.38: ACTOR_SetAction() failed.");

		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SF_LinkAnim(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #41 (0x29) nonblocking
 *
 * Links the specified animations for playback
 *
 * Param1: ?
 * Param2: total linked frame count
 * Param3: animation id link target
 * Param4: animation id link source
 *
\*--------------------------------------------------------------------------*/
{
	SDataWord_T unk_parm;

	SDataWord_T tframes_parm;
	SDataWord_T anim1_parm;
	SDataWord_T anim2_parm;

	int tframes;

	uint anim_id1;
	uint anim_id2;

	SSTACK_Pop(thread->stack, &anim1_parm);
	SSTACK_Pop(thread->stack, &anim2_parm);

	SSTACK_Pop(thread->stack, &tframes_parm);
	SSTACK_Pop(thread->stack, &unk_parm);

	tframes = SDATA_ReadWordS(tframes_parm);

	anim_id1 = SDATA_ReadWordU(anim1_parm);
	anim_id2 = SDATA_ReadWordU(anim2_parm);

	if (ANIM_Link(anim_id1, anim_id2) != R_SUCCESS) {

		CON_Print(S_WARN_PREFIX
		    "SF.41: ANIM_Link() failed. (%u->%u)\n", anim_id1,
		    anim_id2);

		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SF_PlaceActorEx(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #43 (0x2B) nonblocking
 *
 * Positions an actor at the specified location; actor is created if the 
 *  actor does not already exist.
 *
 * Param1: actor id
 * Param2: actor pos x
 * Param3: actor pos y
 * Param4: ?
 * Param5: actor action
 * Param6: ?
 *
\*--------------------------------------------------------------------------*/
{
	/* INCOMPLETE */

	SDataWord_T actor_parm;

	SDataWord_T x_parm;
	SDataWord_T y_parm;

	SDataWord_T action_parm;

	SDataWord_T unknown_parm;

	int actor_id;
	int actor_idx;
	int action_state;
	int result;

	R_POINT pt;

	SSTACK_Pop(thread->stack, &actor_parm);

	SSTACK_Pop(thread->stack, &x_parm);
	SSTACK_Pop(thread->stack, &y_parm);

	SSTACK_Pop(thread->stack, &unknown_parm);
	SSTACK_Pop(thread->stack, &action_parm);
	SSTACK_Pop(thread->stack, &unknown_parm);

	actor_id = SDATA_ReadWordS(actor_parm);

	pt.x = SDATA_ReadWordS(x_parm);
	pt.y = SDATA_ReadWordS(y_parm);

	action_state = SDATA_ReadWordU(action_parm);

	if (!ACTOR_ActorExists(actor_id)) {

		result = ACTOR_Create(actor_id, pt.x, pt.y);

		if (result != R_SUCCESS) {

			CON_Print(S_WARN_PREFIX
			    "SF.43: Couldn't create actor 0x%X.", actor_id);

			return R_FAILURE;
		}
	} else {

		actor_idx = ACTOR_GetActorIndex(actor_id);

		ACTOR_Move(actor_idx, &pt);
	}

	actor_idx = ACTOR_GetActorIndex(actor_id);

	ACTOR_SetDefaultAction(actor_idx, action_state, ACTION_NONE);
	ACTOR_SetAction(actor_idx, action_state, ACTION_NONE);

	return R_SUCCESS;
}

int SF_CheckUserInterrupt(R_SCRIPTFUNC_PARAMS)
/*--------------------------------------------------------------------------*\
 * 
 * Script function #44 (0x2C) nonblocking
 *
 * Checks to see if the user has interrupted a currently playing 
 * game cinematic. Pushes a zero or positive value if the game 
 * has not been interrupted.
 *
\*--------------------------------------------------------------------------*/
{
	SSTACK_Push(thread->stack, 0);

	/* INCOMPLETE */

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: sfuncs.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sfuncs.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module script function component header file

 Notes: 
*/

#ifndef SAGA_SFUNCS_H
#define SAGA_SFUNCS_H

#include "sthread.h"

namespace Saga {

#define R_SFUNC_NUM 78


#define R_SCRIPTFUNC_PARAMS R_SCRIPT_THREAD * thread

typedef int (*SFunc_T) (R_SCRIPTFUNC_PARAMS);

typedef struct R_SFUNC_ENTRY_tag {

	int sfunc_num;
	int sfunc_argc;
	SFunc_T sfunc_fp;

} R_SFUNC_ENTRY;

extern R_SFUNC_ENTRY SFuncList[];

/* SF 1 */
int SF_Sleep(R_SCRIPTFUNC_PARAMS);

/* SF 3 */
int SF_3(R_SCRIPTFUNC_PARAMS);

/* SF 4 */
int SF_SetCommandText(R_SCRIPTFUNC_PARAMS);

/* SF 6 */
int SF_ActorWalkTo(R_SCRIPTFUNC_PARAMS);

/* SF 8 */
int SF_SetActorOrient(R_SCRIPTFUNC_PARAMS);

/* SF 11 */
int SF_FreezeInterface(R_SCRIPTFUNC_PARAMS);

/* SF 26 */
int SF_StartAnim(R_SCRIPTFUNC_PARAMS);

/* SF 27 */
int SF_ActorWalkToAsync(R_SCRIPTFUNC_PARAMS);

/* SF 30 */
int SF_PlaceActor(R_SCRIPTFUNC_PARAMS);

/* SF 36 */
int SF_ActorWalkTo2(R_SCRIPTFUNC_PARAMS);

/* SF 37 */
int SF_SetActorAct(R_SCRIPTFUNC_PARAMS);

/* SF 38 */
int SF_SetActorAct2(R_SCRIPTFUNC_PARAMS);

/* SF 41 */
int SF_LinkAnim(R_SCRIPTFUNC_PARAMS);

/* SF 43 */
int SF_PlaceActorEx(R_SCRIPTFUNC_PARAMS);

/* SF 44 */
int SF_CheckUserInterrupt(R_SCRIPTFUNC_PARAMS);

} // End of namespace Saga

#endif				/* SAGA_SFUNCS_H */

--- NEW FILE: sndres.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sndres.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:   
 
    Sound resource management module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

#include <limits.h>

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "game_mod.h"
#include "rscfile_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "sndres_mod.h"
#include "sndres.h"

namespace Saga {

R_SNDRES_MODULE SndModule;

int SND_Init(void)
{
	int result;

	/* Load sound module resource file contexts
	 * \*------------------------------------------------------------- */
	result = GAME_GetFileContext(&SndModule.sfx_ctxt, R_GAME_SOUNDFILE, 0);
	if (result != R_SUCCESS) {
		return R_FAILURE;
	}

	result = GAME_GetFileContext(&SndModule.voice_ctxt,
	    R_GAME_VOICEFILE, 0);
	if (result != R_SUCCESS) {
		return R_FAILURE;
	}

	/* Grab sound resource information for the current game
	 * \*------------------------------------------------------------- */
	GAME_GetSoundInfo(&SndModule.snd_info);

	SndModule.init = 1;

	return R_SUCCESS;
}

int SND_PlayVoice(ulong voice_rn)
{
	R_SOUNDBUFFER snd_buffer;
	int result;

	result = SND_Load(SndModule.voice_ctxt, voice_rn, &snd_buffer);
	if (result != R_SUCCESS) {
		return R_FAILURE;
	}

	SYSSOUND_PlayVoice(&snd_buffer);

	return R_SUCCESS;
}

int
SND_Load(R_RSCFILE_CONTEXT * snd_ctxt, ulong snd_rn, R_SOUNDBUFFER * snd_buf_i)
{

	uchar *snd_res;
	size_t snd_res_len;

	int result;

	assert((snd_ctxt != NULL) && (snd_buf_i != NULL));

	result = RSC_LoadResource(snd_ctxt, snd_rn, &snd_res, &snd_res_len);
	if (result != R_SUCCESS) {
		return R_FAILURE;
	}

	switch (SndModule.snd_info.res_type) {

	case R_GAME_SOUND_PCM:

		snd_buf_i->s_freq = SndModule.snd_info.freq;
		snd_buf_i->s_samplebits = SndModule.snd_info.sample_size;
		snd_buf_i->s_stereo = SndModule.snd_info.stereo;

		snd_buf_i->res_data = snd_res;
		snd_buf_i->res_len = snd_res_len;

		snd_buf_i->s_buf = snd_res;
		snd_buf_i->s_buf_len = snd_res_len;

		snd_buf_i->s_signed = 1;

		break;

	case R_GAME_SOUND_VOC:

		if (LoadVocSound(snd_res, snd_res_len, snd_buf_i) != R_SUCCESS) {

			RSC_FreeResource(snd_res);

			return R_FAILURE;
		}

		break;

	default:
		/* Unknown sound type */

		RSC_FreeResource(snd_res);

		return R_FAILURE;
		break;
	}

	return R_SUCCESS;
}

int
LoadVocSound(const uchar * snd_res,
    size_t snd_res_len, R_SOUNDBUFFER * snd_buf_i)
{

	R_VOC_HEADER_BLOCK voc_hb;
	R_VOC_GENBLOCK voc_gb;
	R_VOC_BLOCK1 voc_b1;

	long byte_rate;

	const uchar *read_p;
	size_t read_len;

	read_p = snd_res;
	read_len = snd_res_len;

	if (read_len < R_VOC_HEADER_BLOCK_LEN) {
		return R_FAILURE;
	}

	memcpy(voc_hb.ft_desc, read_p, R_VOC_FILE_DESC_LEN);
	read_p += R_VOC_FILE_DESC_LEN;
	read_len -= R_VOC_FILE_DESC_LEN;

	if (memcmp(voc_hb.ft_desc, R_VOC_FILE_DESC, R_VOC_FILE_DESC_LEN) != 0) {

		/* Voc file desc string not found */
		return R_FAILURE;
	}

	voc_hb.db_offset = ys_read_u16_le(read_p, &read_p);
	voc_hb.voc_version = ys_read_u16_le(read_p, &read_p);
	voc_hb.voc_fileid = ys_read_u16_le(read_p, &read_p);

	if (read_len < voc_hb.db_offset + R_VOC_GENBLOCK_LEN) {

		return R_FAILURE;
	}

	read_p = snd_res + voc_hb.db_offset;
	read_len = snd_res_len - voc_hb.db_offset;

	for (;;) {

		/* Read generic block header
		 * \*--------------------------------------------------------- */
		if (read_len < R_VOC_GENBLOCK_LEN) {
			return R_FAILURE;
		}

		voc_gb.block_id = ys_read_u8(read_p, &read_p);
		if (voc_gb.block_id == 0) {
			return R_FAILURE;
		}

		voc_gb.block_len = ys_read_u24_le(read_p, &read_p);

		read_len -= R_VOC_GENBLOCK_LEN;

		/* Process block
		 * \*--------------------------------------------------------- */
		switch (voc_gb.block_id) {

		case 1:	/* Sound data block */

			voc_b1.time_constant = ys_read_u8(read_p, &read_p);
			voc_b1.pack_method = ys_read_u8(read_p, &read_p);
			read_len -= 2;

			if (voc_b1.pack_method != 0) {
				/* Packed VOC files not supported */
				return R_FAILURE;
			}

			byte_rate = R_VOC_TIME_BASE / (R_VOC_TIME_CBASE -
			    (voc_b1.time_constant << 8));

			snd_buf_i->s_stereo = 0;
			snd_buf_i->s_samplebits = 8;
			snd_buf_i->s_freq = byte_rate;

			snd_buf_i->res_data = (uchar *) snd_res;
			snd_buf_i->res_len = snd_res_len;

			snd_buf_i->s_buf = (uchar *) read_p;
			snd_buf_i->s_buf_len = read_len - 1;	/* -1 for end block */

			snd_buf_i->s_signed = 0;

			return R_SUCCESS;

			break;

		default:

			read_p += voc_gb.block_len;
			read_len -= voc_gb.block_len;
			break;
		}
	}

	return R_SUCCESS;
}

int SND_GetVoiceLength(ulong voice_rn)
{

	ulong length;

	double ms_f;
	int ms_i = -1;

	int result;

	assert(SndModule.init);

	result = RSC_GetResourceSize(SndModule.voice_ctxt, voice_rn, &length);
	if (result != R_SUCCESS) {
		return -1;
	}

	if (SndModule.snd_info.res_type == R_GAME_SOUND_PCM) {

		ms_f = (double)length /
		    (SndModule.snd_info.sample_size / CHAR_BIT) /
		    (SndModule.snd_info.freq) * 1000.0;

		ms_i = (int)ms_f;
	} else if (SndModule.snd_info.res_type == R_GAME_SOUND_VOC) {

		/* Rough hack, fix this to be accurate */

		ms_f = (double)length / 14705 * 1000.0;
		ms_i = (int)ms_f;
	} else {
		return -1;
	}

	return ms_i;
}

int
SND_ITEVOC_Resample(long src_freq,
    long dst_freq,
    uchar * src_buf,
    size_t src_buf_len, uchar ** dst_buf, size_t * dst_buf_len)
{
	uchar *resamp_buf;
	size_t resamp_len;

	uchar src_samp_a;
	uchar src_samp_b;

	const uchar *read_pa;
	const uchar *read_pb;

	uchar *write_pa;
	uchar *write_pb;
	uchar *write_pc;

	size_t src_i;

	assert(src_freq == 14705);
	assert(dst_freq == 22050);

	resamp_len = (size_t) (src_buf_len * 1.5);
	resamp_buf = (uchar *)malloc(resamp_len);
	if (resamp_buf == NULL) {
		return R_FAILURE;
	}

	read_pa = src_buf;
	read_pb = src_buf + 1;

	write_pa = resamp_buf;
	write_pb = resamp_buf + 1;
	write_pc = resamp_buf + 2;

	for (src_i = 0; src_i < src_buf_len / 2; src_i++) {

		src_samp_a = *read_pa;
		src_samp_b = *read_pb;

		read_pa += 2;
		read_pb += 2;

		*write_pa = src_samp_a;
		*write_pb = (uchar) ((src_samp_a / 2) + (src_samp_b / 2));
		*write_pc = src_samp_b;

		write_pa += 3;
		write_pb += 3;
		write_pc += 3;
	}

	*dst_buf = resamp_buf;
	*dst_buf_len = resamp_len;

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: sndres.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sndres.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:   
 
    Sound resource management module - private header

 Notes: 
*/

#ifndef SAGA_SNDRES_H_
#define SAGA_SNDRES_H_

namespace Saga {

#define R_VOC_TIME_BASE  256000000L
#define R_VOC_TIME_CBASE 65536L

#define R_VOC_FILE_DESC_LEN 20
#define R_VOC_FILE_DESC "Creative Voice File\x1A"

typedef struct R_VOC_HEADER_BLOCK_tag {

	char ft_desc[20];	/* BYTE [20] */
	uint db_offset;		/* WORD */
	uint voc_version;	/* WORD */
	uint voc_fileid;	/* WORD */

} R_VOC_HEADER_BLOCK;

#define R_VOC_HEADER_BLOCK_LEN 26

typedef struct R_VOC_GENBLOCK_tag {

	int block_id;		/* BYTE */
	ulong block_len;	/* BYTE[3] */

} R_VOC_GENBLOCK;

#define R_VOC_GENBLOCK_LEN 4

typedef struct R_VOC_BLOCK1_tag {

	int block_id;		/* BYTE */
	ulong block_len;	/* BYTE[3] */
	uint time_constant;	/* BYTE */
	int pack_method;	/* BYTE */

} R_VOC_BLOCK1;

typedef struct R_SNDRES_MODULE_tag {

	int init;

	R_RSCFILE_CONTEXT *sfx_ctxt;
	R_RSCFILE_CONTEXT *voice_ctxt;

	R_GAME_SOUNDINFO snd_info;

} R_SNDRES_MODULE;

int
SND_Load(R_RSCFILE_CONTEXT * snd_ctxt,
    ulong snd_rn, R_SOUNDBUFFER * snd_buf_i);

int
LoadVocSound(const uchar * snd_res,
    size_t snd_res_len, R_SOUNDBUFFER * snd_buf_i);

} // End of namespace Saga

#endif				/* SAGA_SNDRES_H_ */

--- NEW FILE: sndres_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sndres_mod.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:   
 
    Sound resource management module - public header

 Notes: 
*/

#ifndef SAGA_SNDRES_MOD_H_
#define SAGA_SNDRES_MOD_H_

namespace Saga {

int SND_Init(void);

int SND_LoadSound(ulong sound_rn);

int SND_PlayVoice(ulong voice_rn);

int SND_GetVoiceLength(ulong voice_rn);

int
SND_ITEVOC_Resample(long src_freq,
    long dst_freq,
    uchar * src_buf,
    size_t src_buf_len, uchar ** dst_buf, size_t * dst_buf_len);

} // End of namespace Saga

#endif				/* SAGA_SNDRES_MOD_H_ */

--- NEW FILE: sprite.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sprite.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:   
 
    Sprite management module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "game_mod.h"
#include "gfx_mod.h"
#include "scene_mod.h"
#include "rscfile_mod.h"

#include "text_mod.h"
#include "font_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "sprite_mod.h"
#include "sprite.h"

namespace Saga {

R_SPRITE_MODULE SpriteModule = { 0 };

int SPRITE_Init(void)
{
	int result;

	if (SpriteModule.init) {
		return R_FAILURE;
	}

	R_printf(R_STDOUT, "Initializing sprite subsystem...\n");

	/* Load sprite module resource context
	 * \*------------------------------------------------------------- */
	result = GAME_GetFileContext(&SpriteModule.sprite_ctxt,
	    R_GAME_RESOURCEFILE, 0);
	if (result != R_SUCCESS) {

		return R_FAILURE;
	}

	SpriteModule.decode_buf_len = R_DECODE_BUF_LEN;

	SpriteModule.decode_buf = (uchar *)malloc(R_DECODE_BUF_LEN);
	if (SpriteModule.decode_buf == NULL) {
		return R_MEM;
	}

	SpriteModule.init = 1;

	return R_SUCCESS;
}

int SPRITE_Shutdown(void)
{
	if (!SpriteModule.init) {
		return R_FAILURE;
	}

	R_printf(R_STDOUT, "Shutting down sprite subsystem...\n");

	free(SpriteModule.decode_buf);

	return R_SUCCESS;
}

int SPRITE_LoadList(int resource_num, R_SPRITELIST ** sprite_list_p)
{
	R_SPRITELIST *new_slist;

	uchar *spritelist_data;
	size_t spritelist_len;

	const uchar *read_p;

	uint sprite_count;
	uint i;

	new_slist = (R_SPRITELIST *)malloc(sizeof *new_slist);
	if (new_slist == NULL) {

		return R_MEM;
	}

	if (RSC_LoadResource(SpriteModule.sprite_ctxt,
		resource_num,
		&spritelist_data, &spritelist_len) != R_SUCCESS) {

		return R_FAILURE;
	}

	read_p = spritelist_data;

	sprite_count = ys_read_u16_le(read_p, &read_p);

	new_slist->sprite_count = sprite_count;

	new_slist->offset_list = (R_SPRITELIST_OFFSET *)malloc(sprite_count *
	    sizeof *new_slist->offset_list);
	if (new_slist->offset_list == NULL) {
		free(new_slist);

		return R_MEM;
	}

	for (i = 0; i < sprite_count; i++) {
		new_slist->offset_list[i].data_idx = 0;
		new_slist->offset_list[i].offset =
		    ys_read_u16_le(read_p, &read_p);
	}

	new_slist->slist_rn = resource_num;
	new_slist->sprite_data[0] = spritelist_data;
	new_slist->append_count = 0;

	*sprite_list_p = new_slist;

	return R_SUCCESS;
}

int SPRITE_AppendList(int resource_num, R_SPRITELIST * spritelist)
{
	uchar *spritelist_data;
	size_t spritelist_len;

	const uchar *read_p;

	void *test_p;

	uint old_sprite_count;
	uint new_sprite_count;
	uint sprite_count;

	int i;

	if (spritelist->append_count >= (R_APPENDMAX - 1)) {

		return R_FAILURE;
	}

	if (RSC_LoadResource(SpriteModule.sprite_ctxt,
		resource_num,
		&spritelist_data, &spritelist_len) != R_SUCCESS) {

		return R_FAILURE;
	}

	read_p = spritelist_data;

	sprite_count = ys_read_u16_le(read_p, &read_p);

	old_sprite_count = spritelist->sprite_count;
	new_sprite_count = spritelist->sprite_count + sprite_count;

	test_p = realloc(spritelist->offset_list,
	    new_sprite_count * sizeof *spritelist->offset_list);
	if (test_p == NULL) {
		return R_MEM;
	}

	spritelist->offset_list = (R_SPRITELIST_OFFSET *)test_p;

	spritelist->sprite_count = new_sprite_count;
	spritelist->append_count++;

	for (i = old_sprite_count; i < spritelist->sprite_count; i++) {
		spritelist->offset_list[i].data_idx = spritelist->append_count;
		spritelist->offset_list[i].offset =
		    ys_read_u16_le(read_p, &read_p);
	}

	spritelist->sprite_data[spritelist->append_count] = spritelist_data;

	return R_SUCCESS;
}

int SPRITE_GetListLen(R_SPRITELIST * spritelist)
{

	return spritelist->sprite_count;
}

int SPRITE_Free(R_SPRITELIST * spritelist)
{
	int i;

	for (i = 0; i <= spritelist->append_count; i++) {

		RSC_FreeResource(spritelist->sprite_data[i]);
	}

	free(spritelist->offset_list);
	free(spritelist);

	return R_SUCCESS;
}

int
SPRITE_Draw(R_SURFACE * ds,
    R_SPRITELIST * sprite_list, int sprite_num, int spr_x, int spr_y)
{

	int offset;
	int offset_idx;

	uchar *sprite_p;

	const uchar *sprite_data_p;
	const uchar *read_p;

	int i, j;

	uchar *buf_row_p;
	uchar *src_row_p;

	int s_width;
	int s_height;

	int clip_width;
	int clip_height;

	int x_align;
	int y_align;

	if (!SpriteModule.init) {
		return R_FAILURE;
	}

	offset = sprite_list->offset_list[sprite_num].offset;
	offset_idx = sprite_list->offset_list[sprite_num].data_idx;

	sprite_p = sprite_list->sprite_data[offset_idx];
	sprite_p += offset;

	read_p = (uchar *) sprite_p;

	x_align = ys_read_s8(read_p, &read_p);
	y_align = ys_read_s8(read_p, &read_p);

	s_width = ys_read_u8(read_p, &read_p);
	s_height = ys_read_u8(read_p, &read_p);

	sprite_data_p = read_p;

	spr_x += x_align;
	spr_y += y_align;

	if (spr_x < 0) {
		return 0;
	}

	if (spr_y < 0) {
		return 0;
	}

	DecodeRLESprite(sprite_data_p,
	    64000, SpriteModule.decode_buf, s_width * s_height);

	buf_row_p = ds->buf + ds->buf_pitch * spr_y;
	src_row_p = SpriteModule.decode_buf;

	/* Clip to right side of surface */
	clip_width = s_width;
	if (s_width > (ds->buf_w - spr_x)) {
		clip_width = (ds->buf_w - spr_x);
	}

	/* Clip to bottom side of surface */
	clip_height = s_height;
	if (s_height > (ds->buf_h - spr_y)) {
		clip_height = (ds->buf_h - spr_y);
	}

	for (i = 0; i < clip_height; i++) {

		for (j = 0; j < clip_width; j++) {
			if (*(src_row_p + j) != 0) {
				*(buf_row_p + j + spr_x) = *(src_row_p + j);
			}
		}

		buf_row_p += ds->buf_pitch;
		src_row_p += s_width;
	}

	return R_SUCCESS;
}

int
SPRITE_DrawOccluded(R_SURFACE * ds,
    R_SPRITELIST * sprite_list, int sprite_num, int spr_x, int spr_y)
{
	int offset;
	int offset_idx;

	uchar *sprite_p;
	const uchar *sprite_data_p;
	const uchar *read_p;

	int i;

	int x, y;
	uchar *dst_row_p;
	uchar *src_row_p;
	uchar *src_p;
	uchar *dst_p;
	uchar *mask_p;

	int s_width;
	int s_height;
	int x_align;
	int y_align;

	int z_lut[R_SPRITE_ZMAX];
	int e_slope;

	/* Clipinfo variables */
	R_POINT spr_pt;
	R_RECT spr_src_rect;
	R_RECT spr_dst_rect;

	R_CLIPINFO ci;

	/* BG mask variables */
	int mask_w;
	int mask_h;
	uchar *mask_buf;
	size_t mask_buf_len;

	uchar *mask_row_p;
	int mask_z;

	/* Z info variables */
	SCENE_ZINFO zinfo;
	int actor_z;

	if (!SpriteModule.init) {
		return R_FAILURE;
	}

	if (!SCENE_IsBGMaskPresent()) {
		return SPRITE_Draw(ds, sprite_list, sprite_num, spr_x, spr_y);
	}

	if (sprite_num >= sprite_list->sprite_count) {

		R_printf(R_STDOUT,
		    "Invalid sprite number (%d) for sprite list %d.\n",
		    sprite_num, sprite_list->slist_rn);

		return R_FAILURE;
	}

	/* Get sprite data from list 
	 * \*------------------------------------------------------------- */
	offset = sprite_list->offset_list[sprite_num].offset;
	offset_idx = sprite_list->offset_list[sprite_num].data_idx;

	sprite_p = sprite_list->sprite_data[offset_idx];
	sprite_p += offset;

	read_p = sprite_p;

	/* Read sprite dimensions -- should probably cache this stuff in 
	 * sprite list */
	x_align = ys_read_s8(read_p, &read_p);
	y_align = ys_read_s8(read_p, &read_p);

	s_width = ys_read_u8(read_p, &read_p);
	s_height = ys_read_u8(read_p, &read_p);

	sprite_data_p = read_p;

	/* Create actor Z occlusion LUT
	 * \*---------------------------------------------------------------------- */
	SCENE_GetZInfo(&zinfo);

	e_slope = zinfo.end_slope;

	for (i = 0; i < R_SPRITE_ZMAX; i++) {

		z_lut[i] =
		    (int)(e_slope + ((137.0 - e_slope) / 14.0) * (15.0 - i));
	}

	actor_z = spr_y;

	SCENE_GetBGMaskInfo(&mask_w, &mask_h, &mask_buf, &mask_buf_len);

	spr_src_rect.x1 = 0;
	spr_src_rect.y1 = 0;
	spr_src_rect.x2 = s_width - 1;
	spr_src_rect.y2 = s_height - 1;

	spr_dst_rect.x1 = 0;
	spr_dst_rect.y1 = 0;
	spr_dst_rect.x2 = ds->clip_rect.x2;
	spr_dst_rect.y2 = YS_MIN(ds->clip_rect.y2, mask_h - 1);

	spr_pt.x = spr_x + x_align;
	spr_pt.y = spr_y + y_align;

	spr_x += x_align;
	spr_y += y_align;

	ci.dst_rect = &spr_dst_rect;
	ci.src_rect = &spr_src_rect;
	ci.dst_pt = &spr_pt;

	GFX_GetClipInfo(&ci);

	if (ci.nodraw) {
		return R_SUCCESS;
	}

	DecodeRLESprite(sprite_data_p,
	    64000, SpriteModule.decode_buf, s_width * s_height);

	/* Finally, draw the occluded sprite
	 * \*---------------------------------------------------------------------- */
	src_row_p = SpriteModule.decode_buf + ci.src_draw_x +
	    (ci.src_draw_y * s_width);

	dst_row_p = ds->buf + ci.dst_draw_x + (ci.dst_draw_y * ds->buf_pitch);
	mask_row_p = mask_buf + ci.dst_draw_x + (ci.dst_draw_y * mask_w);

	for (y = 0; y < ci.draw_h; y++) {

		src_p = src_row_p;
		dst_p = dst_row_p;
		mask_p = mask_row_p;

		for (x = 0; x < ci.draw_w; x++) {

			if (*src_p != 0) {

				mask_z = *mask_p & R_SPRITE_ZMASK;

				if (actor_z > z_lut[mask_z]) {
					*dst_p = *src_p;
				}
			}
			src_p++;
			dst_p++;
			mask_p++;
		}
		dst_row_p += ds->buf_pitch;
		mask_row_p += mask_w;
		src_row_p += s_width;
	}
/*
    {
        char buf[1024] = { 0 };
        
        sprintf( buf, "dw: %d, dh: %d.", ci.draw_w, ci.draw_h );

        TEXT_Draw( 2,
                   ds,
                   buf,
                   spr_x - x_align, spr_y - y_align,
                   255, 0,
                   FONT_OUTLINE );
    }
*/
	return R_SUCCESS;
}

int
DecodeRLESprite(const uchar * inbuf,
    size_t inbuf_len, uchar * outbuf, size_t outbuf_len)
{

	int bg_runcount;
	int fg_runcount;

	const uchar *inbuf_ptr;
	uchar *outbuf_ptr;

	const uchar *inbuf_end;
	uchar *outbuf_end;

	int c;

	inbuf_ptr = inbuf;
	outbuf_ptr = outbuf;

	inbuf_end = inbuf + (inbuf_len);
	inbuf_end--;

	outbuf_end = outbuf + outbuf_len;
	outbuf_end--;

	memset(outbuf, 0, outbuf_len);

	while ((inbuf_ptr < inbuf_end) && (outbuf_ptr < outbuf_end)) {

		bg_runcount = *inbuf_ptr;
		if (inbuf_ptr < inbuf_end)
			inbuf_ptr++;
		else
			return 0;
		fg_runcount = *inbuf_ptr;
		if (inbuf_ptr < inbuf_end)
			inbuf_ptr++;
		else
			return 0;

		for (c = 0; c < bg_runcount; c++) {

			*outbuf_ptr = (uchar) 0;
			if (outbuf_ptr < outbuf_end)
				outbuf_ptr++;
			else
				return 0;
		}

		for (c = 0; c < fg_runcount; c++) {

			*outbuf_ptr = *inbuf_ptr;
			if (inbuf_ptr < inbuf_end)
				inbuf_ptr++;
			else
				return 0;
			if (outbuf_ptr < outbuf_end)
				outbuf_ptr++;
			else
				return 0;
		}
	}

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: sprite.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sprite.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:	
 
	Sprite management module private header file

 Notes: 
*/

#ifndef SAGA_SPRITE_H__
#define SAGA_SPRITE_H__

namespace Saga {

#define R_APPENDMAX 4

#define R_SPRITE_ZMAX  16
#define R_SPRITE_ZMASK 0x0F

#define R_DECODE_BUF_LEN 64000

typedef struct R_SPRITELIST_ENTRY_tag {

	int x_align;
	int y_align;
	int width;
	int height;

} R_SPRITELIST_ENTRY;

typedef struct R_SPRITELIST_OFFSET_tag {

	uint data_idx;
	size_t offset;

} R_SPRITELIST_OFFSET;

struct R_SPRITELIST_tag {

	int append_count;
	int sprite_count;

	R_SPRITELIST_OFFSET *offset_list;

	int slist_rn;
	uchar *sprite_data[R_APPENDMAX];

};

typedef struct R_SPRITE_MODULE_tag {

	int init;

	R_RSCFILE_CONTEXT *sprite_ctxt;

	uchar *decode_buf;
	size_t decode_buf_len;

} R_SPRITE_MODULE;

int
DecodeRLESprite(const uchar * inbuf,
    size_t inbuf_len, uchar * outbuf, size_t outbuf_len);

} // End of namespace Saga

#endif				/* SAGA_SPRITE_H__ */

--- NEW FILE: sprite_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sprite_mod.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Sprite management module public header file

 Notes: 
*/

#ifndef SAGA_SPRITE_MOD_H__
#define SAGA_SPRITE_MOD_H__

namespace Saga {

typedef struct R_SPRITELIST_tag R_SPRITELIST;

int SPRITE_Init(void);

int SPRITE_Shutdown(void);

int SPRITE_LoadList(int resource_num, R_SPRITELIST ** sprite_list_p);

int SPRITE_AppendList(int resource_num, R_SPRITELIST * spritelist);

int SPRITE_GetListLen(R_SPRITELIST * spritelist);

int SPRITE_Free(R_SPRITELIST * spritelist);

int
SPRITE_Draw(R_SURFACE * ds,
    R_SPRITELIST * sprite_list, int sprite_num, int spr_x, int spr_y);

int
SPRITE_DrawOccluded(R_SURFACE * ds,
    R_SPRITELIST * sprite_list, int sprite_num, int spr_x, int spr_y);

} // End of namespace Saga

#endif				/* SAGA_SPRITE_MOD_H__ */

--- NEW FILE: sstack.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sstack.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting engine stack component

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "console_mod.h"
#include "text_mod.h"

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "script.h"
#include "sstack.h"

namespace Saga {

int SSTACK_Create(SSTACK * stack, int stack_len, int flags)
{

	SSTACK new_stack;
	SDataWord_T *new_stack_data;

	*stack = NULL;

	new_stack = (SSTACK_tag *)malloc(sizeof(struct SSTACK_tag));
	if (new_stack == NULL) {

		return STACK_MEM;
	}

	new_stack_data = (SDataWord_T *)calloc(stack_len, sizeof *new_stack_data);
	if (new_stack_data == NULL) {
		free(new_stack);

		return STACK_MEM;
	}

	new_stack->data = new_stack_data;

	new_stack->flags = flags;
	new_stack->len = stack_len;
	new_stack->top = -1;

	*stack = new_stack;

	return STACK_SUCCESS;
}

int SSTACK_Destroy(SSTACK stack)
{
	if (stack != NULL) {
		free(stack->data);
	}

	free(stack);

	return STACK_SUCCESS;
}

int SSTACK_Clear(SSTACK stack)
{

	stack->top = -1;

	return STACK_SUCCESS;
}

int SSTACK_PushNull(SSTACK stack)
{

	if (stack->top >= (stack->len - 1)) {

		if (stack->flags & STACK_FIXED) {

			return STACK_OVERFLOW;
		} else if (SSTACK_Grow(stack) != STACK_SUCCESS) {

			return STACK_MEM;
		}
	}

	stack->top++;

	return STACK_SUCCESS;
}

int SSTACK_Push(SSTACK stack, SDataWord_T value)
{

	if (stack->top >= (stack->len - 1)) {

		if (stack->flags & STACK_FIXED) {

			return STACK_OVERFLOW;
		} else if (SSTACK_Grow(stack) != STACK_SUCCESS) {

			return STACK_MEM;
		}
	}

	stack->top++;
	stack->data[stack->top] = value;

	return STACK_SUCCESS;
}

int SSTACK_Pop(SSTACK stack, SDataWord_T * value)
{

	if (stack->top <= -1) {

		return STACK_UNDERFLOW;
	}

	if (value == NULL) {

		stack->top--;
		return STACK_SUCCESS;
	}

	*value = stack->data[stack->top];
	stack->top--;

	return STACK_SUCCESS;
}

int SSTACK_Top(SSTACK stack, SDataWord_T * value)
{

	*value = 0;

	if (stack->top <= -1) {

		return STACK_UNDERFLOW;
	}

	*value = stack->data[stack->top];

	return STACK_SUCCESS;
}

int SSTACK_Grow(SSTACK stack)
{

	SDataWord_T *new_data;

	if ((stack->len * 2) > R_STACK_SIZE_LIMIT) {

		CON_Print(S_ERROR_PREFIX "Stack fault: growing beyond limit.");
		return STACK_OVERFLOW;
	}

	new_data = (SDataWord_T *)realloc(stack->data, (stack->len * 2) * sizeof *new_data);
	if (new_data == NULL) {

		return STACK_MEM;
	}

	stack->data = new_data;
	stack->len *= 2;

	return STACK_SUCCESS;
}

} // End of namespace Saga


--- NEW FILE: sstack.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sstack.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting engine stack component header file

 Notes: 
*/

#ifndef SAGA_SSTACK_H
#define SAGA_SSTACK_H

#include "script_mod.h"

namespace Saga {

#define R_STACK_SIZE_LIMIT 16384

struct SSTACK_tag {
	int flags;
	int len;
	int top;
	SDataWord_T *data;
};

typedef struct SSTACK_tag *SSTACK;

typedef enum SSTACK_ERR_enum {
	STACK_SUCCESS = 0,
	STACK_ERROR,
	STACK_MEM,
	STACK_UNDERFLOW,
	STACK_OVERFLOW
} SSTACK_ERR_CODE;

typedef enum SSTACK_FLAGS_enum {
	STACK_FIXED = 0x00,
	STACK_GROW = 0x01
} SSTACK_FLAGS;

int SSTACK_Create(SSTACK * stack, int stack_len, int flags);

int SSTACK_Destroy(SSTACK stack);

int SSTACK_Clear(SSTACK stack);

int SSTACK_Push(SSTACK stack, SDataWord_T value);

int SSTACK_PushNull(SSTACK stack);

int SSTACK_Pop(SSTACK stack, SDataWord_T * value);

int SSTACK_Top(SSTACK stack, SDataWord_T * value);

int SSTACK_Grow(SSTACK stack);

} // End of namespace Saga

#endif				/* SAGA_SSTACK_H */

--- NEW FILE: stack.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/stack.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:	
 
	Simple integer stack module

 Notes: 
*/

#include "reinherit.h"

#include "stack.h"
#include "stack_mod.h"

namespace Saga {

int ISTACK_Create(R_ISTACK * stack, int stack_len, int flags)
{

	R_ISTACK new_stack;
	int *new_stack_data;

	*stack = NULL;

	new_stack = (R_ISTACK_tag *)malloc(sizeof(struct R_ISTACK_tag));

	if (new_stack == NULL) {
		return STACK_MEM;
	}

	new_stack_data = (int *)calloc(stack_len, sizeof(int));

	if (new_stack_data == NULL) {

		free(new_stack);
		return STACK_MEM;
	}

	new_stack->flags = flags;
	new_stack->len = stack_len;
	new_stack->top = -1;

	return STACK_SUCCESS;
}

int ISTACK_Destroy(R_ISTACK * stack)
{

	if (stack != NULL) {
		free((*stack)->data);
	}

	free(stack);

	*stack = NULL;

	return STACK_SUCCESS;
}

int ISTACK_Clear(R_ISTACK stack)
{

	stack->top = -1;
	return STACK_SUCCESS;
}

int ISTACK_PushNull(R_ISTACK stack)
{

	if (stack->top >= (stack->len - 1)) {

		if (stack->flags & STACK_FIXED) {

			return STACK_OVERFLOW;
		} else if (ISTACK_Grow(stack) != STACK_SUCCESS) {

			return STACK_MEM;
		}
	}

	stack->top++;

}

int ISTACK_Push(R_ISTACK stack, int value)
{

	if (stack->top >= (stack->len - 1)) {

		if (stack->flags & STACK_FIXED) {

			return STACK_OVERFLOW;
		} else if (ISTACK_Grow(stack) != STACK_SUCCESS) {

			return STACK_MEM;
		}
	}

	stack->top++;
	stack->data[stack->top] = value;

	return STACK_SUCCESS;
}

int ISTACK_Pop(R_ISTACK stack, int *value)
{

	if (stack->top <= -1) {

		return STACK_UNDERFLOW;
	}

	if (value == NULL) {

		stack->top--;
		return STACK_SUCCESS;
	}

	*value = stack->data[stack->top];
	stack->top--;

	return STACK_SUCCESS;
}

int ISTACK_Top(R_ISTACK stack, int *value)
{
	*value = 0;

	if (stack->top <= -1) {

		return STACK_UNDERFLOW;
	}

	*value = stack->data[stack->top];

	return STACK_SUCCESS;

}

int ISTACK_Grow(R_ISTACK stack)
{

	int *new_data;

	new_data = (int *)realloc(stack->data, (stack->len * 2) * sizeof(int));

	if (new_data == NULL) {

		return STACK_MEM;
	};

	stack->data = new_data;
	stack->len *= 2;

	return STACK_SUCCESS;
}

} // End of namespace Saga


--- NEW FILE: stack.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/stack.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:	
 
	Simple integer stack module private header

 Notes: 
*/

#ifndef SAGA_STACK_H
#define SAGA_STACK_H

namespace Saga {

#define ISTACK_MAX

struct R_ISTACK_tag {

	int flags;
	int len;
	int top;
	int *data;

};

} // End of namespace Saga

#endif				/* SAGA_STACK_H */

--- NEW FILE: stack_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/stack_mod.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:	
 
	Simple integer stack module public header

 Notes: 
*/

#ifndef SAGA_STACK_MOD_H
#define SAGA_STACK_MOD_H

#include "stack.h"

namespace Saga {

typedef enum STACK_ERR_enum {
	STACK_SUCCESS = 0,
	STACK_ERROR,
	STACK_MEM,
	STACK_UNDERFLOW,
	STACK_OVERFLOW
} STACK_ERR_CODE;

typedef enum STACK_FLAGS_enum {
	STACK_FIXED = 0x00,
	STACK_GROW = 0x01
} STACK_FLAGS;

typedef struct R_ISTACK_tag *R_ISTACK;

int ISTACK_Create(R_ISTACK * stack, int stack_len, int flags);

int ISTACK_Destroy(R_ISTACK * stack);

int ISTACK_Clear(R_ISTACK stack);

int ISTACK_Push(R_ISTACK stack, int value);

int ISTACK_PushNull(R_ISTACK stack);

int ISTACK_Pop(R_ISTACK stack, int *value);

int ISTACK_Grow(R_ISTACK stack);

} // End of namespace Saga

#endif				/* SAGA_STACK_MOD_H */

--- NEW FILE: sthread.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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.
 *
[...1081 lines suppressed...]
		}

		if (unhandled) {

			CON_Print(S_ERROR_PREFIX "%X: Unhandled opcode.\n",
			    thread->i_offset);
			thread->executing = 0;
		}

		if (thread->executing && debug_print) {
			SDEBUG_PrintInstr(thread);
		}

	}

	return R_SUCCESS;
}

} // End of namespace Saga


--- NEW FILE: sthread.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sthread.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Scripting module thread management component header file

 Notes: 
*/

#ifndef SAGA_STHREAD_H__
#define SAGA_STHREAD_H__

#include "sstack.h"

namespace Saga {

#define STHREAD_DEF_INSTR_COUNT 7

struct R_SEMAPHORE_tag {
	int hold_count;
};

struct R_SCRIPT_THREAD_tag {
	int executing;

	int sleep_time;
	int ep_num;	/* Entrypoint number */
	unsigned long ep_offset;	/* Entrypoint offset */
	unsigned long i_offset;	/* Instruction offset */

	R_SEMAPHORE sem;

	SSTACK stack;
};

R_SCRIPT_THREAD *STHREAD_Create(void);
int STHREAD_Destroy(R_SCRIPT_THREAD *thread);
int STHREAD_SetEntrypoint(R_SCRIPT_THREAD *thread, int ep_num);
int STHREAD_Execute(R_SCRIPT_THREAD *thread, int ep_num);
int STHREAD_Run(R_SCRIPT_THREAD *thread, int instr_limit, int msec);
unsigned long GetReadOffset(const uchar *read_p);
unsigned char *GetReadPtr(R_SCRIPT_THREAD *thread);
int SDEBUG_PrintInstr(R_SCRIPT_THREAD *thread);

}				// End of namespace Saga

#endif				/* SAGA_STHREAD_H__ */

--- NEW FILE: sys_fs.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sys_fs.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#include "reinherit.h"

namespace Saga {

int
SYSFS_GetFQFN(const char *f_dir, const char *f_name, char *buf, size_t buf_len)
{
	size_t f_dir_len;
	size_t f_name_len;
	char sep_buf[2] = { R_DIRECTORY_SEP };

	size_t i;

	if ((f_dir == NULL) || (f_name == NULL) || (buf == NULL)) {

		return R_FAILURE;
	}

	f_dir_len = strlen(f_dir);
	f_name_len = strlen(f_name);

	buf[0] = 0;

	strncat(buf, f_dir, buf_len);

#if R_DIRECTORY_SEP != '/'
	/* Convert frontslashes to backslashes */
	for (i = 0; i < f_dir_len; i++) {
		if (buf[i] == '/') {
			buf[i] = R_DIRECTORY_SEP;
		}
	}
#endif

	for (i = f_dir_len - 1; i > 0; i--) {

		/* Remove any trailing whitespace */
		if (isspace(buf[i])) {
			buf[i] = 0;
		} else {
			break;
		}
	}

	f_dir_len = strlen(buf);

	if (buf[f_dir_len - 1] != R_DIRECTORY_SEP) {

		/* Append a proper directory separator if req. */
		strncat(buf, sep_buf, buf_len);
	}

	strncat(buf, f_name, buf_len);

	return R_SUCCESS;
}

} // End of namespace Saga



--- NEW FILE: sys_interface.h ---
/****************************************************************************\
 ____      ___       _               _ _
|  _ \ ___|_ _|_ __ | |__   ___ _ __(_) |_
| |_) / _ \| || '_ \| '_ \ / _ \ '__| | __|
|  _ <  __/| || | | | | | |  __/ |  | | |_
|_| \_\___|___|_| |_|_| |_|\___|_|  |_|\__|

 ----------------------------------------------------------------------------
 Project:		ReInherit Engine
 Version:		.1a
 
 The ReInherit Engine is (C)2000-2001 by Daniel Balsom
 This code is subject to the terms and conditions of the General Public
 License (GPL).
 
 ----------------------------------------------------------------------------
 
 File:			sys_interface.h
 Revision:		$Revision: 1.1 $

 Description:	
 
	(Linux) System-specific interface data

 Notes: 
 
\****************************************************************************/
#ifndef REINHERIT_SYSINTERFACE_H
#define REINHERIT_SYSINTERFACE_H

namespace Saga {

#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned int

#define R_CFGFILE_NAME ".reinheritrc"

#define R_DIRECTORY_SEP '/'

#define R_STDOUT stdout
#define R_STDERR stderr

#define R_printf fprintf
#define R_vprintf vfprintf

} // End of namespace Saga

#endif				/* REINHERIT_SYSTYPES_H */

--- NEW FILE: sysgfx.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sysgfx.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#include "reinherit.h"

#include <SDL.h>
#include <limits.h>

/*
 * Begin module component
\*--------------------------------------------------------------------------*/
#include "sysgfx.h"

namespace Saga {

R_SYSGFX_MODULE SGfxModule;

static SDL_Color cur_pal[R_PAL_ENTRIES];

int SYSGFX_Init(R_SYSGFX_INIT * gfx_init)
{
	SDL_Surface *sdl_screen;
	R_SURFACE r_screen;

	SDL_Surface *sdl_back_buf;
	R_SURFACE r_back_buf;

	int result;
	Uint32 flags;

	assert(gfx_init != NULL);

	if (gfx_init->fullscreen) {
		flags = SDL_FULLSCREEN | SDL_HWPALETTE;
	} else {
		flags = SDL_HWPALETTE;
	}

	/* Test video mode availability
	 * \*------------------------------------------------------------- */
	result = SDL_VideoModeOK(gfx_init->screen_w,
	    gfx_init->screen_h, gfx_init->screen_bpp, flags);
	if (result == 0) {
		R_printf(R_STDERR,
		    "Requested video mode (%d x %d @ %d bpp) "
		    "is unavailable.\n",
		    gfx_init->screen_w,
		    gfx_init->screen_h, gfx_init->screen_bpp);

		return R_FAILURE;
	}

	/* Set the video mode
	 * \*------------------------------------------------------------- */
	sdl_screen = SDL_SetVideoMode(gfx_init->screen_w,
	    gfx_init->screen_h, gfx_init->screen_bpp, flags);
	if (sdl_screen == NULL) {

		R_printf(R_STDERR,
		    "Unable to set video mode (%d x %d @ %d bpp).\n",
		    gfx_init->screen_w,
		    gfx_init->screen_h, gfx_init->screen_bpp);

		R_printf(R_STDERR, "SDL reports: %s\n", SDL_GetError());

		return R_FAILURE;
	}

	R_printf(R_STDOUT,
	    "Set video mode: (%d x %d @ %d bpp)\n",
	    sdl_screen->w, sdl_screen->h, sdl_screen->format->BitsPerPixel);

	/* Convert sdl surface data to R surface data */
	r_screen.buf = (uchar *)sdl_screen->pixels;
	r_screen.buf_w = sdl_screen->w;
	r_screen.buf_h = sdl_screen->h;
	r_screen.buf_pitch = sdl_screen->pitch;
	r_screen.bpp = gfx_init->screen_bpp;

	r_screen.clip_rect.x1 = 0;
	r_screen.clip_rect.y1 = 0;
	r_screen.clip_rect.x2 = sdl_screen->w - 1;
	r_screen.clip_rect.y2 = sdl_screen->h - 1;

	r_screen.impl_src = sdl_screen;

	/* Create the back buffer 
	 * \*------------------------------------------------------------- */
	sdl_back_buf = SDL_CreateRGBSurface(SDL_SWSURFACE,
	    gfx_init->backbuf_w,
	    gfx_init->backbuf_h, gfx_init->backbuf_bpp, 0, 0, 0, 0);
	if (sdl_back_buf == NULL) {

		R_printf(R_STDERR,
		    "Unable to create back buffer (%d x %d @ %d bpp).\n",
		    gfx_init->backbuf_w,
		    gfx_init->backbuf_h, gfx_init->backbuf_bpp);

		R_printf(R_STDERR, "SDL reports: %s.\n", SDL_GetError());

		return R_FAILURE;
	}

	/* Convert sdl surface data to R surface data
	 * \*------------------------------------------------------------- */
	r_back_buf.buf = (uchar *)sdl_back_buf->pixels;
	r_back_buf.buf_w = sdl_back_buf->w;
	r_back_buf.buf_h = sdl_back_buf->h;
	r_back_buf.buf_pitch = sdl_back_buf->pitch;
	r_back_buf.bpp = gfx_init->backbuf_bpp;

	r_back_buf.clip_rect.x1 = 0;
	r_back_buf.clip_rect.y1 = 0;
	r_back_buf.clip_rect.x2 = sdl_back_buf->w - 1;
	r_back_buf.clip_rect.y2 = sdl_back_buf->h - 1;

	r_back_buf.impl_src = sdl_back_buf;

	/* Set module data
	 * \*------------------------------------------------------------- */
	SGfxModule.sdl_screen = sdl_screen;
	SGfxModule.r_screen = r_screen;
	SGfxModule.sdl_back_buf = sdl_back_buf;
	SGfxModule.r_back_buf = r_back_buf;

	SGfxModule.init = 1;

	return R_SUCCESS;
}

R_SURFACE *SYSGFX_GetScreenSurface(void)
{
	return &SGfxModule.r_screen;
}

R_SURFACE *SYSGFX_GetBackBuffer(void)
{
	return &SGfxModule.r_back_buf;
}

int SYSGFX_LockSurface(R_SURFACE * surface)
{
	int result;

	assert(surface != NULL);

	result = SDL_LockSurface((SDL_Surface *) surface->impl_src);

	return (result == 0) ? R_SUCCESS : R_FAILURE;
}

int SYSGFX_UnlockSurface(R_SURFACE * surface)
{
	assert(surface != NULL);

	SDL_UnlockSurface((SDL_Surface *) surface->impl_src);

	return R_SUCCESS;
}

R_SURFACE *SYSGFX_FormatToDisplay(R_SURFACE * surface)
{
	R_SURFACE *new_r_surface;
	SDL_Surface *new_sdl_surface;

	new_r_surface = (R_SURFACE *)malloc(sizeof *new_r_surface);
	if (new_r_surface == NULL) {
		return NULL;
	}

	new_sdl_surface = SDL_DisplayFormat((SDL_Surface *)surface->impl_src);
	if (new_sdl_surface == NULL) {
		free(new_r_surface);
		return NULL;
	}

	new_r_surface->buf = (uchar *)new_sdl_surface->pixels;
	new_r_surface->buf_w = new_sdl_surface->w;
	new_r_surface->buf_h = new_sdl_surface->h;
	new_r_surface->buf_pitch = new_sdl_surface->pitch;
	new_r_surface->bpp = new_sdl_surface->format->BitsPerPixel;

	new_r_surface->clip_rect.x1 = 0;
	new_r_surface->clip_rect.y1 = 0;
	new_r_surface->clip_rect.x2 = new_sdl_surface->w - 1;
	new_r_surface->clip_rect.y2 = new_sdl_surface->h - 1;

	new_r_surface->impl_src = new_sdl_surface;

	return new_r_surface;
}

R_SURFACE *SYSGFX_CreateSurface(int w, int h, int bpp)
{
	R_SURFACE *new_surface;
	SDL_Surface *new_sdl_surface;

	assert(bpp == 8);	/* 16bpp not supported, maybe not necessary? */
	assert((w > 0) && (h > 0));

	new_surface = (R_SURFACE *)malloc(sizeof *new_surface);
	if (new_surface == NULL) {
		return NULL;
	}

	new_sdl_surface =
	    SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, 0, 0, 0, 0);
	if (new_sdl_surface == NULL) {

		free(new_surface);
		return NULL;
	}

	new_surface->buf_w = new_sdl_surface->w;
	new_surface->buf_h = new_sdl_surface->h;
	new_surface->buf_pitch = new_sdl_surface->pitch;
	new_surface->bpp = new_sdl_surface->format->BitsPerPixel;

	new_surface->clip_rect.x1 = 0;
	new_surface->clip_rect.y1 = 0;
	new_surface->clip_rect.x2 = w - 1;
	new_surface->clip_rect.y2 = h - 1;

	new_surface->impl_src = new_sdl_surface;

	return new_surface;
}

int SYSGFX_DestroySurface(R_SURFACE * surface)
{
	SDL_FreeSurface((SDL_Surface *) surface->impl_src);

	free(surface);

	return R_SUCCESS;
}

int SYSGFX_GetWhite(void)
{
	return SGfxModule.white_index;
}

int SYSGFX_GetBlack(void)
{
	return SGfxModule.black_index;
}

int SYSGFX_MatchColor(unsigned long colormask)
{

	int i;

	int red = (colormask & 0x0FF0000UL) >> 16;
	int green = (colormask & 0x000FF00UL) >> 8;
	int blue = colormask & 0x00000FFUL;

	int dr;
	int dg;
	int db;

	long color_delta;
	long best_delta = LONG_MAX;
	int best_index = 0;

	for (i = 0; i < R_PAL_ENTRIES; i++) {

		dr = cur_pal[i].r - red;
		dr = ABS(dr);

		dg = cur_pal[i].g - green;
		dg = ABS(dg);

		db = cur_pal[i].b - blue;
		db = ABS(db);

#if R_COLORSEARCH_SQUARE
		color_delta = (long)((dr * dr) * R_RED_WEIGHT +
		    (dg * dg) * R_GREEN_WEIGHT + (db * db) * R_BLUE_WEIGHT);
#else
		color_delta = (long)(dr * R_RED_WEIGHT +
		    dg * R_GREEN_WEIGHT + db * R_BLUE_WEIGHT);
#endif
		if (color_delta == 0) {
			return i;
		}

		if (color_delta < best_delta) {
			best_delta = color_delta;
			best_index = i;
		}
	}

	return best_index;
}

int SYSGFX_SetPalette(R_SURFACE *surface, PALENTRY *pal)
{

	uchar red;
	uchar green;
	uchar blue;

	int color_delta;
	int best_wdelta = 0;
	int best_windex = 0;
	int best_bindex = 0;
	int best_bdelta = 1000;

	int i;

	for (i = 0; i < R_PAL_ENTRIES; i++) {

		red = pal[i].red;
		cur_pal[i].r = red;

		color_delta = red;

		green = pal[i].green;
		cur_pal[i].g = green;

		color_delta += green;

		blue = pal[i].blue;
		cur_pal[i].b = blue;

		color_delta += blue;

		if (color_delta < best_bdelta) {
			best_bindex = i;
			best_bdelta = color_delta;
		}

		if (color_delta > best_wdelta) {
			best_windex = i;
			best_wdelta = color_delta;
		}
	}

	/* Set whitest and blackest color indices */
	SGfxModule.white_index = best_windex;
	SGfxModule.black_index = best_bindex;

	/* If the screen surface is palettized, set the screen palette.
	 * If the screen surface is not palettized, set the palette of 
	 * the surface parameter */
	if (SGfxModule.r_screen.bpp < 16) {

		SDL_SetColors(SGfxModule.sdl_screen, cur_pal, 0,
		    R_PAL_ENTRIES);
	} else {

		SDL_SetColors((SDL_Surface *) surface->impl_src,
		    cur_pal, 0, R_PAL_ENTRIES);
	}

	return R_SUCCESS;
}

int SYSGFX_GetCurrentPal(PALENTRY * src_pal)
{

	int i;

	for (i = 0; i < R_PAL_ENTRIES; i++) {

		src_pal[i].red = cur_pal[i].r;
		src_pal[i].green = cur_pal[i].g;
		src_pal[i].blue = cur_pal[i].b;
	}

	return R_SUCCESS;
}

int SYSGFX_PalToBlack(R_SURFACE * surface, PALENTRY * src_pal, double percent)
{

	int i;

	/*int fade_max = 255; */
	int new_entry;

	double fpercent;

	if (percent > 1.0) {
		percent = 1.0;
	}

	/* Exponential fade */
	fpercent = percent * percent;

	fpercent = 1.0 - fpercent;

	/* Use the correct percentage change per frame for each palette entry */
	for (i = 0; i < R_PAL_ENTRIES; i++) {

		new_entry = (int)(src_pal[i].red * fpercent);

		if (new_entry < 0) {
			cur_pal[i].r = 0;
		} else {
			cur_pal[i].r = (uchar) new_entry;
		}

		new_entry = (int)(src_pal[i].green * fpercent);

		if (new_entry < 0) {
			cur_pal[i].g = 0;
		} else {
			cur_pal[i].g = (uchar) new_entry;
		}

		new_entry = (int)(src_pal[i].blue * fpercent);

		if (new_entry < 0) {
			cur_pal[i].b = 0;
		} else {
			cur_pal[i].b = (uchar) new_entry;
		}
	}

	/* If the screen surface is palettized, set the screen palette.
	 * If the screen surface is not palettized, set the palette of 
	 * the surface parameter */
	if (SGfxModule.r_screen.bpp < 16) {

		SDL_SetColors(SGfxModule.sdl_screen, cur_pal, 0,
		    R_PAL_ENTRIES);
	} else {

		SDL_SetColors((SDL_Surface *) surface->impl_src,
		    cur_pal, 0, R_PAL_ENTRIES);
	}

	return R_SUCCESS;

}

int SYSGFX_BlackToPal(R_SURFACE * surface, PALENTRY * src_pal, double percent)
{

	int new_entry;
	double fpercent;

	int color_delta;
	int best_wdelta = 0;
	int best_windex = 0;
	int best_bindex = 0;
	int best_bdelta = 1000;

	int i;

	if (percent > 1.0) {
		percent = 1.0;
	}

	/* Exponential fade */
	fpercent = percent * percent;

	fpercent = 1.0 - fpercent;

	/* Use the correct percentage change per frame for each palette entry */
	for (i = 0; i < R_PAL_ENTRIES; i++) {

		new_entry = (int)(src_pal[i].red - src_pal[i].red * fpercent);

		if (new_entry < 0) {
			cur_pal[i].r = 0;
		} else {
			cur_pal[i].r = (uchar) new_entry;
		}

		new_entry =
		    (int)(src_pal[i].green - src_pal[i].green * fpercent);

		if (new_entry < 0) {
			cur_pal[i].g = 0;
		} else {
			cur_pal[i].g = (uchar) new_entry;
		}

		new_entry =
		    (int)(src_pal[i].blue - src_pal[i].blue * fpercent);

		if (new_entry < 0) {
			cur_pal[i].b = 0;
		} else {
			cur_pal[i].b = (uchar) new_entry;
		}
	}

	/* Find the best white and black color indices again */
	if (percent >= 1.0) {

		for (i = 0; i < R_PAL_ENTRIES; i++) {

			color_delta = cur_pal[i].r;
			color_delta += cur_pal[i].g;
			color_delta += cur_pal[i].b;

			if (color_delta < best_bdelta) {
				best_bindex = i;
				best_bdelta = color_delta;
			}

			if (color_delta > best_wdelta) {
				best_windex = i;
				best_wdelta = color_delta;
			}
		}
	}

	/* If the screen surface is palettized, set the screen palette.
	 * If the screen surface is not palettized, set the palette of 
	 * the surface parameter */
	if (SGfxModule.r_screen.bpp < 16) {

		SDL_SetColors(SGfxModule.sdl_screen, cur_pal, 0,
		    R_PAL_ENTRIES);
	} else {

		SDL_SetColors((SDL_Surface *) surface->impl_src,
		    cur_pal, 0, R_PAL_ENTRIES);
	}

	return R_SUCCESS;
}

} // End of namespace Saga


--- NEW FILE: sysgfx.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sysgfx.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#ifndef SYSGFX_H_
#define SYSGFX_H_

namespace Saga {

#define R_COLORSEARCH_SQUARE 0

#define R_RED_WEIGHT 0.299
#define R_GREEN_WEIGHT 0.587
#define R_BLUE_WEIGHT 0.114

typedef struct R_SYSGFX_MODULE_tag {

	int init;

	SDL_Surface *sdl_screen;	/* Screen surface */
	R_SURFACE r_screen;

	SDL_Surface *sdl_back_buf;	/* Double buffer surface */
	R_SURFACE r_back_buf;

	int white_index;
	int black_index;

} R_SYSGFX_MODULE;

} // End of namespace Saga

#endif				/* SYSGFX_H_ */

--- NEW FILE: sysinput.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sysinput.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#include "reinherit.h"

#include <SDL.h>

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "actor_mod.h"
#include "console_mod.h"
#include "interface_mod.h"
#include "render_mod.h"
#include "scene_mod.h"
#include "script_mod.h"

namespace Saga {

/*
 * Begin module component
\*--------------------------------------------------------------------------*/

int SYSINPUT_Init(void)
{

	SDL_EnableUNICODE(1);
	SDL_EnableKeyRepeat(200, 30);

	return R_SUCCESS;
}

int SYSINPUT_ProcessInput(void)
{
	SDL_Event sdl_event;

	int mouse_x, mouse_y;
	R_POINT imouse_pt;

	SYSINPUT_GetMousePos(&mouse_x, &mouse_y);

	imouse_pt.x = mouse_x;
	imouse_pt.y = mouse_y;

	RENDER_ConvertMousePt(&imouse_pt);

	while (SDL_PollEvent(&sdl_event)) {

		int in_char;

		switch (sdl_event.type) {

		case SDL_KEYDOWN:

			if (CON_IsActive()) {

				in_char = sdl_event.key.keysym.sym;

				switch (sdl_event.key.keysym.sym) {

				case SDLK_BACKQUOTE:
					CON_Deactivate();
					break;

				case SDLK_PAGEUP:
					CON_PageUp();
					break;

				case SDLK_PAGEDOWN:
					CON_PageDown();
					break;

				case SDLK_UP:
				case SDLK_KP8:
					CON_CmdUp();
					break;

				case SDLK_DOWN:
				case SDLK_KP2:
					CON_CmdDown();
					break;

				default:

					if ((sdl_event.key.keysym.
						unicode & 0xFF80) == 0) {

						in_char =
						    sdl_event.key.keysym.
						    unicode & 0x7F;
						if (in_char) {
							CON_Type(in_char);
						}
					} else {
						R_printf(R_STDOUT,
						    "Ignored UNICODE character.\n");
					}

					break;
				}

				break;
			}

			switch (sdl_event.key.keysym.sym) {

			case SDLK_BACKQUOTE:
				CON_Activate();
				break;

			case SDLK_q:
				R_printf(R_STDOUT, "Quit key pressed.\n");
				/*goto done; */
				break;

			case SDLK_r:
				INTERFACE_Draw();
				break;

			case SDLK_F1:
				RENDER_ToggleFlag(RF_SHOW_FPS);
				break;

			case SDLK_F2:
				RENDER_ToggleFlag(RF_PALETTE_TEST);
				break;

			case SDLK_F3:
				RENDER_ToggleFlag(RF_TEXT_TEST);
				break;

			case SDLK_F4:
				RENDER_ToggleFlag(RF_OBJECTMAP_TEST);
				break;

			case SDLK_1:
				RENDER_SetMode(RM_NORMAL);
				break;

			case SDLK_4:
				RENDER_SetMode(RM_2XSAI);
				break;

			case SDLK_5:
				RENDER_SetMode(RM_SUPER2XSAI);
				break;

			case SDLK_6:
				RENDER_SetMode(RM_SUPEREAGLE);
				break;

			case SDLK_TAB:
				STHREAD_DebugStep();
				break;

				/* Actual game keys */

			case SDLK_SPACE:

				ACTOR_SkipDialogue();
				break;

			case SDLK_PAUSE:
			case SDLK_p:
				RENDER_ToggleFlag(RF_RENDERPAUSE);
				break;

			case SDLK_ESCAPE:
				/* Skip to next scene skip target */
				SCENE_Skip();
				break;

			default:
				break;
			}

			break;

		case SDL_KEYUP:
			break;

		case SDL_MOUSEBUTTONDOWN:
			INTERFACE_Update(&imouse_pt, UPDATE_MOUSECLICK);
			break;

		default:
			break;
		}
	}

	return R_SUCCESS;
}

int SYSINPUT_GetMousePos(int *mouse_x, int *mouse_y)
{

	SDL_GetMouseState(mouse_x, mouse_y);

	return R_SUCCESS;
}

int SYSINPUT_HideMouse(void)
{

	SDL_ShowCursor(SDL_DISABLE);

	return R_SUCCESS;
}

int SYSINPUT_ShowMouse(void)
{

	SDL_ShowCursor(SDL_ENABLE);

	return R_SUCCESS;
}

} // End of namespace Saga


--- NEW FILE: sysio.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sysio.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */

#include "reinherit.h"

#include "SDL.h"

namespace Saga {

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/

/*
 * Begin module component
\*--------------------------------------------------------------------------*/

int SYSIO_Init(void)
{

	int result;

	/* Initialize SDL library */
	result = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO);

	if (result != 0) {

		R_printf(R_STDERR, "SDL library initialization failed.\n");

		return R_FAILURE;
	}

	R_printf(R_STDOUT, "SDL library initialized.\n");

	return R_SUCCESS;
}

int SYSIO_Shutdown(void)
{

	return R_SUCCESS;
}

} // End of namespace Saga


--- NEW FILE: sysmusic.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/sysmusic.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#include "reinherit.h"

#include "yslib.h"

namespace Saga {

static int MusicInitialized = 0;

int SYSMUSIC_Init(int enabled)
{
	YS_IGNORE_PARAM(enabled);

	if (MusicInitialized) {
		return R_FAILURE;
	}

	MusicInitialized = 1;
	return R_SUCCESS;
}

int SYSMUSIC_Shutdown(void)
{
	if (!MusicInitialized) {
		return R_FAILURE;
	}

	MusicInitialized = 0;
	return R_SUCCESS;
}

int SYSMUSIC_Play(ulong music_rn, uint flags)
{
	if (!MusicInitialized) {
		return R_FAILURE;
	}

	YS_IGNORE_PARAM(music_rn);
	YS_IGNORE_PARAM(flags);

	return R_SUCCESS;

}

int SYSMUSIC_Pause(void)
{
	if (!MusicInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;

}

int SYSMUSIC_Resume(void)
{
	if (!MusicInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;

}

int SYSMUSIC_Stop(void)
{

	if (!MusicInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;

}

} // End of namespace Saga


--- NEW FILE: syssound.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/syssound.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "game_mod.h"
#include "rscfile_mod.h"

namespace Saga {

/*
 * Begin module component
\*--------------------------------------------------------------------------*/

static int SoundInitialized = 0;

static R_RSCFILE_CONTEXT *SoundContext;
static R_RSCFILE_CONTEXT *VoiceContext;

int SYSSOUND_Init(int enabled)
{

	int result;

	YS_IGNORE_PARAM(enabled);

	if (SoundInitialized) {
		return R_FAILURE;
	}

	/* Load sound module resource file contexts
	 * \*------------------------------------------------------------- */
	result = GAME_GetFileContext(&SoundContext, R_GAME_SOUNDFILE, 0);
	if (result != R_SUCCESS) {
		return R_FAILURE;
	}

	result = GAME_GetFileContext(&VoiceContext, R_GAME_VOICEFILE, 0);
	if (result != R_SUCCESS) {
		return R_FAILURE;
	}

	SoundInitialized = 1;
	return R_SUCCESS;
}

int SYSSOUND_Shutdown()
{
	if (!SoundInitialized) {
		return R_FAILURE;
	}

	SoundInitialized = 0;

	return R_SUCCESS;
}

int SYSSOUND_Play(int sound_rn, int channel)
{

	(void)sound_rn;
	(void)channel;

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSSOUND_Pause(int channel)
{

	(void)channel;

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSSOUND_Resume(int channel)
{

	(void)channel;

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSSOUND_Stop(int channel)
{

	(void)channel;

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSSOUND_PlayVoice(R_SOUNDBUFFER * buf)
{

	(void)buf;

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSSOUND_PauseVoice(void)
{

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSSOUND_ResumeVoice(void)
{

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSSOUND_StopVoice(void)
{

	if (!SoundInitialized) {
		return R_FAILURE;
	}

	return R_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: systimer.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/systimer.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#include "reinherit.h"

#include <SDL.h>

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "systimer.h"

namespace Saga {

R_SYSTIMER_DATA R_TimerData;

int SYSTIMER_InitMSCounter(void)
{

	if (R_TimerData.initialized) {
		return R_FAILURE;
	}

	R_TimerData.t_previous_ticks = SDL_GetTicks();

	R_TimerData.initialized = 1;

	return R_SUCCESS;
}

unsigned long SYSTIMER_ReadMSCounter(void)
{

	Uint32 ms_elapsed = 0;

	if (!R_TimerData.initialized) {
		return 0;
	}

	R_TimerData.t_current_ticks = SDL_GetTicks();

	if (R_TimerData.t_current_ticks < R_TimerData.t_previous_ticks) {
		/* Timer has rolled over after 49 days... */
	} else {
		ms_elapsed = R_TimerData.t_current_ticks -
		    R_TimerData.t_previous_ticks;

		R_TimerData.t_previous_ticks = R_TimerData.t_current_ticks;
	}

	return ms_elapsed;
}

int SYSTIMER_ResetMSCounter(void)
{

	if (!R_TimerData.initialized) {
		return R_FAILURE;
	}

	R_TimerData.t_previous_ticks = SDL_GetTicks();

	return R_SUCCESS;
}

int SYSTIMER_Sleep(uint msec)
{
	SDL_Delay(msec);

	return R_SUCCESS;
}

int
SYSTIMER_CreateTimer(R_SYSTIMER ** timer,
    unsigned long interval, void *param, R_SYSTIMER_CALLBACK callback)
{
	R_SYSTIMER *new_timer = (R_SYSTIMER *)malloc(sizeof *new_timer);
	if (new_timer == NULL) {
		return R_MEM;
	}

	new_timer->t_interval = interval;
	new_timer->t_param = param;
	new_timer->t_callback_f = callback;

	*timer = new_timer;

	new_timer->t_sdl_timerid = SDL_AddTimer(interval,
	    SYSTIMER_Callback, new_timer);

	if (new_timer->t_sdl_timerid == NULL) {
		free(new_timer);
		*timer = NULL;

		return R_FAILURE;
	}

	return R_SUCCESS;
}

int SYSTIMER_DestroyTimer(R_SYSTIMER * timer)
{
	if (timer == NULL) {
		return R_FAILURE;
	}

	timer->t_running = 0;

	SDL_RemoveTimer(timer->t_sdl_timerid);

	free(timer);

	return R_SUCCESS;
}

Uint32 SYSTIMER_Callback(Uint32 interval, void *param)
{
	R_SYSTIMER *timer_p = (R_SYSTIMER *)param;

	timer_p->t_callback_f(timer_p->t_interval, timer_p->t_param);

	return timer_p->t_interval;
}

} // End of namespace Saga

--- NEW FILE: systimer.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/systimer.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
#ifndef SAGA_SYSTIMER_H__
#define SAGA_SYSTIMER_H__

namespace Saga {

typedef struct R_SYSTIMER_DATA_tag {

	int initialized;

	Uint32 t_start_ticks;

	Uint32 t_current_ticks;
	Uint32 t_previous_ticks;

} R_SYSTIMER_DATA;

struct R_SYSTIMER_tag {

	int t_running;

	unsigned long t_interval;
	void *t_param;

	R_SYSTIMER_CALLBACK t_callback_f;
	SDL_TimerID t_sdl_timerid;
};

Uint32         SYSTIMER_Callback(Uint32 interval, void *param);

} // End of namespace Saga

#endif				/* SAGA_SYSTIMER_H__ */

--- NEW FILE: text.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/text.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:   
 
    Text / dialogue display management module

 Notes: 
*/

#include "reinherit.h"

#include "yslib.h"

/*
 * Uses the following modules:
\*--------------------------------------------------------------------------*/
#include "font_mod.h"

/*
 * Begin module
\*--------------------------------------------------------------------------*/
#include "text_mod.h"
#include "text.h"

namespace Saga {

int
TEXT_Draw(int font_id,
    R_SURFACE * ds,
    const char *string,
    int text_x, int text_y, int color, int effect_color, int flags)
{

	int string_w;
	int string_len;

	int fit_w;

	const char *start_p;
	const char *search_p;
	const char *measure_p;
	const char *found_p;
	int len;
	int w;
	const char *end_p;
	int h;
	int wc;

	int w_total;
	int len_total;

	string_len = strlen(string);

	if (flags & FONT_CENTERED) {

		/* Text is centered... format output */

		/* Enforce minimum and maximum center points for centered text */
		if (text_x < R_TEXT_CENTERLIMIT) {
			text_x = R_TEXT_CENTERLIMIT;
		}

		if (text_x > ds->buf_w - R_TEXT_CENTERLIMIT) {
			text_x = ds->buf_w - R_TEXT_CENTERLIMIT;
		}

		if (text_x < (R_TEXT_MARGIN * 2)) {
			/* Text can't be centered if it's too close to the margin */
			return R_FAILURE;
		}

		string_w =
		    FONT_GetStringWidth(font_id, string, string_len, flags);

		if (text_x < (ds->buf_w / 2)) {
			/* Fit to right side */
			fit_w = (text_x - R_TEXT_MARGIN) * 2;
		} else {
			/* Fit to left side */
			fit_w = ((ds->buf_w - R_TEXT_MARGIN) - text_x) * 2;
		}

		if (fit_w >= string_w) {

			/* Entire string fits, draw it */
			text_x = text_x - (string_w / 2);

			FONT_Draw(font_id,
			    ds,
			    string,
			    string_len,
			    text_x, text_y, color, effect_color, flags);

			return R_SUCCESS;
		}

		/* String won't fit on one line ... */

		h = FONT_GetHeight(font_id);
		w_total = 0;
		len_total = 0;
		wc = 0;

		start_p = string;
		measure_p = string;
		search_p = string;
		end_p = string + string_len;

		for (;;) {

			found_p = strchr(search_p, ' ');

			if (found_p == NULL) {
				/* Ran to the end of the buffer */
				len = end_p - measure_p;
			} else {
				len = found_p - measure_p;
			}

			w = FONT_GetStringWidth(font_id, measure_p, len,
			    flags);
			measure_p = found_p;

			if ((w_total + w) > fit_w) {
				/* This word won't fit */
				if (wc == 0) {
					/* The first word in the line didn't fit. abort */
					return R_SUCCESS;
				}

				/* Wrap what we've got and restart */
				FONT_Draw(font_id,
				    ds,
				    start_p,
				    len_total,
				    text_x - (w_total / 2),
				    text_y, color, effect_color, flags);

				text_y += h + R_TEXT_LINESPACING;
				w_total = 0;
				len_total = 0;
				wc = 0;
				measure_p = search_p;
				start_p = search_p;

			} else {
				/* Word will fit ok */
				w_total += w;
				len_total += len;
				wc++;

				if (found_p == NULL) {
					/* Since word hit NULL but fit, we are done */
					FONT_Draw(font_id,
					    ds,
					    start_p,
					    len_total,
					    text_x - (w_total / 2),
					    text_y,
					    color, effect_color, flags);

					return R_SUCCESS;
				}

				search_p = measure_p + 1;
			}
		}		/* End for (;;) */

	} else {

		/* Text is not centered; No formatting required */

		FONT_Draw(font_id,
		    ds,
		    string,
		    string_len, text_x, text_y, color, effect_color, flags);

	}

	return R_SUCCESS;
}

R_TEXTLIST *TEXT_CreateList(void)
{
	R_TEXTLIST *new_textlist;

	new_textlist = (R_TEXTLIST *)malloc(sizeof *new_textlist);

	if (new_textlist == NULL) {
		return NULL;
	}

	new_textlist->list = ys_dll_create();

	if (new_textlist->list == NULL) {
		free(new_textlist);
		return NULL;
	}

	return new_textlist;
}

void TEXT_ClearList(R_TEXTLIST * tlist)
{
	if (tlist != NULL) {
		ys_dll_delete_all(tlist->list);
	}

	return;
}

void TEXT_DestroyList(R_TEXTLIST * tlist)
{
	if (tlist != NULL) {
		ys_dll_destroy(tlist->list);
	}
	free(tlist);

	return;
}

int TEXT_DrawList(R_TEXTLIST * textlist, R_SURFACE * ds)
{

	R_TEXTLIST_ENTRY *entry_p;
	YS_DL_NODE *walk_p;

	assert((textlist != NULL) && (ds != NULL));

	for (walk_p = ys_dll_head(textlist->list);
	    walk_p != NULL; walk_p = ys_dll_next(walk_p)) {

		entry_p = (R_TEXTLIST_ENTRY *)ys_dll_get_data(walk_p);

		if (entry_p->display != 0) {

			TEXT_Draw(entry_p->font_id,
			    ds,
			    entry_p->string,
			    entry_p->text_x,
			    entry_p->text_y,
			    entry_p->color,
			    entry_p->effect_color, entry_p->flags);
		}
	}

	return R_SUCCESS;
}

int TEXT_ProcessList(R_TEXTLIST * textlist, long ms)
{
	R_TEXTLIST_ENTRY *entry_p;
	YS_DL_NODE *walk_p;
	YS_DL_NODE *temp_p;

	for (walk_p = ys_dll_head(textlist->list);
	    walk_p != NULL; walk_p = temp_p) {

		temp_p = ys_dll_next(walk_p);

		entry_p = (R_TEXTLIST_ENTRY *)ys_dll_get_data(walk_p);

		if (entry_p->flags & TEXT_TIMEOUT) {

			entry_p->time -= ms;
			if (entry_p->time <= 0) {

				ys_dll_delete(walk_p);
			}
		}
	}

	return R_SUCCESS;

}

R_TEXTLIST_ENTRY *TEXT_AddEntry(R_TEXTLIST * textlist,
    R_TEXTLIST_ENTRY * entry)
{
	YS_DL_NODE *new_node = NULL;

	if (entry != NULL) {
		new_node =
		    ys_dll_add_tail(textlist->list, entry, sizeof *entry);
	}

	return (new_node != NULL) ? (R_TEXTLIST_ENTRY *)new_node->data : NULL;
}

int TEXT_SetDisplay(R_TEXTLIST_ENTRY * entry, int val)
{
	if (entry != NULL) {
		entry->display = !!val;
		return R_SUCCESS;
	}

	return R_FAILURE;
}

int TEXT_DeleteEntry(R_TEXTLIST * textlist, R_TEXTLIST_ENTRY * entry)
{
	YS_DL_NODE *walk_p;

	if (entry == NULL) {
		return R_FAILURE;
	}

	for (walk_p = ys_dll_head(textlist->list);
	    walk_p != NULL; walk_p = ys_dll_next(walk_p)) {

		if (entry == ys_dll_get_data(walk_p)) {
			ys_dll_delete(walk_p);
			break;
		}
	}

	return R_SUCCESS;
}

} // End of namespace Saga


--- NEW FILE: text.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/text.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*

 Description:   
 
    Text / dialogue display management module private header

 Notes: 
*/

#ifndef SAGA_TEXT_H__
#define SAGA_TEXT_H__

namespace Saga {

#define R_TEXT_CENTERLIMIT 50
#define R_TEXT_MARGIN 10
#define R_TEXT_LINESPACING 2

struct R_TEXTLIST_tag {
	YS_DL_LIST *list;
};

}				// End of namespace Saga
#endif				/* SAGA_TEXT_H__ */

--- NEW FILE: text_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/text_mod.h,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:   
 
    Text / dialogue display management module public header

 Notes: 
*/

#ifndef SAGA_TEXT_MOD_H_
#define SAGA_TEXT_MOD_H_

namespace Saga {

enum R_TEXT_FLAGS {
	TEXT_TIMEOUT = 0x01
};

typedef struct R_TEXTLIST_ENTRY_tag {
	struct R_TEXTLIST_ENTRY_tag *next;
	struct R_TEXTLIST_ENTRY_tag *prev;
	int display;
	int id;
	int text_x;
	int text_y;
	int color;
	int effect_color;
	int flags;
	int font_id;
	long time;
	char *string;
} R_TEXTLIST_ENTRY;

typedef struct R_TEXTLIST_tag R_TEXTLIST;

R_TEXTLIST *TEXT_CreateList(void);
void TEXT_DestroyList(R_TEXTLIST *textlist);
void TEXT_ClearList(R_TEXTLIST *textlist);
int TEXT_DrawList(R_TEXTLIST *textlist, R_SURFACE *ds);
R_TEXTLIST_ENTRY *TEXT_AddEntry(R_TEXTLIST *textlist, R_TEXTLIST_ENTRY *entry);
int TEXT_DeleteEntry(R_TEXTLIST *textlist, R_TEXTLIST_ENTRY *entry);
int TEXT_SetDisplay(R_TEXTLIST_ENTRY *entry, int val);
int TEXT_Draw(int font_id, R_SURFACE *ds, const char *string, int text_x, 
			  int text_y, int color, int effect_color, int flags);
int TEXT_ProcessList(R_TEXTLIST *textlist, long ms);

}				// End of namespace Saga

#endif				/* SAGA_TEXT_MOD_H_ */

--- NEW FILE: transitions.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/transitions.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:	
 
	Background transition routines

 Notes: 
*/

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

#include "yslib.h"

#include "reinherit.h"

namespace Saga {

int
TRANSITION_Dissolve(uchar * dst_img,
    int dst_w,
    int dst_h,
    int dst_p, const uchar * src_img, int src_p, int flags, double percent)
{
#define XOR_MASK 0xB400;

	int pixelcount = dst_w * dst_h;
	int seqlimit = (int)(65535 * percent);

	int seq = 1;
	int i;

	YS_IGNORE_PARAM(flags);
	YS_IGNORE_PARAM(src_p);
	YS_IGNORE_PARAM(dst_p);

	for (i = 0; i < seqlimit; i++) {

		if (seq & 1) {
			seq = (seq >> 1) ^ XOR_MASK;
		} else {
			seq = seq >> 1;
		}

		if (seq == 1) {
			return 0;
		}

		if (seq >= pixelcount) {
			continue;
		} else {

			dst_img[seq] = src_img[seq];

		}
	}

	return 1;
}

} // End of namespace Saga


--- NEW FILE: x86_32.h ---
/****************************************************************************\
 ____      ___       _               _ _
|  _ \ ___|_ _|_ __ | |__   ___ _ __(_) |_
| |_) / _ \| || '_ \| '_ \ / _ \ '__| | __|
|  _ <  __/| || | | | | | |  __/ |  | | |_
|_| \_\___|___|_| |_|_| |_|\___|_|  |_|\__|

 ----------------------------------------------------------------------------
 Project:		ReInherit Engine
 Version:		.1a
 
 The ReInherit Engine is (C)2000-2001 by Daniel Balsom
 This code is subject to the terms and conditions of the General Public
 License (GPL).
 
 ----------------------------------------------------------------------------
 
 File:			x86-32.h
 Revision:		$Revision: 1.1 $

 Description:	
 
	Architecture-specific typedefs for Intel(tm) compatible 32 bit processors

 Notes: 

\****************************************************************************/
#ifndef R_ARCH_H
#define R_ARCH_H

namespace Saga {

#define R_LITTLE_ENDIAN

typedef unsigned int R_UINT32;
typedef signed int R_SINT32;

typedef unsigned short R_UINT16;
typedef signed short R_SINT16;

typedef unsigned char R_UINT8;
typedef signed char R_SINT8;

} // End of namespace Saga

#endif				/* R_ARCH_H */

--- NEW FILE: xmidi.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/xmidi.cpp,v 1.1 2004/04/12 21:40:48 sev Exp $
 *
 */
/*
 Description:   
 
    XMIDI conversion routines

 Notes: 
 
    Code adapted from XMILoader by Keet ( fox at foxpaws.net ), (C)2000
*/

#include "reinherit.h"

#include "yslib.h"

/* Begin module component
\*--------------------------------------------------------------------------*/
#include "xmidi_mod.h"
#include "xmidi.h"

namespace Saga {

int
ConvertEventListToSMF(XMIDIEVENT_LIST * event_list,
    uchar ** smf_ptr, size_t * smf_len)
/*--------------------------------------------------------------------------*\
 * Given a pointer to an event list structure, this function creates and 
 * returns a pointer to a Standard Midi File (SMF) image and the image's
 * length in bytes.
\*--------------------------------------------------------------------------*/
{
	YS_IGNORE_PARAM(event_list);
	YS_IGNORE_PARAM(smf_ptr);
	YS_IGNORE_PARAM(smf_len);

#if 0
	SMF_HEADER_CHUNK smfh;
	SMF_TRACK_CHUNK smft;

	XMIDIEVENT *event_p;

	uchar *write_p = NULL;
	uchar *smf_buf = NULL;

	size_t alloc_size;

	int vlq_len;

	if ((smf_ptr == NULL) || (smf_len == NULL)) {

		return R_FAILURE;
	}

	/* Allocate memory for SMF image
	 * \*---------------------------------------------------------------------- */
	alloc_size = event_list->smf_size + MIDI_HEADER_LEN +
	    MIDI_TRACK_CHUNK_LEN;

	/* SMF requires an even size */
	if (alloc_size % 2) {
		alloc_size++;
	}

	smf_buf = malloc(alloc_size);
	if (smf_buf == NULL) {
		R_printf(R_STDERR, "Memory allocation error.\n");

		return R_FAILURE;
	}

	memset(smf_ptr, 0, alloc_size);

	/* Write header chunk
	 * \*---------------------------------------------------------------------- */
	write_p = smf_buf;

	smfh.smf_header_len = MIDI_HEADER_CHUNK_LEN;
	smfh.smf_format = 0;
	smfh.smf_ntracks = 1;
	smfh.time_division.ppqn = XMIDI_TIMEDIV;

	memcpy(write_p, MIDI_HEADER_TAG, 4);
	write_p += 4;

	ys_write_u32_be(smfh.smf_header_len, write_p, &write_p);
	ys_write_u16_be(smfh.smf_format, write_p, &write_p);
	ys_write_u16_be(smfh.smf_ntracks, write_p, &write_p);
	ys_write_u16_be(smfh.time_division.ppqn, write_p, &write_p);

	/* Write track chunk
	 * \*---------------------------------------------------------------------- */
	memcpy(write_p, MIDI_TRACK_TAG, 4);
	write_p += 4;

	smft.smf_track_len = event_list->smf_size;

	ys_write_u32_be(smft.smf_track_len, write_p, &write_p);

	/* Write MIDI events
	 * \*---------------------------------------------------------------------- */
	event_p = event_list->head;

	while (event_p != NULL) {

		vlq_len = WriteVLQ_DW(write_p, event_p->delta_time);
		write_p += vlq_len;

		/*
		 * R_printf( R_STDOUT, 
		 * "Wrote %d len VLQ. (%d)\n",
		 * vlq_len,
		 * event_p->delta_time );
		 */

		switch (event_p->event) {

		case MIDI_NOTE_ON:
		case MIDI_NOTE_OFF:
		case MIDI_AFTERTOUCH:
		case MIDI_CONTROLCHANGE:
		case MIDI_PITCHWHEEL:

			*write_p++ =
			    (uchar) (event_p->event | (uchar) event_p->
			    channel);
			*write_p++ = event_p->op1;
			*write_p++ = event_p->op2;
			break;

		case MIDI_PROGRAMCHANGE:
		case MIDI_CHANNELPRESSURE:

			*write_p =
			    (uchar) (event_p->event | (uchar) event_p->
			    channel);
			*write_p = event_p->op1;
			break;

		case MIDI_SYSTEMEXCLUSIVE:

			*write_p = (uchar) MIDI_NONMIDI;

			switch (event_p->sysex_op) {

			case MIDI_SYSEX_TRACKEND:

				*write_p++ = event_p->sysex_op;
				*write_p++ = (uchar) 0;
				break;

			case MIDI_SYSEX_TEMPO:

				*write_p++ = event_p->sysex_op;
				*write_p++ = (uchar) 3;
				/*
				 *write_p++ = event_p->op1;
				 *write_p++ = event_p->op2;
				 *write_p++ = event_p->op3;
				 */

				/* Override tempo change */
				*write_p++ = (uchar) 0x07;
				*write_p++ = (uchar) 0xA1;
				*write_p++ = (uchar) 0x20;
				break;

			case MIDI_SYSEX_TIMESIG:

				*write_p++ = event_p->sysex_op;
				*write_p++ = (uchar) 4;
				*write_p++ = event_p->op1;
				*write_p++ = event_p->op2;
				*write_p++ = event_p->op3;
				*write_p++ = event_p->op4;
				break;

			default:

				R_printf(R_STDERR,
				    "Error, invalid sysex event type (%d): "
				    "Aborting.\n", event_p->sysex_op);

				return R_FAILURE;
				break;

			}
			break;

		default:
			R_printf(R_STDERR,
			    "Invalid event code encountered; " "aborting.\n");

			return R_FAILURE;
			break;
		}

		event_p = event_p->next_event;
	}

	*smf_ptr = smf_buf;
	*smf_len = alloc_size;
#endif
	return R_SUCCESS;
}

int WriteVLQ_DW(char *write_ptr, DWORD value)
{

	int vlq_len = 1;
	DWORD pack = value & 0x7F;
	int x;

	while (value >>= 7) {
		pack <<= 8;
		pack |= ((value & 0x7F) | 0x80);
		vlq_len++;
	}
	for (x = 0; x < sizeof(DWORD); x++) {
		*write_ptr++ = ((char *)(&pack))[x];
	}

	return vlq_len;
}

int XMIDI_Read(const uchar * XMI_img, XMIDIEVENT_LIST * event_list)
{
	/* XMI header data */
	const uchar *XMIDI_data;
	uint n_tracks;

	/* XMIDI data */
	IFF_ID_CHUNK cat_chunk;
	IFF_ID_CHUNK id_chunk;	/* Present after categeory chunk */
	XMI_TIMB_CHUNK timbre_chunk;	/* Present after id chunk */
	XMI_EVENT_CHUNK event_chunk;

	const uchar *read_p;

	const uchar *event_data;
	size_t event_data_len;

	if (XMIDI_ReadXMIHeader(XMI_img, &XMIDI_data, &n_tracks) != R_SUCCESS) {

		return R_FAILURE;
	}

	read_p = XMIDI_data;

	/* Read category chunk
	 * \*------------------------------------------------------------- */
	ReadIFF_IDChunk(&cat_chunk, read_p, &read_p);

	if (memcmp(cat_chunk.id_4cc, IFF_CATEGORY_4CC, 4) != 0) {

		R_printf(R_STDERR, "Error: Category chunk not present.\n");
		Print4CC(cat_chunk.id_4cc);

		return R_FAILURE;
	}

	if (memcmp(cat_chunk.desc_4cc, XMIDI_DESC_4CC, 4) != 0) {

		R_printf(R_STDERR,
		    "Error: Incorrect category description field.\n");
		Print4CC(cat_chunk.desc_4cc);

		return R_FAILURE;
	}

	/* Read XMIDI ID Chunk
	 * \*------------------------------------------------------------- */
	ReadIFF_IDChunk(&id_chunk, read_p, &read_p);

	if (memcmp(id_chunk.id_4cc, IFF_FORMAT_4CC, 4) != 0) {

		R_printf(R_STDERR, "Error: ID chunk not present.\n");
		Print4CC(id_chunk.id_4cc);

		return R_FAILURE;
	}

	if (memcmp(id_chunk.desc_4cc, XMIDI_DESC_4CC, 4) != 0) {

		R_printf(R_STDERR,
		    "Error: XMID tag not present in ID chunk: "
		    "Not XMIDI data.\n");
		Print4CC(id_chunk.desc_4cc);

		return R_FAILURE;
	}

	/* Read XMIDI Timbre Chunk
	 * \*------------------------------------------------------------- */
	ys_read_4cc(timbre_chunk.id_4cc, read_p, &read_p);
	timbre_chunk.chunk_len = ys_read_u32_be(read_p, &read_p);

	if (memcmp(timbre_chunk.id_4cc, XMIDI_TIMBRE_4CC, 4) != 0) {

		R_printf(R_STDERR, "Error: Timbre chunk not present.\n");
		Print4CC(timbre_chunk.id_4cc);

		return R_FAILURE;
	}

	/* Read XMIDI Event Chunk
	 * \*------------------------------------------------------------- */
	read_p += timbre_chunk.chunk_len;

	ys_read_4cc(event_chunk.id_4cc, read_p, &read_p);
	event_chunk.chunk_len = ys_read_u32_be(read_p, &read_p);

	if (memcmp(event_chunk.id_4cc, XMIDI_EVENT_4CC, 4) != 0) {

		R_printf(R_STDERR, "Error: Event chunk not present.\n");
		Print4CC(event_chunk.id_4cc);

		return R_FAILURE;
	}

	/* Read XMIDI Event data
	 * \*------------------------------------------------------------- */
	event_data = read_p;
	event_data_len = event_chunk.chunk_len;

	R_printf(R_STDOUT,
	    "Converting %d bytes of event data:\n", event_data_len);

	XMIDI_ReadEvents(event_list, event_data, event_data_len, n_tracks);

	/* Process XMIDI Event data
	 * \*------------------------------------------------------------- */
	ProcessEventList(event_list);

	return R_SUCCESS;
}

int
ReadIFF_IDChunk(IFF_ID_CHUNK * chunk,
    const uchar * read_p, const uchar ** read_pp)
{
	const uchar *chunk_p = read_p;

	ys_read_4cc(chunk->id_4cc, chunk_p, &chunk_p);

	chunk->chunk_len = ys_read_u32_be(chunk_p, &chunk_p);

	ys_read_4cc(chunk->desc_4cc, chunk_p, &chunk_p);

	if (read_pp != NULL) {
		*read_pp = chunk_p;
	}

	return R_SUCCESS;
}

int Print4CC(char *fourcc)
{
	R_printf(R_STDERR,
	    "FourCC: %c%c%c%c (%X %X %X %X)\n",
	    fourcc[0], fourcc[1], fourcc[2], fourcc[3],
	    fourcc[0], fourcc[1], fourcc[2], fourcc[3]);

	return R_SUCCESS;
}

int
XMIDI_ReadXMIHeader(const uchar * XMI_img,
    const uchar ** XMIDI_data, uint * n_tracks)
{
	const uchar *read_p;

	IFF_ID_CHUNK id_chunk;
	XMI_INFO_CHUNK info_chunk;

	*n_tracks = 0;
	*XMIDI_data = NULL;

	/* Read ID chunk
	 * \*------------------------------------------------------------ */
	read_p = XMI_img;

	ys_read_4cc(id_chunk.id_4cc, read_p, &read_p);
	id_chunk.chunk_len = ys_read_u32_be(read_p, &read_p);
	ys_read_4cc(id_chunk.desc_4cc, read_p, &read_p);

	if (memcmp(id_chunk.id_4cc, IFF_FORMAT_4CC, 4) != 0) {
		R_printf(R_STDERR, "Error: ID chunk not present.\n");

		return R_FAILURE;
	}

	if (memcmp(id_chunk.desc_4cc, XMI_DESC_4CC, 4) != 0) {
		R_printf(R_STDERR,
		    "Error: XDIR tag not present in ID chunk.\n");

		return R_FAILURE;
	}

	/* Read INFO chunk
	 * \*------------------------------------------------------------ */
	ys_read_4cc(info_chunk.id_4cc, read_p, &read_p);
	info_chunk.chunk_len = ys_read_u32_be(read_p, &read_p);
	info_chunk.n_tracks = ys_read_u16_le(read_p, &read_p);

	if (memcmp(info_chunk.id_4cc, XMI_INFO_4CC, 4) != 0) {

		R_printf(R_STDERR, "Error: INFO chunk not present.\n");

		return R_FAILURE;
	}

	*n_tracks = info_chunk.n_tracks;

	*XMIDI_data = XMI_img +
	    (id_chunk.chunk_len + IFF_ID_CHUNK_HEADERLEN - 4);

	return R_SUCCESS;
}

int
XMIDI_ReadEvents(XMIDIEVENT_LIST * event_list,
    const uchar * event_data, size_t event_data_len, uint n_tracks)
{

	const uchar *event_data_ptr = event_data;
	size_t event_bytes_left = event_data_len;

	ulong new_event_time = 0;
	ulong event_time = 0;
	ulong event_len;

	ulong vlq_len;
	uint data_byte;

	int channel;
	int event;

	/*int tempo = MIDI_STD_TEMPO; */

	unsigned int sysex_op;
	unsigned int op1;
	unsigned int op2;
	unsigned int op3;
	unsigned int op4;

	/* Set initial tempo */
	/*
	 * AddEventToList( event_list, MIDI_SYSEX_TEMPO_LEN + GetLengthAsVLQ( 0 ), 0, MIDI_SYSTEMEXCLUSIVE, 0, MIDI_SYSEX_TEMPO, 0, );
	 */

	while (event_bytes_left > 0) {

		vlq_len = ReadVLQ2_DW((char *)event_data_ptr,
							  (DWORD)event_bytes_left, (DWORD *)&new_event_time);

		event_time += new_event_time;
		event_data_ptr += vlq_len;
		event_bytes_left -= vlq_len;

		/*
		 * vlq_len = GetLengthAsVLQ( new_event_time );
		 * R_printf( R_STDOUT, "Count: %d len VLQ (%d)\n", vlq_len, new_event_time );
		 */

		data_byte = *event_data_ptr++;

		channel = data_byte & 0x0FU;
		event = data_byte & 0xF0U;

		switch (event) {

		case MIDI_NOTE_ON:

#ifdef XMIPLAY_VERBOSE
			R_printf(R_STDOUT, "MIDI_NOTE_ON event:\n");
#endif

			op1 = *(event_data_ptr++);
			op2 = *(event_data_ptr++);

			AddEventToList(event_list,
			    MIDI_NOTE_ON_LEN,
			    event_time, event, channel, 0, op1, op2, 0, 0);

			vlq_len =
			    ReadVLQ_DW((char *)event_data_ptr, (DWORD)event_bytes_left,
						   (DWORD *)&event_len);
			AddEventToList(event_list, MIDI_NOTE_OFF_LEN,
			    event_time + event_len, MIDI_NOTE_OFF, channel, 0,
			    op1, MIDI_STD_VELOCITY, 0, 0);

			event_data_ptr += (vlq_len);
			event_bytes_left -= (2 + vlq_len);
			break;

		case MIDI_AFTERTOUCH:
#ifdef XMIPLAY_VERBOSE
			R_printf(R_STDOUT, "MIDI_AFTERTOUCH event:\n");
#endif
			op1 = *(event_data_ptr++);
			op2 = *(event_data_ptr++);

			AddEventToList(event_list,
			    MIDI_AFTERTOUCH_LEN,
			    event_time, event, channel, 0, op1, op2, 0, 0);

			event_bytes_left -= 2;
			break;

		case MIDI_CONTROLCHANGE:
#ifdef XMIPLAY_VERBOSE
			R_printf(R_STDOUT, "MIDI_CONTROLCHANGE event:\n");
#endif
			op1 = *(event_data_ptr++);
			op2 = *(event_data_ptr++);

			AddEventToList(event_list,
			    MIDI_CONTROLCHANGE_LEN,
			    event_time, event, channel, 0, op1, op2, 0, 0);

			event_bytes_left -= 2;
			break;

		case MIDI_PITCHWHEEL:
#ifdef XMIPLAY_VERBOSE
			R_printf(R_STDOUT, "MIDI_PITCHWHEEL event:\n");
#endif
			op1 = *(event_data_ptr++);
			op2 = *(event_data_ptr++);

			AddEventToList(event_list,
			    MIDI_PITCHWHEEL_LEN,
			    event_time, event, channel, 0, op1, op2, 0, 0);

			event_bytes_left -= 2;
			break;

		case MIDI_PROGRAMCHANGE:
#ifdef XMIPLAY_VERBOSE
			R_printf(R_STDOUT, "MIDI_PROGRAMCHANGE event:\n");
#endif
			op1 = *(event_data_ptr++);
			AddEventToList(event_list, MIDI_PROGRAMCHANGE_LEN,
			    event_time, event, channel, 0, op1, 0, 0, 0);

			event_bytes_left--;
			break;

		case MIDI_CHANNELPRESSURE:
#ifdef XMIPLAY_VERBOSE
			R_printf(R_STDOUT, "MIDI_CHANNELPRESSURE event:\n");
#endif
			op1 = *(event_data_ptr++);
			AddEventToList(event_list, MIDI_CHANNELPRESSURE_LEN,
			    event_time, event, channel, 0, op1, 0, 0, 0);

			event_bytes_left--;
			break;

		case MIDI_SYSTEMEXCLUSIVE:

			sysex_op = (BYTE) * event_data_ptr++;
			event_bytes_left--;

			if (data_byte == MIDI_NONMIDI) {

				switch (sysex_op) {

				case MIDI_SYSEX_TRACKEND:
					R_printf(R_STDOUT,
					    "Track end encountered.\n");
					AddEventToList(event_list,
					    MIDI_SYSEX_TRACKEND_LEN,
					    event_time, event, channel,
					    sysex_op, op1, op2, 0, 0);
					event_bytes_left = 0;
					break;

				case MIDI_SYSEX_TEMPO:
					event_data_ptr++;	/*(skip length VLQ) (always 3) */

					op1 = (BYTE) * event_data_ptr++;
					op2 = (BYTE) * event_data_ptr++;
					op3 = (BYTE) * event_data_ptr++;
					AddEventToList(event_list,
					    MIDI_SYSEX_TEMPO_LEN, event_time,
					    event, channel, sysex_op, op1, op2,
					    op3, 0);
					/*
					 * R_printf( R_STDOUT, "Adding tempo change event. :%X %X %X\n", op1, op2, op3 );
					 */
					event_bytes_left -= 4;
					break;

				case MIDI_SYSEX_TIMESIG:
					event_data_ptr++;	/*(skip length VLQ) (always 4) */

					op1 = (BYTE) * event_data_ptr++;
					op2 = (BYTE) * event_data_ptr++;
					op3 = (BYTE) * event_data_ptr++;
					op4 = (BYTE) * event_data_ptr++;
					AddEventToList(event_list,
					    MIDI_SYSEX_TIMESIG_LEN, event_time,
					    event, channel, sysex_op, op1, op2,
					    op3, op4);

					/*
					 * R_printf( R_STDOUT, "Adding time signature event. :%X %X %X %X\n", op1, op2, op3, op4 );
					 */
					event_bytes_left -= 5;
					break;

				default:
					R_printf(R_STDERR,
					    "Unhandled sysex nonmidi event, aborting.\n");
					R_printf(R_STDERR, "%X %X %X %X",
					    *event_data_ptr,
					    *(event_data_ptr + 1),
					    *(event_data_ptr + 2),
					    *(event_data_ptr + 3));

					event_bytes_left = 0;
					break;

				}
			} else {
				R_printf(R_STDERR,
				    "Unhandled sysex event, aborting.\n");
				event_bytes_left = 0;
			}

			break;

		default:
			R_printf(R_STDERR,
			    "Invalid event code encountered; aborting.\n");
			event_bytes_left = 0;
			break;
		}

	}			/* end while ( event_bytes_left > 0 ) */

	return R_SUCCESS;
}

int GetLengthAsVLQ(DWORD data)
{

	int len = 1;

	while (data >>= 7)
		len++;
	return len;

}

DWORD ReadVLQ_DW(char *data, DWORD bytes_left, DWORD * value)
{
	BYTE byte;
	DWORD vlq_len = 0;
	*value = 0;

	do {
		if (bytes_left <= 0)
			return 0;
		byte = *data++;
		bytes_left--;
		vlq_len++;
		*value = (*value << 7) | (byte & 0x7F);
	} while (byte & 0x80);

	return vlq_len;
}

DWORD ReadVLQ2_DW(char *data, DWORD bytes_left, DWORD * value)
{

	BYTE byte;
	DWORD vlq_len = 0;
	*value = 0;

	while (!((byte = *data++) & 0x80)) {
		if (bytes_left <= 0)
			return 0;
		bytes_left--;
		vlq_len++;
		(*value) += byte;
	}

	return vlq_len;
}

int
AddEventToList(XMIDIEVENT_LIST * event_list, int smf_size, int time, int event,
    int channel, int sysex_op, int op1, int op2, int op3, int op4)
{

	XMIDIEVENT *new_event;
	XMIDIEVENT *search_ptr = event_list->tail;

	new_event = (XMIDIEVENT *)malloc(sizeof(XMIDIEVENT));

	if (new_event == NULL) {
		R_printf(R_STDERR,
		    "Error: Out of memory allocating XMIDI event list entry.");
		return -1;
	}

	new_event->next_event = NULL;
	new_event->prev_event = NULL;

	if (event_list->head == NULL) {
		/* Set up new list */
		event_list->head = new_event;
		event_list->tail = new_event;
	} else {
		/* List isn't empty */
		if ((unsigned int)time >= event_list->tail->delta_time) {

			/* If this is the most recent event, append */
			event_list->tail->next_event = new_event;
			new_event->prev_event = event_list->tail;
			event_list->tail = new_event;

		} else {
			/* Otherwise scan list backwards and insert in proper position */
			while (search_ptr != NULL) {

				if ((unsigned int)time >=
				    search_ptr->delta_time) {
					/* Insert entry */
					new_event->next_event =
					    search_ptr->next_event;
					new_event->prev_event = search_ptr;

					search_ptr->next_event->prev_event =
					    new_event;
					search_ptr->next_event = new_event;
					break;
				}
				search_ptr = search_ptr->prev_event;
			}
		}
	}

	new_event->smf_size = smf_size;
	new_event->delta_time = time;

	new_event->sysex_op = sysex_op;
	new_event->event = (BYTE) event;
	new_event->channel = (BYTE) channel;
	new_event->op1 = (BYTE) op1;
	new_event->op2 = (BYTE) op2;
	new_event->op3 = (BYTE) op3;
	new_event->op4 = (BYTE) op4;

#ifdef XMIPLAY_VERBOSE
	R_printf(R_STDOUT,
	    "Added event: Time: %d Tempo: %d Event: %d Chan: %d Op1: %d Op2: %d\n",
	    new_event->delta_time, new_event->tempo, new_event->event,
	    new_event->channel, new_event->op1, new_event->op2);
#endif
	return 0;
}

int ProcessEventList(XMIDIEVENT_LIST * event_list)
{
	XMIDIEVENT *convert_ptr = event_list->head;
	int last_time = 0;
	int delta = 0;

	while (convert_ptr != NULL) {

		delta = convert_ptr->delta_time - last_time;
		if (delta < 0)
			R_printf(R_STDERR,
			    "Error: Negative delta time found.");
		last_time = convert_ptr->delta_time;
		convert_ptr->delta_time = delta;

		/* Update smf size count */
		event_list->smf_size +=
		    (convert_ptr->smf_size + GetLengthAsVLQ(delta));
		convert_ptr = convert_ptr->next_event;
	}

	R_printf(R_STDOUT,
	    "ProcessEventList(): %d bytes of SMF data processed.\n",
	    event_list->smf_size);

	return 0;
}

int XMIDI_Free(XMIDIEVENT_LIST * event_list)
{

	XMIDIEVENT *free_ptr = event_list->head;
	XMIDIEVENT *temp_ptr;

	while (free_ptr != NULL) {
		temp_ptr = free_ptr->next_event;
		free(free_ptr);
		free_ptr = temp_ptr;
	}

	return 0;

}

} // End of namespace Saga


--- NEW FILE: xmidi.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/xmidi.h,v 1.1 2004/04/12 21:40:49 sev Exp $
 *
 */
/*
 Description:   
 
    XMIDI conversion routines

 Notes: 
 
    Code adapted from XMILoader by Keet ( fox at foxpaws.net ), (C)2000
*/

#ifndef SAGA_XMIDI_H_
#define SAGA_XMIDI_H_

namespace Saga {

#define XMIDI_TIMEDIV 0x3C

/* XMIDI/IFF 4CC codes
\*--------------------------------------------------------------------------*/
#define IFF_FORMAT_4CC   "FORM"
#define IFF_CATEGORY_4CC "CAT "

#define XMI_DESC_4CC     "XDIR"
#define XMI_INFO_4CC     "INFO"

#define XMIDI_DESC_4CC   "XMID"
#define XMIDI_TIMBRE_4CC "TIMB"
#define XMIDI_EVENT_4CC  "EVNT"

/* IFF/XMI Data structures
\*--------------------------------------------------------------------------*/

typedef struct IFF_ID_CHUNK_tag {
	char id_4cc[4];	/* 4cc */
	ulong chunk_len;	/* u32_be */
	char desc_4cc[4];	/* 4cc */
} IFF_ID_CHUNK;

#define IFF_ID_CHUNK_HEADERLEN 12

typedef struct XMI_INFO_CHUNK_tag {
	char id_4cc[4];	/* 4cc */
	ulong chunk_len;	/* u32_be */
	uint n_tracks;	/* u16_le */
} XMI_INFO_CHUNK;

typedef struct XMI_TIMB_CHUNK_tag {
	char id_4cc[4];	/* 4cc */
	ulong chunk_len;	/* u32_be */
} XMI_TIMB_CHUNK;

typedef struct XMI_EVENT_CHUNK_tag {
	char id_4cc[4];	/* 4cc */
	ulong chunk_len;	/* u32_be */
} XMI_EVENT_CHUNK;

typedef struct SMF_HEADER_CHUNK_tag {
	char smf_id[4];	/* u8 */
	unsigned int smf_header_len;	/* u32_be */
	unsigned short smf_format;	/* u16_be */
	unsigned short smf_ntracks;	/* u16_be */
	union {
		unsigned short ppqn;	/* u16_be */
		signed char smpte[2];
	} time_division;
} SMF_HEADER_CHUNK;

typedef struct SMF_TRACK_CHUNK_tag {
	char smf_track_id[4];
	unsigned int smf_track_len;
} SMF_TRACK_CHUNK;

#define MIDI_HEADER_LEN 14
#define MIDI_HEADER_CHUNK_LEN 6
#define MIDI_TRACK_CHUNK_LEN 8

#define MIDI_HEADER_TAG "MThd"
#define MIDI_TRACK_TAG  "MTrk"

int XMIDI_ReadXMIHeader(const uchar *XMI_img, const uchar **XMIDI_data, uint *n_tracks);
int ReadIFF_IDChunk(IFF_ID_CHUNK *chunk, const uchar *read_p, const uchar **read_pp);
int Print4CC(char *fourcc);
int XMIDI_ReadEvents(XMIDIEVENT_LIST *event_list, const uchar *event_data, 
					 size_t event_data_len, uint n_tracks);
int WriteVLQ_DW(char *write_ptr, DWORD value);
DWORD ReadVLQ_DW(char *data, DWORD bytes_left, DWORD *value);
DWORD ReadVLQ2_DW(char *data, DWORD bytes_left, DWORD *value);
int GetLengthAsVLQ(DWORD data);
int AddEventToList(XMIDIEVENT_LIST *event_list, int smf_size, int time,
	    int event, int channel, int sysex_op, int op1, int op2, int op3, int op4);
int ProcessEventList(XMIDIEVENT_LIST *event_list);
void PrintMidiOutError(unsigned long err);
}				// End of namespace Saga

#endif				/* SAGA_XMIDI_H_ */

--- NEW FILE: xmidi_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/xmidi_mod.h,v 1.1 2004/04/12 21:40:49 sev Exp $
 *
 */
/*
 Description:   
 
    XMIDI conversion routines - module header

 Notes: 
*/

#ifndef SAGA_XMIDI_MOD_H_
#define SAGA_XMIDI_MOD_H_

namespace Saga {

#define MIDI_STD_VELOCITY 0x7F
#define MIDI_STD_TEMPO    0x0007A120L	/* 500000 */

/* MIDI Events 
\*--------------------------------------------------------------------------*/
enum R_MIDI_EVENTS {
	MIDI_NOTE_ON = 0x90,
	MIDI_NOTE_OFF = 0x80,
	MIDI_AFTERTOUCH = 0xA0,
	MIDI_CONTROLCHANGE = 0xB0,
	MIDI_PROGRAMCHANGE = 0xC0,
	MIDI_CHANNELPRESSURE = 0xD0,
	MIDI_PITCHWHEEL = 0xE0,
	MIDI_SYSTEMEXCLUSIVE = 0xF0,

	MIDI_NONMIDI = 0xFF,

	MIDI_SYSEX_SEQNUM = 0x00,
	MIDI_SYSEX_TEXT = 0x01,
	MIDI_SYSEX_COPYRIGHT = 0x02,
	MIDI_SYSEX_SEQNAME = 0x03,
	MIDI_SYSEX_INSTRUMENT = 0x04,
	MIDI_SYSEX_LYRIC = 0x05,
	MIDI_SYSEX_MARKER = 0x06,
	MIDI_SYSEX_CUEPOINT = 0x07,

	MIDI_SYSEX_CHANNEL = 0x20,
	MIDI_SYSEX_PORTNUM = 0x21,
	MIDI_SYSEX_TRACKEND = 0x2F,
	MIDI_SYSEX_TEMPO = 0x51,
	MIDI_SYSEX_TIMESIG = 0x58,

	MIDI_SYSEX_PROPRIETARY = 0x7F
};

enum MIDI_EVENT_LENGTHS {
	MIDI_NOTE_ON_LEN = 3,
	MIDI_NOTE_OFF_LEN = 3,
	MIDI_AFTERTOUCH_LEN = 3,
	MIDI_CONTROLCHANGE_LEN = 3,
	MIDI_PITCHWHEEL_LEN = 3,

	MIDI_PROGRAMCHANGE_LEN = 2,
	MIDI_CHANNELPRESSURE_LEN = 2,

	MIDI_SYSEX_TRACKEND_LEN = 3,
	MIDI_SYSEX_TEMPO_LEN = 6,
	MIDI_SYSEX_TIMESIG_LEN = 7
};

typedef struct XMIDIEVENT_tag {
	struct XMIDIEVENT_tag *prev_event;
	struct XMIDIEVENT_tag *next_event;

	size_t smf_size;	/* Size of event in SMF format */

	ulong delta_time;

	uchar event;
	uchar channel;
	uchar sysex_op;
	uchar op1;
	uchar op2;
	uchar op3;
	uchar op4;
	uchar pad;
} XMIDIEVENT;

typedef struct XMIDIEVENT_LIST_tag {
	XMIDIEVENT *head;
	XMIDIEVENT *tail;
	int smf_size;
} XMIDIEVENT_LIST;

int XMIDI_Read(const uchar *XMI_img, XMIDIEVENT_LIST *event_list);
int XMIDI_Free(XMIDIEVENT_LIST *event_list);

}				// End of namespace Saga

#endif				/* SAGA_XMIDI_MOD_H_ */

--- NEW FILE: ys_binread.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ys_binread.cpp,v 1.1 2004/04/12 21:40:49 sev Exp $
 *
 */
#include <stdio.h>
#include "yslib.h"

namespace Saga {

void
ys_read_4cc(char *fourcc,
    const unsigned char *data_p, const unsigned char **data_pp)
{
	fourcc[0] = (char)data_p[0];
	fourcc[1] = (char)data_p[1];
	fourcc[2] = (char)data_p[2];
	fourcc[3] = (char)data_p[3];

	if (data_pp) {

		*data_pp = data_p + 4;
	}

	return;
}

unsigned int
ys_read_u8(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads an unsigned 8 bit integer in from the array of bytes pointed to by
 *  'data_p'. If 'data_pp' is not null, it will set '*data_pp' to point past
 *  the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned int u8 = *data_p;

	if (data_pp != NULL) {
		*data_pp = data_p + 1;
	}

	return u8;
}

int ys_read_s8(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads a signed 8 bit integer in two's complement notation from the array
 *  of bytes pointed to by 'data_p'. If 'data_pp' is not null, it will set
 * '*data_pp' to point past the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned int u8 = *data_p;
	int s8;

#ifndef YS_ASSUME_2S_COMP
	if (u8 & 0x80U) {
		s8 = (int)(u8 - 0x80U) - 0x7F - 1;
	} else
#endif
		s8 = u8;

	if (data_pp != NULL) {
		*data_pp = data_p + 1;
	}

	return s8;
}

unsigned int
ys_read_u16_be(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads an unsigned 16 bit integer in big-endian format from the array of 
 * bytes pointed to by 'data_p'. If 'data_pp' is not null, it will set   
 * '*data_pp' to point past the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned int u16_be = ((unsigned int)data_p[0] << 8) | data_p[1];

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 2);
	}

	return u16_be;
}

unsigned int
ys_read_u16_le(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads an unsigned 16 bit integer in little-endian format from the array of 
 * bytes pointed to by 'data_p'. If 'data_pp' is not null, it will set   
 * '*data_pp' to point past the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned int u16_le = ((unsigned int)data_p[1] << 8) | data_p[0];

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 2);
	}

	return u16_le;
}

int ys_read_s16_be(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads a signed 16 bit integer in big-endian, 2's complement format from
 *  the array of bytes pointed to by 'data_p'. 
 * If 'data_pp' is not null, it will set '*data_pp' to point past the integer
 *  read.
\*---------------------------------------------------------------------------*/
{
	unsigned int u16_be = ((unsigned int)data_p[0] << 8) | data_p[1];
	int s16_be;

#ifndef YS_ASSUME_2S_COMP
	if (u16_be & 0x8000U) {
		s16_be = (int)(u16_be - 0x8000U) - 0x7FFF - 1;
	} else
#endif
		s16_be = u16_be;

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 2);
	}

	return s16_be;
}

int ys_read_s16_le(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads a signed 16 bit integer in little-endian, 2's complement format from
 *  the array of bytes pointed to by 'data_p'. 
 * If 'data_pp' is not null, it will set '*data_pp' to point past the integer
 *  read.
\*---------------------------------------------------------------------------*/
{
	unsigned int u16_le = ((unsigned int)data_p[1] << 8) | data_p[0];
	int s16_le;

#ifndef YS_ASSUME_2S_COMP
	if (u16_le & 0x8000U) {
		s16_le = (int)(u16_le - 0x8000U) - 0x7FFF - 1;
	} else
#endif
		s16_le = u16_le;

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 2);
	}

	return s16_le;
}

unsigned long
ys_read_u24_be(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads an unsigned 24 bit integer in big-endian format from the array of 
 * bytes pointed to by 'data_p'. If 'data_pp' is not null, it will set
 * '*data_pp' to point past the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u24_be = ((unsigned long)data_p[0] << 16) |
	    ((unsigned long)data_p[1] << 8) | data_p[2];

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 3);
	}

	return u24_be;
}

unsigned long
ys_read_u24_le(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads an unsigned 24 bit integer in big-endian format from the array of 
 * bytes pointed to by 'data_p'. If 'data_pp' is not null, it will set
 * '*data_pp' to point past the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u24_le = ((unsigned long)data_p[3] << 16) |
	    ((unsigned long)data_p[2] << 8) | data_p[0];

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 3);
	}

	return u24_le;
}

long ys_read_s24_be(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads a signed 24 bit integer in big-endian, 2's complement format from
 *  the array of bytes pointed to by 'data_p'. 
 * If 'data_pp' is not null, it will set '*data_pp' to point past the integer
 *  read.
\*---------------------------------------------------------------------------*/
{
	unsigned long u24_be = ((unsigned long)data_p[0] << 16) |
	    ((unsigned long)data_p[1] << 8) | data_p[2];
	long s24_be;

#ifndef YS_ASSUME_2S_COMP
	if (u24_be & 0x800000UL) {
		s24_be = (long)(u24_be - 0x800000UL) - 0x800000;
	} else
#endif
		s24_be = u24_be;

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 3);
	}

	return s24_be;
}

long ys_read_s24_le(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads a signed 24 bit integer in little-endian, 2's complement format from
 *  the array of bytes pointed to by 'data_p'. 
 * If 'data_pp' is not null, it will set '*data_pp' to point past the integer
 *  read.
\*---------------------------------------------------------------------------*/
{
	unsigned long u24_be = ((unsigned long)data_p[2] << 16) |
	    ((unsigned long)data_p[1] << 8) | data_p[0];
	long s24_be;

#ifndef YS_ASSUME_2S_COMP
	if (u24_be & 0x800000UL) {
		s24_be = (long)(u24_be - 0x800000UL) - 0x800000;
	} else
#endif
		s24_be = u24_be;

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 3);
	}

	return s24_be;
}

unsigned long
ys_read_u32_be(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads an unsigned 32 bit integer in big-endian format from the array of 
 * bytes pointed to by 'data_p'. If 'data_pp' is not null, it will set
 * '*data_pp' to point past the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u32_be = ((unsigned long)data_p[0] << 24) |
	    ((unsigned long)data_p[1] << 16) |
	    ((unsigned long)data_p[2] << 8) | data_p[3];

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 4);
	}

	return u32_be;
}

unsigned long
ys_read_u32_le(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads an unsigned 32 bit integer in little-endian format from the array of 
 * bytes pointed to by 'data_p'. If 'data_pp' is not null, it will set
 * '*data_pp' to point past the integer read. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u32_le = ((unsigned long)data_p[3] << 24) |
	    ((unsigned long)data_p[2] << 16) |
	    ((unsigned long)data_p[1] << 8) | data_p[0];

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 4);
	}

	return u32_le;
}

long ys_read_s32_be(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads a signed 32 bit integer in big-endian, 2's complement format from
 *  the array of bytes pointed to by 'data_p'. 
 * If 'data_pp' is not null, it will set '*data_pp' to point past the integer
 *  read.
\*---------------------------------------------------------------------------*/
{
	unsigned long u32_be = ((unsigned long)data_p[0] << 24) |
	    ((unsigned long)data_p[1] << 16) |
	    ((unsigned long)data_p[2] << 8) | data_p[3];
	long s32_be;

#ifndef YS_ASSUME_2S_COMP
	if (u32_be & 0x80000000UL) {
		s32_be = (long)(u32_be - 0x80000000UL) - 0x7FFFFFFF - 1;
	} else
#endif
		s32_be = u32_be;

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 4);
	}

	return s32_be;
}

long ys_read_s32_le(const unsigned char *data_p, const unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Reads a signed 32 bit integer in little-endian, 2's complement format from
 *  the array of bytes pointed to by 'data_p'. 
 * If 'data_pp' is not null, it will set '*data_pp' to point past the integer
 *  read.
\*---------------------------------------------------------------------------*/
{
	unsigned long u32_le = ((unsigned long)data_p[3] << 24) |
	    ((unsigned long)data_p[2] << 16) |
	    ((unsigned long)data_p[1] << 8) | data_p[0];
	long s32_le;

#ifndef YS_ASSUME_2S_COMP
	if (u32_le & 0x80000000UL) {
		s32_le = (long)(u32_le - 0x80000000UL) - 0x7FFFFFFF - 1;
	} else
#endif
		s32_le = u32_le;

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 4);
	}

	return s32_le;
}

} // End of namespace Saga

--- NEW FILE: ys_binwrite.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ys_binwrite.cpp,v 1.1 2004/04/12 21:40:49 sev Exp $
 *
 */
#include <stddef.h>

namespace Saga {
void
ys_write_u8(unsigned int u8, unsigned char *data_p, unsigned char **data_pp)
{
	*data_p = (unsigned char)(u8 & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 1;
	}

	return;
}

void
ys_write_u16_be(unsigned int u16_be,
    unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an unsigned 16 bit integer in big-endian format to the buffer
 *  pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	data_p[0] = (unsigned char)((u16_be >> 8) & 0xFFU);
	data_p[1] = (unsigned char)(u16_be & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 2;
	}

	return;
}

void
ys_write_u16_le(unsigned int u16_le,
    unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an unsigned 16 bit integer in little-endian format to the buffer
 *  pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	data_p[0] = (unsigned char)(u16_le & 0xFFU);
	data_p[1] = (unsigned char)((u16_le >> 8) & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 2;
	}

	return;
}

void
ys_write_s16_be(int s16_be, unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an signed 16 bit integer in big-endian format and two's
 *  complement representation to the buffer pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	unsigned int u16_be = s16_be;

	data_p[0] = (unsigned char)((u16_be >> 8) & 0xFFU);
	data_p[1] = (unsigned char)(u16_be & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 2;
	}

	return;
}

void
ys_write_s16_le(int s16_le, unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an signed 16 bit integer in little-endian format and two's
 *  complement representation to the buffer pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	unsigned int u16_le = s16_le;

	data_p[0] = (unsigned char)(u16_le & 0xFFU);
	data_p[1] = (unsigned char)((u16_le >> 8) & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 2;
	}

	return;
}

void
ys_write_u24_be(unsigned long u24_be,
    unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an unsigned 24 bit integer in big-endian format to the buffer
 *  pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	data_p[0] = (unsigned char)((u24_be >> 16) & 0xFFU);
	data_p[1] = (unsigned char)((u24_be >> 8) & 0xFFU);
	data_p[2] = (unsigned char)(u24_be & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 3;
	}

	return;
}

void
ys_write_u24_le(unsigned long u24_le,
    unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an unsigned 24 bit integer in little-endian format to the buffer
 *  pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	data_p[0] = (unsigned char)(u24_le & 0xFFU);
	data_p[1] = (unsigned char)((u24_le >> 8) & 0xFFU);
	data_p[2] = (unsigned char)((u24_le >> 16) & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 3;
	}

	return;
}

void
ys_write_s24_be(long s24_be, unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an signed 24 bit integer in big-endian format and two's
 *  complement representation to the buffer pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u24_be = s24_be;

	data_p[0] = (unsigned char)((u24_be >> 16) & 0xFFU);
	data_p[1] = (unsigned char)((u24_be >> 8) & 0xFFU);
	data_p[2] = (unsigned char)(u24_be & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 3;
	}

	return;
}

void
ys_write_s24_le(long s24_le, unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an signed 24 bit integer in little-endian format and two's
 *  complement representation to the buffer pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u24_le = s24_le;

	data_p[0] = (unsigned char)(u24_le & 0xFFU);
	data_p[1] = (unsigned char)((u24_le >> 8) & 0xFFU);
	data_p[2] = (unsigned char)((u24_le >> 16) & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = (unsigned char *)(data_p + 3);
	}

	return;
}

void
ys_write_u32_be(unsigned long u32_be,
    unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an unsigned 32 bit integer in big-endian format to the buffer
 *  pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	data_p[0] = (unsigned char)((u32_be >> 24) & 0xFFU);
	data_p[1] = (unsigned char)((u32_be >> 16) & 0xFFU);
	data_p[2] = (unsigned char)((u32_be >> 8) & 0xFFU);
	data_p[3] = (unsigned char)(u32_be & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 4;
	}

	return;
}

void
ys_write_u32_le(unsigned long u32_le,
    unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an unsigned 32 bit integer in little-endian format to the buffer
 *  pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	data_p[0] = (unsigned char)(u32_le & 0xFFU);
	data_p[1] = (unsigned char)((u32_le >> 8) & 0xFFU);
	data_p[2] = (unsigned char)((u32_le >> 16) & 0xFFU);
	data_p[3] = (unsigned char)((u32_le >> 24) & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 4;
	}

	return;
}

void
ys_write_s32_be(long s32_be, unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an signed 32 bit integer in big-endian format and two's
 *  complement representation to the buffer pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u32_be = s32_be;

	data_p[0] = (unsigned char)((u32_be >> 24) & 0xFFU);
	data_p[1] = (unsigned char)((u32_be >> 16) & 0xFFU);
	data_p[2] = (unsigned char)((u32_be >> 8) & 0xFFU);
	data_p[3] = (unsigned char)(u32_be & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 4;
	}

	return;
}

void
ys_write_s32_le(long s32_le, unsigned char *data_p, unsigned char **data_pp)
/*---------------------------------------------------------------------------*\
 * Writes an signed 32 bit integer in little-endian format and two's
 *  complement representation to the buffer pointed to by 'data_p'.
 * If 'data_pp' is not null, the function will set it to point just beyond
 *  the integer written. 
\*---------------------------------------------------------------------------*/
{
	unsigned long u32_le = s32_le;

	data_p[0] = (unsigned char)(u32_le & 0xFFU);
	data_p[1] = (unsigned char)((u32_le >> 8) & 0xFFU);
	data_p[2] = (unsigned char)((u32_le >> 16) & 0xFFU);
	data_p[3] = (unsigned char)((u32_le >> 24) & 0xFFU);

	if (data_pp != NULL) {
		*data_pp = data_p + 4;
	}

	return;
}

} // End of namespace Saga

--- NEW FILE: ys_dl_list.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ys_dl_list.cpp,v 1.1 2004/04/12 21:40:49 sev Exp $
 *
 */
#include "reinherit.h"

#include "yslib.h"

namespace Saga {

YS_DL_LIST *ys_dll_create(void)
{

	YS_DL_LIST *new_list;

	new_list = (YS_DL_LIST *)malloc(sizeof *new_list);

	if (new_list != NULL) {
		new_list->next = new_list;
		new_list->prev = new_list;

		/* Sentinel is marked by self-referential node data. 
		 * No other link is permitted to do this */
		new_list->data = new_list;
	}

	return new_list;
}

void ys_dll_destroy(YS_DL_LIST * list)
{
	YS_DL_NODE *walk_p;
	YS_DL_NODE *temp_p;

	for (walk_p = list->next; walk_p != list; walk_p = temp_p) {
		temp_p = walk_p->next;

		free(walk_p->data);
		free(walk_p);
	}

	free(list);

	return;
}

void *ys_dll_get_data(YS_DL_NODE * node)
{
	return node->data;
}

YS_DL_NODE *ys_dll_head(YS_DL_LIST * list)
{
	return (list->next != list) ? list->next : NULL;
}

YS_DL_NODE *ys_dll_tail(YS_DL_LIST * list)
{
	return (list->prev != list) ? list->prev : NULL;
}

YS_DL_NODE *ys_dll_next(YS_DL_NODE *node)
{
	return (node->next !=
	    (YS_DL_LIST *) node->next->data) ? node->next : NULL;
}

YS_DL_NODE *ys_dll_prev(YS_DL_NODE * node)
{
	return (node->prev !=
	    (YS_DL_LIST *) node->prev->data) ? node->prev : NULL;
}

YS_DL_NODE *ys_dll_add_head(YS_DL_LIST * list, void *data, size_t size)
{
	YS_DL_NODE *new_node;
	void *new_data;

	new_node = (YS_DL_NODE *)malloc(sizeof *new_node);

	if (new_node) {
		new_data = malloc(size);

		if (new_data) {
			memcpy(new_data, data, size);
			new_node->data = new_data;

			new_node->prev = list;
			new_node->next = list->next;
			new_node->next->prev = new_node;
			list->next = new_node;
		}
	}
	return new_node;
}

YS_DL_NODE *ys_dll_add_tail(YS_DL_LIST * list, void *data, size_t size)
{
	YS_DL_NODE *new_node;
	void *new_data;

	new_node = (YS_DL_NODE *)malloc(sizeof *new_node);

	if (new_node != NULL) {
		new_data = malloc(size);

		if (new_data != NULL) {

			memcpy(new_data, data, size);
			new_node->data = new_data;

			new_node->next = list;
			new_node->prev = list->prev;
			new_node->prev->next = new_node;
			list->prev = new_node;
		}
	}
	return new_node;
}

YS_DL_NODE *ys_dll_insert(YS_DL_NODE * list,
    void *data, size_t size, YS_COMPARE_FUNC * compare)
{
	YS_DL_NODE *walk_p;
	YS_DL_NODE *new_node;
	int result;

	for (walk_p = list->next; walk_p != list; walk_p = walk_p->next) {

		result = compare(data, walk_p->data);
		if (result < 0) {
			new_node = ys_dll_preinsert(walk_p, data, size);
			return new_node;
		}
	}

	new_node = ys_dll_add_tail(list, data, size);
	return new_node;
}

int ys_dll_delete(YS_DL_NODE * node)
{

	if (node == NULL) {
		return YS_E_FAILURE;
	}

	node->next->prev = node->prev;
	node->prev->next = node->next;

	free(node->data);
	free(node);

	return YS_E_SUCCESS;
}

void ys_dll_delete_all(YS_DL_LIST * list)
{
	YS_DL_NODE *walk_p;
	YS_DL_NODE *temp_p;

	for (walk_p = list->next; walk_p != list; walk_p = temp_p) {
		temp_p = walk_p->next;

		free(walk_p->data);
		free(walk_p);
	}

	list->next = list;
	list->prev = list;

	return;
}

YS_DL_NODE *ys_dll_replace(YS_DL_NODE * node, void *data, size_t size)
{
	void *new_data;

	if ((node == NULL) || (data == NULL) || (!size)) {
		return NULL;
	}

	new_data = malloc(size);

	if (new_data == NULL) {
		return NULL;
	}

	free(node->data);
	node->data = new_data;
	memcpy(new_data, data, size);

	return node;
}

int
ys_dll_reorder_up(YS_DL_NODE * list,
    YS_DL_NODE * olink, YS_COMPARE_FUNC * compare)
{
	YS_DL_NODE *walk_p;
	int result;
	int reorder = 0;

	for (walk_p = olink->prev; walk_p != list; walk_p = walk_p->prev) {
		result = compare(walk_p->data, olink->data);
		if (result <= 0) {
			reorder = 1;
			break;
		}
	}

	if (reorder) {
		/* Unlink original link */
		olink->next->prev = olink->prev;
		olink->prev->next = olink->next;

		/* Reinsert after walk link */
		olink->prev = walk_p;
		olink->next = walk_p->next;
		olink->next->prev = olink;
		walk_p->next = olink;
	}
	return YS_E_SUCCESS;
}

int
ys_dll_reorder_down(YS_DL_NODE * list,
    YS_DL_NODE * olink, YS_COMPARE_FUNC * compare)
{
	YS_DL_NODE *walk_p;
	int result;
	int reorder = 0;

	for (walk_p = olink->next; walk_p != list; walk_p = walk_p->next) {
		result = compare(walk_p->data, olink->data);
		if (result >= 0) {
			reorder = 1;
			break;
		}
	}

	if (reorder) {
		/* Unlink original link */
		olink->next->prev = olink->prev;
		olink->prev->next = olink->next;

		/* Reinsert before walk link */
		olink->next = walk_p;
		olink->prev = walk_p->prev;
		olink->prev->next = olink;
		walk_p->prev = olink;
	}
	return YS_E_SUCCESS;
}

int
ys_dll_foreach(YS_DL_NODE * list,
    int direction,
    void *param,
    int (*ys_dll_proc) (void *data, void *param), YS_DL_NODE ** t_node)
{
	YS_DL_NODE *walk_p;

	/* Only walk bakcward if explicitly requested to */
	if (direction == YS_WALK_BACKWARD) {
		for (walk_p = list->prev; walk_p != list;
		    walk_p = walk_p->prev) {

			if (ys_dll_proc(walk_p->data, param) == 0) {
				break;
			}

		}
	} else {
		/* Default behavior is to walk forwards */
		for (walk_p = list->next; walk_p != list;
		    walk_p = walk_p->next) {

			if (ys_dll_proc(walk_p->data, param) == 0) {
				break;
			}
		}
	}

	if (t_node) {
		*t_node = (walk_p != list) ? walk_p : NULL;
	}

	return YS_E_SUCCESS;
}

} // End of namespace Saga

--- NEW FILE: ys_file.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/ys_file.cpp,v 1.1 2004/04/12 21:40:49 sev Exp $
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include "yslib.h"

namespace Saga {

int ys_get_filesize(FILE * file_p, unsigned long *len_p, int *p_errno)
/*--------------------------------------------------------------------------*\
 * Returns the 'size' of the specified file. The file must be opened in 
 *  binary mode. Note that not all operating systems support determing the 
 *  exact end of a binary file stream, so this function is limited in 
 *  portability.
\*--------------------------------------------------------------------------*/
{
	long f_pos;
	long f_len;

	f_pos = ftell(file_p);
	if (f_pos == -1) {
		*p_errno = errno;
		return YS_E_FAILURE;
	}

	fseek(file_p, 0, SEEK_END);

	f_len = ftell(file_p);
	if (f_pos == -1) {
		*p_errno = errno;
		return YS_E_FAILURE;
	}

	fseek(file_p, f_pos, SEEK_SET);

	*len_p = (unsigned long)f_len;

	return YS_E_SUCCESS;;
}

} // End of namespace Saga

--- NEW FILE: yslib.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 The ScummVM project
 *
 * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
 *
 * 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/saga/yslib.h,v 1.1 2004/04/12 21:40:49 sev Exp $
 *
 */
#ifndef YSLIB_MAIN_H__
#define YSLIB_MAIN_H__

namespace Saga {

enum YS_ERROR_STATES {

	YS_E_SUCCESS = 0,
	YS_E_FAILURE,
	YS_E_MEM
};

enum YS_CONFIRM_STATES {

	YS_CONFIRM_NO = 0,
	YS_CONFIRM_YES,
	YS_CONFIRM_CANCEL
};

/* General purpose quantity-comparison function */
typedef int (YS_COMPARE_FUNC) (const void *, const void *);

/* General-purpose utility macros 
\*------------------------------------------------------------------*/

/* Ignore a parameter (Supress warnings) */
#define YS_IGNORE_PARAM( param ) ( void )( param )

/* Calculate the number of elements in an array */
#define YS_NELEMS( arr ) (( sizeof arr ) / ( sizeof *arr ))

#define YS_DUMMY_DECL		/* C99 permits statements before declarations */

#define YS_REG_FUNC( arr ) YS_DUMMY_DECL
#define YS_FUNC __func__

#define YS_FLEX_ARRAY
#define YS_FLEX_ARRAY_MOD 0

/* Minimum and maximum of two values */
#define YS_MIN(a,b) (((a) < (b)) ? (a) : (b))
#define YS_MAX(a,b) (((a) > (b)) ? (a) : (b))

/* Minimum and maximum of two objects, convert to lvalue */
#define YS_LV_MIN(a,b) (*((a) < (b)) ? &(a) : &(b))
#define YS_LV_MAX(a,b) (*((a) < (b)) ? &(a) : &(b))

#define YS_ABS(n) ((n < 0) ? -n : n)

/* ys_binread.c : Binary input functions (buffer oriented)
\*------------------------------------------------------------------*/

/* #define YS_ASSUME_2S_COMP */

/* Read a 4CC ( Four characater code ) */
void
ys_read_4cc(char *fourcc,
    const unsigned char *data_p, const unsigned char **data_pp);

/* Read 8 bit unsigned integer */
unsigned int ys_read_u8(const unsigned char *, const unsigned char **);

/* Read 8 bit signed integer */
int ys_read_s8(const unsigned char *, const unsigned char **);

/* Read 16 bit unsigned integer, big-endian */
unsigned int ys_read_u16_be(const unsigned char *, const unsigned char **);

/* Read 16 bit unsigned integer, little-endian */
unsigned int ys_read_u16_le(const unsigned char *, const unsigned char **);

/* Read 16 bit signed integer, 2's complement, big-endian */
int ys_read_s16_be(const unsigned char *, const unsigned char **);

/* Read 16 bit signed integer, 2's complement, little-endian */
int ys_read_s16_le(const unsigned char *, const unsigned char **);

/* Read 24 bit unsigned integer, big-endian */
unsigned long ys_read_u24_be(const unsigned char *, const unsigned char **);

/* Read 24 bit unsigned integer, little-endian */
unsigned long ys_read_u24_le(const unsigned char *, const unsigned char **);

/* Read 24 bit signed integer, 2's complement, big-endian */
long ys_read_s24_be(const unsigned char *, const unsigned char **);

/* Read 24 bit signed integer, 2's complement, little-endian */
long ys_read_s24_le(const unsigned char *, const unsigned char **);

/* Read 32 bit unsigned integer, big-endian */
unsigned long ys_read_u32_be(const unsigned char *, const unsigned char **);

/* Read 32 bit unsigned integer, little-endian */
unsigned long ys_read_u32_le(const unsigned char *, const unsigned char **);

/* Read 32 bit signed integer, 2's complement, big-endian */
long ys_read_s32_be(const unsigned char *, const unsigned char **);

/* Read 32 bit signed integer, 2's complement, little-endian */
long ys_read_s32_le(const unsigned char *, const unsigned char **);

/* ys_binwrite.c : Binary output functions ( buffer oriented ) 
\*------------------------------------------------------------------*/

void ys_write_u8(unsigned int, unsigned char *, unsigned char **);

/* Write 16 bit unsigned integer, big-endian */
void ys_write_u16_be(unsigned int, unsigned char *, unsigned char **);

/* Write 16 bit unsigned integer, little-endian */
void ys_write_u16_le(unsigned int, unsigned char *, unsigned char **);

/* Write 16 bit signed integer, 2's complement, big-endian */
void ys_write_s16_be(int, unsigned char *, unsigned char **);

/* Write 16 bit signed integer, 2's complement, little-endian */
void ys_write_s16_le(int, unsigned char *, unsigned char **);

/* Write 24 bit unsigned integer, big-endian */
void ys_write_u24_be(unsigned long, unsigned char *, unsigned char **);

/* Write 24 bit unsigned integer, little-endian */
void ys_write_u24_le(unsigned long, unsigned char *, unsigned char **);

/* Write 24 bit signed integer, 2's complement, big-endian */
void ys_write_s24_be(long, unsigned char *, unsigned char **);

/* Write 24 bit signed integer, 2's complement, little-endian */
void ys_write_s24_le(long, unsigned char *, unsigned char **);

/* Write 32 bit unsigned integer, big-endian */
void ys_write_u32_be(unsigned long, unsigned char *, unsigned char **);

/* Write 32 bit unsigned integer, little-endian */
void ys_write_u32_le(unsigned long, unsigned char *, unsigned char **);

/* Write 32 bit signed integer, 2's complement, big-endian */
void ys_write_s32_be(long, unsigned char *, unsigned char **);

/* Write 32 bit signed integer, 2's complement, little-endian */
void ys_write_s32_le(long, unsigned char *, unsigned char **);


/* ys_file.c     : File management functions
\*------------------------------------------------------------------*/
int ys_get_filesize(FILE *, unsigned long *, int *);

/* Shared declarations for list modules
\*------------------------------------------------------------------*/
enum YS_WALK_DIRECTIONS {
	YS_WALK_BACKWARD = 0,
	YS_WALK_FORWARD
};

/* ys_dl_list.c  : Doubly-linked list functions
\*------------------------------------------------------------------*/
typedef struct ys_dl_node_tag YS_DL_NODE;
typedef struct ys_dl_node_tag YS_DL_LIST;

struct ys_dl_node_tag {
	void *data;
	struct ys_dl_node_tag *next;
	struct ys_dl_node_tag *prev;
};

YS_DL_LIST *ys_dll_create(void);
void ys_dll_destroy(YS_DL_LIST *);

void *ys_dll_get_data(YS_DL_NODE *);

YS_DL_NODE *ys_dll_head(YS_DL_LIST *);
YS_DL_NODE *ys_dll_tail(YS_DL_LIST *);
YS_DL_NODE *ys_dll_next(YS_DL_NODE *);
YS_DL_NODE *ys_dll_prev(YS_DL_NODE *);

YS_DL_NODE *ys_dll_add_head(YS_DL_LIST *, void *, size_t);
YS_DL_NODE *ys_dll_add_tail(YS_DL_LIST *, void *, size_t);

#define ys_dll_preinsert  ys_dll_add_tail
#define ys_dll_postinsert ys_dll_add_head

YS_DL_NODE *ys_dll_insert(YS_DL_LIST *, void *, size_t, YS_COMPARE_FUNC *);
int ys_dll_delete(YS_DL_NODE *);
void ys_dll_delete_all(YS_DL_LIST *);

YS_DL_NODE *ys_dll_replace(YS_DL_NODE *, void *, size_t);

int ys_dll_reorder_up(YS_DL_LIST *, YS_DL_NODE *, YS_COMPARE_FUNC *);
int ys_dll_reorder_down(YS_DL_LIST *, YS_DL_NODE *, YS_COMPARE_FUNC *);

int ys_dll_foreach(YS_DL_LIST *,
    int, void *, int (*)(void *, void *), YS_DL_NODE **);


} // End of namespace Saga

#endif				/* YSLIB_MAIN_H__ */

Index: gamedesc_priv.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/gamedesc_priv.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- gamedesc_priv.h	22 Mar 2004 21:25:28 -0000	1.3
+++ gamedesc_priv.h	12 Apr 2004 21:40:47 -0000	1.4
@@ -1,5 +1,7 @@
 /* ScummVM - Scumm Interpreter
- * Copyright (C) 2003 The ScummVM project
+ * Copyright (C) 2004 The ScummVM project
+ *
+ * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -40,68 +42,64 @@
 #define R_SCR_LUT_ENTRYLEN_ITECD 22
 #define R_SCR_LUT_ENTRYLEN_ITEDISK 16
 
-typedef bool (ResourceFile::*R_GAME_VERIFYFUNC)();
+typedef bool(ResourceFile::*R_GAME_VERIFYFUNC) ();
 
 typedef struct R_GAME_FILEDESC_tag {
-    const char *gf_fname;
-    unsigned int gf_type;
+	const char *gf_fname;
+	unsigned int gf_type;
 
 } R_GAME_FILEDESC;
 
 typedef struct R_GAMEDESC_tag {
-    int gd_game_type;
-    int gd_game_id;
+	int gd_game_type;
+	int gd_game_id;
 
-    const char *gd_title;
+	const char *gd_title;
 
-    R_GAME_DISPLAYINFO *gd_display_info;
+	R_GAME_DISPLAYINFO *gd_display_info;
 
-    int   gd_startscene;
+	int gd_startscene;
 
-    R_GAME_RESOURCEINFO *gd_resource_info;
+	R_GAME_RESOURCEINFO *gd_resource_info;
 
-    int              gd_filect;
-    R_GAME_FILEDESC *gd_filedescs;
-    
-    int              gd_fontct;
-    R_GAME_FONTDESC *gd_fontdescs;
-    
-    R_GAME_SOUNDINFO *gd_soundinfo;
+	int gd_filect;
+	R_GAME_FILEDESC *gd_filedescs;
 
-    int gd_supported;
+	int gd_fontct;
+	R_GAME_FONTDESC *gd_fontdescs;
 
-} R_GAMEDESC;
+	R_GAME_SOUNDINFO *gd_soundinfo;
 
+	int gd_supported;
+} R_GAMEDESC;
 
 typedef struct R_GAME_FILEDATA_tag {
-    ResourceFile *file_ctxt;
-
-    unsigned int  file_types;
-    unsigned int  file_flags;
+	ResourceFile *file_ctxt;
 
+	unsigned int file_types;
+	unsigned int file_flags;
 } R_GAME_FILEDATA;
 
-
 typedef struct R_GAMEMODULE_tag {
-    int game_init;
-    int game_index;
-    
-    R_GAMEDESC *gamedesc;
+	int game_init;
+	int game_index;
 
-    int g_skipintro;
+	R_GAMEDESC *gamedesc;
 
-    const char *game_dir;
-    
-    char game_language[R_GAME_LANGSTR_LIMIT];
+	int g_skipintro;
 
-    unsigned int gfile_n;
-    R_GAME_FILEDATA *gfile_data;
+	const char *game_dir;
 
-    unsigned int gd_fontct;
-    R_GAME_FONTDESC *gd_fontdescs;
+	char game_language[R_GAME_LANGSTR_LIMIT];
 
-    int         err_n;
-    const char *err_str;
+	unsigned int gfile_n;
+	R_GAME_FILEDATA *gfile_data;
+
+	unsigned int gd_fontct;
+	R_GAME_FONTDESC *gd_fontdescs;
+
+	int err_n;
+	const char *err_str;
 
 } R_GAMEMODULE;
 
@@ -111,9 +109,5 @@
 bool verifyIHNMDEMO();
 bool verifyIHNMCD();
 
-} // End of namespace Saga
-
-#endif // SAGA_GAMEDESC_PRIV_H
-
-
-
+}				// End of namespace Saga
+#endif				// SAGA_GAMEDESC_PRIV_H

Index: module.mk
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/module.mk,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- module.mk	14 Mar 2004 23:39:41 -0000	1.1
+++ module.mk	12 Apr 2004 21:40:47 -0000	1.2
@@ -1,10 +1,56 @@
 MODULE := saga
 
 MODULE_OBJS = \
+	saga/actionmap.o \
+	saga/actor.o \
+	saga/actordata.o \
+	saga/animation.o \
+	saga/cmdline.o \
+	saga/console.o \
+	saga/cvar.o \
+	saga/events.o \
+	saga/expr.o \
+	saga/font.o \
+	saga/font_map.o \
+	saga/game.o \
+	saga/gfx.o \
+	saga/ihnm_introproc.o \
+	saga/image.o \
+	saga/interface.o \
+	saga/isomap.o \
+	saga/ite_introproc.o \
+	saga/math.o \
+	saga/misc.o \
+	saga/objectmap.o \
+	saga/palanim.o \
+	saga/render.o \
+	saga/rscfile.o \
 	saga/saga.o \
-	saga/binread.o \
-	saga/gamedesc.o \
-	saga/resfile.o
+	saga/scene.o \
+	saga/sceneproc.o \
+	saga/script.o \
+	saga/sdata.o \
+	saga/sdebug.o \
+	saga/sfuncs.o \
+	saga/sndres.o \
+	saga/sprite.o \
+	saga/sstack.o \
+	saga/stack.o \
+	saga/sthread.o \
+	saga/text.o \
+	saga/transitions.o \
+	saga/xmidi.o \
+	saga/ys_binread.o \
+	saga/ys_binwrite.o \
+	saga/ys_dl_list.o \
+	saga/ys_file.o \
+	saga/sysgfx.o \
+	saga/sysinput.o \
+	saga/systimer.o \
+	saga/sysmusic.o \
+	saga/syssound.o \
+	saga/sysio.o \
+	saga/sys_fs.o
 
 MODULE_DIRS += \
 	saga

Index: saga.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/saga.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- saga.cpp	22 Mar 2004 21:25:28 -0000	1.3
+++ saga.cpp	12 Apr 2004 21:40:47 -0000	1.4
@@ -1,24 +1,3 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2003 The ScummVM project
- *
- * 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$
- *
- */
-
 #include "stdafx.h"
 
 #include "base/gameDetector.h"
@@ -31,7 +10,26 @@
 
 #include "saga.h"
 
-#include "gamedesc.h"
+#include "reinherit.h"
+
+#include "rscfile_mod.h"
+#include "render_mod.h"
+#include "actor_mod.h"
+#include "animation_mod.h"
+#include "console_mod.h"
+#include "cvar_mod.h"
+#include "events_mod.h"
+#include "actionmap_mod.h"
+#include "font_mod.h"
+#include "game_mod.h"
+#include "interface_mod.h"
+#include "isomap_mod.h"
+#include "script_mod.h"
+#include "scene_mod.h"
+#include "sndres_mod.h"
+#include "sprite_mod.h"
+#include "text_mod.h"
+#include "objectmap_mod.h"
 
 struct SAGAGameSettings {
 	const char *name;
@@ -96,11 +94,24 @@
 
 namespace Saga {
 
+#define R_MAX_TIME_DELTA 100
+
+typedef struct R_MAIN_DATA_tag {
+
+	int sound_enabled;
+	int music_enabled;
+
+} R_MAIN_DATA;
+
+static void CF_quitfunc(int argc, char *argv[]);
+static void CF_testfunc(int argc, char *argv[]);
+
+static R_MAIN_DATA MainData;
+
 SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst)
 	: Engine(syst) {
 
-	setGameDirectory(getGameDataPath());
-	openGame();
+	GAME_setGameDirectory(getGameDataPath());
 
 	// Setup mixer
 	if (!_mixer->isReady()) {
@@ -110,7 +121,7 @@
 	_mixer->setVolume(ConfMan.getInt("sfx_volume") * ConfMan.getInt("master_volume") / 255);
 
 	// Initialize backend
-	syst->initSize(320, 240);
+	//syst->initSize(320, 240);
 }
 
 SagaEngine::~SagaEngine() {
@@ -122,13 +133,200 @@
 }
 
 void SagaEngine::go() {
+	int msec = 0;
+
+	/* Register engine modules
+	 * \*------------------------------------------------------------- */
+	CON_Register();		/* Register console cvars first */
+
+	RENDER_Register();
+	GAME_Register();
+
+	ANIM_Register();
+	ACTIONMAP_Register();
+	OBJECTMAP_Register();
+	SCRIPT_Register();
+	ACTOR_Register();
+	SCENE_Register();
+
+	MainData.sound_enabled = 1;
+
+	CVAR_RegisterFunc(CF_testfunc,
+	    "testfunc", "foo [ optional foo ]", R_CVAR_NONE, 0, -1);
+
+	CVAR_Register_I(&MainData.sound_enabled,
+	    "sound", NULL, R_CVAR_CFG, 0, 1);
+
+	CVAR_Register_I(&MainData.music_enabled,
+	    "music", NULL, R_CVAR_CFG, 0, 1);
+
+	CVAR_RegisterFunc(CF_quitfunc, "quit", NULL, R_CVAR_NONE, 0, 0);
+
+	/* Process config file
+	 * \*------------------------------------------------------------- */
+	// FIXME
+	/*
+	if (CFG_Read(NULL) != R_SUCCESS) {
+		R_printf(R_STDERR, "Couldn't read configuration file.\n");
+	}
+	*/
+
+	/* Process command line
+	 * \*------------------------------------------------------------- */
+
+	/* Detect game and open resource files
+	 * \*------------------------------------------------------------- */
+	if (GAME_Init() != R_SUCCESS) {
+
+		R_printf(R_STDERR,
+		    "Couldn't start the game: %s\n", GAME_GetErrS());
+
+		return;
+	}
+
+	/* Initialize engine modules
+	 * \*------------------------------------------------------------- */
+	SND_Init();
+	EVENT_Init();
+	FONT_Init();
+	SPRITE_Init();
+	ANIM_Init();
+	ACTIONMAP_Init();
+	OBJECTMAP_Init();
+	ISOMAP_Init();
+	SCRIPT_Init();
+	INTERFACE_Init();	/* requires script module */
+	ACTOR_Init();
 
+	if (SCENE_Init() != R_SUCCESS) {
+
+		R_printf(R_STDERR, "Couldn't initialize scene module.\n");
+		return;
+	}
+
+	/* System initialization
+	 * \*------------------------------------------------------------- */
+
+	if (SYSIO_Init() != R_SUCCESS) {
+
+		return;
+	}
+
+	/* Must initialize system timer module first */
+	if (SYSTIMER_InitMSCounter() != R_SUCCESS) {
+
+		return;
+	}
+
+	/* On some platforms, graphics initialization also initializes sound
+	 * ( Win32 DirectX )... Music must be initialized before sound for 
+	 * native midi support */
+	SYSMUSIC_Init(MainData.music_enabled);
+	if (!MainData.music_enabled) {
+		R_printf(R_STDOUT, "Music disabled.\n");
+	}
+
+	/* Initialize graphics */
+	if (RENDER_Init() != R_SUCCESS) {
+		return;
+	}
 
+	/* Initialize system specific sound */
+	SYSSOUND_Init(MainData.sound_enabled);
+	if (!MainData.sound_enabled) {
+		R_printf(R_STDOUT, "Sound disabled.\n");
+	}
+
+	SYSINPUT_Init();
+
+	SYSTIMER_ResetMSCounter();
+
+	/* Begin Main Engine Loop
+	 * \*------------------------------------------------------------- */
+
+	SCENE_Start();
+
+	for (;;) {
+
+#ifdef R_USE_CUSTOM_WININIT
+
+		if (ITESYS_CheckSignal()) {
+			break;
+		}
+#endif
+
+		if (RENDER_GetFlags() & RF_RENDERPAUSE) {
+			/* Freeze time while paused */
+			SYSTIMER_ResetMSCounter();
+		} else {
+			msec = SYSTIMER_ReadMSCounter();
+
+			if (msec > R_MAX_TIME_DELTA) {
+				msec = R_MAX_TIME_DELTA;
+			}
+
+			ACTOR_Direct(msec);
+			EVENT_HandleEvents(msec);
+			STHREAD_ExecThreads(msec);
+		}
+
+		/* Per frame processing
+		 * \*--------------------------------------------------------- */
+		RENDER_DrawScene();
+
+		SYSTIMER_Sleep(0);
+
+	}			/* end main game engine loop */
+
+	R_Shutdown(0);
+
+	return;
 }
 
 void SagaEngine::shutdown() {
-
 	_system->quit();
 }
 
+void R_Shutdown(int param) {
+	SCENE_Shutdown();
+	ACTOR_Shutdown();
+	SCRIPT_Shutdown();
+	ANIM_Shutdown();
+	SPRITE_Shutdown();
+	OBJECTMAP_Shutdown();
+
+	FONT_Shutdown();
+
+	CON_Shutdown();
+	CVAR_Shutdown();
+	EVENT_Shutdown();
+
+	/* Shutdown system modules */
+	SYSMUSIC_Shutdown();
+	SYSSOUND_Shutdown();
+
+	SYSIO_Shutdown();
+
+	/*  exit(param); */
+}
+
+static void CF_quitfunc(int argc, char *argv[])
+{
+	R_Shutdown(0);
+	exit(0);
+}
+
+static void CF_testfunc(int argc, char *argv[])
+{
+	int i;
+
+	CON_Print("Test function invoked: Got %d arguments.", argc);
+
+	for (i = 0; i < argc; i++) {
+		CON_Print("Arg %d: %s", i, argv[i]);
+	}
+
+	return;
+}
+
 } // End of namespace Saga

Index: saga.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/saga.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- saga.h	22 Mar 2004 21:25:29 -0000	1.3
+++ saga.h	12 Apr 2004 21:40:47 -0000	1.4
@@ -1,5 +1,7 @@
 /* ScummVM - Scumm Interpreter
- * Copyright (C) 2003 The ScummVM project
+ * Copyright (C) 2004 The ScummVM project
+ *
+ * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,7 +29,7 @@
 #include "base/gameDetector.h"
 #include "common/util.h"
 
-#include "gamedesc.h"
+//#include "gamedesc.h"
 
 namespace Saga {
 
@@ -39,18 +41,16 @@
 	GID_IHNM
 };
 
-class SagaEngine : public Engine {
-
-	void errorString( const char *buf_input, char *buf_output);
+class SagaEngine:public Engine {
+	void errorString(const char *buf_input, char *buf_output);
 
-protected:
+ protected:
 	void go();
 	void shutdown();
 
-public:
-
-	SagaEngine(GameDetector *detector, OSystem *syst);
-	virtual ~SagaEngine();
+ public:
+	SagaEngine(GameDetector * detector, OSystem * syst);
+	virtual ~ SagaEngine();
 
 };
 

--- binread.cpp DELETED ---

--- binread.h DELETED ---

--- gamedesc.cpp DELETED ---

--- gamedesc.h DELETED ---

--- resfile.cpp DELETED ---

--- resfile.h DELETED ---

--- resnames.h DELETED ---





More information about the Scummvm-git-logs mailing list